@meridianjs/workflow-engine 0.1.0 → 1.0.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.
Files changed (2) hide show
  1. package/README.md +129 -0
  2. package/package.json +2 -2
package/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # @meridianjs/workflow-engine
2
+
3
+ DAG-based workflow engine for MeridianJS with LIFO saga compensation. Define multi-step operations where each step declares a rollback function — if any step fails, all previously completed steps are automatically compensated in reverse order.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @meridianjs/workflow-engine
9
+ ```
10
+
11
+ ## Overview
12
+
13
+ Workflows are used for any operation that touches multiple services or needs transactional guarantees. Every mutation route in a MeridianJS application runs through a workflow.
14
+
15
+ ## Core Concepts
16
+
17
+ ### Steps
18
+
19
+ A step is the atomic unit of a workflow. It has a **forward** function (the operation) and an optional **compensation** function (the rollback):
20
+
21
+ ```typescript
22
+ import { createStep, StepResponse } from "@meridianjs/workflow-engine"
23
+ import type { MeridianContainer } from "@meridianjs/types"
24
+
25
+ const createProjectStep = createStep(
26
+ "create-project",
27
+ async (input: { name: string; workspace_id: string }, { container }: { container: MeridianContainer }) => {
28
+ const svc = container.resolve("projectModuleService") as any
29
+ const project = await svc.createProject(input)
30
+ return new StepResponse({ project }, { projectId: project.id })
31
+ },
32
+ // Compensation — called if a later step fails
33
+ async ({ projectId }: { projectId: string }, { container }: { container: MeridianContainer }) => {
34
+ const svc = container.resolve("projectModuleService") as any
35
+ await svc.deleteProject(projectId)
36
+ }
37
+ )
38
+ ```
39
+
40
+ `StepResponse` takes two arguments: the **output** (passed to the next step) and the **compensation data** (passed back to the compensation function if needed).
41
+
42
+ ### Workflows
43
+
44
+ Wire steps together into a named workflow:
45
+
46
+ ```typescript
47
+ import { createWorkflow, WorkflowResponse } from "@meridianjs/workflow-engine"
48
+
49
+ interface CreateProjectInput {
50
+ name: string
51
+ workspace_id: string
52
+ identifier?: string
53
+ }
54
+
55
+ export const createProjectWorkflow = createWorkflow(
56
+ "create-project",
57
+ (input: CreateProjectInput) => {
58
+ const projectResult = createProjectStep(input)
59
+ const statusResult = seedDefaultStatusesStep(projectResult)
60
+ return new WorkflowResponse(statusResult)
61
+ }
62
+ )
63
+ ```
64
+
65
+ ### Running a Workflow
66
+
67
+ Call the workflow from a route handler using `req.scope` as the container:
68
+
69
+ ```typescript
70
+ export const POST = async (req: any, res: Response) => {
71
+ const { result, errors, transaction_status } = await createProjectWorkflow(req.scope).run({
72
+ input: req.body,
73
+ })
74
+
75
+ if (transaction_status === "reverted") {
76
+ res.status(500).json({ error: { message: errors[0].message } })
77
+ return
78
+ }
79
+
80
+ res.status(201).json({ project: result.project })
81
+ }
82
+ ```
83
+
84
+ | `transaction_status` | Meaning |
85
+ |---|---|
86
+ | `"done"` | All steps completed successfully |
87
+ | `"reverted"` | A step failed; compensation ran for all previous steps |
88
+
89
+ ### Conditional Branching
90
+
91
+ Use `when()` to execute steps conditionally:
92
+
93
+ ```typescript
94
+ import { when } from "@meridianjs/workflow-engine"
95
+
96
+ const workflowResult = createWorkflow("my-workflow", (input: Input) => {
97
+ const base = createBaseStep(input)
98
+ const extra = when(base, (data) => data.needsExtra === true, () => extraStep(base))
99
+ return new WorkflowResponse(extra)
100
+ })
101
+ ```
102
+
103
+ ### Data Transformation
104
+
105
+ Use `transform()` to reshape step output before passing it to the next step:
106
+
107
+ ```typescript
108
+ import { transform } from "@meridianjs/workflow-engine"
109
+
110
+ const shaped = transform(stepResult, (data) => ({
111
+ projectId: data.project.id,
112
+ workspaceId: data.project.workspace_id,
113
+ }))
114
+ ```
115
+
116
+ ## API Reference
117
+
118
+ | Export | Description |
119
+ |---|---|
120
+ | `createStep(name, forward, compensate?)` | Define a step with optional rollback |
121
+ | `createWorkflow(name, builder)` | Define a workflow from a step composition function |
122
+ | `StepResponse(output, compensationData?)` | Wrap step output + compensation payload |
123
+ | `WorkflowResponse(stepResult)` | Declare the workflow's final return value |
124
+ | `transform(input, fn)` | Reshape step output |
125
+ | `when(input, condition, fn)` | Conditionally run a step |
126
+
127
+ ## License
128
+
129
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meridianjs/workflow-engine",
3
- "version": "0.1.0",
3
+ "version": "1.0.0",
4
4
  "description": "Meridian workflow engine — DAG runner with LIFO saga compensation",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -25,7 +25,7 @@
25
25
  "prepublishOnly": "npm run build"
26
26
  },
27
27
  "dependencies": {
28
- "@meridianjs/types": "^0.1.0"
28
+ "@meridianjs/types": "^1.0.0"
29
29
  },
30
30
  "devDependencies": {
31
31
  "tsup": "^8.3.5",