pg-workflows 0.8.2 → 0.9.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.js.map CHANGED
@@ -2,18 +2,18 @@
2
2
  "version": 3,
3
3
  "sources": ["src/client.ts", "src/constants.ts", "src/db/migration.ts", "src/db/queries.ts", "src/error.ts", "src/types.ts", "src/definition.ts", "src/duration.ts", "src/engine.ts", "src/ast-parser.ts"],
4
4
  "sourcesContent": [
5
- "import { merge } from 'es-toolkit';\nimport pg from 'pg';\nimport { type Db, PgBoss } from 'pg-boss';\nimport { DEFAULT_PGBOSS_SCHEMA, PAUSE_EVENT_NAME, WORKFLOW_RUN_QUEUE_NAME } from './constants';\nimport { runMigrations } from './db/migration';\nimport {\n getWorkflowRun,\n getWorkflowRuns,\n insertWorkflowRun,\n updateWorkflowRun,\n withPostgresTransaction,\n} from './db/queries';\nimport type { WorkflowRun } from './db/types';\nimport { WorkflowEngineError, WorkflowRunNotFoundError } from './error';\nimport {\n type InferInputParameters,\n type InputParameters,\n type WorkflowLogger,\n type WorkflowRef,\n type WorkflowRunProgress,\n WorkflowStatus,\n} from './types';\n\nconst LOG_PREFIX = '[WorkflowClient]';\n\ntype WorkflowRunJobParameters = {\n runId: string;\n resourceId?: string;\n workflowId: string;\n input: unknown;\n event?: {\n name: string;\n data?: Record<string, unknown>;\n };\n};\n\nexport type WorkflowClientOptions = {\n logger?: WorkflowLogger;\n /**\n * Pre-configured pg-boss instance. Pass this when the engine side uses a\n * non-default pg-boss config (schema, retention, logger, etc.) so the\n * client enqueues jobs where the engine reads them. Mirrors the same\n * option on `WorkflowEngineOptions`.\n */\n boss?: PgBoss;\n} & ({ pool: pg.Pool; connectionString?: never } | { connectionString: string; pool?: never });\n\nexport type StartWorkflowOptions = {\n resourceId?: string;\n timeout?: number;\n retries?: number;\n expireInSeconds?: number;\n idempotencyKey?: string;\n};\n\nconst defaultLogger: WorkflowLogger = {\n log: (_message: string) => console.warn(_message),\n error: (message: string, error: Error) => console.error(message, error),\n};\n\nconst defaultExpireInSeconds = process.env.WORKFLOW_RUN_EXPIRE_IN_SECONDS\n ? Number.parseInt(process.env.WORKFLOW_RUN_EXPIRE_IN_SECONDS, 10)\n : 5 * 60;\n\nexport class WorkflowClient {\n private boss: PgBoss;\n private db: Db;\n private pool: pg.Pool;\n private _ownsPool = false;\n private _started = false;\n private logger: WorkflowLogger;\n\n constructor({ logger, boss, ...connectionOptions }: WorkflowClientOptions) {\n this.logger = logger ?? defaultLogger;\n\n if ('pool' in connectionOptions && connectionOptions.pool) {\n this.pool = connectionOptions.pool;\n } else if ('connectionString' in connectionOptions && connectionOptions.connectionString) {\n this.pool = new pg.Pool({ connectionString: connectionOptions.connectionString });\n this._ownsPool = true;\n } else {\n throw new WorkflowEngineError('Either pool or connectionString must be provided');\n }\n\n const db: Db = {\n executeSql: (text: string, values?: unknown[]) =>\n this.pool.query(text, values) as Promise<{ rows: unknown[] }>,\n };\n\n if (boss) {\n this.boss = boss;\n } else {\n this.boss = new PgBoss({ db, schema: DEFAULT_PGBOSS_SCHEMA });\n }\n this.db = db;\n }\n\n async start(): Promise<void> {\n if (this._started) {\n return;\n }\n\n await this.boss.start();\n this.db = this.boss.getDb();\n await runMigrations(this.db);\n await this.boss.createQueue(WORKFLOW_RUN_QUEUE_NAME);\n\n this._started = true;\n this.logger.log(`${LOG_PREFIX} Client started`);\n }\n\n async stop(): Promise<void> {\n await this.boss.stop();\n\n if (this._ownsPool) {\n await this.pool.end();\n }\n\n this._started = false;\n this.logger.log(`${LOG_PREFIX} Client stopped`);\n }\n\n async startWorkflow<TInput extends InputParameters>(\n ref: WorkflowRef<TInput>,\n input: InferInputParameters<TInput>,\n options?: StartWorkflowOptions,\n ): Promise<WorkflowRun>;\n\n async startWorkflow(params: {\n workflowId: string;\n input: unknown;\n resourceId?: string;\n idempotencyKey?: string;\n options?: StartWorkflowOptions;\n }): Promise<WorkflowRun>;\n\n async startWorkflow<TInput extends InputParameters>(\n refOrParams:\n | WorkflowRef<TInput>\n | {\n workflowId: string;\n input: unknown;\n resourceId?: string;\n idempotencyKey?: string;\n options?: StartWorkflowOptions;\n },\n inputArg?: InferInputParameters<TInput>,\n optionsArg?: StartWorkflowOptions,\n ): Promise<WorkflowRun> {\n await this.ensureStarted();\n\n let workflowId: string;\n let input: unknown;\n let resourceId: string | undefined;\n let idempotencyKey: string | undefined;\n let options: StartWorkflowOptions | undefined;\n\n if (typeof refOrParams === 'function' && 'id' in refOrParams) {\n const ref = refOrParams as WorkflowRef<TInput>;\n workflowId = ref.id;\n input = inputArg;\n options = optionsArg;\n resourceId = optionsArg?.resourceId;\n idempotencyKey = optionsArg?.idempotencyKey;\n\n if (ref.inputSchema) {\n const result = await ref.inputSchema['~standard'].validate(input);\n if (result.issues) {\n throw new WorkflowEngineError(\n JSON.stringify(result.issues),\n workflowId,\n undefined,\n undefined,\n result.issues,\n );\n }\n }\n } else {\n const params = refOrParams as {\n workflowId: string;\n input: unknown;\n resourceId?: string;\n idempotencyKey?: string;\n options?: StartWorkflowOptions;\n };\n workflowId = params.workflowId;\n input = params.input;\n resourceId = params.resourceId;\n idempotencyKey = params.idempotencyKey;\n options = params.options;\n }\n\n const run = await withPostgresTransaction(\n this.db,\n async (_db) => {\n const timeoutAt = options?.timeout ? new Date(Date.now() + options.timeout) : null;\n\n const { run: insertedRun, created } = await insertWorkflowRun(\n {\n resourceId,\n workflowId,\n currentStepId: '__start__',\n status: WorkflowStatus.RUNNING,\n input,\n maxRetries: options?.retries ?? 0,\n timeoutAt,\n idempotencyKey,\n },\n _db,\n );\n\n if (created) {\n const job: WorkflowRunJobParameters = {\n runId: insertedRun.id,\n resourceId,\n workflowId,\n input,\n };\n\n await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {\n startAfter: new Date(),\n expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,\n });\n }\n\n return insertedRun;\n },\n this.pool,\n );\n\n this.logger.log(`${LOG_PREFIX} Started workflow run ${run.id} for ${workflowId}`);\n\n return run;\n }\n\n async triggerEvent({\n runId,\n resourceId,\n eventName,\n data,\n options,\n }: {\n runId: string;\n resourceId?: string;\n eventName: string;\n data?: Record<string, unknown>;\n options?: { expireInSeconds?: number };\n }): Promise<WorkflowRun> {\n await this.ensureStarted();\n\n const run = await this.getRun({ runId, resourceId });\n\n const job: WorkflowRunJobParameters = {\n runId: run.id,\n resourceId: resourceId ?? run.resourceId ?? undefined,\n workflowId: run.workflowId,\n input: run.input,\n event: {\n name: eventName,\n data,\n },\n };\n\n await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {\n expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,\n });\n\n this.logger.log(`${LOG_PREFIX} Event ${eventName} sent for workflow run ${runId}`);\n return run;\n }\n\n async pauseWorkflow({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRun> {\n await this.ensureStarted();\n\n const run = await updateWorkflowRun(\n {\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.PAUSED,\n pausedAt: new Date(),\n },\n expectedStatuses: [WorkflowStatus.RUNNING, WorkflowStatus.PENDING],\n },\n this.db,\n );\n\n if (!run) {\n throw new WorkflowRunNotFoundError(runId);\n }\n\n this.logger.log(`${LOG_PREFIX} Paused workflow run ${runId}`);\n return run;\n }\n\n async resumeWorkflow({\n runId,\n resourceId,\n options,\n }: {\n runId: string;\n resourceId?: string;\n options?: { expireInSeconds?: number };\n }): Promise<WorkflowRun> {\n await this.ensureStarted();\n\n const current = await this.getRun({ runId, resourceId });\n if (current.status !== WorkflowStatus.PAUSED) {\n throw new WorkflowEngineError(\n `Cannot resume workflow run in '${current.status}' status, must be 'paused'`,\n current.workflowId,\n runId,\n );\n }\n\n return this.triggerEvent({\n runId,\n resourceId,\n eventName: PAUSE_EVENT_NAME,\n data: {},\n options,\n });\n }\n\n async fastForwardWorkflow({\n runId,\n resourceId,\n data,\n }: {\n runId: string;\n resourceId?: string;\n data?: Record<string, unknown>;\n }): Promise<WorkflowRun> {\n await this.ensureStarted();\n\n const run = await this.getRun({ runId, resourceId });\n\n if (run.status !== WorkflowStatus.PAUSED) {\n return run;\n }\n\n const stepId = run.currentStepId;\n const waitForEntry = run.timeline[`${stepId}-wait-for`];\n if (!waitForEntry || typeof waitForEntry !== 'object' || !('waitFor' in waitForEntry)) {\n return run;\n }\n\n const { eventName, timeoutEvent, skipOutput } = (\n waitForEntry as { waitFor: { eventName?: string; timeoutEvent?: string; skipOutput?: true } }\n ).waitFor;\n\n // step.pause() - delegate to resumeWorkflow\n if (eventName === PAUSE_EVENT_NAME) {\n return this.resumeWorkflow({ runId, resourceId });\n }\n\n // step.poll() - write output to timeline first, then trigger resume\n if (skipOutput && timeoutEvent) {\n await withPostgresTransaction(\n this.db,\n async (db) => {\n const freshRun = await getWorkflowRun({ runId, resourceId }, { exclusiveLock: true, db });\n if (!freshRun) throw new WorkflowRunNotFoundError(runId);\n return updateWorkflowRun(\n {\n runId,\n resourceId,\n data: {\n timeline: merge(freshRun.timeline, {\n [stepId]: {\n output: data ?? {},\n timestamp: new Date(),\n },\n }),\n },\n },\n db,\n );\n },\n this.pool,\n );\n\n return this.triggerEvent({ runId, resourceId, eventName: timeoutEvent });\n }\n\n // waitFor steps - trigger the event with data\n if (eventName) {\n return this.triggerEvent({ runId, resourceId, eventName, data: data ?? {} });\n }\n\n // delay/waitUntil steps - trigger the timeout event\n if (timeoutEvent) {\n return this.triggerEvent({ runId, resourceId, eventName: timeoutEvent, data: data ?? {} });\n }\n\n return run;\n }\n\n async cancelWorkflow({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRun> {\n await this.ensureStarted();\n\n const run = await updateWorkflowRun(\n {\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.CANCELLED,\n },\n expectedStatuses: [WorkflowStatus.PENDING, WorkflowStatus.RUNNING, WorkflowStatus.PAUSED],\n },\n this.db,\n );\n\n if (!run) {\n throw new WorkflowRunNotFoundError(runId);\n }\n\n this.logger.log(`${LOG_PREFIX} Cancelled workflow run ${runId}`);\n return run;\n }\n\n async getRun({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRun> {\n await this.ensureStarted();\n\n const run = await getWorkflowRun({ runId, resourceId }, { db: this.db });\n\n if (!run) {\n throw new WorkflowRunNotFoundError(runId);\n }\n\n return run;\n }\n\n async checkProgress({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRunProgress> {\n const run = await this.getRun({ runId, resourceId });\n\n const completedSteps = Object.values(run.timeline).filter(\n (entry): entry is { output: unknown; timestamp: Date } =>\n typeof entry === 'object' &&\n entry !== null &&\n 'output' in entry &&\n entry.output !== undefined,\n ).length;\n\n // Without registered workflow definitions, total steps are unknown.\n // Use completed steps as best-effort estimate for in-progress runs.\n const totalSteps = run.status === WorkflowStatus.COMPLETED ? completedSteps : 0;\n const completionPercentage =\n run.status === WorkflowStatus.COMPLETED\n ? 100\n : run.status === WorkflowStatus.FAILED || run.status === WorkflowStatus.CANCELLED\n ? 0\n : 0;\n\n return {\n ...run,\n completedSteps,\n completionPercentage,\n totalSteps,\n };\n }\n\n async getRuns({\n resourceId,\n startingAfter,\n endingBefore,\n limit = 20,\n statuses,\n workflowId,\n }: {\n resourceId?: string;\n startingAfter?: string | null;\n endingBefore?: string | null;\n limit?: number;\n statuses?: WorkflowStatus[];\n workflowId?: string;\n }): Promise<{\n items: WorkflowRun[];\n nextCursor: string | null;\n prevCursor: string | null;\n hasMore: boolean;\n hasPrev: boolean;\n }> {\n await this.ensureStarted();\n\n return getWorkflowRuns(\n {\n resourceId,\n startingAfter,\n endingBefore,\n limit,\n statuses,\n workflowId,\n },\n this.db,\n );\n }\n\n private async ensureStarted(): Promise<void> {\n if (!this._started) {\n await this.start();\n }\n }\n}\n",
6
- "export const PAUSE_EVENT_NAME = '__internal_pause';\nexport const WORKFLOW_RUN_QUEUE_NAME = 'workflow-run';\nexport const DEFAULT_PGBOSS_SCHEMA = 'pgboss_v12_pgworkflow';\n",
7
- "import type { Db } from 'pg-boss';\n\n// Arbitrary but stable lock ID for serializing migrations across processes\nexport const MIGRATION_LOCK_ID = 738291645;\n\n// Bump this when adding new migrations. The engine stores the current version\n// in a `workflow_schema_version` table so migrations only run once per version.\nconst CURRENT_SCHEMA_VERSION = 2;\n\nexport async function runMigrations(db: Db): Promise<void> {\n // Fast path: skip the advisory lock if schema is already current.\n // This is the common case - every engine.start() after initial setup.\n if (await isSchemaUpToDate(db)) {\n return;\n }\n\n // Slow path: build migration SQL based on current version, then execute\n // everything in a single transaction with an advisory lock.\n // This mirrors pg-boss's approach: one executeSql call ensures all DDL\n // runs on a single connection inside BEGIN/COMMIT, and pg_advisory_xact_lock\n // auto-releases on commit or rollback (no manual unlock needed).\n const currentVersion = await getCurrentVersion(db);\n\n const commands: string[] = [];\n\n if (currentVersion < 1) {\n commands.push(`\n CREATE TABLE IF NOT EXISTS workflow_runs (\n id varchar(32) PRIMARY KEY NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n resource_id varchar(32),\n workflow_id varchar(32) NOT NULL,\n status text DEFAULT 'pending' NOT NULL,\n input jsonb NOT NULL,\n output jsonb,\n error text,\n current_step_id varchar(256) NOT NULL,\n timeline jsonb DEFAULT '{}'::jsonb NOT NULL,\n paused_at timestamp with time zone,\n resumed_at timestamp with time zone,\n completed_at timestamp with time zone,\n timeout_at timestamp with time zone,\n retry_count integer DEFAULT 0 NOT NULL,\n max_retries integer DEFAULT 0 NOT NULL,\n job_id varchar(256)\n )\n `);\n commands.push(`\n CREATE INDEX IF NOT EXISTS workflow_runs_created_at_idx ON workflow_runs USING btree (created_at)\n `);\n commands.push(`\n CREATE INDEX IF NOT EXISTS workflow_runs_resource_id_created_at_idx ON workflow_runs USING btree (resource_id, created_at DESC)\n `);\n commands.push(`\n CREATE INDEX IF NOT EXISTS workflow_runs_status_created_at_idx ON workflow_runs USING btree (status, created_at DESC)\n `);\n commands.push(`\n CREATE INDEX IF NOT EXISTS workflow_runs_workflow_id_created_at_idx ON workflow_runs USING btree (workflow_id, created_at DESC)\n `);\n commands.push(`\n CREATE INDEX IF NOT EXISTS workflow_runs_resource_id_workflow_id_created_at_idx ON workflow_runs USING btree (resource_id, workflow_id, created_at DESC)\n `);\n }\n\n if (currentVersion < 2) {\n commands.push('DROP INDEX IF EXISTS workflow_runs_workflow_id_idx');\n commands.push('DROP INDEX IF EXISTS workflow_runs_resource_id_idx');\n commands.push(\n 'ALTER TABLE workflow_runs ADD COLUMN IF NOT EXISTS idempotency_key varchar(256)',\n );\n commands.push(`\n CREATE UNIQUE INDEX IF NOT EXISTS workflow_runs_idempotency_key_idx ON workflow_runs (idempotency_key) WHERE idempotency_key IS NOT NULL\n `);\n }\n\n // Upsert the schema version\n if (currentVersion === 0) {\n commands.push(\n `INSERT INTO workflow_schema_version (version) VALUES (${CURRENT_SCHEMA_VERSION})`,\n );\n } else {\n commands.push(`UPDATE workflow_schema_version SET version = ${CURRENT_SCHEMA_VERSION}`);\n }\n\n if (commands.length === 0) {\n return;\n }\n\n const sql = [\n 'BEGIN',\n \"SET LOCAL lock_timeout = '30s'\",\n \"SET LOCAL idle_in_transaction_session_timeout = '30s'\",\n `SELECT pg_advisory_xact_lock(${MIGRATION_LOCK_ID})`,\n 'CREATE TABLE IF NOT EXISTS workflow_schema_version (version integer NOT NULL)',\n ...commands,\n 'COMMIT',\n ].join(';\\n');\n\n await db.executeSql(sql, []);\n}\n\nasync function isSchemaUpToDate(db: Db): Promise<boolean> {\n try {\n const result = await db.executeSql('SELECT version FROM workflow_schema_version LIMIT 1', []);\n return (\n ((result.rows[0] as { version: number } | undefined)?.version ?? 0) >= CURRENT_SCHEMA_VERSION\n );\n } catch {\n // Table doesn't exist yet - needs migration\n return false;\n }\n}\n\nasync function getCurrentVersion(db: Db): Promise<number> {\n try {\n const result = await db.executeSql('SELECT version FROM workflow_schema_version LIMIT 1', []);\n return (result.rows[0] as { version: number } | undefined)?.version ?? 0;\n } catch {\n return 0;\n }\n}\n",
5
+ "import { merge } from 'es-toolkit';\nimport pg from 'pg';\nimport { type Db, PgBoss } from 'pg-boss';\nimport { DEFAULT_PGBOSS_SCHEMA, PAUSE_EVENT_NAME, WORKFLOW_RUN_QUEUE_NAME } from './constants';\nimport { runMigrations } from './db/migration';\nimport {\n getWorkflowRun,\n getWorkflowRuns,\n insertWorkflowRun,\n updateWorkflowRun,\n withPostgresTransaction,\n} from './db/queries';\nimport type { WorkflowRun } from './db/types';\nimport {\n validateResourceId,\n validateWorkflowId,\n WorkflowEngineError,\n WorkflowRunNotFoundError,\n} from './error';\nimport {\n type InferInputParameters,\n type InputParameters,\n type WorkflowLogger,\n type WorkflowRef,\n type WorkflowRunProgress,\n WorkflowStatus,\n} from './types';\n\nconst LOG_PREFIX = '[WorkflowClient]';\n\ntype WorkflowRunJobParameters = {\n runId: string;\n resourceId?: string;\n workflowId: string;\n input: unknown;\n event?: {\n name: string;\n data?: Record<string, unknown>;\n };\n};\n\nexport type WorkflowClientOptions = {\n logger?: WorkflowLogger;\n /**\n * Pre-configured pg-boss instance. Pass this when the engine side uses a\n * non-default pg-boss config (schema, retention, logger, etc.) so the\n * client enqueues jobs where the engine reads them. Mirrors the same\n * option on `WorkflowEngineOptions`.\n */\n boss?: PgBoss;\n} & ({ pool: pg.Pool; connectionString?: never } | { connectionString: string; pool?: never });\n\nexport type StartWorkflowOptions = {\n resourceId?: string;\n timeout?: number;\n retries?: number;\n expireInSeconds?: number;\n idempotencyKey?: string;\n};\n\nconst defaultLogger: WorkflowLogger = {\n log: (_message: string) => console.warn(_message),\n error: (message: string, error: Error) => console.error(message, error),\n};\n\nconst defaultExpireInSeconds = process.env.WORKFLOW_RUN_EXPIRE_IN_SECONDS\n ? Number.parseInt(process.env.WORKFLOW_RUN_EXPIRE_IN_SECONDS, 10)\n : 5 * 60;\n\nexport class WorkflowClient {\n private boss: PgBoss;\n private db: Db;\n private pool: pg.Pool;\n private _ownsPool = false;\n private _started = false;\n private logger: WorkflowLogger;\n\n constructor({ logger, boss, ...connectionOptions }: WorkflowClientOptions) {\n this.logger = logger ?? defaultLogger;\n\n if ('pool' in connectionOptions && connectionOptions.pool) {\n this.pool = connectionOptions.pool;\n } else if ('connectionString' in connectionOptions && connectionOptions.connectionString) {\n this.pool = new pg.Pool({ connectionString: connectionOptions.connectionString });\n this._ownsPool = true;\n } else {\n throw new WorkflowEngineError('Either pool or connectionString must be provided');\n }\n\n const db: Db = {\n executeSql: (text: string, values?: unknown[]) =>\n this.pool.query(text, values) as Promise<{ rows: unknown[] }>,\n };\n\n if (boss) {\n this.boss = boss;\n } else {\n this.boss = new PgBoss({ db, schema: DEFAULT_PGBOSS_SCHEMA });\n }\n this.db = db;\n }\n\n async start(): Promise<void> {\n if (this._started) {\n return;\n }\n\n await this.boss.start();\n this.db = this.boss.getDb();\n await runMigrations(this.db);\n await this.boss.createQueue(WORKFLOW_RUN_QUEUE_NAME);\n\n this._started = true;\n this.logger.log(`${LOG_PREFIX} Client started`);\n }\n\n async stop(): Promise<void> {\n await this.boss.stop();\n\n if (this._ownsPool) {\n await this.pool.end();\n }\n\n this._started = false;\n this.logger.log(`${LOG_PREFIX} Client stopped`);\n }\n\n async startWorkflow<TInput extends InputParameters>(\n ref: WorkflowRef<TInput>,\n input: InferInputParameters<TInput>,\n options?: StartWorkflowOptions,\n ): Promise<WorkflowRun>;\n\n async startWorkflow(params: {\n workflowId: string;\n input: unknown;\n resourceId?: string;\n idempotencyKey?: string;\n options?: StartWorkflowOptions;\n }): Promise<WorkflowRun>;\n\n async startWorkflow<TInput extends InputParameters>(\n refOrParams:\n | WorkflowRef<TInput>\n | {\n workflowId: string;\n input: unknown;\n resourceId?: string;\n idempotencyKey?: string;\n options?: StartWorkflowOptions;\n },\n inputArg?: InferInputParameters<TInput>,\n optionsArg?: StartWorkflowOptions,\n ): Promise<WorkflowRun> {\n await this.ensureStarted();\n\n let workflowId: string;\n let input: unknown;\n let resourceId: string | undefined;\n let idempotencyKey: string | undefined;\n let options: StartWorkflowOptions | undefined;\n\n if (typeof refOrParams === 'function' && 'id' in refOrParams) {\n const ref = refOrParams as WorkflowRef<TInput>;\n workflowId = ref.id;\n input = inputArg;\n options = optionsArg;\n resourceId = optionsArg?.resourceId;\n idempotencyKey = optionsArg?.idempotencyKey;\n\n if (ref.inputSchema) {\n const result = await ref.inputSchema['~standard'].validate(input);\n if (result.issues) {\n throw new WorkflowEngineError(\n JSON.stringify(result.issues),\n workflowId,\n undefined,\n undefined,\n result.issues,\n );\n }\n }\n } else {\n const params = refOrParams as {\n workflowId: string;\n input: unknown;\n resourceId?: string;\n idempotencyKey?: string;\n options?: StartWorkflowOptions;\n };\n workflowId = params.workflowId;\n input = params.input;\n resourceId = params.resourceId;\n idempotencyKey = params.idempotencyKey;\n options = params.options;\n }\n\n validateWorkflowId(workflowId);\n validateResourceId(resourceId);\n\n const run = await withPostgresTransaction(\n this.db,\n async (_db) => {\n const timeoutAt = options?.timeout ? new Date(Date.now() + options.timeout) : null;\n\n const { run: insertedRun, created } = await insertWorkflowRun(\n {\n resourceId,\n workflowId,\n currentStepId: '__start__',\n status: WorkflowStatus.RUNNING,\n input,\n maxRetries: options?.retries ?? 0,\n timeoutAt,\n idempotencyKey,\n },\n _db,\n );\n\n if (created) {\n const job: WorkflowRunJobParameters = {\n runId: insertedRun.id,\n resourceId,\n workflowId,\n input,\n };\n\n await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {\n startAfter: new Date(),\n expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,\n });\n }\n\n return insertedRun;\n },\n this.pool,\n );\n\n this.logger.log(`${LOG_PREFIX} Started workflow run ${run.id} for ${workflowId}`);\n\n return run;\n }\n\n async triggerEvent({\n runId,\n resourceId,\n eventName,\n data,\n options,\n }: {\n runId: string;\n resourceId?: string;\n eventName: string;\n data?: Record<string, unknown>;\n options?: { expireInSeconds?: number };\n }): Promise<WorkflowRun> {\n await this.ensureStarted();\n\n const run = await this.getRun({ runId, resourceId });\n\n const job: WorkflowRunJobParameters = {\n runId: run.id,\n resourceId: resourceId ?? run.resourceId ?? undefined,\n workflowId: run.workflowId,\n input: run.input,\n event: {\n name: eventName,\n data,\n },\n };\n\n await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {\n expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,\n });\n\n this.logger.log(`${LOG_PREFIX} Event ${eventName} sent for workflow run ${runId}`);\n return run;\n }\n\n async pauseWorkflow({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRun> {\n await this.ensureStarted();\n\n const run = await updateWorkflowRun(\n {\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.PAUSED,\n pausedAt: new Date(),\n },\n expectedStatuses: [WorkflowStatus.RUNNING, WorkflowStatus.PENDING],\n },\n this.db,\n );\n\n if (!run) {\n throw new WorkflowRunNotFoundError(runId);\n }\n\n this.logger.log(`${LOG_PREFIX} Paused workflow run ${runId}`);\n return run;\n }\n\n async resumeWorkflow({\n runId,\n resourceId,\n options,\n }: {\n runId: string;\n resourceId?: string;\n options?: { expireInSeconds?: number };\n }): Promise<WorkflowRun> {\n await this.ensureStarted();\n\n const current = await this.getRun({ runId, resourceId });\n if (current.status !== WorkflowStatus.PAUSED) {\n throw new WorkflowEngineError(\n `Cannot resume workflow run in '${current.status}' status, must be 'paused'`,\n current.workflowId,\n runId,\n );\n }\n\n return this.triggerEvent({\n runId,\n resourceId,\n eventName: PAUSE_EVENT_NAME,\n data: {},\n options,\n });\n }\n\n async fastForwardWorkflow({\n runId,\n resourceId,\n data,\n }: {\n runId: string;\n resourceId?: string;\n data?: Record<string, unknown>;\n }): Promise<WorkflowRun> {\n await this.ensureStarted();\n\n const run = await this.getRun({ runId, resourceId });\n\n if (run.status !== WorkflowStatus.PAUSED) {\n return run;\n }\n\n const stepId = run.currentStepId;\n const waitForEntry = run.timeline[`${stepId}-wait-for`];\n if (!waitForEntry || typeof waitForEntry !== 'object' || !('waitFor' in waitForEntry)) {\n return run;\n }\n\n const { eventName, timeoutEvent, skipOutput } = (\n waitForEntry as { waitFor: { eventName?: string; timeoutEvent?: string; skipOutput?: true } }\n ).waitFor;\n\n // step.pause() - delegate to resumeWorkflow\n if (eventName === PAUSE_EVENT_NAME) {\n return this.resumeWorkflow({ runId, resourceId });\n }\n\n // step.poll() - write output to timeline first, then trigger resume\n if (skipOutput && timeoutEvent) {\n await withPostgresTransaction(\n this.db,\n async (db) => {\n const freshRun = await getWorkflowRun({ runId, resourceId }, { exclusiveLock: true, db });\n if (!freshRun) throw new WorkflowRunNotFoundError(runId);\n return updateWorkflowRun(\n {\n runId,\n resourceId,\n data: {\n timeline: merge(freshRun.timeline, {\n [stepId]: {\n output: data ?? {},\n timestamp: new Date(),\n },\n }),\n },\n },\n db,\n );\n },\n this.pool,\n );\n\n return this.triggerEvent({ runId, resourceId, eventName: timeoutEvent });\n }\n\n // waitFor steps - trigger the event with data\n if (eventName) {\n return this.triggerEvent({ runId, resourceId, eventName, data: data ?? {} });\n }\n\n // delay/waitUntil steps - trigger the timeout event\n if (timeoutEvent) {\n return this.triggerEvent({ runId, resourceId, eventName: timeoutEvent, data: data ?? {} });\n }\n\n return run;\n }\n\n async cancelWorkflow({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRun> {\n await this.ensureStarted();\n\n const run = await updateWorkflowRun(\n {\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.CANCELLED,\n },\n expectedStatuses: [WorkflowStatus.PENDING, WorkflowStatus.RUNNING, WorkflowStatus.PAUSED],\n },\n this.db,\n );\n\n if (!run) {\n throw new WorkflowRunNotFoundError(runId);\n }\n\n this.logger.log(`${LOG_PREFIX} Cancelled workflow run ${runId}`);\n return run;\n }\n\n async getRun({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRun> {\n await this.ensureStarted();\n\n const run = await getWorkflowRun({ runId, resourceId }, { db: this.db });\n\n if (!run) {\n throw new WorkflowRunNotFoundError(runId);\n }\n\n return run;\n }\n\n async checkProgress({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRunProgress> {\n const run = await this.getRun({ runId, resourceId });\n\n const completedSteps = Object.values(run.timeline).filter(\n (entry): entry is { output: unknown; timestamp: Date } =>\n typeof entry === 'object' &&\n entry !== null &&\n 'output' in entry &&\n entry.output !== undefined,\n ).length;\n\n // Without registered workflow definitions, total steps are unknown.\n // Use completed steps as best-effort estimate for in-progress runs.\n const totalSteps = run.status === WorkflowStatus.COMPLETED ? completedSteps : 0;\n const completionPercentage =\n run.status === WorkflowStatus.COMPLETED\n ? 100\n : run.status === WorkflowStatus.FAILED || run.status === WorkflowStatus.CANCELLED\n ? 0\n : 0;\n\n return {\n ...run,\n completedSteps,\n completionPercentage,\n totalSteps,\n };\n }\n\n async getRuns({\n resourceId,\n startingAfter,\n endingBefore,\n limit = 20,\n statuses,\n workflowId,\n }: {\n resourceId?: string;\n startingAfter?: string | null;\n endingBefore?: string | null;\n limit?: number;\n statuses?: WorkflowStatus[];\n workflowId?: string;\n }): Promise<{\n items: WorkflowRun[];\n nextCursor: string | null;\n prevCursor: string | null;\n hasMore: boolean;\n hasPrev: boolean;\n }> {\n await this.ensureStarted();\n\n if (workflowId) validateWorkflowId(workflowId);\n validateResourceId(resourceId);\n\n return getWorkflowRuns(\n {\n resourceId,\n startingAfter,\n endingBefore,\n limit,\n statuses,\n workflowId,\n },\n this.db,\n );\n }\n\n private async ensureStarted(): Promise<void> {\n if (!this._started) {\n await this.start();\n }\n }\n}\n",
6
+ "export const PAUSE_EVENT_NAME = '__internal_pause';\nexport const WORKFLOW_RUN_QUEUE_NAME = 'workflow-run';\nexport const WORKFLOW_RUN_DLQ_QUEUE_NAME = 'workflow_run_dlq';\nexport const DEFAULT_PGBOSS_SCHEMA = 'pgboss_v12_pgworkflow';\nexport const MAX_WORKFLOW_ID_LENGTH = 256;\nexport const MAX_RESOURCE_ID_LENGTH = 256;\n",
7
+ "import type { Db } from 'pg-boss';\n\n// Arbitrary but stable lock ID for serializing migrations across processes\nexport const MIGRATION_LOCK_ID = 738291645;\n\n// Bump this when adding new migrations. The engine stores the current version\n// in a `workflow_schema_version` table so migrations only run once per version.\nconst CURRENT_SCHEMA_VERSION = 3;\n\nexport async function runMigrations(db: Db): Promise<void> {\n // Fast path: skip the advisory lock if schema is already current.\n // This is the common case - every engine.start() after initial setup.\n if (await isSchemaUpToDate(db)) {\n return;\n }\n\n // Slow path: build migration SQL based on current version, then execute\n // everything in a single transaction with an advisory lock.\n // This mirrors pg-boss's approach: one executeSql call ensures all DDL\n // runs on a single connection inside BEGIN/COMMIT, and pg_advisory_xact_lock\n // auto-releases on commit or rollback (no manual unlock needed).\n const currentVersion = await getCurrentVersion(db);\n\n const commands: string[] = [];\n\n if (currentVersion < 1) {\n commands.push(`\n CREATE TABLE IF NOT EXISTS workflow_runs (\n id varchar(32) PRIMARY KEY NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n resource_id varchar(256),\n workflow_id varchar(256) NOT NULL,\n status text DEFAULT 'pending' NOT NULL,\n input jsonb NOT NULL,\n output jsonb,\n error text,\n current_step_id varchar(256) NOT NULL,\n timeline jsonb DEFAULT '{}'::jsonb NOT NULL,\n paused_at timestamp with time zone,\n resumed_at timestamp with time zone,\n completed_at timestamp with time zone,\n timeout_at timestamp with time zone,\n retry_count integer DEFAULT 0 NOT NULL,\n max_retries integer DEFAULT 0 NOT NULL,\n job_id varchar(256)\n )\n `);\n commands.push(`\n CREATE INDEX IF NOT EXISTS workflow_runs_created_at_idx ON workflow_runs USING btree (created_at)\n `);\n commands.push(`\n CREATE INDEX IF NOT EXISTS workflow_runs_resource_id_created_at_idx ON workflow_runs USING btree (resource_id, created_at DESC)\n `);\n commands.push(`\n CREATE INDEX IF NOT EXISTS workflow_runs_status_created_at_idx ON workflow_runs USING btree (status, created_at DESC)\n `);\n commands.push(`\n CREATE INDEX IF NOT EXISTS workflow_runs_workflow_id_created_at_idx ON workflow_runs USING btree (workflow_id, created_at DESC)\n `);\n commands.push(`\n CREATE INDEX IF NOT EXISTS workflow_runs_resource_id_workflow_id_created_at_idx ON workflow_runs USING btree (resource_id, workflow_id, created_at DESC)\n `);\n }\n\n if (currentVersion < 2) {\n commands.push('DROP INDEX IF EXISTS workflow_runs_workflow_id_idx');\n commands.push('DROP INDEX IF EXISTS workflow_runs_resource_id_idx');\n commands.push(\n 'ALTER TABLE workflow_runs ADD COLUMN IF NOT EXISTS idempotency_key varchar(256)',\n );\n commands.push(`\n CREATE UNIQUE INDEX IF NOT EXISTS workflow_runs_idempotency_key_idx ON workflow_runs (idempotency_key) WHERE idempotency_key IS NOT NULL\n `);\n }\n\n if (currentVersion < 3) {\n commands.push('ALTER TABLE workflow_runs ALTER COLUMN resource_id TYPE varchar(256)');\n commands.push('ALTER TABLE workflow_runs ALTER COLUMN workflow_id TYPE varchar(256)');\n }\n\n // Upsert the schema version\n if (currentVersion === 0) {\n commands.push(\n `INSERT INTO workflow_schema_version (version) VALUES (${CURRENT_SCHEMA_VERSION})`,\n );\n } else {\n commands.push(`UPDATE workflow_schema_version SET version = ${CURRENT_SCHEMA_VERSION}`);\n }\n\n if (commands.length === 0) {\n return;\n }\n\n const sql = [\n 'BEGIN',\n \"SET LOCAL lock_timeout = '30s'\",\n \"SET LOCAL idle_in_transaction_session_timeout = '30s'\",\n `SELECT pg_advisory_xact_lock(${MIGRATION_LOCK_ID})`,\n 'CREATE TABLE IF NOT EXISTS workflow_schema_version (version integer NOT NULL)',\n ...commands,\n 'COMMIT',\n ].join(';\\n');\n\n await db.executeSql(sql, []);\n}\n\nasync function isSchemaUpToDate(db: Db): Promise<boolean> {\n try {\n const result = await db.executeSql('SELECT version FROM workflow_schema_version LIMIT 1', []);\n return (\n ((result.rows[0] as { version: number } | undefined)?.version ?? 0) >= CURRENT_SCHEMA_VERSION\n );\n } catch {\n // Table doesn't exist yet - needs migration\n return false;\n }\n}\n\nasync function getCurrentVersion(db: Db): Promise<number> {\n try {\n const result = await db.executeSql('SELECT version FROM workflow_schema_version LIMIT 1', []);\n return (result.rows[0] as { version: number } | undefined)?.version ?? 0;\n } catch {\n return 0;\n }\n}\n",
8
8
  "import ksuid from 'ksuid';\nimport type { Db } from 'pg-boss';\nimport type { WorkflowRun } from './types';\n\nexport function generateKSUID(prefix?: string): string {\n return `${prefix ? `${prefix}_` : ''}${ksuid.randomSync().string}`;\n}\n\ntype WorkflowRunRow = {\n id: string;\n created_at: string | Date;\n updated_at: string | Date;\n resource_id: string | null;\n workflow_id: string;\n status: 'pending' | 'running' | 'paused' | 'completed' | 'failed' | 'cancelled';\n input: string | unknown;\n output: string | unknown | null;\n error: string | null;\n current_step_id: string;\n timeline: string | Record<string, unknown>;\n paused_at: string | Date | null;\n resumed_at: string | Date | null;\n completed_at: string | Date | null;\n timeout_at: string | Date | null;\n retry_count: number;\n max_retries: number;\n job_id: string | null;\n idempotency_key: string | null;\n};\n\nfunction mapRowToWorkflowRun(row: WorkflowRunRow): WorkflowRun {\n return {\n id: row.id,\n createdAt: new Date(row.created_at),\n updatedAt: new Date(row.updated_at),\n resourceId: row.resource_id,\n workflowId: row.workflow_id,\n status: row.status,\n input: typeof row.input === 'string' ? JSON.parse(row.input) : row.input,\n output:\n typeof row.output === 'string'\n ? row.output.trim().startsWith('{') || row.output.trim().startsWith('[')\n ? JSON.parse(row.output)\n : row.output\n : (row.output ?? null),\n error: row.error,\n currentStepId: row.current_step_id,\n timeline: typeof row.timeline === 'string' ? JSON.parse(row.timeline) : row.timeline,\n pausedAt: row.paused_at ? new Date(row.paused_at) : null,\n resumedAt: row.resumed_at ? new Date(row.resumed_at) : null,\n completedAt: row.completed_at ? new Date(row.completed_at) : null,\n timeoutAt: row.timeout_at ? new Date(row.timeout_at) : null,\n retryCount: row.retry_count,\n maxRetries: row.max_retries,\n jobId: row.job_id,\n idempotencyKey: row.idempotency_key,\n };\n}\n\nexport async function insertWorkflowRun(\n {\n resourceId,\n workflowId,\n currentStepId,\n status,\n input,\n maxRetries,\n timeoutAt,\n idempotencyKey,\n }: {\n resourceId?: string;\n workflowId: string;\n currentStepId: string;\n status: string;\n input: unknown;\n maxRetries: number;\n timeoutAt: Date | null;\n idempotencyKey?: string;\n },\n db: Db,\n): Promise<{ run: WorkflowRun; created: boolean }> {\n const runId = generateKSUID('run');\n const now = new Date();\n\n const result = await db.executeSql(\n `INSERT INTO workflow_runs (\n id,\n resource_id,\n workflow_id,\n current_step_id,\n status,\n input,\n max_retries,\n timeout_at,\n created_at,\n updated_at,\n timeline,\n retry_count,\n idempotency_key\n )\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)\n ON CONFLICT (idempotency_key) WHERE idempotency_key IS NOT NULL DO NOTHING\n RETURNING *`,\n [\n runId,\n resourceId ?? null,\n workflowId,\n currentStepId,\n status,\n JSON.stringify(input),\n maxRetries,\n timeoutAt,\n now,\n now,\n '{}',\n 0,\n idempotencyKey ?? null,\n ],\n );\n\n if (result.rows[0]) {\n return { run: mapRowToWorkflowRun(result.rows[0]), created: true };\n }\n\n // Conflict - fetch the existing row\n const existing = await db.executeSql('SELECT * FROM workflow_runs WHERE idempotency_key = $1', [\n idempotencyKey,\n ]);\n\n if (!existing.rows[0]) {\n throw new Error(`Idempotency conflict: existing run not found for key \"${idempotencyKey}\"`);\n }\n\n return { run: mapRowToWorkflowRun(existing.rows[0]), created: false };\n}\n\nexport async function getWorkflowRun(\n {\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n },\n { exclusiveLock = false, db }: { exclusiveLock?: boolean; db: Db },\n): Promise<WorkflowRun | null> {\n const lockSuffix = exclusiveLock ? 'FOR UPDATE' : '';\n\n const result = resourceId\n ? await db.executeSql(\n `SELECT * FROM workflow_runs \n WHERE id = $1 AND resource_id = $2\n ${lockSuffix}`,\n [runId, resourceId],\n )\n : await db.executeSql(\n `SELECT * FROM workflow_runs \n WHERE id = $1\n ${lockSuffix}`,\n [runId],\n );\n\n const run = result.rows[0];\n\n if (!run) {\n return null;\n }\n\n return mapRowToWorkflowRun(run);\n}\n\nexport async function updateWorkflowRun(\n {\n runId,\n resourceId,\n data,\n expectedStatuses,\n }: {\n runId: string;\n resourceId?: string;\n data: Partial<WorkflowRun>;\n expectedStatuses?: string[];\n },\n db: Db,\n): Promise<WorkflowRun | null> {\n const now = new Date();\n\n const updates: string[] = ['updated_at = $1'];\n const values: (string | number | Date | null | string[])[] = [now];\n let paramIndex = 2;\n\n if (data.status !== undefined) {\n updates.push(`status = $${paramIndex}`);\n values.push(data.status);\n paramIndex++;\n }\n if (data.currentStepId !== undefined) {\n updates.push(`current_step_id = $${paramIndex}`);\n values.push(data.currentStepId);\n paramIndex++;\n }\n if (data.timeline !== undefined) {\n updates.push(`timeline = $${paramIndex}`);\n values.push(JSON.stringify(data.timeline));\n paramIndex++;\n }\n if (data.pausedAt !== undefined) {\n updates.push(`paused_at = $${paramIndex}`);\n values.push(data.pausedAt);\n paramIndex++;\n }\n if (data.resumedAt !== undefined) {\n updates.push(`resumed_at = $${paramIndex}`);\n values.push(data.resumedAt);\n paramIndex++;\n }\n if (data.completedAt !== undefined) {\n updates.push(`completed_at = $${paramIndex}`);\n values.push(data.completedAt);\n paramIndex++;\n }\n if (data.output !== undefined) {\n updates.push(`output = $${paramIndex}`);\n values.push(JSON.stringify(data.output));\n paramIndex++;\n }\n if (data.error !== undefined) {\n updates.push(`error = $${paramIndex}`);\n values.push(data.error);\n paramIndex++;\n }\n if (data.retryCount !== undefined) {\n updates.push(`retry_count = $${paramIndex}`);\n values.push(data.retryCount);\n paramIndex++;\n }\n if (data.jobId !== undefined) {\n updates.push(`job_id = $${paramIndex}`);\n values.push(data.jobId);\n paramIndex++;\n }\n\n values.push(runId);\n const idParam = paramIndex;\n paramIndex++;\n\n if (resourceId) {\n values.push(resourceId);\n paramIndex++;\n }\n\n if (expectedStatuses && expectedStatuses.length > 0) {\n values.push(expectedStatuses);\n paramIndex++;\n }\n\n let whereClause = resourceId\n ? `WHERE id = $${idParam} AND resource_id = $${idParam + 1}`\n : `WHERE id = $${idParam}`;\n\n if (expectedStatuses && expectedStatuses.length > 0) {\n whereClause += ` AND status = ANY($${paramIndex - 1})`;\n }\n\n const query = `\n UPDATE workflow_runs \n SET ${updates.join(', ')}\n ${whereClause}\n RETURNING *\n `;\n\n const result = await db.executeSql(query, values);\n const run = result.rows[0];\n\n if (!run) {\n return null;\n }\n\n return mapRowToWorkflowRun(run);\n}\n\nexport async function getWorkflowRuns(\n {\n resourceId,\n startingAfter,\n endingBefore,\n limit = 20,\n statuses,\n workflowId,\n }: {\n resourceId?: string;\n startingAfter?: string | null;\n endingBefore?: string | null;\n limit?: number;\n statuses?: string[];\n workflowId?: string;\n },\n db: Db,\n): Promise<{\n items: WorkflowRun[];\n nextCursor: string | null;\n prevCursor: string | null;\n hasMore: boolean;\n hasPrev: boolean;\n}> {\n const conditions: string[] = [];\n const values: (string | number | string[] | Date)[] = [];\n let paramIndex = 1;\n\n if (resourceId) {\n conditions.push(`resource_id = $${paramIndex}`);\n values.push(resourceId);\n paramIndex++;\n }\n\n if (statuses && statuses.length > 0) {\n conditions.push(`status = ANY($${paramIndex})`);\n values.push(statuses);\n paramIndex++;\n }\n\n if (workflowId) {\n conditions.push(`workflow_id = $${paramIndex}`);\n values.push(workflowId);\n paramIndex++;\n }\n\n const cursorIds = [startingAfter, endingBefore].filter(Boolean) as string[];\n if (cursorIds.length > 0) {\n const cursorResult = await db.executeSql(\n 'SELECT id, created_at FROM workflow_runs WHERE id = ANY($1)',\n [cursorIds],\n );\n const cursorMap = new Map<string, Date>();\n for (const row of cursorResult.rows) {\n cursorMap.set(\n row.id,\n typeof row.created_at === 'string' ? new Date(row.created_at) : row.created_at,\n );\n }\n\n if (startingAfter) {\n const cursor = cursorMap.get(startingAfter);\n if (cursor) {\n conditions.push(`created_at < $${paramIndex}`);\n values.push(cursor);\n paramIndex++;\n }\n }\n\n if (endingBefore) {\n const cursor = cursorMap.get(endingBefore);\n if (cursor) {\n conditions.push(`created_at > $${paramIndex}`);\n values.push(cursor);\n paramIndex++;\n }\n }\n }\n\n const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n const actualLimit = Math.min(Math.max(limit, 1), 100) + 1;\n\n const isBackward = !!endingBefore && !startingAfter;\n\n const query = `\n SELECT * FROM workflow_runs\n ${whereClause}\n ORDER BY created_at ${isBackward ? 'ASC' : 'DESC'}\n LIMIT $${paramIndex}\n `;\n values.push(actualLimit);\n\n const result = await db.executeSql(query, values);\n const rows = result.rows;\n\n const hasExtraRow = rows.length > (limit ?? 20);\n const rawItems = hasExtraRow ? rows.slice(0, limit) : rows;\n\n if (isBackward) {\n rawItems.reverse();\n }\n\n const items = rawItems.map((row) => mapRowToWorkflowRun(row));\n\n const hasMore = isBackward ? items.length > 0 : hasExtraRow;\n const hasPrev = isBackward ? hasExtraRow : !!startingAfter && items.length > 0;\n\n const nextCursor = hasMore && items.length > 0 ? (items[items.length - 1]?.id ?? null) : null;\n const prevCursor = hasPrev && items.length > 0 ? (items[0]?.id ?? null) : null;\n\n return { items, nextCursor, prevCursor, hasMore, hasPrev };\n}\n\n/**\n * Run a callback inside a PostgreSQL transaction using a dedicated client.\n *\n * When a `pool` is provided, a dedicated client is checked out so that\n * BEGIN / COMMIT / ROLLBACK all execute on the **same** connection.\n * This is critical for `SELECT … FOR UPDATE` locks and any work that\n * yields to the event-loop inside the transaction (e.g. async step handlers).\n *\n * Falls back to the pg-boss `Db` adapter when no pool is given (unit-test path).\n */\nexport async function withPostgresTransaction<T>(\n db: Db,\n callback: (db: Db) => Promise<T>,\n pool?: {\n connect: () => Promise<{\n query: (text: string, values?: unknown[]) => Promise<unknown>;\n release: () => void;\n }>;\n },\n): Promise<T> {\n let txDb: Db;\n let release: (() => void) | undefined;\n\n if (pool) {\n const client = await pool.connect();\n txDb = {\n executeSql: (text: string, values?: unknown[]) =>\n client.query(text, values) as Promise<{ rows: unknown[] }>,\n };\n release = () => client.release();\n } else {\n txDb = db;\n }\n\n try {\n await txDb.executeSql('BEGIN', []);\n const result = await callback(txDb);\n await txDb.executeSql('COMMIT', []);\n return result;\n } catch (error) {\n await txDb.executeSql('ROLLBACK', []);\n throw error;\n } finally {\n release?.();\n }\n}\n",
9
- "import type { StandardSchemaV1 } from '@standard-schema/spec';\n\nexport class WorkflowEngineError extends Error {\n constructor(\n message: string,\n public readonly workflowId?: string,\n public readonly runId?: string,\n public override readonly cause: Error | undefined = undefined,\n public readonly issues?: StandardSchemaV1.FailureResult['issues'] | undefined,\n ) {\n super(message);\n this.name = 'WorkflowEngineError';\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, WorkflowEngineError);\n }\n }\n}\n\nexport class WorkflowRunNotFoundError extends WorkflowEngineError {\n constructor(runId?: string, workflowId?: string) {\n super('Workflow run not found', workflowId, runId);\n this.name = 'WorkflowRunNotFoundError';\n }\n}\n",
9
+ "import type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { MAX_RESOURCE_ID_LENGTH, MAX_WORKFLOW_ID_LENGTH } from './constants';\n\nexport function validateWorkflowId(workflowId: string): void {\n if (workflowId.length > MAX_WORKFLOW_ID_LENGTH) {\n throw new WorkflowEngineError(\n `workflowId exceeds maximum length of ${MAX_WORKFLOW_ID_LENGTH} characters (got ${workflowId.length})`,\n workflowId,\n );\n }\n}\n\nexport function validateResourceId(resourceId: string | undefined | null): void {\n if (resourceId != null && resourceId.length > MAX_RESOURCE_ID_LENGTH) {\n throw new WorkflowEngineError(\n `resourceId exceeds maximum length of ${MAX_RESOURCE_ID_LENGTH} characters (got ${resourceId.length})`,\n );\n }\n}\n\nexport class WorkflowEngineError extends Error {\n constructor(\n message: string,\n public readonly workflowId?: string,\n public readonly runId?: string,\n public override readonly cause: Error | undefined = undefined,\n public readonly issues?: StandardSchemaV1.FailureResult['issues'] | undefined,\n ) {\n super(message);\n this.name = 'WorkflowEngineError';\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, WorkflowEngineError);\n }\n }\n}\n\nexport class WorkflowRunNotFoundError extends WorkflowEngineError {\n constructor(runId?: string, workflowId?: string) {\n super('Workflow run not found', workflowId, runId);\n this.name = 'WorkflowRunNotFoundError';\n }\n}\n",
10
10
  "import type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { WorkflowRun } from './db/types';\nimport type { Duration } from './duration';\n\nexport enum WorkflowStatus {\n PENDING = 'pending',\n RUNNING = 'running',\n PAUSED = 'paused',\n COMPLETED = 'completed',\n FAILED = 'failed',\n CANCELLED = 'cancelled',\n}\n\nexport enum StepType {\n PAUSE = 'pause',\n RUN = 'run',\n WAIT_FOR = 'waitFor',\n WAIT_UNTIL = 'waitUntil',\n DELAY = 'delay',\n POLL = 'poll',\n}\n\nexport type InputParameters = StandardSchemaV1;\nexport type InferInputParameters<P extends InputParameters> = StandardSchemaV1.InferOutput<P>;\n\nexport type WorkflowOptions<I extends InputParameters> = {\n timeout?: number;\n retries?: number;\n inputSchema?: I;\n};\n\nexport type StepBaseContext = {\n run: <T>(stepId: string, handler: () => Promise<T>) => Promise<T>;\n waitFor: {\n <T extends InputParameters>(\n stepId: string,\n options: { eventName: string; schema?: T },\n ): Promise<InferInputParameters<T>>;\n <T extends InputParameters>(\n stepId: string,\n options: { eventName: string; timeout: number; schema?: T },\n ): Promise<InferInputParameters<T> | undefined>;\n };\n waitUntil: {\n (stepId: string, date: Date): Promise<void>;\n (stepId: string, dateString: string): Promise<void>;\n (stepId: string, options: { date: Date | string }): Promise<void>;\n };\n /** Delay execution for a duration (sugar over waitUntil). Alias: sleep. */\n delay: (stepId: string, duration: Duration) => Promise<void>;\n /** Alias for delay. */\n sleep: (stepId: string, duration: Duration) => Promise<void>;\n pause: (stepId: string) => Promise<void>;\n poll: <T>(\n stepId: string,\n conditionFn: () => Promise<T | false>,\n options?: { interval?: Duration; timeout?: Duration },\n ) => Promise<{ timedOut: false; data: T } | { timedOut: true }>;\n};\n\n/**\n * Plugin that extends the workflow step API with extra methods.\n * @template TStepBase - The step type this plugin receives (base + previous plugins).\n * @template TStepExt - The extra methods this plugin adds to step.\n */\nexport interface WorkflowPlugin<TStepBase = StepBaseContext, TStepExt = object> {\n name: string;\n methods: (step: TStepBase) => TStepExt;\n}\n\nexport type WorkflowContext<\n TInput extends InputParameters = InputParameters,\n TStep extends StepBaseContext = StepBaseContext,\n> = {\n input: InferInputParameters<TInput>;\n step: TStep;\n workflowId: string;\n runId: string;\n timeline: Record<string, unknown>;\n logger: WorkflowLogger;\n};\n\nexport type WorkflowDefinition<TInput extends InputParameters = InputParameters> = {\n id: string;\n /** Widest context avoids contravariance when collecting definitions; `workflow()` still types the handler narrowly. */\n handler: (context: WorkflowContext<InputParameters, StepBaseContext>) => Promise<unknown>;\n inputSchema?: TInput;\n timeout?: number; // milliseconds\n retries?: number;\n plugins?: WorkflowPlugin[];\n};\n\nexport type StepInternalDefinition = {\n id: string;\n type: StepType;\n conditional: boolean;\n loop: boolean;\n isDynamic: boolean;\n};\n\nexport type WorkflowInternalDefinition<TInput extends InputParameters = InputParameters> =\n WorkflowDefinition<TInput> & {\n steps: StepInternalDefinition[];\n };\n\n/**\n * Chainable workflow factory: call as (id, handler, options) and/or use .use(plugin).\n * TStepExt is the accumulated step extension from all plugins (step = StepContext & TStepExt).\n */\nexport interface WorkflowFactory<TStepExt = object> {\n <I extends InputParameters = InputParameters>(\n id: string,\n handler: (context: WorkflowContext<I, StepBaseContext & TStepExt>) => Promise<unknown>,\n options?: WorkflowOptions<I>,\n ): WorkflowDefinition<I>;\n use<TNewExt>(\n plugin: WorkflowPlugin<StepBaseContext & TStepExt, TNewExt>,\n ): WorkflowFactory<TStepExt & TNewExt>;\n ref<TInput extends InputParameters = InputParameters>(\n id: string,\n options?: { inputSchema?: TInput },\n ): WorkflowRef<TInput>;\n}\n\n/**\n * Lightweight workflow reference - carries the workflow ID and input type\n * but no handler code. Safe to import in API services without pulling in\n * heavy worker dependencies.\n *\n * Callable: pass a handler to create a full WorkflowDefinition.\n */\nexport interface WorkflowRef<TInput extends InputParameters = InputParameters> {\n (\n handler: (context: WorkflowContext<TInput, StepBaseContext>) => Promise<unknown>,\n options?: Omit<WorkflowOptions<TInput>, 'inputSchema'>,\n ): WorkflowDefinition<TInput>;\n readonly id: string;\n readonly inputSchema?: TInput;\n}\n\nexport type WorkflowRunProgress = WorkflowRun & {\n completionPercentage: number;\n totalSteps: number;\n completedSteps: number;\n};\n\nexport interface WorkflowLogger {\n log(message: string): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nexport type WorkflowInternalLoggerContext = {\n runId?: string;\n workflowId?: string;\n};\nexport interface WorkflowInternalLogger {\n log(message: string, context?: WorkflowInternalLoggerContext): void;\n error(message: string, error: Error, context?: WorkflowInternalLoggerContext): void;\n}\n",
11
11
  "import type {\n InputParameters,\n StepBaseContext,\n WorkflowContext,\n WorkflowDefinition,\n WorkflowFactory,\n WorkflowOptions,\n WorkflowPlugin,\n WorkflowRef,\n} from './types';\n\n/**\n * Create a lightweight workflow reference.\n * Safe to import from `pg-workflows/client` - no engine or handler code.\n */\nexport function createWorkflowRef<TInput extends InputParameters = InputParameters>(\n id: string,\n options?: { inputSchema?: TInput },\n): WorkflowRef<TInput> {\n const ref = ((\n handler: (context: WorkflowContext<TInput, StepBaseContext>) => Promise<unknown>,\n defineOptions?: Omit<WorkflowOptions<TInput>, 'inputSchema'>,\n ): WorkflowDefinition<TInput> => ({\n id,\n handler: handler as (\n context: WorkflowContext<InputParameters, StepBaseContext>,\n ) => Promise<unknown>,\n inputSchema: options?.inputSchema,\n timeout: defineOptions?.timeout,\n retries: defineOptions?.retries,\n })) as WorkflowRef<TInput>;\n\n Object.defineProperty(ref, 'id', { value: id, enumerable: true });\n Object.defineProperty(ref, 'inputSchema', { value: options?.inputSchema, enumerable: true });\n\n return ref;\n}\n\nfunction createWorkflowFactory<TStepExt extends object = object>(\n plugins: Array<WorkflowPlugin<unknown, object>> = [],\n): WorkflowFactory<TStepExt> {\n const factory = (<I extends InputParameters>(\n id: string,\n handler: (context: WorkflowContext<I, StepBaseContext & TStepExt>) => Promise<unknown>,\n { inputSchema, timeout, retries }: WorkflowOptions<I> = {},\n ): WorkflowDefinition<I> => ({\n id,\n handler: handler as (\n context: WorkflowContext<InputParameters, StepBaseContext>,\n ) => Promise<unknown>,\n inputSchema,\n timeout,\n retries,\n plugins: plugins.length > 0 ? (plugins as WorkflowPlugin[]) : undefined,\n })) as WorkflowFactory<TStepExt>;\n\n factory.use = <TNewExt>(\n plugin: WorkflowPlugin<StepBaseContext & TStepExt, TNewExt>,\n ): WorkflowFactory<TStepExt & TNewExt> =>\n createWorkflowFactory<TStepExt & TNewExt>([\n ...plugins,\n plugin as WorkflowPlugin<unknown, object>,\n ]);\n\n factory.ref = createWorkflowRef;\n\n return factory;\n}\n\nexport const workflow: WorkflowFactory = createWorkflowFactory();\n",
12
12
  "import parse from 'parse-duration';\nimport { WorkflowEngineError } from './error';\n\nexport type DurationObject = {\n weeks?: number;\n days?: number;\n hours?: number;\n minutes?: number;\n seconds?: number;\n};\n\nexport type Duration = string | DurationObject;\n\nconst MS_PER_SECOND = 1000;\nconst MS_PER_MINUTE = 60 * MS_PER_SECOND;\nconst MS_PER_HOUR = 60 * MS_PER_MINUTE;\nconst MS_PER_DAY = 24 * MS_PER_HOUR;\nconst MS_PER_WEEK = 7 * MS_PER_DAY;\n\nexport function parseDuration(duration: Duration): number {\n if (typeof duration === 'string') {\n if (duration.trim() === '') {\n throw new WorkflowEngineError('Invalid duration: empty string');\n }\n\n const ms = parse(duration);\n\n if (ms == null || ms <= 0) {\n throw new WorkflowEngineError(`Invalid duration: \"${duration}\"`);\n }\n\n return ms;\n }\n\n const { weeks = 0, days = 0, hours = 0, minutes = 0, seconds = 0 } = duration;\n\n const ms =\n weeks * MS_PER_WEEK +\n days * MS_PER_DAY +\n hours * MS_PER_HOUR +\n minutes * MS_PER_MINUTE +\n seconds * MS_PER_SECOND;\n\n if (ms <= 0) {\n throw new WorkflowEngineError('Invalid duration: must be a positive value');\n }\n\n return ms;\n}\n",
13
- "import { merge } from 'es-toolkit';\nimport pg from 'pg';\nimport { type Db, type Job, PgBoss } from 'pg-boss';\nimport { parseWorkflowHandler } from './ast-parser';\nimport { DEFAULT_PGBOSS_SCHEMA, PAUSE_EVENT_NAME, WORKFLOW_RUN_QUEUE_NAME } from './constants';\nimport { runMigrations } from './db/migration';\nimport {\n getWorkflowRun,\n getWorkflowRuns,\n insertWorkflowRun,\n updateWorkflowRun,\n withPostgresTransaction,\n} from './db/queries';\nimport type { WorkflowRun } from './db/types';\nimport type { Duration } from './duration';\nimport { parseDuration } from './duration';\nimport { WorkflowEngineError, WorkflowRunNotFoundError } from './error';\nimport {\n type InferInputParameters,\n type InputParameters,\n StepType,\n type WorkflowContext,\n type WorkflowDefinition,\n type WorkflowInternalDefinition,\n type WorkflowInternalLogger,\n type WorkflowInternalLoggerContext,\n type WorkflowLogger,\n type WorkflowRef,\n type WorkflowRunProgress,\n WorkflowStatus,\n} from './types';\n\nconst LOG_PREFIX = '[WorkflowEngine]';\n\ntype StartWorkflowOptions = {\n resourceId?: string;\n timeout?: number;\n retries?: number;\n expireInSeconds?: number;\n batchSize?: number;\n idempotencyKey?: string;\n};\n\nexport type WorkflowEngineOptions = {\n workflows?: WorkflowDefinition[];\n logger?: WorkflowLogger;\n boss?: PgBoss;\n} & ({ pool: pg.Pool; connectionString?: never } | { connectionString: string; pool?: never });\n\nconst StepTypeToIcon = {\n [StepType.RUN]: 'λ',\n [StepType.WAIT_FOR]: '○',\n [StepType.PAUSE]: '⏸',\n [StepType.WAIT_UNTIL]: '⏲',\n [StepType.DELAY]: '⏱',\n [StepType.POLL]: '↻',\n};\n\n// Timeline entry types\ntype TimelineStepEntry = {\n output?: unknown;\n timedOut?: true;\n timestamp: Date;\n};\n\ntype TimelineWaitForEntry = {\n waitFor: {\n eventName?: string;\n timeoutEvent?: string;\n skipOutput?: true;\n };\n timestamp: Date;\n};\n\ntype WorkflowRunJobParameters = {\n runId: string;\n resourceId?: string;\n workflowId: string;\n input: unknown;\n event?: {\n name: string;\n data?: Record<string, unknown>;\n };\n};\n\nconst defaultLogger: WorkflowLogger = {\n log: (_message: string) => console.warn(_message),\n error: (message: string, error: Error) => console.error(message, error),\n};\n\nconst defaultExpireInSeconds = process.env.WORKFLOW_RUN_EXPIRE_IN_SECONDS\n ? Number.parseInt(process.env.WORKFLOW_RUN_EXPIRE_IN_SECONDS, 10)\n : 5 * 60; // 5 minutes\n\nexport class WorkflowEngine {\n private boss: PgBoss;\n private db: Db;\n private pool: pg.Pool;\n private _ownsPool = false;\n private unregisteredWorkflows = new Map<string, WorkflowDefinition>();\n private _started = false;\n\n public workflows: Map<string, WorkflowInternalDefinition> = new Map<\n string,\n WorkflowInternalDefinition\n >();\n private logger: WorkflowInternalLogger;\n\n constructor({ workflows, logger, boss, ...connectionOptions }: WorkflowEngineOptions) {\n this.logger = this.buildLogger(logger ?? defaultLogger);\n\n if ('pool' in connectionOptions && connectionOptions.pool) {\n this.pool = connectionOptions.pool;\n } else if ('connectionString' in connectionOptions && connectionOptions.connectionString) {\n this.pool = new pg.Pool({ connectionString: connectionOptions.connectionString });\n this._ownsPool = true;\n } else {\n throw new WorkflowEngineError('Either pool or connectionString must be provided');\n }\n\n if (workflows) {\n this.unregisteredWorkflows = new Map(workflows.map((workflow) => [workflow.id, workflow]));\n }\n\n const db: Db = {\n executeSql: (text: string, values?: unknown[]) =>\n this.pool.query(text, values) as Promise<{ rows: unknown[] }>,\n };\n\n if (boss) {\n this.boss = boss;\n } else {\n this.boss = new PgBoss({ db, schema: DEFAULT_PGBOSS_SCHEMA });\n }\n this.db = this.boss.getDb();\n }\n\n async start(\n asEngine = true,\n { batchSize }: { batchSize?: number } = { batchSize: 1 },\n ): Promise<void> {\n if (this._started) {\n return;\n }\n\n // Start boss first to get the database connection\n await this.boss.start();\n\n await runMigrations(this.boss.getDb());\n\n if (this.unregisteredWorkflows.size > 0) {\n for (const workflow of this.unregisteredWorkflows.values()) {\n await this.registerWorkflow(workflow);\n }\n }\n\n await this.boss.createQueue(WORKFLOW_RUN_QUEUE_NAME);\n\n const numWorkers: number = +(process.env.WORKFLOW_RUN_WORKERS ?? 3);\n\n if (asEngine) {\n for (let i = 0; i < numWorkers; i++) {\n await this.boss.work<WorkflowRunJobParameters>(\n WORKFLOW_RUN_QUEUE_NAME,\n { pollingIntervalSeconds: 0.5, batchSize },\n (job) => this.handleWorkflowRun(job),\n );\n this.logger.log(\n `Worker ${i + 1}/${numWorkers} started for queue ${WORKFLOW_RUN_QUEUE_NAME}`,\n );\n }\n }\n\n this._started = true;\n\n this.logger.log('Workflow engine started!');\n }\n\n async stop(): Promise<void> {\n await this.boss.stop();\n\n if (this._ownsPool) {\n await this.pool.end();\n }\n\n this._started = false;\n\n this.logger.log('Workflow engine stopped');\n }\n\n async registerWorkflow(definition: WorkflowDefinition<InputParameters>): Promise<WorkflowEngine> {\n if (this.workflows.has(definition.id)) {\n throw new WorkflowEngineError(\n `Workflow ${definition.id} is already registered`,\n definition.id,\n );\n }\n\n const { steps } = parseWorkflowHandler(\n definition.handler as (context: WorkflowContext) => Promise<unknown>,\n );\n\n this.workflows.set(definition.id, {\n ...definition,\n steps,\n } as WorkflowInternalDefinition);\n\n this.logger.log(`Registered workflow \"${definition.id}\" with steps:`);\n for (const step of steps.values()) {\n const tags = [];\n if (step.conditional) tags.push('[conditional]');\n if (step.loop) tags.push('[loop]');\n if (step.isDynamic) tags.push('[dynamic]');\n this.logger.log(` └─ (${StepTypeToIcon[step.type]}) ${step.id} ${tags.join(' ')}`);\n }\n\n return this;\n }\n\n async unregisterWorkflow(workflowId: string): Promise<WorkflowEngine> {\n this.workflows.delete(workflowId);\n return this;\n }\n\n async unregisterAllWorkflows(): Promise<WorkflowEngine> {\n this.workflows.clear();\n return this;\n }\n\n async startWorkflow<TInput extends InputParameters>(\n ref: WorkflowRef<TInput>,\n input: InferInputParameters<TInput>,\n options?: StartWorkflowOptions,\n ): Promise<WorkflowRun>;\n\n async startWorkflow(params: {\n resourceId?: string;\n workflowId: string;\n input: unknown;\n idempotencyKey?: string;\n options?: StartWorkflowOptions;\n }): Promise<WorkflowRun>;\n\n async startWorkflow<TInput extends InputParameters>(\n refOrParams:\n | WorkflowRef<TInput>\n | {\n resourceId?: string;\n workflowId: string;\n input: unknown;\n idempotencyKey?: string;\n options?: StartWorkflowOptions;\n },\n inputArg?: InferInputParameters<TInput>,\n optionsArg?: StartWorkflowOptions,\n ): Promise<WorkflowRun> {\n let workflowId: string;\n let input: unknown;\n let resourceId: string | undefined;\n let idempotencyKey: string | undefined;\n let options: StartWorkflowOptions | undefined;\n\n if (typeof refOrParams === 'function' && 'id' in refOrParams) {\n workflowId = refOrParams.id;\n input = inputArg;\n options = optionsArg;\n resourceId = optionsArg?.resourceId;\n idempotencyKey = optionsArg?.idempotencyKey;\n } else {\n const params = refOrParams as {\n resourceId?: string;\n workflowId: string;\n input: unknown;\n idempotencyKey?: string;\n options?: StartWorkflowOptions;\n };\n workflowId = params.workflowId;\n input = params.input;\n resourceId = params.resourceId;\n idempotencyKey = params.idempotencyKey;\n options = params.options;\n }\n\n if (!this._started) {\n await this.start(false, { batchSize: options?.batchSize ?? 1 });\n }\n\n const workflow = this.workflows.get(workflowId);\n if (!workflow) {\n throw new WorkflowEngineError(`Unknown workflow ${workflowId}`);\n }\n\n const hasSteps = workflow.steps.length > 0 && workflow.steps[0];\n const hasPlugins = (workflow.plugins?.length ?? 0) > 0;\n if (!hasSteps && !hasPlugins) {\n throw new WorkflowEngineError(`Workflow ${workflowId} has no steps`, workflowId);\n }\n if (workflow.inputSchema) {\n const result = await workflow.inputSchema['~standard'].validate(input);\n if (result.issues) {\n throw new WorkflowEngineError(\n JSON.stringify(result.issues),\n workflowId,\n undefined,\n undefined,\n result.issues,\n );\n }\n }\n\n const initialStepId = workflow.steps[0]?.id ?? '__start__';\n\n const run = await withPostgresTransaction(\n this.boss.getDb(),\n async (_db) => {\n const timeoutAt = options?.timeout\n ? new Date(Date.now() + options.timeout)\n : workflow.timeout\n ? new Date(Date.now() + workflow.timeout)\n : null;\n\n const { run: insertedRun, created } = await insertWorkflowRun(\n {\n resourceId,\n workflowId,\n currentStepId: initialStepId,\n status: WorkflowStatus.RUNNING,\n input,\n maxRetries: options?.retries ?? workflow.retries ?? 0,\n timeoutAt,\n idempotencyKey,\n },\n _db,\n );\n\n if (created) {\n const job: WorkflowRunJobParameters = {\n runId: insertedRun.id,\n resourceId,\n workflowId,\n input,\n };\n\n await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {\n startAfter: new Date(),\n expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,\n });\n }\n\n return insertedRun;\n },\n this.pool,\n );\n\n this.logger.log('Started workflow run', {\n runId: run.id,\n workflowId,\n });\n\n return run;\n }\n\n async pauseWorkflow({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n // TODO: Pause all running steps immediately\n const run = await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.PAUSED,\n pausedAt: new Date(),\n },\n expectedStatuses: [WorkflowStatus.RUNNING, WorkflowStatus.PENDING],\n });\n\n this.logger.log('Paused workflow run', {\n runId,\n workflowId: run.workflowId,\n });\n\n return run;\n }\n\n async resumeWorkflow({\n runId,\n resourceId,\n options,\n }: {\n runId: string;\n resourceId?: string;\n options?: { expireInSeconds?: number };\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n const current = await this.getRun({ runId, resourceId });\n if (current.status !== WorkflowStatus.PAUSED) {\n throw new WorkflowEngineError(\n `Cannot resume workflow run in '${current.status}' status, must be 'paused'`,\n current.workflowId,\n runId,\n );\n }\n\n return this.triggerEvent({\n runId,\n resourceId,\n eventName: PAUSE_EVENT_NAME,\n data: {},\n options,\n });\n }\n\n async fastForwardWorkflow({\n runId,\n resourceId,\n data,\n }: {\n runId: string;\n resourceId?: string;\n data?: Record<string, unknown>;\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n const run = await this.getRun({ runId, resourceId });\n\n if (run.status !== WorkflowStatus.PAUSED) {\n return run;\n }\n\n const stepId = run.currentStepId;\n const waitForStep = this.getWaitForStepEntry(run.timeline, stepId);\n\n if (!waitForStep) {\n return run;\n }\n\n const { eventName, timeoutEvent, skipOutput } = waitForStep.waitFor;\n\n // step.pause() - delegate to resumeWorkflow\n if (eventName === PAUSE_EVENT_NAME) {\n return this.resumeWorkflow({ runId, resourceId });\n }\n\n // step.poll() - write output to timeline first, then trigger resume\n if (skipOutput && timeoutEvent) {\n await withPostgresTransaction(\n this.db,\n async (db) => {\n const freshRun = await this.getRun({ runId, resourceId }, { exclusiveLock: true, db });\n return this.updateRun(\n {\n runId,\n resourceId,\n data: {\n timeline: merge(freshRun.timeline, {\n [stepId]: {\n output: data ?? {},\n timestamp: new Date(),\n },\n }),\n },\n },\n { db },\n );\n },\n this.pool,\n );\n\n return this.triggerEvent({ runId, resourceId, eventName: timeoutEvent });\n }\n\n // waitFor steps - trigger the event with data\n if (eventName) {\n return this.triggerEvent({ runId, resourceId, eventName, data: data ?? {} });\n }\n\n // delay/waitUntil steps - trigger the timeout event\n if (timeoutEvent) {\n return this.triggerEvent({ runId, resourceId, eventName: timeoutEvent, data: data ?? {} });\n }\n\n return run;\n }\n\n async cancelWorkflow({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n const run = await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.CANCELLED,\n },\n expectedStatuses: [WorkflowStatus.PENDING, WorkflowStatus.RUNNING, WorkflowStatus.PAUSED],\n });\n\n this.logger.log(`cancelled workflow run with id ${runId}`);\n\n return run;\n }\n\n async triggerEvent({\n runId,\n resourceId,\n eventName,\n data,\n options,\n }: {\n runId: string;\n resourceId?: string;\n eventName: string;\n data?: Record<string, unknown>;\n options?: {\n expireInSeconds?: number;\n };\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n const run = await this.getRun({ runId, resourceId });\n\n const jobResourceId = resourceId ?? run.resourceId ?? undefined;\n\n const job: WorkflowRunJobParameters = {\n runId: run.id,\n resourceId: jobResourceId,\n workflowId: run.workflowId,\n input: run.input,\n event: {\n name: eventName,\n data,\n },\n };\n\n await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {\n expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,\n });\n\n this.logger.log(`event ${eventName} sent for workflow run with id ${runId}`);\n return run;\n }\n\n async getRun(\n { runId, resourceId }: { runId: string; resourceId?: string },\n { exclusiveLock = false, db }: { exclusiveLock?: boolean; db?: Db } = {},\n ): Promise<WorkflowRun> {\n const run = await getWorkflowRun({ runId, resourceId }, { exclusiveLock, db: db ?? this.db });\n\n if (!run) {\n throw new WorkflowRunNotFoundError(runId);\n }\n\n return run;\n }\n\n async updateRun(\n {\n runId,\n resourceId,\n data,\n expectedStatuses,\n }: {\n runId: string;\n resourceId?: string;\n data: Partial<WorkflowRun>;\n expectedStatuses?: string[];\n },\n { db }: { db?: Db } = {},\n ): Promise<WorkflowRun> {\n const run = await updateWorkflowRun(\n { runId, resourceId, data, expectedStatuses },\n db ?? this.db,\n );\n\n if (!run) {\n if (expectedStatuses) {\n const current = await getWorkflowRun({ runId, resourceId }, { db: db ?? this.db });\n if (current) {\n throw new WorkflowEngineError(\n `Cannot update workflow run in '${current.status}' status, expected: ${expectedStatuses.join(', ')}`,\n current.workflowId,\n runId,\n );\n }\n }\n throw new WorkflowRunNotFoundError(runId);\n }\n\n return run;\n }\n\n async checkProgress({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRunProgress> {\n const run = await this.getRun({ runId, resourceId });\n const workflow = this.workflows.get(run.workflowId);\n\n if (!workflow) {\n throw new WorkflowEngineError(`Workflow ${run.workflowId} not found`, run.workflowId, runId);\n }\n const steps = workflow?.steps ?? [];\n\n let completionPercentage = 0;\n let completedSteps = 0;\n\n if (steps.length > 0) {\n completedSteps = Object.values(run.timeline).filter(\n (step): step is TimelineStepEntry =>\n typeof step === 'object' &&\n step !== null &&\n 'output' in step &&\n step.output !== undefined,\n ).length;\n\n if (run.status === WorkflowStatus.COMPLETED) {\n completionPercentage = 100;\n } else if (run.status === WorkflowStatus.FAILED || run.status === WorkflowStatus.CANCELLED) {\n completionPercentage = Math.min((completedSteps / steps.length) * 100, 100);\n } else {\n const currentStepIndex = steps.findIndex((step) => step.id === run.currentStepId);\n if (currentStepIndex >= 0) {\n completionPercentage = (currentStepIndex / steps.length) * 100;\n } else {\n const completedSteps = Object.keys(run.timeline).length;\n\n completionPercentage = Math.min((completedSteps / steps.length) * 100, 100);\n }\n }\n }\n\n return {\n ...run,\n completedSteps,\n completionPercentage: Math.round(completionPercentage * 100) / 100, // Round to 2 decimal places\n totalSteps: steps.length,\n };\n }\n\n /**\n * Resolves the resource id used for scoped DB access (getRun/updateRun).\n * When the job omits resourceId, the run's stored resourceId is used.\n * When the job includes resourceId, it must match the run's resourceId if the run is scoped;\n * unscoped runs reject a job-supplied resourceId (authorization).\n */\n private resolveScopedResourceId(\n jobResourceId: string | undefined,\n run: WorkflowRun,\n ): string | undefined {\n const jobResourceProvided =\n jobResourceId !== undefined && jobResourceId !== null && jobResourceId !== '';\n\n if (jobResourceProvided) {\n if (run.resourceId === null) {\n throw new WorkflowRunNotFoundError(run.id);\n }\n if (run.resourceId !== jobResourceId) {\n throw new WorkflowRunNotFoundError(run.id);\n }\n return jobResourceId;\n }\n\n return run.resourceId ?? undefined;\n }\n\n private async handleWorkflowRun([job]: Job<WorkflowRunJobParameters>[]) {\n const { runId = '', resourceId, workflowId = '', input, event } = job?.data ?? {};\n\n let run: WorkflowRun | undefined;\n let scopedResourceId: string | undefined;\n\n try {\n if (!runId) {\n throw new WorkflowEngineError('Invalid workflow run job, missing runId', workflowId);\n }\n\n if (!workflowId) {\n throw new WorkflowEngineError(\n 'Invalid workflow run job, missing workflowId',\n undefined,\n runId,\n );\n }\n\n const workflow = this.workflows.get(workflowId);\n if (!workflow) {\n throw new WorkflowEngineError(`Workflow ${workflowId} not found`, workflowId, runId);\n }\n\n this.logger.log('Processing workflow run...', {\n runId,\n workflowId,\n });\n\n run = await this.getRun({ runId });\n\n if (run.workflowId !== workflowId) {\n throw new WorkflowEngineError(\n `Workflow run ${runId} does not match job workflowId ${workflowId}`,\n workflowId,\n runId,\n );\n }\n\n scopedResourceId = this.resolveScopedResourceId(resourceId, run);\n\n if (run.status === WorkflowStatus.CANCELLED) {\n this.logger.log(`Workflow run ${runId} is cancelled, skipping`);\n return;\n }\n\n if (!run.currentStepId) {\n throw new WorkflowEngineError('Missing current step id', workflowId, runId);\n }\n\n if (run.status === WorkflowStatus.PAUSED) {\n run = await withPostgresTransaction(\n this.db,\n async (db) => {\n const lockedRun = await this.getRun(\n { runId, resourceId: scopedResourceId },\n { exclusiveLock: true, db },\n );\n if (lockedRun.status !== WorkflowStatus.PAUSED) {\n return lockedRun;\n }\n\n const waitForStep = this.getWaitForStepEntry(\n lockedRun.timeline,\n lockedRun.currentStepId,\n );\n const currentStep = this.getCachedStepEntry(\n lockedRun.timeline,\n lockedRun.currentStepId,\n );\n const waitFor = waitForStep?.waitFor;\n const hasCurrentStepOutput = currentStep?.output !== undefined;\n\n const eventMatches =\n waitFor &&\n event?.name &&\n (event.name === waitFor.eventName || event.name === waitFor.timeoutEvent) &&\n !hasCurrentStepOutput;\n\n if (eventMatches) {\n const isTimeout = event?.name === waitFor?.timeoutEvent;\n const skipOutput = waitFor?.skipOutput;\n return this.updateRun(\n {\n runId,\n resourceId: scopedResourceId,\n data: {\n status: WorkflowStatus.RUNNING,\n pausedAt: null,\n resumedAt: new Date(),\n jobId: job?.id,\n ...(skipOutput\n ? {}\n : {\n timeline: merge(lockedRun.timeline, {\n [lockedRun.currentStepId]: {\n output: event?.data ?? {},\n ...(isTimeout ? { timedOut: true as const } : {}),\n timestamp: new Date(),\n },\n }),\n }),\n },\n },\n { db },\n );\n }\n\n return this.updateRun(\n {\n runId,\n resourceId: scopedResourceId,\n data: {\n status: WorkflowStatus.RUNNING,\n pausedAt: null,\n resumedAt: new Date(),\n jobId: job?.id,\n },\n },\n { db },\n );\n },\n this.pool,\n );\n }\n\n const baseStep = {\n run: async <T>(stepId: string, handler: () => Promise<T>) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n return this.runStep({ stepId, run, handler }) as Promise<T>;\n },\n waitFor: async <T extends InputParameters>(\n stepId: string,\n { eventName, timeout }: { eventName: string; timeout?: number; schema?: T },\n ) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n const timeoutDate = timeout ? new Date(Date.now() + timeout) : undefined;\n return this.waitStep({ run, stepId, eventName, timeoutDate }) as Promise<\n InferInputParameters<T> | undefined\n >;\n },\n waitUntil: async (\n stepId: string,\n dateOrOptions: Date | string | { date: Date | string },\n ) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n const date =\n dateOrOptions instanceof Date\n ? dateOrOptions\n : typeof dateOrOptions === 'string'\n ? new Date(dateOrOptions)\n : dateOrOptions.date instanceof Date\n ? dateOrOptions.date\n : new Date(dateOrOptions.date);\n await this.waitStep({ run, stepId, timeoutDate: date });\n },\n pause: async (stepId: string) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n await this.waitStep({ run, stepId, eventName: PAUSE_EVENT_NAME });\n },\n delay: async (stepId: string, duration: Duration) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n await this.waitStep({\n run,\n stepId,\n timeoutDate: new Date(Date.now() + parseDuration(duration)),\n });\n },\n get sleep() {\n return this.delay;\n },\n poll: async <T>(\n stepId: string,\n conditionFn: () => Promise<T | false>,\n options?: { interval?: Duration; timeout?: Duration },\n ) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n const intervalMs = parseDuration(options?.interval ?? '30s');\n if (intervalMs < 30_000) {\n throw new WorkflowEngineError(\n `step.poll interval must be at least 30s (got ${intervalMs}ms)`,\n workflowId,\n runId,\n );\n }\n const timeoutMs = options?.timeout ? parseDuration(options.timeout) : undefined;\n return this.pollStep({ run, stepId, conditionFn, intervalMs, timeoutMs }) as Promise<\n { timedOut: false; data: T } | { timedOut: true }\n >;\n },\n };\n\n let step = { ...baseStep };\n const plugins = workflow.plugins ?? [];\n for (const plugin of plugins) {\n const extra = plugin.methods(step);\n step = { ...step, ...extra };\n }\n\n const context: WorkflowContext = {\n input: run.input as InferInputParameters<InputParameters>,\n workflowId: run.workflowId,\n runId: run.id,\n timeline: run.timeline,\n logger: this.logger,\n step,\n };\n\n const result = await workflow.handler(context);\n\n run = await this.getRun({ runId, resourceId: scopedResourceId });\n\n const isLastParsedStep = run.currentStepId === workflow.steps[workflow.steps.length - 1]?.id;\n const hasPluginSteps = (workflow.plugins?.length ?? 0) > 0;\n const noParsedSteps = workflow.steps.length === 0;\n const shouldComplete =\n run.status === WorkflowStatus.RUNNING &&\n (noParsedSteps || isLastParsedStep || (hasPluginSteps && result !== undefined));\n if (shouldComplete) {\n const normalizedResult = result === undefined ? {} : result;\n await this.updateRun({\n runId,\n resourceId: scopedResourceId,\n data: {\n status: WorkflowStatus.COMPLETED,\n output: normalizedResult,\n completedAt: new Date(),\n jobId: job?.id,\n },\n });\n\n this.logger.log('Workflow run completed.', {\n runId,\n workflowId,\n });\n }\n } catch (error) {\n if (run && run.retryCount < run.maxRetries) {\n await this.updateRun({\n runId,\n resourceId: scopedResourceId,\n data: {\n retryCount: run.retryCount + 1,\n jobId: job?.id,\n },\n });\n\n const retryDelay = 2 ** run.retryCount * 1000;\n\n // NOTE: Do not use pg-boss retryLimit and retryBackoff so that we can fully control the retry logic from the WorkflowEngine and not PGBoss.\n const pgBossJob: WorkflowRunJobParameters = {\n runId,\n resourceId: scopedResourceId,\n workflowId,\n input,\n };\n await this.boss?.send('workflow-run', pgBossJob, {\n startAfter: new Date(Date.now() + retryDelay),\n expireInSeconds: defaultExpireInSeconds,\n });\n\n return;\n }\n\n // TODO: Ensure that this code always runs, even if worker is stopped unexpectedly.\n if (runId) {\n await this.updateRun({\n runId,\n resourceId: scopedResourceId,\n data: {\n status: WorkflowStatus.FAILED,\n error: error instanceof Error ? error.message : String(error),\n jobId: job?.id,\n },\n });\n }\n\n throw error;\n }\n }\n\n private getCachedStepEntry(\n timeline: Record<string, unknown>,\n stepId: string,\n ): TimelineStepEntry | null {\n const stepEntry = timeline[stepId];\n return stepEntry && typeof stepEntry === 'object' && 'output' in stepEntry\n ? (stepEntry as TimelineStepEntry)\n : null;\n }\n\n private getWaitForStepEntry(\n timeline: Record<string, unknown>,\n stepId: string,\n ): TimelineWaitForEntry | null {\n const entry = timeline[`${stepId}-wait-for`];\n return entry && typeof entry === 'object' && 'waitFor' in entry\n ? (entry as TimelineWaitForEntry)\n : null;\n }\n\n private async runStep({\n stepId,\n run,\n handler,\n }: {\n stepId: string;\n run: WorkflowRun;\n handler: () => Promise<unknown>;\n }) {\n return withPostgresTransaction(\n this.db,\n async (db) => {\n const persistedRun = await this.getRun(\n { runId: run.id, resourceId: run.resourceId ?? undefined },\n {\n exclusiveLock: true,\n db,\n },\n );\n\n if (\n persistedRun.status === WorkflowStatus.CANCELLED ||\n persistedRun.status === WorkflowStatus.PAUSED ||\n persistedRun.status === WorkflowStatus.FAILED\n ) {\n this.logger.log(`Step ${stepId} skipped, workflow run is ${persistedRun.status}`, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n\n return;\n }\n\n try {\n const cached = this.getCachedStepEntry(persistedRun.timeline, stepId);\n if (cached?.output !== undefined) {\n return cached.output;\n }\n\n await this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n currentStepId: stepId,\n },\n },\n { db },\n );\n\n this.logger.log(`Running step ${stepId}...`, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n\n let output = await handler();\n\n if (output === undefined) {\n output = {};\n }\n\n run = await this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n timeline: merge(persistedRun.timeline, {\n [stepId]: {\n output,\n timestamp: new Date(),\n },\n }),\n },\n },\n { db },\n );\n\n return output;\n } catch (error) {\n this.logger.error(`Step ${stepId} failed:`, error as Error, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n\n await this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n status: WorkflowStatus.FAILED,\n error: error instanceof Error ? `${error.message}\\n${error.stack}` : String(error),\n },\n },\n { db },\n );\n\n throw error;\n }\n },\n this.pool,\n );\n }\n\n private async waitStep({\n run,\n stepId,\n eventName,\n timeoutDate,\n }: {\n run: WorkflowRun;\n stepId: string;\n eventName?: string;\n timeoutDate?: Date;\n }): Promise<unknown> {\n const persistedRun = await this.getRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n });\n\n if (\n persistedRun.status === WorkflowStatus.CANCELLED ||\n persistedRun.status === WorkflowStatus.PAUSED ||\n persistedRun.status === WorkflowStatus.FAILED\n ) {\n return;\n }\n\n const cached = this.getCachedStepEntry(persistedRun.timeline, stepId);\n if (cached?.output !== undefined) {\n return cached.timedOut ? undefined : cached.output;\n }\n\n const timeoutEvent = timeoutDate ? `__timeout_${stepId}` : undefined;\n\n await withPostgresTransaction(\n this.db,\n async (db) => {\n const freshRun = await this.getRun(\n { runId: run.id, resourceId: run.resourceId ?? undefined },\n { exclusiveLock: true, db },\n );\n return this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n status: WorkflowStatus.PAUSED,\n currentStepId: stepId,\n pausedAt: new Date(),\n timeline: merge(freshRun.timeline, {\n [`${stepId}-wait-for`]: {\n waitFor: { eventName, timeoutEvent },\n timestamp: new Date(),\n },\n }),\n },\n },\n { db },\n );\n },\n this.pool,\n );\n\n if (timeoutDate && timeoutEvent) {\n try {\n const job: WorkflowRunJobParameters = {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n workflowId: run.workflowId,\n input: run.input,\n event: { name: timeoutEvent, data: { date: timeoutDate.toISOString() } },\n };\n await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {\n startAfter: timeoutDate.getTime() <= Date.now() ? new Date() : timeoutDate,\n expireInSeconds: defaultExpireInSeconds,\n });\n } catch (error) {\n // Revert PAUSED status so the workflow can retry this step\n await this.updateRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: { status: WorkflowStatus.RUNNING, pausedAt: null },\n });\n throw error;\n }\n }\n\n this.logger.log(\n `Step ${stepId} waiting${eventName ? ` for event \"${eventName}\"` : ''}${timeoutDate ? ` until ${timeoutDate.toISOString()}` : ''}`,\n { runId: run.id, workflowId: run.workflowId },\n );\n }\n\n private async pollStep<T>({\n run,\n stepId,\n conditionFn,\n intervalMs,\n timeoutMs,\n }: {\n run: WorkflowRun;\n stepId: string;\n conditionFn: () => Promise<T | false>;\n intervalMs: number;\n timeoutMs?: number;\n }): Promise<{ timedOut: false; data: T } | { timedOut: true } | undefined> {\n const persistedRun = await this.getRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n });\n\n if (\n persistedRun.status === WorkflowStatus.CANCELLED ||\n persistedRun.status === WorkflowStatus.PAUSED ||\n persistedRun.status === WorkflowStatus.FAILED\n ) {\n return { timedOut: true };\n }\n\n const cached = this.getCachedStepEntry(persistedRun.timeline, stepId);\n if (cached?.output !== undefined) {\n return cached.timedOut ? { timedOut: true } : { timedOut: false, data: cached.output as T };\n }\n\n const pollStateEntry = persistedRun.timeline[`${stepId}-poll`];\n const startedAt =\n pollStateEntry && typeof pollStateEntry === 'object' && 'startedAt' in pollStateEntry\n ? new Date((pollStateEntry as { startedAt: string }).startedAt)\n : new Date();\n\n if (timeoutMs !== undefined && Date.now() >= startedAt.getTime() + timeoutMs) {\n await withPostgresTransaction(\n this.db,\n async (db) => {\n const freshRun = await this.getRun(\n { runId: run.id, resourceId: run.resourceId ?? undefined },\n { exclusiveLock: true, db },\n );\n return this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n currentStepId: stepId,\n timeline: merge(freshRun.timeline, {\n [stepId]: { output: {}, timedOut: true as const, timestamp: new Date() },\n }),\n },\n },\n { db },\n );\n },\n this.pool,\n );\n return { timedOut: true };\n }\n\n let result: T | false;\n try {\n result = await conditionFn();\n } catch (error) {\n this.logger.error(\n `Poll conditionFn for step ${stepId} threw an error, treating as non-match and continuing to poll`,\n error as Error,\n { runId: run.id, workflowId: run.workflowId },\n );\n\n // If the poll has timed out, respect the timeout even though conditionFn threw\n if (timeoutMs !== undefined && Date.now() >= startedAt.getTime() + timeoutMs) {\n await withPostgresTransaction(\n this.db,\n async (db) => {\n const freshRun = await this.getRun(\n { runId: run.id, resourceId: run.resourceId ?? undefined },\n { exclusiveLock: true, db },\n );\n return this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n currentStepId: stepId,\n timeline: merge(freshRun.timeline, {\n [stepId]: { output: {}, timedOut: true as const, timestamp: new Date() },\n }),\n },\n },\n { db },\n );\n },\n this.pool,\n );\n return { timedOut: true };\n }\n\n result = false;\n }\n\n if (result !== false) {\n await withPostgresTransaction(\n this.db,\n async (db) => {\n const freshRun = await this.getRun(\n { runId: run.id, resourceId: run.resourceId ?? undefined },\n { exclusiveLock: true, db },\n );\n return this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n currentStepId: stepId,\n timeline: merge(freshRun.timeline, {\n [stepId]: { output: result, timestamp: new Date() },\n }),\n },\n },\n { db },\n );\n },\n this.pool,\n );\n return { timedOut: false, data: result };\n }\n\n const pollEvent = `__poll_${stepId}`;\n await withPostgresTransaction(\n this.db,\n async (db) => {\n const freshRun = await this.getRun(\n { runId: run.id, resourceId: run.resourceId ?? undefined },\n { exclusiveLock: true, db },\n );\n return this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n status: WorkflowStatus.PAUSED,\n currentStepId: stepId,\n pausedAt: new Date(),\n timeline: merge(freshRun.timeline, {\n [`${stepId}-poll`]: { startedAt: startedAt.toISOString() },\n [`${stepId}-wait-for`]: {\n waitFor: { timeoutEvent: pollEvent, skipOutput: true },\n timestamp: new Date(),\n },\n }),\n },\n },\n { db },\n );\n },\n this.pool,\n );\n\n try {\n await this.boss.send(\n WORKFLOW_RUN_QUEUE_NAME,\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n workflowId: run.workflowId,\n input: run.input,\n event: { name: pollEvent, data: {} },\n },\n {\n startAfter: new Date(Date.now() + intervalMs),\n expireInSeconds: defaultExpireInSeconds,\n },\n );\n } catch (error) {\n // Revert PAUSED status so the workflow can retry this step\n await this.updateRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: { status: WorkflowStatus.RUNNING, pausedAt: null },\n });\n throw error;\n }\n\n this.logger.log(`Step ${stepId} polling every ${intervalMs}ms...`, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n\n return { timedOut: false, data: undefined as T };\n }\n\n private async checkIfHasStarted(): Promise<void> {\n if (!this._started) {\n throw new WorkflowEngineError('Workflow engine not started');\n }\n }\n\n private buildLogger(logger: WorkflowLogger): WorkflowInternalLogger {\n return {\n log: (message: string, context?: WorkflowInternalLoggerContext) => {\n const { runId, workflowId } = context ?? {};\n const parts = [LOG_PREFIX, workflowId, runId].filter(Boolean).join(' ');\n logger.log(`${parts}: ${message}`);\n },\n error: (message: string, error: Error, context?: WorkflowInternalLoggerContext) => {\n const { runId, workflowId } = context ?? {};\n const parts = [LOG_PREFIX, workflowId, runId].filter(Boolean).join(' ');\n logger.error(`${parts}: ${message}`, error);\n },\n };\n }\n\n async getRuns({\n resourceId,\n startingAfter,\n endingBefore,\n limit = 20,\n statuses,\n workflowId,\n }: {\n resourceId?: string;\n startingAfter?: string | null;\n endingBefore?: string | null;\n limit?: number;\n statuses?: WorkflowStatus[];\n workflowId?: string;\n }): Promise<{\n items: WorkflowRun[];\n nextCursor: string | null;\n prevCursor: string | null;\n hasMore: boolean;\n hasPrev: boolean;\n }> {\n return getWorkflowRuns(\n {\n resourceId,\n startingAfter,\n endingBefore,\n limit,\n statuses,\n workflowId,\n },\n this.db,\n );\n }\n}\n",
13
+ "import { merge } from 'es-toolkit';\nimport pg from 'pg';\nimport { type Db, type JobWithMetadata, PgBoss } from 'pg-boss';\nimport { parseWorkflowHandler } from './ast-parser';\nimport {\n DEFAULT_PGBOSS_SCHEMA,\n PAUSE_EVENT_NAME,\n WORKFLOW_RUN_DLQ_QUEUE_NAME,\n WORKFLOW_RUN_QUEUE_NAME,\n} from './constants';\nimport { runMigrations } from './db/migration';\nimport {\n getWorkflowRun,\n getWorkflowRuns,\n insertWorkflowRun,\n updateWorkflowRun,\n withPostgresTransaction,\n} from './db/queries';\nimport type { WorkflowRun } from './db/types';\nimport type { Duration } from './duration';\nimport { parseDuration } from './duration';\nimport {\n validateResourceId,\n validateWorkflowId,\n WorkflowEngineError,\n WorkflowRunNotFoundError,\n} from './error';\nimport {\n type InferInputParameters,\n type InputParameters,\n StepType,\n type WorkflowContext,\n type WorkflowDefinition,\n type WorkflowInternalDefinition,\n type WorkflowInternalLogger,\n type WorkflowInternalLoggerContext,\n type WorkflowLogger,\n type WorkflowRef,\n type WorkflowRunProgress,\n WorkflowStatus,\n} from './types';\n\nconst LOG_PREFIX = '[WorkflowEngine]';\n\ntype StartWorkflowOptions = {\n resourceId?: string;\n timeout?: number;\n retries?: number;\n expireInSeconds?: number;\n batchSize?: number;\n idempotencyKey?: string;\n};\n\nexport type WorkflowEngineOptions = {\n workflows?: WorkflowDefinition[];\n logger?: WorkflowLogger;\n boss?: PgBoss;\n} & ({ pool: pg.Pool; connectionString?: never } | { connectionString: string; pool?: never });\n\nconst StepTypeToIcon = {\n [StepType.RUN]: 'λ',\n [StepType.WAIT_FOR]: '○',\n [StepType.PAUSE]: '⏸',\n [StepType.WAIT_UNTIL]: '⏲',\n [StepType.DELAY]: '⏱',\n [StepType.POLL]: '↻',\n};\n\n// Timeline entry types\ntype TimelineStepEntry = {\n output?: unknown;\n timedOut?: true;\n timestamp: Date;\n};\n\ntype TimelineWaitForEntry = {\n waitFor: {\n eventName?: string;\n timeoutEvent?: string;\n skipOutput?: true;\n };\n timestamp: Date;\n};\n\ntype WorkflowRunJobParameters = {\n runId: string;\n resourceId?: string;\n workflowId: string;\n input: unknown;\n event?: {\n name: string;\n data?: Record<string, unknown>;\n };\n};\n\nconst defaultLogger: WorkflowLogger = {\n log: (_message: string) => console.warn(_message),\n error: (message: string, error: Error) => console.error(message, error),\n};\n\nconst defaultExpireInSeconds = process.env.WORKFLOW_RUN_EXPIRE_IN_SECONDS\n ? Number.parseInt(process.env.WORKFLOW_RUN_EXPIRE_IN_SECONDS, 10)\n : 5 * 60; // 5 minutes\n\n// retryDelay is the base for pg-boss's exponential backoff:\n// `retryDelay * 2^retryCount` seconds (with up to ±50% jitter), so a base\n// of 1 second yields ~1s, ~2s, ~4s, ~8s, … between attempts.\nconst retrySendOptions = (maxRetries: number) => ({\n retryLimit: maxRetries,\n retryBackoff: true,\n retryDelay: 1,\n});\n\n// pg-boss workers auto-touch heartbeat_on every heartbeatSeconds / 2 seconds\n// while the process is alive. If the worker dies, heartbeats stop and pg-boss's\n// monitor (~60s ticks) routes the job to the dead-letter queue. Minimum is 10.\nconst defaultHeartbeatSeconds = process.env.WORKFLOW_RUN_HEARTBEAT_SECONDS\n ? Number.parseInt(process.env.WORKFLOW_RUN_HEARTBEAT_SECONDS, 10)\n : 30;\n\nexport class WorkflowEngine {\n private boss: PgBoss;\n private db: Db;\n private pool: pg.Pool;\n private _ownsPool = false;\n private unregisteredWorkflows = new Map<string, WorkflowDefinition>();\n private _started = false;\n\n public workflows: Map<string, WorkflowInternalDefinition> = new Map<\n string,\n WorkflowInternalDefinition\n >();\n private logger: WorkflowInternalLogger;\n\n constructor({ workflows, logger, boss, ...connectionOptions }: WorkflowEngineOptions) {\n this.logger = this.buildLogger(logger ?? defaultLogger);\n\n if ('pool' in connectionOptions && connectionOptions.pool) {\n this.pool = connectionOptions.pool;\n } else if ('connectionString' in connectionOptions && connectionOptions.connectionString) {\n this.pool = new pg.Pool({ connectionString: connectionOptions.connectionString });\n this._ownsPool = true;\n } else {\n throw new WorkflowEngineError('Either pool or connectionString must be provided');\n }\n\n if (workflows) {\n this.unregisteredWorkflows = new Map(workflows.map((workflow) => [workflow.id, workflow]));\n }\n\n const db: Db = {\n executeSql: (text: string, values?: unknown[]) =>\n this.pool.query(text, values) as Promise<{ rows: unknown[] }>,\n };\n\n if (boss) {\n this.boss = boss;\n } else {\n this.boss = new PgBoss({ db, schema: DEFAULT_PGBOSS_SCHEMA });\n }\n this.db = this.boss.getDb();\n }\n\n async start(\n asEngine = true,\n {\n batchSize = 1,\n heartbeatSeconds = defaultHeartbeatSeconds,\n }: { batchSize?: number; heartbeatSeconds?: number } = {},\n ): Promise<void> {\n if (this._started) {\n return;\n }\n\n // Start boss first to get the database connection\n await this.boss.start();\n\n await runMigrations(this.boss.getDb());\n\n if (this.unregisteredWorkflows.size > 0) {\n for (const workflow of this.unregisteredWorkflows.values()) {\n await this.registerWorkflow(workflow);\n }\n }\n\n // pg-boss handles retries: every send sets retryLimit + retryBackoff\n // per-job from the workflow's `retries` option. Failures (thrown error,\n // expired job, missed heartbeats) re-enqueue automatically; once a job's\n // retries are exhausted, pg-boss routes it to the DLQ where\n // handleWorkflowRunDlq marks the run FAILED. heartbeatSeconds lets\n // pg-boss detect dead workers in ~heartbeatSeconds + monitorInterval\n // (≈60s) instead of waiting for the full expireInSeconds.\n const mainQueueOptions = {\n retryLimit: 0,\n deadLetter: WORKFLOW_RUN_DLQ_QUEUE_NAME,\n heartbeatSeconds,\n };\n await this.boss.createQueue(WORKFLOW_RUN_DLQ_QUEUE_NAME, { retryLimit: 0 });\n await this.boss.createQueue(WORKFLOW_RUN_QUEUE_NAME, mainQueueOptions);\n // createQueue is a no-op for existing queues; updateQueue ensures\n // installations that predate the DLQ adopt these settings on next start.\n await this.boss.updateQueue(WORKFLOW_RUN_QUEUE_NAME, mainQueueOptions);\n\n const numWorkers: number = +(process.env.WORKFLOW_RUN_WORKERS ?? 3);\n\n if (asEngine) {\n // includeMetadata exposes job.retryCount so we can mirror pg-boss's\n // attempt counter into workflow_runs.retryCount.\n await Promise.all(\n Array.from({ length: numWorkers }, (_, i) =>\n this.boss\n .work<WorkflowRunJobParameters>(\n WORKFLOW_RUN_QUEUE_NAME,\n { pollingIntervalSeconds: 0.5, batchSize, includeMetadata: true },\n (jobs) => this.handleWorkflowRun(jobs),\n )\n .then(() => {\n this.logger.log(\n `Worker ${i + 1}/${numWorkers} started for queue ${WORKFLOW_RUN_QUEUE_NAME}`,\n );\n }),\n ),\n );\n\n await this.boss.work<WorkflowRunJobParameters>(\n WORKFLOW_RUN_DLQ_QUEUE_NAME,\n { pollingIntervalSeconds: 0.5, batchSize: 1 },\n (jobs) => this.handleWorkflowRunDlq(jobs),\n );\n this.logger.log(`Worker started for queue ${WORKFLOW_RUN_DLQ_QUEUE_NAME}`);\n }\n\n this._started = true;\n\n this.logger.log('Workflow engine started!');\n }\n\n async stop(): Promise<void> {\n await this.boss.stop();\n\n if (this._ownsPool) {\n await this.pool.end();\n }\n\n this._started = false;\n\n this.logger.log('Workflow engine stopped');\n }\n\n async registerWorkflow(definition: WorkflowDefinition<InputParameters>): Promise<WorkflowEngine> {\n if (this.workflows.has(definition.id)) {\n throw new WorkflowEngineError(\n `Workflow ${definition.id} is already registered`,\n definition.id,\n );\n }\n\n const { steps } = parseWorkflowHandler(\n definition.handler as (context: WorkflowContext) => Promise<unknown>,\n );\n\n this.workflows.set(definition.id, {\n ...definition,\n steps,\n } as WorkflowInternalDefinition);\n\n this.logger.log(`Registered workflow \"${definition.id}\" with steps:`);\n for (const step of steps.values()) {\n const tags = [];\n if (step.conditional) tags.push('[conditional]');\n if (step.loop) tags.push('[loop]');\n if (step.isDynamic) tags.push('[dynamic]');\n this.logger.log(` └─ (${StepTypeToIcon[step.type]}) ${step.id} ${tags.join(' ')}`);\n }\n\n return this;\n }\n\n async unregisterWorkflow(workflowId: string): Promise<WorkflowEngine> {\n this.workflows.delete(workflowId);\n return this;\n }\n\n async unregisterAllWorkflows(): Promise<WorkflowEngine> {\n this.workflows.clear();\n return this;\n }\n\n async startWorkflow<TInput extends InputParameters>(\n ref: WorkflowRef<TInput>,\n input: InferInputParameters<TInput>,\n options?: StartWorkflowOptions,\n ): Promise<WorkflowRun>;\n\n async startWorkflow(params: {\n resourceId?: string;\n workflowId: string;\n input: unknown;\n idempotencyKey?: string;\n options?: StartWorkflowOptions;\n }): Promise<WorkflowRun>;\n\n async startWorkflow<TInput extends InputParameters>(\n refOrParams:\n | WorkflowRef<TInput>\n | {\n resourceId?: string;\n workflowId: string;\n input: unknown;\n idempotencyKey?: string;\n options?: StartWorkflowOptions;\n },\n inputArg?: InferInputParameters<TInput>,\n optionsArg?: StartWorkflowOptions,\n ): Promise<WorkflowRun> {\n let workflowId: string;\n let input: unknown;\n let resourceId: string | undefined;\n let idempotencyKey: string | undefined;\n let options: StartWorkflowOptions | undefined;\n\n if (typeof refOrParams === 'function' && 'id' in refOrParams) {\n workflowId = refOrParams.id;\n input = inputArg;\n options = optionsArg;\n resourceId = optionsArg?.resourceId;\n idempotencyKey = optionsArg?.idempotencyKey;\n } else {\n const params = refOrParams as {\n resourceId?: string;\n workflowId: string;\n input: unknown;\n idempotencyKey?: string;\n options?: StartWorkflowOptions;\n };\n workflowId = params.workflowId;\n input = params.input;\n resourceId = params.resourceId;\n idempotencyKey = params.idempotencyKey;\n options = params.options;\n }\n\n validateWorkflowId(workflowId);\n validateResourceId(resourceId);\n\n if (!this._started) {\n await this.start(false, { batchSize: options?.batchSize ?? 1 });\n }\n\n const workflow = this.workflows.get(workflowId);\n if (!workflow) {\n throw new WorkflowEngineError(`Unknown workflow ${workflowId}`);\n }\n\n const hasSteps = workflow.steps.length > 0 && workflow.steps[0];\n const hasPlugins = (workflow.plugins?.length ?? 0) > 0;\n if (!hasSteps && !hasPlugins) {\n throw new WorkflowEngineError(`Workflow ${workflowId} has no steps`, workflowId);\n }\n if (workflow.inputSchema) {\n const result = await workflow.inputSchema['~standard'].validate(input);\n if (result.issues) {\n throw new WorkflowEngineError(\n JSON.stringify(result.issues),\n workflowId,\n undefined,\n undefined,\n result.issues,\n );\n }\n }\n\n const initialStepId = workflow.steps[0]?.id ?? '__start__';\n\n const run = await withPostgresTransaction(\n this.boss.getDb(),\n async (_db) => {\n const timeoutAt = options?.timeout\n ? new Date(Date.now() + options.timeout)\n : workflow.timeout\n ? new Date(Date.now() + workflow.timeout)\n : null;\n\n const { run: insertedRun, created } = await insertWorkflowRun(\n {\n resourceId,\n workflowId,\n currentStepId: initialStepId,\n status: WorkflowStatus.RUNNING,\n input,\n maxRetries: options?.retries ?? workflow.retries ?? 0,\n timeoutAt,\n idempotencyKey,\n },\n _db,\n );\n\n if (created) {\n const job: WorkflowRunJobParameters = {\n runId: insertedRun.id,\n resourceId,\n workflowId,\n input,\n };\n\n await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {\n startAfter: new Date(),\n expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,\n ...retrySendOptions(insertedRun.maxRetries),\n });\n }\n\n return insertedRun;\n },\n this.pool,\n );\n\n this.logger.log('Started workflow run', {\n runId: run.id,\n workflowId,\n });\n\n return run;\n }\n\n async pauseWorkflow({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n // TODO: Pause all running steps immediately\n const run = await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.PAUSED,\n pausedAt: new Date(),\n },\n expectedStatuses: [WorkflowStatus.RUNNING, WorkflowStatus.PENDING],\n });\n\n this.logger.log('Paused workflow run', {\n runId,\n workflowId: run.workflowId,\n });\n\n return run;\n }\n\n async resumeWorkflow({\n runId,\n resourceId,\n options,\n }: {\n runId: string;\n resourceId?: string;\n options?: { expireInSeconds?: number };\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n const current = await this.getRun({ runId, resourceId });\n if (current.status !== WorkflowStatus.PAUSED) {\n throw new WorkflowEngineError(\n `Cannot resume workflow run in '${current.status}' status, must be 'paused'`,\n current.workflowId,\n runId,\n );\n }\n\n return this.triggerEvent({\n runId,\n resourceId,\n eventName: PAUSE_EVENT_NAME,\n data: {},\n options,\n });\n }\n\n async fastForwardWorkflow({\n runId,\n resourceId,\n data,\n }: {\n runId: string;\n resourceId?: string;\n data?: Record<string, unknown>;\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n const run = await this.getRun({ runId, resourceId });\n\n if (run.status !== WorkflowStatus.PAUSED) {\n return run;\n }\n\n const stepId = run.currentStepId;\n const waitForStep = this.getWaitForStepEntry(run.timeline, stepId);\n\n if (!waitForStep) {\n return run;\n }\n\n const { eventName, timeoutEvent, skipOutput } = waitForStep.waitFor;\n\n // step.pause() - delegate to resumeWorkflow\n if (eventName === PAUSE_EVENT_NAME) {\n return this.resumeWorkflow({ runId, resourceId });\n }\n\n // step.poll() - write output to timeline first, then trigger resume\n if (skipOutput && timeoutEvent) {\n await withPostgresTransaction(\n this.db,\n async (db) => {\n const freshRun = await this.getRun({ runId, resourceId }, { exclusiveLock: true, db });\n return this.updateRun(\n {\n runId,\n resourceId,\n data: {\n timeline: merge(freshRun.timeline, {\n [stepId]: {\n output: data ?? {},\n timestamp: new Date(),\n },\n }),\n },\n },\n { db },\n );\n },\n this.pool,\n );\n\n return this.triggerEvent({ runId, resourceId, eventName: timeoutEvent });\n }\n\n // waitFor steps - trigger the event with data\n if (eventName) {\n return this.triggerEvent({ runId, resourceId, eventName, data: data ?? {} });\n }\n\n // delay/waitUntil steps - trigger the timeout event\n if (timeoutEvent) {\n return this.triggerEvent({ runId, resourceId, eventName: timeoutEvent, data: data ?? {} });\n }\n\n return run;\n }\n\n async cancelWorkflow({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n const run = await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.CANCELLED,\n },\n expectedStatuses: [WorkflowStatus.PENDING, WorkflowStatus.RUNNING, WorkflowStatus.PAUSED],\n });\n\n this.logger.log(`cancelled workflow run with id ${runId}`);\n\n return run;\n }\n\n async triggerEvent({\n runId,\n resourceId,\n eventName,\n data,\n options,\n }: {\n runId: string;\n resourceId?: string;\n eventName: string;\n data?: Record<string, unknown>;\n options?: {\n expireInSeconds?: number;\n };\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n const run = await this.getRun({ runId, resourceId });\n\n const jobResourceId = resourceId ?? run.resourceId ?? undefined;\n\n const job: WorkflowRunJobParameters = {\n runId: run.id,\n resourceId: jobResourceId,\n workflowId: run.workflowId,\n input: run.input,\n event: {\n name: eventName,\n data,\n },\n };\n\n await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {\n expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,\n ...retrySendOptions(run.maxRetries),\n });\n\n this.logger.log(`event ${eventName} sent for workflow run with id ${runId}`);\n return run;\n }\n\n async getRun(\n { runId, resourceId }: { runId: string; resourceId?: string },\n { exclusiveLock = false, db }: { exclusiveLock?: boolean; db?: Db } = {},\n ): Promise<WorkflowRun> {\n const run = await getWorkflowRun({ runId, resourceId }, { exclusiveLock, db: db ?? this.db });\n\n if (!run) {\n throw new WorkflowRunNotFoundError(runId);\n }\n\n return run;\n }\n\n async updateRun(\n {\n runId,\n resourceId,\n data,\n expectedStatuses,\n }: {\n runId: string;\n resourceId?: string;\n data: Partial<WorkflowRun>;\n expectedStatuses?: string[];\n },\n { db }: { db?: Db } = {},\n ): Promise<WorkflowRun> {\n const run = await updateWorkflowRun(\n { runId, resourceId, data, expectedStatuses },\n db ?? this.db,\n );\n\n if (!run) {\n if (expectedStatuses) {\n const current = await getWorkflowRun({ runId, resourceId }, { db: db ?? this.db });\n if (current) {\n throw new WorkflowEngineError(\n `Cannot update workflow run in '${current.status}' status, expected: ${expectedStatuses.join(', ')}`,\n current.workflowId,\n runId,\n );\n }\n }\n throw new WorkflowRunNotFoundError(runId);\n }\n\n return run;\n }\n\n async checkProgress({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRunProgress> {\n const run = await this.getRun({ runId, resourceId });\n const workflow = this.workflows.get(run.workflowId);\n\n if (!workflow) {\n throw new WorkflowEngineError(`Workflow ${run.workflowId} not found`, run.workflowId, runId);\n }\n const steps = workflow?.steps ?? [];\n\n let completionPercentage = 0;\n let completedSteps = 0;\n\n if (steps.length > 0) {\n completedSteps = Object.values(run.timeline).filter(\n (step): step is TimelineStepEntry =>\n typeof step === 'object' &&\n step !== null &&\n 'output' in step &&\n step.output !== undefined,\n ).length;\n\n if (run.status === WorkflowStatus.COMPLETED) {\n completionPercentage = 100;\n } else if (run.status === WorkflowStatus.FAILED || run.status === WorkflowStatus.CANCELLED) {\n completionPercentage = Math.min((completedSteps / steps.length) * 100, 100);\n } else {\n const currentStepIndex = steps.findIndex((step) => step.id === run.currentStepId);\n if (currentStepIndex >= 0) {\n completionPercentage = (currentStepIndex / steps.length) * 100;\n } else {\n const completedSteps = Object.keys(run.timeline).length;\n\n completionPercentage = Math.min((completedSteps / steps.length) * 100, 100);\n }\n }\n }\n\n return {\n ...run,\n completedSteps,\n completionPercentage: Math.round(completionPercentage * 100) / 100, // Round to 2 decimal places\n totalSteps: steps.length,\n };\n }\n\n /**\n * Resolves the resource id used for scoped DB access (getRun/updateRun).\n * When the job omits resourceId, the run's stored resourceId is used.\n * When the job includes resourceId, it must match the run's resourceId if the run is scoped;\n * unscoped runs reject a job-supplied resourceId (authorization).\n */\n private resolveScopedResourceId(\n jobResourceId: string | undefined,\n run: WorkflowRun,\n ): string | undefined {\n const jobResourceProvided =\n jobResourceId !== undefined && jobResourceId !== null && jobResourceId !== '';\n\n if (jobResourceProvided) {\n if (run.resourceId === null) {\n throw new WorkflowRunNotFoundError(run.id);\n }\n if (run.resourceId !== jobResourceId) {\n throw new WorkflowRunNotFoundError(run.id);\n }\n return jobResourceId;\n }\n\n return run.resourceId ?? undefined;\n }\n\n private async handleWorkflowRun([job]: JobWithMetadata<WorkflowRunJobParameters>[]) {\n const { runId = '', resourceId, workflowId = '', event } = job?.data ?? {};\n\n let run: WorkflowRun | undefined;\n let scopedResourceId: string | undefined;\n\n try {\n if (!runId) {\n throw new WorkflowEngineError('Invalid workflow run job, missing runId', workflowId);\n }\n\n if (!workflowId) {\n throw new WorkflowEngineError(\n 'Invalid workflow run job, missing workflowId',\n undefined,\n runId,\n );\n }\n\n const workflow = this.workflows.get(workflowId);\n if (!workflow) {\n throw new WorkflowEngineError(`Workflow ${workflowId} not found`, workflowId, runId);\n }\n\n this.logger.log('Processing workflow run...', {\n runId,\n workflowId,\n });\n\n run = await this.getRun({ runId });\n\n if (run.workflowId !== workflowId) {\n throw new WorkflowEngineError(\n `Workflow run ${runId} does not match job workflowId ${workflowId}`,\n workflowId,\n runId,\n );\n }\n\n scopedResourceId = this.resolveScopedResourceId(resourceId, run);\n\n // Mirror pg-boss's attempt counter so workflow_runs.retryCount stays\n // observable to API consumers across retries.\n if (job?.retryCount !== undefined && run.retryCount !== job.retryCount) {\n await this.updateRun({\n runId,\n resourceId: scopedResourceId,\n data: { retryCount: job.retryCount },\n });\n run = { ...run, retryCount: job.retryCount };\n }\n\n if (run.status === WorkflowStatus.CANCELLED) {\n this.logger.log(`Workflow run ${runId} is cancelled, skipping`);\n return;\n }\n\n if (!run.currentStepId) {\n throw new WorkflowEngineError('Missing current step id', workflowId, runId);\n }\n\n if (run.status === WorkflowStatus.PAUSED) {\n run = await withPostgresTransaction(\n this.db,\n async (db) => {\n const lockedRun = await this.getRun(\n { runId, resourceId: scopedResourceId },\n { exclusiveLock: true, db },\n );\n if (lockedRun.status !== WorkflowStatus.PAUSED) {\n return lockedRun;\n }\n\n const waitForStep = this.getWaitForStepEntry(\n lockedRun.timeline,\n lockedRun.currentStepId,\n );\n const currentStep = this.getCachedStepEntry(\n lockedRun.timeline,\n lockedRun.currentStepId,\n );\n const waitFor = waitForStep?.waitFor;\n const hasCurrentStepOutput = currentStep?.output !== undefined;\n\n const eventMatches =\n waitFor &&\n event?.name &&\n (event.name === waitFor.eventName || event.name === waitFor.timeoutEvent) &&\n !hasCurrentStepOutput;\n\n if (eventMatches) {\n const isTimeout = event?.name === waitFor?.timeoutEvent;\n const skipOutput = waitFor?.skipOutput;\n return this.updateRun(\n {\n runId,\n resourceId: scopedResourceId,\n data: {\n status: WorkflowStatus.RUNNING,\n pausedAt: null,\n resumedAt: new Date(),\n jobId: job?.id,\n ...(skipOutput\n ? {}\n : {\n timeline: merge(lockedRun.timeline, {\n [lockedRun.currentStepId]: {\n output: event?.data ?? {},\n ...(isTimeout ? { timedOut: true as const } : {}),\n timestamp: new Date(),\n },\n }),\n }),\n },\n },\n { db },\n );\n }\n\n return this.updateRun(\n {\n runId,\n resourceId: scopedResourceId,\n data: {\n status: WorkflowStatus.RUNNING,\n pausedAt: null,\n resumedAt: new Date(),\n jobId: job?.id,\n },\n },\n { db },\n );\n },\n this.pool,\n );\n }\n\n const baseStep = {\n run: async <T>(stepId: string, handler: () => Promise<T>) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n return this.runStep({ stepId, run, handler }) as Promise<T>;\n },\n waitFor: async <T extends InputParameters>(\n stepId: string,\n { eventName, timeout }: { eventName: string; timeout?: number; schema?: T },\n ) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n const timeoutDate = timeout ? new Date(Date.now() + timeout) : undefined;\n return this.waitStep({ run, stepId, eventName, timeoutDate }) as Promise<\n InferInputParameters<T> | undefined\n >;\n },\n waitUntil: async (\n stepId: string,\n dateOrOptions: Date | string | { date: Date | string },\n ) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n const date =\n dateOrOptions instanceof Date\n ? dateOrOptions\n : typeof dateOrOptions === 'string'\n ? new Date(dateOrOptions)\n : dateOrOptions.date instanceof Date\n ? dateOrOptions.date\n : new Date(dateOrOptions.date);\n await this.waitStep({ run, stepId, timeoutDate: date });\n },\n pause: async (stepId: string) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n await this.waitStep({ run, stepId, eventName: PAUSE_EVENT_NAME });\n },\n delay: async (stepId: string, duration: Duration) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n await this.waitStep({\n run,\n stepId,\n timeoutDate: new Date(Date.now() + parseDuration(duration)),\n });\n },\n get sleep() {\n return this.delay;\n },\n poll: async <T>(\n stepId: string,\n conditionFn: () => Promise<T | false>,\n options?: { interval?: Duration; timeout?: Duration },\n ) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n const intervalMs = parseDuration(options?.interval ?? '30s');\n if (intervalMs < 30_000) {\n throw new WorkflowEngineError(\n `step.poll interval must be at least 30s (got ${intervalMs}ms)`,\n workflowId,\n runId,\n );\n }\n const timeoutMs = options?.timeout ? parseDuration(options.timeout) : undefined;\n return this.pollStep({ run, stepId, conditionFn, intervalMs, timeoutMs }) as Promise<\n { timedOut: false; data: T } | { timedOut: true }\n >;\n },\n };\n\n let step = { ...baseStep };\n const plugins = workflow.plugins ?? [];\n for (const plugin of plugins) {\n const extra = plugin.methods(step);\n step = { ...step, ...extra };\n }\n\n const context: WorkflowContext = {\n input: run.input as InferInputParameters<InputParameters>,\n workflowId: run.workflowId,\n runId: run.id,\n timeline: run.timeline,\n logger: this.logger,\n step,\n };\n\n const result = await workflow.handler(context);\n\n run = await this.getRun({ runId, resourceId: scopedResourceId });\n\n const isLastParsedStep = run.currentStepId === workflow.steps[workflow.steps.length - 1]?.id;\n const hasPluginSteps = (workflow.plugins?.length ?? 0) > 0;\n const noParsedSteps = workflow.steps.length === 0;\n const shouldComplete =\n run.status === WorkflowStatus.RUNNING &&\n (noParsedSteps || isLastParsedStep || (hasPluginSteps && result !== undefined));\n if (shouldComplete) {\n const normalizedResult = result === undefined ? {} : result;\n await this.updateRun({\n runId,\n resourceId: scopedResourceId,\n data: {\n status: WorkflowStatus.COMPLETED,\n output: normalizedResult,\n completedAt: new Date(),\n jobId: job?.id,\n },\n });\n\n this.logger.log('Workflow run completed.', {\n runId,\n workflowId,\n });\n }\n } catch (error) {\n // Persist the error so the DLQ handler can surface it after retries\n // are exhausted. pg-boss handles the retry-vs-DLQ decision based on\n // the per-job retryLimit set when the job was enqueued.\n if (runId) {\n await this.updateRun({\n runId,\n resourceId: scopedResourceId,\n data: {\n error: error instanceof Error ? error.message : String(error),\n jobId: job?.id,\n },\n });\n }\n\n throw error;\n }\n }\n\n /**\n * Reconciles workflow runs whose retries pg-boss has exhausted (handler\n * threw on the final attempt, or worker died and missed the heartbeat\n * past the retry budget). The DLQ entry tells us the run is unrecoverable;\n * we mark it FAILED with whatever error message the catch block last\n * persisted, falling back to a worker-death message.\n */\n private async handleWorkflowRunDlq([job]: { data?: WorkflowRunJobParameters }[]) {\n const { runId } = job?.data ?? {};\n if (!runId) return;\n\n const run = await getWorkflowRun({ runId }, { db: this.db });\n if (!run || run.status !== WorkflowStatus.RUNNING) return;\n\n await this.updateRun({\n runId,\n resourceId: run.resourceId ?? undefined,\n data: {\n status: WorkflowStatus.FAILED,\n error: run.error ?? 'Workflow run worker died or job expired before completion',\n },\n });\n\n this.logger.log('Marked stuck workflow run as failed', {\n runId,\n workflowId: run.workflowId,\n });\n }\n\n private getCachedStepEntry(\n timeline: Record<string, unknown>,\n stepId: string,\n ): TimelineStepEntry | null {\n const stepEntry = timeline[stepId];\n return stepEntry && typeof stepEntry === 'object' && 'output' in stepEntry\n ? (stepEntry as TimelineStepEntry)\n : null;\n }\n\n private getWaitForStepEntry(\n timeline: Record<string, unknown>,\n stepId: string,\n ): TimelineWaitForEntry | null {\n const entry = timeline[`${stepId}-wait-for`];\n return entry && typeof entry === 'object' && 'waitFor' in entry\n ? (entry as TimelineWaitForEntry)\n : null;\n }\n\n private async runStep({\n stepId,\n run,\n handler,\n }: {\n stepId: string;\n run: WorkflowRun;\n handler: () => Promise<unknown>;\n }) {\n return withPostgresTransaction(\n this.db,\n async (db) => {\n const persistedRun = await this.getRun(\n { runId: run.id, resourceId: run.resourceId ?? undefined },\n {\n exclusiveLock: true,\n db,\n },\n );\n\n if (\n persistedRun.status === WorkflowStatus.CANCELLED ||\n persistedRun.status === WorkflowStatus.PAUSED ||\n persistedRun.status === WorkflowStatus.FAILED\n ) {\n this.logger.log(`Step ${stepId} skipped, workflow run is ${persistedRun.status}`, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n\n return;\n }\n\n try {\n const cached = this.getCachedStepEntry(persistedRun.timeline, stepId);\n if (cached?.output !== undefined) {\n return cached.output;\n }\n\n await this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n currentStepId: stepId,\n },\n },\n { db },\n );\n\n this.logger.log(`Running step ${stepId}...`, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n\n let output = await handler();\n\n if (output === undefined) {\n output = {};\n }\n\n run = await this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n timeline: merge(persistedRun.timeline, {\n [stepId]: {\n output,\n timestamp: new Date(),\n },\n }),\n },\n },\n { db },\n );\n\n return output;\n } catch (error) {\n this.logger.error(`Step ${stepId} failed:`, error as Error, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n\n await this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n status: WorkflowStatus.FAILED,\n error: error instanceof Error ? `${error.message}\\n${error.stack}` : String(error),\n },\n },\n { db },\n );\n\n throw error;\n }\n },\n this.pool,\n );\n }\n\n private async waitStep({\n run,\n stepId,\n eventName,\n timeoutDate,\n }: {\n run: WorkflowRun;\n stepId: string;\n eventName?: string;\n timeoutDate?: Date;\n }): Promise<unknown> {\n const persistedRun = await this.getRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n });\n\n if (\n persistedRun.status === WorkflowStatus.CANCELLED ||\n persistedRun.status === WorkflowStatus.PAUSED ||\n persistedRun.status === WorkflowStatus.FAILED\n ) {\n return;\n }\n\n const cached = this.getCachedStepEntry(persistedRun.timeline, stepId);\n if (cached?.output !== undefined) {\n return cached.timedOut ? undefined : cached.output;\n }\n\n const timeoutEvent = timeoutDate ? `__timeout_${stepId}` : undefined;\n\n await withPostgresTransaction(\n this.db,\n async (db) => {\n const freshRun = await this.getRun(\n { runId: run.id, resourceId: run.resourceId ?? undefined },\n { exclusiveLock: true, db },\n );\n return this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n status: WorkflowStatus.PAUSED,\n currentStepId: stepId,\n pausedAt: new Date(),\n timeline: merge(freshRun.timeline, {\n [`${stepId}-wait-for`]: {\n waitFor: { eventName, timeoutEvent },\n timestamp: new Date(),\n },\n }),\n },\n },\n { db },\n );\n },\n this.pool,\n );\n\n if (timeoutDate && timeoutEvent) {\n try {\n const job: WorkflowRunJobParameters = {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n workflowId: run.workflowId,\n input: run.input,\n event: { name: timeoutEvent, data: { date: timeoutDate.toISOString() } },\n };\n await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {\n startAfter: timeoutDate.getTime() <= Date.now() ? new Date() : timeoutDate,\n expireInSeconds: defaultExpireInSeconds,\n ...retrySendOptions(run.maxRetries),\n });\n } catch (error) {\n // Revert PAUSED status so the workflow can retry this step\n await this.updateRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: { status: WorkflowStatus.RUNNING, pausedAt: null },\n });\n throw error;\n }\n }\n\n this.logger.log(\n `Step ${stepId} waiting${eventName ? ` for event \"${eventName}\"` : ''}${timeoutDate ? ` until ${timeoutDate.toISOString()}` : ''}`,\n { runId: run.id, workflowId: run.workflowId },\n );\n }\n\n private async pollStep<T>({\n run,\n stepId,\n conditionFn,\n intervalMs,\n timeoutMs,\n }: {\n run: WorkflowRun;\n stepId: string;\n conditionFn: () => Promise<T | false>;\n intervalMs: number;\n timeoutMs?: number;\n }): Promise<{ timedOut: false; data: T } | { timedOut: true } | undefined> {\n const persistedRun = await this.getRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n });\n\n if (\n persistedRun.status === WorkflowStatus.CANCELLED ||\n persistedRun.status === WorkflowStatus.PAUSED ||\n persistedRun.status === WorkflowStatus.FAILED\n ) {\n return { timedOut: true };\n }\n\n const cached = this.getCachedStepEntry(persistedRun.timeline, stepId);\n if (cached?.output !== undefined) {\n return cached.timedOut ? { timedOut: true } : { timedOut: false, data: cached.output as T };\n }\n\n const pollStateEntry = persistedRun.timeline[`${stepId}-poll`];\n const startedAt =\n pollStateEntry && typeof pollStateEntry === 'object' && 'startedAt' in pollStateEntry\n ? new Date((pollStateEntry as { startedAt: string }).startedAt)\n : new Date();\n\n if (timeoutMs !== undefined && Date.now() >= startedAt.getTime() + timeoutMs) {\n await withPostgresTransaction(\n this.db,\n async (db) => {\n const freshRun = await this.getRun(\n { runId: run.id, resourceId: run.resourceId ?? undefined },\n { exclusiveLock: true, db },\n );\n return this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n currentStepId: stepId,\n timeline: merge(freshRun.timeline, {\n [stepId]: { output: {}, timedOut: true as const, timestamp: new Date() },\n }),\n },\n },\n { db },\n );\n },\n this.pool,\n );\n return { timedOut: true };\n }\n\n let result: T | false;\n try {\n result = await conditionFn();\n } catch (error) {\n this.logger.error(\n `Poll conditionFn for step ${stepId} threw an error, treating as non-match and continuing to poll`,\n error as Error,\n { runId: run.id, workflowId: run.workflowId },\n );\n\n // If the poll has timed out, respect the timeout even though conditionFn threw\n if (timeoutMs !== undefined && Date.now() >= startedAt.getTime() + timeoutMs) {\n await withPostgresTransaction(\n this.db,\n async (db) => {\n const freshRun = await this.getRun(\n { runId: run.id, resourceId: run.resourceId ?? undefined },\n { exclusiveLock: true, db },\n );\n return this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n currentStepId: stepId,\n timeline: merge(freshRun.timeline, {\n [stepId]: { output: {}, timedOut: true as const, timestamp: new Date() },\n }),\n },\n },\n { db },\n );\n },\n this.pool,\n );\n return { timedOut: true };\n }\n\n result = false;\n }\n\n if (result !== false) {\n await withPostgresTransaction(\n this.db,\n async (db) => {\n const freshRun = await this.getRun(\n { runId: run.id, resourceId: run.resourceId ?? undefined },\n { exclusiveLock: true, db },\n );\n return this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n currentStepId: stepId,\n timeline: merge(freshRun.timeline, {\n [stepId]: { output: result, timestamp: new Date() },\n }),\n },\n },\n { db },\n );\n },\n this.pool,\n );\n return { timedOut: false, data: result };\n }\n\n const pollEvent = `__poll_${stepId}`;\n await withPostgresTransaction(\n this.db,\n async (db) => {\n const freshRun = await this.getRun(\n { runId: run.id, resourceId: run.resourceId ?? undefined },\n { exclusiveLock: true, db },\n );\n return this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n status: WorkflowStatus.PAUSED,\n currentStepId: stepId,\n pausedAt: new Date(),\n timeline: merge(freshRun.timeline, {\n [`${stepId}-poll`]: { startedAt: startedAt.toISOString() },\n [`${stepId}-wait-for`]: {\n waitFor: { timeoutEvent: pollEvent, skipOutput: true },\n timestamp: new Date(),\n },\n }),\n },\n },\n { db },\n );\n },\n this.pool,\n );\n\n try {\n await this.boss.send(\n WORKFLOW_RUN_QUEUE_NAME,\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n workflowId: run.workflowId,\n input: run.input,\n event: { name: pollEvent, data: {} },\n },\n {\n startAfter: new Date(Date.now() + intervalMs),\n expireInSeconds: defaultExpireInSeconds,\n ...retrySendOptions(run.maxRetries),\n },\n );\n } catch (error) {\n // Revert PAUSED status so the workflow can retry this step\n await this.updateRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: { status: WorkflowStatus.RUNNING, pausedAt: null },\n });\n throw error;\n }\n\n this.logger.log(`Step ${stepId} polling every ${intervalMs}ms...`, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n\n return { timedOut: false, data: undefined as T };\n }\n\n private async checkIfHasStarted(): Promise<void> {\n if (!this._started) {\n throw new WorkflowEngineError('Workflow engine not started');\n }\n }\n\n private buildLogger(logger: WorkflowLogger): WorkflowInternalLogger {\n return {\n log: (message: string, context?: WorkflowInternalLoggerContext) => {\n const { runId, workflowId } = context ?? {};\n const parts = [LOG_PREFIX, workflowId, runId].filter(Boolean).join(' ');\n logger.log(`${parts}: ${message}`);\n },\n error: (message: string, error: Error, context?: WorkflowInternalLoggerContext) => {\n const { runId, workflowId } = context ?? {};\n const parts = [LOG_PREFIX, workflowId, runId].filter(Boolean).join(' ');\n logger.error(`${parts}: ${message}`, error);\n },\n };\n }\n\n async getRuns({\n resourceId,\n startingAfter,\n endingBefore,\n limit = 20,\n statuses,\n workflowId,\n }: {\n resourceId?: string;\n startingAfter?: string | null;\n endingBefore?: string | null;\n limit?: number;\n statuses?: WorkflowStatus[];\n workflowId?: string;\n }): Promise<{\n items: WorkflowRun[];\n nextCursor: string | null;\n prevCursor: string | null;\n hasMore: boolean;\n hasPrev: boolean;\n }> {\n if (workflowId) validateWorkflowId(workflowId);\n validateResourceId(resourceId);\n\n return getWorkflowRuns(\n {\n resourceId,\n startingAfter,\n endingBefore,\n limit,\n statuses,\n workflowId,\n },\n this.db,\n );\n }\n}\n",
14
14
  "import * as ts from 'typescript';\nimport type { StepInternalDefinition, WorkflowContext } from './types';\nimport { StepType } from './types';\n\ntype ParseWorkflowHandlerReturnType = {\n steps: StepInternalDefinition[];\n};\n\nexport function parseWorkflowHandler(\n handler: (context: WorkflowContext) => Promise<unknown>,\n): ParseWorkflowHandlerReturnType {\n const handlerSource = handler.toString();\n const sourceFile = ts.createSourceFile('handler.ts', handlerSource, ts.ScriptTarget.Latest, true);\n\n const steps: Map<string, StepInternalDefinition> = new Map();\n\n function isInConditional(node: ts.Node): boolean {\n let current = node.parent;\n while (current) {\n if (\n ts.isIfStatement(current) ||\n ts.isConditionalExpression(current) ||\n ts.isSwitchStatement(current) ||\n ts.isCaseClause(current)\n ) {\n return true;\n }\n current = current.parent;\n }\n return false;\n }\n\n function isInLoop(node: ts.Node): boolean {\n let current = node.parent;\n while (current) {\n if (\n ts.isForStatement(current) ||\n ts.isForInStatement(current) ||\n ts.isForOfStatement(current) ||\n ts.isWhileStatement(current) ||\n ts.isDoStatement(current)\n ) {\n return true;\n }\n current = current.parent;\n }\n return false;\n }\n\n function extractStepId(arg: ts.Expression): {\n id: string;\n isDynamic: boolean;\n } {\n if (ts.isStringLiteral(arg) || ts.isNoSubstitutionTemplateLiteral(arg)) {\n return { id: arg.text, isDynamic: false };\n }\n\n if (ts.isTemplateExpression(arg)) {\n let templateStr = arg.head.text;\n for (const span of arg.templateSpans) {\n templateStr += `\\${...}`;\n templateStr += span.literal.text;\n }\n return { id: templateStr, isDynamic: true };\n }\n\n return { id: arg.getText(sourceFile), isDynamic: true };\n }\n\n function visit(node: ts.Node) {\n if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression)) {\n const propertyAccess = node.expression;\n const objectName = propertyAccess.expression.getText(sourceFile);\n const methodName = propertyAccess.name.text;\n\n if (\n objectName === 'step' &&\n (methodName === 'run' ||\n methodName === 'waitFor' ||\n methodName === 'pause' ||\n methodName === 'waitUntil' ||\n methodName === 'delay' ||\n methodName === 'sleep' ||\n methodName === 'poll')\n ) {\n const firstArg = node.arguments[0];\n if (firstArg) {\n const { id, isDynamic } = extractStepId(firstArg);\n const stepType = methodName === 'sleep' ? StepType.DELAY : (methodName as StepType);\n\n const stepDefinition: StepInternalDefinition = {\n id,\n type: stepType,\n conditional: isInConditional(node),\n loop: isInLoop(node),\n isDynamic,\n };\n\n if (steps.has(id)) {\n throw new Error(\n `Duplicate step ID detected: '${id}'. Step IDs must be unique within a workflow.`,\n );\n }\n\n steps.set(id, stepDefinition);\n }\n }\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n\n return { steps: Array.from(steps.values()) };\n}\n"
15
15
  ],
16
- "mappings": "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",
17
- "debugId": "E199D83236562DFF64756E2164756E21",
16
+ "mappings": "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",
17
+ "debugId": "CBDC1CAB86CECE9C64756E2164756E21",
18
18
  "names": []
19
19
  }