Add operator console (Fleet, Trace, Docs) with screenshots
Some checks are pending
offline / test (push) Waiting to run
Some checks are pending
offline / test (push) Waiting to run
Unify loopback ops, hop testing, and reading order. Overview lists high-level docs first, then architecture, then the rest. Credits: Scott Lindsey, George Lambert, NATS.IO, Grok-Code by Grok.com.
This commit is contained in:
parent
a32c91475c
commit
cf4ef9e3af
17 changed files with 457 additions and 143 deletions
|
|
@ -9,6 +9,7 @@ import fs from 'node:fs';
|
|||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { listServices } from './load.js';
|
||||
import { ACTIONS, Simulator } from '../../verae-zapier-simulator/src/pipeline.js';
|
||||
|
||||
const PUBLIC = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'public');
|
||||
|
||||
|
|
@ -24,12 +25,27 @@ function json(res, code, obj) {
|
|||
export function startControlServer(sup, mon) {
|
||||
const bind = sup.loaded.control?.bind || '127.0.0.1';
|
||||
const port = Number(sup.loaded.control?.port || 3850);
|
||||
const sim = new Simulator();
|
||||
|
||||
const server = http.createServer(async (req, res) => {
|
||||
const url = new URL(req.url, `http://${bind}:${port}`);
|
||||
try {
|
||||
if (req.method === 'GET' && url.pathname === '/health') {
|
||||
return json(res, 200, { ok: true, role: 'fleet-control' });
|
||||
return json(res, 200, { ok: true, role: 'operator-console' });
|
||||
}
|
||||
if (req.method === 'GET' && url.pathname === '/api/sim/actions') {
|
||||
return json(res, 200, { actions: ACTIONS, state: sim.snapshot() });
|
||||
}
|
||||
if (req.method === 'POST' && url.pathname === '/api/sim/reset') {
|
||||
sim.reset();
|
||||
return json(res, 200, { ok: true, state: sim.snapshot() });
|
||||
}
|
||||
if (req.method === 'POST' && url.pathname === '/api/sim/run') {
|
||||
const chunks = [];
|
||||
for await (const c of req) chunks.push(c);
|
||||
const body = JSON.parse(Buffer.concat(chunks).toString('utf8') || '{}');
|
||||
const result = await sim.run(body);
|
||||
return json(res, 200, result);
|
||||
}
|
||||
if (req.method === 'GET' && url.pathname === '/api/services') {
|
||||
return json(res, 200, { services: listServices(sup.loaded), fleetPath: sup.loaded.fleetPath });
|
||||
|
|
@ -92,6 +108,14 @@ export function startControlServer(sup, mon) {
|
|||
fs.createReadStream(dest).pipe(res);
|
||||
return;
|
||||
}
|
||||
if (req.method === 'GET' && url.pathname.startsWith('/docs/screenshots/')) {
|
||||
const dest = path.normalize(path.join(PUBLIC, '..', url.pathname));
|
||||
const root = path.normalize(path.join(PUBLIC, '..'));
|
||||
if (!dest.startsWith(root) || !fs.existsSync(dest)) return json(res, 404, { error: 'not found' });
|
||||
res.writeHead(200, { 'content-type': 'image/png' });
|
||||
fs.createReadStream(dest).pipe(res);
|
||||
return;
|
||||
}
|
||||
json(res, 404, { error: 'not found' });
|
||||
} catch (err) {
|
||||
json(res, 400, { error: err.message });
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue