pg-workflows 0.14.0 → 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.
package/README.md CHANGED
@@ -54,6 +54,7 @@ That's it. Each step runs **exactly once**. Crash, redeploy, or retry - the work
54
54
  - **Schedules & polling built in** - `step.delay('3 days')`, `step.waitUntil('2025-01-01')`, `step.poll(...)` - no cron, no external scheduler.
55
55
  - **Built for AI agents** - cache expensive LLM calls, retry on 429s, pause for human review. [See AI patterns →](docs/ai-agents.md)
56
56
  - **Client/worker separation** - keep your API service light; run handlers in a worker. [See architecture →](docs/architecture.md)
57
+ - **Optional React UI** - browse runs and step timelines with [`@pg-workflows/ui`](packages/ui/README.md). Separate package, so workers never take a React peer.
57
58
  - **Idempotent starts** - pass an `idempotencyKey` and duplicate calls safely return the same run.
58
59
 
59
60
  ---
@@ -155,6 +156,7 @@ See [runnable examples](https://github.com/SokratisVidros/pg-workflows/tree/main
155
156
  - **[API Reference](docs/api-reference.md)** - `WorkflowEngine`, `WorkflowClient`, `WorkflowRef`, types
156
157
  - **[Configuration](docs/configuration.md)** - env vars, database setup, requirements
157
158
  - **[Observability](docs/observability.md)** - OpenTelemetry tracing via `otelPlugin`
159
+ - **[UI](packages/ui/README.md)** - `@pg-workflows/ui`: hooks and components for inspecting runs
158
160
 
159
161
  ---
160
162
 
@@ -67,6 +67,7 @@ __export(exports_client_entry, {
67
67
  createWorkflowRef: () => createWorkflowRef,
68
68
  WorkflowStatus: () => WorkflowStatus,
69
69
  WorkflowRunNotFoundError: () => WorkflowRunNotFoundError,
70
+ WorkflowRunInProgressError: () => WorkflowRunInProgressError,
70
71
  WorkflowEngineError: () => WorkflowEngineError,
71
72
  WorkflowClient: () => WorkflowClient
72
73
  });
@@ -94,7 +95,7 @@ var isInvokeChildWorkflowTimelineEntry = (entry) => !!entry && typeof entry ===
94
95
 
95
96
  // src/db/migration.ts
96
97
  var MIGRATION_LOCK_ID = 738291645;
97
- var CURRENT_SCHEMA_VERSION = 6;
98
+ var CURRENT_SCHEMA_VERSION = 7;
98
99
  async function runMigrations(db) {
99
100
  if (await isSchemaUpToDate(db)) {
100
101
  return;
@@ -173,6 +174,14 @@ async function runMigrations(db) {
173
174
  if (currentVersion < 6) {
174
175
  commands.push("ALTER TABLE workflow_runs ADD COLUMN IF NOT EXISTS priority integer DEFAULT 0 NOT NULL");
175
176
  }
177
+ if (currentVersion < 7) {
178
+ commands.push("ALTER TABLE workflow_runs ADD COLUMN IF NOT EXISTS singleton boolean DEFAULT false NOT NULL");
179
+ commands.push(`
180
+ CREATE UNIQUE INDEX IF NOT EXISTS workflow_runs_singleton_active_idx
181
+ ON workflow_runs (workflow_id)
182
+ WHERE singleton AND status IN ('pending', 'running')
183
+ `);
184
+ }
176
185
  if (currentVersion === 0) {
177
186
  commands.push(`INSERT INTO workflow_schema_version (version) VALUES (${CURRENT_SCHEMA_VERSION})`);
178
187
  } else {
@@ -212,9 +221,65 @@ async function getCurrentVersion(db) {
212
221
 
213
222
  // src/db/queries.ts
214
223
  var import_ksuid = __toESM(require("ksuid"));
224
+
225
+ // src/error.ts
226
+ function validateWorkflowId(workflowId) {
227
+ if (workflowId.length > MAX_WORKFLOW_ID_LENGTH) {
228
+ throw new WorkflowEngineError(`workflowId exceeds maximum length of ${MAX_WORKFLOW_ID_LENGTH} characters (got ${workflowId.length})`, workflowId);
229
+ }
230
+ }
231
+ function validateResourceId(resourceId) {
232
+ if (resourceId != null && resourceId.length > MAX_RESOURCE_ID_LENGTH) {
233
+ throw new WorkflowEngineError(`resourceId exceeds maximum length of ${MAX_RESOURCE_ID_LENGTH} characters (got ${resourceId.length})`);
234
+ }
235
+ }
236
+
237
+ class WorkflowEngineError extends Error {
238
+ workflowId;
239
+ runId;
240
+ cause;
241
+ issues;
242
+ constructor(message, workflowId, runId, cause = undefined, issues) {
243
+ super(message);
244
+ this.workflowId = workflowId;
245
+ this.runId = runId;
246
+ this.cause = cause;
247
+ this.issues = issues;
248
+ this.name = "WorkflowEngineError";
249
+ if (Error.captureStackTrace) {
250
+ Error.captureStackTrace(this, WorkflowEngineError);
251
+ }
252
+ }
253
+ }
254
+
255
+ class WorkflowRunNotFoundError extends WorkflowEngineError {
256
+ constructor(runId, workflowId) {
257
+ super("Workflow run not found", workflowId, runId);
258
+ this.name = "WorkflowRunNotFoundError";
259
+ }
260
+ }
261
+
262
+ class WorkflowRunInProgressError extends WorkflowEngineError {
263
+ constructor(workflowId, runId) {
264
+ super(`Workflow "${workflowId}" already has a running run; wait for it to pause, complete, fail, or be cancelled`, workflowId, runId);
265
+ this.name = "WorkflowRunInProgressError";
266
+ }
267
+ }
268
+
269
+ // src/db/queries.ts
215
270
  function generateKSUID(prefix) {
216
271
  return `${prefix ? `${prefix}_` : ""}${import_ksuid.default.randomSync().string}`;
217
272
  }
273
+ function isUniqueViolation(error) {
274
+ if (!error || typeof error !== "object") {
275
+ return false;
276
+ }
277
+ if ("code" in error && error.code === "23505") {
278
+ return true;
279
+ }
280
+ const cause = "cause" in error ? error.cause : undefined;
281
+ return Boolean(cause && typeof cause === "object" && "code" in cause && cause.code === "23505");
282
+ }
218
283
  function mapRowToWorkflowRun(row) {
219
284
  return {
220
285
  id: row.id,
@@ -240,7 +305,8 @@ function mapRowToWorkflowRun(row) {
240
305
  parentRunId: row.parent_run_id,
241
306
  parentStepId: row.parent_step_id,
242
307
  parentResourceId: row.parent_resource_id,
243
- scheduledAt: row.scheduled_at ? new Date(row.scheduled_at) : null
308
+ scheduledAt: row.scheduled_at ? new Date(row.scheduled_at) : null,
309
+ singleton: Boolean(row.singleton)
244
310
  };
245
311
  }
246
312
  async function insertWorkflowRun({
@@ -256,11 +322,20 @@ async function insertWorkflowRun({
256
322
  parentRunId,
257
323
  parentStepId,
258
324
  parentResourceId,
259
- scheduledAt
325
+ scheduledAt,
326
+ singleton = false
260
327
  }, db) {
261
328
  const runId = generateKSUID("run");
262
329
  const now = new Date;
263
- const result = await db.executeSql(`INSERT INTO workflow_runs (
330
+ if (singleton) {
331
+ const active = await getActiveSingletonRun(workflowId, db);
332
+ if (active) {
333
+ throw new WorkflowRunInProgressError(workflowId, active.id);
334
+ }
335
+ }
336
+ let result;
337
+ try {
338
+ result = await db.executeSql(`INSERT INTO workflow_runs (
264
339
  id,
265
340
  resource_id,
266
341
  workflow_id,
@@ -278,30 +353,39 @@ async function insertWorkflowRun({
278
353
  parent_run_id,
279
354
  parent_step_id,
280
355
  parent_resource_id,
281
- scheduled_at
356
+ scheduled_at,
357
+ singleton
282
358
  )
283
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)
359
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)
284
360
  ON CONFLICT (idempotency_key) WHERE idempotency_key IS NOT NULL DO NOTHING
285
361
  RETURNING *`, [
286
- runId,
287
- resourceId ?? null,
288
- workflowId,
289
- currentStepId,
290
- status,
291
- JSON.stringify(input),
292
- maxRetries,
293
- priority,
294
- timeoutAt,
295
- now,
296
- now,
297
- "{}",
298
- 0,
299
- idempotencyKey ?? null,
300
- parentRunId ?? null,
301
- parentStepId ?? null,
302
- parentResourceId ?? null,
303
- scheduledAt ?? null
304
- ]);
362
+ runId,
363
+ resourceId ?? null,
364
+ workflowId,
365
+ currentStepId,
366
+ status,
367
+ JSON.stringify(input),
368
+ maxRetries,
369
+ priority,
370
+ timeoutAt,
371
+ now,
372
+ now,
373
+ "{}",
374
+ 0,
375
+ idempotencyKey ?? null,
376
+ parentRunId ?? null,
377
+ parentStepId ?? null,
378
+ parentResourceId ?? null,
379
+ scheduledAt ?? null,
380
+ singleton
381
+ ]);
382
+ } catch (error) {
383
+ if (singleton && isUniqueViolation(error)) {
384
+ const active = await getActiveSingletonRun(workflowId, db);
385
+ throw new WorkflowRunInProgressError(workflowId, active?.id);
386
+ }
387
+ throw error;
388
+ }
305
389
  if (result.rows[0]) {
306
390
  return { run: mapRowToWorkflowRun(result.rows[0]), created: true };
307
391
  }
@@ -313,6 +397,20 @@ async function insertWorkflowRun({
313
397
  }
314
398
  return { run: mapRowToWorkflowRun(existing.rows[0]), created: false };
315
399
  }
400
+ async function getActiveSingletonRun(workflowId, db) {
401
+ const result = await db.executeSql(`SELECT * FROM workflow_runs
402
+ WHERE workflow_id = $1
403
+ AND singleton
404
+ AND status IN ('pending', 'running')
405
+ LIMIT 1`, [workflowId]);
406
+ return result.rows[0] ? mapRowToWorkflowRun(result.rows[0]) : null;
407
+ }
408
+ async function assertSingletonSlotAvailable({ workflowId, exceptRunId }, db) {
409
+ const active = await getActiveSingletonRun(workflowId, db);
410
+ if (active && active.id !== exceptRunId) {
411
+ throw new WorkflowRunInProgressError(workflowId, active.id);
412
+ }
413
+ }
316
414
  async function getWorkflowRun({
317
415
  runId,
318
416
  resourceId
@@ -427,7 +525,15 @@ async function updateWorkflowRun({
427
525
  ${whereClause}
428
526
  RETURNING *
429
527
  `;
430
- const result = await db.executeSql(query, values);
528
+ let result;
529
+ try {
530
+ result = await db.executeSql(query, values);
531
+ } catch (error) {
532
+ if (data.status === "running" && isUniqueViolation(error)) {
533
+ throw new WorkflowRunInProgressError("unknown", runId);
534
+ }
535
+ throw error;
536
+ }
431
537
  const run = result.rows[0];
432
538
  if (!run) {
433
539
  return null;
@@ -533,43 +639,6 @@ async function withPostgresTransaction(db, callback, pool) {
533
639
  }
534
640
  }
535
641
 
536
- // src/error.ts
537
- function validateWorkflowId(workflowId) {
538
- if (workflowId.length > MAX_WORKFLOW_ID_LENGTH) {
539
- throw new WorkflowEngineError(`workflowId exceeds maximum length of ${MAX_WORKFLOW_ID_LENGTH} characters (got ${workflowId.length})`, workflowId);
540
- }
541
- }
542
- function validateResourceId(resourceId) {
543
- if (resourceId != null && resourceId.length > MAX_RESOURCE_ID_LENGTH) {
544
- throw new WorkflowEngineError(`resourceId exceeds maximum length of ${MAX_RESOURCE_ID_LENGTH} characters (got ${resourceId.length})`);
545
- }
546
- }
547
-
548
- class WorkflowEngineError extends Error {
549
- workflowId;
550
- runId;
551
- cause;
552
- issues;
553
- constructor(message, workflowId, runId, cause = undefined, issues) {
554
- super(message);
555
- this.workflowId = workflowId;
556
- this.runId = runId;
557
- this.cause = cause;
558
- this.issues = issues;
559
- this.name = "WorkflowEngineError";
560
- if (Error.captureStackTrace) {
561
- Error.captureStackTrace(this, WorkflowEngineError);
562
- }
563
- }
564
- }
565
-
566
- class WorkflowRunNotFoundError extends WorkflowEngineError {
567
- constructor(runId, workflowId) {
568
- super("Workflow run not found", workflowId, runId);
569
- this.name = "WorkflowRunNotFoundError";
570
- }
571
- }
572
-
573
642
  // src/priority.ts
574
643
  var PRIORITY_LEVELS = { high: 100, normal: 0, low: -100 };
575
644
  function priorityToInt(value) {
@@ -644,11 +713,10 @@ class WorkflowClient {
644
713
  const db = {
645
714
  executeSql: (text, values) => this.pool.query(text, values)
646
715
  };
647
- if (boss) {
648
- this.boss = boss;
649
- } else {
650
- this.boss = new import_pg_boss.PgBoss({ db, schema: DEFAULT_PGBOSS_SCHEMA });
651
- }
716
+ this.boss = boss ?? new import_pg_boss.PgBoss({ db, schema: DEFAULT_PGBOSS_SCHEMA });
717
+ this.boss.on("error", (error) => {
718
+ this.logger.error("pg-boss error", error);
719
+ });
652
720
  this.db = db;
653
721
  }
654
722
  async start() {
@@ -677,6 +745,7 @@ class WorkflowClient {
677
745
  let resourceId;
678
746
  let idempotencyKey;
679
747
  let options;
748
+ let singleton = false;
680
749
  if (typeof refOrParams === "function" && "id" in refOrParams) {
681
750
  const ref = refOrParams;
682
751
  workflowId = ref.id;
@@ -684,6 +753,7 @@ class WorkflowClient {
684
753
  options = optionsArg;
685
754
  resourceId = optionsArg?.resourceId;
686
755
  idempotencyKey = optionsArg?.idempotencyKey;
756
+ singleton = optionsArg?.singleton ?? ref.singleton === true;
687
757
  if (ref.inputSchema) {
688
758
  const result = await ref.inputSchema["~standard"].validate(input);
689
759
  if (result.issues) {
@@ -697,6 +767,7 @@ class WorkflowClient {
697
767
  resourceId = params.resourceId;
698
768
  idempotencyKey = params.idempotencyKey;
699
769
  options = params.options;
770
+ singleton = params.options?.singleton === true;
700
771
  }
701
772
  validateWorkflowId(workflowId);
702
773
  validateResourceId(resourceId);
@@ -711,7 +782,8 @@ class WorkflowClient {
711
782
  maxRetries: options?.retries ?? 0,
712
783
  priority: resolvePriority(options?.priority),
713
784
  timeoutAt,
714
- idempotencyKey
785
+ idempotencyKey,
786
+ singleton
715
787
  }, _db);
716
788
  if (created) {
717
789
  const job = {
@@ -741,6 +813,9 @@ class WorkflowClient {
741
813
  }) {
742
814
  await this.ensureStarted();
743
815
  const run = await this.getRun({ runId, resourceId });
816
+ if (run.singleton) {
817
+ await assertSingletonSlotAvailable({ workflowId: run.workflowId, exceptRunId: run.id }, this.db);
818
+ }
744
819
  const job = {
745
820
  runId: run.id,
746
821
  resourceId: resourceId ?? run.resourceId ?? undefined,
@@ -933,6 +1008,7 @@ function createWorkflowRef(id, options) {
933
1008
  timeout: defineOptions?.timeout,
934
1009
  retries: defineOptions?.retries,
935
1010
  priority: defineOptions?.priority,
1011
+ singleton: defineOptions?.singleton ?? options?.singleton,
936
1012
  schedule: defineOptions?.schedule,
937
1013
  timezone: defineOptions?.timezone
938
1014
  });
@@ -941,16 +1017,29 @@ function createWorkflowRef(id, options) {
941
1017
  value: options?.inputSchema,
942
1018
  enumerable: true
943
1019
  });
1020
+ Object.defineProperty(ref, "singleton", {
1021
+ value: options?.singleton,
1022
+ enumerable: true
1023
+ });
944
1024
  return ref;
945
1025
  }
946
1026
  function createWorkflowFactory(plugins = []) {
947
- const factory = (id, handler, { inputSchema, timeout, retries, priority, schedule, timezone } = {}) => ({
1027
+ const factory = (id, handler, {
1028
+ inputSchema,
1029
+ timeout,
1030
+ retries,
1031
+ priority,
1032
+ singleton,
1033
+ schedule,
1034
+ timezone
1035
+ } = {}) => ({
948
1036
  id,
949
1037
  handler,
950
1038
  inputSchema,
951
1039
  timeout,
952
1040
  retries,
953
1041
  priority,
1042
+ singleton,
954
1043
  schedule,
955
1044
  timezone,
956
1045
  plugins: plugins.length > 0 ? plugins : undefined
@@ -964,5 +1053,5 @@ function createWorkflowFactory(plugins = []) {
964
1053
  }
965
1054
  var workflow = createWorkflowFactory();
966
1055
 
967
- //# debugId=65B5E13A5C10F50064756E2164756E21
1056
+ //# debugId=9B37033329AD266364756E2164756E21
968
1057
  //# sourceMappingURL=client.entry.js.map
@@ -20,6 +20,13 @@ type WorkflowRun = {
20
20
  maxRetries: number;
21
21
  /** Resolved scheduling priority (pg-boss integer; higher runs first). */
22
22
  priority: number;
23
+ /**
24
+ * When true, this run participates in the per-workflow-ID uniqueness
25
+ * constraint: no other pending or running singleton run of the same
26
+ * workflow ID may exist at the same time. Paused, completed, failed, and
27
+ * cancelled runs release the slot.
28
+ */
29
+ singleton: boolean;
23
30
  jobId: string | null;
24
31
  idempotencyKey: string | null;
25
32
  parentRunId: string | null;
@@ -67,6 +74,12 @@ type StartWorkflowOptions = {
67
74
  expireInSeconds?: number;
68
75
  idempotencyKey?: string;
69
76
  priority?: WorkflowPriority;
77
+ /**
78
+ * Client-side counterpart of `workflow(..., { singleton: true })`.
79
+ * The engine reads this from the registered definition; pass it here when
80
+ * starting from `WorkflowClient` so the uniqueness constraint applies.
81
+ */
82
+ singleton?: boolean;
70
83
  };
71
84
  type WorkflowOptions<I extends InputParameters> = {
72
85
  timeout?: number;
@@ -74,6 +87,12 @@ type WorkflowOptions<I extends InputParameters> = {
74
87
  inputSchema?: I;
75
88
  priority?: WorkflowPriority;
76
89
  /**
90
+ * When true, at most one pending or running run of this workflow ID may exist.
91
+ * A second `startWorkflow` throws `WorkflowRunInProgressError` until the
92
+ * current run pauses, completes, fails, or is cancelled.
93
+ */
94
+ singleton?: boolean;
95
+ /**
77
96
  * Recurring schedule. Accepts a cron expression (`'0 9 * * 1-5'`),
78
97
  * a duration string (`'5m'`, `'1 hour'`), or a `DurationObject`.
79
98
  */
@@ -181,6 +200,7 @@ type WorkflowDefinition<TInput extends InputParameters = InputParameters> = {
181
200
  timeout?: number;
182
201
  retries?: number;
183
202
  priority?: WorkflowPriority;
203
+ singleton?: boolean;
184
204
  schedule?: Schedule;
185
205
  timezone?: string;
186
206
  plugins?: WorkflowPlugin[];
@@ -199,6 +219,7 @@ interface WorkflowRef<
199
219
  (handler: (context: WorkflowContext<TInput, StepBaseContext>) => Promise<unknown>, options?: Omit<WorkflowOptions<TInput>, "inputSchema">): WorkflowDefinition<TInput>;
200
220
  readonly id: string;
201
221
  readonly inputSchema?: TInput;
222
+ readonly singleton?: boolean;
202
223
  }
203
224
  type WorkflowRunProgress = WorkflowRun & {
204
225
  completionPercentage: number;
@@ -305,6 +326,7 @@ declare function createWorkflowRef<
305
326
  TInput extends InputParameters = InputParameters
306
327
  >(id: string, options?: {
307
328
  inputSchema?: TInput;
329
+ singleton?: boolean;
308
330
  }): WorkflowRef<TInput, TOutput>;
309
331
  import { StandardSchemaV1 as StandardSchemaV12 } from "@standard-schema/spec";
310
332
  declare class WorkflowEngineError extends Error {
@@ -317,4 +339,7 @@ declare class WorkflowEngineError extends Error {
317
339
  declare class WorkflowRunNotFoundError extends WorkflowEngineError {
318
340
  constructor(runId?: string, workflowId?: string);
319
341
  }
320
- export { createWorkflowRef, WorkflowStatus, WorkflowRunProgress, WorkflowRunNotFoundError, WorkflowRun, WorkflowRef, WorkflowLogger, WorkflowEngineError, WorkflowClientOptions, WorkflowClient, StartWorkflowOptions, InputParameters, InferInputParameters };
342
+ declare class WorkflowRunInProgressError extends WorkflowEngineError {
343
+ constructor(workflowId: string, runId?: string);
344
+ }
345
+ export { createWorkflowRef, WorkflowStatus, WorkflowRunProgress, WorkflowRunNotFoundError, WorkflowRunInProgressError, WorkflowRun, WorkflowRef, WorkflowLogger, WorkflowEngineError, WorkflowClientOptions, WorkflowClient, StartWorkflowOptions, InputParameters, InferInputParameters };
@@ -20,6 +20,13 @@ type WorkflowRun = {
20
20
  maxRetries: number;
21
21
  /** Resolved scheduling priority (pg-boss integer; higher runs first). */
22
22
  priority: number;
23
+ /**
24
+ * When true, this run participates in the per-workflow-ID uniqueness
25
+ * constraint: no other pending or running singleton run of the same
26
+ * workflow ID may exist at the same time. Paused, completed, failed, and
27
+ * cancelled runs release the slot.
28
+ */
29
+ singleton: boolean;
23
30
  jobId: string | null;
24
31
  idempotencyKey: string | null;
25
32
  parentRunId: string | null;
@@ -67,6 +74,12 @@ type StartWorkflowOptions = {
67
74
  expireInSeconds?: number;
68
75
  idempotencyKey?: string;
69
76
  priority?: WorkflowPriority;
77
+ /**
78
+ * Client-side counterpart of `workflow(..., { singleton: true })`.
79
+ * The engine reads this from the registered definition; pass it here when
80
+ * starting from `WorkflowClient` so the uniqueness constraint applies.
81
+ */
82
+ singleton?: boolean;
70
83
  };
71
84
  type WorkflowOptions<I extends InputParameters> = {
72
85
  timeout?: number;
@@ -74,6 +87,12 @@ type WorkflowOptions<I extends InputParameters> = {
74
87
  inputSchema?: I;
75
88
  priority?: WorkflowPriority;
76
89
  /**
90
+ * When true, at most one pending or running run of this workflow ID may exist.
91
+ * A second `startWorkflow` throws `WorkflowRunInProgressError` until the
92
+ * current run pauses, completes, fails, or is cancelled.
93
+ */
94
+ singleton?: boolean;
95
+ /**
77
96
  * Recurring schedule. Accepts a cron expression (`'0 9 * * 1-5'`),
78
97
  * a duration string (`'5m'`, `'1 hour'`), or a `DurationObject`.
79
98
  */
@@ -181,6 +200,7 @@ type WorkflowDefinition<TInput extends InputParameters = InputParameters> = {
181
200
  timeout?: number;
182
201
  retries?: number;
183
202
  priority?: WorkflowPriority;
203
+ singleton?: boolean;
184
204
  schedule?: Schedule;
185
205
  timezone?: string;
186
206
  plugins?: WorkflowPlugin[];
@@ -199,6 +219,7 @@ interface WorkflowRef<
199
219
  (handler: (context: WorkflowContext<TInput, StepBaseContext>) => Promise<unknown>, options?: Omit<WorkflowOptions<TInput>, "inputSchema">): WorkflowDefinition<TInput>;
200
220
  readonly id: string;
201
221
  readonly inputSchema?: TInput;
222
+ readonly singleton?: boolean;
202
223
  }
203
224
  type WorkflowRunProgress = WorkflowRun & {
204
225
  completionPercentage: number;
@@ -305,6 +326,7 @@ declare function createWorkflowRef<
305
326
  TInput extends InputParameters = InputParameters
306
327
  >(id: string, options?: {
307
328
  inputSchema?: TInput;
329
+ singleton?: boolean;
308
330
  }): WorkflowRef<TInput, TOutput>;
309
331
  import { StandardSchemaV1 as StandardSchemaV12 } from "@standard-schema/spec";
310
332
  declare class WorkflowEngineError extends Error {
@@ -317,4 +339,7 @@ declare class WorkflowEngineError extends Error {
317
339
  declare class WorkflowRunNotFoundError extends WorkflowEngineError {
318
340
  constructor(runId?: string, workflowId?: string);
319
341
  }
320
- export { createWorkflowRef, WorkflowStatus, WorkflowRunProgress, WorkflowRunNotFoundError, WorkflowRun, WorkflowRef, WorkflowLogger, WorkflowEngineError, WorkflowClientOptions, WorkflowClient, StartWorkflowOptions, InputParameters, InferInputParameters };
342
+ declare class WorkflowRunInProgressError extends WorkflowEngineError {
343
+ constructor(workflowId: string, runId?: string);
344
+ }
345
+ export { createWorkflowRef, WorkflowStatus, WorkflowRunProgress, WorkflowRunNotFoundError, WorkflowRunInProgressError, WorkflowRun, WorkflowRef, WorkflowLogger, WorkflowEngineError, WorkflowClientOptions, WorkflowClient, StartWorkflowOptions, InputParameters, InferInputParameters };
@@ -1,17 +1,19 @@
1
1
  import {
2
2
  WorkflowClient,
3
3
  WorkflowEngineError,
4
+ WorkflowRunInProgressError,
4
5
  WorkflowRunNotFoundError,
5
6
  WorkflowStatus,
6
7
  createWorkflowRef
7
- } from "./shared/chunk-w3qcrrwx.js";
8
+ } from "./shared/chunk-n0f7hd40.js";
8
9
  export {
9
10
  createWorkflowRef,
10
11
  WorkflowStatus,
11
12
  WorkflowRunNotFoundError,
13
+ WorkflowRunInProgressError,
12
14
  WorkflowEngineError,
13
15
  WorkflowClient
14
16
  };
15
17
 
16
- //# debugId=64DD8F1F4DBCBD8C64756E2164756E21
18
+ //# debugId=2B13F4A442F0A3AD64756E2164756E21
17
19
  //# sourceMappingURL=client.entry.js.map