pg-workflows 0.1.2 → 0.2.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
@@ -31,6 +31,7 @@ Most workflow engines ask you to adopt an entirely new platform - a new runtime,
31
31
  - You already run **PostgreSQL** and want to add durable workflows without new services
32
32
  - You need a **lightweight, self-hosted** workflow engine with zero operational overhead
33
33
  - You want **event-driven orchestration** (pause, resume, wait for external signals)
34
+ - You're building **AI agents or LLM pipelines** that need durable execution, retries, and human-in-the-loop
34
35
  - You're building with **TypeScript/Node.js** and want a native developer experience
35
36
 
36
37
  ### When to consider alternatives
@@ -165,15 +166,176 @@ console.log(`Progress: ${progress.completionPercentage}%`);
165
166
 
166
167
  ## What Can You Build?
167
168
 
169
+ - **AI Agents & LLM Pipelines** - Build durable AI agents that survive crashes, retry on flaky LLM APIs, and pause for human-in-the-loop review. [See examples below.](#ai--agent-workflows)
168
170
  - **User Onboarding Flows** - Multi-step signup sequences with email verification, waiting for user actions, and conditional paths.
169
171
  - **Payment & Checkout Pipelines** - Durable payment processing that survives failures, with automatic retries and event-driven confirmations.
170
- - **AI & LLM Pipelines** - Chain LLM calls with built-in retries for flaky APIs. Persist intermediate results across steps.
171
172
  - **Background Job Orchestration** - Replace fragile cron jobs with durable, observable workflows that track progress.
172
173
  - **Approval Workflows** - Pause execution and wait for human approval events before proceeding.
173
174
  - **Data Processing Pipelines** - ETL workflows with step-by-step execution, error handling, and progress monitoring.
174
175
 
175
176
  ---
176
177
 
178
+ ## AI & Agent Workflows
179
+
180
+ AI agents and LLM pipelines are one of the best use cases for durable execution. LLM calls are **slow**, **expensive**, and **unreliable** - exactly the kind of work that should never be repeated unnecessarily. pg-workflows gives you:
181
+
182
+ - **Cached step results** - If your process crashes after a $0.50 GPT-4 call, the result is already persisted. On retry, it skips the LLM call and picks up where it left off.
183
+ - **Automatic retries** - LLM APIs return 429s and 500s. Built-in exponential backoff handles transient failures without custom retry logic.
184
+ - **Human-in-the-loop** - Pause an AI pipeline with `step.waitFor()` to wait for human review, approval, or feedback before continuing.
185
+ - **Observable progress** - Track which step your agent is on, how far along it is, and inspect intermediate results with `checkProgress()`.
186
+ - **Long-running agents** - Multi-step agents that run for minutes or hours don't need to hold a connection open. They persist state and resume.
187
+
188
+ ### Example: Multi-Step AI Agent
189
+
190
+ ```typescript
191
+ const researchAgent = workflow(
192
+ 'research-agent',
193
+ async ({ step, input }) => {
194
+ // Step 1: Plan the research (persisted - never re-runs on retry)
195
+ const plan = await step.run('create-plan', async () => {
196
+ return await llm.chat({
197
+ model: 'gpt-4o',
198
+ messages: [{ role: 'user', content: `Create a research plan for: ${input.topic}` }],
199
+ });
200
+ });
201
+
202
+ // Step 2: Execute each research task durably
203
+ const findings = [];
204
+ for (const task of plan.tasks) {
205
+ const result = await step.run(`research-${task.id}`, async () => {
206
+ return await llm.chat({
207
+ model: 'gpt-4o',
208
+ messages: [{ role: 'user', content: `Research: ${task.description}` }],
209
+ });
210
+ });
211
+ findings.push(result);
212
+ }
213
+
214
+ // Step 3: Synthesize results
215
+ const report = await step.run('synthesize', async () => {
216
+ return await llm.chat({
217
+ model: 'gpt-4o',
218
+ messages: [{ role: 'user', content: `Synthesize these findings: ${JSON.stringify(findings)}` }],
219
+ });
220
+ });
221
+
222
+ return { plan, findings, report };
223
+ },
224
+ {
225
+ retries: 3,
226
+ timeout: 30 * 60 * 1000, // 30 minutes
227
+ }
228
+ );
229
+ ```
230
+
231
+ If the process crashes after completing 3 of 5 research tasks, the agent **resumes from task 4** - no LLM calls are wasted.
232
+
233
+ ### Example: Human-in-the-Loop AI Pipeline
234
+
235
+ ```typescript
236
+ const contentPipeline = workflow(
237
+ 'ai-content-pipeline',
238
+ async ({ step, input }) => {
239
+ // Step 1: Generate draft with AI
240
+ const draft = await step.run('generate-draft', async () => {
241
+ return await llm.chat({
242
+ model: 'gpt-4o',
243
+ messages: [{ role: 'user', content: `Write a blog post about: ${input.topic}` }],
244
+ });
245
+ });
246
+
247
+ // Step 2: Pause for human review - costs nothing while waiting
248
+ const review = await step.waitFor('human-review', {
249
+ eventName: 'content-reviewed',
250
+ timeout: 7 * 24 * 60 * 60 * 1000, // 7 days
251
+ });
252
+
253
+ // Step 3: Revise based on feedback
254
+ if (review.approved) {
255
+ return { status: 'published', content: draft };
256
+ }
257
+
258
+ const revision = await step.run('revise-draft', async () => {
259
+ return await llm.chat({
260
+ model: 'gpt-4o',
261
+ messages: [
262
+ { role: 'user', content: `Revise this draft based on feedback:\n\nDraft: ${draft}\n\nFeedback: ${review.feedback}` },
263
+ ],
264
+ });
265
+ });
266
+
267
+ return { status: 'revised', content: revision };
268
+ },
269
+ { retries: 3 }
270
+ );
271
+
272
+ // A reviewer approves or requests changes via your API
273
+ await engine.triggerEvent({
274
+ runId: run.id,
275
+ eventName: 'content-reviewed',
276
+ data: { approved: false, feedback: 'Make the intro more engaging' },
277
+ });
278
+ ```
279
+
280
+ ### Example: RAG Pipeline with Tool Use
281
+
282
+ ```typescript
283
+ const ragAgent = workflow(
284
+ 'rag-agent',
285
+ async ({ step, input }) => {
286
+ // Step 1: Generate embeddings (cached on retry)
287
+ const embedding = await step.run('embed-query', async () => {
288
+ return await openai.embeddings.create({
289
+ model: 'text-embedding-3-small',
290
+ input: input.query,
291
+ });
292
+ });
293
+
294
+ // Step 2: Search vector store
295
+ const documents = await step.run('search-docs', async () => {
296
+ return await vectorStore.search(embedding, { topK: 10 });
297
+ });
298
+
299
+ // Step 3: Generate answer with context
300
+ const answer = await step.run('generate-answer', async () => {
301
+ return await llm.chat({
302
+ model: 'gpt-4o',
303
+ messages: [
304
+ { role: 'system', content: `Answer using these documents:\n${documents.map(d => d.text).join('\n')}` },
305
+ { role: 'user', content: input.query },
306
+ ],
307
+ });
308
+ });
309
+
310
+ // Step 4: Validate and fact-check
311
+ const validation = await step.run('fact-check', async () => {
312
+ return await llm.chat({
313
+ model: 'gpt-4o',
314
+ messages: [
315
+ { role: 'user', content: `Fact-check this answer against the source documents. Answer: ${answer}` },
316
+ ],
317
+ });
318
+ });
319
+
320
+ return { answer, validation, sources: documents };
321
+ },
322
+ { retries: 3, timeout: 5 * 60 * 1000 }
323
+ );
324
+ ```
325
+
326
+ ### Why Durable Execution Matters for AI
327
+
328
+ | Problem | Without pg-workflows | With pg-workflows |
329
+ |---------|---------------------|-------------------|
330
+ | Process crashes mid-pipeline | All LLM calls re-run from scratch | Resumes from the last completed step |
331
+ | LLM API returns 429/500 | Manual retry logic everywhere | Automatic retries with exponential backoff |
332
+ | Human review needed | Custom polling/webhook infrastructure | `step.waitFor()` - zero resource consumption while waiting |
333
+ | Debugging failed agents | Lost intermediate state | Full timeline of every step's input/output in PostgreSQL |
334
+ | Cost control | Repeated expensive LLM calls on failure | Each LLM call runs exactly once, result cached |
335
+ | Long-running pipelines | Timeout or lost connections | Runs for hours/days, state persisted in Postgres |
336
+
337
+ ---
338
+
177
339
  ## Core Concepts
178
340
 
179
341
  ### Workflows
@@ -218,10 +380,10 @@ const eventData = await step.waitFor('wait-step', {
218
380
 
219
381
  ### Resource ID
220
382
 
221
- The optional `resourceId` associates a workflow run with an external entity in your application a user, an order, a subscription, or any domain object the workflow operates on. It serves two purposes:
383
+ The optional `resourceId` associates a workflow run with an external entity in your application - a user, an order, a subscription, or any domain object the workflow operates on. It serves two purposes:
222
384
 
223
- 1. **Association** Links each workflow run to the business entity it belongs to, so you can query all runs for a given resource.
224
- 2. **Scoping** When provided, all read and write operations (get, update, pause, resume, cancel, trigger events) include `resource_id` in their database queries, ensuring you only access workflow runs that belong to that resource. This is useful for enforcing tenant isolation or ownership checks.
385
+ 1. **Association** - Links each workflow run to the business entity it belongs to, so you can query all runs for a given resource.
386
+ 2. **Scoping** - When provided, all read and write operations (get, update, pause, resume, cancel, trigger events) include `resource_id` in their database queries, ensuring you only access workflow runs that belong to that resource. This is useful for enforcing tenant isolation or ownership checks.
225
387
 
226
388
  `resourceId` is optional on every API method. If you don't need to group or scope runs by an external entity, you can omit it entirely and use `runId` alone.
227
389
 
package/dist/index.cjs CHANGED
@@ -110,7 +110,7 @@ function parseWorkflowHandler(handler) {
110
110
  const propertyAccess = node.expression;
111
111
  const objectName = propertyAccess.expression.getText(sourceFile);
112
112
  const methodName = propertyAccess.name.text;
113
- if (objectName === "step" && (methodName === "run" || methodName === "waitFor" || methodName === "pause")) {
113
+ if (objectName === "step" && (methodName === "run" || methodName === "waitFor" || methodName === "pause" || methodName === "waitUntil")) {
114
114
  const firstArg = node.arguments[0];
115
115
  if (firstArg) {
116
116
  const { id, isDynamic } = extractStepId(firstArg);
@@ -825,8 +825,15 @@ class WorkflowEngine {
825
825
  timeout
826
826
  });
827
827
  },
828
- waitUntil: async ({ date }) => {
829
- return this.waitUntil(runId, date);
828
+ waitUntil: async (stepId, { date }) => {
829
+ if (!run) {
830
+ throw new WorkflowEngineError("Missing workflow run", workflowId, runId);
831
+ }
832
+ await this.waitUntilDate({
833
+ run,
834
+ stepId,
835
+ date
836
+ });
830
837
  },
831
838
  pause: async (stepId) => {
832
839
  if (!run) {
@@ -875,7 +882,10 @@ class WorkflowEngine {
875
882
  workflowId,
876
883
  input
877
884
  };
878
- await this.boss?.send("workflow-run", pgBossJob, { retryDelay });
885
+ await this.boss?.send("workflow-run", pgBossJob, {
886
+ startAfter: new Date(Date.now() + retryDelay),
887
+ expireInSeconds: defaultExpireInSeconds
888
+ });
879
889
  return;
880
890
  }
881
891
  await this.updateRun({
@@ -1011,8 +1021,35 @@ ${error.stack}` : String(error)
1011
1021
  eventName: PAUSE_EVENT_NAME
1012
1022
  });
1013
1023
  }
1014
- async waitUntil(runId, _date) {
1015
- throw new WorkflowEngineError("Not implemented yet", undefined, runId);
1024
+ async waitUntilDate({
1025
+ run,
1026
+ stepId,
1027
+ date
1028
+ }) {
1029
+ const eventName = `__wait_until_${stepId}`;
1030
+ await this.waitForEvent({
1031
+ run,
1032
+ stepId,
1033
+ eventName
1034
+ });
1035
+ const job = {
1036
+ runId: run.id,
1037
+ resourceId: run.resourceId ?? undefined,
1038
+ workflowId: run.workflowId,
1039
+ input: run.input,
1040
+ event: {
1041
+ name: eventName,
1042
+ data: { date: date.toISOString() }
1043
+ }
1044
+ };
1045
+ await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {
1046
+ startAfter: date,
1047
+ expireInSeconds: defaultExpireInSeconds
1048
+ });
1049
+ this.logger.log(`Running step ${stepId}, waiting until ${date.toISOString()}...`, {
1050
+ runId: run.id,
1051
+ workflowId: run.workflowId
1052
+ });
1016
1053
  }
1017
1054
  async checkIfHasStarted() {
1018
1055
  if (!this._started) {
@@ -1052,5 +1089,5 @@ ${error.stack}` : String(error)
1052
1089
  }
1053
1090
  }
1054
1091
 
1055
- //# debugId=738B5C3F90E7864264756E2164756E21
1092
+ //# debugId=EB7CB5376BB0770264756E2164756E21
1056
1093
  //# sourceMappingURL=index.js.map
package/dist/index.d.cts CHANGED
@@ -172,7 +172,7 @@ declare class WorkflowEngine {
172
172
  private runStep;
173
173
  private waitForEvent;
174
174
  private pauseStep;
175
- private waitUntil;
175
+ private waitUntilDate;
176
176
  private checkIfHasStarted;
177
177
  private buildLogger;
178
178
  getRuns({ resourceId, startingAfter, endingBefore, limit, statuses, workflowId }: {
package/dist/index.d.ts CHANGED
@@ -172,7 +172,7 @@ declare class WorkflowEngine {
172
172
  private runStep;
173
173
  private waitForEvent;
174
174
  private pauseStep;
175
- private waitUntil;
175
+ private waitUntilDate;
176
176
  private checkIfHasStarted;
177
177
  private buildLogger;
178
178
  getRuns({ resourceId, startingAfter, endingBefore, limit, statuses, workflowId }: {
package/dist/index.js CHANGED
@@ -56,7 +56,7 @@ function parseWorkflowHandler(handler) {
56
56
  const propertyAccess = node.expression;
57
57
  const objectName = propertyAccess.expression.getText(sourceFile);
58
58
  const methodName = propertyAccess.name.text;
59
- if (objectName === "step" && (methodName === "run" || methodName === "waitFor" || methodName === "pause")) {
59
+ if (objectName === "step" && (methodName === "run" || methodName === "waitFor" || methodName === "pause" || methodName === "waitUntil")) {
60
60
  const firstArg = node.arguments[0];
61
61
  if (firstArg) {
62
62
  const { id, isDynamic } = extractStepId(firstArg);
@@ -771,8 +771,15 @@ class WorkflowEngine {
771
771
  timeout
772
772
  });
773
773
  },
774
- waitUntil: async ({ date }) => {
775
- return this.waitUntil(runId, date);
774
+ waitUntil: async (stepId, { date }) => {
775
+ if (!run) {
776
+ throw new WorkflowEngineError("Missing workflow run", workflowId, runId);
777
+ }
778
+ await this.waitUntilDate({
779
+ run,
780
+ stepId,
781
+ date
782
+ });
776
783
  },
777
784
  pause: async (stepId) => {
778
785
  if (!run) {
@@ -821,7 +828,10 @@ class WorkflowEngine {
821
828
  workflowId,
822
829
  input
823
830
  };
824
- await this.boss?.send("workflow-run", pgBossJob, { retryDelay });
831
+ await this.boss?.send("workflow-run", pgBossJob, {
832
+ startAfter: new Date(Date.now() + retryDelay),
833
+ expireInSeconds: defaultExpireInSeconds
834
+ });
825
835
  return;
826
836
  }
827
837
  await this.updateRun({
@@ -957,8 +967,35 @@ ${error.stack}` : String(error)
957
967
  eventName: PAUSE_EVENT_NAME
958
968
  });
959
969
  }
960
- async waitUntil(runId, _date) {
961
- throw new WorkflowEngineError("Not implemented yet", undefined, runId);
970
+ async waitUntilDate({
971
+ run,
972
+ stepId,
973
+ date
974
+ }) {
975
+ const eventName = `__wait_until_${stepId}`;
976
+ await this.waitForEvent({
977
+ run,
978
+ stepId,
979
+ eventName
980
+ });
981
+ const job = {
982
+ runId: run.id,
983
+ resourceId: run.resourceId ?? undefined,
984
+ workflowId: run.workflowId,
985
+ input: run.input,
986
+ event: {
987
+ name: eventName,
988
+ data: { date: date.toISOString() }
989
+ }
990
+ };
991
+ await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {
992
+ startAfter: date,
993
+ expireInSeconds: defaultExpireInSeconds
994
+ });
995
+ this.logger.log(`Running step ${stepId}, waiting until ${date.toISOString()}...`, {
996
+ runId: run.id,
997
+ workflowId: run.workflowId
998
+ });
962
999
  }
963
1000
  async checkIfHasStarted() {
964
1001
  if (!this._started) {
@@ -1006,5 +1043,5 @@ export {
1006
1043
  StepType
1007
1044
  };
1008
1045
 
1009
- //# debugId=C6368049A4A4F68664756E2164756E21
1046
+ //# debugId=83CCFC149D5B47CD64756E2164756E21
1010
1047
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -3,14 +3,14 @@
3
3
  "sources": ["src/definition.ts", "src/engine.ts", "src/ast-parser.ts", "src/db/migration.ts", "src/db/queries.ts", "src/error.ts", "src/types.ts"],
4
4
  "sourcesContent": [
5
5
  "import type {\n inferParameters,\n Parameters,\n WorkflowContext,\n WorkflowDefinition,\n WorkflowOptions,\n} from './types';\n\nexport function workflow<I extends Parameters>(\n id: string,\n handler: (context: WorkflowContext<inferParameters<I>>) => Promise<unknown>,\n { inputSchema, timeout, retries }: WorkflowOptions<I> = {},\n): WorkflowDefinition<I> {\n return {\n id,\n handler,\n inputSchema,\n timeout,\n retries,\n };\n}\n",
6
- "import { merge } from 'es-toolkit';\nimport type { Db, 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 { WorkflowEngineError, WorkflowRunNotFoundError } from './error';\nimport {\n type InternalWorkflowDefinition,\n type InternalWorkflowLogger,\n type InternalWorkflowLoggerContext,\n type inferParameters,\n type Parameters,\n StepType,\n type WorkflowContext,\n type WorkflowDefinition,\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]';\n\nconst StepTypeToIcon = {\n [StepType.RUN]: 'λ',\n [StepType.WAIT_FOR]: '○',\n [StepType.PAUSE]: '⏸',\n [StepType.WAIT_UNTIL]: '⏲',\n};\n\n// Timeline entry types\ntype TimelineStepEntry = {\n output?: unknown;\n timestamp: Date;\n};\n\ntype TimelineWaitForEntry = {\n waitFor: {\n eventName: string;\n timeout?: number;\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 unregisteredWorkflows = new Map<string, WorkflowDefinition>();\n private _started = false;\n\n public workflows: Map<string, InternalWorkflowDefinition> = new Map<\n string,\n InternalWorkflowDefinition\n >();\n private logger: InternalWorkflowLogger;\n\n constructor({\n workflows,\n logger,\n boss,\n }: Partial<{\n workflows: WorkflowDefinition[];\n logger: WorkflowLogger;\n boss: PgBoss;\n }> = {}) {\n this.logger = this.buildLogger(logger ?? defaultLogger);\n\n if (workflows) {\n this.unregisteredWorkflows = new Map(workflows.map((workflow) => [workflow.id, workflow]));\n }\n\n if (!boss) {\n throw new WorkflowEngineError('PgBoss instance is required in constructor');\n }\n this.boss = boss;\n this.db = 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 this._started = false;\n\n this.logger.log('Workflow engine stopped');\n }\n\n async registerWorkflow(definition: WorkflowDefinition): 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(definition.handler);\n\n this.workflows.set(definition.id, {\n ...definition,\n steps,\n });\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 if (workflow.steps.length === 0 || !workflow.steps[0]) {\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;\n\n const run = await withPostgresTransaction(this.boss.getDb(), 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 this.boss.getDb(),\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\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 currentStepEntry = run.timeline[run.currentStepId];\n const currentStep =\n currentStepEntry && typeof currentStepEntry === 'object' && 'output' in currentStepEntry\n ? (currentStepEntry as TimelineStepEntry)\n : null;\n const waitFor = waitForStep?.waitFor;\n const hasCurrentStepOutput = currentStep?.output !== undefined;\n\n if (waitFor && waitFor.eventName === event?.name && !hasCurrentStepOutput) {\n run = await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.RUNNING,\n pausedAt: null,\n resumedAt: new Date(),\n timeline: merge(run.timeline, {\n [run.currentStepId]: {\n output: event?.data ?? {},\n timestamp: new Date(),\n },\n }),\n jobId: job?.id,\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 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 run: async <T>(stepId: string, handler: () => Promise<T>) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n\n return this.runStep({\n stepId,\n run,\n handler,\n }) as Promise<T>;\n },\n waitFor: async <T extends Parameters>(\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 return this.waitForEvent({\n run,\n stepId,\n eventName,\n timeout,\n }) as Promise<inferParameters<T>>;\n },\n // @ts-expect-error TODO: Implement waitUntil\n waitUntil: async ({ date }: { date: Date }) => {\n return this.waitUntil(runId, date);\n },\n pause: async (stepId: string) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n return this.pauseStep({\n stepId,\n run,\n });\n },\n },\n };\n\n const result = await workflow.handler(context);\n\n run = await this.getRun({ runId, resourceId });\n\n if (\n run.status === WorkflowStatus.RUNNING &&\n run.currentStepId === workflow.steps[workflow.steps.length - 1]?.id\n ) {\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, { retryDelay });\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 async runStep({\n stepId,\n run,\n handler,\n }: {\n stepId: string;\n run: WorkflowRun;\n handler: () => Promise<unknown>;\n }) {\n return withPostgresTransaction(this.db, 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 let result: unknown;\n\n // If the step has already been run, return the result\n const timelineStepEntry = persistedRun.timeline[stepId];\n const timelineStep =\n timelineStepEntry &&\n typeof timelineStepEntry === 'object' &&\n 'output' in timelineStepEntry\n ? (timelineStepEntry as TimelineStepEntry)\n : null;\n if (timelineStep?.output !== undefined) {\n result = timelineStep.output;\n } else {\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 result = await handler();\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: result === undefined ? {} : result,\n timestamp: new Date(),\n },\n }),\n },\n },\n { db },\n );\n }\n\n const finalResult = result === undefined ? {} : result;\n return finalResult;\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 }\n\n private async waitForEvent({\n run,\n stepId,\n eventName,\n timeout,\n }: {\n run: WorkflowRun;\n stepId: string;\n eventName: string;\n timeout?: number;\n }) {\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 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 const timelineStepCheckEntry = persistedRun.timeline[stepId];\n const timelineStepCheck =\n timelineStepCheckEntry &&\n typeof timelineStepCheckEntry === 'object' &&\n 'output' in timelineStepCheckEntry\n ? (timelineStepCheckEntry as TimelineStepEntry)\n : null;\n if (timelineStepCheck?.output !== undefined) {\n return timelineStepCheck.output;\n }\n\n await this.updateRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n status: WorkflowStatus.PAUSED,\n currentStepId: stepId,\n timeline: merge(run.timeline, {\n [`${stepId}-wait-for`]: {\n waitFor: {\n eventName,\n timeout,\n },\n timestamp: new Date(),\n },\n }),\n pausedAt: new Date(),\n },\n });\n\n this.logger.log(`Running step ${stepId}, waiting for event ${eventName}...`, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n }\n\n private async pauseStep({ stepId, run }: { stepId: string; run: WorkflowRun }): Promise<void> {\n await this.waitForEvent({\n run,\n stepId,\n eventName: PAUSE_EVENT_NAME,\n });\n }\n\n private async waitUntil(runId: string, _date: Date): Promise<void> {\n throw new WorkflowEngineError('Not implemented yet', undefined, runId);\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): InternalWorkflowLogger {\n return {\n log: (message: string, context?: InternalWorkflowLoggerContext) => {\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?: InternalWorkflowLoggerContext) => {\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",
7
- "import * as ts from 'typescript';\nimport type { InternalStepDefinition, StepType, WorkflowContext } from './types';\n\ntype ParseWorkflowHandlerReturnType = {\n steps: InternalStepDefinition[];\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, InternalStepDefinition> = 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' || methodName === 'waitFor' || methodName === 'pause')\n ) {\n const firstArg = node.arguments[0];\n if (firstArg) {\n const { id, isDynamic } = extractStepId(firstArg);\n\n const stepDefinition: InternalStepDefinition = {\n id,\n type: methodName as 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",
6
+ "import { merge } from 'es-toolkit';\nimport type { Db, 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 { WorkflowEngineError, WorkflowRunNotFoundError } from './error';\nimport {\n type InternalWorkflowDefinition,\n type InternalWorkflowLogger,\n type InternalWorkflowLoggerContext,\n type inferParameters,\n type Parameters,\n StepType,\n type WorkflowContext,\n type WorkflowDefinition,\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]';\n\nconst StepTypeToIcon = {\n [StepType.RUN]: 'λ',\n [StepType.WAIT_FOR]: '○',\n [StepType.PAUSE]: '⏸',\n [StepType.WAIT_UNTIL]: '⏲',\n};\n\n// Timeline entry types\ntype TimelineStepEntry = {\n output?: unknown;\n timestamp: Date;\n};\n\ntype TimelineWaitForEntry = {\n waitFor: {\n eventName: string;\n timeout?: number;\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 unregisteredWorkflows = new Map<string, WorkflowDefinition>();\n private _started = false;\n\n public workflows: Map<string, InternalWorkflowDefinition> = new Map<\n string,\n InternalWorkflowDefinition\n >();\n private logger: InternalWorkflowLogger;\n\n constructor({\n workflows,\n logger,\n boss,\n }: Partial<{\n workflows: WorkflowDefinition[];\n logger: WorkflowLogger;\n boss: PgBoss;\n }> = {}) {\n this.logger = this.buildLogger(logger ?? defaultLogger);\n\n if (workflows) {\n this.unregisteredWorkflows = new Map(workflows.map((workflow) => [workflow.id, workflow]));\n }\n\n if (!boss) {\n throw new WorkflowEngineError('PgBoss instance is required in constructor');\n }\n this.boss = boss;\n this.db = 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 this._started = false;\n\n this.logger.log('Workflow engine stopped');\n }\n\n async registerWorkflow(definition: WorkflowDefinition): 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(definition.handler);\n\n this.workflows.set(definition.id, {\n ...definition,\n steps,\n });\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 if (workflow.steps.length === 0 || !workflow.steps[0]) {\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;\n\n const run = await withPostgresTransaction(this.boss.getDb(), 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 this.boss.getDb(),\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\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 currentStepEntry = run.timeline[run.currentStepId];\n const currentStep =\n currentStepEntry && typeof currentStepEntry === 'object' && 'output' in currentStepEntry\n ? (currentStepEntry as TimelineStepEntry)\n : null;\n const waitFor = waitForStep?.waitFor;\n const hasCurrentStepOutput = currentStep?.output !== undefined;\n\n if (waitFor && waitFor.eventName === event?.name && !hasCurrentStepOutput) {\n run = await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.RUNNING,\n pausedAt: null,\n resumedAt: new Date(),\n timeline: merge(run.timeline, {\n [run.currentStepId]: {\n output: event?.data ?? {},\n timestamp: new Date(),\n },\n }),\n jobId: job?.id,\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 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 run: async <T>(stepId: string, handler: () => Promise<T>) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n\n return this.runStep({\n stepId,\n run,\n handler,\n }) as Promise<T>;\n },\n waitFor: async <T extends Parameters>(\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 return this.waitForEvent({\n run,\n stepId,\n eventName,\n timeout,\n }) as Promise<inferParameters<T>>;\n },\n waitUntil: async (stepId: string, { date }: { date: Date }) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n await this.waitUntilDate({\n run,\n stepId,\n date,\n });\n },\n pause: async (stepId: string) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n return this.pauseStep({\n stepId,\n run,\n });\n },\n },\n };\n\n const result = await workflow.handler(context);\n\n run = await this.getRun({ runId, resourceId });\n\n if (\n run.status === WorkflowStatus.RUNNING &&\n run.currentStepId === workflow.steps[workflow.steps.length - 1]?.id\n ) {\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 async runStep({\n stepId,\n run,\n handler,\n }: {\n stepId: string;\n run: WorkflowRun;\n handler: () => Promise<unknown>;\n }) {\n return withPostgresTransaction(this.db, 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 let result: unknown;\n\n // If the step has already been run, return the result\n const timelineStepEntry = persistedRun.timeline[stepId];\n const timelineStep =\n timelineStepEntry &&\n typeof timelineStepEntry === 'object' &&\n 'output' in timelineStepEntry\n ? (timelineStepEntry as TimelineStepEntry)\n : null;\n if (timelineStep?.output !== undefined) {\n result = timelineStep.output;\n } else {\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 result = await handler();\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: result === undefined ? {} : result,\n timestamp: new Date(),\n },\n }),\n },\n },\n { db },\n );\n }\n\n const finalResult = result === undefined ? {} : result;\n return finalResult;\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 }\n\n private async waitForEvent({\n run,\n stepId,\n eventName,\n timeout,\n }: {\n run: WorkflowRun;\n stepId: string;\n eventName: string;\n timeout?: number;\n }) {\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 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 const timelineStepCheckEntry = persistedRun.timeline[stepId];\n const timelineStepCheck =\n timelineStepCheckEntry &&\n typeof timelineStepCheckEntry === 'object' &&\n 'output' in timelineStepCheckEntry\n ? (timelineStepCheckEntry as TimelineStepEntry)\n : null;\n if (timelineStepCheck?.output !== undefined) {\n return timelineStepCheck.output;\n }\n\n await this.updateRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n status: WorkflowStatus.PAUSED,\n currentStepId: stepId,\n timeline: merge(run.timeline, {\n [`${stepId}-wait-for`]: {\n waitFor: {\n eventName,\n timeout,\n },\n timestamp: new Date(),\n },\n }),\n pausedAt: new Date(),\n },\n });\n\n this.logger.log(`Running step ${stepId}, waiting for event ${eventName}...`, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n }\n\n private async pauseStep({ stepId, run }: { stepId: string; run: WorkflowRun }): Promise<void> {\n await this.waitForEvent({\n run,\n stepId,\n eventName: PAUSE_EVENT_NAME,\n });\n }\n\n private async waitUntilDate({\n run,\n stepId,\n date,\n }: {\n run: WorkflowRun;\n stepId: string;\n date: Date;\n }) {\n const eventName = `__wait_until_${stepId}`;\n\n await this.waitForEvent({\n run,\n stepId,\n eventName,\n });\n\n const job: WorkflowRunJobParameters = {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n workflowId: run.workflowId,\n input: run.input,\n event: {\n name: eventName,\n data: { date: date.toISOString() },\n },\n };\n\n await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {\n startAfter: date,\n expireInSeconds: defaultExpireInSeconds,\n });\n\n this.logger.log(`Running step ${stepId}, waiting until ${date.toISOString()}...`, {\n runId: run.id,\n workflowId: run.workflowId,\n });\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): InternalWorkflowLogger {\n return {\n log: (message: string, context?: InternalWorkflowLoggerContext) => {\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?: InternalWorkflowLoggerContext) => {\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",
7
+ "import * as ts from 'typescript';\nimport type { InternalStepDefinition, StepType, WorkflowContext } from './types';\n\ntype ParseWorkflowHandlerReturnType = {\n steps: InternalStepDefinition[];\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, InternalStepDefinition> = 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 ) {\n const firstArg = node.arguments[0];\n if (firstArg) {\n const { id, isDynamic } = extractStepId(firstArg);\n\n const stepDefinition: InternalStepDefinition = {\n id,\n type: methodName as 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",
8
8
  "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",
9
9
  "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\nexport async function withPostgresTransaction<T>(\n db: Db,\n callback: (db: Db) => Promise<T>,\n): Promise<T> {\n try {\n await db.executeSql('BEGIN', []);\n const result = await callback(db);\n await db.executeSql('COMMIT', []);\n return result;\n } catch (error) {\n await db.executeSql('ROLLBACK', []);\n throw error;\n }\n}\n",
10
10
  "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",
11
11
  "import type { z } from 'zod';\nimport type { WorkflowRun } from './db/types';\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}\n\nexport type Parameters = z.ZodTypeAny;\nexport type inferParameters<P extends Parameters> = P extends z.ZodTypeAny ? z.infer<P> : never;\n\nexport type WorkflowOptions<I extends Parameters> = {\n timeout?: number;\n retries?: number;\n inputSchema?: I;\n};\n\nexport interface WorkflowLogger {\n log(message: string): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nexport type InternalWorkflowLoggerContext = {\n runId?: string;\n workflowId?: string;\n};\nexport interface InternalWorkflowLogger {\n log(message: string, context?: InternalWorkflowLoggerContext): void;\n error(message: string, error: Error, context?: InternalWorkflowLoggerContext): void;\n}\n\nexport type StepContext = {\n run: <T>(stepId: string, handler: () => Promise<T>) => Promise<T>;\n waitFor: <T extends Parameters>(\n stepId: string,\n { eventName, timeout, schema }: { eventName: string; timeout?: number; schema?: T },\n ) => Promise<inferParameters<T>>;\n waitUntil: (stepId: string, { date }: { date: Date }) => Promise<void>;\n pause: (stepId: string) => Promise<void>;\n};\n\nexport type WorkflowContext<T extends Parameters = Parameters> = {\n input: T;\n step: StepContext;\n workflowId: string;\n runId: string;\n timeline: Record<string, unknown>;\n logger: WorkflowLogger;\n};\n\nexport type WorkflowDefinition<T extends Parameters = Parameters> = {\n id: string;\n handler: (context: WorkflowContext<inferParameters<T>>) => Promise<unknown>;\n inputSchema?: T;\n timeout?: number; // milliseconds\n retries?: number;\n};\n\nexport type InternalStepDefinition = {\n id: string;\n type: StepType;\n conditional: boolean;\n loop: boolean;\n isDynamic: boolean;\n};\n\nexport type InternalWorkflowDefinition<T extends Parameters = Parameters> =\n WorkflowDefinition<T> & {\n steps: InternalStepDefinition[];\n };\n\nexport type WorkflowRunProgress = WorkflowRun & {\n completionPercentage: number;\n totalSteps: number;\n completedSteps: number;\n};\n"
12
12
  ],
13
- "mappings": "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",
14
- "debugId": "738B5C3F90E7864264756E2164756E21",
13
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQO,SAAS,QAA8B,CAC5C,IACA,WACE,aAAa,SAAS,YAAgC,CAAC,GAClC;AAAA,EACvB,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA;;ACnBoB,IAAtB;;;ACAoB,IAApB;AAOO,SAAS,oBAAoB,CAClC,SACgC;AAAA,EAChC,MAAM,gBAAgB,QAAQ,SAAS;AAAA,EACvC,MAAM,aAAgB,oBAAiB,cAAc,eAAkB,gBAAa,QAAQ,IAAI;AAAA,EAEhG,MAAM,QAA6C,IAAI;AAAA,EAEvD,SAAS,eAAe,CAAC,MAAwB;AAAA,IAC/C,IAAI,UAAU,KAAK;AAAA,IACnB,OAAO,SAAS;AAAA,MACd,IACK,iBAAc,OAAO,KACrB,2BAAwB,OAAO,KAC/B,qBAAkB,OAAO,KACzB,gBAAa,OAAO,GACvB;AAAA,QACA,OAAO;AAAA,MACT;AAAA,MACA,UAAU,QAAQ;AAAA,IACpB;AAAA,IACA,OAAO;AAAA;AAAA,EAGT,SAAS,QAAQ,CAAC,MAAwB;AAAA,IACxC,IAAI,UAAU,KAAK;AAAA,IACnB,OAAO,SAAS;AAAA,MACd,IACK,kBAAe,OAAO,KACtB,oBAAiB,OAAO,KACxB,oBAAiB,OAAO,KACxB,oBAAiB,OAAO,KACxB,iBAAc,OAAO,GACxB;AAAA,QACA,OAAO;AAAA,MACT;AAAA,MACA,UAAU,QAAQ;AAAA,IACpB;AAAA,IACA,OAAO;AAAA;AAAA,EAGT,SAAS,aAAa,CAAC,KAGrB;AAAA,IACA,IAAO,mBAAgB,GAAG,KAAQ,mCAAgC,GAAG,GAAG;AAAA,MACtE,OAAO,EAAE,IAAI,IAAI,MAAM,WAAW,MAAM;AAAA,IAC1C;AAAA,IAEA,IAAO,wBAAqB,GAAG,GAAG;AAAA,MAChC,IAAI,cAAc,IAAI,KAAK;AAAA,MAC3B,WAAW,QAAQ,IAAI,eAAe;AAAA,QACpC,eAAe;AAAA,QACf,eAAe,KAAK,QAAQ;AAAA,MAC9B;AAAA,MACA,OAAO,EAAE,IAAI,aAAa,WAAW,KAAK;AAAA,IAC5C;AAAA,IAEA,OAAO,EAAE,IAAI,IAAI,QAAQ,UAAU,GAAG,WAAW,KAAK;AAAA;AAAA,EAGxD,SAAS,KAAK,CAAC,MAAe;AAAA,IAC5B,IAAO,oBAAiB,IAAI,KAAQ,8BAA2B,KAAK,UAAU,GAAG;AAAA,MAC/E,MAAM,iBAAiB,KAAK;AAAA,MAC5B,MAAM,aAAa,eAAe,WAAW,QAAQ,UAAU;AAAA,MAC/D,MAAM,aAAa,eAAe,KAAK;AAAA,MAEvC,IACE,eAAe,WACd,eAAe,SACd,eAAe,aACf,eAAe,WACf,eAAe,cACjB;AAAA,QACA,MAAM,WAAW,KAAK,UAAU;AAAA,QAChC,IAAI,UAAU;AAAA,UACZ,QAAQ,IAAI,cAAc,cAAc,QAAQ;AAAA,UAEhD,MAAM,iBAAyC;AAAA,YAC7C;AAAA,YACA,MAAM;AAAA,YACN,aAAa,gBAAgB,IAAI;AAAA,YACjC,MAAM,SAAS,IAAI;AAAA,YACnB;AAAA,UACF;AAAA,UAEA,IAAI,MAAM,IAAI,EAAE,GAAG;AAAA,YACjB,MAAM,IAAI,MACR,gCAAgC,iDAClC;AAAA,UACF;AAAA,UAEA,MAAM,IAAI,IAAI,cAAc;AAAA,QAC9B;AAAA,MACF;AAAA,IACF;AAAA,IAEG,gBAAa,MAAM,KAAK;AAAA;AAAA,EAG7B,MAAM,UAAU;AAAA,EAEhB,OAAO,EAAE,OAAO,MAAM,KAAK,MAAM,OAAO,CAAC,EAAE;AAAA;;;AC3G7C,eAAsB,aAAa,CAAC,IAAuB;AAAA,EACzD,MAAM,oBAAoB,MAAM,GAAG,WACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAOA,CAAC,CACH;AAAA,EAEA,IAAI,CAAC,kBAAkB,KAAK,IAAI,QAAQ;AAAA,IACtC,MAAM,GAAG,WACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAsBA,CAAC,CACH;AAAA,IAEA,MAAM,GAAG,WACP;AAAA;AAAA,OAGA,CAAC,CACH;AAAA,IAEA,MAAM,GAAG,WACP;AAAA;AAAA,OAGA,CAAC,CACH;AAAA,IAEA,MAAM,GAAG,WACP;AAAA;AAAA,OAGA,CAAC,CACH;AAAA,EACF;AAAA;;;AC7DgB,IAAlB;AAIO,SAAS,aAAa,CAAC,QAAyB;AAAA,EACrD,OAAO,GAAG,SAAS,GAAG,YAAY,KAAK,qBAAM,WAAW,EAAE;AAAA;AAwB5D,SAAS,mBAAmB,CAAC,KAAkC;AAAA,EAC7D,OAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,WAAW,IAAI,KAAK,IAAI,UAAU;AAAA,IAClC,WAAW,IAAI,KAAK,IAAI,UAAU;AAAA,IAClC,YAAY,IAAI;AAAA,IAChB,YAAY,IAAI;AAAA,IAChB,QAAQ,IAAI;AAAA,IACZ,OAAO,OAAO,IAAI,UAAU,WAAW,KAAK,MAAM,IAAI,KAAK,IAAI,IAAI;AAAA,IACnE,QACE,OAAO,IAAI,WAAW,WAClB,IAAI,OAAO,KAAK,EAAE,WAAW,GAAG,KAAK,IAAI,OAAO,KAAK,EAAE,WAAW,GAAG,IACnE,KAAK,MAAM,IAAI,MAAM,IACrB,IAAI,SACL,IAAI,UAAU;AAAA,IACrB,OAAO,IAAI;AAAA,IACX,eAAe,IAAI;AAAA,IACnB,UAAU,OAAO,IAAI,aAAa,WAAW,KAAK,MAAM,IAAI,QAAQ,IAAI,IAAI;AAAA,IAC5E,UAAU,IAAI,YAAY,IAAI,KAAK,IAAI,SAAS,IAAI;AAAA,IACpD,WAAW,IAAI,aAAa,IAAI,KAAK,IAAI,UAAU,IAAI;AAAA,IACvD,aAAa,IAAI,eAAe,IAAI,KAAK,IAAI,YAAY,IAAI;AAAA,IAC7D,WAAW,IAAI,aAAa,IAAI,KAAK,IAAI,UAAU,IAAI;AAAA,IACvD,YAAY,IAAI;AAAA,IAChB,YAAY,IAAI;AAAA,IAChB,OAAO,IAAI;AAAA,EACb;AAAA;AAGF,eAAsB,iBAAiB;AAAA,EAEnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,GAUF,IACsB;AAAA,EACtB,MAAM,QAAQ,cAAc,KAAK;AAAA,EACjC,MAAM,MAAM,IAAI;AAAA,EAEhB,MAAM,SAAS,MAAM,GAAG,WACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAgBA;AAAA,IACE;AAAA,IACA,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA,KAAK,UAAU,KAAK;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CACF;AAAA,EAEA,MAAM,cAAc,OAAO,KAAK;AAAA,EAEhC,IAAI,CAAC,aAAa;AAAA,IAChB,MAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AAAA,EAEA,OAAO,oBAAoB,WAAW;AAAA;AAGxC,eAAsB,cAAc;AAAA,EAEhC;AAAA,EACA;AAAA,KAKA,gBAAgB,OAAO,MACI;AAAA,EAC7B,MAAM,aAAa,gBAAgB,eAAe;AAAA,EAElD,MAAM,SAAS,aACX,MAAM,GAAG,WACP;AAAA;AAAA,UAEE,cACF,CAAC,OAAO,UAAU,CACpB,IACA,MAAM,GAAG,WACP;AAAA;AAAA,UAEE,cACF,CAAC,KAAK,CACR;AAAA,EAEJ,MAAM,MAAM,OAAO,KAAK;AAAA,EAExB,IAAI,CAAC,KAAK;AAAA,IACR,OAAO;AAAA,EACT;AAAA,EAEA,OAAO,oBAAoB,GAAG;AAAA;AAGhC,eAAsB,iBAAiB;AAAA,EAEnC;AAAA,EACA;AAAA,EACA;AAAA,GAMF,IAC6B;AAAA,EAC7B,MAAM,MAAM,IAAI;AAAA,EAEhB,MAAM,UAAoB,CAAC,iBAAiB;AAAA,EAC5C,MAAM,SAA4C,CAAC,GAAG;AAAA,EACtD,IAAI,aAAa;AAAA,EAEjB,IAAI,KAAK,WAAW,WAAW;AAAA,IAC7B,QAAQ,KAAK,aAAa,YAAY;AAAA,IACtC,OAAO,KAAK,KAAK,MAAM;AAAA,IACvB;AAAA,EACF;AAAA,EACA,IAAI,KAAK,kBAAkB,WAAW;AAAA,IACpC,QAAQ,KAAK,sBAAsB,YAAY;AAAA,IAC/C,OAAO,KAAK,KAAK,aAAa;AAAA,IAC9B;AAAA,EACF;AAAA,EACA,IAAI,KAAK,aAAa,WAAW;AAAA,IAC/B,QAAQ,KAAK,eAAe,YAAY;AAAA,IACxC,OAAO,KAAK,KAAK,UAAU,KAAK,QAAQ,CAAC;AAAA,IACzC;AAAA,EACF;AAAA,EACA,IAAI,KAAK,aAAa,WAAW;AAAA,IAC/B,QAAQ,KAAK,gBAAgB,YAAY;AAAA,IACzC,OAAO,KAAK,KAAK,QAAQ;AAAA,IACzB;AAAA,EACF;AAAA,EACA,IAAI,KAAK,cAAc,WAAW;AAAA,IAChC,QAAQ,KAAK,iBAAiB,YAAY;AAAA,IAC1C,OAAO,KAAK,KAAK,SAAS;AAAA,IAC1B;AAAA,EACF;AAAA,EACA,IAAI,KAAK,gBAAgB,WAAW;AAAA,IAClC,QAAQ,KAAK,mBAAmB,YAAY;AAAA,IAC5C,OAAO,KAAK,KAAK,WAAW;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,IAAI,KAAK,WAAW,WAAW;AAAA,IAC7B,QAAQ,KAAK,aAAa,YAAY;AAAA,IACtC,OAAO,KAAK,KAAK,UAAU,KAAK,MAAM,CAAC;AAAA,IACvC;AAAA,EACF;AAAA,EACA,IAAI,KAAK,UAAU,WAAW;AAAA,IAC5B,QAAQ,KAAK,YAAY,YAAY;AAAA,IACrC,OAAO,KAAK,KAAK,KAAK;AAAA,IACtB;AAAA,EACF;AAAA,EACA,IAAI,KAAK,eAAe,WAAW;AAAA,IACjC,QAAQ,KAAK,kBAAkB,YAAY;AAAA,IAC3C,OAAO,KAAK,KAAK,UAAU;AAAA,IAC3B;AAAA,EACF;AAAA,EACA,IAAI,KAAK,UAAU,WAAW;AAAA,IAC5B,QAAQ,KAAK,aAAa,YAAY;AAAA,IACtC,OAAO,KAAK,KAAK,KAAK;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,aAChB,eAAe,iCAAiC,aAAa,MAC7D,eAAe;AAAA,EAEnB,OAAO,KAAK,KAAK;AAAA,EACjB,IAAI,YAAY;AAAA,IACd,OAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEA,MAAM,QAAQ;AAAA;AAAA,UAEN,QAAQ,KAAK,IAAI;AAAA,MACrB;AAAA;AAAA;AAAA,EAIJ,MAAM,SAAS,MAAM,GAAG,WAAW,OAAO,MAAM;AAAA,EAChD,MAAM,MAAM,OAAO,KAAK;AAAA,EAExB,IAAI,CAAC,KAAK;AAAA,IACR,OAAO;AAAA,EACT;AAAA,EAEA,OAAO,oBAAoB,GAAG;AAAA;AAGhC,eAAsB,eAAe;AAAA,EAEjC;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,GASF,IAOC;AAAA,EACD,MAAM,aAAuB,CAAC;AAAA,EAC9B,MAAM,SAAgD,CAAC;AAAA,EACvD,IAAI,aAAa;AAAA,EAEjB,IAAI,YAAY;AAAA,IACd,WAAW,KAAK,kBAAkB,YAAY;AAAA,IAC9C,OAAO,KAAK,UAAU;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,IAAI,YAAY,SAAS,SAAS,GAAG;AAAA,IACnC,WAAW,KAAK,iBAAiB,aAAa;AAAA,IAC9C,OAAO,KAAK,QAAQ;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,IAAI,YAAY;AAAA,IACd,WAAW,KAAK,kBAAkB,YAAY;AAAA,IAC9C,OAAO,KAAK,UAAU;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,IAAI,eAAe;AAAA,IACjB,MAAM,eAAe,MAAM,GAAG,WAC5B,8DACA,CAAC,aAAa,CAChB;AAAA,IACA,IAAI,aAAa,KAAK,IAAI,YAAY;AAAA,MACpC,WAAW,KAAK,iBAAiB,YAAY;AAAA,MAC7C,OAAO,KACL,OAAO,aAAa,KAAK,GAAG,eAAe,WACvC,IAAI,KAAK,aAAa,KAAK,GAAG,UAAU,IACxC,aAAa,KAAK,GAAG,UAC3B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,IAAI,cAAc;AAAA,IAChB,MAAM,eAAe,MAAM,GAAG,WAC5B,8DACA,CAAC,YAAY,CACf;AAAA,IACA,IAAI,aAAa,KAAK,IAAI,YAAY;AAAA,MACpC,WAAW,KAAK,iBAAiB,YAAY;AAAA,MAC7C,OAAO,KACL,OAAO,aAAa,KAAK,GAAG,eAAe,WACvC,IAAI,KAAK,aAAa,KAAK,GAAG,UAAU,IACxC,aAAa,KAAK,GAAG,UAC3B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,WAAW,SAAS,IAAI,SAAS,WAAW,KAAK,OAAO,MAAM;AAAA,EAClF,MAAM,cAAc,KAAK,IAAI,KAAK,IAAI,OAAO,CAAC,GAAG,GAAG,IAAI;AAAA,EAExD,MAAM,QAAQ;AAAA;AAAA,MAEV;AAAA;AAAA,aAEO;AAAA;AAAA,EAEX,OAAO,KAAK,WAAW;AAAA,EAEvB,MAAM,SAAS,MAAM,GAAG,WAAW,OAAO,MAAM;AAAA,EAChD,MAAM,OAAO,OAAO;AAAA,EAEpB,MAAM,UAAU,KAAK,UAAU,SAAS;AAAA,EACxC,MAAM,WAAW,UAAU,KAAK,MAAM,GAAG,KAAK,IAAI;AAAA,EAClD,MAAM,QAAQ,SAAS,IAAI,CAAC,QAAQ,oBAAoB,GAAG,CAAC;AAAA,EAC5D,MAAM,UAAU,CAAC,CAAC;AAAA,EAClB,MAAM,aAAa,WAAW,MAAM,SAAS,IAAK,MAAM,MAAM,SAAS,IAAI,MAAM,OAAQ;AAAA,EACzF,MAAM,aAAa,WAAW,MAAM,SAAS,IAAK,MAAM,IAAI,MAAM,OAAQ;AAAA,EAE1E,OAAO,EAAE,OAAO,YAAY,YAAY,SAAS,QAAQ;AAAA;AAG3D,eAAsB,uBAA0B,CAC9C,IACA,UACY;AAAA,EACZ,IAAI;AAAA,IACF,MAAM,GAAG,WAAW,SAAS,CAAC,CAAC;AAAA,IAC/B,MAAM,SAAS,MAAM,SAAS,EAAE;AAAA,IAChC,MAAM,GAAG,WAAW,UAAU,CAAC,CAAC;AAAA,IAChC,OAAO;AAAA,IACP,OAAO,OAAO;AAAA,IACd,MAAM,GAAG,WAAW,YAAY,CAAC,CAAC;AAAA,IAClC,MAAM;AAAA;AAAA;;;AC7WH,MAAM,4BAA4B,MAAM;AAAA,EAG3B;AAAA,EACA;AAAA,EACS;AAAA,EAJ3B,WAAW,CACT,SACgB,YACA,OACS,QAA2B,WACpD;AAAA,IACA,MAAM,OAAO;AAAA,IAJG;AAAA,IACA;AAAA,IACS;AAAA,IAGzB,KAAK,OAAO;AAAA,IAEZ,IAAI,MAAM,mBAAmB;AAAA,MAC3B,MAAM,kBAAkB,MAAM,mBAAmB;AAAA,IACnD;AAAA;AAEJ;AAAA;AAEO,MAAM,iCAAiC,oBAAoB;AAAA,EAChE,WAAW,CAAC,OAAgB,YAAqB;AAAA,IAC/C,MAAM,0BAA0B,YAAY,KAAK;AAAA,IACjD,KAAK,OAAO;AAAA;AAEhB;;;AClBO,IAAK;AAAA,CAAL,CAAK,oBAAL;AAAA,EACL,6BAAU;AAAA,EACV,6BAAU;AAAA,EACV,4BAAS;AAAA,EACT,+BAAY;AAAA,EACZ,4BAAS;AAAA,EACT,+BAAY;AAAA,GANF;AASL,IAAK;AAAA,CAAL,CAAK,cAAL;AAAA,EACL,qBAAQ;AAAA,EACR,mBAAM;AAAA,EACN,wBAAW;AAAA,EACX,0BAAa;AAAA,GAJH;;;ALgBZ,IAAM,mBAAmB;AACzB,IAAM,0BAA0B;AAChC,IAAM,aAAa;AAEnB,IAAM,iBAAiB;AAAA,qBACL;AAAA,8BACK;AAAA,yBACH;AAAA,kCACK;AACzB;AA2BA,IAAM,gBAAgC;AAAA,EACpC,KAAK,CAAC,aAAqB,QAAQ,KAAK,QAAQ;AAAA,EAChD,OAAO,CAAC,SAAiB,UAAiB,QAAQ,MAAM,SAAS,KAAK;AACxE;AAEA,IAAM,yBAAyB,QAAQ,IAAI,iCACvC,OAAO,SAAS,QAAQ,IAAI,gCAAgC,EAAE,IAC9D,IAAI;AAAA;AAED,MAAM,eAAe;AAAA,EAClB;AAAA,EACA;AAAA,EACA,wBAAwB,IAAI;AAAA,EAC5B,WAAW;AAAA,EAEZ,YAAqD,IAAI;AAAA,EAIxD;AAAA,EAER,WAAW;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,MAKG,CAAC,GAAG;AAAA,IACP,KAAK,SAAS,KAAK,YAAY,UAAU,aAAa;AAAA,IAEtD,IAAI,WAAW;AAAA,MACb,KAAK,wBAAwB,IAAI,IAAI,UAAU,IAAI,CAAC,cAAa,CAAC,UAAS,IAAI,SAAQ,CAAC,CAAC;AAAA,IAC3F;AAAA,IAEA,IAAI,CAAC,MAAM;AAAA,MACT,MAAM,IAAI,oBAAoB,4CAA4C;AAAA,IAC5E;AAAA,IACA,KAAK,OAAO;AAAA,IACZ,KAAK,KAAK,KAAK,MAAM;AAAA;AAAA,OAGjB,MAAK,CACT,WAAW,QACT,cAAsC,EAAE,WAAW,EAAE,GACxC;AAAA,IACf,IAAI,KAAK,UAAU;AAAA,MACjB;AAAA,IACF;AAAA,IAGA,MAAM,KAAK,KAAK,MAAM;AAAA,IAEtB,MAAM,cAAc,KAAK,KAAK,MAAM,CAAC;AAAA,IAErC,IAAI,KAAK,sBAAsB,OAAO,GAAG;AAAA,MACvC,WAAW,aAAY,KAAK,sBAAsB,OAAO,GAAG;AAAA,QAC1D,MAAM,KAAK,iBAAiB,SAAQ;AAAA,MACtC;AAAA,IACF;AAAA,IAEA,MAAM,KAAK,KAAK,YAAY,uBAAuB;AAAA,IAEnD,MAAM,aAAqB,EAAE,QAAQ,IAAI,wBAAwB;AAAA,IAEjE,IAAI,UAAU;AAAA,MACZ,SAAS,IAAI,EAAG,IAAI,YAAY,KAAK;AAAA,QACnC,MAAM,KAAK,KAAK,KACd,yBACA,EAAE,wBAAwB,KAAK,UAAU,GACzC,CAAC,QAAQ,KAAK,kBAAkB,GAAG,CACrC;AAAA,QACA,KAAK,OAAO,IACV,UAAU,IAAI,KAAK,gCAAgC,yBACrD;AAAA,MACF;AAAA,IACF;AAAA,IAEA,KAAK,WAAW;AAAA,IAEhB,KAAK,OAAO,IAAI,0BAA0B;AAAA;AAAA,OAGtC,KAAI,GAAkB;AAAA,IAC1B,MAAM,KAAK,KAAK,KAAK;AAAA,IAErB,KAAK,WAAW;AAAA,IAEhB,KAAK,OAAO,IAAI,yBAAyB;AAAA;AAAA,OAGrC,iBAAgB,CAAC,YAAyD;AAAA,IAC9E,IAAI,KAAK,UAAU,IAAI,WAAW,EAAE,GAAG;AAAA,MACrC,MAAM,IAAI,oBACR,YAAY,WAAW,4BACvB,WAAW,EACb;AAAA,IACF;AAAA,IAEA,QAAQ,UAAU,qBAAqB,WAAW,OAAO;AAAA,IAEzD,KAAK,UAAU,IAAI,WAAW,IAAI;AAAA,SAC7B;AAAA,MACH;AAAA,IACF,CAAC;AAAA,IAED,KAAK,OAAO,IAAI,wBAAwB,WAAW,iBAAiB;AAAA,IACpE,WAAW,QAAQ,MAAM,OAAO,GAAG;AAAA,MACjC,MAAM,OAAO,CAAC;AAAA,MACd,IAAI,KAAK;AAAA,QAAa,KAAK,KAAK,eAAe;AAAA,MAC/C,IAAI,KAAK;AAAA,QAAM,KAAK,KAAK,QAAQ;AAAA,MACjC,IAAI,KAAK;AAAA,QAAW,KAAK,KAAK,WAAW;AAAA,MACzC,KAAK,OAAO,IAAI,SAAQ,eAAe,KAAK,UAAU,KAAK,MAAM,KAAK,KAAK,GAAG,GAAG;AAAA,IACnF;AAAA,IAEA,OAAO;AAAA;AAAA,OAGH,mBAAkB,CAAC,YAA6C;AAAA,IACpE,KAAK,UAAU,OAAO,UAAU;AAAA,IAChC,OAAO;AAAA;AAAA,OAGH,uBAAsB,GAA4B;AAAA,IACtD,KAAK,UAAU,MAAM;AAAA,IACrB,OAAO;AAAA;AAAA,OAGH,cAAa;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,KAWuB;AAAA,IACvB,IAAI,CAAC,KAAK,UAAU;AAAA,MAClB,MAAM,KAAK,MAAM,OAAO,EAAE,WAAW,SAAS,aAAa,EAAE,CAAC;AAAA,IAChE;AAAA,IAEA,MAAM,YAAW,KAAK,UAAU,IAAI,UAAU;AAAA,IAC9C,IAAI,CAAC,WAAU;AAAA,MACb,MAAM,IAAI,oBAAoB,oBAAoB,YAAY;AAAA,IAChE;AAAA,IAEA,IAAI,UAAS,MAAM,WAAW,KAAK,CAAC,UAAS,MAAM,IAAI;AAAA,MACrD,MAAM,IAAI,oBAAoB,YAAY,2BAA2B,UAAU;AAAA,IACjF;AAAA,IACA,IAAI,UAAS,aAAa;AAAA,MACxB,MAAM,SAAS,UAAS,YAAY,UAAU,KAAK;AAAA,MACnD,IAAI,CAAC,OAAO,SAAS;AAAA,QACnB,MAAM,IAAI,oBAAoB,OAAO,MAAM,SAAS,UAAU;AAAA,MAChE;AAAA,IACF;AAAA,IAEA,MAAM,gBAAgB,UAAS,MAAM,IAAI;AAAA,IAEzC,MAAM,MAAM,MAAM,wBAAwB,KAAK,KAAK,MAAM,GAAG,OAAO,QAAQ;AAAA,MAC1E,MAAM,YAAY,SAAS,UACvB,IAAI,KAAK,KAAK,IAAI,IAAI,QAAQ,OAAO,IACrC,UAAS,UACP,IAAI,KAAK,KAAK,IAAI,IAAI,UAAS,OAAO,IACtC;AAAA,MAEN,MAAM,cAAc,MAAM,kBACxB;AAAA,QACE;AAAA,QACA;AAAA,QACA,eAAe;AAAA,QACf;AAAA,QACA;AAAA,QACA,YAAY,SAAS,WAAW,UAAS,WAAW;AAAA,QACpD;AAAA,MACF,GACA,KAAK,KAAK,MAAM,CAClB;AAAA,MAEA,MAAM,MAAgC;AAAA,QACpC,OAAO,YAAY;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MAEA,MAAM,KAAK,KAAK,KAAK,yBAAyB,KAAK;AAAA,QACjD,YAAY,IAAI;AAAA,QAChB,iBAAiB,SAAS,mBAAmB;AAAA,MAC/C,CAAC;AAAA,MAED,OAAO;AAAA,KACR;AAAA,IAED,KAAK,OAAO,IAAI,wBAAwB;AAAA,MACtC,OAAO,IAAI;AAAA,MACX;AAAA,IACF,CAAC;AAAA,IAED,OAAO;AAAA;AAAA,OAGH,cAAa;AAAA,IACjB;AAAA,IACA;AAAA,KAIuB;AAAA,IACvB,MAAM,KAAK,kBAAkB;AAAA,IAG7B,MAAM,MAAM,MAAM,KAAK,UAAU;AAAA,MAC/B;AAAA,MACA;AAAA,MACA,MAAM;AAAA,QACJ;AAAA,QACA,UAAU,IAAI;AAAA,MAChB;AAAA,IACF,CAAC;AAAA,IAED,KAAK,OAAO,IAAI,uBAAuB;AAAA,MACrC;AAAA,MACA,YAAY,IAAI;AAAA,IAClB,CAAC;AAAA,IAED,OAAO;AAAA;AAAA,OAGH,eAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,KAKuB;AAAA,IACvB,MAAM,KAAK,kBAAkB;AAAA,IAE7B,OAAO,KAAK,aAAa;AAAA,MACvB;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX,MAAM,CAAC;AAAA,MACP;AAAA,IACF,CAAC;AAAA;AAAA,OAGG,eAAc;AAAA,IAClB;AAAA,IACA;AAAA,KAIuB;AAAA,IACvB,MAAM,KAAK,kBAAkB;AAAA,IAE7B,MAAM,MAAM,MAAM,KAAK,UAAU;AAAA,MAC/B;AAAA,MACA;AAAA,MACA,MAAM;AAAA,QACJ;AAAA,MACF;AAAA,IACF,CAAC;AAAA,IAED,KAAK,OAAO,IAAI,kCAAkC,OAAO;AAAA,IAEzD,OAAO;AAAA;AAAA,OAGH,aAAY;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,KASuB;AAAA,IACvB,MAAM,KAAK,kBAAkB;AAAA,IAE7B,MAAM,MAAM,MAAM,KAAK,OAAO,EAAE,OAAO,WAAW,CAAC;AAAA,IAEnD,MAAM,MAAgC;AAAA,MACpC,OAAO,IAAI;AAAA,MACX;AAAA,MACA,YAAY,IAAI;AAAA,MAChB,OAAO,IAAI;AAAA,MACX,OAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAAA,IAEA,KAAK,KAAK,KAAK,yBAAyB,KAAK;AAAA,MAC3C,iBAAiB,SAAS,mBAAmB;AAAA,IAC/C,CAAC;AAAA,IAED,KAAK,OAAO,IAAI,SAAS,2CAA2C,OAAO;AAAA,IAC3E,OAAO;AAAA;AAAA,OAGH,OAAM,GACR,OAAO,gBACP,gBAAgB,OAAO,OAA6C,CAAC,GACjD;AAAA,IACtB,MAAM,MAAM,MAAM,eAAe,EAAE,OAAO,WAAW,GAAG,EAAE,eAAe,IAAI,MAAM,KAAK,GAAG,CAAC;AAAA,IAE5F,IAAI,CAAC,KAAK;AAAA,MACR,MAAM,IAAI,yBAAyB,KAAK;AAAA,IAC1C;AAAA,IAEA,OAAO;AAAA;AAAA,OAGH,UAAS;AAAA,IAEX;AAAA,IACA;AAAA,IACA;AAAA,OAMA,OAAoB,CAAC,GACD;AAAA,IACtB,MAAM,MAAM,MAAM,kBAAkB,EAAE,OAAO,YAAY,KAAK,GAAG,MAAM,KAAK,EAAE;AAAA,IAE9E,IAAI,CAAC,KAAK;AAAA,MACR,MAAM,IAAI,yBAAyB,KAAK;AAAA,IAC1C;AAAA,IAEA,OAAO;AAAA;AAAA,OAGH,cAAa;AAAA,IACjB;AAAA,IACA;AAAA,KAI+B;AAAA,IAC/B,MAAM,MAAM,MAAM,KAAK,OAAO,EAAE,OAAO,WAAW,CAAC;AAAA,IACnD,MAAM,YAAW,KAAK,UAAU,IAAI,IAAI,UAAU;AAAA,IAElD,IAAI,CAAC,WAAU;AAAA,MACb,MAAM,IAAI,oBAAoB,YAAY,IAAI,wBAAwB,IAAI,YAAY,KAAK;AAAA,IAC7F;AAAA,IACA,MAAM,QAAQ,WAAU,SAAS,CAAC;AAAA,IAElC,IAAI,uBAAuB;AAAA,IAC3B,IAAI,iBAAiB;AAAA,IAErB,IAAI,MAAM,SAAS,GAAG;AAAA,MACpB,iBAAiB,OAAO,OAAO,IAAI,QAAQ,EAAE,OAC3C,CAAC,SACC,OAAO,SAAS,YAChB,SAAS,SACT,YAAY,SACZ,KAAK,WAAW,SACpB,EAAE;AAAA,MAEF,IAAI,IAAI,wCAAqC;AAAA,QAC3C,uBAAuB;AAAA,MACzB,EAAO,SAAI,IAAI,oCAAoC,IAAI,wCAAqC;AAAA,QAC1F,uBAAuB,KAAK,IAAK,iBAAiB,MAAM,SAAU,KAAK,GAAG;AAAA,MAC5E,EAAO;AAAA,QACL,MAAM,mBAAmB,MAAM,UAAU,CAAC,SAAS,KAAK,OAAO,IAAI,aAAa;AAAA,QAChF,IAAI,oBAAoB,GAAG;AAAA,UACzB,uBAAwB,mBAAmB,MAAM,SAAU;AAAA,QAC7D,EAAO;AAAA,UACL,MAAM,kBAAiB,OAAO,KAAK,IAAI,QAAQ,EAAE;AAAA,UAEjD,uBAAuB,KAAK,IAAK,kBAAiB,MAAM,SAAU,KAAK,GAAG;AAAA;AAAA;AAAA,IAGhF;AAAA,IAEA,OAAO;AAAA,SACF;AAAA,MACH;AAAA,MACA,sBAAsB,KAAK,MAAM,uBAAuB,GAAG,IAAI;AAAA,MAC/D,YAAY,MAAM;AAAA,IACpB;AAAA;AAAA,OAGY,kBAAiB,EAAE,MAAuC;AAAA,IACtE,QAAQ,OAAO,YAAY,YAAY,OAAO,UAAU,KAAK,QAAQ,CAAC;AAAA,IAEtE,IAAI,CAAC,OAAO;AAAA,MACV,MAAM,IAAI,oBAAoB,2CAA2C,UAAU;AAAA,IACrF;AAAA,IAEA,IAAI,CAAC,YAAY;AAAA,MACf,MAAM,IAAI,oBAAoB,gDAAgD,UAAU;AAAA,IAC1F;AAAA,IAEA,IAAI,CAAC,YAAY;AAAA,MACf,MAAM,IAAI,oBACR,gDACA,WACA,KACF;AAAA,IACF;AAAA,IAEA,MAAM,YAAW,KAAK,UAAU,IAAI,UAAU;AAAA,IAC9C,IAAI,CAAC,WAAU;AAAA,MACb,MAAM,IAAI,oBAAoB,YAAY,wBAAwB,YAAY,KAAK;AAAA,IACrF;AAAA,IAEA,KAAK,OAAO,IAAI,8BAA8B;AAAA,MAC5C;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IAED,IAAI,MAAM,MAAM,KAAK,OAAO,EAAE,OAAO,WAAW,CAAC;AAAA,IAEjD,IAAI;AAAA,MACF,IAAI,IAAI,wCAAqC;AAAA,QAC3C,KAAK,OAAO,IAAI,gBAAgB,8BAA8B;AAAA,QAC9D;AAAA,MACF;AAAA,MAEA,IAAI,CAAC,IAAI,eAAe;AAAA,QACtB,MAAM,IAAI,oBAAoB,2BAA2B,YAAY,KAAK;AAAA,MAC5E;AAAA,MAEA,IAAI,IAAI,kCAAkC;AAAA,QACxC,MAAM,mBAAmB,IAAI,SAAS,GAAG,IAAI;AAAA,QAC7C,MAAM,cACJ,oBAAoB,OAAO,qBAAqB,YAAY,aAAa,mBACpE,mBACD;AAAA,QACN,MAAM,mBAAmB,IAAI,SAAS,IAAI;AAAA,QAC1C,MAAM,cACJ,oBAAoB,OAAO,qBAAqB,YAAY,YAAY,mBACnE,mBACD;AAAA,QACN,MAAM,UAAU,aAAa;AAAA,QAC7B,MAAM,uBAAuB,aAAa,WAAW;AAAA,QAErD,IAAI,WAAW,QAAQ,cAAc,OAAO,QAAQ,CAAC,sBAAsB;AAAA,UACzE,MAAM,MAAM,KAAK,UAAU;AAAA,YACzB;AAAA,YACA;AAAA,YACA,MAAM;AAAA,cACJ;AAAA,cACA,UAAU;AAAA,cACV,WAAW,IAAI;AAAA,cACf,UAAU,wBAAM,IAAI,UAAU;AAAA,iBAC3B,IAAI,gBAAgB;AAAA,kBACnB,QAAQ,OAAO,QAAQ,CAAC;AAAA,kBACxB,WAAW,IAAI;AAAA,gBACjB;AAAA,cACF,CAAC;AAAA,cACD,OAAO,KAAK;AAAA,YACd;AAAA,UACF,CAAC;AAAA,QACH,EAAO;AAAA,UACL,MAAM,MAAM,KAAK,UAAU;AAAA,YACzB;AAAA,YACA;AAAA,YACA,MAAM;AAAA,cACJ;AAAA,cACA,UAAU;AAAA,cACV,WAAW,IAAI;AAAA,cACf,OAAO,KAAK;AAAA,YACd;AAAA,UACF,CAAC;AAAA;AAAA,MAEL;AAAA,MAEA,MAAM,UAA2B;AAAA,QAC/B,OAAO,IAAI;AAAA,QACX,YAAY,IAAI;AAAA,QAChB,OAAO,IAAI;AAAA,QACX,UAAU,IAAI;AAAA,QACd,QAAQ,KAAK;AAAA,QACb,MAAM;AAAA,UACJ,KAAK,OAAU,QAAgB,YAA8B;AAAA,YAC3D,IAAI,CAAC,KAAK;AAAA,cACR,MAAM,IAAI,oBAAoB,wBAAwB,YAAY,KAAK;AAAA,YACzE;AAAA,YAEA,OAAO,KAAK,QAAQ;AAAA,cAClB;AAAA,cACA;AAAA,cACA;AAAA,YACF,CAAC;AAAA;AAAA,UAEH,SAAS,OACP,UACE,WAAW,cACV;AAAA,YACH,IAAI,CAAC,KAAK;AAAA,cACR,MAAM,IAAI,oBAAoB,wBAAwB,YAAY,KAAK;AAAA,YACzE;AAAA,YACA,OAAO,KAAK,aAAa;AAAA,cACvB;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF,CAAC;AAAA;AAAA,UAEH,WAAW,OAAO,UAAkB,WAA2B;AAAA,YAC7D,IAAI,CAAC,KAAK;AAAA,cACR,MAAM,IAAI,oBAAoB,wBAAwB,YAAY,KAAK;AAAA,YACzE;AAAA,YACA,MAAM,KAAK,cAAc;AAAA,cACvB;AAAA,cACA;AAAA,cACA;AAAA,YACF,CAAC;AAAA;AAAA,UAEH,OAAO,OAAO,WAAmB;AAAA,YAC/B,IAAI,CAAC,KAAK;AAAA,cACR,MAAM,IAAI,oBAAoB,wBAAwB,YAAY,KAAK;AAAA,YACzE;AAAA,YACA,OAAO,KAAK,UAAU;AAAA,cACpB;AAAA,cACA;AAAA,YACF,CAAC;AAAA;AAAA,QAEL;AAAA,MACF;AAAA,MAEA,MAAM,SAAS,MAAM,UAAS,QAAQ,OAAO;AAAA,MAE7C,MAAM,MAAM,KAAK,OAAO,EAAE,OAAO,WAAW,CAAC;AAAA,MAE7C,IACE,IAAI,sCACJ,IAAI,kBAAkB,UAAS,MAAM,UAAS,MAAM,SAAS,IAAI,IACjE;AAAA,QACA,MAAM,mBAAmB,WAAW,YAAY,CAAC,IAAI;AAAA,QACrD,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA;AAAA,UACA,MAAM;AAAA,YACJ;AAAA,YACA,QAAQ;AAAA,YACR,aAAa,IAAI;AAAA,YACjB,OAAO,KAAK;AAAA,UACd;AAAA,QACF,CAAC;AAAA,QAED,KAAK,OAAO,IAAI,2BAA2B;AAAA,UACzC;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,MACA,OAAO,OAAO;AAAA,MACd,IAAI,IAAI,aAAa,IAAI,YAAY;AAAA,QACnC,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA;AAAA,UACA,MAAM;AAAA,YACJ,YAAY,IAAI,aAAa;AAAA,YAC7B,OAAO,KAAK;AAAA,UACd;AAAA,QACF,CAAC;AAAA,QAED,MAAM,aAAa,KAAK,IAAI,aAAa;AAAA,QAGzC,MAAM,YAAsC;AAAA,UAC1C;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,MAAM,KAAK,MAAM,KAAK,gBAAgB,WAAW;AAAA,UAC/C,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,UAAU;AAAA,UAC5C,iBAAiB;AAAA,QACnB,CAAC;AAAA,QAED;AAAA,MACF;AAAA,MAGA,MAAM,KAAK,UAAU;AAAA,QACnB;AAAA,QACA;AAAA,QACA,MAAM;AAAA,UACJ;AAAA,UACA,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,UAC5D,OAAO,KAAK;AAAA,QACd;AAAA,MACF,CAAC;AAAA,MAED,MAAM;AAAA;AAAA;AAAA,OAII,QAAO;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,KAKC;AAAA,IACD,OAAO,wBAAwB,KAAK,IAAI,OAAO,OAAO;AAAA,MACpD,MAAM,eAAe,MAAM,KAAK,OAC9B,EAAE,OAAO,IAAI,IAAI,YAAY,IAAI,cAAc,UAAU,GACzD;AAAA,QACE,eAAe;AAAA,QACf;AAAA,MACF,CACF;AAAA,MAEA,IACE,aAAa,0CACb,aAAa,oCACb,aAAa,kCACb;AAAA,QACA,KAAK,OAAO,IAAI,QAAQ,mCAAmC,aAAa,UAAU;AAAA,UAChF,OAAO,IAAI;AAAA,UACX,YAAY,IAAI;AAAA,QAClB,CAAC;AAAA,QAED;AAAA,MACF;AAAA,MAEA,IAAI;AAAA,QACF,IAAI;AAAA,QAGJ,MAAM,oBAAoB,aAAa,SAAS;AAAA,QAChD,MAAM,eACJ,qBACA,OAAO,sBAAsB,YAC7B,YAAY,oBACP,oBACD;AAAA,QACN,IAAI,cAAc,WAAW,WAAW;AAAA,UACtC,SAAS,aAAa;AAAA,QACxB,EAAO;AAAA,UACL,MAAM,KAAK,UACT;AAAA,YACE,OAAO,IAAI;AAAA,YACX,YAAY,IAAI,cAAc;AAAA,YAC9B,MAAM;AAAA,cACJ,eAAe;AAAA,YACjB;AAAA,UACF,GACA,EAAE,GAAG,CACP;AAAA,UAEA,KAAK,OAAO,IAAI,gBAAgB,aAAa;AAAA,YAC3C,OAAO,IAAI;AAAA,YACX,YAAY,IAAI;AAAA,UAClB,CAAC;AAAA,UAED,SAAS,MAAM,QAAQ;AAAA,UAEvB,MAAM,MAAM,KAAK,UACf;AAAA,YACE,OAAO,IAAI;AAAA,YACX,YAAY,IAAI,cAAc;AAAA,YAC9B,MAAM;AAAA,cACJ,UAAU,wBAAM,IAAI,UAAU;AAAA,iBAC3B,SAAS;AAAA,kBACR,QAAQ,WAAW,YAAY,CAAC,IAAI;AAAA,kBACpC,WAAW,IAAI;AAAA,gBACjB;AAAA,cACF,CAAC;AAAA,YACH;AAAA,UACF,GACA,EAAE,GAAG,CACP;AAAA;AAAA,QAGF,MAAM,cAAc,WAAW,YAAY,CAAC,IAAI;AAAA,QAChD,OAAO;AAAA,QACP,OAAO,OAAO;AAAA,QACd,KAAK,OAAO,MAAM,QAAQ,kBAAkB,OAAgB;AAAA,UAC1D,OAAO,IAAI;AAAA,UACX,YAAY,IAAI;AAAA,QAClB,CAAC;AAAA,QAED,MAAM,KAAK,UACT;AAAA,UACE,OAAO,IAAI;AAAA,UACX,YAAY,IAAI,cAAc;AAAA,UAC9B,MAAM;AAAA,YACJ;AAAA,YACA,OAAO,iBAAiB,QAAQ,GAAG,MAAM;AAAA,EAAY,MAAM,UAAU,OAAO,KAAK;AAAA,UACnF;AAAA,QACF,GACA,EAAE,GAAG,CACP;AAAA,QAEA,MAAM;AAAA;AAAA,KAET;AAAA;AAAA,OAGW,aAAY;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,KAMC;AAAA,IACD,MAAM,eAAe,MAAM,KAAK,OAAO;AAAA,MACrC,OAAO,IAAI;AAAA,MACX,YAAY,IAAI,cAAc;AAAA,IAChC,CAAC;AAAA,IAED,IACE,aAAa,0CACb,aAAa,oCACb,aAAa,kCACb;AAAA,MACA,KAAK,OAAO,IAAI,QAAQ,mCAAmC,aAAa,UAAU;AAAA,QAChF,OAAO,IAAI;AAAA,QACX,YAAY,IAAI;AAAA,MAClB,CAAC;AAAA,MAED;AAAA,IACF;AAAA,IAEA,MAAM,yBAAyB,aAAa,SAAS;AAAA,IACrD,MAAM,oBACJ,0BACA,OAAO,2BAA2B,YAClC,YAAY,yBACP,yBACD;AAAA,IACN,IAAI,mBAAmB,WAAW,WAAW;AAAA,MAC3C,OAAO,kBAAkB;AAAA,IAC3B;AAAA,IAEA,MAAM,KAAK,UAAU;AAAA,MACnB,OAAO,IAAI;AAAA,MACX,YAAY,IAAI,cAAc;AAAA,MAC9B,MAAM;AAAA,QACJ;AAAA,QACA,eAAe;AAAA,QACf,UAAU,wBAAM,IAAI,UAAU;AAAA,WAC3B,GAAG,oBAAoB;AAAA,YACtB,SAAS;AAAA,cACP;AAAA,cACA;AAAA,YACF;AAAA,YACA,WAAW,IAAI;AAAA,UACjB;AAAA,QACF,CAAC;AAAA,QACD,UAAU,IAAI;AAAA,MAChB;AAAA,IACF,CAAC;AAAA,IAED,KAAK,OAAO,IAAI,gBAAgB,6BAA6B,gBAAgB;AAAA,MAC3E,OAAO,IAAI;AAAA,MACX,YAAY,IAAI;AAAA,IAClB,CAAC;AAAA;AAAA,OAGW,UAAS,GAAG,QAAQ,OAA4D;AAAA,IAC5F,MAAM,KAAK,aAAa;AAAA,MACtB;AAAA,MACA;AAAA,MACA,WAAW;AAAA,IACb,CAAC;AAAA;AAAA,OAGW,cAAa;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,KAKC;AAAA,IACD,MAAM,YAAY,gBAAgB;AAAA,IAElC,MAAM,KAAK,aAAa;AAAA,MACtB;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IAED,MAAM,MAAgC;AAAA,MACpC,OAAO,IAAI;AAAA,MACX,YAAY,IAAI,cAAc;AAAA,MAC9B,YAAY,IAAI;AAAA,MAChB,OAAO,IAAI;AAAA,MACX,OAAO;AAAA,QACL,MAAM;AAAA,QACN,MAAM,EAAE,MAAM,KAAK,YAAY,EAAE;AAAA,MACnC;AAAA,IACF;AAAA,IAEA,MAAM,KAAK,KAAK,KAAK,yBAAyB,KAAK;AAAA,MACjD,YAAY;AAAA,MACZ,iBAAiB;AAAA,IACnB,CAAC;AAAA,IAED,KAAK,OAAO,IAAI,gBAAgB,yBAAyB,KAAK,YAAY,QAAQ;AAAA,MAChF,OAAO,IAAI;AAAA,MACX,YAAY,IAAI;AAAA,IAClB,CAAC;AAAA;AAAA,OAGW,kBAAiB,GAAkB;AAAA,IAC/C,IAAI,CAAC,KAAK,UAAU;AAAA,MAClB,MAAM,IAAI,oBAAoB,6BAA6B;AAAA,IAC7D;AAAA;AAAA,EAGM,WAAW,CAAC,QAAgD;AAAA,IAClE,OAAO;AAAA,MACL,KAAK,CAAC,SAAiB,YAA4C;AAAA,QACjE,QAAQ,OAAO,eAAe,WAAW,CAAC;AAAA,QAC1C,MAAM,QAAQ,CAAC,YAAY,YAAY,KAAK,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA,QACtE,OAAO,IAAI,GAAG,UAAU,SAAS;AAAA;AAAA,MAEnC,OAAO,CAAC,SAAiB,OAAc,YAA4C;AAAA,QACjF,QAAQ,OAAO,eAAe,WAAW,CAAC;AAAA,QAC1C,MAAM,QAAQ,CAAC,YAAY,YAAY,KAAK,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA,QACtE,OAAO,MAAM,GAAG,UAAU,WAAW,KAAK;AAAA;AAAA,IAE9C;AAAA;AAAA,OAGI,QAAO;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,KAcC;AAAA,IACD,OAAO,gBACL;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,GACA,KAAK,EACP;AAAA;AAEJ;",
14
+ "debugId": "EB7CB5376BB0770264756E2164756E21",
15
15
  "names": []
16
16
  }
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.1.2",
4
+ "version": "0.2.0",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"