86 lines
2.4 KiB
TypeScript
86 lines
2.4 KiB
TypeScript
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<EndpointHook>) {
|
|
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);
|
|
});
|
|
};
|
|
}
|