flowcraft 1.0.0-beta.9 → 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 (134) hide show
  1. package/README.md +68 -200
  2. package/dist/builder/graph/graph.d.ts +57 -0
  3. package/dist/builder/graph/graph.js +21 -0
  4. package/dist/builder/graph/graph.js.map +1 -0
  5. package/dist/builder/graph/index.d.ts +8 -0
  6. package/dist/builder/graph/index.js +23 -0
  7. package/dist/builder/graph/index.js.map +1 -0
  8. package/dist/builder/graph/internal-nodes.d.ts +59 -0
  9. package/dist/builder/graph/internal-nodes.js +20 -0
  10. package/dist/builder/graph/internal-nodes.js.map +1 -0
  11. package/dist/builder/graph/runner.d.ts +51 -0
  12. package/dist/builder/graph/runner.js +21 -0
  13. package/dist/builder/graph/runner.js.map +1 -0
  14. package/dist/builder/graph/types.d.ts +3 -0
  15. package/dist/builder/graph/types.js +3 -0
  16. package/dist/builder/graph/types.js.map +1 -0
  17. package/dist/builder/index.d.ts +8 -0
  18. package/dist/builder/index.js +24 -0
  19. package/dist/builder/index.js.map +1 -0
  20. package/dist/builder/patterns.d.ts +136 -0
  21. package/dist/builder/patterns.js +19 -0
  22. package/dist/builder/patterns.js.map +1 -0
  23. package/dist/chunk-3YMBNZ77.js +441 -0
  24. package/dist/chunk-3YMBNZ77.js.map +1 -0
  25. package/dist/chunk-64DNBF5W.js +36 -0
  26. package/dist/chunk-64DNBF5W.js.map +1 -0
  27. package/dist/chunk-6QCXIRLA.js +18 -0
  28. package/dist/chunk-6QCXIRLA.js.map +1 -0
  29. package/dist/chunk-7XUN3OQT.js +3 -0
  30. package/dist/chunk-7XUN3OQT.js.map +1 -0
  31. package/dist/chunk-AOHBHYF6.js +7 -0
  32. package/dist/chunk-AOHBHYF6.js.map +1 -0
  33. package/dist/chunk-BRFMFLR6.js +85 -0
  34. package/dist/chunk-BRFMFLR6.js.map +1 -0
  35. package/dist/chunk-ELEHMJPM.js +13 -0
  36. package/dist/chunk-ELEHMJPM.js.map +1 -0
  37. package/dist/chunk-F2RSES6P.js +3 -0
  38. package/dist/chunk-F2RSES6P.js.map +1 -0
  39. package/dist/chunk-F6C6J7HK.js +3 -0
  40. package/dist/chunk-F6C6J7HK.js.map +1 -0
  41. package/dist/chunk-GMKJ34T2.js +3 -0
  42. package/dist/chunk-GMKJ34T2.js.map +1 -0
  43. package/dist/chunk-HEO3XL4Z.js +328 -0
  44. package/dist/chunk-HEO3XL4Z.js.map +1 -0
  45. package/dist/chunk-IIKTTIW5.js +56 -0
  46. package/dist/chunk-IIKTTIW5.js.map +1 -0
  47. package/dist/chunk-KOBEU2EM.js +3 -0
  48. package/dist/chunk-KOBEU2EM.js.map +1 -0
  49. package/dist/chunk-L5PK5VL2.js +178 -0
  50. package/dist/chunk-L5PK5VL2.js.map +1 -0
  51. package/dist/chunk-P3RPDZHO.js +36 -0
  52. package/dist/chunk-P3RPDZHO.js.map +1 -0
  53. package/dist/chunk-PNWOW52F.js +19 -0
  54. package/dist/chunk-PNWOW52F.js.map +1 -0
  55. package/dist/chunk-R27FIYR5.js +62 -0
  56. package/dist/chunk-R27FIYR5.js.map +1 -0
  57. package/dist/chunk-S4WFNGQG.js +17 -0
  58. package/dist/chunk-S4WFNGQG.js.map +1 -0
  59. package/dist/chunk-TS3M7MWA.js +3 -0
  60. package/dist/chunk-TS3M7MWA.js.map +1 -0
  61. package/dist/chunk-UY4PNPBX.js +156 -0
  62. package/dist/chunk-UY4PNPBX.js.map +1 -0
  63. package/dist/chunk-VMH2LRM6.js +114 -0
  64. package/dist/chunk-VMH2LRM6.js.map +1 -0
  65. package/dist/chunk-VZDHIOCH.js +76 -0
  66. package/dist/chunk-VZDHIOCH.js.map +1 -0
  67. package/dist/chunk-WGVHM7DU.js +66 -0
  68. package/dist/chunk-WGVHM7DU.js.map +1 -0
  69. package/dist/chunk-WR5PDOPP.js +91 -0
  70. package/dist/chunk-WR5PDOPP.js.map +1 -0
  71. package/dist/chunk-YR433ZDA.js +20 -0
  72. package/dist/chunk-YR433ZDA.js.map +1 -0
  73. package/dist/context.d.ts +113 -0
  74. package/dist/context.js +3 -0
  75. package/dist/context.js.map +1 -0
  76. package/dist/errors.d.ts +35 -0
  77. package/dist/errors.js +3 -0
  78. package/dist/errors.js.map +1 -0
  79. package/dist/executors/in-memory.d.ts +39 -0
  80. package/dist/executors/in-memory.js +6 -0
  81. package/dist/executors/in-memory.js.map +1 -0
  82. package/dist/executors/types.d.ts +3 -0
  83. package/dist/executors/types.js +3 -0
  84. package/dist/executors/types.js.map +1 -0
  85. package/dist/functions.d.ts +88 -0
  86. package/dist/functions.js +21 -0
  87. package/dist/functions.js.map +1 -0
  88. package/dist/index.d.ts +16 -1066
  89. package/dist/index.js +26 -5
  90. package/dist/index.js.map +1 -1
  91. package/dist/logger.d.ts +43 -0
  92. package/dist/logger.js +3 -0
  93. package/dist/logger.js.map +1 -0
  94. package/dist/types-U76Ukj96.d.ts +609 -0
  95. package/dist/types.d.ts +3 -0
  96. package/dist/types.js +3 -0
  97. package/dist/types.js.map +1 -0
  98. package/dist/utils/analysis.d.ts +75 -0
  99. package/dist/utils/analysis.js +3 -0
  100. package/dist/utils/analysis.js.map +1 -0
  101. package/dist/utils/index.d.ts +8 -0
  102. package/dist/utils/index.js +10 -0
  103. package/dist/utils/index.js.map +1 -0
  104. package/dist/utils/mermaid.d.ts +46 -0
  105. package/dist/utils/mermaid.js +4 -0
  106. package/dist/utils/mermaid.js.map +1 -0
  107. package/dist/utils/middleware.d.ts +11 -0
  108. package/dist/utils/middleware.js +3 -0
  109. package/dist/utils/middleware.js.map +1 -0
  110. package/dist/utils/sanitize.d.ts +19 -0
  111. package/dist/utils/sanitize.js +3 -0
  112. package/dist/utils/sanitize.js.map +1 -0
  113. package/dist/utils/sleep.d.ts +9 -0
  114. package/dist/utils/sleep.js +4 -0
  115. package/dist/utils/sleep.js.map +1 -0
  116. package/dist/workflow/AbstractNode.d.ts +3 -0
  117. package/dist/workflow/AbstractNode.js +4 -0
  118. package/dist/workflow/AbstractNode.js.map +1 -0
  119. package/dist/workflow/Flow.d.ts +3 -0
  120. package/dist/workflow/Flow.js +16 -0
  121. package/dist/workflow/Flow.js.map +1 -0
  122. package/dist/workflow/Node.d.ts +3 -0
  123. package/dist/workflow/Node.js +15 -0
  124. package/dist/workflow/Node.js.map +1 -0
  125. package/dist/workflow/index.d.ts +4 -0
  126. package/dist/workflow/index.js +18 -0
  127. package/dist/workflow/index.js.map +1 -0
  128. package/dist/workflow/node-patterns.d.ts +55 -0
  129. package/dist/workflow/node-patterns.js +16 -0
  130. package/dist/workflow/node-patterns.js.map +1 -0
  131. package/dist/workflow/registry.d.ts +17 -0
  132. package/dist/workflow/registry.js +3 -0
  133. package/dist/workflow/registry.js.map +1 -0
  134. package/package.json +30 -11
package/README.md CHANGED
@@ -1,65 +1,72 @@
1
1
  # Flowcraft: A Workflow Framework
2
2
 
3
- Build complex, multi-step processes, from simple sequences to dynamic, graph-driven AI agents.
3
+ [![npm version](https://img.shields.io/npm/v/flowcraft.svg)](https://www.npmjs.com/package/flowcraft)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ Build complex, multi-step processes with a lightweight, composable, and type-safe TypeScript framework. Model everything from simple sequences to dynamic AI agents, running in-memory or across distributed systems.
7
+
8
+ **[Read the Friendly Manual »](https://gorango.github.io/flowcraft/guide/)**
4
9
 
5
10
  ## Features
6
11
 
7
12
  - **Zero Dependencies**: Lightweight and dependency-free, ensuring a small footprint and easy integration.
13
+ - **Composable & Reusable**: Define workflows by chaining nodes or declaratively embedding other flows as nodes.
14
+ - **Type-Safe by Default**: Strong typing for workflow definitions, shared state, and node parameters.
15
+ - **Async First**: Built on an asynchronous foundation to handle I/O-bound tasks gracefully.
16
+ - **Resilient & Reliable**: Built-in support for retries with configurable delays and fallback logic.
17
+ - **Dynamic Graph Engine**: Construct executable workflows from declarative JSON, ideal for AI agents.
18
+ - **Extensible Execution**: A pluggable Executor pattern enables in-memory or distributed flows.
19
+ - **Advanced Control Flow**: Full support for conditional branching, loops, and parallel execution.
20
+ - **Modern Tooling**: A fluent functional API, static graph validation, and automatic visualizations.
8
21
 
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.
22
+ ---
12
23
 
13
- - **Type-Safe**: Written in TypeScript to provide strong typing for your workflow definitions, context, and node parameters.
24
+ Flowcraft is a lightweight, zero-dependency TypeScript framework for building complex, multi-step processes. It empowers you to model everything from simple sequential tasks to dynamic, graph-driven AI agents with a clear and composable API.
14
25
 
15
- - **Async by Default**: Built on an asynchronous foundation to handle I/O-bound and CPU-bound tasks.
26
+ At its core, Flowcraft is guided by a few key principles:
16
27
 
17
- - **Middleware**: Intercept execution of nodes to handle cross-cutting concerns like logging or auth.
28
+ 1. **Structure for Complexity**: It provides a clear way to model asynchronous processes. By breaking logic into discrete `Node`s with a defined lifecycle, you can turn tangled promise chains and `async/await` blocks into maintainable, testable graphs.
29
+ 2. **Start Simple, Scale Gracefully**: You can start with an in-memory workflow in a single file. As your needs grow, the architecture allows you to scale up to a robust, distributed system using message queues—**without changing your core business logic**.
30
+ 3. **Composability is Key**: A `Flow` is just a specialized `Node`. This simple but powerful concept means entire workflows can be treated as building blocks, allowing you to create highly modular and reusable systems.
18
31
 
19
- - **Conditional Branching**: Direct the flow's execution path based on the results of any node.
32
+ ## The Two Paths of Flowcraft
20
33
 
21
- - **Retry Logic & Fallbacks**: Retry failed operations with configurable delays and fallback logic.
34
+ Flowcraft is designed to cater to two primary use cases, and the documentation is structured to guide you down the path that best fits your needs:
22
35
 
23
- - **Cancellation Support**: Gracefully abort running workflows using standard `AbortController`s.
36
+ ### 1. Programmatic Workflows
24
37
 
25
- - **Pluggable Logging**: Use the built-in `ConsoleLogger` or bring your own (e.g., Pino, Winston).
38
+ This is the path for developers who want to build and manage workflows directly within their application's code. Using a fluent, chainable API and functional helpers, you can quickly define, test, and run complex processes in-memory.
26
39
 
27
- - **Dynamic Graph Engine**: Define complex, graph-based workflows as simple JSON files.
40
+ **Choose this path if you are:**
28
41
 
29
- - **Fluent & Functional API**: A chainable API on the `Node` class and a collection of functional helpers.
42
+ - Building background jobs for a web application.
43
+ - Creating complex, multi-step data processing pipelines.
44
+ - Looking for a structured way to manage complex `async/await` logic.
30
45
 
31
- ## Installation
46
+ **[Learn how to build Programmatic Workflows »](https://gorango.github.io/flowcraft/guide/programmatic/basics.html)**
32
47
 
33
- ```bash
34
- npm install flowcraft
35
- ```
48
+ ### 2. Declarative Workflows (for Scale)
36
49
 
37
- ## Quick Start
50
+ This is the path for architects and developers building dynamic, data-driven, or distributed systems. You define your workflow's structure as a declarative data format (like JSON), and the `GraphBuilder` "compiles" it into an executable, serializable `Blueprint`.
38
51
 
39
- Create and run a simple workflow in a few lines of code.
52
+ **Choose this path if you are:**
40
53
 
41
- ```typescript
42
- import { Flow, Node } from 'flowcraft'
54
+ - Building a system where workflows are defined by users or stored in a database.
55
+ - Creating a runtime for dynamic AI agents.
56
+ - Architecting a distributed system where tasks are executed by a pool of workers.
43
57
 
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)
58
+ **[Learn how to build Declarative Workflows »](https://gorango.github.io/flowcraft/guide/declarative/basics.html)**
49
59
 
50
- const flow = new Flow(greetNode)
51
- // Run using the default InMemoryExecutor.
52
- await flow.run()
53
- ```
60
+ ---
54
61
 
55
62
  ## Learn by Example
56
63
 
57
64
  > [!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.
65
+ > The best way to learn is by exploring the included sandbox examples. They are ordered by complexity, each demonstrating a new feature of the core engine.
59
66
 
60
67
  ### 1. Basic Sequential Flow: Article Writer
61
68
 
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.
69
+ A simple, linear workflow that demonstrates the core concepts of creating a sequence of nodes to perform a multi-step task.
63
70
 
64
71
  ```mermaid
65
72
  graph LR
@@ -67,8 +74,8 @@ graph LR
67
74
  B --> C[Apply Style]
68
75
  ```
69
76
 
70
- - **Demonstrates**: `Node` chaining, passing data via `Context`, and a simple `BatchFlow`.
71
- - **[Explore the Basic example »](./sandbox/1.basic/)**
77
+ - **Demonstrates**: `Node` chaining, passing data via `Context`.
78
+ - **[Explore the Basic example »](https://github.com/gorango/flowcraft/tree/main/sandbox/1.basic/)**
72
79
 
73
80
  ### 2. Conditional Branching: Research Agent
74
81
 
@@ -81,12 +88,12 @@ graph TD
81
88
  B --> A
82
89
  ```
83
90
 
84
- - **Demonstrates**: Conditional branching with custom actions, creating loops, and building simple state machines.
85
- - **[Explore the Research Agent example »](./sandbox/2.research/)**
91
+ - **Demonstrates**: Conditional branching, creating loops, and building simple state machines.
92
+ - **[Explore the Research Agent example »](https://github.com/gorango/flowcraft/tree/main/sandbox/2.research/)**
86
93
 
87
94
  ### 3. Parallel Batch Processing: Document Translator
88
95
 
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.
96
+ A practical example that translates a document into multiple languages concurrently using `ParallelBatchFlow` for a massive performance boost on I/O-bound tasks.
90
97
 
91
98
  ```mermaid
92
99
  graph TD
@@ -94,192 +101,53 @@ graph TD
94
101
  B -- "Chinese" --> T1[TranslateNode]
95
102
  B -- "Spanish" --> T2[TranslateNode]
96
103
  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]
104
+ T1 & T2 & T3 --> S[Save Files]
102
105
  ```
103
106
 
104
- - **Demonstrates**: `ParallelBatchFlow` for high-throughput concurrent processing of I/O-bound tasks.
105
- - **[Explore the Parallel Translation example »](./sandbox/3.parallel/)**
107
+ - **Demonstrates**: High-throughput concurrent processing for data-parallel tasks.
108
+ - **[Explore the Parallel Translation example »](https://github.com/gorango/flowcraft/tree/main/sandbox/3.parallel/)**
106
109
 
107
110
  ### 4. Dynamic Graph Engine: AI Agent Runtime
108
111
 
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.
112
+ 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.
113
113
 
114
114
  ```mermaid
115
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
116
+ A(User Post) --> B[check_pii] & C[check_hate_speech] & D[check_spam]
117
+ B & C & D --> E{triage_post}
122
118
  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
119
+ E -- action_approve --> G[approve_post_branch]
130
120
  ```
131
121
 
132
122
  - **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/)**
123
+ - Type-safe graph construction from declarative definitions using `GraphBuilder`.
124
+ - Parallel fan-in and fan-out.
125
+ - Reusable, data-driven nodes and complex sub-workflow composition.
126
+ - **[Explore the Dynamic AI Agent example »](https://github.com/gorango/flowcraft/tree/main/sandbox/4.dag/)**
138
127
 
139
128
  ### 5. Distributed Execution: AI Agent with BullMQ
140
129
 
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.
130
+ This example takes the same type-safe graph definition from the previous example and runs it in a distributed environment using a custom `BullMQExecutor`, demonstrating a client-worker architecture for scalable background jobs.
142
131
 
143
132
  - **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/)**
133
+ - A pluggable `IExecutor` for distributed workflows.
134
+ - How business logic (the graph) remains unchanged when the execution environment changes.
135
+ - **[Explore the Distributed AI Agent example »](https://github.com/gorango/flowcraft/tree/main/sandbox/5.distributed/)**
149
136
 
150
137
  ### 6. Advanced RAG Agent: Complex Data & Serialization
151
138
 
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
- ```
139
+ A complete Retrieval-Augmented Generation (RAG) agent that ingests a document, creates embeddings, performs a vector search, and synthesizes an answer, showcasing a sophisticated, data-driven AI workflow.
161
140
 
162
141
  - **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 unit of work and is fully generic, allowing you to define types for its lifecycle results and its static parameters.
174
-
175
- The class signature is: `Node<PrepRes, ExecRes, PostRes, TParams>`
176
-
177
- - `PrepRes`: The type of data returned by the `prep` phase.
178
- - `ExecRes`: The type of data returned by the `exec` phase.
179
- - `PostRes`: The type of the "action" returned by the `post` phase.
180
- - `TParams`: The type of the static parameters object for the node, accessible via `.withParams()`.
181
-
182
- **Example: A Type-Safe GreetNode**
183
-
184
- For nodes that do require static configuration, you can provide a type for the parameters to get full autocompletion and compile-time safety.
185
-
186
- ```typescript
187
- // 1. Define the shape of the node's parameters.
188
- interface GreetParams {
189
- greeting: string
190
- loudly: boolean
191
- }
192
-
193
- // 2. Define the node with the TParams generic.
194
- class GreetNode extends Node<void, string, any, GreetParams> {
195
- // 3. The 'exec' method can safely access typed parameters.
196
- async exec({ params }: NodeArgs<GreetParams>): Promise<string> {
197
- let message = `${params.greeting}, World!`
198
- if (params.loudly) {
199
- message = message.toUpperCase()
200
- }
201
- return message
202
- }
203
- }
204
-
205
- // 4. Instantiate and configure with type-safe .withParams()
206
- const greetNode = new GreetNode()
207
- .withParams({ greeting: 'Hello', loudly: true }) // Autocompletes and type-checks!
208
- .tap(console.log) // "HELLO, WORLD!"
209
-
210
- // TypeScript would throw an error on this line:
211
- // greetNode.withParams({ greting: 'Hi', loudly: false }); // Property 'greting' does not exist.
212
- ```
213
-
214
- A chainable API on the `Node` class has a set of functional helpers:
215
-
216
- - `.withParams(params)`: Sets type-safe static parameters for the node.
217
- - `.map(fn)`: Transform the output of a node.
218
- - `.filter(predicate)`: Conditionally proceed based on a node's output.
219
- - `.tap(fn)`: Perform a side-effect without changing the output.
220
- - `.toContext(key)`: Store a node's result in the context.
221
-
222
- ### Flow
223
-
224
- A `Flow` is a special type of `Node` that orchestrates a sequence of other nodes. It is also generic (`Flow<PrepRes, ExecRes, TParams>`) and can be configured with its own parameters and middleware. It contains the logic for traversing its own graph of operations, making it a powerful, self-contained unit of work.
225
-
226
- ### Executor
227
-
228
- 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).
229
-
230
- ### Middleware
142
+ - A full, practical RAG pipeline with custom nodes.
143
+ - Handling complex data types (`Map`, `Date`, etc.) in the `Context`.
144
+ - Robust serialization (using `superjson`) for reliable state management.
145
+ - **[Explore the RAG Agent example &raquo;](https://github.com/gorango/flowcraft/tree/main/sandbox/6.rag/)**
231
146
 
232
- 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.
147
+ ## Documentation
233
148
 
234
- ### Context
235
-
236
- 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.
237
-
238
- ### Actions & Branching
239
-
240
- 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.
241
-
242
- ### Builders
243
-
244
- To simplify the creation of common and complex patterns, the framework provides a `builder` module. These helpers abstract the construction of executable `Flow`s.
245
-
246
- - **`SequenceFlow`**: Creates a linear flow from a sequence of nodes.
247
- - **`BatchFlow` / `ParallelBatchFlow`**: Process a collection of items sequentially or concurrently.
248
- - **`GraphBuilder`**: Translates a declarative graph definition into a fully executable `Flow`.
249
-
250
- ## Unit Tests
251
-
252
- > [!TIP]
253
- > For clear, focused examples of specific, individual features (like retries, middleware, cancellation, and composition), the unit tests are an excellent resource.
254
-
255
- - Core workflow tests: [`src/workflow.test.ts`](src/workflow.test.ts)
256
- - Collections tests: [`src/builder/collection.test.ts`](src/builder/collection.test.ts)
257
- - Graph builder tests: [`src/builder/graph.test.ts`](src/builder/graph.test.ts)
258
-
259
- ## API Reference
260
-
261
- ### Core Classes
262
-
263
- - `Node`: The base class for a unit of work: `Node<PrepRes, ExecRes, PostRes, TParams>`. It has built-in retry logic and a fluent API (`.map`, `.filter`, etc.).
264
- - `Flow`: Orchestrates a sequence of nodes: `Flow<PrepRes, ExecRes, TParams>`. Supports middleware via `.use()`.
265
- - `InMemoryExecutor`: The default `IExecutor` implementation for running flows in-memory.
266
- - `TypedContext`: The standard `Map`-based implementation for the `Context` interface.
267
- - `ConsoleLogger`, `NullLogger`: Pre-built logger implementations.
268
-
269
- ### Functional Helpers
270
-
271
- A collection of functions for creating nodes and pipelines in a more functional style.
272
-
273
- - `mapNode`: Creates a `Node` from a simple, pure function: `mapNode<TIn extends Params, TOut>(fn)`. The function receives the node's `params` as its input.
274
- - `contextNode`: Creates a `Node` from a function that requires access to the `Context`: `contextNode<TIn extends Params, TOut>(fn)`. The function receives the context and the node's `params`.
275
- - `pipeline`: A functional alias for creating a linear sequence of nodes.
276
-
277
- ### Builder Classes
278
-
279
- - `SequenceFlow`: A `Flow` that creates a linear flow from a sequence of nodes.
280
- - `BatchFlow`: A `Flow` that processes a collection of items sequentially.
281
- - `ParallelBatchFlow`: A `Flow` that processes a collection of items in parallel.
282
- - `GraphBuilder`: Constructs a `Flow` from a declarative graph definition.
149
+ For a deep dive into all features, patterns, and APIs, please see the **[complete Flowcraft documentation](https://gorango.github.io/flowcraft/guide/)**.
283
150
 
284
151
  ---
285
- Licensed under the [MIT License](./LICENSE).
152
+
153
+ Licensed under the [MIT License](https://github.com/gorango/flowcraft/tree/main/LICENSE).
@@ -0,0 +1,57 @@
1
+ import { Logger } from '../../logger.js';
2
+ import { f as NodeTypeMap, i as TypedNodeRegistry, n as NodeRegistry, o as GraphBuilderOptions, h as TypedWorkflowGraph, k as BuildResult, m as WorkflowGraph, B as BlueprintBuildResult } from '../../types-U76Ukj96.js';
3
+ import '../../context.js';
4
+
5
+ /**
6
+ * A smart factory that takes an object of custom node classes and returns a fully
7
+ * prepared `NodeRegistry` map with all internal nodes required by the GraphBuilder.
8
+ *
9
+ * @param registry An object where keys are node type strings and values are the corresponding Node constructors.
10
+ * @returns A `Map` instance ready to be used by the `GraphBuilder` or a custom executor.
11
+ */
12
+ declare function createNodeRegistry<TNodeMap extends NodeTypeMap, TContext = object>(registry: TypedNodeRegistry<TNodeMap, TContext>): NodeRegistry;
13
+ /**
14
+ * Constructs a serializable `WorkflowBlueprint` from a declarative `WorkflowGraph` definition.
15
+ * The blueprint is a static, storable artifact that can be executed by a `BlueprintExecutor`.
16
+ * @template TNodeMap A `NodeTypeMap` for validating type-safe graph definitions.
17
+ * @template TContext The shape of the dependency injection context object.
18
+ */
19
+ declare class GraphBuilder<TNodeMap extends NodeTypeMap, TContext extends object = object> {
20
+ private nodeOptionsContext;
21
+ private registry;
22
+ private subWorkflowNodeTypes;
23
+ private conditionalNodeTypes;
24
+ private subWorkflowResolver?;
25
+ private logger;
26
+ /**
27
+ * @param registry A type-safe object or a `Map` where keys are node `type` strings and
28
+ * values are the corresponding `Node` class constructors. For type-safety, use `createNodeRegistry`.
29
+ * @param nodeOptionsContext An optional object that is passed to every node's
30
+ * constructor, useful for dependency injection (e.g., passing a database client or the builder itself).
31
+ */
32
+ constructor(registry: TypedNodeRegistry<TNodeMap, TContext>, nodeOptionsContext?: TContext, options?: GraphBuilderOptions, logger?: Logger);
33
+ constructor(registry: NodeRegistry, nodeOptionsContext?: Record<string, any>, options?: GraphBuilderOptions, logger?: Logger);
34
+ private _logMermaid;
35
+ private _flattenGraph;
36
+ /**
37
+ * Builds a runnable `Flow` from a graph definition for immediate in-memory execution.
38
+ * @param graph The `WorkflowGraph` object describing the flow.
39
+ * @param log Whether to log the graph after flattening. Defaults to `false`.
40
+ * @returns A `BuildResult` object containing the executable `flow` and a `nodeMap`.
41
+ */
42
+ build(graph: TypedWorkflowGraph<TNodeMap>, log?: boolean): BuildResult;
43
+ build(graph: WorkflowGraph, log?: boolean): BuildResult;
44
+ /**
45
+ * Builds a serializable `WorkflowBlueprint` from a graph definition.
46
+ * This is the recommended method for preparing a workflow for a distributed environment.
47
+ * @param graph The `WorkflowGraph` object describing the flow.
48
+ * @returns A `BlueprintBuildResult` object containing the serializable `blueprint`.
49
+ */
50
+ buildBlueprint(graph: TypedWorkflowGraph<TNodeMap>): BlueprintBuildResult;
51
+ buildBlueprint(graph: WorkflowGraph): BlueprintBuildResult;
52
+ private _createPredecessorIdMaps;
53
+ private _findBranchTerminals;
54
+ private _findConditionalConvergence;
55
+ }
56
+
57
+ export { GraphBuilder, createNodeRegistry };
@@ -0,0 +1,21 @@
1
+ export { GraphBuilder, createNodeRegistry } from '../../chunk-3YMBNZ77.js';
2
+ import '../../chunk-WGVHM7DU.js';
3
+ import '../../chunk-L5PK5VL2.js';
4
+ import '../../chunk-F6C6J7HK.js';
5
+ import '../../chunk-UY4PNPBX.js';
6
+ import '../../chunk-ELEHMJPM.js';
7
+ import '../../chunk-HEO3XL4Z.js';
8
+ import '../../chunk-7XUN3OQT.js';
9
+ import '../../chunk-WR5PDOPP.js';
10
+ import '../../chunk-VMH2LRM6.js';
11
+ import '../../chunk-YR433ZDA.js';
12
+ import '../../chunk-6QCXIRLA.js';
13
+ import '../../chunk-BRFMFLR6.js';
14
+ import '../../chunk-PNWOW52F.js';
15
+ import '../../chunk-VZDHIOCH.js';
16
+ import '../../chunk-S4WFNGQG.js';
17
+ import '../../chunk-64DNBF5W.js';
18
+ import '../../chunk-IIKTTIW5.js';
19
+ import '../../chunk-AOHBHYF6.js';
20
+ //# sourceMappingURL=graph.js.map
21
+ //# sourceMappingURL=graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"graph.js"}
@@ -0,0 +1,8 @@
1
+ export { GraphBuilder, createNodeRegistry } from './graph.js';
2
+ export { ConditionalJoinNode, InputMappingNode, OutputMappingNode, ParallelBranchContainer, SubWorkflowContainerNode } from './internal-nodes.js';
3
+ export { BlueprintExecutor } from './runner.js';
4
+ export { B as BlueprintBuildResult, k as BuildResult, o as GraphBuilderOptions, G as GraphEdge, l as GraphNode, g as NodeConstructorOptions, n as NodeRegistry, f as NodeTypeMap, O as OriginalPredecessorIdMap, j as PredecessorIdMap, S as SubWorkflowResolver, T as TypedGraphNode, i as TypedNodeRegistry, h as TypedWorkflowGraph, W as WorkflowBlueprint, m as WorkflowGraph } from '../../types-U76Ukj96.js';
5
+ import '../patterns.js';
6
+ import '../../logger.js';
7
+ import '../../context.js';
8
+ import '../../functions.js';
@@ -0,0 +1,23 @@
1
+ import '../../chunk-GMKJ34T2.js';
2
+ import '../../chunk-KOBEU2EM.js';
3
+ export { BlueprintExecutor, GraphBuilder, createNodeRegistry } from '../../chunk-3YMBNZ77.js';
4
+ export { ConditionalJoinNode, InputMappingNode, OutputMappingNode, ParallelBranchContainer, SubWorkflowContainerNode } from '../../chunk-WGVHM7DU.js';
5
+ import '../../chunk-L5PK5VL2.js';
6
+ import '../../chunk-F6C6J7HK.js';
7
+ import '../../chunk-UY4PNPBX.js';
8
+ import '../../chunk-ELEHMJPM.js';
9
+ import '../../chunk-HEO3XL4Z.js';
10
+ import '../../chunk-7XUN3OQT.js';
11
+ import '../../chunk-WR5PDOPP.js';
12
+ import '../../chunk-VMH2LRM6.js';
13
+ import '../../chunk-YR433ZDA.js';
14
+ import '../../chunk-6QCXIRLA.js';
15
+ import '../../chunk-BRFMFLR6.js';
16
+ import '../../chunk-PNWOW52F.js';
17
+ import '../../chunk-VZDHIOCH.js';
18
+ import '../../chunk-S4WFNGQG.js';
19
+ import '../../chunk-64DNBF5W.js';
20
+ import '../../chunk-IIKTTIW5.js';
21
+ import '../../chunk-AOHBHYF6.js';
22
+ //# sourceMappingURL=index.js.map
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,59 @@
1
+ import { Context } from '../../context.js';
2
+ import { N as Node, b as NodeArgs, A as AbstractNode } from '../../types-U76Ukj96.js';
3
+ import { ParallelFlow } from '../patterns.js';
4
+ import '../../logger.js';
5
+ import '../../functions.js';
6
+
7
+ /**
8
+ * An internal node used by the GraphBuilder to handle the `inputs` mapping
9
+ * of an inlined sub-workflow. It copies data from the parent context scope
10
+ * to the sub-workflow's context scope.
11
+ * @internal
12
+ */
13
+ declare class InputMappingNode<TContext extends Context = Context> extends Node<void, void, any, any, TContext> {
14
+ private mappings;
15
+ constructor(options: {
16
+ data: Record<string, string>;
17
+ });
18
+ prep({ ctx, logger }: NodeArgs<void, void, any, TContext>): Promise<void>;
19
+ }
20
+ /**
21
+ * An internal node used by the GraphBuilder to handle the `outputs` mapping
22
+ * of an inlined sub-workflow. It copies data from the sub-workflow's
23
+ * context scope back to the parent's context scope.
24
+ * @internal
25
+ */
26
+ declare class OutputMappingNode<TContext extends Context = Context> extends Node<void, void, any, any, TContext> {
27
+ private mappings;
28
+ constructor(options: {
29
+ data: Record<string, string>;
30
+ });
31
+ prep({ ctx, logger }: NodeArgs<void, void, any, TContext>): Promise<void>;
32
+ }
33
+ /**
34
+ * A private class used by the builder to represent the sub-workflow container itself.
35
+ * It's a structural node that preserves the original node ID in the flattened graph.
36
+ * @internal
37
+ */
38
+ declare class SubWorkflowContainerNode<TContext extends Context = Context> extends Node<void, void, any, any, TContext> {
39
+ constructor();
40
+ exec(): Promise<void>;
41
+ }
42
+ /** A private class used by the builder to represent parallel execution blocks. */
43
+ declare class ParallelBranchContainer<TContext extends Context = Context> extends ParallelFlow<TContext> {
44
+ /** A tag to reliably identify this node type in the visualizer. */
45
+ readonly isParallelContainer = true;
46
+ nodesToRun: AbstractNode[];
47
+ constructor();
48
+ }
49
+ /**
50
+ * A private class used by the builder to unify conditional branches
51
+ * before they connect to a common successor. This ensures the successor
52
+ * only has one predecessor, preventing false fan-in detection.
53
+ * @internal
54
+ */
55
+ declare class ConditionalJoinNode<TContext extends Context = Context> extends Node<void, void, any, any, TContext> {
56
+ constructor();
57
+ }
58
+
59
+ export { ConditionalJoinNode, InputMappingNode, OutputMappingNode, ParallelBranchContainer, SubWorkflowContainerNode };
@@ -0,0 +1,20 @@
1
+ export { ConditionalJoinNode, InputMappingNode, OutputMappingNode, ParallelBranchContainer, SubWorkflowContainerNode } from '../../chunk-WGVHM7DU.js';
2
+ import '../../chunk-L5PK5VL2.js';
3
+ import '../../chunk-F6C6J7HK.js';
4
+ import '../../chunk-UY4PNPBX.js';
5
+ import '../../chunk-ELEHMJPM.js';
6
+ import '../../chunk-HEO3XL4Z.js';
7
+ import '../../chunk-7XUN3OQT.js';
8
+ import '../../chunk-WR5PDOPP.js';
9
+ import '../../chunk-VMH2LRM6.js';
10
+ import '../../chunk-YR433ZDA.js';
11
+ import '../../chunk-6QCXIRLA.js';
12
+ import '../../chunk-BRFMFLR6.js';
13
+ import '../../chunk-PNWOW52F.js';
14
+ import '../../chunk-VZDHIOCH.js';
15
+ import '../../chunk-S4WFNGQG.js';
16
+ import '../../chunk-64DNBF5W.js';
17
+ import '../../chunk-IIKTTIW5.js';
18
+ import '../../chunk-AOHBHYF6.js';
19
+ //# sourceMappingURL=internal-nodes.js.map
20
+ //# sourceMappingURL=internal-nodes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"internal-nodes.js"}
@@ -0,0 +1,51 @@
1
+ import { Context } from '../../context.js';
2
+ import { I as IExecutor, F as Flow, A as AbstractNode, W as WorkflowBlueprint, n as NodeRegistry, i as TypedNodeRegistry, R as RunOptions } from '../../types-U76Ukj96.js';
3
+ import '../../logger.js';
4
+
5
+ /**
6
+ * An execution engine that hydrates a runnable `Flow` from a serializable
7
+ * `WorkflowBlueprint` and runs it. This is the recommended executor for
8
+ * distributed systems where the workflow is built once and executed many times by workers.
9
+ */
10
+ declare class BlueprintExecutor implements IExecutor {
11
+ private blueprint;
12
+ private nodeOptionsContext;
13
+ readonly flow: Flow;
14
+ readonly nodeMap: Map<string, AbstractNode>;
15
+ private readonly registry;
16
+ constructor(blueprint: WorkflowBlueprint, registry: NodeRegistry | TypedNodeRegistry<any, any>, nodeOptionsContext?: Record<string, any>);
17
+ private _populateContainers;
18
+ /**
19
+ * Retrieves a hydrated node instance from the blueprint by its ID.
20
+ * This is useful for workers that need to execute a specific node from the graph.
21
+ * @param nodeId The ID of the node to retrieve.
22
+ * @returns The `AbstractNode` instance if found, otherwise `undefined`.
23
+ */
24
+ getNode(nodeId: string): AbstractNode | undefined;
25
+ /**
26
+ * Instantiates all node objects from the blueprint's definition.
27
+ * @private
28
+ */
29
+ private _createNodeMap;
30
+ /**
31
+ * Wires the hydrated node instances together based on the blueprint's edges.
32
+ * @private
33
+ */
34
+ private _wireGraph;
35
+ /**
36
+ * Executes the flow defined by the blueprint.
37
+ * @param flow The flow to execute.
38
+ * @param context The shared context for the workflow.
39
+ * @param options Runtime options, including a logger, abort controller, or initial params.
40
+ * @returns A promise that resolves with the final action of the workflow.
41
+ */
42
+ run<T>(flow: Flow<any, T>, context: Context, options?: RunOptions): Promise<T>;
43
+ /**
44
+ * Determines the next node to execute based on the action returned by the current node.
45
+ * For distributed systems, this logic would live on the orchestrator.
46
+ * @internal
47
+ */
48
+ getNextNode(curr: AbstractNode, action: any): AbstractNode | undefined;
49
+ }
50
+
51
+ export { BlueprintExecutor };
@@ -0,0 +1,21 @@
1
+ export { BlueprintExecutor } from '../../chunk-3YMBNZ77.js';
2
+ import '../../chunk-WGVHM7DU.js';
3
+ import '../../chunk-L5PK5VL2.js';
4
+ import '../../chunk-F6C6J7HK.js';
5
+ import '../../chunk-UY4PNPBX.js';
6
+ import '../../chunk-ELEHMJPM.js';
7
+ import '../../chunk-HEO3XL4Z.js';
8
+ import '../../chunk-7XUN3OQT.js';
9
+ import '../../chunk-WR5PDOPP.js';
10
+ import '../../chunk-VMH2LRM6.js';
11
+ import '../../chunk-YR433ZDA.js';
12
+ import '../../chunk-6QCXIRLA.js';
13
+ import '../../chunk-BRFMFLR6.js';
14
+ import '../../chunk-PNWOW52F.js';
15
+ import '../../chunk-VZDHIOCH.js';
16
+ import '../../chunk-S4WFNGQG.js';
17
+ import '../../chunk-64DNBF5W.js';
18
+ import '../../chunk-IIKTTIW5.js';
19
+ import '../../chunk-AOHBHYF6.js';
20
+ //# sourceMappingURL=runner.js.map
21
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"runner.js"}
@@ -0,0 +1,3 @@
1
+ export { B as BlueprintBuildResult, k as BuildResult, o as GraphBuilderOptions, G as GraphEdge, l as GraphNode, g as NodeConstructorOptions, n as NodeRegistry, f as NodeTypeMap, O as OriginalPredecessorIdMap, j as PredecessorIdMap, S as SubWorkflowResolver, T as TypedGraphNode, i as TypedNodeRegistry, h as TypedWorkflowGraph, W as WorkflowBlueprint, m as WorkflowGraph } from '../../types-U76Ukj96.js';
2
+ import '../../context.js';
3
+ import '../../logger.js';