pg-workflows 0.13.2 → 0.15.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.
@@ -50,6 +50,13 @@ class WorkflowRunNotFoundError extends WorkflowEngineError {
50
50
  }
51
51
  }
52
52
 
53
+ class WorkflowRunInProgressError extends WorkflowEngineError {
54
+ constructor(workflowId, runId) {
55
+ super(`Workflow "${workflowId}" already has a running run; wait for it to pause, complete, fail, or be cancelled`, workflowId, runId);
56
+ this.name = "WorkflowRunInProgressError";
57
+ }
58
+ }
59
+
53
60
  // src/types.ts
54
61
  var WorkflowStatus;
55
62
  ((WorkflowStatus2) => {
@@ -79,7 +86,7 @@ import { PgBoss } from "pg-boss";
79
86
 
80
87
  // src/db/migration.ts
81
88
  var MIGRATION_LOCK_ID = 738291645;
82
- var CURRENT_SCHEMA_VERSION = 5;
89
+ var CURRENT_SCHEMA_VERSION = 7;
83
90
  async function runMigrations(db) {
84
91
  if (await isSchemaUpToDate(db)) {
85
92
  return;
@@ -155,6 +162,17 @@ async function runMigrations(db) {
155
162
  if (currentVersion < 5) {
156
163
  commands.push("ALTER TABLE workflow_runs ADD COLUMN IF NOT EXISTS scheduled_at timestamp with time zone");
157
164
  }
165
+ if (currentVersion < 6) {
166
+ commands.push("ALTER TABLE workflow_runs ADD COLUMN IF NOT EXISTS priority integer DEFAULT 0 NOT NULL");
167
+ }
168
+ if (currentVersion < 7) {
169
+ commands.push("ALTER TABLE workflow_runs ADD COLUMN IF NOT EXISTS singleton boolean DEFAULT false NOT NULL");
170
+ commands.push(`
171
+ CREATE UNIQUE INDEX IF NOT EXISTS workflow_runs_singleton_active_idx
172
+ ON workflow_runs (workflow_id)
173
+ WHERE singleton AND status IN ('pending', 'running')
174
+ `);
175
+ }
158
176
  if (currentVersion === 0) {
159
177
  commands.push(`INSERT INTO workflow_schema_version (version) VALUES (${CURRENT_SCHEMA_VERSION})`);
160
178
  } else {
@@ -197,6 +215,16 @@ import ksuid from "ksuid";
197
215
  function generateKSUID(prefix) {
198
216
  return `${prefix ? `${prefix}_` : ""}${ksuid.randomSync().string}`;
199
217
  }
218
+ function isUniqueViolation(error) {
219
+ if (!error || typeof error !== "object") {
220
+ return false;
221
+ }
222
+ if ("code" in error && error.code === "23505") {
223
+ return true;
224
+ }
225
+ const cause = "cause" in error ? error.cause : undefined;
226
+ return Boolean(cause && typeof cause === "object" && "code" in cause && cause.code === "23505");
227
+ }
200
228
  function mapRowToWorkflowRun(row) {
201
229
  return {
202
230
  id: row.id,
@@ -216,12 +244,14 @@ function mapRowToWorkflowRun(row) {
216
244
  timeoutAt: row.timeout_at ? new Date(row.timeout_at) : null,
217
245
  retryCount: row.retry_count,
218
246
  maxRetries: row.max_retries,
247
+ priority: row.priority,
219
248
  jobId: row.job_id,
220
249
  idempotencyKey: row.idempotency_key,
221
250
  parentRunId: row.parent_run_id,
222
251
  parentStepId: row.parent_step_id,
223
252
  parentResourceId: row.parent_resource_id,
224
- scheduledAt: row.scheduled_at ? new Date(row.scheduled_at) : null
253
+ scheduledAt: row.scheduled_at ? new Date(row.scheduled_at) : null,
254
+ singleton: Boolean(row.singleton)
225
255
  };
226
256
  }
227
257
  async function insertWorkflowRun({
@@ -231,16 +261,26 @@ async function insertWorkflowRun({
231
261
  status,
232
262
  input,
233
263
  maxRetries,
264
+ priority,
234
265
  timeoutAt,
235
266
  idempotencyKey,
236
267
  parentRunId,
237
268
  parentStepId,
238
269
  parentResourceId,
239
- scheduledAt
270
+ scheduledAt,
271
+ singleton = false
240
272
  }, db) {
241
273
  const runId = generateKSUID("run");
242
274
  const now = new Date;
243
- const result = await db.executeSql(`INSERT INTO workflow_runs (
275
+ if (singleton) {
276
+ const active = await getActiveSingletonRun(workflowId, db);
277
+ if (active) {
278
+ throw new WorkflowRunInProgressError(workflowId, active.id);
279
+ }
280
+ }
281
+ let result;
282
+ try {
283
+ result = await db.executeSql(`INSERT INTO workflow_runs (
244
284
  id,
245
285
  resource_id,
246
286
  workflow_id,
@@ -248,6 +288,7 @@ async function insertWorkflowRun({
248
288
  status,
249
289
  input,
250
290
  max_retries,
291
+ priority,
251
292
  timeout_at,
252
293
  created_at,
253
294
  updated_at,
@@ -257,29 +298,39 @@ async function insertWorkflowRun({
257
298
  parent_run_id,
258
299
  parent_step_id,
259
300
  parent_resource_id,
260
- scheduled_at
301
+ scheduled_at,
302
+ singleton
261
303
  )
262
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
304
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)
263
305
  ON CONFLICT (idempotency_key) WHERE idempotency_key IS NOT NULL DO NOTHING
264
306
  RETURNING *`, [
265
- runId,
266
- resourceId ?? null,
267
- workflowId,
268
- currentStepId,
269
- status,
270
- JSON.stringify(input),
271
- maxRetries,
272
- timeoutAt,
273
- now,
274
- now,
275
- "{}",
276
- 0,
277
- idempotencyKey ?? null,
278
- parentRunId ?? null,
279
- parentStepId ?? null,
280
- parentResourceId ?? null,
281
- scheduledAt ?? null
282
- ]);
307
+ runId,
308
+ resourceId ?? null,
309
+ workflowId,
310
+ currentStepId,
311
+ status,
312
+ JSON.stringify(input),
313
+ maxRetries,
314
+ priority,
315
+ timeoutAt,
316
+ now,
317
+ now,
318
+ "{}",
319
+ 0,
320
+ idempotencyKey ?? null,
321
+ parentRunId ?? null,
322
+ parentStepId ?? null,
323
+ parentResourceId ?? null,
324
+ scheduledAt ?? null,
325
+ singleton
326
+ ]);
327
+ } catch (error) {
328
+ if (singleton && isUniqueViolation(error)) {
329
+ const active = await getActiveSingletonRun(workflowId, db);
330
+ throw new WorkflowRunInProgressError(workflowId, active?.id);
331
+ }
332
+ throw error;
333
+ }
283
334
  if (result.rows[0]) {
284
335
  return { run: mapRowToWorkflowRun(result.rows[0]), created: true };
285
336
  }
@@ -291,6 +342,20 @@ async function insertWorkflowRun({
291
342
  }
292
343
  return { run: mapRowToWorkflowRun(existing.rows[0]), created: false };
293
344
  }
345
+ async function getActiveSingletonRun(workflowId, db) {
346
+ const result = await db.executeSql(`SELECT * FROM workflow_runs
347
+ WHERE workflow_id = $1
348
+ AND singleton
349
+ AND status IN ('pending', 'running')
350
+ LIMIT 1`, [workflowId]);
351
+ return result.rows[0] ? mapRowToWorkflowRun(result.rows[0]) : null;
352
+ }
353
+ async function assertSingletonSlotAvailable({ workflowId, exceptRunId }, db) {
354
+ const active = await getActiveSingletonRun(workflowId, db);
355
+ if (active && active.id !== exceptRunId) {
356
+ throw new WorkflowRunInProgressError(workflowId, active.id);
357
+ }
358
+ }
294
359
  async function getWorkflowRun({
295
360
  runId,
296
361
  resourceId
@@ -405,7 +470,15 @@ async function updateWorkflowRun({
405
470
  ${whereClause}
406
471
  RETURNING *
407
472
  `;
408
- const result = await db.executeSql(query, values);
473
+ let result;
474
+ try {
475
+ result = await db.executeSql(query, values);
476
+ } catch (error) {
477
+ if (data.status === "running" && isUniqueViolation(error)) {
478
+ throw new WorkflowRunInProgressError("unknown", runId);
479
+ }
480
+ throw error;
481
+ }
409
482
  const run = result.rows[0];
410
483
  if (!run) {
411
484
  return null;
@@ -511,6 +584,30 @@ async function withPostgresTransaction(db, callback, pool) {
511
584
  }
512
585
  }
513
586
 
587
+ // src/priority.ts
588
+ var PRIORITY_LEVELS = { high: 100, normal: 0, low: -100 };
589
+ function priorityToInt(value) {
590
+ if (typeof value === "number") {
591
+ if (!Number.isInteger(value)) {
592
+ throw new WorkflowEngineError(`Invalid priority ${value}: numeric priority must be an integer.`);
593
+ }
594
+ return value;
595
+ }
596
+ const mapped = PRIORITY_LEVELS[value];
597
+ if (mapped === undefined) {
598
+ throw new WorkflowEngineError(`Invalid priority "${value}": expected one of ${Object.keys(PRIORITY_LEVELS).map((k) => `"${k}"`).join(", ")} or an integer.`);
599
+ }
600
+ return mapped;
601
+ }
602
+ function resolvePriority(...candidates) {
603
+ for (const candidate of candidates) {
604
+ if (candidate !== undefined) {
605
+ return priorityToInt(candidate);
606
+ }
607
+ }
608
+ return PRIORITY_LEVELS.normal;
609
+ }
610
+
514
611
  // src/client.ts
515
612
  var LOG_PREFIX = "[WorkflowClient]";
516
613
  var defaultLogger = {
@@ -539,11 +636,10 @@ class WorkflowClient {
539
636
  const db = {
540
637
  executeSql: (text, values) => this.pool.query(text, values)
541
638
  };
542
- if (boss) {
543
- this.boss = boss;
544
- } else {
545
- this.boss = new PgBoss({ db, schema: DEFAULT_PGBOSS_SCHEMA });
546
- }
639
+ this.boss = boss ?? new PgBoss({ db, schema: DEFAULT_PGBOSS_SCHEMA });
640
+ this.boss.on("error", (error) => {
641
+ this.logger.error("pg-boss error", error);
642
+ });
547
643
  this.db = db;
548
644
  }
549
645
  async start() {
@@ -572,6 +668,7 @@ class WorkflowClient {
572
668
  let resourceId;
573
669
  let idempotencyKey;
574
670
  let options;
671
+ let singleton = false;
575
672
  if (typeof refOrParams === "function" && "id" in refOrParams) {
576
673
  const ref = refOrParams;
577
674
  workflowId = ref.id;
@@ -579,6 +676,7 @@ class WorkflowClient {
579
676
  options = optionsArg;
580
677
  resourceId = optionsArg?.resourceId;
581
678
  idempotencyKey = optionsArg?.idempotencyKey;
679
+ singleton = optionsArg?.singleton ?? ref.singleton === true;
582
680
  if (ref.inputSchema) {
583
681
  const result = await ref.inputSchema["~standard"].validate(input);
584
682
  if (result.issues) {
@@ -592,6 +690,7 @@ class WorkflowClient {
592
690
  resourceId = params.resourceId;
593
691
  idempotencyKey = params.idempotencyKey;
594
692
  options = params.options;
693
+ singleton = params.options?.singleton === true;
595
694
  }
596
695
  validateWorkflowId(workflowId);
597
696
  validateResourceId(resourceId);
@@ -604,8 +703,10 @@ class WorkflowClient {
604
703
  status: "running" /* RUNNING */,
605
704
  input,
606
705
  maxRetries: options?.retries ?? 0,
706
+ priority: resolvePriority(options?.priority),
607
707
  timeoutAt,
608
- idempotencyKey
708
+ idempotencyKey,
709
+ singleton
609
710
  }, _db);
610
711
  if (created) {
611
712
  const job = {
@@ -617,6 +718,7 @@ class WorkflowClient {
617
718
  await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {
618
719
  startAfter: new Date,
619
720
  expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,
721
+ priority: insertedRun.priority,
620
722
  db: _db
621
723
  });
622
724
  }
@@ -634,6 +736,9 @@ class WorkflowClient {
634
736
  }) {
635
737
  await this.ensureStarted();
636
738
  const run = await this.getRun({ runId, resourceId });
739
+ if (run.singleton) {
740
+ await assertSingletonSlotAvailable({ workflowId: run.workflowId, exceptRunId: run.id }, this.db);
741
+ }
637
742
  const job = {
638
743
  runId: run.id,
639
744
  resourceId: resourceId ?? run.resourceId ?? undefined,
@@ -645,7 +750,8 @@ class WorkflowClient {
645
750
  }
646
751
  };
647
752
  await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {
648
- expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds
753
+ expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,
754
+ priority: run.priority
649
755
  });
650
756
  this.logger.log(`${LOG_PREFIX} Event ${eventName} sent for workflow run ${runId}`);
651
757
  return run;
@@ -825,6 +931,8 @@ function createWorkflowRef(id, options) {
825
931
  inputSchema: options?.inputSchema,
826
932
  timeout: defineOptions?.timeout,
827
933
  retries: defineOptions?.retries,
934
+ priority: defineOptions?.priority,
935
+ singleton: defineOptions?.singleton ?? options?.singleton,
828
936
  schedule: defineOptions?.schedule,
829
937
  timezone: defineOptions?.timezone
830
938
  });
@@ -833,15 +941,29 @@ function createWorkflowRef(id, options) {
833
941
  value: options?.inputSchema,
834
942
  enumerable: true
835
943
  });
944
+ Object.defineProperty(ref, "singleton", {
945
+ value: options?.singleton,
946
+ enumerable: true
947
+ });
836
948
  return ref;
837
949
  }
838
950
  function createWorkflowFactory(plugins = []) {
839
- const factory = (id, handler, { inputSchema, timeout, retries, schedule, timezone } = {}) => ({
951
+ const factory = (id, handler, {
952
+ inputSchema,
953
+ timeout,
954
+ retries,
955
+ priority,
956
+ singleton,
957
+ schedule,
958
+ timezone
959
+ } = {}) => ({
840
960
  id,
841
961
  handler,
842
962
  inputSchema,
843
963
  timeout,
844
964
  retries,
965
+ priority,
966
+ singleton,
845
967
  schedule,
846
968
  timezone,
847
969
  plugins: plugins.length > 0 ? plugins : undefined
@@ -855,7 +977,7 @@ function createWorkflowFactory(plugins = []) {
855
977
  }
856
978
  var workflow = createWorkflowFactory();
857
979
 
858
- export { PAUSE_EVENT_NAME, WORKFLOW_RUN_QUEUE_NAME, WORKFLOW_RUN_DLQ_QUEUE_NAME, scheduleQueueNameFor, DEFAULT_PGBOSS_SCHEMA, invokeChildWorkflowTimelineKey, waitForTimelineKey, isInvokeChildWorkflowTimelineEntry, runMigrations, insertWorkflowRun, getWorkflowRun, getWorkflowLastRun, updateWorkflowRun, getWorkflowRuns, withPostgresTransaction, validateWorkflowId, validateResourceId, WorkflowEngineError, WorkflowRunNotFoundError, WorkflowStatus, STEP_BASE_METHOD_TYPES, WorkflowClient, createWorkflowRef, workflow };
980
+ export { PAUSE_EVENT_NAME, WORKFLOW_RUN_QUEUE_NAME, WORKFLOW_RUN_DLQ_QUEUE_NAME, scheduleQueueNameFor, DEFAULT_PGBOSS_SCHEMA, invokeChildWorkflowTimelineKey, waitForTimelineKey, isInvokeChildWorkflowTimelineEntry, runMigrations, validateWorkflowId, validateResourceId, WorkflowEngineError, WorkflowRunNotFoundError, WorkflowRunInProgressError, insertWorkflowRun, assertSingletonSlotAvailable, getWorkflowRun, getWorkflowLastRun, updateWorkflowRun, getWorkflowRuns, withPostgresTransaction, resolvePriority, WorkflowStatus, STEP_BASE_METHOD_TYPES, WorkflowClient, createWorkflowRef, workflow };
859
981
 
860
- //# debugId=9CDBDF4EE7FE9C3F64756E2164756E21
861
- //# sourceMappingURL=chunk-hjycwrsq.js.map
982
+ //# debugId=779362C94AF314E764756E2164756E21
983
+ //# sourceMappingURL=chunk-n0f7hd40.js.map
@@ -0,0 +1,17 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["src/constants.ts", "src/error.ts", "src/types.ts", "src/client.ts", "src/db/migration.ts", "src/db/queries.ts", "src/priority.ts", "src/definition.ts"],
4
+ "sourcesContent": [
5
+ "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';\n// pg-boss queue names allow only alphanumeric, _, -, ., or / — keep the\n// prefix in that character set so any valid workflow id stays addressable.\nconst SCHEDULE_QUEUE_PREFIX = '__pgw_schedule_';\nexport const scheduleQueueNameFor = (workflowId: string): string =>\n `${SCHEDULE_QUEUE_PREFIX}${workflowId}`;\nexport const DEFAULT_PGBOSS_SCHEMA = 'pgboss_v12_pgworkflow';\nexport const MAX_WORKFLOW_ID_LENGTH = 256;\nexport const MAX_RESOURCE_ID_LENGTH = 256;\n\n// Per-step timeline key suffixes. The shared helpers below are the single\n// source of truth for engine + client so timeline-shape changes only need to\n// happen in one place.\nexport const INVOKE_CHILD_WORKFLOW_TIMELINE_SUFFIX = 'invoke-child-workflow';\nexport const WAIT_FOR_TIMELINE_SUFFIX = 'wait-for';\nexport const invokeChildWorkflowTimelineKey = (stepId: string) =>\n `${stepId}-${INVOKE_CHILD_WORKFLOW_TIMELINE_SUFFIX}`;\nexport const waitForTimelineKey = (stepId: string) => `${stepId}-${WAIT_FOR_TIMELINE_SUFFIX}`;\n\n/**\n * Type guard for `${stepId}-invoke-child-workflow` timeline entries. Used by the\n * engine to dispatch invoke-aware behavior and by the client's resume /\n * fast-forward no-op guards. Centralizing this keeps the timeline shape\n * contract in one place.\n */\nexport const isInvokeChildWorkflowTimelineEntry = (\n entry: unknown,\n): entry is { invokeChildWorkflow: { childRunId: string; childWorkflowId: string } } =>\n !!entry && typeof entry === 'object' && 'invokeChildWorkflow' in entry;\n",
6
+ "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\nexport class WorkflowRunInProgressError extends WorkflowEngineError {\n constructor(workflowId: string, runId?: string) {\n super(\n `Workflow \"${workflowId}\" already has a running run; wait for it to pause, complete, fail, or be cancelled`,\n workflowId,\n runId,\n );\n this.name = 'WorkflowRunInProgressError';\n }\n}\n",
7
+ "import type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { WorkflowRun } from './db/types';\nimport type { Duration } from './duration';\nimport type { WorkflowPriority } from './priority';\nimport type { Schedule } from './schedule';\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 INVOKE_CHILD_WORKFLOW = 'invokeChildWorkflow',\n}\n\nexport type InputParameters = StandardSchemaV1;\nexport type InferInputParameters<P extends InputParameters> = StandardSchemaV1.InferOutput<P>;\n\nexport type StartWorkflowOptions = {\n resourceId?: string;\n timeout?: number;\n retries?: number;\n expireInSeconds?: number;\n idempotencyKey?: string;\n priority?: WorkflowPriority;\n /**\n * Client-side counterpart of `workflow(..., { singleton: true })`.\n * The engine reads this from the registered definition; pass it here when\n * starting from `WorkflowClient` so the uniqueness constraint applies.\n */\n singleton?: boolean;\n};\n\nexport type WorkflowOptions<I extends InputParameters> = {\n timeout?: number;\n retries?: number;\n inputSchema?: I;\n priority?: WorkflowPriority;\n /**\n * When true, at most one pending or running run of this workflow ID may exist.\n * A second `startWorkflow` throws `WorkflowRunInProgressError` until the\n * current run pauses, completes, fails, or is cancelled.\n */\n singleton?: boolean;\n /**\n * Recurring schedule. Accepts a cron expression (`'0 9 * * 1-5'`),\n * a duration string (`'5m'`, `'1 hour'`), or a `DurationObject`.\n */\n schedule?: Schedule;\n /** IANA timezone for cron expressions. Defaults to UTC. Ignored for duration-based schedules. */\n timezone?: string;\n};\n\n/** Metadata about a scheduled fire, exposed on `ctx.schedule` for runs triggered by a schedule. */\nexport type ScheduleContext = {\n /** Time the schedule fired this run. */\n timestamp: Date;\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 * Invoke a child workflow from inside the current workflow and pause until\n * the child run reaches a terminal state.\n */\n invokeChildWorkflow: {\n <TInput extends InputParameters, TOutput = unknown>(\n stepId: string,\n ref: WorkflowRef<TInput, TOutput>,\n input: InferInputParameters<TInput>,\n options?: StartWorkflowOptions,\n ): Promise<TOutput>;\n <TOutput = unknown>(\n stepId: string,\n params: {\n workflowId: string;\n input: unknown;\n resourceId?: string;\n idempotencyKey?: string;\n options?: StartWorkflowOptions;\n },\n ): Promise<TOutput>;\n };\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, context: WorkflowContext) => TStepExt;\n /**\n * Optional middleware around the workflow handler call. Composes in\n * registration order — the first plugin passed to `.use()` wraps everything\n * inside. Implementations MUST call `next()` exactly once.\n */\n wrap?: (context: WorkflowContext, next: () => Promise<unknown>) => Promise<unknown>;\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 /** Tenant/scope identifier set when the run was started, if any. */\n resourceId?: string;\n /** Zero-based retry attempt number (= `run.retryCount`). */\n attempt: number;\n timeline: Record<string, unknown>;\n logger: WorkflowLogger;\n /** Set only for runs triggered by a recurring schedule. */\n schedule?: ScheduleContext;\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 priority?: WorkflowPriority;\n singleton?: boolean;\n schedule?: Schedule;\n timezone?: string;\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, TOutput = unknown>(\n id: string,\n options?: { inputSchema?: TInput; singleton?: boolean },\n ): WorkflowRef<TInput, TOutput>;\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<\n TInput extends InputParameters = InputParameters,\n // biome-ignore lint/correctness/noUnusedVariables: phantom type carried for typed return inference\n TOutput = unknown,\n> {\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 readonly singleton?: boolean;\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};\n\nexport interface WorkflowInternalLogger {\n log(message: string, context?: WorkflowInternalLoggerContext): void;\n error(message: string, error: Error, context?: WorkflowInternalLoggerContext): void;\n}\n\nconst _STEP_BASE_METHOD_TO_TYPE: Record<keyof StepBaseContext, StepType> = {\n run: StepType.RUN,\n waitFor: StepType.WAIT_FOR,\n waitUntil: StepType.WAIT_UNTIL,\n delay: StepType.DELAY,\n sleep: StepType.DELAY,\n pause: StepType.PAUSE,\n poll: StepType.POLL,\n invokeChildWorkflow: StepType.INVOKE_CHILD_WORKFLOW,\n};\n\nexport const STEP_BASE_METHOD_TYPES: ReadonlyMap<string, StepType> = new Map(\n Object.entries(_STEP_BASE_METHOD_TO_TYPE),\n);\n",
8
+ "import { merge } from 'es-toolkit';\nimport pg from 'pg';\nimport { type Db, PgBoss } from 'pg-boss';\nimport {\n DEFAULT_PGBOSS_SCHEMA,\n invokeChildWorkflowTimelineKey,\n isInvokeChildWorkflowTimelineEntry,\n PAUSE_EVENT_NAME,\n WORKFLOW_RUN_QUEUE_NAME,\n waitForTimelineKey,\n} from './constants';\nimport { runMigrations } from './db/migration';\nimport {\n assertSingletonSlotAvailable,\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 { resolvePriority } from './priority';\nimport {\n type InferInputParameters,\n type InputParameters,\n type StartWorkflowOptions,\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\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 this.boss = boss ?? new PgBoss({ db, schema: DEFAULT_PGBOSS_SCHEMA });\n // 12.26+ surfaces fetch/work DB errors here; without a listener Node crashes.\n this.boss.on('error', (error) => {\n this.logger.error('pg-boss error', error);\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 let singleton = false;\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 singleton = optionsArg?.singleton ?? ref.singleton === true;\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 singleton = params.options?.singleton === true;\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 priority: resolvePriority(options?.priority),\n timeoutAt,\n idempotencyKey,\n singleton,\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 // Same connection (`_db`) used for the workflow_runs INSERT is passed\n // to `boss.send` so the pgboss.job INSERT joins the same transaction.\n // The two writes commit or roll back together, so we never leak an\n // orphan workflow_runs row when the queue insert fails.\n await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {\n startAfter: new Date(),\n expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,\n priority: insertedRun.priority,\n db: _db,\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 if (run.singleton) {\n await assertSingletonSlotAvailable(\n { workflowId: run.workflowId, exceptRunId: run.id },\n this.db,\n );\n }\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 priority: run.priority,\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 const currentStepId = current.currentStepId;\n const currentStepTimelineEntry =\n current.timeline[invokeChildWorkflowTimelineKey(currentStepId)];\n if (isInvokeChildWorkflowTimelineEntry(currentStepTimelineEntry)) {\n return current;\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 currentStepId = run.currentStepId;\n const currentStepTimelineEntry = run.timeline[invokeChildWorkflowTimelineKey(currentStepId)];\n if (isInvokeChildWorkflowTimelineEntry(currentStepTimelineEntry)) {\n return run;\n }\n\n const waitForEntry = run.timeline[waitForTimelineKey(currentStepId)];\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 [currentStepId]: {\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",
9
+ "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 = 7;\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 // On first run, we run a check to see if there is an existing foreign\n // `workflow_runs` table. To decide on that, we check if the `workflow_runs`\n // exists but a `workflow_schema_version` table doesn't. If that is true\n // then `workflow_runs` is foreign and we should fail lest we start\n // adding rows there, corrupting it. We also do the reverse check.\n // We are basing this off the fact that our transaction creates both or no tables\n // This is not airtight, but serves as an extra safety check for now.\n const existing = await db.executeSql(\n `SELECT\n to_regclass('workflow_runs') IS NOT NULL AS has_runs_table,\n to_regclass('workflow_schema_version') IS NOT NULL AS has_version_table`,\n [],\n );\n\n const row = existing.rows[0] as\n | { has_runs_table: boolean; has_version_table: boolean }\n | undefined;\n\n if (row?.has_runs_table && !row.has_version_table) {\n throw new Error(\n `pg-workflows: a \"workflow_runs\" table already exists in this schema but was not ` +\n `created by pg-workflows. Point the workflow engine at a dedicated schema/database.`,\n );\n }\n\n if (!row?.has_runs_table && row?.has_version_table) {\n throw new Error(\n `pg-workflows: a \"workflow_schema_version\" table already exists in this schema but was not ` +\n `created by pg-workflows. Point the workflow engine at a dedicated schema/database.`,\n );\n }\n\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 if (currentVersion < 4) {\n commands.push('ALTER TABLE workflow_runs ADD COLUMN IF NOT EXISTS parent_run_id varchar(32)');\n commands.push('ALTER TABLE workflow_runs ADD COLUMN IF NOT EXISTS parent_step_id varchar(256)');\n commands.push(\n 'ALTER TABLE workflow_runs ADD COLUMN IF NOT EXISTS parent_resource_id varchar(256)',\n );\n }\n\n if (currentVersion < 5) {\n commands.push(\n 'ALTER TABLE workflow_runs ADD COLUMN IF NOT EXISTS scheduled_at timestamp with time zone',\n );\n }\n\n if (currentVersion < 6) {\n commands.push(\n 'ALTER TABLE workflow_runs ADD COLUMN IF NOT EXISTS priority integer DEFAULT 0 NOT NULL',\n );\n }\n\n if (currentVersion < 7) {\n commands.push(\n 'ALTER TABLE workflow_runs ADD COLUMN IF NOT EXISTS singleton boolean DEFAULT false NOT NULL',\n );\n commands.push(`\n CREATE UNIQUE INDEX IF NOT EXISTS workflow_runs_singleton_active_idx\n ON workflow_runs (workflow_id)\n WHERE singleton AND status IN ('pending', 'running')\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",
10
+ "import ksuid from 'ksuid';\nimport type { Db } from 'pg-boss';\nimport { WorkflowRunInProgressError } from '../error';\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 priority: number;\n job_id: string | null;\n idempotency_key: string | null;\n parent_run_id: string | null;\n parent_step_id: string | null;\n parent_resource_id: string | null;\n scheduled_at: string | Date | null;\n singleton: boolean;\n};\n\nfunction isUniqueViolation(error: unknown): boolean {\n if (!error || typeof error !== 'object') {\n return false;\n }\n if ('code' in error && error.code === '23505') {\n return true;\n }\n const cause = 'cause' in error ? error.cause : undefined;\n return Boolean(cause && typeof cause === 'object' && 'code' in cause && cause.code === '23505');\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 priority: row.priority,\n jobId: row.job_id,\n idempotencyKey: row.idempotency_key,\n parentRunId: row.parent_run_id,\n parentStepId: row.parent_step_id,\n parentResourceId: row.parent_resource_id,\n scheduledAt: row.scheduled_at ? new Date(row.scheduled_at) : null,\n singleton: Boolean(row.singleton),\n };\n}\n\nexport async function insertWorkflowRun(\n {\n resourceId,\n workflowId,\n currentStepId,\n status,\n input,\n maxRetries,\n priority,\n timeoutAt,\n idempotencyKey,\n parentRunId,\n parentStepId,\n parentResourceId,\n scheduledAt,\n singleton = false,\n }: {\n resourceId?: string;\n workflowId: string;\n currentStepId: string;\n status: string;\n input: unknown;\n maxRetries: number;\n priority: number;\n timeoutAt: Date | null;\n idempotencyKey?: string;\n parentRunId?: string;\n parentStepId?: string;\n parentResourceId?: string;\n scheduledAt?: Date;\n singleton?: boolean;\n },\n db: Db,\n): Promise<{ run: WorkflowRun; created: boolean }> {\n const runId = generateKSUID('run');\n const now = new Date();\n\n if (singleton) {\n const active = await getActiveSingletonRun(workflowId, db);\n if (active) {\n throw new WorkflowRunInProgressError(workflowId, active.id);\n }\n }\n\n let result: { rows: WorkflowRunRow[] };\n try {\n 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 priority,\n timeout_at,\n created_at,\n updated_at,\n timeline,\n retry_count,\n idempotency_key,\n parent_run_id,\n parent_step_id,\n parent_resource_id,\n scheduled_at,\n singleton\n )\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)\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 priority,\n timeoutAt,\n now,\n now,\n '{}',\n 0,\n idempotencyKey ?? null,\n parentRunId ?? null,\n parentStepId ?? null,\n parentResourceId ?? null,\n scheduledAt ?? null,\n singleton,\n ],\n )) as { rows: WorkflowRunRow[] };\n } catch (error) {\n if (singleton && isUniqueViolation(error)) {\n const active = await getActiveSingletonRun(workflowId, db);\n throw new WorkflowRunInProgressError(workflowId, active?.id);\n }\n throw error;\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 getActiveSingletonRun(\n workflowId: string,\n db: Db,\n): Promise<WorkflowRun | null> {\n const result = await db.executeSql(\n `SELECT * FROM workflow_runs\n WHERE workflow_id = $1\n AND singleton\n AND status IN ('pending', 'running')\n LIMIT 1`,\n [workflowId],\n );\n\n return result.rows[0] ? mapRowToWorkflowRun(result.rows[0] as WorkflowRunRow) : null;\n}\n\nexport async function assertSingletonSlotAvailable(\n { workflowId, exceptRunId }: { workflowId: string; exceptRunId?: string },\n db: Db,\n): Promise<void> {\n const active = await getActiveSingletonRun(workflowId, db);\n if (active && active.id !== exceptRunId) {\n throw new WorkflowRunInProgressError(workflowId, active.id);\n }\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 getWorkflowLastRun(\n {\n workflowId,\n resourceId,\n }: {\n workflowId: string;\n resourceId?: string;\n },\n db: Db,\n): Promise<WorkflowRun | null> {\n const result = resourceId\n ? await db.executeSql(\n `SELECT * FROM workflow_runs\n WHERE workflow_id = $1 AND resource_id = $2\n ORDER BY created_at DESC\n LIMIT 1`,\n [workflowId, resourceId],\n )\n : await db.executeSql(\n `SELECT * FROM workflow_runs\n WHERE workflow_id = $1\n ORDER BY created_at DESC\n LIMIT 1`,\n [workflowId],\n );\n\n const run = result.rows[0];\n if (!run) {\n return null;\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 let result: { rows: WorkflowRunRow[] };\n try {\n result = (await db.executeSql(query, values)) as { rows: WorkflowRunRow[] };\n } catch (error) {\n if (data.status === 'running' && isUniqueViolation(error)) {\n throw new WorkflowRunInProgressError('unknown', runId);\n }\n throw error;\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 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",
11
+ "import { WorkflowEngineError } from './error';\n\n/**\n * Named priority levels mapped to pg-boss integer priorities. Higher numbers\n * are fetched first (pg-boss orders by `priority DESC`), and `normal = 0`\n * matches pg-boss's own default. The ±100 spacing leaves room for numeric\n * tuning between tiers via the escape hatch.\n */\nexport const PRIORITY_LEVELS = { high: 100, normal: 0, low: -100 } as const;\n\nexport type WorkflowPriority = keyof typeof PRIORITY_LEVELS | number;\n\nfunction priorityToInt(value: WorkflowPriority): number {\n if (typeof value === 'number') {\n if (!Number.isInteger(value)) {\n throw new WorkflowEngineError(\n `Invalid priority ${value}: numeric priority must be an integer.`,\n );\n }\n return value;\n }\n\n const mapped = PRIORITY_LEVELS[value];\n if (mapped === undefined) {\n throw new WorkflowEngineError(\n `Invalid priority \"${value}\": expected one of ${Object.keys(PRIORITY_LEVELS)\n .map((k) => `\"${k}\"`)\n .join(', ')} or an integer.`,\n );\n }\n return mapped;\n}\n\n/**\n * Resolve the effective priority from a precedence chain. The first defined\n * candidate wins (e.g. per-run override, then definition default, then an\n * inherited parent priority); when nothing is defined it falls back to\n * normal (0).\n */\nexport function resolvePriority(...candidates: (WorkflowPriority | undefined)[]): number {\n for (const candidate of candidates) {\n if (candidate !== undefined) {\n return priorityToInt(candidate);\n }\n }\n return PRIORITY_LEVELS.normal;\n}\n",
12
+ "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<\n TOutput = unknown,\n TInput extends InputParameters = InputParameters,\n>(\n id: string,\n options?: { inputSchema?: TInput; singleton?: boolean },\n): WorkflowRef<TInput, TOutput> {\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 priority: defineOptions?.priority,\n singleton: defineOptions?.singleton ?? options?.singleton,\n schedule: defineOptions?.schedule,\n timezone: defineOptions?.timezone,\n })) as WorkflowRef<TInput, TOutput>;\n\n Object.defineProperty(ref, 'id', { value: id, enumerable: true });\n Object.defineProperty(ref, 'inputSchema', {\n value: options?.inputSchema,\n enumerable: true,\n });\n Object.defineProperty(ref, 'singleton', {\n value: options?.singleton,\n enumerable: true,\n });\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 {\n inputSchema,\n timeout,\n retries,\n priority,\n singleton,\n schedule,\n timezone,\n }: 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 priority,\n singleton,\n schedule,\n timezone,\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"
13
+ ],
14
+ "mappings": "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",
15
+ "debugId": "779362C94AF314E764756E2164756E21",
16
+ "names": []
17
+ }
package/package.json CHANGED
@@ -1,8 +1,11 @@
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.13.2",
4
+ "version": "0.15.0",
5
5
  "type": "module",
6
+ "workspaces": [
7
+ "packages/*"
8
+ ],
6
9
  "files": [
7
10
  "dist"
8
11
  ],
@@ -34,9 +37,12 @@
34
37
  },
35
38
  "scripts": {
36
39
  "build": "bunup",
40
+ "build:ui": "bun run --filter '@pg-workflows/ui' build",
37
41
  "dev": "bunup --watch",
38
- "test": "bun run test:unit && bun run test:integration",
42
+ "test": "bun run test:unit && bun run test:ui && bun run test:integration",
39
43
  "test:unit": "vitest --typecheck run --config src/vitest.unit.config.ts ",
44
+ "test:ui": "bun run --filter '@pg-workflows/ui' test",
45
+ "check-types:ui": "bun run --filter '@pg-workflows/ui' check-types",
40
46
  "test:integration": "vitest run --config src/vitest.integration.config.ts",
41
47
  "test:watch": "vitest watch --config src/vitest.unit.config.ts",
42
48
  "lint": "biome check .",
@@ -82,7 +88,7 @@
82
88
  "es-toolkit": "^1.44.0",
83
89
  "ksuid": "^3.0.0",
84
90
  "parse-duration": "^2.1.5",
85
- "pg-boss": "^12.16.0",
91
+ "pg-boss": "^12.29.0",
86
92
  "typescript": "^5.9.3"
87
93
  },
88
94
  "peerDependencies": {