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
+86
View File
@@ -0,0 +1,86 @@
import yaml from "yaml";
import * as store from "../../store.js";
import * as fsStore from "../../fs-store.js";
/**
* @param {{ workflows: Map<string, any>, loadErrors: Map<string, string> }} registry
*/
export default function dashboardPluginFactory(registry) {
/**
* @param {import("fastify").FastifyInstance} fastify
*/
return async function dashboardPlugin(fastify) {
fastify.get("/dashboard", async () => {
const owners = fsStore.listOwners();
let workflowCount = 0;
let enabledCount = 0;
let brokenCount = registry.loadErrors.size;
const brokenWorkflows = [];
for (const [key, message] of registry.loadErrors) {
const [owner, ...rest] = key.split("/");
brokenWorkflows.push({
key,
owner,
file: rest.join("/"),
loadError: message,
});
}
for (const owner of owners) {
let registered = [];
try {
registered = fsStore.readRegisters(owner);
} catch {
registered = [];
}
const files = [
...new Set([...registered, ...fsStore.listOwnerYamlFiles(owner)]),
];
for (const file of files) {
workflowCount += 1;
const key = `${owner}/${file}`;
const loaded = registry.workflows.get(key);
if (loaded?.workflow && loaded.workflow.enabled !== false) {
enabledCount += 1;
} else if (!loaded && !registry.loadErrors.has(key)) {
const raw = fsStore.readWorkflowYaml(owner, file);
if (raw) {
try {
const parsed = yaml.parse(raw);
if (parsed?.enabled !== false) enabledCount += 1;
} catch (err) {
brokenCount += 1;
brokenWorkflows.push({
key,
owner,
file,
loadError: err instanceof Error ? err.message : String(err),
});
}
}
}
}
}
const [running, failed, recent] = await Promise.all([
store.listRuns({ status: "running", limit: 10 }),
store.listRuns({ status: "failed", limit: 20 }),
store.listRuns({ limit: 10 }),
]);
return {
workflowCount,
scriptCount: fsStore.listScriptFiles().length,
enabledCount,
brokenCount,
running,
needsAttention: {
failed,
brokenWorkflows,
},
recent,
};
});
};
}