pg-workflows 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -757,9 +757,10 @@ class WorkflowEngine {
757
757
  }) {
758
758
  await this.checkIfHasStarted();
759
759
  const run = await this.getRun({ runId, resourceId });
760
+ const jobResourceId = resourceId ?? run.resourceId ?? undefined;
760
761
  const job = {
761
762
  runId: run.id,
762
- resourceId,
763
+ resourceId: jobResourceId,
763
764
  workflowId: run.workflowId,
764
765
  input: run.input,
765
766
  event: {
@@ -826,14 +827,24 @@ class WorkflowEngine {
826
827
  totalSteps: steps.length
827
828
  };
828
829
  }
830
+ resolveScopedResourceId(jobResourceId, run) {
831
+ const jobResourceProvided = jobResourceId !== undefined && jobResourceId !== null && jobResourceId !== "";
832
+ if (jobResourceProvided) {
833
+ if (run.resourceId === null) {
834
+ throw new WorkflowRunNotFoundError(run.id);
835
+ }
836
+ if (run.resourceId !== jobResourceId) {
837
+ throw new WorkflowRunNotFoundError(run.id);
838
+ }
839
+ return jobResourceId;
840
+ }
841
+ return run.resourceId ?? undefined;
842
+ }
829
843
  async handleWorkflowRun([job]) {
830
844
  const { runId, resourceId, workflowId, input, event } = job?.data ?? {};
831
845
  if (!runId) {
832
846
  throw new WorkflowEngineError("Invalid workflow run job, missing runId", workflowId);
833
847
  }
834
- if (!resourceId) {
835
- throw new WorkflowEngineError("Invalid workflow run job, missing resourceId", workflowId);
836
- }
837
848
  if (!workflowId) {
838
849
  throw new WorkflowEngineError("Invalid workflow run job, missing workflowId", undefined, runId);
839
850
  }
@@ -845,7 +856,11 @@ class WorkflowEngine {
845
856
  runId,
846
857
  workflowId
847
858
  });
848
- let run = await this.getRun({ runId, resourceId });
859
+ let run = await this.getRun({ runId });
860
+ if (run.workflowId !== workflowId) {
861
+ throw new WorkflowEngineError(`Workflow run ${runId} does not match job workflowId ${workflowId}`, workflowId, runId);
862
+ }
863
+ const scopedResourceId = this.resolveScopedResourceId(resourceId, run);
849
864
  try {
850
865
  if (run.status === "cancelled" /* CANCELLED */) {
851
866
  this.logger.log(`Workflow run ${runId} is cancelled, skipping`);
@@ -866,7 +881,7 @@ class WorkflowEngine {
866
881
  const skipOutput = waitFor?.skipOutput;
867
882
  run = await this.updateRun({
868
883
  runId,
869
- resourceId,
884
+ resourceId: scopedResourceId,
870
885
  data: {
871
886
  status: "running" /* RUNNING */,
872
887
  pausedAt: null,
@@ -886,7 +901,7 @@ class WorkflowEngine {
886
901
  } else {
887
902
  run = await this.updateRun({
888
903
  runId,
889
- resourceId,
904
+ resourceId: scopedResourceId,
890
905
  data: {
891
906
  status: "running" /* RUNNING */,
892
907
  pausedAt: null,
@@ -963,7 +978,7 @@ class WorkflowEngine {
963
978
  step
964
979
  };
965
980
  const result = await workflow2.handler(context);
966
- run = await this.getRun({ runId, resourceId });
981
+ run = await this.getRun({ runId, resourceId: scopedResourceId });
967
982
  const isLastParsedStep = run.currentStepId === workflow2.steps[workflow2.steps.length - 1]?.id;
968
983
  const hasPluginSteps = (workflow2.plugins?.length ?? 0) > 0;
969
984
  const noParsedSteps = workflow2.steps.length === 0;
@@ -972,7 +987,7 @@ class WorkflowEngine {
972
987
  const normalizedResult = result === undefined ? {} : result;
973
988
  await this.updateRun({
974
989
  runId,
975
- resourceId,
990
+ resourceId: scopedResourceId,
976
991
  data: {
977
992
  status: "completed" /* COMPLETED */,
978
993
  output: normalizedResult,
@@ -989,7 +1004,7 @@ class WorkflowEngine {
989
1004
  if (run.retryCount < run.maxRetries) {
990
1005
  await this.updateRun({
991
1006
  runId,
992
- resourceId,
1007
+ resourceId: scopedResourceId,
993
1008
  data: {
994
1009
  retryCount: run.retryCount + 1,
995
1010
  jobId: job?.id
@@ -998,7 +1013,7 @@ class WorkflowEngine {
998
1013
  const retryDelay = 2 ** run.retryCount * 1000;
999
1014
  const pgBossJob = {
1000
1015
  runId,
1001
- resourceId,
1016
+ resourceId: scopedResourceId,
1002
1017
  workflowId,
1003
1018
  input
1004
1019
  };
@@ -1010,7 +1025,7 @@ class WorkflowEngine {
1010
1025
  }
1011
1026
  await this.updateRun({
1012
1027
  runId,
1013
- resourceId,
1028
+ resourceId: scopedResourceId,
1014
1029
  data: {
1015
1030
  status: "failed" /* FAILED */,
1016
1031
  error: error instanceof Error ? error.message : String(error),
@@ -1258,5 +1273,5 @@ ${error.stack}` : String(error)
1258
1273
  }
1259
1274
  }
1260
1275
 
1261
- //# debugId=AA54057FBD64F69364756E2164756E21
1276
+ //# debugId=CB5A27C81F2BF17864756E2164756E21
1262
1277
  //# sourceMappingURL=index.js.map
package/dist/index.d.cts CHANGED
@@ -242,6 +242,13 @@ declare class WorkflowEngine {
242
242
  runId: string;
243
243
  resourceId?: string;
244
244
  }): Promise<WorkflowRunProgress>;
245
+ /**
246
+ * Resolves the resource id used for scoped DB access (getRun/updateRun).
247
+ * When the job omits resourceId, the run's stored resourceId is used.
248
+ * When the job includes resourceId, it must match the run's resourceId if the run is scoped;
249
+ * unscoped runs reject a job-supplied resourceId (authorization).
250
+ */
251
+ private resolveScopedResourceId;
245
252
  private handleWorkflowRun;
246
253
  private getCachedStepEntry;
247
254
  private runStep;
package/dist/index.d.ts CHANGED
@@ -242,6 +242,13 @@ declare class WorkflowEngine {
242
242
  runId: string;
243
243
  resourceId?: string;
244
244
  }): Promise<WorkflowRunProgress>;
245
+ /**
246
+ * Resolves the resource id used for scoped DB access (getRun/updateRun).
247
+ * When the job omits resourceId, the run's stored resourceId is used.
248
+ * When the job includes resourceId, it must match the run's resourceId if the run is scoped;
249
+ * unscoped runs reject a job-supplied resourceId (authorization).
250
+ */
251
+ private resolveScopedResourceId;
245
252
  private handleWorkflowRun;
246
253
  private getCachedStepEntry;
247
254
  private runStep;
package/dist/index.js CHANGED
@@ -681,9 +681,10 @@ class WorkflowEngine {
681
681
  }) {
682
682
  await this.checkIfHasStarted();
683
683
  const run = await this.getRun({ runId, resourceId });
684
+ const jobResourceId = resourceId ?? run.resourceId ?? undefined;
684
685
  const job = {
685
686
  runId: run.id,
686
- resourceId,
687
+ resourceId: jobResourceId,
687
688
  workflowId: run.workflowId,
688
689
  input: run.input,
689
690
  event: {
@@ -750,14 +751,24 @@ class WorkflowEngine {
750
751
  totalSteps: steps.length
751
752
  };
752
753
  }
754
+ resolveScopedResourceId(jobResourceId, run) {
755
+ const jobResourceProvided = jobResourceId !== undefined && jobResourceId !== null && jobResourceId !== "";
756
+ if (jobResourceProvided) {
757
+ if (run.resourceId === null) {
758
+ throw new WorkflowRunNotFoundError(run.id);
759
+ }
760
+ if (run.resourceId !== jobResourceId) {
761
+ throw new WorkflowRunNotFoundError(run.id);
762
+ }
763
+ return jobResourceId;
764
+ }
765
+ return run.resourceId ?? undefined;
766
+ }
753
767
  async handleWorkflowRun([job]) {
754
768
  const { runId, resourceId, workflowId, input, event } = job?.data ?? {};
755
769
  if (!runId) {
756
770
  throw new WorkflowEngineError("Invalid workflow run job, missing runId", workflowId);
757
771
  }
758
- if (!resourceId) {
759
- throw new WorkflowEngineError("Invalid workflow run job, missing resourceId", workflowId);
760
- }
761
772
  if (!workflowId) {
762
773
  throw new WorkflowEngineError("Invalid workflow run job, missing workflowId", undefined, runId);
763
774
  }
@@ -769,7 +780,11 @@ class WorkflowEngine {
769
780
  runId,
770
781
  workflowId
771
782
  });
772
- let run = await this.getRun({ runId, resourceId });
783
+ let run = await this.getRun({ runId });
784
+ if (run.workflowId !== workflowId) {
785
+ throw new WorkflowEngineError(`Workflow run ${runId} does not match job workflowId ${workflowId}`, workflowId, runId);
786
+ }
787
+ const scopedResourceId = this.resolveScopedResourceId(resourceId, run);
773
788
  try {
774
789
  if (run.status === "cancelled" /* CANCELLED */) {
775
790
  this.logger.log(`Workflow run ${runId} is cancelled, skipping`);
@@ -790,7 +805,7 @@ class WorkflowEngine {
790
805
  const skipOutput = waitFor?.skipOutput;
791
806
  run = await this.updateRun({
792
807
  runId,
793
- resourceId,
808
+ resourceId: scopedResourceId,
794
809
  data: {
795
810
  status: "running" /* RUNNING */,
796
811
  pausedAt: null,
@@ -810,7 +825,7 @@ class WorkflowEngine {
810
825
  } else {
811
826
  run = await this.updateRun({
812
827
  runId,
813
- resourceId,
828
+ resourceId: scopedResourceId,
814
829
  data: {
815
830
  status: "running" /* RUNNING */,
816
831
  pausedAt: null,
@@ -887,7 +902,7 @@ class WorkflowEngine {
887
902
  step
888
903
  };
889
904
  const result = await workflow2.handler(context);
890
- run = await this.getRun({ runId, resourceId });
905
+ run = await this.getRun({ runId, resourceId: scopedResourceId });
891
906
  const isLastParsedStep = run.currentStepId === workflow2.steps[workflow2.steps.length - 1]?.id;
892
907
  const hasPluginSteps = (workflow2.plugins?.length ?? 0) > 0;
893
908
  const noParsedSteps = workflow2.steps.length === 0;
@@ -896,7 +911,7 @@ class WorkflowEngine {
896
911
  const normalizedResult = result === undefined ? {} : result;
897
912
  await this.updateRun({
898
913
  runId,
899
- resourceId,
914
+ resourceId: scopedResourceId,
900
915
  data: {
901
916
  status: "completed" /* COMPLETED */,
902
917
  output: normalizedResult,
@@ -913,7 +928,7 @@ class WorkflowEngine {
913
928
  if (run.retryCount < run.maxRetries) {
914
929
  await this.updateRun({
915
930
  runId,
916
- resourceId,
931
+ resourceId: scopedResourceId,
917
932
  data: {
918
933
  retryCount: run.retryCount + 1,
919
934
  jobId: job?.id
@@ -922,7 +937,7 @@ class WorkflowEngine {
922
937
  const retryDelay = 2 ** run.retryCount * 1000;
923
938
  const pgBossJob = {
924
939
  runId,
925
- resourceId,
940
+ resourceId: scopedResourceId,
926
941
  workflowId,
927
942
  input
928
943
  };
@@ -934,7 +949,7 @@ class WorkflowEngine {
934
949
  }
935
950
  await this.updateRun({
936
951
  runId,
937
- resourceId,
952
+ resourceId: scopedResourceId,
938
953
  data: {
939
954
  status: "failed" /* FAILED */,
940
955
  error: error instanceof Error ? error.message : String(error),
@@ -1191,5 +1206,5 @@ export {
1191
1206
  StepType
1192
1207
  };
1193
1208
 
1194
- //# debugId=CE7E5C5A6D5068D664756E2164756E21
1209
+ //# debugId=3D0DF5019111390C64756E2164756E21
1195
1210
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -5,13 +5,13 @@
5
5
  "import type {\n InputParameters,\n StepBaseContext,\n WorkflowContext,\n WorkflowDefinition,\n WorkflowFactory,\n WorkflowOptions,\n WorkflowPlugin,\n} from './types';\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, StepBaseContext & TStepExt> => ({\n id,\n handler,\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 return factory;\n}\n\nexport const workflow: WorkflowFactory = createWorkflowFactory();\n",
6
6
  "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",
7
7
  "export 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 ) {\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",
8
- "import { merge } from 'es-toolkit';\nimport pg from 'pg';\nimport { type Db, type Job, PgBoss } from 'pg-boss';\nimport type { z } from 'zod';\nimport { parseWorkflowHandler } from './ast-parser';\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 type StepBaseContext,\n StepType,\n type WorkflowContext,\n type WorkflowDefinition,\n type WorkflowInternalDefinition,\n type WorkflowInternalLogger,\n type WorkflowInternalLoggerContext,\n type WorkflowLogger,\n type WorkflowRunProgress,\n WorkflowStatus,\n} from './types';\n\nconst PAUSE_EVENT_NAME = '__internal_pause';\nconst WORKFLOW_RUN_QUEUE_NAME = 'workflow-run';\nconst LOG_PREFIX = '[WorkflowEngine]';\nconst DEFAULT_PGBOSS_SCHEMA = 'pgboss_v12_pgworkflow';\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<TStep extends StepBaseContext>(\n definition: WorkflowDefinition<InputParameters, TStep>,\n ): 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({\n resourceId,\n workflowId,\n input,\n options,\n }: {\n resourceId?: string;\n workflowId: string;\n input: unknown;\n options?: {\n timeout?: number;\n retries?: number;\n expireInSeconds?: number;\n batchSize?: number;\n };\n }): Promise<WorkflowRun> {\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 = workflow.inputSchema.safeParse(input);\n if (!result.success) {\n throw new WorkflowEngineError(result.error.message, workflowId);\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 insertedRun = 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 },\n _db,\n );\n\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 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 });\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 return this.triggerEvent({\n runId,\n resourceId,\n eventName: PAUSE_EVENT_NAME,\n data: {},\n options,\n });\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 });\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 job: WorkflowRunJobParameters = {\n runId: run.id,\n resourceId,\n workflowId: run.workflowId,\n input: run.input,\n event: {\n name: eventName,\n data,\n },\n };\n\n 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 }: {\n runId: string;\n resourceId?: string;\n data: Partial<WorkflowRun>;\n },\n { db }: { db?: Db } = {},\n ): Promise<WorkflowRun> {\n const run = await updateWorkflowRun({ runId, resourceId, data }, 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 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 private async handleWorkflowRun([job]: Job<WorkflowRunJobParameters>[]) {\n const { runId, resourceId, workflowId, input, event } = job?.data ?? {};\n\n if (!runId) {\n throw new WorkflowEngineError('Invalid workflow run job, missing runId', workflowId);\n }\n\n if (!resourceId) {\n throw new WorkflowEngineError('Invalid workflow run job, missing resourceId', 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 let run = await this.getRun({ runId, resourceId });\n\n try {\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 const waitForStepEntry = run.timeline[`${run.currentStepId}-wait-for`];\n const waitForStep =\n waitForStepEntry && typeof waitForStepEntry === 'object' && 'waitFor' in waitForStepEntry\n ? (waitForStepEntry as TimelineWaitForEntry)\n : null;\n const currentStep = this.getCachedStepEntry(run.timeline, run.currentStepId);\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 run = await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.RUNNING,\n pausedAt: null,\n resumedAt: new Date(),\n jobId: job?.id,\n ...(skipOutput\n ? {}\n : {\n timeline: merge(run.timeline, {\n [run.currentStepId]: {\n output: event?.data ?? {},\n ...(isTimeout ? { timedOut: true as const } : {}),\n timestamp: new Date(),\n },\n }),\n }),\n },\n });\n } else {\n run = await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.RUNNING,\n pausedAt: null,\n resumedAt: new Date(),\n jobId: job?.id,\n },\n });\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 z.ZodTypeAny,\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 });\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,\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.retryCount < run.maxRetries) {\n await this.updateRun({\n runId,\n resourceId,\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,\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 await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.FAILED,\n error: error instanceof Error ? error.message : String(error),\n jobId: job?.id,\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 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(run.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 this.updateRun({\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(run.timeline, {\n [`${stepId}-wait-for`]: {\n waitFor: { eventName, timeoutEvent },\n timestamp: new Date(),\n },\n }),\n },\n });\n\n if (timeoutDate && timeoutEvent) {\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 }\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 this.updateRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n currentStepId: stepId,\n timeline: merge(persistedRun.timeline, {\n [stepId]: { output: {}, timedOut: true as const, timestamp: new Date() },\n }),\n },\n });\n return { timedOut: true };\n }\n\n const result = await conditionFn();\n\n if (result !== false) {\n await this.updateRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n currentStepId: stepId,\n timeline: merge(persistedRun.timeline, {\n [stepId]: { output: result, timestamp: new Date() },\n }),\n },\n });\n return { timedOut: false, data: result };\n }\n\n const pollEvent = `__poll_${stepId}`;\n await this.updateRun({\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(persistedRun.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\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\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",
8
+ "import { merge } from 'es-toolkit';\nimport pg from 'pg';\nimport { type Db, type Job, PgBoss } from 'pg-boss';\nimport type { z } from 'zod';\nimport { parseWorkflowHandler } from './ast-parser';\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 type StepBaseContext,\n StepType,\n type WorkflowContext,\n type WorkflowDefinition,\n type WorkflowInternalDefinition,\n type WorkflowInternalLogger,\n type WorkflowInternalLoggerContext,\n type WorkflowLogger,\n type WorkflowRunProgress,\n WorkflowStatus,\n} from './types';\n\nconst PAUSE_EVENT_NAME = '__internal_pause';\nconst WORKFLOW_RUN_QUEUE_NAME = 'workflow-run';\nconst LOG_PREFIX = '[WorkflowEngine]';\nconst DEFAULT_PGBOSS_SCHEMA = 'pgboss_v12_pgworkflow';\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<TStep extends StepBaseContext>(\n definition: WorkflowDefinition<InputParameters, TStep>,\n ): 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({\n resourceId,\n workflowId,\n input,\n options,\n }: {\n resourceId?: string;\n workflowId: string;\n input: unknown;\n options?: {\n timeout?: number;\n retries?: number;\n expireInSeconds?: number;\n batchSize?: number;\n };\n }): Promise<WorkflowRun> {\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 = workflow.inputSchema.safeParse(input);\n if (!result.success) {\n throw new WorkflowEngineError(result.error.message, workflowId);\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 insertedRun = 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 },\n _db,\n );\n\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 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 });\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 return this.triggerEvent({\n runId,\n resourceId,\n eventName: PAUSE_EVENT_NAME,\n data: {},\n options,\n });\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 });\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 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 }: {\n runId: string;\n resourceId?: string;\n data: Partial<WorkflowRun>;\n },\n { db }: { db?: Db } = {},\n ): Promise<WorkflowRun> {\n const run = await updateWorkflowRun({ runId, resourceId, data }, 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 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 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 let 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 const scopedResourceId = this.resolveScopedResourceId(resourceId, run);\n\n try {\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 const waitForStepEntry = run.timeline[`${run.currentStepId}-wait-for`];\n const waitForStep =\n waitForStepEntry && typeof waitForStepEntry === 'object' && 'waitFor' in waitForStepEntry\n ? (waitForStepEntry as TimelineWaitForEntry)\n : null;\n const currentStep = this.getCachedStepEntry(run.timeline, run.currentStepId);\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 run = await this.updateRun({\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(run.timeline, {\n [run.currentStepId]: {\n output: event?.data ?? {},\n ...(isTimeout ? { timedOut: true as const } : {}),\n timestamp: new Date(),\n },\n }),\n }),\n },\n });\n } else {\n run = await this.updateRun({\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 }\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 z.ZodTypeAny,\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.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 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 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 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(run.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 this.updateRun({\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(run.timeline, {\n [`${stepId}-wait-for`]: {\n waitFor: { eventName, timeoutEvent },\n timestamp: new Date(),\n },\n }),\n },\n });\n\n if (timeoutDate && timeoutEvent) {\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 }\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 this.updateRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n currentStepId: stepId,\n timeline: merge(persistedRun.timeline, {\n [stepId]: { output: {}, timedOut: true as const, timestamp: new Date() },\n }),\n },\n });\n return { timedOut: true };\n }\n\n const result = await conditionFn();\n\n if (result !== false) {\n await this.updateRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n currentStepId: stepId,\n timeline: merge(persistedRun.timeline, {\n [stepId]: { output: result, timestamp: new Date() },\n }),\n },\n });\n return { timedOut: false, data: result };\n }\n\n const pollEvent = `__poll_${stepId}`;\n await this.updateRun({\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(persistedRun.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\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\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",
9
9
  "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",
10
10
  "import type { z } from 'zod';\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 = z.ZodTypeAny;\nexport type InferInputParameters<P extends InputParameters> = P extends z.ZodTypeAny\n ? z.infer<P>\n : never;\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<\n TInput extends InputParameters = InputParameters,\n TStep extends StepBaseContext = StepBaseContext,\n> = {\n id: string;\n handler: (context: WorkflowContext<TInput, TStep>) => 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<\n TInput extends InputParameters = InputParameters,\n TStep extends StepBaseContext = StepBaseContext,\n> = WorkflowDefinition<TInput, TStep> & {\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 (\n id: string,\n handler: (\n context: WorkflowContext<InputParameters, StepBaseContext & TStepExt>,\n ) => Promise<unknown>,\n options?: WorkflowOptions<InputParameters>,\n ): WorkflowDefinition<InputParameters, StepBaseContext & TStepExt>;\n use<TNewExt>(\n plugin: WorkflowPlugin<StepBaseContext & TStepExt, TNewExt>,\n ): WorkflowFactory<TStepExt & TNewExt>;\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 { Db } from 'pg-boss';\n\nexport async function runMigrations(db: Db): Promise<void> {\n const tableExistsResult = await db.executeSql(\n `\n SELECT EXISTS (\n SELECT FROM information_schema.tables \n WHERE table_schema = 'public' \n AND table_name = 'workflow_runs'\n );\n `,\n [],\n );\n\n if (!tableExistsResult.rows[0]?.exists) {\n await db.executeSql(\n `\n CREATE TABLE 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 [],\n );\n\n await db.executeSql(\n `\n CREATE INDEX workflow_runs_workflow_id_idx ON workflow_runs USING btree (workflow_id);\n `,\n [],\n );\n\n await db.executeSql(\n `\n CREATE INDEX workflow_runs_created_at_idx ON workflow_runs USING btree (created_at);\n `,\n [],\n );\n\n await db.executeSql(\n `\n CREATE INDEX workflow_runs_resource_id_idx ON workflow_runs USING btree (resource_id);\n `,\n [],\n );\n }\n}\n",
12
12
  "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};\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 };\n}\n\nexport async function insertWorkflowRun(\n {\n resourceId,\n workflowId,\n currentStepId,\n status,\n input,\n maxRetries,\n timeoutAt,\n }: {\n resourceId?: string;\n workflowId: string;\n currentStepId: string;\n status: string;\n input: unknown;\n maxRetries: number;\n timeoutAt: Date | null;\n },\n db: Db,\n): Promise<WorkflowRun> {\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 )\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)\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 ],\n );\n\n const insertedRun = result.rows[0];\n\n if (!insertedRun) {\n throw new Error('Failed to insert workflow run');\n }\n\n return mapRowToWorkflowRun(insertedRun);\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 }: {\n runId: string;\n resourceId?: string;\n data: Partial<WorkflowRun>;\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)[] = [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 const whereClause = resourceId\n ? `WHERE id = $${paramIndex} AND resource_id = $${paramIndex + 1}`\n : `WHERE id = $${paramIndex}`;\n\n values.push(runId);\n if (resourceId) {\n values.push(resourceId);\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 if (startingAfter) {\n const cursorResult = await db.executeSql(\n 'SELECT created_at FROM workflow_runs WHERE id = $1 LIMIT 1',\n [startingAfter],\n );\n if (cursorResult.rows[0]?.created_at) {\n conditions.push(`created_at < $${paramIndex}`);\n values.push(\n typeof cursorResult.rows[0].created_at === 'string'\n ? new Date(cursorResult.rows[0].created_at)\n : cursorResult.rows[0].created_at,\n );\n paramIndex++;\n }\n }\n\n if (endingBefore) {\n const cursorResult = await db.executeSql(\n 'SELECT created_at FROM workflow_runs WHERE id = $1 LIMIT 1',\n [endingBefore],\n );\n if (cursorResult.rows[0]?.created_at) {\n conditions.push(`created_at > $${paramIndex}`);\n values.push(\n typeof cursorResult.rows[0].created_at === 'string'\n ? new Date(cursorResult.rows[0].created_at)\n : cursorResult.rows[0].created_at,\n );\n paramIndex++;\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 query = `\n SELECT * FROM workflow_runs\n ${whereClause}\n ORDER BY created_at 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 hasMore = rows.length > (limit ?? 20);\n const rawItems = hasMore ? rows.slice(0, limit) : rows;\n const items = rawItems.map((row) => mapRowToWorkflowRun(row));\n const hasPrev = !!endingBefore;\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"
13
13
  ],
14
- "mappings": "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",
15
- "debugId": "AA54057FBD64F69364756E2164756E21",
14
+ "mappings": "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",
15
+ "debugId": "CB5A27C81F2BF17864756E2164756E21",
16
16
  "names": []
17
17
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pg-workflows",
3
3
  "description": "The simplest Postgres workflow engine for TypeScript - durable execution, event-driven orchestration, and automatic retries powered entirely by PostgreSQL",
4
- "version": "0.4.0",
4
+ "version": "0.5.0",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"