@auto-engineer/pipeline 1.65.0 → 1.67.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 +6 -6
- package/.turbo/turbo-type-check.log +1 -1
- package/CHANGELOG.md +135 -0
- package/dist/src/builder/define-v2.d.ts +101 -0
- package/dist/src/builder/define-v2.d.ts.map +1 -0
- package/dist/src/builder/define-v2.js +209 -0
- package/dist/src/builder/define-v2.js.map +1 -0
- package/dist/src/engine/command-dispatcher.d.ts +31 -0
- package/dist/src/engine/command-dispatcher.d.ts.map +1 -0
- package/dist/src/engine/command-dispatcher.js +26 -0
- package/dist/src/engine/command-dispatcher.js.map +1 -0
- package/dist/src/engine/event-router.d.ts +21 -0
- package/dist/src/engine/event-router.d.ts.map +1 -0
- package/dist/src/engine/event-router.js +22 -0
- package/dist/src/engine/event-router.js.map +1 -0
- package/dist/src/engine/index.d.ts +15 -0
- package/dist/src/engine/index.d.ts.map +1 -0
- package/dist/src/engine/index.js +15 -0
- package/dist/src/engine/index.js.map +1 -0
- package/dist/src/engine/pipeline-engine.d.ts +37 -0
- package/dist/src/engine/pipeline-engine.d.ts.map +1 -0
- package/dist/src/engine/pipeline-engine.js +53 -0
- package/dist/src/engine/pipeline-engine.js.map +1 -0
- package/dist/src/engine/projections/item-status.d.ts +9 -0
- package/dist/src/engine/projections/item-status.d.ts.map +1 -0
- package/dist/src/engine/projections/item-status.js +9 -0
- package/dist/src/engine/projections/item-status.js.map +1 -0
- package/dist/src/engine/projections/latest-run.d.ts +9 -0
- package/dist/src/engine/projections/latest-run.d.ts.map +1 -0
- package/dist/src/engine/projections/latest-run.js +9 -0
- package/dist/src/engine/projections/latest-run.js.map +1 -0
- package/dist/src/engine/projections/message-log.d.ts +9 -0
- package/dist/src/engine/projections/message-log.d.ts.map +1 -0
- package/dist/src/engine/projections/message-log.js +10 -0
- package/dist/src/engine/projections/message-log.js.map +1 -0
- package/dist/src/engine/projections/node-status.d.ts +9 -0
- package/dist/src/engine/projections/node-status.d.ts.map +1 -0
- package/dist/src/engine/projections/node-status.js +9 -0
- package/dist/src/engine/projections/node-status.js.map +1 -0
- package/dist/src/engine/projections/stats.d.ts +9 -0
- package/dist/src/engine/projections/stats.d.ts.map +1 -0
- package/dist/src/engine/projections/stats.js +9 -0
- package/dist/src/engine/projections/stats.js.map +1 -0
- package/dist/src/engine/sqlite-consumer.d.ts +11 -0
- package/dist/src/engine/sqlite-consumer.d.ts.map +1 -0
- package/dist/src/engine/sqlite-consumer.js +27 -0
- package/dist/src/engine/sqlite-consumer.js.map +1 -0
- package/dist/src/engine/sqlite-store.d.ts +10 -0
- package/dist/src/engine/sqlite-store.d.ts.map +1 -0
- package/dist/src/engine/sqlite-store.js +14 -0
- package/dist/src/engine/sqlite-store.js.map +1 -0
- package/dist/src/engine/workflow-processor.d.ts +20 -0
- package/dist/src/engine/workflow-processor.d.ts.map +1 -0
- package/dist/src/engine/workflow-processor.js +36 -0
- package/dist/src/engine/workflow-processor.js.map +1 -0
- package/dist/src/engine/workflows/await-workflow.d.ts +33 -0
- package/dist/src/engine/workflows/await-workflow.d.ts.map +1 -0
- package/dist/src/engine/workflows/await-workflow.js +45 -0
- package/dist/src/engine/workflows/await-workflow.js.map +1 -0
- package/dist/src/engine/workflows/phased-workflow.d.ts +64 -0
- package/dist/src/engine/workflows/phased-workflow.d.ts.map +1 -0
- package/dist/src/engine/workflows/phased-workflow.js +103 -0
- package/dist/src/engine/workflows/phased-workflow.js.map +1 -0
- package/dist/src/engine/workflows/settled-workflow.d.ts +62 -0
- package/dist/src/engine/workflows/settled-workflow.d.ts.map +1 -0
- package/dist/src/engine/workflows/settled-workflow.js +92 -0
- package/dist/src/engine/workflows/settled-workflow.js.map +1 -0
- package/dist/src/graph/types.d.ts +1 -1
- package/dist/src/graph/types.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/server/pipeline-server-v2.d.ts +48 -0
- package/dist/src/server/pipeline-server-v2.d.ts.map +1 -0
- package/dist/src/server/pipeline-server-v2.js +61 -0
- package/dist/src/server/pipeline-server-v2.js.map +1 -0
- package/dist/src/server/pipeline-server.d.ts +5 -1
- package/dist/src/server/pipeline-server.d.ts.map +1 -1
- package/dist/src/server/pipeline-server.js +71 -10
- package/dist/src/server/pipeline-server.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/ketchup-plan.md +13 -0
- package/package.json +3 -3
- package/src/builder/define-v2.specs.ts +236 -0
- package/src/builder/define-v2.ts +351 -0
- package/src/engine/command-dispatcher.specs.ts +62 -0
- package/src/engine/command-dispatcher.ts +46 -0
- package/src/engine/event-router.specs.ts +75 -0
- package/src/engine/event-router.ts +36 -0
- package/src/engine/index.ts +39 -0
- package/src/engine/pipeline-engine-e2e.specs.ts +776 -0
- package/src/engine/pipeline-engine.integration.specs.ts +126 -0
- package/src/engine/pipeline-engine.specs.ts +70 -0
- package/src/engine/pipeline-engine.ts +82 -0
- package/src/engine/projections/item-status.ts +11 -0
- package/src/engine/projections/latest-run.ts +10 -0
- package/src/engine/projections/message-log.ts +11 -0
- package/src/engine/projections/node-status.ts +10 -0
- package/src/engine/projections/projections.specs.ts +176 -0
- package/src/engine/projections/stats.ts +10 -0
- package/src/engine/sqlite-consumer.specs.ts +42 -0
- package/src/engine/sqlite-consumer.ts +34 -0
- package/src/engine/sqlite-store.specs.ts +46 -0
- package/src/engine/sqlite-store.ts +21 -0
- package/src/engine/workflow-processor.specs.ts +37 -0
- package/src/engine/workflow-processor.ts +57 -0
- package/src/engine/workflows/await-workflow.specs.ts +104 -0
- package/src/engine/workflows/await-workflow.ts +66 -0
- package/src/engine/workflows/phased-workflow.specs.ts +383 -0
- package/src/engine/workflows/phased-workflow.ts +153 -0
- package/src/engine/workflows/settled-workflow.specs.ts +364 -0
- package/src/engine/workflows/settled-workflow.ts +139 -0
- package/src/graph/types.ts +1 -1
- package/src/index.ts +2 -0
- package/src/server/pipeline-server-v2.specs.ts +91 -0
- package/src/server/pipeline-server-v2.ts +70 -0
- package/src/server/pipeline-server.specs.ts +327 -134
- package/src/server/pipeline-server.ts +77 -11
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { createPipelineServerV2 } from './pipeline-server-v2.js';
|
|
2
|
+
|
|
3
|
+
describe('PipelineServerV2', () => {
|
|
4
|
+
it('POST /command dispatches to engine', async () => {
|
|
5
|
+
const server = await createPipelineServerV2();
|
|
6
|
+
const calls: string[] = [];
|
|
7
|
+
|
|
8
|
+
server.engine.registerCommandHandler('TestCommand', (cmd) => {
|
|
9
|
+
calls.push(cmd.type);
|
|
10
|
+
return [{ type: 'TestResult', data: {} }];
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const port = await server.start();
|
|
14
|
+
|
|
15
|
+
const response = await fetch(`http://localhost:${port}/command`, {
|
|
16
|
+
method: 'POST',
|
|
17
|
+
headers: { 'Content-Type': 'application/json' },
|
|
18
|
+
body: JSON.stringify({ type: 'TestCommand', data: { key: 'value' } }),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const body = await response.json();
|
|
22
|
+
expect(response.status).toBe(200);
|
|
23
|
+
expect(body).toEqual({ ok: true });
|
|
24
|
+
expect(calls).toEqual(['TestCommand']);
|
|
25
|
+
|
|
26
|
+
await server.stop();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('GET /health returns ok', async () => {
|
|
30
|
+
const server = await createPipelineServerV2();
|
|
31
|
+
const port = await server.start();
|
|
32
|
+
|
|
33
|
+
const response = await fetch(`http://localhost:${port}/health`);
|
|
34
|
+
const body = await response.json();
|
|
35
|
+
|
|
36
|
+
expect(response.status).toBe(200);
|
|
37
|
+
expect(body).toEqual(expect.objectContaining({ status: 'ok' }));
|
|
38
|
+
|
|
39
|
+
await server.stop();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('GET /events returns SSE headers and streams events', async () => {
|
|
43
|
+
const server = await createPipelineServerV2();
|
|
44
|
+
|
|
45
|
+
server.engine.registerCommandHandler('Ping', () => [{ type: 'Pong', data: { value: 42 } }]);
|
|
46
|
+
|
|
47
|
+
const port = await server.start();
|
|
48
|
+
|
|
49
|
+
const controller = new AbortController();
|
|
50
|
+
const response = await fetch(`http://localhost:${port}/events`, {
|
|
51
|
+
signal: controller.signal,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
expect(response.status).toBe(200);
|
|
55
|
+
expect(response.headers.get('content-type')).toContain('text/event-stream');
|
|
56
|
+
|
|
57
|
+
const reader = response.body!.getReader();
|
|
58
|
+
const decoder = new TextDecoder();
|
|
59
|
+
|
|
60
|
+
await fetch(`http://localhost:${port}/command`, {
|
|
61
|
+
method: 'POST',
|
|
62
|
+
headers: { 'Content-Type': 'application/json' },
|
|
63
|
+
body: JSON.stringify({ type: 'Ping', data: {} }),
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const { value } = await reader.read();
|
|
67
|
+
const text = decoder.decode(value);
|
|
68
|
+
const parsed = JSON.parse(text.replace('data: ', '').trim());
|
|
69
|
+
|
|
70
|
+
expect(parsed).toEqual({ type: 'Pong', data: { value: 42 } });
|
|
71
|
+
|
|
72
|
+
await reader.cancel().catch(() => {});
|
|
73
|
+
controller.abort();
|
|
74
|
+
await server.stop();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('GET /registry returns registered handlers', async () => {
|
|
78
|
+
const server = await createPipelineServerV2();
|
|
79
|
+
server.engine.registerCommandHandler('A', () => []);
|
|
80
|
+
server.engine.registerCommandHandler('B', () => []);
|
|
81
|
+
|
|
82
|
+
const port = await server.start();
|
|
83
|
+
const response = await fetch(`http://localhost:${port}/registry`);
|
|
84
|
+
const body = await response.json();
|
|
85
|
+
|
|
86
|
+
expect(response.status).toBe(200);
|
|
87
|
+
expect(body.commands).toEqual(expect.arrayContaining(['A', 'B']));
|
|
88
|
+
|
|
89
|
+
await server.stop();
|
|
90
|
+
});
|
|
91
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { createServer } from 'node:http';
|
|
2
|
+
import cors from 'cors';
|
|
3
|
+
import express from 'express';
|
|
4
|
+
import { createPipelineEngine } from '../engine/pipeline-engine.js';
|
|
5
|
+
|
|
6
|
+
export async function createPipelineServerV2(config?: { port?: number }) {
|
|
7
|
+
const engine = await createPipelineEngine();
|
|
8
|
+
const app = express();
|
|
9
|
+
app.use(cors());
|
|
10
|
+
app.use(express.json());
|
|
11
|
+
const server = createServer(app);
|
|
12
|
+
|
|
13
|
+
app.post('/command', async (req, res) => {
|
|
14
|
+
const { type, data } = req.body;
|
|
15
|
+
await engine.dispatch({ type, data });
|
|
16
|
+
res.json({ ok: true });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
app.get('/health', (_req, res) => {
|
|
20
|
+
res.json({ status: 'ok', uptime: process.uptime() });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
app.get('/registry', (_req, res) => {
|
|
24
|
+
res.json({ commands: engine.registeredCommands() });
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
app.get('/events', (req, res) => {
|
|
28
|
+
res.writeHead(200, {
|
|
29
|
+
'Content-Type': 'text/event-stream',
|
|
30
|
+
'Cache-Control': 'no-cache',
|
|
31
|
+
Connection: 'keep-alive',
|
|
32
|
+
});
|
|
33
|
+
res.flushHeaders();
|
|
34
|
+
|
|
35
|
+
let connected = true;
|
|
36
|
+
|
|
37
|
+
const listener = (event: { type: string; data: Record<string, unknown> }) => {
|
|
38
|
+
if (connected) {
|
|
39
|
+
res.write(`data: ${JSON.stringify(event)}\n\n`);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
engine.onEvent(listener);
|
|
44
|
+
|
|
45
|
+
req.on('close', () => {
|
|
46
|
+
connected = false;
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
engine,
|
|
52
|
+
app,
|
|
53
|
+
async start(): Promise<number> {
|
|
54
|
+
const port = config?.port ?? 0;
|
|
55
|
+
return new Promise((resolve) => {
|
|
56
|
+
server.listen(port, () => {
|
|
57
|
+
const addr = server.address();
|
|
58
|
+
const actualPort = typeof addr === 'object' && addr ? addr.port : port;
|
|
59
|
+
resolve(actualPort);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
async stop(): Promise<void> {
|
|
64
|
+
await new Promise<void>((resolve) => {
|
|
65
|
+
server.close(() => resolve());
|
|
66
|
+
});
|
|
67
|
+
await engine.close();
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|