Resources tuneup

This commit is contained in:
2026-02-20 12:35:47 +00:00
parent 8a637c7788
commit f48093424c
5 changed files with 2104 additions and 40 deletions
+43 -7
View File
@@ -198,20 +198,22 @@ function buildConnectionConfig(
return { url: `http://127.0.0.1:${port ?? resource.port}` };
}
async function loadResources(): Promise<Resource[]> {
async function parseResources() {
const dir = getResourcesDir();
if (!existsSync(dir)) return [];
const [files, config] = await Promise.all([readdir(dir), readConfig()]);
const files = await readdir(dir);
const serviceFiles = files.filter((f) => f.startsWith('SERVICE_') && f.endsWith('.md'));
const parsed = await Promise.all(
return Promise.all(
serviceFiles.map(async (filename) => {
const content = await Bun.file(`${dir}/${filename}`).text();
return parseResourceFile(filename, content);
}),
);
}
const resources = await Promise.all(
async function loadResources(): Promise<Resource[]> {
const [parsed, config] = await Promise.all([parseResources(), readConfig()]);
return Promise.all(
parsed.map(async (r) => {
const configUrl = config[r.id]?.url;
const status = await checkResourceStatus({ resource: r, configUrl });
@@ -219,8 +221,6 @@ async function loadResources(): Promise<Resource[]> {
return { ...r, ...status, connectionConfig };
}),
);
return resources;
}
export const resourcesRouter = createRouter();
@@ -290,6 +290,42 @@ resourcesRouter.post('/error-log', async (ctx) => {
return ctx.json({ filePath });
});
resourcesRouter.post('/:id/run', async (ctx) => {
const id = ctx.req.param('id');
const { action } = await ctx.req.json<{ action: string }>();
const parsed = await parseResources();
const resource = parsed.find((r) => r.id === id);
if (!resource) return ctx.json({ error: 'Resource not found' }, 404);
const commands: Record<string, string | null> = {
install: resource.installCommand,
uninstall: resource.uninstallCommand,
verify: resource.verifyCommand,
update: resource.updateCommand,
manage: resource.manageCommand,
};
const command = commands[action];
if (!command) return ctx.json({ error: `No ${action} command for this resource` }, 400);
if (command.trimStart().startsWith('sudo')) {
return ctx.json({ error: 'Sudo commands must run in terminal' }, 400);
}
try {
const proc = Bun.spawn(['sh', '-c', command], { stdout: 'pipe', stderr: 'pipe' });
const [stdout, stderr] = await Promise.all([
new Response(proc.stdout).text(),
new Response(proc.stderr).text(),
]);
await proc.exited;
return ctx.json({ exitCode: proc.exitCode, output: (stdout + stderr).trim() });
} catch {
return ctx.json({ exitCode: 1, output: 'Failed to execute command' });
}
});
resourcesRouter.get('/:id', async (ctx) => {
const resources = await loadResources();
const resource = resources.find((r) => r.id === ctx.req.param('id'));