bunqueue 2.6.116 → 2.7.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 +80 -0
- package/dist/client/workflow/engine.d.ts +26 -0
- package/dist/client/workflow/engine.d.ts.map +1 -0
- package/dist/client/workflow/engine.js +62 -0
- package/dist/client/workflow/engine.js.map +1 -0
- package/dist/client/workflow/executor.d.ts +32 -0
- package/dist/client/workflow/executor.d.ts.map +1 -0
- package/dist/client/workflow/executor.js +247 -0
- package/dist/client/workflow/executor.js.map +1 -0
- package/dist/client/workflow/index.d.ts +22 -0
- package/dist/client/workflow/index.d.ts.map +1 -0
- package/dist/client/workflow/index.js +21 -0
- package/dist/client/workflow/index.js.map +1 -0
- package/dist/client/workflow/store.d.ts +16 -0
- package/dist/client/workflow/store.d.ts.map +1 -0
- package/dist/client/workflow/store.js +105 -0
- package/dist/client/workflow/store.js.map +1 -0
- package/dist/client/workflow/types.d.ts +100 -0
- package/dist/client/workflow/types.d.ts.map +1 -0
- package/dist/client/workflow/types.js +5 -0
- package/dist/client/workflow/types.js.map +1 -0
- package/dist/client/workflow/workflow.d.ts +23 -0
- package/dist/client/workflow/workflow.d.ts.map +1 -0
- package/dist/client/workflow/workflow.js +73 -0
- package/dist/client/workflow/workflow.js.map +1 -0
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -481,6 +481,85 @@ process.on('SIGINT', async () => {
|
|
|
481
481
|
|
|
482
482
|
---
|
|
483
483
|
|
|
484
|
+
## Workflow Engine
|
|
485
|
+
|
|
486
|
+
Orchestrate multi-step business processes with branching, saga compensation, and human-in-the-loop signals. Built on top of bunqueue — no new infrastructure.
|
|
487
|
+
|
|
488
|
+
```typescript
|
|
489
|
+
import { Workflow, Engine } from 'bunqueue/workflow';
|
|
490
|
+
|
|
491
|
+
const orderFlow = new Workflow('order-pipeline')
|
|
492
|
+
.step('validate', async (ctx) => {
|
|
493
|
+
const { orderId, amount } = ctx.input as { orderId: string; amount: number };
|
|
494
|
+
if (amount <= 0) throw new Error('Invalid amount');
|
|
495
|
+
return { orderId };
|
|
496
|
+
})
|
|
497
|
+
.step('reserve-stock', async () => {
|
|
498
|
+
await inventory.reserve();
|
|
499
|
+
return { reserved: true };
|
|
500
|
+
}, {
|
|
501
|
+
compensate: async () => await inventory.release(), // Auto-rollback on failure
|
|
502
|
+
})
|
|
503
|
+
.step('charge', async () => {
|
|
504
|
+
return { txId: await payments.charge() };
|
|
505
|
+
}, {
|
|
506
|
+
compensate: async () => await payments.refund(),
|
|
507
|
+
})
|
|
508
|
+
.step('confirm', async (ctx) => {
|
|
509
|
+
const { txId } = ctx.steps['charge'] as { txId: string };
|
|
510
|
+
return { emailSent: true, txId };
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
const engine = new Engine({ embedded: true });
|
|
514
|
+
engine.register(orderFlow);
|
|
515
|
+
await engine.start('order-pipeline', { orderId: 'ORD-1', amount: 99.99 });
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
**Features:**
|
|
519
|
+
|
|
520
|
+
- **Saga pattern** — Compensation handlers run in reverse when a step fails
|
|
521
|
+
- **Branching** — Route to different paths based on runtime conditions
|
|
522
|
+
- **Human-in-the-loop** — `waitFor('event')` pauses execution, `engine.signal()` resumes it
|
|
523
|
+
- **Step timeouts** — Prevent steps from running indefinitely
|
|
524
|
+
- **Context passing** — Each step accesses input and all previous step results
|
|
525
|
+
- **SQLite persistence** — Execution state survives restarts
|
|
526
|
+
|
|
527
|
+
**vs Competitors:**
|
|
528
|
+
|
|
529
|
+
| | **bunqueue** | **Temporal** | **Inngest** | **AWS Step Functions** |
|
|
530
|
+
|---|---|---|---|---|
|
|
531
|
+
| **Infrastructure** | None (embedded) | PostgreSQL + 7 services | Cloud-only | AWS-native |
|
|
532
|
+
| **Saga compensation** | Built-in | Manual | Manual | Manual |
|
|
533
|
+
| **Human-in-the-loop** | `.waitFor()` | Signals API | `step.waitForEvent()` | Callback tasks |
|
|
534
|
+
| **Self-hosted** | Zero-config | Complex | No | No |
|
|
535
|
+
| **Pricing** | Free (MIT) | Free / Cloud $$ | Per-execution | Per-transition |
|
|
536
|
+
|
|
537
|
+
```typescript
|
|
538
|
+
// Branching
|
|
539
|
+
const flow = new Workflow('tiered')
|
|
540
|
+
.step('classify', async (ctx) => ({ tier: ctx.input.amount > 1000 ? 'vip' : 'basic' }))
|
|
541
|
+
.branch((ctx) => ctx.steps['classify'].tier)
|
|
542
|
+
.path('vip', (w) => w.step('vip-handler', async () => ({ discount: 20 })))
|
|
543
|
+
.path('basic', (w) => w.step('basic-handler', async () => ({ discount: 0 })))
|
|
544
|
+
.step('done', async () => ({ processed: true }));
|
|
545
|
+
|
|
546
|
+
// Human-in-the-loop
|
|
547
|
+
const approvalFlow = new Workflow('expense')
|
|
548
|
+
.step('submit', async (ctx) => ({ amount: ctx.input.amount }))
|
|
549
|
+
.waitFor('manager-approval')
|
|
550
|
+
.step('reimburse', async (ctx) => {
|
|
551
|
+
const decision = ctx.signals['manager-approval'] as { approved: boolean };
|
|
552
|
+
return { status: decision.approved ? 'paid' : 'rejected' };
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
// Signal a waiting workflow
|
|
556
|
+
await engine.signal(run.id, 'manager-approval', { approved: true });
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
[Workflow Engine docs →](https://bunqueue.dev/guide/workflow/)
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
484
563
|
<p align="center">
|
|
485
564
|
<strong>bunqueue Dashboard</strong><br/>
|
|
486
565
|
<sub>A visual interface for managing queues, jobs, workers and monitoring in real time. Currently in beta.</sub>
|
|
@@ -728,6 +807,7 @@ docker compose --profile monitoring up -d
|
|
|
728
807
|
**[Read the full documentation →](https://bunqueue.dev/)**
|
|
729
808
|
|
|
730
809
|
- [Quick Start](https://bunqueue.dev/guide/quickstart/)
|
|
810
|
+
- [Workflow Engine](https://bunqueue.dev/guide/workflow/)
|
|
731
811
|
- [MCP Server (AI Agents)](https://bunqueue.dev/guide/mcp/)
|
|
732
812
|
- [Simple Mode](https://bunqueue.dev/guide/simple-mode/)
|
|
733
813
|
- [Queue API](https://bunqueue.dev/guide/queue/)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine - Public facade for the workflow engine
|
|
3
|
+
* Manages lifecycle of internal Queue, Worker, and Store.
|
|
4
|
+
*/
|
|
5
|
+
import type { Workflow } from './workflow';
|
|
6
|
+
import type { EngineOptions, RunHandle, Execution, ExecutionState } from './types';
|
|
7
|
+
export declare class Engine {
|
|
8
|
+
private readonly queue;
|
|
9
|
+
private readonly worker;
|
|
10
|
+
private readonly store;
|
|
11
|
+
private readonly executor;
|
|
12
|
+
constructor(opts?: EngineOptions);
|
|
13
|
+
/** Register a workflow definition */
|
|
14
|
+
register(workflow: Workflow): this;
|
|
15
|
+
/** Start a new workflow execution */
|
|
16
|
+
start(workflowName: string, input?: unknown): Promise<RunHandle>;
|
|
17
|
+
/** Get execution state by ID */
|
|
18
|
+
getExecution(id: string): Execution | null;
|
|
19
|
+
/** List executions with optional filters */
|
|
20
|
+
listExecutions(workflowName?: string, state?: ExecutionState): Execution[];
|
|
21
|
+
/** Send a signal to a waiting execution */
|
|
22
|
+
signal(executionId: string, event: string, payload?: unknown): Promise<void>;
|
|
23
|
+
/** Shut down the engine */
|
|
24
|
+
close(force?: boolean): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/client/workflow/engine.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAe,MAAM,SAAS,CAAC;AAIhG,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;gBAEhC,IAAI,GAAE,aAAkB;IA2BpC,qCAAqC;IACrC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAKlC,qCAAqC;IAC/B,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC;IAItE,gCAAgC;IAChC,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAI1C,4CAA4C;IAC5C,cAAc,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,cAAc,GAAG,SAAS,EAAE;IAI1E,2CAA2C;IACrC,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlF,2BAA2B;IACrB,KAAK,CAAC,KAAK,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAK1C"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine - Public facade for the workflow engine
|
|
3
|
+
* Manages lifecycle of internal Queue, Worker, and Store.
|
|
4
|
+
*/
|
|
5
|
+
import { Queue } from '../queue/queue';
|
|
6
|
+
import { Worker } from '../worker/worker';
|
|
7
|
+
import { WorkflowStore } from './store';
|
|
8
|
+
import { WorkflowExecutor } from './executor';
|
|
9
|
+
const DEFAULT_QUEUE_NAME = '__wf:steps';
|
|
10
|
+
export class Engine {
|
|
11
|
+
queue;
|
|
12
|
+
worker;
|
|
13
|
+
store;
|
|
14
|
+
executor;
|
|
15
|
+
constructor(opts = {}) {
|
|
16
|
+
const queueName = opts.queueName ?? DEFAULT_QUEUE_NAME;
|
|
17
|
+
this.queue = new Queue(queueName, {
|
|
18
|
+
connection: opts.connection,
|
|
19
|
+
embedded: opts.embedded,
|
|
20
|
+
dataPath: opts.dataPath,
|
|
21
|
+
});
|
|
22
|
+
this.store = new WorkflowStore(opts.dataPath);
|
|
23
|
+
this.executor = new WorkflowExecutor(this.store, this.queue);
|
|
24
|
+
this.worker = new Worker(queueName, async (job) => {
|
|
25
|
+
const data = job.data;
|
|
26
|
+
return this.executor.processStep(data);
|
|
27
|
+
}, {
|
|
28
|
+
connection: opts.connection,
|
|
29
|
+
embedded: opts.embedded,
|
|
30
|
+
dataPath: opts.dataPath,
|
|
31
|
+
concurrency: opts.concurrency ?? 5,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/** Register a workflow definition */
|
|
35
|
+
register(workflow) {
|
|
36
|
+
this.executor.register(workflow);
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
/** Start a new workflow execution */
|
|
40
|
+
async start(workflowName, input) {
|
|
41
|
+
return this.executor.start(workflowName, input);
|
|
42
|
+
}
|
|
43
|
+
/** Get execution state by ID */
|
|
44
|
+
getExecution(id) {
|
|
45
|
+
return this.executor.getExecution(id);
|
|
46
|
+
}
|
|
47
|
+
/** List executions with optional filters */
|
|
48
|
+
listExecutions(workflowName, state) {
|
|
49
|
+
return this.executor.listExecutions(workflowName, state);
|
|
50
|
+
}
|
|
51
|
+
/** Send a signal to a waiting execution */
|
|
52
|
+
async signal(executionId, event, payload) {
|
|
53
|
+
return this.executor.signal(executionId, event, payload);
|
|
54
|
+
}
|
|
55
|
+
/** Shut down the engine */
|
|
56
|
+
async close(force = false) {
|
|
57
|
+
await this.worker.close(force);
|
|
58
|
+
this.queue.close();
|
|
59
|
+
this.store.close();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/client/workflow/engine.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAI9C,MAAM,kBAAkB,GAAG,YAAY,CAAC;AAExC,MAAM,OAAO,MAAM;IACA,KAAK,CAAQ;IACb,MAAM,CAAS;IACf,KAAK,CAAgB;IACrB,QAAQ,CAAmB;IAE5C,YAAY,OAAsB,EAAE;QAClC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,kBAAkB,CAAC;QAEvD,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,SAAS,EAAE;YAChC,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,CAAC,QAAQ,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAE7D,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CACtB,SAAS,EACT,KAAK,EAAE,GAAG,EAAE,EAAE;YACZ,MAAM,IAAI,GAAG,GAAG,CAAC,IAA8B,CAAC;YAChD,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC,EACD;YACE,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,CAAC;SACnC,CACF,CAAC;IACJ,CAAC;IAED,qCAAqC;IACrC,QAAQ,CAAC,QAAkB;QACzB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,qCAAqC;IACrC,KAAK,CAAC,KAAK,CAAC,YAAoB,EAAE,KAAe;QAC/C,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC;IAED,gCAAgC;IAChC,YAAY,CAAC,EAAU;QACrB,OAAO,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,4CAA4C;IAC5C,cAAc,CAAC,YAAqB,EAAE,KAAsB;QAC1D,OAAO,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IAC3D,CAAC;IAED,2CAA2C;IAC3C,KAAK,CAAC,MAAM,CAAC,WAAmB,EAAE,KAAa,EAAE,OAAiB;QAChE,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC3D,CAAC;IAED,2BAA2B;IAC3B,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK;QACvB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkflowExecutor - Core execution logic
|
|
3
|
+
* Processes steps as bunqueue jobs, handles transitions, branching, compensation.
|
|
4
|
+
*/
|
|
5
|
+
import type { Queue } from '../queue/queue';
|
|
6
|
+
import type { Workflow } from './workflow';
|
|
7
|
+
import type { WorkflowStore } from './store';
|
|
8
|
+
import type { Execution, StepJobData, RunHandle } from './types';
|
|
9
|
+
export declare class WorkflowExecutor {
|
|
10
|
+
private readonly store;
|
|
11
|
+
private readonly queue;
|
|
12
|
+
private readonly workflows;
|
|
13
|
+
constructor(store: WorkflowStore, queue: Queue);
|
|
14
|
+
register(workflow: Workflow): void;
|
|
15
|
+
start(workflowName: string, input: unknown): Promise<RunHandle>;
|
|
16
|
+
/** Process a step job — this is the Worker processor function */
|
|
17
|
+
processStep(data: StepJobData): Promise<unknown>;
|
|
18
|
+
signal(executionId: string, event: string, payload: unknown): Promise<void>;
|
|
19
|
+
getExecution(id: string): Execution | null;
|
|
20
|
+
listExecutions(workflowName?: string, state?: Execution['state']): Execution[];
|
|
21
|
+
private executeNode;
|
|
22
|
+
private executeStep;
|
|
23
|
+
private executeBranch;
|
|
24
|
+
private executeWaitFor;
|
|
25
|
+
private advanceToNext;
|
|
26
|
+
private enqueueNode;
|
|
27
|
+
private runCompensation;
|
|
28
|
+
private findStepDef;
|
|
29
|
+
private buildContext;
|
|
30
|
+
private runWithTimeout;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../src/client/workflow/executor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EACX,SAAS,EAIV,MAAM,SAAS,CAAC;AASjB,qBAAa,gBAAgB;IAIzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAJxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+B;gBAGtC,KAAK,EAAE,aAAa,EACpB,KAAK,EAAE,KAAK;IAG/B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAS5B,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC;IAuBrE,iEAAiE;IAC3D,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IA2BhD,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAUjF,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAI1C,cAAc,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,SAAS,EAAE;YAMhE,WAAW;YAeX,WAAW;YAiCX,aAAa;YA2Bb,cAAc;YAkBd,aAAa;YASb,WAAW;YASX,eAAe;IA0B7B,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,cAAc;CAmBvB"}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkflowExecutor - Core execution logic
|
|
3
|
+
* Processes steps as bunqueue jobs, handles transitions, branching, compensation.
|
|
4
|
+
*/
|
|
5
|
+
/** Thrown when a step needs to wait for a signal */
|
|
6
|
+
class WaitForSignalError extends Error {
|
|
7
|
+
event;
|
|
8
|
+
constructor(event) {
|
|
9
|
+
super(`Waiting for signal: ${event}`);
|
|
10
|
+
this.event = event;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class WorkflowExecutor {
|
|
14
|
+
store;
|
|
15
|
+
queue;
|
|
16
|
+
workflows = new Map();
|
|
17
|
+
constructor(store, queue) {
|
|
18
|
+
this.store = store;
|
|
19
|
+
this.queue = queue;
|
|
20
|
+
}
|
|
21
|
+
register(workflow) {
|
|
22
|
+
const names = workflow.getStepNames();
|
|
23
|
+
const dupes = names.filter((n, i) => names.indexOf(n) !== i);
|
|
24
|
+
if (dupes.length > 0) {
|
|
25
|
+
throw new Error(`Duplicate step names in "${workflow.name}": ${dupes.join(', ')}`);
|
|
26
|
+
}
|
|
27
|
+
this.workflows.set(workflow.name, workflow);
|
|
28
|
+
}
|
|
29
|
+
async start(workflowName, input) {
|
|
30
|
+
const wf = this.workflows.get(workflowName);
|
|
31
|
+
if (!wf)
|
|
32
|
+
throw new Error(`Workflow "${workflowName}" not registered`);
|
|
33
|
+
if (wf.nodes.length === 0)
|
|
34
|
+
throw new Error(`Workflow "${workflowName}" has no steps`);
|
|
35
|
+
const now = Date.now();
|
|
36
|
+
const exec = {
|
|
37
|
+
id: `wf_${now}_${Math.random().toString(36).slice(2, 10)}`,
|
|
38
|
+
workflowName,
|
|
39
|
+
state: 'running',
|
|
40
|
+
input,
|
|
41
|
+
steps: {},
|
|
42
|
+
currentNodeIndex: 0,
|
|
43
|
+
signals: {},
|
|
44
|
+
createdAt: now,
|
|
45
|
+
updatedAt: now,
|
|
46
|
+
};
|
|
47
|
+
this.store.save(exec);
|
|
48
|
+
await this.enqueueNode(exec);
|
|
49
|
+
return { id: exec.id, workflowName };
|
|
50
|
+
}
|
|
51
|
+
/** Process a step job — this is the Worker processor function */
|
|
52
|
+
async processStep(data) {
|
|
53
|
+
const exec = this.store.get(data.executionId);
|
|
54
|
+
if (exec?.state !== 'running')
|
|
55
|
+
return null;
|
|
56
|
+
const wf = this.workflows.get(exec.workflowName);
|
|
57
|
+
if (!wf)
|
|
58
|
+
throw new Error(`Workflow "${exec.workflowName}" not registered`);
|
|
59
|
+
const node = wf.nodes[data.nodeIndex];
|
|
60
|
+
if (!node) {
|
|
61
|
+
exec.state = 'completed';
|
|
62
|
+
this.store.update(exec);
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
await this.executeNode(exec, node, data.nodeIndex, wf);
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
if (err instanceof WaitForSignalError)
|
|
70
|
+
return null;
|
|
71
|
+
exec.state = 'failed';
|
|
72
|
+
this.store.update(exec);
|
|
73
|
+
await this.runCompensation(exec, wf);
|
|
74
|
+
throw err;
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
async signal(executionId, event, payload) {
|
|
79
|
+
const exec = this.store.get(executionId);
|
|
80
|
+
if (!exec)
|
|
81
|
+
throw new Error(`Execution "${executionId}" not found`);
|
|
82
|
+
exec.signals[event] = payload;
|
|
83
|
+
exec.state = 'running';
|
|
84
|
+
this.store.update(exec);
|
|
85
|
+
await this.enqueueNode(exec);
|
|
86
|
+
}
|
|
87
|
+
getExecution(id) {
|
|
88
|
+
return this.store.get(id);
|
|
89
|
+
}
|
|
90
|
+
listExecutions(workflowName, state) {
|
|
91
|
+
return this.store.list(workflowName, state);
|
|
92
|
+
}
|
|
93
|
+
// ============ Internal ============
|
|
94
|
+
async executeNode(exec, node, nodeIndex, wf) {
|
|
95
|
+
if (node.type === 'step') {
|
|
96
|
+
await this.executeStep(exec, node.def, nodeIndex, wf);
|
|
97
|
+
}
|
|
98
|
+
else if (node.type === 'branch') {
|
|
99
|
+
await this.executeBranch(exec, node, nodeIndex, wf);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
await this.executeWaitFor(exec, node, nodeIndex);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async executeStep(exec, def, nodeIndex, wf) {
|
|
106
|
+
const ctx = this.buildContext(exec);
|
|
107
|
+
exec.steps[def.name] = { status: 'running', startedAt: Date.now() };
|
|
108
|
+
this.store.update(exec);
|
|
109
|
+
try {
|
|
110
|
+
const result = await this.runWithTimeout(def.handler(ctx), def.timeout);
|
|
111
|
+
exec.steps[def.name] = {
|
|
112
|
+
status: 'completed',
|
|
113
|
+
result,
|
|
114
|
+
startedAt: exec.steps[def.name].startedAt,
|
|
115
|
+
completedAt: Date.now(),
|
|
116
|
+
};
|
|
117
|
+
exec.currentNodeIndex = nodeIndex + 1;
|
|
118
|
+
this.store.update(exec);
|
|
119
|
+
await this.advanceToNext(exec, wf);
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
exec.steps[def.name] = {
|
|
123
|
+
status: 'failed',
|
|
124
|
+
error: String(err),
|
|
125
|
+
startedAt: exec.steps[def.name].startedAt,
|
|
126
|
+
completedAt: Date.now(),
|
|
127
|
+
};
|
|
128
|
+
this.store.update(exec);
|
|
129
|
+
throw err;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async executeBranch(exec, node, nodeIndex, wf) {
|
|
133
|
+
const ctx = this.buildContext(exec);
|
|
134
|
+
const pathName = node.def.condition(ctx);
|
|
135
|
+
const pathSteps = node.def.paths.get(pathName);
|
|
136
|
+
if (!pathSteps || pathSteps.length === 0) {
|
|
137
|
+
exec.currentNodeIndex = nodeIndex + 1;
|
|
138
|
+
this.store.update(exec);
|
|
139
|
+
await this.advanceToNext(exec, wf);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
// Execute branch steps inline
|
|
143
|
+
for (const step of pathSteps) {
|
|
144
|
+
await this.executeStep(exec, step, nodeIndex, wf);
|
|
145
|
+
}
|
|
146
|
+
exec.currentNodeIndex = nodeIndex + 1;
|
|
147
|
+
this.store.update(exec);
|
|
148
|
+
await this.advanceToNext(exec, wf);
|
|
149
|
+
}
|
|
150
|
+
async executeWaitFor(exec, node, nodeIndex) {
|
|
151
|
+
if (exec.signals[node.event] !== undefined) {
|
|
152
|
+
exec.currentNodeIndex = nodeIndex + 1;
|
|
153
|
+
this.store.update(exec);
|
|
154
|
+
await this.enqueueNode(exec);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
// Not yet received — pause execution
|
|
158
|
+
exec.state = 'waiting';
|
|
159
|
+
this.store.update(exec);
|
|
160
|
+
throw new WaitForSignalError(node.event);
|
|
161
|
+
}
|
|
162
|
+
async advanceToNext(exec, wf) {
|
|
163
|
+
if (exec.currentNodeIndex >= wf.nodes.length) {
|
|
164
|
+
exec.state = 'completed';
|
|
165
|
+
this.store.update(exec);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
await this.enqueueNode(exec);
|
|
169
|
+
}
|
|
170
|
+
async enqueueNode(exec) {
|
|
171
|
+
const jobData = {
|
|
172
|
+
executionId: exec.id,
|
|
173
|
+
workflowName: exec.workflowName,
|
|
174
|
+
nodeIndex: exec.currentNodeIndex,
|
|
175
|
+
};
|
|
176
|
+
await this.queue.add('wf:step', jobData);
|
|
177
|
+
}
|
|
178
|
+
async runCompensation(exec, wf) {
|
|
179
|
+
const completedSteps = Object.entries(exec.steps)
|
|
180
|
+
.filter(([, s]) => s.status === 'completed')
|
|
181
|
+
.reverse();
|
|
182
|
+
if (completedSteps.length === 0)
|
|
183
|
+
return;
|
|
184
|
+
exec.state = 'compensating';
|
|
185
|
+
this.store.update(exec);
|
|
186
|
+
const ctx = this.buildContext(exec);
|
|
187
|
+
for (const [name] of completedSteps) {
|
|
188
|
+
const def = this.findStepDef(wf, name);
|
|
189
|
+
if (def?.compensate) {
|
|
190
|
+
try {
|
|
191
|
+
await def.compensate(ctx);
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
// Compensation errors are logged but don't stop the chain
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
exec.state = 'failed';
|
|
199
|
+
this.store.update(exec);
|
|
200
|
+
}
|
|
201
|
+
findStepDef(wf, name) {
|
|
202
|
+
for (const node of wf.nodes) {
|
|
203
|
+
if (node.type === 'step' && node.def.name === name)
|
|
204
|
+
return node.def;
|
|
205
|
+
if (node.type === 'branch') {
|
|
206
|
+
for (const steps of node.def.paths.values()) {
|
|
207
|
+
const found = steps.find((s) => s.name === name);
|
|
208
|
+
if (found)
|
|
209
|
+
return found;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
buildContext(exec) {
|
|
216
|
+
const stepResults = {};
|
|
217
|
+
for (const [name, record] of Object.entries(exec.steps)) {
|
|
218
|
+
if (record.status === 'completed')
|
|
219
|
+
stepResults[name] = record.result;
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
input: exec.input,
|
|
223
|
+
steps: stepResults,
|
|
224
|
+
signals: exec.signals,
|
|
225
|
+
executionId: exec.id,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
runWithTimeout(promise, timeoutMs) {
|
|
229
|
+
if (!(promise instanceof Promise))
|
|
230
|
+
return Promise.resolve(promise);
|
|
231
|
+
if (timeoutMs <= 0)
|
|
232
|
+
return promise;
|
|
233
|
+
return new Promise((resolve, reject) => {
|
|
234
|
+
const timer = setTimeout(() => {
|
|
235
|
+
reject(new Error(`Step timed out after ${timeoutMs}ms`));
|
|
236
|
+
}, timeoutMs);
|
|
237
|
+
promise.then((v) => {
|
|
238
|
+
clearTimeout(timer);
|
|
239
|
+
resolve(v);
|
|
240
|
+
}, (e) => {
|
|
241
|
+
clearTimeout(timer);
|
|
242
|
+
reject(e instanceof Error ? e : new Error(String(e)));
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../src/client/workflow/executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bunqueue Workflow Engine
|
|
3
|
+
*
|
|
4
|
+
* Lightweight workflow orchestration built on top of bunqueue.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { Workflow, Engine } from 'bunqueue/workflow';
|
|
9
|
+
*
|
|
10
|
+
* const flow = new Workflow('onboarding')
|
|
11
|
+
* .step('create', async (ctx) => { ... })
|
|
12
|
+
* .step('notify', async (ctx) => { ... });
|
|
13
|
+
*
|
|
14
|
+
* const engine = new Engine({ embedded: true });
|
|
15
|
+
* engine.register(flow);
|
|
16
|
+
* const run = await engine.start('onboarding', { email: 'user@test.com' });
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export { Workflow } from './workflow';
|
|
20
|
+
export { Engine } from './engine';
|
|
21
|
+
export type { StepContext, StepHandler, CompensateHandler, StepOptions, Execution, ExecutionState, StepState, StepRecord, EngineOptions, RunHandle, } from './types';
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/workflow/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EACV,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,SAAS,EACT,cAAc,EACd,SAAS,EACT,UAAU,EACV,aAAa,EACb,SAAS,GACV,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bunqueue Workflow Engine
|
|
3
|
+
*
|
|
4
|
+
* Lightweight workflow orchestration built on top of bunqueue.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { Workflow, Engine } from 'bunqueue/workflow';
|
|
9
|
+
*
|
|
10
|
+
* const flow = new Workflow('onboarding')
|
|
11
|
+
* .step('create', async (ctx) => { ... })
|
|
12
|
+
* .step('notify', async (ctx) => { ... });
|
|
13
|
+
*
|
|
14
|
+
* const engine = new Engine({ embedded: true });
|
|
15
|
+
* engine.register(flow);
|
|
16
|
+
* const run = await engine.start('onboarding', { email: 'user@test.com' });
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export { Workflow } from './workflow';
|
|
20
|
+
export { Engine } from './engine';
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/workflow/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkflowStore - SQLite persistence for workflow executions
|
|
3
|
+
*/
|
|
4
|
+
import type { Execution, ExecutionState } from './types';
|
|
5
|
+
export declare class WorkflowStore {
|
|
6
|
+
private readonly db;
|
|
7
|
+
private readonly stmts;
|
|
8
|
+
constructor(dbPath?: string);
|
|
9
|
+
save(exec: Execution): void;
|
|
10
|
+
get(id: string): Execution | null;
|
|
11
|
+
update(exec: Execution): void;
|
|
12
|
+
list(workflowName?: string, state?: ExecutionState): Execution[];
|
|
13
|
+
close(): void;
|
|
14
|
+
private rowToExecution;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/client/workflow/store.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAc,MAAM,SAAS,CAAC;AA+BrE,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAW;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAQpB;gBAEU,MAAM,CAAC,EAAE,MAAM;IAgC3B,IAAI,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAe3B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAKjC,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAa7B,IAAI,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,cAAc,GAAG,SAAS,EAAE;IAchE,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,cAAc;CAgBvB"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkflowStore - SQLite persistence for workflow executions
|
|
3
|
+
*/
|
|
4
|
+
import { Database } from 'bun:sqlite';
|
|
5
|
+
import { Packr, Unpackr } from 'msgpackr';
|
|
6
|
+
const packr = new Packr({ structuredClone: true });
|
|
7
|
+
const unpackr = new Unpackr({ structuredClone: true });
|
|
8
|
+
function pack(data) {
|
|
9
|
+
return packr.pack(data);
|
|
10
|
+
}
|
|
11
|
+
function unpack(buf) {
|
|
12
|
+
if (!buf)
|
|
13
|
+
return null;
|
|
14
|
+
return unpackr.unpack(buf);
|
|
15
|
+
}
|
|
16
|
+
const CREATE_TABLE = `
|
|
17
|
+
CREATE TABLE IF NOT EXISTS workflow_executions (
|
|
18
|
+
id TEXT PRIMARY KEY,
|
|
19
|
+
workflow_name TEXT NOT NULL,
|
|
20
|
+
state TEXT NOT NULL DEFAULT 'running',
|
|
21
|
+
input BLOB,
|
|
22
|
+
steps BLOB,
|
|
23
|
+
current_node_index INTEGER NOT NULL DEFAULT 0,
|
|
24
|
+
resolved_steps BLOB,
|
|
25
|
+
signals BLOB,
|
|
26
|
+
created_at INTEGER NOT NULL,
|
|
27
|
+
updated_at INTEGER NOT NULL
|
|
28
|
+
)`;
|
|
29
|
+
const CREATE_IDX_NAME = `CREATE INDEX IF NOT EXISTS idx_wf_name ON workflow_executions(workflow_name)`;
|
|
30
|
+
const CREATE_IDX_STATE = `CREATE INDEX IF NOT EXISTS idx_wf_state ON workflow_executions(state)`;
|
|
31
|
+
export class WorkflowStore {
|
|
32
|
+
db;
|
|
33
|
+
stmts;
|
|
34
|
+
constructor(dbPath) {
|
|
35
|
+
this.db = new Database(dbPath ?? ':memory:', { create: true });
|
|
36
|
+
this.db.run('PRAGMA journal_mode = WAL');
|
|
37
|
+
this.db.run(CREATE_TABLE);
|
|
38
|
+
this.db.run(CREATE_IDX_NAME);
|
|
39
|
+
this.db.run(CREATE_IDX_STATE);
|
|
40
|
+
this.stmts = {
|
|
41
|
+
upsert: this.db.prepare(`
|
|
42
|
+
INSERT OR REPLACE INTO workflow_executions
|
|
43
|
+
(id, workflow_name, state, input, steps, current_node_index, resolved_steps, signals, created_at, updated_at)
|
|
44
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
45
|
+
`),
|
|
46
|
+
get: this.db.prepare(`SELECT * FROM workflow_executions WHERE id = ?`),
|
|
47
|
+
updateState: this.db.prepare(`
|
|
48
|
+
UPDATE workflow_executions
|
|
49
|
+
SET state = ?, steps = ?, current_node_index = ?, resolved_steps = ?, signals = ?, updated_at = ?
|
|
50
|
+
WHERE id = ?
|
|
51
|
+
`),
|
|
52
|
+
list: this.db.prepare(`SELECT * FROM workflow_executions ORDER BY created_at DESC LIMIT 100`),
|
|
53
|
+
listByName: this.db.prepare(`SELECT * FROM workflow_executions WHERE workflow_name = ? ORDER BY created_at DESC LIMIT 100`),
|
|
54
|
+
listByState: this.db.prepare(`SELECT * FROM workflow_executions WHERE state = ? ORDER BY created_at DESC LIMIT 100`),
|
|
55
|
+
listByBoth: this.db.prepare(`SELECT * FROM workflow_executions WHERE workflow_name = ? AND state = ? ORDER BY created_at DESC LIMIT 100`),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
save(exec) {
|
|
59
|
+
this.stmts.upsert.run(exec.id, exec.workflowName, exec.state, pack(exec.input), pack(exec.steps), exec.currentNodeIndex, exec.resolvedSteps ? pack(exec.resolvedSteps) : null, pack(exec.signals), exec.createdAt, exec.updatedAt);
|
|
60
|
+
}
|
|
61
|
+
get(id) {
|
|
62
|
+
const row = this.stmts.get.get(id);
|
|
63
|
+
return row ? this.rowToExecution(row) : null;
|
|
64
|
+
}
|
|
65
|
+
update(exec) {
|
|
66
|
+
exec.updatedAt = Date.now();
|
|
67
|
+
this.stmts.updateState.run(exec.state, pack(exec.steps), exec.currentNodeIndex, exec.resolvedSteps ? pack(exec.resolvedSteps) : null, pack(exec.signals), exec.updatedAt, exec.id);
|
|
68
|
+
}
|
|
69
|
+
list(workflowName, state) {
|
|
70
|
+
let rows;
|
|
71
|
+
if (workflowName && state) {
|
|
72
|
+
rows = this.stmts.listByBoth.all(workflowName, state);
|
|
73
|
+
}
|
|
74
|
+
else if (workflowName) {
|
|
75
|
+
rows = this.stmts.listByName.all(workflowName);
|
|
76
|
+
}
|
|
77
|
+
else if (state) {
|
|
78
|
+
rows = this.stmts.listByState.all(state);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
rows = this.stmts.list.all();
|
|
82
|
+
}
|
|
83
|
+
return rows.map((r) => this.rowToExecution(r));
|
|
84
|
+
}
|
|
85
|
+
close() {
|
|
86
|
+
this.db.close();
|
|
87
|
+
}
|
|
88
|
+
rowToExecution(row) {
|
|
89
|
+
return {
|
|
90
|
+
id: row.id,
|
|
91
|
+
workflowName: row.workflow_name,
|
|
92
|
+
state: row.state,
|
|
93
|
+
input: unpack(row.input),
|
|
94
|
+
steps: unpack(row.steps) ?? {},
|
|
95
|
+
currentNodeIndex: row.current_node_index,
|
|
96
|
+
resolvedSteps: row.resolved_steps
|
|
97
|
+
? unpack(row.resolved_steps)
|
|
98
|
+
: undefined,
|
|
99
|
+
signals: unpack(row.signals) ?? {},
|
|
100
|
+
createdAt: row.created_at,
|
|
101
|
+
updatedAt: row.updated_at,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/client/workflow/store.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAG1C,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;AACnD,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;AAEvD,SAAS,IAAI,CAAC,IAAa;IACzB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,MAAM,CAAC,GAAsB;IACpC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,YAAY,GAAG;;;;;;;;;;;;EAYnB,CAAC;AAEH,MAAM,eAAe,GAAG,8EAA8E,CAAC;AACvG,MAAM,gBAAgB,GAAG,uEAAuE,CAAC;AAEjG,MAAM,OAAO,aAAa;IACP,EAAE,CAAW;IACb,KAAK,CAQpB;IAEF,YAAY,MAAe;QACzB,IAAI,CAAC,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,IAAI,UAAU,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/D,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACzC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC1B,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC7B,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAE9B,IAAI,CAAC,KAAK,GAAG;YACX,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;OAIvB,CAAC;YACF,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,gDAAgD,CAAC;YACtE,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;OAI5B,CAAC;YACF,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,sEAAsE,CAAC;YAC7F,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,CACzB,8FAA8F,CAC/F;YACD,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B,sFAAsF,CACvF;YACD,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,CACzB,4GAA4G,CAC7G;SACF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,IAAe;QAClB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CACnB,IAAI,CAAC,EAAE,EACP,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAChB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAChB,IAAI,CAAC,gBAAgB,EACrB,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,EACpD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAClB,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,SAAS,CACf,CAAC;IACJ,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAmC,CAAC;QACrE,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/C,CAAC;IAED,MAAM,CAAC,IAAe;QACpB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CACxB,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAChB,IAAI,CAAC,gBAAgB,EACrB,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,EACpD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAClB,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,EAAE,CACR,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,YAAqB,EAAE,KAAsB;QAChD,IAAI,IAA+B,CAAC;QACpC,IAAI,YAAY,IAAI,KAAK,EAAE,CAAC;YAC1B,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,CAA8B,CAAC;QACrF,CAAC;aAAM,IAAI,YAAY,EAAE,CAAC;YACxB,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,YAAY,CAA8B,CAAC;QAC9E,CAAC;aAAM,IAAI,KAAK,EAAE,CAAC;YACjB,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAA8B,CAAC;QACxE,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAA+B,CAAC;QAC5D,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,KAAK;QACH,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;IAEO,cAAc,CAAC,GAA4B;QACjD,OAAO;YACL,EAAE,EAAE,GAAG,CAAC,EAAY;YACpB,YAAY,EAAE,GAAG,CAAC,aAAuB;YACzC,KAAK,EAAE,GAAG,CAAC,KAAuB;YAClC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,KAA0B,CAAC;YAC7C,KAAK,EAAG,MAAM,CAAC,GAAG,CAAC,KAA0B,CAAuC,IAAI,EAAE;YAC1F,gBAAgB,EAAE,GAAG,CAAC,kBAA4B;YAClD,aAAa,EAAE,GAAG,CAAC,cAAc;gBAC/B,CAAC,CAAE,MAAM,CAAC,GAAG,CAAC,cAAmC,CAAc;gBAC/D,CAAC,CAAC,SAAS;YACb,OAAO,EAAG,MAAM,CAAC,GAAG,CAAC,OAA4B,CAAoC,IAAI,EAAE;YAC3F,SAAS,EAAE,GAAG,CAAC,UAAoB;YACnC,SAAS,EAAE,GAAG,CAAC,UAAoB;SACpC,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow Engine Types
|
|
3
|
+
*/
|
|
4
|
+
import type { ConnectionOptions } from '../types';
|
|
5
|
+
/** Context passed to step handlers */
|
|
6
|
+
export interface StepContext<TInput = unknown> {
|
|
7
|
+
/** Original workflow input */
|
|
8
|
+
readonly input: TInput;
|
|
9
|
+
/** Results from completed steps (step name → result) */
|
|
10
|
+
readonly steps: Readonly<Record<string, unknown>>;
|
|
11
|
+
/** Signals received via engine.signal() */
|
|
12
|
+
readonly signals: Readonly<Record<string, unknown>>;
|
|
13
|
+
/** Current execution ID */
|
|
14
|
+
readonly executionId: string;
|
|
15
|
+
}
|
|
16
|
+
/** Step handler function */
|
|
17
|
+
export type StepHandler<TInput = unknown, TResult = unknown> = (ctx: StepContext<TInput>) => Promise<TResult> | TResult;
|
|
18
|
+
/** Compensate handler (rollback on failure) */
|
|
19
|
+
export type CompensateHandler<TInput = unknown> = (ctx: StepContext<TInput>) => Promise<void> | void;
|
|
20
|
+
/** Options for a single step */
|
|
21
|
+
export interface StepOptions<TInput = unknown> {
|
|
22
|
+
retry?: number;
|
|
23
|
+
timeout?: number;
|
|
24
|
+
compensate?: CompensateHandler<TInput>;
|
|
25
|
+
}
|
|
26
|
+
/** Internal step definition */
|
|
27
|
+
export interface StepDefinition {
|
|
28
|
+
name: string;
|
|
29
|
+
handler: StepHandler;
|
|
30
|
+
compensate?: CompensateHandler;
|
|
31
|
+
retry: number;
|
|
32
|
+
timeout: number;
|
|
33
|
+
}
|
|
34
|
+
/** Branch condition function */
|
|
35
|
+
export type BranchCondition = (ctx: StepContext) => string;
|
|
36
|
+
/** Internal branch definition */
|
|
37
|
+
export interface BranchDefinition {
|
|
38
|
+
condition: BranchCondition;
|
|
39
|
+
paths: Map<string, StepDefinition[]>;
|
|
40
|
+
}
|
|
41
|
+
/** Workflow node (discriminated union) */
|
|
42
|
+
export type WorkflowNode = {
|
|
43
|
+
type: 'step';
|
|
44
|
+
def: StepDefinition;
|
|
45
|
+
} | {
|
|
46
|
+
type: 'branch';
|
|
47
|
+
def: BranchDefinition;
|
|
48
|
+
} | {
|
|
49
|
+
type: 'waitFor';
|
|
50
|
+
event: string;
|
|
51
|
+
timeout?: number;
|
|
52
|
+
};
|
|
53
|
+
/** Execution state */
|
|
54
|
+
export type ExecutionState = 'running' | 'waiting' | 'completed' | 'failed' | 'compensating';
|
|
55
|
+
/** Step execution state */
|
|
56
|
+
export type StepState = 'pending' | 'running' | 'completed' | 'failed';
|
|
57
|
+
/** Record of a step's execution */
|
|
58
|
+
export interface StepRecord {
|
|
59
|
+
status: StepState;
|
|
60
|
+
result?: unknown;
|
|
61
|
+
error?: string;
|
|
62
|
+
startedAt?: number;
|
|
63
|
+
completedAt?: number;
|
|
64
|
+
}
|
|
65
|
+
/** Full execution state */
|
|
66
|
+
export interface Execution {
|
|
67
|
+
id: string;
|
|
68
|
+
workflowName: string;
|
|
69
|
+
state: ExecutionState;
|
|
70
|
+
input: unknown;
|
|
71
|
+
steps: Record<string, StepRecord>;
|
|
72
|
+
currentNodeIndex: number;
|
|
73
|
+
/** Flattened step list for branch resolution */
|
|
74
|
+
resolvedSteps?: string[];
|
|
75
|
+
signals: Record<string, unknown>;
|
|
76
|
+
createdAt: number;
|
|
77
|
+
updatedAt: number;
|
|
78
|
+
}
|
|
79
|
+
/** Engine configuration */
|
|
80
|
+
export interface EngineOptions {
|
|
81
|
+
embedded?: boolean;
|
|
82
|
+
dataPath?: string;
|
|
83
|
+
connection?: ConnectionOptions;
|
|
84
|
+
/** Internal queue name (default: __wf:steps) */
|
|
85
|
+
queueName?: string;
|
|
86
|
+
/** Worker concurrency (default: 5) */
|
|
87
|
+
concurrency?: number;
|
|
88
|
+
}
|
|
89
|
+
/** Handle returned from engine.start() */
|
|
90
|
+
export interface RunHandle {
|
|
91
|
+
id: string;
|
|
92
|
+
workflowName: string;
|
|
93
|
+
}
|
|
94
|
+
/** Internal job data for step execution */
|
|
95
|
+
export interface StepJobData {
|
|
96
|
+
executionId: string;
|
|
97
|
+
workflowName: string;
|
|
98
|
+
nodeIndex: number;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/client/workflow/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/client/workflow/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow - DSL builder for defining workflow step graphs
|
|
3
|
+
* Pure data structure, no side effects.
|
|
4
|
+
*/
|
|
5
|
+
import type { WorkflowNode, StepHandler, StepOptions, BranchCondition } from './types';
|
|
6
|
+
export declare class Workflow<TInput = unknown> {
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly nodes: WorkflowNode[];
|
|
9
|
+
constructor(name: string);
|
|
10
|
+
/** Add a step to the workflow */
|
|
11
|
+
step(name: string, handler: StepHandler<TInput>, options?: StepOptions<TInput>): this;
|
|
12
|
+
/** Add a branch point — call .path() after this to define paths */
|
|
13
|
+
branch(condition: BranchCondition): this;
|
|
14
|
+
/** Define a branch path (must follow a .branch() call) */
|
|
15
|
+
path(name: string, builder: (w: Workflow<TInput>) => Workflow<TInput>): this;
|
|
16
|
+
/** Wait for an external signal before continuing */
|
|
17
|
+
waitFor(event: string, options?: {
|
|
18
|
+
timeout?: number;
|
|
19
|
+
}): this;
|
|
20
|
+
/** Get flat list of step names for validation */
|
|
21
|
+
getStepNames(): string[];
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../../src/client/workflow/workflow.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,WAAW,EAEX,WAAW,EAEX,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB,qBAAa,QAAQ,CAAC,MAAM,GAAG,OAAO;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAM;gBAExB,IAAI,EAAE,MAAM;IAIxB,iCAAiC;IACjC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI;IAcrF,mEAAmE;IACnE,MAAM,CAAC,SAAS,EAAE,eAAe,GAAG,IAAI;IAQxC,0DAA0D;IAC1D,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI;IAc5E,oDAAoD;IACpD,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAS5D,iDAAiD;IACjD,YAAY,IAAI,MAAM,EAAE;CAazB"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow - DSL builder for defining workflow step graphs
|
|
3
|
+
* Pure data structure, no side effects.
|
|
4
|
+
*/
|
|
5
|
+
export class Workflow {
|
|
6
|
+
name;
|
|
7
|
+
nodes = [];
|
|
8
|
+
constructor(name) {
|
|
9
|
+
this.name = name;
|
|
10
|
+
}
|
|
11
|
+
/** Add a step to the workflow */
|
|
12
|
+
step(name, handler, options) {
|
|
13
|
+
this.nodes.push({
|
|
14
|
+
type: 'step',
|
|
15
|
+
def: {
|
|
16
|
+
name,
|
|
17
|
+
handler: handler,
|
|
18
|
+
compensate: options?.compensate,
|
|
19
|
+
retry: options?.retry ?? 3,
|
|
20
|
+
timeout: options?.timeout ?? 30_000,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
return this;
|
|
24
|
+
}
|
|
25
|
+
/** Add a branch point — call .path() after this to define paths */
|
|
26
|
+
branch(condition) {
|
|
27
|
+
this.nodes.push({
|
|
28
|
+
type: 'branch',
|
|
29
|
+
def: { condition, paths: new Map() },
|
|
30
|
+
});
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
/** Define a branch path (must follow a .branch() call) */
|
|
34
|
+
path(name, builder) {
|
|
35
|
+
const lastNode = this.nodes[this.nodes.length - 1];
|
|
36
|
+
if (lastNode?.type !== 'branch') {
|
|
37
|
+
throw new Error('path() must follow a branch() call');
|
|
38
|
+
}
|
|
39
|
+
const sub = new Workflow(`${this.name}:${name}`);
|
|
40
|
+
builder(sub);
|
|
41
|
+
const steps = sub.nodes
|
|
42
|
+
.filter((n) => n.type === 'step')
|
|
43
|
+
.map((n) => n.def);
|
|
44
|
+
lastNode.def.paths.set(name, steps);
|
|
45
|
+
return this;
|
|
46
|
+
}
|
|
47
|
+
/** Wait for an external signal before continuing */
|
|
48
|
+
waitFor(event, options) {
|
|
49
|
+
this.nodes.push({
|
|
50
|
+
type: 'waitFor',
|
|
51
|
+
event,
|
|
52
|
+
timeout: options?.timeout,
|
|
53
|
+
});
|
|
54
|
+
return this;
|
|
55
|
+
}
|
|
56
|
+
/** Get flat list of step names for validation */
|
|
57
|
+
getStepNames() {
|
|
58
|
+
const names = [];
|
|
59
|
+
for (const node of this.nodes) {
|
|
60
|
+
if (node.type === 'step') {
|
|
61
|
+
names.push(node.def.name);
|
|
62
|
+
}
|
|
63
|
+
else if (node.type === 'branch') {
|
|
64
|
+
for (const steps of node.def.paths.values()) {
|
|
65
|
+
for (const s of steps)
|
|
66
|
+
names.push(s.name);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return names;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=workflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.js","sourceRoot":"","sources":["../../../src/client/workflow/workflow.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,MAAM,OAAO,QAAQ;IACV,IAAI,CAAS;IACb,KAAK,GAAmB,EAAE,CAAC;IAEpC,YAAY,IAAY;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,iCAAiC;IACjC,IAAI,CAAC,IAAY,EAAE,OAA4B,EAAE,OAA6B;QAC5E,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACd,IAAI,EAAE,MAAM;YACZ,GAAG,EAAE;gBACH,IAAI;gBACJ,OAAO,EAAE,OAAsB;gBAC/B,UAAU,EAAE,OAAO,EAAE,UAA2C;gBAChE,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;gBAC1B,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,MAAM;aACpC;SACF,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mEAAmE;IACnE,MAAM,CAAC,SAA0B;QAC/B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACd,IAAI,EAAE,QAAQ;YACd,GAAG,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE;SACrC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,0DAA0D;IAC1D,IAAI,CAAC,IAAY,EAAE,OAAkD;QACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAA6B,CAAC;QAC/E,IAAI,QAAQ,EAAE,IAAI,KAAK,QAAQ,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAS,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,CAAC;QACb,MAAM,KAAK,GAAqB,GAAG,CAAC,KAAK;aACtC,MAAM,CAAC,CAAC,CAAC,EAA8C,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;aAC5E,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACrB,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oDAAoD;IACpD,OAAO,CAAC,KAAa,EAAE,OAA8B;QACnD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACd,IAAI,EAAE,SAAS;YACf,KAAK;YACL,OAAO,EAAE,OAAO,EAAE,OAAO;SAC1B,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,iDAAiD;IACjD,YAAY;QACV,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACzB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAClC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;oBAC5C,KAAK,MAAM,CAAC,IAAI,KAAK;wBAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC5C,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bunqueue",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"description": "High-performance job queue for Bun & AI agents. SQLite persistence, cron scheduling, priorities, retries, DLQ, webhooks, native MCP server. Zero external dependencies.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -25,6 +25,10 @@
|
|
|
25
25
|
"./mcp": {
|
|
26
26
|
"types": "./dist/mcp/index.d.ts",
|
|
27
27
|
"import": "./dist/mcp/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./workflow": {
|
|
30
|
+
"types": "./dist/client/workflow/index.d.ts",
|
|
31
|
+
"import": "./dist/client/workflow/index.js"
|
|
28
32
|
}
|
|
29
33
|
},
|
|
30
34
|
"files": [
|