@auto-engineer/pipeline 1.148.0 → 1.150.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-test.log +3 -3
- package/.turbo/turbo-type-check.log +1 -1
- package/CHANGELOG.md +40 -0
- package/README.md +348 -119
- package/package.json +3 -3
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @auto-engineer/pipeline@1.
|
|
2
|
+
> @auto-engineer/pipeline@1.150.0 build /home/runner/work/auto-engineer/auto-engineer/packages/pipeline
|
|
3
3
|
> tsc && tsx ../../scripts/fix-esm-imports.ts
|
|
4
4
|
|
|
5
5
|
Fixed ESM imports in dist/
|
package/.turbo/turbo-test.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @auto-engineer/pipeline@1.
|
|
2
|
+
> @auto-engineer/pipeline@1.149.0 test /home/runner/work/auto-engineer/auto-engineer/packages/pipeline
|
|
3
3
|
> vitest run --reporter=dot
|
|
4
4
|
|
|
5
5
|
|
|
@@ -9,6 +9,6 @@
|
|
|
9
9
|
|
|
10
10
|
[2m Test Files [22m [1m[32m42 passed[39m[22m[90m (42)[39m
|
|
11
11
|
[2m Tests [22m [1m[32m591 passed[39m[22m[90m (591)[39m
|
|
12
|
-
[2m Start at [22m
|
|
13
|
-
[2m Duration [22m
|
|
12
|
+
[2m Start at [22m 12:20:57
|
|
13
|
+
[2m Duration [22m 42.28s[2m (transform 8.45s, setup 0ms, collect 18.56s, tests 31.52s, environment 55ms, prepare 30.04s)[22m
|
|
14
14
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# @auto-engineer/pipeline
|
|
2
2
|
|
|
3
|
+
## 1.150.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`a502d47`](https://github.com/BeOnAuto/auto-engineer/commit/a502d472df528a1c5d53905898220c2a3a49d8a5) Thanks [@osamanar](https://github.com/osamanar)! -
|
|
8
|
+
|
|
9
|
+
- [`c96a70e`](https://github.com/BeOnAuto/auto-engineer/commit/c96a70e49f9f64213450d0b9840bc9a8b2b1d77d) Thanks [@osamanar](https://github.com/osamanar)! -
|
|
10
|
+
|
|
11
|
+
- [`4343bca`](https://github.com/BeOnAuto/auto-engineer/commit/4343bcaa2576703ae578fd9b7f5ec5b9776702a9) Thanks [@osamanar](https://github.com/osamanar)! -
|
|
12
|
+
|
|
13
|
+
- [`28ffce9`](https://github.com/BeOnAuto/auto-engineer/commit/28ffce9c8b95f0c3ca61728bd1f667fa9416d461) Thanks [@osamanar](https://github.com/osamanar)! -
|
|
14
|
+
|
|
15
|
+
- [`3fd5dbf`](https://github.com/BeOnAuto/auto-engineer/commit/3fd5dbfbfb4f7a5fe71ae53105b31a1b0f30f911) Thanks [@osamanar](https://github.com/osamanar)! -
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- [`41f3df3`](https://github.com/BeOnAuto/auto-engineer/commit/41f3df3025445ba92208c2b007b8e29a40489309) Thanks [@github-actions[bot]](https://github.com/github-actions%5Bbot%5D)! - - **global**: version packages
|
|
20
|
+
- **global**: major refresh to all the docs
|
|
21
|
+
- Updated dependencies [[`a502d47`](https://github.com/BeOnAuto/auto-engineer/commit/a502d472df528a1c5d53905898220c2a3a49d8a5), [`c96a70e`](https://github.com/BeOnAuto/auto-engineer/commit/c96a70e49f9f64213450d0b9840bc9a8b2b1d77d), [`4343bca`](https://github.com/BeOnAuto/auto-engineer/commit/4343bcaa2576703ae578fd9b7f5ec5b9776702a9), [`28ffce9`](https://github.com/BeOnAuto/auto-engineer/commit/28ffce9c8b95f0c3ca61728bd1f667fa9416d461), [`41f3df3`](https://github.com/BeOnAuto/auto-engineer/commit/41f3df3025445ba92208c2b007b8e29a40489309), [`3fd5dbf`](https://github.com/BeOnAuto/auto-engineer/commit/3fd5dbfbfb4f7a5fe71ae53105b31a1b0f30f911)]:
|
|
22
|
+
- @auto-engineer/file-store@1.150.0
|
|
23
|
+
- @auto-engineer/message-bus@1.150.0
|
|
24
|
+
|
|
25
|
+
## 1.149.0
|
|
26
|
+
|
|
27
|
+
### Minor Changes
|
|
28
|
+
|
|
29
|
+
- [`e1eebbd`](https://github.com/BeOnAuto/auto-engineer/commit/e1eebbdf4f209780e790094d2e6887c4fa809f98) Thanks [@github-actions[bot]](https://github.com/github-actions%5Bbot%5D)! - - **server-generator-apollo-emmett**: add Given state ref hints to state.ts.ejs
|
|
30
|
+
- **server-generator-apollo-emmett**: context-aware nonCommandField instructions
|
|
31
|
+
- **server-generator-apollo-emmett**: add state context instruction
|
|
32
|
+
- **server-generator-apollo-emmett**: extract shared template helpers
|
|
33
|
+
- **server-generator-apollo-emmett**: filter state refs from hasGivenEvents in decide.ts.ejs
|
|
34
|
+
|
|
35
|
+
### Patch Changes
|
|
36
|
+
|
|
37
|
+
- [`d38c81e`](https://github.com/BeOnAuto/auto-engineer/commit/d38c81e7bb442a39626564cf4f6d8d55b60d0a38) Thanks [@SamHatoum](https://github.com/SamHatoum)! -
|
|
38
|
+
|
|
39
|
+
- Updated dependencies [[`d38c81e`](https://github.com/BeOnAuto/auto-engineer/commit/d38c81e7bb442a39626564cf4f6d8d55b60d0a38), [`e1eebbd`](https://github.com/BeOnAuto/auto-engineer/commit/e1eebbdf4f209780e790094d2e6887c4fa809f98)]:
|
|
40
|
+
- @auto-engineer/file-store@1.149.0
|
|
41
|
+
- @auto-engineer/message-bus@1.149.0
|
|
42
|
+
|
|
3
43
|
## 1.148.0
|
|
4
44
|
|
|
5
45
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
# @auto-engineer/pipeline
|
|
2
2
|
|
|
3
|
-
Event-
|
|
3
|
+
Event-sourced pipeline orchestration with declarative workflow definitions, reactive event handling, and real-time SSE monitoring.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
## Purpose
|
|
8
8
|
|
|
9
|
-
Without `@auto-engineer/pipeline`, you would have to manually wire event
|
|
9
|
+
Without `@auto-engineer/pipeline`, you would have to manually wire event-to-command mappings, coordinate phased execution across ordered groups, track scatter-gather completion for parallel commands, implement settled-handler logic for fan-in aggregation, and build your own SSE streaming layer for real-time pipeline visibility.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Key Concepts
|
|
14
|
+
|
|
15
|
+
- **Event** -- An immutable fact that has occurred (e.g. `CodeAnalyzed`, `DeploySucceeded`).
|
|
16
|
+
- **Command** -- An intention to perform an action (e.g. `AnalyzeCode`, `Deploy`).
|
|
17
|
+
- **Handler Descriptor** -- A declarative rule that maps events to commands. Five types exist: `emit`, `custom`, `run-await`, `foreach-phased`, and `settled`.
|
|
18
|
+
- **Pipeline** -- A named collection of handler descriptors plus a `toGraph()` method that produces a `GraphIR` for visualization.
|
|
19
|
+
- **PipelineRuntime** -- Indexes handler descriptors by event type and executes matching handlers when events arrive.
|
|
20
|
+
- **PipelineServer** -- An Express HTTP server that wires everything together: command dispatch, event routing, settled/phased bridges, SSE broadcast, and an in-memory event store with projections.
|
|
21
|
+
- **GraphIR** -- An intermediate representation of the pipeline as typed nodes (`event`, `command`, `settled`, `phased`, `await`) and edges, used for Mermaid rendering and UI visualization.
|
|
12
22
|
|
|
13
23
|
---
|
|
14
24
|
|
|
@@ -18,12 +28,14 @@ This package provides the core infrastructure for building event-sourced pipelin
|
|
|
18
28
|
pnpm add @auto-engineer/pipeline
|
|
19
29
|
```
|
|
20
30
|
|
|
31
|
+
---
|
|
32
|
+
|
|
21
33
|
## Quick Start
|
|
22
34
|
|
|
23
35
|
```typescript
|
|
24
36
|
import { define, PipelineServer } from '@auto-engineer/pipeline';
|
|
25
37
|
|
|
26
|
-
const pipeline = define('
|
|
38
|
+
const pipeline = define('my-sdlc')
|
|
27
39
|
.on('CodePushed')
|
|
28
40
|
.emit('AnalyzeCode', (e) => ({ filePath: e.data.path }))
|
|
29
41
|
|
|
@@ -36,34 +48,25 @@ const server = new PipelineServer({ port: 3000 });
|
|
|
36
48
|
server.registerPipeline(pipeline);
|
|
37
49
|
|
|
38
50
|
await server.start();
|
|
39
|
-
console.log(`
|
|
51
|
+
console.log(`Pipeline server running on port ${server.port}`);
|
|
40
52
|
```
|
|
41
53
|
|
|
42
54
|
---
|
|
43
55
|
|
|
44
|
-
## Key Concepts
|
|
45
|
-
|
|
46
|
-
- **Events**: Immutable facts that have occurred
|
|
47
|
-
- **Commands**: Intentions to perform actions
|
|
48
|
-
- **Handlers**: React to events by dispatching commands
|
|
49
|
-
- **Pipelines**: Declarative workflows connecting events to commands
|
|
50
|
-
|
|
51
|
-
---
|
|
52
|
-
|
|
53
56
|
## How-to Guides
|
|
54
57
|
|
|
55
|
-
### Define a
|
|
58
|
+
### Define a pipeline with emit handlers
|
|
56
59
|
|
|
57
60
|
```typescript
|
|
58
61
|
import { define } from '@auto-engineer/pipeline';
|
|
59
62
|
|
|
60
|
-
const pipeline = define('
|
|
63
|
+
const pipeline = define('simple')
|
|
61
64
|
.on('TriggerEvent')
|
|
62
|
-
.emit('
|
|
65
|
+
.emit('DoWork', { key: 'value' })
|
|
63
66
|
.build();
|
|
64
67
|
```
|
|
65
68
|
|
|
66
|
-
### Use
|
|
69
|
+
### Use conditional predicates
|
|
67
70
|
|
|
68
71
|
```typescript
|
|
69
72
|
const pipeline = define('conditional')
|
|
@@ -73,21 +76,42 @@ const pipeline = define('conditional')
|
|
|
73
76
|
.build();
|
|
74
77
|
```
|
|
75
78
|
|
|
76
|
-
### Use
|
|
79
|
+
### Use custom handlers
|
|
77
80
|
|
|
78
81
|
```typescript
|
|
79
82
|
const pipeline = define('custom')
|
|
80
83
|
.on('SpecialEvent')
|
|
81
84
|
.handle(async (event, ctx) => {
|
|
82
|
-
await ctx.emit('
|
|
83
|
-
})
|
|
85
|
+
await ctx.emit('ProcessingDone', { result: event.data.value });
|
|
86
|
+
}, { emits: ['ProcessingDone'] })
|
|
84
87
|
.build();
|
|
85
88
|
```
|
|
86
89
|
|
|
87
|
-
###
|
|
90
|
+
### Run commands and await completion
|
|
88
91
|
|
|
89
92
|
```typescript
|
|
90
|
-
|
|
93
|
+
import { dispatch } from '@auto-engineer/pipeline';
|
|
94
|
+
|
|
95
|
+
const pipeline = define('scatter-gather')
|
|
96
|
+
.on('FilesDiscovered')
|
|
97
|
+
.run((e) => e.data.files.map((f) => dispatch('ProcessFile', { path: f })))
|
|
98
|
+
.awaitAll('ProcessFile', (e) => e.data.path)
|
|
99
|
+
.onSuccess('AllFilesProcessed', (ctx) => ({
|
|
100
|
+
count: ctx.results.length,
|
|
101
|
+
duration: ctx.duration,
|
|
102
|
+
}))
|
|
103
|
+
.onFailure('FileProcessingFailed', (ctx) => ({
|
|
104
|
+
failures: ctx.failures,
|
|
105
|
+
}))
|
|
106
|
+
.build();
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Use phased execution
|
|
110
|
+
|
|
111
|
+
Process items in ordered groups where each phase completes before the next begins.
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
const pipeline = define('phased')
|
|
91
115
|
.on('ComponentsReady')
|
|
92
116
|
.forEach((e) => e.data.components)
|
|
93
117
|
.groupInto(['critical', 'normal'], (c) => c.priority)
|
|
@@ -101,7 +125,9 @@ const pipeline = define('builder')
|
|
|
101
125
|
.build();
|
|
102
126
|
```
|
|
103
127
|
|
|
104
|
-
### Use
|
|
128
|
+
### Use settled handlers
|
|
129
|
+
|
|
130
|
+
Fire logic when all specified commands have completed.
|
|
105
131
|
|
|
106
132
|
```typescript
|
|
107
133
|
const pipeline = define('aggregator')
|
|
@@ -112,22 +138,55 @@ const pipeline = define('aggregator')
|
|
|
112
138
|
.build();
|
|
113
139
|
```
|
|
114
140
|
|
|
115
|
-
###
|
|
141
|
+
### Register command handlers and start the server
|
|
116
142
|
|
|
117
143
|
```typescript
|
|
118
144
|
import { PipelineServer } from '@auto-engineer/pipeline';
|
|
145
|
+
import type { CommandHandlerWithMetadata } from '@auto-engineer/pipeline';
|
|
146
|
+
|
|
147
|
+
const handlers: CommandHandlerWithMetadata[] = [
|
|
148
|
+
{
|
|
149
|
+
name: 'AnalyzeCode',
|
|
150
|
+
events: ['CodeAnalyzed'],
|
|
151
|
+
handle: async (cmd) => ({
|
|
152
|
+
type: 'CodeAnalyzed',
|
|
153
|
+
data: { path: cmd.data.filePath, issues: [] },
|
|
154
|
+
}),
|
|
155
|
+
},
|
|
156
|
+
];
|
|
119
157
|
|
|
120
158
|
const server = new PipelineServer({ port: 3000 });
|
|
121
|
-
server.registerCommandHandlers(
|
|
159
|
+
server.registerCommandHandlers(handlers);
|
|
122
160
|
server.registerPipeline(pipeline);
|
|
123
|
-
|
|
124
161
|
await server.start();
|
|
125
162
|
```
|
|
126
163
|
|
|
127
|
-
###
|
|
164
|
+
### Configure concurrency control
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
server.registerConcurrency('ProcessFile', {
|
|
168
|
+
strategy: 'cancel-in-progress', // or 'queue'
|
|
169
|
+
groupKey: (data) => data.path,
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Load plugins from packages
|
|
128
174
|
|
|
129
175
|
```typescript
|
|
130
|
-
|
|
176
|
+
import { pipelineConfig, loadPipelineConfig } from '@auto-engineer/pipeline';
|
|
177
|
+
|
|
178
|
+
const config = pipelineConfig({
|
|
179
|
+
plugins: ['@auto-engineer/code-analyzer', '@auto-engineer/deployer'],
|
|
180
|
+
pipeline: myPipeline,
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
const { handlers, pipeline } = await loadPipelineConfig(config);
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Consume SSE events
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
const url = new URL('/events', 'http://localhost:3000');
|
|
131
190
|
url.searchParams.set('correlationId', 'corr-123'); // optional filter
|
|
132
191
|
|
|
133
192
|
const eventSource = new EventSource(url.toString());
|
|
@@ -137,22 +196,17 @@ eventSource.onmessage = (msg) => {
|
|
|
137
196
|
};
|
|
138
197
|
```
|
|
139
198
|
|
|
140
|
-
###
|
|
199
|
+
### Use the v2 builder API
|
|
141
200
|
|
|
142
201
|
```typescript
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
};
|
|
152
|
-
return es;
|
|
153
|
-
}
|
|
154
|
-
return connect();
|
|
155
|
-
}
|
|
202
|
+
import { defineV2, toGraphV2 } from '@auto-engineer/pipeline';
|
|
203
|
+
|
|
204
|
+
const pipeline = defineV2('my-pipeline')
|
|
205
|
+
.on('Start')
|
|
206
|
+
.emit('DoWork', { key: 'value' })
|
|
207
|
+
.build();
|
|
208
|
+
|
|
209
|
+
const graph = toGraphV2(pipeline);
|
|
156
210
|
```
|
|
157
211
|
|
|
158
212
|
---
|
|
@@ -162,78 +216,184 @@ function connectWithRetry(url: string, maxRetries = 5) {
|
|
|
162
216
|
### Package Exports
|
|
163
217
|
|
|
164
218
|
```typescript
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
} from '
|
|
219
|
+
// Builder
|
|
220
|
+
export { define } from './builder/define';
|
|
221
|
+
export { defineV2, toGraphV2 } from './builder/define-v2';
|
|
222
|
+
|
|
223
|
+
// Core helpers
|
|
224
|
+
export { dispatch } from './core/types';
|
|
225
|
+
|
|
226
|
+
// Runtime
|
|
227
|
+
export { PipelineRuntime } from './runtime/pipeline-runtime';
|
|
228
|
+
export { EventCommandMapper } from './runtime/event-command-map';
|
|
229
|
+
export { AwaitTracker } from './runtime/await-tracker';
|
|
230
|
+
|
|
231
|
+
// Server
|
|
232
|
+
export { PipelineServer } from './server/pipeline-server';
|
|
233
|
+
export { SSEManager } from './server/sse-manager';
|
|
234
|
+
|
|
235
|
+
// Logging
|
|
236
|
+
export { EventLogger } from './logging/event-logger';
|
|
237
|
+
|
|
238
|
+
// Engine (v2)
|
|
239
|
+
export { createPipelineEngine } from './engine/pipeline-engine';
|
|
240
|
+
export { createCommandDispatcher, dispatchAndStore } from './engine/command-dispatcher';
|
|
241
|
+
export { createEventRouter } from './engine/event-router';
|
|
242
|
+
export { createWorkflowProcessor } from './engine/workflow-processor';
|
|
243
|
+
export { createPipelineStore } from './engine/sqlite-store';
|
|
244
|
+
export { createConsumer } from './engine/sqlite-consumer';
|
|
245
|
+
export { createAwaitWorkflow } from './engine/workflows/await-workflow';
|
|
246
|
+
export { createPhasedWorkflow } from './engine/workflows/phased-workflow';
|
|
247
|
+
export { createSettledWorkflow } from './engine/workflows/settled-workflow';
|
|
248
|
+
|
|
249
|
+
// Engine projections
|
|
250
|
+
export { itemStatusProjection } from './engine/projections/item-status';
|
|
251
|
+
export { latestRunProjection } from './engine/projections/latest-run';
|
|
252
|
+
export { messageLogProjection } from './engine/projections/message-log';
|
|
253
|
+
export { nodeStatusProjection } from './engine/projections/node-status';
|
|
254
|
+
export { statsProjection } from './engine/projections/stats';
|
|
255
|
+
|
|
256
|
+
// Store
|
|
257
|
+
export { createPipelineEventStore } from './store/pipeline-event-store';
|
|
258
|
+
export { PipelineReadModel } from './store/pipeline-read-model';
|
|
259
|
+
|
|
260
|
+
// Testing utilities
|
|
261
|
+
export {
|
|
262
|
+
compareEventSequence,
|
|
263
|
+
containsSubsequence,
|
|
264
|
+
findMissingEvents,
|
|
265
|
+
findUnexpectedEvents,
|
|
266
|
+
formatSnapshotDiff,
|
|
267
|
+
} from './testing/snapshot-compare';
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Key Types
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
interface Pipeline {
|
|
274
|
+
descriptor: Readonly<PipelineDescriptor>;
|
|
275
|
+
toGraph(): GraphIR;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
interface PipelineDescriptor {
|
|
279
|
+
name: string;
|
|
280
|
+
version?: string;
|
|
281
|
+
description?: string;
|
|
282
|
+
keys: Map<string, KeyExtractor>;
|
|
283
|
+
handlers: HandlerDescriptor[];
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
type HandlerDescriptor =
|
|
287
|
+
| EmitHandlerDescriptor
|
|
288
|
+
| RunAwaitHandlerDescriptor
|
|
289
|
+
| ForEachPhasedDescriptor
|
|
290
|
+
| CustomHandlerDescriptor
|
|
291
|
+
| SettledHandlerDescriptor
|
|
292
|
+
| AcceptsDescriptor;
|
|
293
|
+
|
|
294
|
+
interface CommandDispatch<D = Record<string, unknown>> {
|
|
295
|
+
commandType: string;
|
|
296
|
+
data: D | ((event: Event) => D);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
interface PipelineServerConfig {
|
|
300
|
+
port: number;
|
|
301
|
+
storeFileName?: string; // SQLite file for persistent event storage
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
interface CommandHandlerWithMetadata {
|
|
305
|
+
name: string;
|
|
306
|
+
alias?: string;
|
|
307
|
+
description?: string;
|
|
308
|
+
displayName?: string;
|
|
309
|
+
fields?: Record<string, unknown>;
|
|
310
|
+
examples?: unknown[];
|
|
311
|
+
events?: EventDefinition[];
|
|
312
|
+
handle: (command: Command, context?: PipelineContext) => Promise<Event | Event[]>;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
interface PipelineContext {
|
|
316
|
+
emit: (type: string, data: unknown) => Promise<void>;
|
|
317
|
+
sendCommand: (type: string, data: unknown, correlationId?: string) => Promise<void>;
|
|
318
|
+
correlationId: string;
|
|
319
|
+
signal?: AbortSignal;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
interface ConcurrencyConfig {
|
|
323
|
+
strategy: 'cancel-in-progress' | 'queue';
|
|
324
|
+
groupKey?: (data: unknown) => string;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
interface GraphIR {
|
|
328
|
+
nodes: GraphNode[];
|
|
329
|
+
edges: GraphEdge[];
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
interface GraphNode {
|
|
333
|
+
id: string;
|
|
334
|
+
type: 'event' | 'command' | 'settled' | 'phased' | 'await';
|
|
335
|
+
label: string;
|
|
336
|
+
status?: 'idle' | 'running' | 'success' | 'error';
|
|
337
|
+
}
|
|
191
338
|
```
|
|
192
339
|
|
|
193
|
-
###
|
|
340
|
+
### `define(name: string): PipelineBuilder`
|
|
341
|
+
|
|
342
|
+
Entry point for the fluent builder API. Chain `.on()`, `.emit()`, `.run()`, `.forEach()`, `.settled()`, `.handle()`, and `.build()`.
|
|
194
343
|
|
|
195
|
-
|
|
344
|
+
### `defineV2(name: string): PipelineV2Builder`
|
|
196
345
|
|
|
197
|
-
|
|
346
|
+
Alternative builder that produces a `PipelineV2` with flat registration arrays. Convert to graph with `toGraphV2()`.
|
|
198
347
|
|
|
199
|
-
|
|
348
|
+
### `dispatch(commandType: string, data: DataOrFactory): CommandDispatch`
|
|
200
349
|
|
|
201
|
-
Helper to create
|
|
350
|
+
Helper to create `CommandDispatch` objects for use with `.run()`.
|
|
202
351
|
|
|
203
352
|
### PipelineServer
|
|
204
353
|
|
|
205
354
|
```typescript
|
|
206
355
|
class PipelineServer {
|
|
207
|
-
constructor(config:
|
|
356
|
+
constructor(config: PipelineServerConfig);
|
|
208
357
|
registerCommandHandlers(handlers: CommandHandlerWithMetadata[]): void;
|
|
209
358
|
registerPipeline(pipeline: Pipeline): void;
|
|
359
|
+
registerConcurrency(commandType: string, config: ConcurrencyConfig): void;
|
|
360
|
+
registerItemKeyExtractor(commandType: string, extractor: (data: unknown) => string | undefined): void;
|
|
361
|
+
use(handler: express.RequestHandler): this;
|
|
210
362
|
start(): Promise<void>;
|
|
211
363
|
stop(): Promise<void>;
|
|
212
364
|
readonly port: number;
|
|
365
|
+
getHttpServer(): HttpServer;
|
|
366
|
+
getMessageBus(): MessageBus;
|
|
367
|
+
getRegisteredCommands(): string[];
|
|
368
|
+
getPipelineNames(): string[];
|
|
213
369
|
}
|
|
214
370
|
```
|
|
215
371
|
|
|
216
372
|
### Server Endpoints
|
|
217
373
|
|
|
218
374
|
| Endpoint | Method | Description |
|
|
219
|
-
|
|
220
|
-
| `/health` | GET | Health check |
|
|
221
|
-
| `/registry` | GET | List handlers |
|
|
222
|
-
| `/pipeline` | GET | Pipeline graph |
|
|
223
|
-
| `/pipeline/mermaid` | GET | Mermaid diagram |
|
|
224
|
-
| `/pipeline/diagram` | GET | HTML diagram |
|
|
225
|
-
| `/command` | POST | Dispatch command |
|
|
226
|
-
| `/
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
375
|
+
|---|---|---|
|
|
376
|
+
| `/health` | GET | Health check with uptime |
|
|
377
|
+
| `/registry` | GET | List registered event and command handlers |
|
|
378
|
+
| `/pipeline` | GET | Pipeline graph with live node status |
|
|
379
|
+
| `/pipeline/mermaid` | GET | Mermaid diagram as plain text |
|
|
380
|
+
| `/pipeline/diagram` | GET | Self-contained HTML page with rendered diagram |
|
|
381
|
+
| `/command` | POST | Dispatch a command (returns `ack` with `correlationId`) |
|
|
382
|
+
| `/execute` | POST | Dispatch and wait for synchronous result |
|
|
383
|
+
| `/events` | GET | SSE stream (optional `?correlationId=` filter) |
|
|
384
|
+
| `/messages` | GET | Full message log |
|
|
385
|
+
| `/stats` | GET | Aggregate message statistics |
|
|
386
|
+
| `/run-stats` | GET | Per-run item/node statistics |
|
|
387
|
+
|
|
388
|
+
### Testing Utilities
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
function compareEventSequence(expected: string[], actual: string[]): SnapshotResult;
|
|
392
|
+
function containsSubsequence(sequence: string[], subsequence: string[]): boolean;
|
|
393
|
+
function findMissingEvents(sequence: string[], required: string[]): string[];
|
|
394
|
+
function findUnexpectedEvents(sequence: string[], allowed: string[]): string[];
|
|
395
|
+
function formatSnapshotDiff(result: SnapshotResult): string;
|
|
396
|
+
```
|
|
237
397
|
|
|
238
398
|
---
|
|
239
399
|
|
|
@@ -241,39 +401,108 @@ class PipelineServer {
|
|
|
241
401
|
|
|
242
402
|
```
|
|
243
403
|
src/
|
|
244
|
-
├── builder/
|
|
245
|
-
├──
|
|
246
|
-
|
|
247
|
-
├──
|
|
248
|
-
|
|
249
|
-
├──
|
|
250
|
-
├──
|
|
251
|
-
|
|
252
|
-
├── store
|
|
253
|
-
|
|
404
|
+
├── builder/ # define() and defineV2() fluent builder APIs
|
|
405
|
+
│ ├── define.ts # Primary builder with graph extraction
|
|
406
|
+
│ └── define-v2.ts # Simplified v2 builder
|
|
407
|
+
├── config/ # Pipeline configuration and plugin loading
|
|
408
|
+
│ └── pipeline-config.ts
|
|
409
|
+
├── core/ # Shared types and descriptor definitions
|
|
410
|
+
│ ├── descriptors.ts # Handler descriptor types
|
|
411
|
+
│ └── types.ts # Event, Command, CommandDispatch
|
|
412
|
+
├── engine/ # v2 engine: dispatcher, router, workflows, SQLite store
|
|
413
|
+
│ ├── command-dispatcher.ts
|
|
414
|
+
│ ├── event-router.ts
|
|
415
|
+
│ ├── pipeline-engine.ts
|
|
416
|
+
│ ├── sqlite-consumer.ts
|
|
417
|
+
│ ├── sqlite-store.ts
|
|
418
|
+
│ ├── workflow-processor.ts
|
|
419
|
+
│ ├── projections/ # Event-driven projections (item, node, run, stats)
|
|
420
|
+
│ └── workflows/ # Await, phased, and settled workflow implementations
|
|
421
|
+
├── graph/ # GraphIR types and filtering
|
|
422
|
+
│ ├── types.ts
|
|
423
|
+
│ └── filter-graph.ts
|
|
424
|
+
├── logging/ # EventLogger for recording pipeline activity
|
|
425
|
+
├── plugins/ # Dynamic plugin loading and handler adaptation
|
|
426
|
+
│ ├── plugin-loader.ts
|
|
427
|
+
│ └── handler-adapter.ts
|
|
428
|
+
├── projections/ # In-memory event store projections
|
|
429
|
+
│ ├── await-tracker-projection.ts
|
|
430
|
+
│ ├── item-status-projection.ts
|
|
431
|
+
│ ├── latest-run-projection.ts
|
|
432
|
+
│ ├── message-log-projection.ts
|
|
433
|
+
│ ├── node-status-projection.ts
|
|
434
|
+
│ └── stats-projection.ts
|
|
435
|
+
├── runtime/ # PipelineRuntime, AwaitTracker, EventCommandMapper
|
|
436
|
+
├── server/ # PipelineServer, SSE, command gate, quiescence tracking
|
|
437
|
+
│ ├── pipeline-server.ts
|
|
438
|
+
│ ├── pipeline-server-v2.ts
|
|
439
|
+
│ ├── sse-manager.ts
|
|
440
|
+
│ ├── command-gate.ts
|
|
441
|
+
│ ├── quiescence-tracker.ts
|
|
442
|
+
│ ├── phased-bridge.ts
|
|
443
|
+
│ └── v2-runtime-bridge.ts
|
|
444
|
+
├── store/ # In-memory event store with Emmett projections
|
|
445
|
+
│ ├── pipeline-event-store.ts
|
|
446
|
+
│ └── pipeline-read-model.ts
|
|
447
|
+
└── testing/ # Test helpers: mock handlers, event capture, snapshots
|
|
448
|
+
├── event-capture.ts
|
|
449
|
+
├── mock-handlers.ts
|
|
450
|
+
├── snapshot-compare.ts
|
|
451
|
+
└── snapshot-sanitize.ts
|
|
254
452
|
```
|
|
255
453
|
|
|
256
|
-
The following diagram shows the execution flow:
|
|
257
|
-
|
|
258
454
|
```mermaid
|
|
259
455
|
flowchart TB
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
456
|
+
subgraph Builder
|
|
457
|
+
define["define() / defineV2()"]
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
subgraph Core
|
|
461
|
+
Pipeline["Pipeline + Descriptor"]
|
|
462
|
+
GraphIR["GraphIR"]
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
subgraph Runtime
|
|
466
|
+
PR["PipelineRuntime"]
|
|
467
|
+
AT["AwaitTracker"]
|
|
468
|
+
ECM["EventCommandMapper"]
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
subgraph Server
|
|
472
|
+
PS["PipelineServer"]
|
|
473
|
+
SSE["SSEManager"]
|
|
474
|
+
CG["CommandGate"]
|
|
475
|
+
QT["QuiescenceTracker"]
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
subgraph Store
|
|
479
|
+
ES["EventStore + Projections"]
|
|
480
|
+
RM["PipelineReadModel"]
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
define --> Pipeline
|
|
484
|
+
Pipeline --> GraphIR
|
|
485
|
+
Pipeline --> PR
|
|
486
|
+
PS --> PR
|
|
487
|
+
PS --> SSE
|
|
488
|
+
PS --> CG
|
|
489
|
+
PS --> QT
|
|
490
|
+
PS --> ES
|
|
491
|
+
ES --> RM
|
|
492
|
+
PR --> AT
|
|
493
|
+
PR --> ECM
|
|
267
494
|
```
|
|
268
495
|
|
|
269
|
-
*Flow: Events arrive, handlers match, execute based on type.*
|
|
270
|
-
|
|
271
496
|
### Dependencies
|
|
272
497
|
|
|
273
498
|
| Package | Usage |
|
|
274
|
-
|
|
275
|
-
| `@auto-engineer/message-bus` | Command/event messaging |
|
|
499
|
+
|---|---|
|
|
500
|
+
| `@auto-engineer/message-bus` | Command/event messaging infrastructure |
|
|
276
501
|
| `@auto-engineer/file-store` | File storage utilities |
|
|
277
|
-
| `@event-driven-io/emmett` |
|
|
278
|
-
| `
|
|
279
|
-
| `
|
|
502
|
+
| `@event-driven-io/emmett` | In-memory event store with projections |
|
|
503
|
+
| `@event-driven-io/emmett-sqlite` | SQLite-backed persistent event store |
|
|
504
|
+
| `express` | HTTP server for REST + SSE endpoints |
|
|
505
|
+
| `nanoid` | Compact unique ID generation |
|
|
506
|
+
| `chokidar` | File system watching |
|
|
507
|
+
| `jose` | JWT handling |
|
|
508
|
+
| `get-port` | Automatic port selection |
|
package/package.json
CHANGED
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"jose": "^5.9.6",
|
|
16
16
|
"nanoid": "^5.0.0",
|
|
17
17
|
"uuid": "^11.0.0",
|
|
18
|
-
"@auto-engineer/file-store": "1.
|
|
19
|
-
"@auto-engineer/message-bus": "1.
|
|
18
|
+
"@auto-engineer/file-store": "1.150.0",
|
|
19
|
+
"@auto-engineer/message-bus": "1.150.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/cors": "^2.8.17",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"publishConfig": {
|
|
26
26
|
"access": "public"
|
|
27
27
|
},
|
|
28
|
-
"version": "1.
|
|
28
|
+
"version": "1.150.0",
|
|
29
29
|
"scripts": {
|
|
30
30
|
"build": "tsc && tsx ../../scripts/fix-esm-imports.ts",
|
|
31
31
|
"test": "vitest run --reporter=dot",
|