flowcraft 1.0.0-beta.1

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 (148) hide show
  1. package/.editorconfig +9 -0
  2. package/LICENSE +21 -0
  3. package/README.md +249 -0
  4. package/config/tsconfig.json +21 -0
  5. package/config/tsup.config.ts +11 -0
  6. package/config/vitest.config.ts +11 -0
  7. package/docs/.vitepress/config.ts +105 -0
  8. package/docs/api-reference/builder.md +158 -0
  9. package/docs/api-reference/fn.md +142 -0
  10. package/docs/api-reference/index.md +38 -0
  11. package/docs/api-reference/workflow.md +126 -0
  12. package/docs/guide/advanced-guides/cancellation.md +117 -0
  13. package/docs/guide/advanced-guides/composition.md +68 -0
  14. package/docs/guide/advanced-guides/custom-executor.md +180 -0
  15. package/docs/guide/advanced-guides/error-handling.md +135 -0
  16. package/docs/guide/advanced-guides/logging.md +106 -0
  17. package/docs/guide/advanced-guides/middleware.md +106 -0
  18. package/docs/guide/advanced-guides/observability.md +175 -0
  19. package/docs/guide/best-practices/debugging.md +182 -0
  20. package/docs/guide/best-practices/state-management.md +120 -0
  21. package/docs/guide/best-practices/sub-workflow-data.md +95 -0
  22. package/docs/guide/best-practices/testing.md +187 -0
  23. package/docs/guide/builders.md +157 -0
  24. package/docs/guide/functional-api.md +133 -0
  25. package/docs/guide/index.md +178 -0
  26. package/docs/guide/recipes/creating-a-loop.md +113 -0
  27. package/docs/guide/recipes/data-processing-pipeline.md +123 -0
  28. package/docs/guide/recipes/fan-out-fan-in.md +112 -0
  29. package/docs/guide/recipes/index.md +15 -0
  30. package/docs/guide/recipes/resilient-api-call.md +110 -0
  31. package/docs/guide/tooling/graph-validation.md +160 -0
  32. package/docs/guide/tooling/mermaid.md +156 -0
  33. package/docs/index.md +56 -0
  34. package/eslint.config.js +16 -0
  35. package/package.json +40 -0
  36. package/pnpm-workspace.yaml +2 -0
  37. package/sandbox/1.basic/README.md +45 -0
  38. package/sandbox/1.basic/package.json +16 -0
  39. package/sandbox/1.basic/src/flow.ts +17 -0
  40. package/sandbox/1.basic/src/main.ts +22 -0
  41. package/sandbox/1.basic/src/nodes.ts +112 -0
  42. package/sandbox/1.basic/src/utils.ts +35 -0
  43. package/sandbox/1.basic/tsconfig.json +3 -0
  44. package/sandbox/2.research/README.md +46 -0
  45. package/sandbox/2.research/package.json +16 -0
  46. package/sandbox/2.research/src/flow.ts +14 -0
  47. package/sandbox/2.research/src/main.ts +31 -0
  48. package/sandbox/2.research/src/nodes.ts +108 -0
  49. package/sandbox/2.research/src/utils.ts +45 -0
  50. package/sandbox/2.research/src/visualize.ts +29 -0
  51. package/sandbox/2.research/tsconfig.json +3 -0
  52. package/sandbox/3.parallel/README.md +65 -0
  53. package/sandbox/3.parallel/package.json +16 -0
  54. package/sandbox/3.parallel/src/main.ts +45 -0
  55. package/sandbox/3.parallel/src/nodes.ts +43 -0
  56. package/sandbox/3.parallel/src/utils.ts +25 -0
  57. package/sandbox/3.parallel/tsconfig.json +3 -0
  58. package/sandbox/4.dag/README.md +179 -0
  59. package/sandbox/4.dag/data/1.blog-post/100.json +60 -0
  60. package/sandbox/4.dag/data/1.blog-post/README.md +25 -0
  61. package/sandbox/4.dag/data/2.job-application/200.json +103 -0
  62. package/sandbox/4.dag/data/2.job-application/201.json +31 -0
  63. package/sandbox/4.dag/data/2.job-application/202.json +31 -0
  64. package/sandbox/4.dag/data/2.job-application/README.md +58 -0
  65. package/sandbox/4.dag/data/3.customer-review/300.json +141 -0
  66. package/sandbox/4.dag/data/3.customer-review/301.json +31 -0
  67. package/sandbox/4.dag/data/3.customer-review/302.json +28 -0
  68. package/sandbox/4.dag/data/3.customer-review/README.md +71 -0
  69. package/sandbox/4.dag/data/4.content-moderation/400.json +161 -0
  70. package/sandbox/4.dag/data/4.content-moderation/401.json +47 -0
  71. package/sandbox/4.dag/data/4.content-moderation/402.json +46 -0
  72. package/sandbox/4.dag/data/4.content-moderation/403.json +31 -0
  73. package/sandbox/4.dag/data/4.content-moderation/README.md +83 -0
  74. package/sandbox/4.dag/package.json +19 -0
  75. package/sandbox/4.dag/src/main.ts +73 -0
  76. package/sandbox/4.dag/src/nodes.ts +134 -0
  77. package/sandbox/4.dag/src/registry.ts +87 -0
  78. package/sandbox/4.dag/src/types.ts +25 -0
  79. package/sandbox/4.dag/src/utils.ts +42 -0
  80. package/sandbox/4.dag/tsconfig.json +3 -0
  81. package/sandbox/5.distributed/.env.example +1 -0
  82. package/sandbox/5.distributed/README.md +88 -0
  83. package/sandbox/5.distributed/data/1.blog-post/100.json +59 -0
  84. package/sandbox/5.distributed/data/1.blog-post/README.md +25 -0
  85. package/sandbox/5.distributed/data/2.job-application/200.json +103 -0
  86. package/sandbox/5.distributed/data/2.job-application/201.json +30 -0
  87. package/sandbox/5.distributed/data/2.job-application/202.json +30 -0
  88. package/sandbox/5.distributed/data/2.job-application/README.md +58 -0
  89. package/sandbox/5.distributed/data/3.customer-review/300.json +141 -0
  90. package/sandbox/5.distributed/data/3.customer-review/301.json +31 -0
  91. package/sandbox/5.distributed/data/3.customer-review/302.json +57 -0
  92. package/sandbox/5.distributed/data/3.customer-review/README.md +71 -0
  93. package/sandbox/5.distributed/data/4.content-moderation/400.json +173 -0
  94. package/sandbox/5.distributed/data/4.content-moderation/401.json +47 -0
  95. package/sandbox/5.distributed/data/4.content-moderation/402.json +46 -0
  96. package/sandbox/5.distributed/data/4.content-moderation/403.json +31 -0
  97. package/sandbox/5.distributed/data/4.content-moderation/README.md +83 -0
  98. package/sandbox/5.distributed/package.json +20 -0
  99. package/sandbox/5.distributed/src/client.ts +124 -0
  100. package/sandbox/5.distributed/src/executor.ts +69 -0
  101. package/sandbox/5.distributed/src/nodes.ts +136 -0
  102. package/sandbox/5.distributed/src/registry.ts +101 -0
  103. package/sandbox/5.distributed/src/types.ts +45 -0
  104. package/sandbox/5.distributed/src/utils.ts +69 -0
  105. package/sandbox/5.distributed/src/worker.ts +217 -0
  106. package/sandbox/5.distributed/tsconfig.json +3 -0
  107. package/sandbox/6.rag/.env.example +1 -0
  108. package/sandbox/6.rag/README.md +60 -0
  109. package/sandbox/6.rag/data/README.md +31 -0
  110. package/sandbox/6.rag/data/rag.json +58 -0
  111. package/sandbox/6.rag/documents/sample-cascade.txt +11 -0
  112. package/sandbox/6.rag/package.json +18 -0
  113. package/sandbox/6.rag/src/main.ts +52 -0
  114. package/sandbox/6.rag/src/nodes/GenerateEmbeddingsNode.ts +54 -0
  115. package/sandbox/6.rag/src/nodes/LLMProcessNode.ts +48 -0
  116. package/sandbox/6.rag/src/nodes/LoadAndChunkNode.ts +40 -0
  117. package/sandbox/6.rag/src/nodes/StoreInVectorDBNode.ts +36 -0
  118. package/sandbox/6.rag/src/nodes/VectorSearchNode.ts +53 -0
  119. package/sandbox/6.rag/src/nodes/index.ts +28 -0
  120. package/sandbox/6.rag/src/registry.ts +23 -0
  121. package/sandbox/6.rag/src/types.ts +44 -0
  122. package/sandbox/6.rag/src/utils.ts +77 -0
  123. package/sandbox/6.rag/tsconfig.json +3 -0
  124. package/sandbox/tsconfig.json +13 -0
  125. package/src/builder/collection.test.ts +287 -0
  126. package/src/builder/collection.ts +269 -0
  127. package/src/builder/graph.test.ts +406 -0
  128. package/src/builder/graph.ts +336 -0
  129. package/src/builder/graph.types.ts +104 -0
  130. package/src/builder/index.ts +3 -0
  131. package/src/context.ts +111 -0
  132. package/src/errors.ts +34 -0
  133. package/src/executor.ts +29 -0
  134. package/src/executors/in-memory.test.ts +93 -0
  135. package/src/executors/in-memory.ts +140 -0
  136. package/src/functions.test.ts +191 -0
  137. package/src/functions.ts +117 -0
  138. package/src/index.ts +5 -0
  139. package/src/logger.ts +41 -0
  140. package/src/types.ts +75 -0
  141. package/src/utils/graph.test.ts +144 -0
  142. package/src/utils/graph.ts +182 -0
  143. package/src/utils/index.ts +3 -0
  144. package/src/utils/mermaid.test.ts +239 -0
  145. package/src/utils/mermaid.ts +133 -0
  146. package/src/utils/sleep.ts +20 -0
  147. package/src/workflow.test.ts +622 -0
  148. package/src/workflow.ts +561 -0
package/.editorconfig ADDED
@@ -0,0 +1,9 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ indent_style = tab
7
+ indent_size = 4
8
+ insert_final_newline = true
9
+ trim_trailing_whitespace = true
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Feathers
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,249 @@
1
+ # Flowcraft: A Workflow Framework
2
+
3
+ Build complex, multi-step processes, from simple sequences to dynamic, graph-driven AI agents.
4
+
5
+ ## Features
6
+
7
+ - **Zero Dependencies**: Lightweight and dependency-free, ensuring a small footprint and easy integration.
8
+
9
+ - **Composable & Reusable**: Define workflows by chaining nodes or embedding other flows as nodes.
10
+
11
+ - **Extensible Execution Engine**: A pluggable `Executor` pattern enables in-memory or distributed flows.
12
+
13
+ - **Type-Safe**: Written in TypeScript to provide strong typing for your workflow definitions and context.
14
+
15
+ - **Async by Default**: Built on an asynchronous foundation to handle I/O-bound and CPU-bound tasks.
16
+
17
+ - **Middleware**: Intercept execution of nodes to handle cross-cutting concerns like logging or auth.
18
+
19
+ - **Conditional Branching**: Direct the flow's execution path based on the results of any node.
20
+
21
+ - **Retry Logic & Fallbacks**: Retry failed operations with configurable delays and fallback logic.
22
+
23
+ - **Cancellation Support**: Gracefully abort running workflows using standard `AbortController`s.
24
+
25
+ - **Pluggable Logging**: Use the built-in `ConsoleLogger` or bring your own (e.g., Pino, Winston).
26
+
27
+ - **Dynamic Graph Engine**: Define complex, graph-based workflows as simple JSON files.
28
+
29
+ - **Fluent & Functional API**: A chainable API on the `Node` class and a collection of functional helpers.
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ npm install flowcraft
35
+ ```
36
+
37
+ ## Quick Start
38
+
39
+ Create and run a simple workflow in a few lines of code.
40
+
41
+ ```typescript
42
+ import { Flow, Node } from 'flowcraft'
43
+
44
+ const greetNode = new Node()
45
+ // The exec method contains the core logic of the node.
46
+ .exec(() => 'Hello, World!')
47
+ // Functional helpers make common tasks easy.
48
+ .tap(console.log)
49
+
50
+ const flow = new Flow(greetNode)
51
+ // Run using the default InMemoryExecutor.
52
+ await flow.run()
53
+ ```
54
+
55
+ ## Learn by Example
56
+
57
+ > [!TIP]
58
+ > The best way to understand the framework is by exploring the included sandbox examples. They are ordered by increasing complexity, each introducing new features and demonstrating the flexibility of the core engine.
59
+
60
+ ### 1. Basic Sequential Flow: Article Writer
61
+
62
+ A simple, linear workflow that demonstrates the core concepts of creating a sequence of nodes to perform a multi-step task like generating an article.
63
+
64
+ ```mermaid
65
+ graph LR
66
+ A[Generate Outline] --> B[Write Content]
67
+ B --> C[Apply Style]
68
+ ```
69
+
70
+ - **Demonstrates**: `Node` chaining, passing data via `Context`, and a simple `BatchFlow`.
71
+ - **[Explore the Basic example »](./sandbox/1.basic/)**
72
+
73
+ ### 2. Conditional Branching: Research Agent
74
+
75
+ A simple agent that uses a loop and conditional branching to decide whether to search the web for information or answer a question based on the current context.
76
+
77
+ ```mermaid
78
+ graph TD
79
+ A{Decide Action} -->|"search"| B[Search Web]
80
+ A -->|"answer"| C[Answer Question]
81
+ B --> A
82
+ ```
83
+
84
+ - **Demonstrates**: Conditional branching with custom actions, creating loops, and building simple state machines.
85
+ - **[Explore the Research Agent example »](./sandbox/2.research/)**
86
+
87
+ ### 3. Parallel Batch Processing: Document Translator
88
+
89
+ A practical example that translates a document into multiple languages concurrently. It uses the `ParallelBatchFlow` builder to showcase significant performance boosts for I/O-bound tasks.
90
+
91
+ ```mermaid
92
+ graph TD
93
+ A[Load README.md] --> B["ParallelBatchFlow"]
94
+ B -- "Chinese" --> T1[TranslateNode]
95
+ B -- "Spanish" --> T2[TranslateNode]
96
+ B -- "Japanese" --> T3[TranslateNode]
97
+ B -- "German" --> T4[TranslateNode]
98
+ T1 --> S1[Save Chinese.md]
99
+ T2 --> S2[Save Spanish.md]
100
+ T3 --> S3[Save Japanese.md]
101
+ T4 --> S4[Save German.md]
102
+ ```
103
+
104
+ - **Demonstrates**: `ParallelBatchFlow` for high-throughput concurrent processing of I/O-bound tasks.
105
+ - **[Explore the Parallel Translation example »](./sandbox/3.parallel/)**
106
+
107
+ ### 4. Dynamic Graph Engine: AI Agent Runtime
108
+
109
+ The most advanced example: a powerful runtime that executes complex, graph-based AI workflows defined in simple JSON-like objects. This shows how to build highly dynamic and modular AI agent systems.
110
+
111
+ > [!IMPORTANT]
112
+ > The `GraphBuilder` is fully **type-safe**. By defining a simple map of your node types to their data payloads, TypeScript can validate your entire graph at compile time, ensuring that the data provided to each node matches what its class expects. This eliminates a whole category of runtime configuration errors.
113
+
114
+ ```mermaid
115
+ graph TD
116
+ A(User Post) --> B[check_for_pii]
117
+ A --> C[check_for_hate_speech]
118
+ A --> D[check_for_spam]
119
+ B --> E{triage_post}
120
+ C --> E
121
+ D --> E
122
+ E -- action_ban --> F["Sub-Workflow: Ban User"]
123
+ E -- action_redact --> G["Sub-Workflow: Redact Post"]
124
+ E -- action_delete_spam --> H["Sub-Workflow: Delete"]
125
+ E -- action_approve --> I[approve_post_branch]
126
+ F --> Z[final_log]
127
+ G --> Z
128
+ H --> Z
129
+ I --> Z
130
+ ```
131
+
132
+ - **Demonstrates**:
133
+ - **Type-safe graph construction** from declarative definitions using `GraphBuilder`.
134
+ - Parallel fan-in and fan-out (mid-flow branching).
135
+ - Reusable, data-driven nodes (e.g., an LLM-powered router).
136
+ - Complex sub-workflow composition.
137
+ - **[Explore the Dynamic AI Agent example »](./sandbox/4.dag/)**
138
+
139
+ ### 5. Distributed Execution: AI Agent with BullMQ
140
+
141
+ This example takes the same type-safe graph definition from the previous example and runs it in a distributed environment using a custom `BullMQExecutor`. It demonstrates a client-worker architecture for building scalable and resilient background job processors.
142
+
143
+ - **Demonstrates**:
144
+ - A pluggable `IExecutor` for distributed workflows.
145
+ - Client-worker architecture with state serialization.
146
+ - Mid-flight, distributed cancellation of long-running jobs.
147
+ - How business logic (the graph) remains unchanged when the execution environment changes.
148
+ - **[Explore the Distributed AI Agent example »](./sandbox/5.distributed/)**
149
+
150
+ ### 6. Advanced RAG Agent: Complex Data & Serialization
151
+
152
+ A complete, end-to-end Retrieval-Augmented Generation (RAG) agent that ingests a document, creates embeddings in parallel, performs a vector search, and synthesizes an answer. This example showcases how to build a sophisticated, data-driven AI workflow.
153
+
154
+ ```mermaid
155
+ graph TD
156
+ A[Load & Chunk Document] --> B[Generate Embeddings]
157
+ B --> C[Store in Vector DB]
158
+ C --> D[Vector Search for Question]
159
+ D --> E[Generate Final Answer]
160
+ ```
161
+
162
+ - **Demonstrates**:
163
+ - A full, practical RAG pipeline.
164
+ - A mix of custom, single-responsibility nodes.
165
+ - Handling complex data types (`Map`, `Date`, custom classes) in the `Context`.
166
+ - The necessity of robust serialization (using `superjson`) for state management.
167
+ - **[Explore the RAG Agent example »](./sandbox/6.rag/)**
168
+
169
+ ## Core Concepts
170
+
171
+ ### Node
172
+
173
+ The `Node` is the fundamental building block of a workflow. It represents a single, potentially asynchronous unit of work with a three-phase lifecycle:
174
+
175
+ 1. `prep(args)`: Prepare data for execution (e.g., fetch from `Context`).
176
+ 2. `exec(args)`: Perform the core logic, isolated from the context.
177
+ 3. `post(args)`: Process results, update the `Context`, and return an "action" string to determine the next step.
178
+
179
+ A chainable API on the `Node` class has a set of functional helpers:
180
+
181
+ - `.map(fn)`: Transform the output of a node.
182
+ - `.filter(predicate)`: Conditionally proceed based on a node's output.
183
+ - `.tap(fn)`: Perform a side-effect without changing the output.
184
+ - `.toContext(key)`: Store a node's result in the context.
185
+
186
+ ### Flow
187
+
188
+ A `Flow` is a special type of `Node` that orchestrates a sequence of other nodes. It contains the logic for traversing its own graph of operations, making it a powerful, self-contained unit of work.
189
+
190
+ ### Executor
191
+
192
+ An `Executor` is responsible for **running** a `Flow`. It provides the top-level execution environment, handling setup and teardown. The framework is decoupled from the execution strategy, allowing you to use the default `InMemoryExecutor` or plug in custom executors for different environments (e.g., distributed queues).
193
+
194
+ ### Middleware
195
+
196
+ A `Flow` can be configured with middleware functions that wrap the execution of every node within it. This is the ideal pattern for handling **cross-cutting concerns** like performance monitoring, centralized logging, or transaction management without cluttering your business logic.
197
+
198
+ ### Context
199
+
200
+ The `Context` is a shared, type-safe `Map`-like object passed through every node in a flow. It acts as a shared memory space, allowing nodes to pass data and share state.
201
+
202
+ ### Actions & Branching
203
+
204
+ A node's `post()` method returns a string called an **action**. The flow uses this action to look up the next node to execute. The default action is a `symbol`, but returning custom strings allows for conditional branching. The fluent `.filter()` method provides another powerful way to branch based on a `FILTER_FAILED` action.
205
+
206
+ ### Builders
207
+
208
+ To simplify the creation of common and complex patterns, the framework provides a `builder` module. These helpers abstract the construction of executable `Flow`s.
209
+
210
+ - **`SequenceFlow`**: Creates a linear flow from a sequence of nodes.
211
+ - **`BatchFlow` / `ParallelBatchFlow`**: Process a collection of items sequentially or concurrently.
212
+ - **`GraphBuilder`**: Translates a declarative graph definition into a fully executable `Flow`.
213
+
214
+ ## Unit Tests
215
+
216
+ > [!TIP]
217
+ > For clear, focused examples of specific, individual features (like retries, middleware, cancellation, and composition), the unit tests are an excellent resource.
218
+
219
+ - Core workflow tests: [`src/workflow.test.ts`](src/workflow.test.ts)
220
+ - Collections tests: [`src/builder/collection.test.ts`](src/builder/collection.test.ts)
221
+ - Graph builder tests: [`src/builder/graph.test.ts`](src/builder/graph.test.ts)
222
+
223
+ ## API Reference
224
+
225
+ ### Core Classes
226
+
227
+ - `Node`: The base class for a unit of work with built-in retry logic and a fluent API (`.map`, `.filter`, etc.).
228
+ - `Flow`: Orchestrates a sequence of nodes and supports middleware via `.use()`.
229
+ - `InMemoryExecutor`: The default `IExecutor` implementation for running flows in-memory.
230
+ - `TypedContext`: The standard `Map`-based implementation for the `Context` interface.
231
+ - `ConsoleLogger`, `NullLogger`: Pre-built logger implementations.
232
+
233
+ ### Functional Helpers
234
+
235
+ A collection of functions for creating nodes and pipelines in a more functional style.
236
+
237
+ - `mapNode`: Creates a `Node` from a simple, pure function.
238
+ - `contextNode`: Creates a `Node` from a function that requires access to the `Context`.
239
+ - `pipeline`: A functional alias for creating a linear sequence of nodes.
240
+
241
+ ### Builder Classes
242
+
243
+ - `SequenceFlow`: A `Flow` that creates a linear flow from a sequence of nodes.
244
+ - `BatchFlow`: A `Flow` that processes a collection of items sequentially.
245
+ - `ParallelBatchFlow`: A `Flow` that processes a collection of items in parallel.
246
+ - `GraphBuilder`: Constructs a `Flow` from a declarative graph definition.
247
+
248
+ ---
249
+ Licensed under the [MIT License](./LICENSE).
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "esnext",
4
+ "module": "esnext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "noImplicitAny": true,
8
+ "declaration": true,
9
+ "outDir": "dist",
10
+ "sourceMap": true,
11
+ "esModuleInterop": true,
12
+ "skipLibCheck": true
13
+ },
14
+ "include": [
15
+ "../src"
16
+ ],
17
+ "exclude": [
18
+ "node_modules",
19
+ "dist"
20
+ ]
21
+ }
@@ -0,0 +1,11 @@
1
+ import { defineConfig } from 'tsup'
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.ts'],
5
+ format: ['esm'],
6
+ dts: true,
7
+ splitting: false,
8
+ sourcemap: true,
9
+ clean: true,
10
+ minify: true,
11
+ })
@@ -0,0 +1,11 @@
1
+ import { defineConfig } from 'vitest/config'
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ environment: 'node',
6
+ globals: true,
7
+ coverage: {
8
+ include: ['src/**/*.ts'],
9
+ },
10
+ },
11
+ })
@@ -0,0 +1,105 @@
1
+ import { defineConfig } from 'vitepress'
2
+ import { MermaidMarkdown, MermaidPlugin } from 'vitepress-plugin-mermaid'
3
+
4
+ export default defineConfig({
5
+ cleanUrls: true, // might need to change depending on deployment
6
+ title: 'Flowcraft',
7
+ description: 'A Workflow Framework',
8
+ vite: {
9
+ optimizeDeps: {
10
+ include: [
11
+ 'mermaid',
12
+ ],
13
+ },
14
+ plugins: [
15
+ MermaidPlugin(),
16
+ ],
17
+ },
18
+ markdown: {
19
+ config: (md) => {
20
+ MermaidMarkdown(md, {})
21
+ },
22
+ },
23
+ themeConfig: {
24
+ nav: [
25
+ { text: 'Guide', link: '/guide', activeMatch: '/guide' },
26
+ { text: 'API', link: '/api-reference', activeMatch: '/api-reference' },
27
+ ],
28
+ footer: {
29
+ message: 'Released under the MIT License.',
30
+ copyright: 'Copyright © 2025-present Goran Spasojevic',
31
+ },
32
+ sidebar: {
33
+ '/guide/': [
34
+ {
35
+ text: 'Guide',
36
+ collapsed: true,
37
+ items: [
38
+ { text: 'Introduction', link: '/guide/' },
39
+ { text: 'Builders', link: '/guide/builders' },
40
+ { text: 'Functional API', link: '/guide/functional-api' },
41
+ ],
42
+ },
43
+ {
44
+ text: 'Advanced Concepts',
45
+ collapsed: true,
46
+ items: [
47
+ { text: 'Composition', link: '/guide/advanced-guides/composition' },
48
+ { text: 'Error Handling', link: '/guide/advanced-guides/error-handling' },
49
+ { text: 'Cancellation', link: '/guide/advanced-guides/cancellation' },
50
+ { text: 'Middleware', link: '/guide/advanced-guides/middleware' },
51
+ { text: 'Pluggable Logging', link: '/guide/advanced-guides/logging' },
52
+ { text: 'Observability', link: '/guide/advanced-guides/observability' },
53
+ { text: 'Custom Executor', link: '/guide/advanced-guides/custom-executor' },
54
+ ],
55
+ },
56
+ {
57
+ text: 'Recipes',
58
+ collapsed: true,
59
+ items: [
60
+ { text: 'Creating a Loop', link: '/guide/recipes/creating-a-loop' },
61
+ { text: 'Fan-out and Fan-in', link: '/guide/recipes/fan-out-fan-in' },
62
+ { text: 'Resilient API Call Node', link: '/guide/recipes/resilient-api-call' },
63
+ { text: 'Data Processing Pipeline', link: '/guide/recipes/data-processing-pipeline' },
64
+ ],
65
+ },
66
+ {
67
+ text: 'Best Practices',
68
+ collapsed: true,
69
+ items: [
70
+ { text: 'State Management', link: '/guide/best-practices/state-management' },
71
+ { text: 'Data Flow in Sub-Workflows', link: '/guide/best-practices/sub-workflow-data' },
72
+ { text: 'Testing Workflows', link: '/guide/best-practices/testing' },
73
+ { text: 'Debugging Workflows', link: '/guide/best-practices/debugging' },
74
+ ],
75
+ },
76
+ {
77
+ text: 'Tooling',
78
+ collapsed: true,
79
+ items: [
80
+ { text: 'Visualizing Workflows', link: '/guide/tooling/mermaid' },
81
+ { text: 'Graph Validation', link: '/guide/tooling/graph-validation' },
82
+ ],
83
+ },
84
+ {
85
+ text: 'API Reference',
86
+ link: '/api-reference/',
87
+ },
88
+ ],
89
+ '/api-reference/': [
90
+ {
91
+ text: 'API Reference',
92
+ items: [
93
+ { text: 'Introduction', link: '/api-reference/' },
94
+ { text: 'Workflow', link: '/api-reference/workflow' },
95
+ { text: 'Builders', link: '/api-reference/builder' },
96
+ { text: 'Functional Helpers', link: '/api-reference/fn' },
97
+ ],
98
+ },
99
+ ],
100
+ },
101
+ socialLinks: [
102
+ { icon: 'github', link: 'https://github.com/gorango/cascade' },
103
+ ],
104
+ },
105
+ })
@@ -0,0 +1,158 @@
1
+ # API Reference: Builders
2
+
3
+ Builders are helper classes provided by Flowcraft to abstract away the manual construction of common and complex workflow patterns. They allow you to define high-level behavior, and the builder handles the underlying `Node` and `Flow` wiring for you.
4
+
5
+ You can import all builders from the main `flowcraft` package.
6
+
7
+ ```typescript
8
+ import {
9
+ BatchFlow,
10
+ GraphBuilder,
11
+ ParallelBatchFlow,
12
+ ParallelFlow,
13
+ SequenceFlow,
14
+ } from 'flowcraft'
15
+ ```
16
+
17
+ ## `SequenceFlow`
18
+
19
+ A `Flow` that creates a linear workflow from a sequence of nodes, automatically chaining them in order.
20
+
21
+ `extends Flow`
22
+
23
+ ### Constructor
24
+
25
+ `new SequenceFlow(...nodes: AbstractNode[])`
26
+
27
+ - `...nodes`: A sequence of `Node` or `Flow` instances to be executed in order.
28
+
29
+ ### Example
30
+
31
+ ```typescript
32
+ const linearFlow = new SequenceFlow(
33
+ new GetUserNode(),
34
+ new ProcessDataNode(),
35
+ new SaveResultNode()
36
+ )
37
+ ```
38
+
39
+ ---
40
+
41
+ ## `ParallelFlow`
42
+
43
+ A `Flow` that executes a collection of nodes concurrently. This is the core of the "fan-out, fan-in" pattern. After all parallel branches complete, the flow proceeds to its single successor.
44
+
45
+ `extends Flow`
46
+
47
+ ### Constructor
48
+
49
+ `new ParallelFlow(nodes: AbstractNode[])`
50
+
51
+ - `nodes`: An array of `Node` or `Flow` instances to be executed in parallel.
52
+
53
+ ### Example
54
+
55
+ ```typescript
56
+ const parallelStep = new ParallelFlow([
57
+ new FetchApiANode(),
58
+ new FetchApiBNode(),
59
+ ])
60
+ const aggregateNode = new AggregateResultsNode()
61
+
62
+ // After both API calls are complete, the aggregateNode will run.
63
+ parallelStep.next(aggregateNode)
64
+ ```
65
+
66
+ ---
67
+
68
+ ## `BatchFlow`
69
+
70
+ An **abstract** `Flow` that processes a collection of items sequentially, one by one.
71
+
72
+ `extends Flow`
73
+
74
+ ### Abstract Members to Implement
75
+
76
+ When you extend `BatchFlow`, you must implement the following:
77
+
78
+ - `protected abstract nodeToRun: AbstractNode`: You must implement this property to provide the `Node` instance that will be executed for each item in the batch.
79
+ - `async prep(args: NodeArgs): Promise<Iterable<any>>`: This method provides the list of parameter objects. The `nodeToRun` will be executed once for each of these objects, with the object's contents merged into the `params`.
80
+
81
+ ---
82
+
83
+ ## `ParallelBatchFlow`
84
+
85
+ An **abstract** `Flow` that processes a collection of items concurrently. This provides a significant performance boost for I/O-bound tasks.
86
+
87
+ `extends Flow`
88
+
89
+ ### Abstract Members to Implement
90
+
91
+ When you extend `ParallelBatchFlow`, you must implement the following:
92
+
93
+ - `protected abstract nodeToRun: AbstractNode`: You must implement this property to provide the `Node` instance that will be executed concurrently for each item in the batch.
94
+ - `async prep(args: NodeArgs): Promise<Iterable<any>>`: This method provides the list of parameter objects to be processed in parallel.
95
+
96
+ ---
97
+
98
+ ## `GraphBuilder`
99
+
100
+ A powerful builder that constructs an executable `Flow` from a declarative `WorkflowGraph` definition (e.g., from a JSON file). It supports a fully type-safe API for compile-time validation of graph definitions.
101
+
102
+ > [!IMPORTANT]
103
+ > To leverage compile-time type safety, you must use the `createNodeRegistry` helper and define a `NodeTypeMap` that maps your node type strings to their expected `data` payloads. This prevents configuration errors before you even run your code.
104
+ >
105
+ > (See how the **[Rag Agent](https://github.com/gorango/flowcraft/tree/master/sandbox/6.rag/)** implements a simple node registry; the **[Dynamic AI Agent](https://github.com/gorango/flowcraft/tree/master/sandbox/4.dag/)** even demonstrates type-safety despite using *dynamic graphs*.)
106
+
107
+ ### Sub-Workflow Composition (Graph Inlining)
108
+
109
+ The `GraphBuilder` has built-in support for composing workflows. You must declare which node types should be treated as sub-workflows by passing them in the `options` parameter of the constructor. When the builder encounters a node of a registered sub-workflow type, it automatically performs **graph inlining**:
110
+
111
+ 1. It fetches the sub-workflow's graph definition from a `WorkflowRegistry` (which must be provided in the `nodeOptionsContext`).
112
+ 2. It injects the sub-workflow's nodes and edges into the parent graph.
113
+ 3. It automatically creates and wires lightweight mapping nodes to handle the data contract defined in the `inputs` and `outputs` properties of the node's `data` payload.
114
+
115
+ This powerful, build-time process creates a single, flattened graph, which simplifies the execution logic for both in-memory and distributed runtimes.
116
+
117
+ ### Constructor
118
+
119
+ `new GraphBuilder(registry, nodeOptionsContext?, options?, logger?)`
120
+
121
+ - `registry: TypedNodeRegistry | NodeRegistry`: An object or `Map` where keys are `type` strings from the graph definition and values are the corresponding `Node` class constructors. For type-safety, use the `createNodeRegistry` helper.
122
+ - `nodeOptionsContext?: Record<string, any>`: An optional object passed to every node's constructor. This is crucial for dependency injection, such as passing a `WorkflowRegistry` instance that the builder can use to resolve sub-workflow graphs.
123
+ - `options?: { subWorkflowNodeTypes?: string[] }`: An optional configuration object.
124
+ - `subWorkflowNodeTypes`: An array of node `type` strings that should be treated as composable sub-workflows. The builder will inline any node whose type is in this list.
125
+ - `logger?: Logger`: An optional `Logger` instance. If provided, the `GraphBuilder` will automatically generate and log a Mermaid.js diagram of the final, flattened graph every time `.build()` is called. This is an invaluable tool for debugging.
126
+
127
+ ### Methods
128
+
129
+ - `.build(graph: WorkflowGraph): BuildResult`: The main method that takes a graph definition and returns a `BuildResult` object.
130
+
131
+ #### The `BuildResult` Object
132
+
133
+ The `.build()` method returns an object containing:
134
+
135
+ - `flow: Flow`: The fully wired, executable `Flow` instance.
136
+ - `nodeMap: Map<string, AbstractNode>`: A map of all created node instances, keyed by their `id` from the graph definition.
137
+ - `predecessorCountMap: Map<string, number>`: A map of each node's `id` to the number of its direct predecessors. This is essential for implementing a reliable "fan-in" or "join" pattern in custom distributed executors.
138
+
139
+ > [!TIP]
140
+ > The `nodeMap` is the most efficient way to get a reference to a specific node instance within a built flow. It provides an instant, O(1) lookup, which is ideal for debugging, monitoring, or dynamic inspection.
141
+ >
142
+ > ```typescript
143
+ > const { flow, nodeMap } = builder.build(myGraph)
144
+ > const specificNode = nodeMap.get('my-node-id')
145
+ > ```
146
+
147
+ ### `WorkflowGraph` Interface
148
+
149
+ The data structure that `GraphBuilder` consumes.
150
+
151
+ - `nodes: GraphNode[] | TypedGraphNode[]`: An array of node definitions.
152
+ - `id: string`: A unique identifier for the node.
153
+ - `type: string`: The key to look up the node's class in the `NodeRegistry`.
154
+ - `data?: Record<string, any>`: A flexible data object passed as options to the node's constructor. For sub-workflow nodes, this must contain a `workflowId`.
155
+ - `edges: GraphEdge[]`: An array of edge definitions.
156
+ - `source: string`: The `id` of the source node.
157
+ - `target: string`: The `id` of the target node.
158
+ - `action?: string`: The action from the source node that triggers this edge. Defaults to `DEFAULT_ACTION`.