feat: enhance project structure with server and workflow management

- Introduced a new server package with Fastify for handling API requests and workflows.
- Implemented user authentication and authorization with JWT and cookie management.
- Added endpoints for managing workflows, runs, and user accounts.
- Established a dashboard for monitoring workflow status and statistics.
- Included a script sandbox for executing user-defined scripts securely.
- Updated README with setup instructions and API documentation.
- Configured database migrations for user management.
- Enhanced logging capabilities for better traceability.
This commit is contained in:
2026-08-14 14:25:37 +07:00
parent 5574d6f723
commit 023cf83cfa
48 changed files with 6127 additions and 359 deletions
+64
View File
@@ -0,0 +1,64 @@
import { clearScriptCache } from "../../script-sandbox.js";
import * as fsStore from "../../fs-store.js";
/**
* @param {{ referencedScripts: () => Set<string> }} registry
*/
export default function scriptsPluginFactory(registry) {
/**
* @param {import("fastify").FastifyInstance} fastify
*/
return async function scriptsPlugin(fastify) {
fastify.get("/scripts", async () => {
return { scripts: fsStore.listScriptFiles() };
});
fastify.get("/scripts/:name", async (req, reply) => {
const { name } = /** @type {{ name: string }} */ (req.params);
try {
fsStore.assertScriptName(name);
} catch (err) {
return reply.code(err.statusCode ?? 400).send({ error: err.message });
}
const content = fsStore.readScript(name);
if (content == null) return reply.code(404).send({ error: "script not found" });
return { name, content };
});
fastify.put("/scripts/:name", async (req, reply) => {
const { name } = /** @type {{ name: string }} */ (req.params);
try {
fsStore.assertScriptName(name);
} catch (err) {
return reply.code(err.statusCode ?? 400).send({ error: err.message });
}
const body = /** @type {{ content?: string }} */ (req.body ?? {});
if (typeof body.content !== "string") {
return reply.code(400).send({ error: "content is required" });
}
const existed = fsStore.readScript(name) != null;
fsStore.writeScript(name, body.content);
clearScriptCache();
return reply.code(existed ? 200 : 201).send({ name });
});
fastify.delete("/scripts/:name", async (req, reply) => {
const { name } = /** @type {{ name: string }} */ (req.params);
try {
fsStore.assertScriptName(name);
} catch (err) {
return reply.code(err.statusCode ?? 400).send({ error: err.message });
}
if (registry.referencedScripts().has(name)) {
return reply
.code(409)
.send({ error: "script is referenced by a workflow" });
}
if (!fsStore.deleteScript(name)) {
return reply.code(404).send({ error: "script not found" });
}
clearScriptCache();
return { ok: true };
});
};
}