flowcraft 1.0.0-beta.2 → 1.0.0-beta.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,7 +10,7 @@ Build complex, multi-step processes, from simple sequences to dynamic, graph-dri
10
10
 
11
11
  - **Extensible Execution Engine**: A pluggable `Executor` pattern enables in-memory or distributed flows.
12
12
 
13
- - **Type-Safe**: Written in TypeScript to provide strong typing for your workflow definitions and context.
13
+ - **Type-Safe**: Written in TypeScript to provide strong typing for your workflow definitions, context, and node parameters.
14
14
 
15
15
  - **Async by Default**: Built on an asynchronous foundation to handle I/O-bound and CPU-bound tasks.
16
16
 
@@ -39,12 +39,11 @@ npm install flowcraft
39
39
  Create and run a simple workflow in a few lines of code.
40
40
 
41
41
  ```typescript
42
- import { Flow, Node } from 'flowcraft'
42
+ import { Flow, mapNode } from 'flowcraft' // Use mapNode for simple functions
43
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.
44
+ // Create a node from a simple function that takes params and returns a value.
45
+ const greetNode = mapNode(() => 'Hello, World!')
46
+ // Functional helpers make common tasks easy.
48
47
  .tap(console.log)
49
48
 
50
49
  const flow = new Flow(greetNode)
@@ -68,7 +67,7 @@ graph LR
68
67
  ```
69
68
 
70
69
  - **Demonstrates**: `Node` chaining, passing data via `Context`, and a simple `BatchFlow`.
71
- - **[Explore the Basic example »](./sandbox/1.basic/)**
70
+ - **[Explore the Basic example »](https://github.com/gorango/flowcraft/tree/main/sandbox/1.basic/)**
72
71
 
73
72
  ### 2. Conditional Branching: Research Agent
74
73
 
@@ -82,7 +81,7 @@ graph TD
82
81
  ```
83
82
 
84
83
  - **Demonstrates**: Conditional branching with custom actions, creating loops, and building simple state machines.
85
- - **[Explore the Research Agent example »](./sandbox/2.research/)**
84
+ - **[Explore the Research Agent example »](https://github.com/gorango/flowcraft/tree/main/sandbox/2.research/)**
86
85
 
87
86
  ### 3. Parallel Batch Processing: Document Translator
88
87
 
@@ -102,7 +101,7 @@ graph TD
102
101
  ```
103
102
 
104
103
  - **Demonstrates**: `ParallelBatchFlow` for high-throughput concurrent processing of I/O-bound tasks.
105
- - **[Explore the Parallel Translation example »](./sandbox/3.parallel/)**
104
+ - **[Explore the Parallel Translation example »](https://github.com/gorango/flowcraft/tree/main/sandbox/3.parallel/)**
106
105
 
107
106
  ### 4. Dynamic Graph Engine: AI Agent Runtime
108
107
 
@@ -134,7 +133,7 @@ graph TD
134
133
  - Parallel fan-in and fan-out (mid-flow branching).
135
134
  - Reusable, data-driven nodes (e.g., an LLM-powered router).
136
135
  - Complex sub-workflow composition.
137
- - **[Explore the Dynamic AI Agent example »](./sandbox/4.dag/)**
136
+ - **[Explore the Dynamic AI Agent example »](https://github.com/gorango/flowcraft/tree/main/sandbox/4.dag/)**
138
137
 
139
138
  ### 5. Distributed Execution: AI Agent with BullMQ
140
139
 
@@ -145,7 +144,7 @@ This example takes the same type-safe graph definition from the previous example
145
144
  - Client-worker architecture with state serialization.
146
145
  - Mid-flight, distributed cancellation of long-running jobs.
147
146
  - How business logic (the graph) remains unchanged when the execution environment changes.
148
- - **[Explore the Distributed AI Agent example »](./sandbox/5.distributed/)**
147
+ - **[Explore the Distributed AI Agent example »](https://github.com/gorango/flowcraft/tree/main/sandbox/5.distributed/)**
149
148
 
150
149
  ### 6. Advanced RAG Agent: Complex Data & Serialization
151
150
 
@@ -164,28 +163,127 @@ graph TD
164
163
  - A mix of custom, single-responsibility nodes.
165
164
  - Handling complex data types (`Map`, `Date`, custom classes) in the `Context`.
166
165
  - The necessity of robust serialization (using `superjson`) for state management.
167
- - **[Explore the RAG Agent example »](./sandbox/6.rag/)**
166
+ - **[Explore the RAG Agent example »](https://github.com/gorango/flowcraft/tree/main/sandbox/6.rag/)**
168
167
 
169
168
  ## Core Concepts
170
169
 
171
170
  ### Node
172
171
 
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:
172
+ 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
173
 
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.
174
+ The class signature is: `Node<PrepRes, ExecRes, PostRes, TParams>`
175
+
176
+ - `PrepRes`: The type of data returned by the `prep` phase.
177
+ - `ExecRes`: The type of data returned by the `exec` phase.
178
+ - `PostRes`: The type of the "action" returned by the `post` phase.
179
+ - `TParams`: The type of the static parameters object for the node, accessible via `.withParams()`.
180
+
181
+ **Example: A Type-Safe GreetNode**
182
+
183
+ For nodes that do require static configuration, you can provide a type for the parameters to get full autocompletion and compile-time safety.
184
+
185
+ ```typescript
186
+ // 1. Define the shape of the node's parameters.
187
+ interface GreetParams {
188
+ greeting: string
189
+ loudly: boolean
190
+ }
191
+
192
+ // 2. Define the node with the TParams generic.
193
+ class GreetNode extends Node<void, string, any, GreetParams> {
194
+ // 3. The 'exec' method can safely access typed parameters.
195
+ async exec({ params }: NodeArgs<GreetParams>): Promise<string> {
196
+ let message = `${params.greeting}, World!`
197
+ if (params.loudly) {
198
+ message = message.toUpperCase()
199
+ }
200
+ return message
201
+ }
202
+ }
203
+
204
+ // 4. Instantiate and configure with type-safe .withParams()
205
+ const greetNode = new GreetNode()
206
+ .withParams({ greeting: 'Hello', loudly: true }) // Autocompletes and type-checks!
207
+ .tap(console.log) // "HELLO, WORLD!"
208
+
209
+ // TypeScript would throw an error on this line:
210
+ // greetNode.withParams({ greting: 'Hi', loudly: false }); // Property 'greting' does not exist.
211
+ ```
178
212
 
179
213
  A chainable API on the `Node` class has a set of functional helpers:
180
214
 
215
+ - `.withParams(params)`: Sets type-safe static parameters for the node.
181
216
  - `.map(fn)`: Transform the output of a node.
182
217
  - `.filter(predicate)`: Conditionally proceed based on a node's output.
183
218
  - `.tap(fn)`: Perform a side-effect without changing the output.
184
219
  - `.toContext(key)`: Store a node's result in the context.
220
+ - `.withLens(lens, value)`: Applies a context mutation before the node executes
221
+
222
+ ### Simplified Node Base Classes
223
+
224
+ To reduce boilerplate for common patterns, Flowcraft provides specialized abstract base classes.
225
+
226
+ #### `ExecNode`
227
+
228
+ For nodes that only need to perform a core action and return a value. This is the most common pattern.
229
+
230
+ ```typescript
231
+ // 1. Define params and the node, extending ExecNode<ExecRes, TParams>
232
+ interface GreetParams { name: string }
233
+
234
+ class GreetNode extends ExecNode<string, GreetParams> {
235
+ // 2. You only need to implement the 'exec' method.
236
+ async exec({ params }: NodeArgs<void, void, GreetParams>): Promise<string> {
237
+ return `Hello, ${params.name}!`
238
+ }
239
+ }
240
+
241
+ // Usage:
242
+ const greetNode = new GreetNode().withParams({ name: 'World' })
243
+ ```
244
+
245
+ #### `PreNode`
246
+
247
+ For nodes that only modify state (e.g., in the `Context`) and don't produce an output. Their logic can be placed in the `prep` phase.
248
+
249
+ ```typescript
250
+ const COUNTER = contextKey<number>('counter')
251
+
252
+ class IncrementCounterNode extends PreNode {
253
+ // You only need to implement the 'prep' method for context mutations.
254
+ async prep({ ctx }: NodeArgs): Promise<void> {
255
+ const current = ctx.get(COUNTER) ?? 0
256
+ ctx.set(COUNTER, current + 1)
257
+ }
258
+ }
259
+ ```
260
+
261
+ #### `PostNode`
262
+
263
+ For nodes that route the workflow by returning a custom action string from their `post` method.
264
+
265
+ ```typescript
266
+ const USER_ROLE = contextKey<'admin' | 'guest'>('user_role')
267
+
268
+ type UserAction = 'grant_access' | 'deny_access'
269
+
270
+ class CheckAdminNode extends PostNode<UserAction> {
271
+ // You only need to implement the 'post' method for branching logic.
272
+ async post({ ctx }: NodeArgs): Promise<UserAction> {
273
+ const role = ctx.get(USER_ROLE)
274
+ return role === 'admin' ? 'grant_access' : 'deny_access'
275
+ }
276
+ }
277
+
278
+ // Usage in a flow:
279
+ const checkAdmin = new CheckAdminNode()
280
+ checkAdmin.next(new AdminPanelNode(), 'grant_access')
281
+ checkAdmin.next(new GuestPageNode(), 'deny_access')
282
+ ```
185
283
 
186
284
  ### Flow
187
285
 
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.
286
+ 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.
189
287
 
190
288
  ### Executor
191
289
 
@@ -216,16 +314,16 @@ To simplify the creation of common and complex patterns, the framework provides
216
314
  > [!TIP]
217
315
  > For clear, focused examples of specific, individual features (like retries, middleware, cancellation, and composition), the unit tests are an excellent resource.
218
316
 
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)
317
+ - Core workflow tests: [`src/workflow.test.ts`](https://github.com/gorango/flowcraft/tree/main/workflow.test.ts)
318
+ - Patterns tests: [`src/builder/patterns.test.ts`](https://github.com/gorango/flowcraft/tree/main/builder/patterns.test.ts)
319
+ - Graph builder tests: [`src/builder/graph.test.ts`](https://github.com/gorango/flowcraft/tree/main/builder/graph.test.ts)
222
320
 
223
321
  ## API Reference
224
322
 
225
323
  ### Core Classes
226
324
 
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()`.
325
+ - `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.).
326
+ - `Flow`: Orchestrates a sequence of nodes: `Flow<PrepRes, ExecRes, TParams>`. Supports middleware via `.use()`.
229
327
  - `InMemoryExecutor`: The default `IExecutor` implementation for running flows in-memory.
230
328
  - `TypedContext`: The standard `Map`-based implementation for the `Context` interface.
231
329
  - `ConsoleLogger`, `NullLogger`: Pre-built logger implementations.
@@ -234,16 +332,28 @@ To simplify the creation of common and complex patterns, the framework provides
234
332
 
235
333
  A collection of functions for creating nodes and pipelines in a more functional style.
236
334
 
237
- - `mapNode`: Creates a `Node` from a simple, pure function.
238
- - `contextNode`: Creates a `Node` from a function that requires access to the `Context`.
335
+ - `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.
336
+ - `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`.
337
+ - `transformNode`: Creates a `Node` that applies one or more `ContextTransform` functions (often created with a `lens`). This is ideal for declarative state management.
239
338
  - `pipeline`: A functional alias for creating a linear sequence of nodes.
339
+ - `mapCollection`: Creates a `Flow` that applies a function to each item in a collection in parallel, returning an array of the results.
340
+ - `filterCollection`: Creates a `Flow` that filters a collection in parallel based on a predicate function.
341
+ - `reduceCollection`: Creates a `Flow` that reduces a collection to a single value by applying a reducer function sequentially.
240
342
 
241
343
  ### Builder Classes
242
344
 
243
345
  - `SequenceFlow`: A `Flow` that creates a linear flow from a sequence of nodes.
244
346
  - `BatchFlow`: A `Flow` that processes a collection of items sequentially.
245
347
  - `ParallelBatchFlow`: A `Flow` that processes a collection of items in parallel.
246
- - `GraphBuilder`: Constructs a `Flow` from a declarative graph definition.
348
+ - `GraphBuilder`: Constructs a `Flow` from a declarative graph definition. Its `.build()` method returns a `BuildResult` object containing:
349
+ - `flow`: The executable `Flow` instance.
350
+ - `nodeMap`: A `Map` of all instantiated nodes, keyed by their ID.
351
+ - `predecessorCountMap`: A `Map` of node IDs to their total number of incoming connections.
352
+ - `predecessorIdMap`: A `Map` of node IDs to an array of their direct predecessor IDs, useful for advanced executors.
353
+
354
+ ## Documentation
355
+
356
+ The complete [Flowcraft documentation](https://flowcraft-docs.netlify.app) is available on the website.
247
357
 
248
358
  ---
249
- Licensed under the [MIT License](./LICENSE).
359
+ Licensed under the [MIT License](https://github.com/gorango/flowcraft/tree/main/LICENSE).