featchoremiscmiscmisc
This commit is contained in:
parent
fb3d904f5b
commit
44f345fff0
8 changed files with 914 additions and 0 deletions
88
plumbing.js
Normal file
88
plumbing.js
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
// plumbing.js — read-only JSON utility API.
|
||||
//
|
||||
// This is plumbing, not part of the product surface. The workshop UI renders
|
||||
// HTML; anything that wants structured data (the bliss CLI, scripts, tooling)
|
||||
// reads it here instead of scraping fragments. Read-only by design: all writes
|
||||
// still go through the real /workshop/* endpoints a human uses, so this stays a
|
||||
// thin mirror of model.* with no business logic of its own.
|
||||
|
||||
const express = require("express");
|
||||
const model = require("./db");
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// Wrap a handler so thrown errors come back as JSON instead of an HTML stack.
|
||||
function json(handler) {
|
||||
return (req, res) => {
|
||||
try {
|
||||
const body = handler(req);
|
||||
if (body === undefined || body === null) {
|
||||
return res.status(404).json({ error: "not found" });
|
||||
}
|
||||
return res.json(body);
|
||||
} catch (e) {
|
||||
return res.status(500).json({ error: String(e), stack: e.stack });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// All structures.
|
||||
router.get(
|
||||
"/structures",
|
||||
json(() => model.getStructures()),
|
||||
);
|
||||
|
||||
// One structure with everything the sidebar shows, in one call.
|
||||
router.get(
|
||||
"/structures/:id",
|
||||
json((req) => {
|
||||
const structure = model.getStructure(req.params.id);
|
||||
if (!structure) return null;
|
||||
return {
|
||||
structure,
|
||||
routes: model.getRoutes(req.params.id),
|
||||
templates: model.getTemplates(req.params.id),
|
||||
dbs: model.getDbsForStructure(req.params.id),
|
||||
files: model.getFilesForStruct(req.params.id),
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
// One route, including its handler source.
|
||||
router.get(
|
||||
"/structures/:id/routes/:routeId",
|
||||
json((req) => model.getRoute(req.params.routeId)),
|
||||
);
|
||||
|
||||
// One template, including content + test_object.
|
||||
router.get(
|
||||
"/structures/:id/templates/:templateId",
|
||||
json((req) => model.getTemplate(req.params.templateId)),
|
||||
);
|
||||
|
||||
// One db (scoped to the structure), including its library source.
|
||||
router.get(
|
||||
"/structures/:id/dbs/:dbId",
|
||||
json((req) => model.getDbForStructure(req.params.id, req.params.dbId)),
|
||||
);
|
||||
|
||||
// Files attached to a structure.
|
||||
router.get(
|
||||
"/structures/:id/files",
|
||||
json((req) => model.getFilesForStruct(req.params.id)),
|
||||
);
|
||||
|
||||
// Logs for a route. ?since=<id> returns only newer rows (for polling).
|
||||
router.get(
|
||||
"/structures/:id/routes/:routeId/logs",
|
||||
json((req) => {
|
||||
const { since } = req.query;
|
||||
const logs =
|
||||
since !== undefined
|
||||
? model.getNewLogsByRoute(req.params.routeId, since)
|
||||
: model.getLogsByRoute(req.params.routeId);
|
||||
return { logs, since: model.getMostRecentLogIdByRoute(req.params.routeId) };
|
||||
}),
|
||||
);
|
||||
|
||||
module.exports = router;
|
||||
Loading…
Add table
Add a link
Reference in a new issue