Here is the complete Express REST API and OpenAPI 3.0 specification.
This implementation provides full CRUD capabilities for the routine catalog,
dynamic remote execution, and a dedicated endpoint to distribute the compiled
artifact to edge nodes or browsers.
1. The OpenAPI Specification (harness/openapi.json)
This JSON defines the contract for the registry. Express will serve this
directly and use it to render the Swagger UI.
{ "openapi": "3.0.0", "info": { "title": "Routine Registry API",
"description": "Network distribution and execution service for JS routines.",
"version": "1.0.0" }, "paths": { "/routines": { "get": { "summary": "List all
registered routines", "responses": { "200": { "description": "Array of routine
specifications" } } } }, "/routines/{name}": { "get": { "summary": "Get
routine specification", "parameters": [{ "name": "name", "in": "path",
"required": true, "schema": { "type": "string" } }], "responses": { "200": {
"description": "Routine spec.json" } } }, "put": { "summary": "Create or
update a routine", "parameters": [{ "name": "name", "in": "path", "required":
true, "schema": { "type": "string" } }], "requestBody": { "required": true,
"content": { "application/json": { "schema": { "type": "object", "properties":
{ "spec": { "type": "object", "description": "The spec.json object" }, "code":
{ "type": "string", "description": "The JS anonymous function code" } } } } }
}, "responses": { "200": { "description": "Routine saved successfully" } } }
}, "/routines/{name}/artifact": { "get": { "summary": "Download the compiled,
self-contained executable artifact", "parameters": [{ "name": "name", "in":
"path", "required": true, "schema": { "type": "string" } }], "responses": {
"200": { "description": "Javascript IIFE payload", "content": {
"application/javascript": {} } } } } }, "/routines/{name}/run": { "post": {
"summary": "Execute a routine remotely on the registry node", "parameters": [{
"name": "name", "in": "path", "required": true, "schema": { "type": "string" }
}], "requestBody": { "required": true, "content": { "application/json": {
"schema": { "type": "object" } } } }, "responses": { "200": { "description":
"Execution result" } } } } } }
2. The Express API (harness/api.js)
This binds the OpenAPI documentation to a Swagger UI and wires up the
file-system operations and execution sandbox we built earlier.
const express = require('express'); const swaggerUi = require('swagger-ui-expre
ss'); const fs = require('fs').promises; const path = require('path'); const {
runSecurely } = require('./runner'); const { compileRoutine } =
require('./packager'); const app = express(); app.use(express.json()); // 1.
Swagger UI Setup const openapiSpec = require('./openapi.json');
app.use('/docs', swaggerUi.serve, swaggerUi.setup(openapiSpec));
app.get('/openapi.json', (req, res) => res.json(openapiSpec)); const
ROUTINE_DIR = path.join(__dirname, '../routines'); // 2. List Routines
app.get('/routines', async (req, res) => { try { const entries = await
fs.readdir(ROUTINE_DIR, { withFileTypes: true }); const routines = []; for
(const entry of entries) { if (entry.isDirectory()) { const specPath =
path.join(ROUTINE_DIR, entry.name, 'spec.json'); try { const spec =
JSON.parse(await fs.readFile(specPath, 'utf8')); routines.push(spec); } catch
(e) { // Skip invalid directories silently for the list endpoint } } }
res.json(routines); } catch (err) { res.status(500).json({ error: err.message
}); } }); // 3. Get Routine Spec app.get('/routines/:name', async (req, res)
=> { try { const specPath = path.join(ROUTINE_DIR, req.params.name,
'spec.json'); const spec = JSON.parse(await fs.readFile(specPath, 'utf8'));
res.json(spec); } catch (err) { res.status(404).json({ error: 'Routine not
found' }); } }); // 4. Create or Update Routine app.put('/routines/:name',
async (req, res) => { const { name } = req.params; const { spec, code } =
req.body; if (!spec || !code) { return res.status(400).json({ error: 'Both
spec and code are required' }); } try { const dir = path.join(ROUTINE_DIR,
name); const implDir = path.join(dir, 'implementations/javascript'); await
fs.mkdir(implDir, { recursive: true }); // Ensure the spec points to the right
entry format spec.name = name; if (!spec.implementations) spec.implementations
= {}; spec.implementations.javascript = { entry: "implementations/javascript/in
dex.js", format: "anonymous_function" }; await fs.writeFile(p
ath.join(dir, 'spec.json'), JSON.stringify(spec, null, 2)); await
fs.writeFile(path.join(implDir, 'index.js'), code); res.json({ success: true,
message: `Routine [${name}] saved.` }); } catch (err) { res.status(500).json({
error: err.message }); } }); // 5. Get Compiled Artifact (for Edge Nodes /
Browsers) app.get('/routines/:name/artifact', async (req, res) => { try {
const artifact = await compileRoutine(req.params.name); res.type('application/j
avascript').send(artifact); } catch (err) { res.status(400).json({ error:
`Compilation failed: ${err.message}` }); } }); // 6. Run Routine Remotely
app.post('/routines/:name/run', async (req, res) => { try { const dir =
path.join(ROUTINE_DIR, req.params.name); const specPath = path.join(dir,
'spec.json'); const spec = JSON.parse(await fs.readFile(specPath, 'utf8'));
const codePath = path.join(dir, spec.implementations.javascript.entry); const
code = await fs.readFile(codePath, 'utf8'); // Execute via the V8 vm lockdown
module const result = await runSecurely(code, req.body); res.json({ success:
true, result }); } catch (err) { res.status(400).json({ success: false, error:
err.message }); } }); const PORT = process.env.PORT || 3000; app.listen(PORT,
() => { console.log(` Registry API listening on port ${PORT}`); console.log(`
Swagger UI available at http://localhost:${PORT}/docs`); });
Network Distribution Dynamics
This setup gives you two entirely different ways to consume logic across a
distributed network:
RPC Mode (POST /run): Lightweight edge nodes (or frontends) can treat the
Registry as a computation engine. They pass parameters, the Registry runs the
code in the Node vm sandbox, and returns the result.
Pull Mode (GET /artifact): Systems that need zero-latency execution can fetch
the artifact on startup, cache it locally, and eval() it into their own
runtime.