import { System } from "./runtime"; import { EndpointHook } from "./types"; import express from "express"; export type EndpointRequest = { method: string; path: string; query: { [key: string]: string }; headers: { [key: string]: string }; body: any; }; export type EndpointResponse = { status: number; headers?: { [key: string]: string }; body: any; }; const endPointPrefix = "/_"; export function exposeSystem(system: System) { return ( req: express.Request, res: express.Response, next: express.NextFunction ) => { if (!req.path.startsWith(endPointPrefix)) { return next(); } Promise.resolve() .then(async () => { for (const [plugName, plug] of system.loadedPlugs.entries()) { const manifest = plug.manifest; if (!manifest) { continue; } const endpoints = manifest.hooks?.endpoints; if (endpoints) { let prefix = `${endPointPrefix}/${plugName}`; if (!req.path.startsWith(prefix)) { continue; } for (const { path, method, handler } of endpoints) { let prefixedPath = `${prefix}${path}`; if (prefixedPath === req.path && method === req.method) { try { const response: EndpointResponse = await plug.invoke( handler, [ { path: req.path, method: req.method, body: req.body, query: req.query, headers: req.headers, } as EndpointRequest, ] ); let resp = res.status(response.status); if (response.headers) { for (const [key, value] of Object.entries( response.headers )) { resp = resp.header(key, value); } } resp.send(response.body); return; } catch (e: any) { console.error("Error executing function", e); res.status(500).send(e.message); return; } } } } } next(); }) .catch((e) => { console.error(e); next(e); }); }; }