This commit is contained in:
2026-02-16 19:34:35 +00:00
commit 9ab0940ca4
784 changed files with 41710 additions and 0 deletions
+95
View File
@@ -0,0 +1,95 @@
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { createRouter } from './create-router';
import type { HonoVariables } from './create-router';
import { authRouter } from './api/auth';
import { serverSettingsRouter, settingsPath } from './api/server-settings/server-settings';
import { updateUserHandler } from './api/users/update-user';
import { plansRouter } from './api/plans/plans';
import { skillsRouter } from './api/skills/skills';
import { tasksRouter } from './api/tasks/tasks';
import { processesRouter } from './api/processes/processes';
import { sessionsRouter } from './api/claude/sessions';
import { opencodeSessionsRouter } from './api/opencode/sessions';
import { scrapeRouter } from './api/scrape/scrape';
import { uploadRouter } from './api/upload/upload';
import { settingsRouter } from './api/settings/settings';
import { taskLogsRouter } from './api/task-logs/task-logs';
import { readdirSync, existsSync } from 'node:fs';
import { join } from 'node:path';
import { CustomError } from './custom-errors';
import { userMiddleware, bodyParser } from './_middlewares';
export { Hono };
export { createRouter };
export type { HonoVariables };
export const honoServer = new Hono<{ Variables: HonoVariables }>();
honoServer.use(
cors({
origin: '*',
allowMethods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
allowHeaders: ['Content-Type', 'Authorization'],
}),
);
honoServer.get('/api', (ctx) => ctx.json({ officerAPI: 'ok' }));
honoServer.route('/api/auth', authRouter);
honoServer.route('/api/server-settings', serverSettingsRouter);
const protectedRouter = createRouter();
protectedRouter.use(bodyParser());
protectedRouter.use(userMiddleware);
protectedRouter.put('/users', updateUserHandler);
protectedRouter.route('/plans', plansRouter);
protectedRouter.route('/skills', skillsRouter);
protectedRouter.route('/tasks', tasksRouter);
protectedRouter.route('/processes', processesRouter);
protectedRouter.route('/', sessionsRouter);
protectedRouter.route('/opencode', opencodeSessionsRouter);
protectedRouter.route('/scrape', scrapeRouter);
protectedRouter.route('/upload', uploadRouter);
protectedRouter.route('/user', settingsRouter);
protectedRouter.route('/task-logs', taskLogsRouter);
// Auto-discover and mount plugin routers, then mount the protected router.
// Hono's .route() copies routes at call time, so plugins must be loaded first.
export async function loadPlugins() {
const pluginsDir = join(import.meta.dir, '../workspaces/plugins');
const pluginDirs = readdirSync(pluginsDir, { withFileTypes: true }).filter((d) => d.isDirectory());
const settings = await Bun.file(settingsPath)
.json()
.catch(() => ({}));
const pluginSettings: Record<string, boolean> = settings.plugins ?? {};
for (const dir of pluginDirs) {
if (pluginSettings[dir.name] === false) continue;
const serverIndex = join(pluginsDir, dir.name, 'server', 'index.ts');
if (!existsSync(serverIndex)) continue;
const mod = await import(serverIndex);
if (mod.router && mod.apiPath) {
protectedRouter.route(mod.apiPath, mod.router);
}
}
honoServer.route('/api', protectedRouter);
}
honoServer.onError((error, ctx) => {
if (error instanceof CustomError) {
if (error.returnValue) {
if (typeof error.returnValue === 'string') {
return ctx.text(error.returnValue, error.statusCode);
} else {
return ctx.json(error.returnValue, error.statusCode);
}
}
return ctx.text(error.message, error.statusCode);
}
console.error('Unexpected error:', error.message);
return ctx.text('Internal Server Error', 500);
});