Spaces:
Paused
Paused
File size: 2,997 Bytes
5d0a52f b7d4394 5d0a52f 0c8b3c0 df56b50 5d0a52f df56b50 5d0a52f 4a940a5 5d0a52f b94940f edb874f b7d4394 5d0a52f 85aec43 b94940f edb874f 5d0a52f 85aec43 b94940f 5d0a52f 4a940a5 b94940f edb874f b94940f 4a940a5 b94940f edb874f 4a940a5 b94940f 4a940a5 0c8b3c0 df56b50 69a8388 5d0a52f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | import { Hono } from "hono";
import { serveStatic } from "@hono/node-server/serve-static";
import { readFileSync, existsSync } from "fs";
import { resolve } from "path";
import type { AccountPool } from "../auth/account-pool.js";
import { getPublicDir, getDesktopPublicDir } from "../paths.js";
import { createHealthRoutes } from "./admin/health.js";
import { createUpdateRoutes } from "./admin/update.js";
import { createConnectionRoutes } from "./admin/connection.js";
import { createSettingsRoutes } from "./admin/settings.js";
import { createUsageStatsRoutes } from "./admin/usage-stats.js";
import type { UsageStatsStore } from "../auth/usage-stats.js";
export function createWebRoutes(accountPool: AccountPool, usageStats: UsageStatsStore): Hono {
const app = new Hono();
const publicDir = getPublicDir();
const desktopPublicDir = getDesktopPublicDir();
const desktopIndexPath = resolve(desktopPublicDir, "index.html");
const webIndexPath = resolve(publicDir, "index.html");
const hasDesktopUI = existsSync(desktopIndexPath);
const hasWebUI = existsSync(webIndexPath);
console.log(`[Web] publicDir: ${publicDir} (exists: ${hasWebUI})`);
console.log(`[Web] desktopPublicDir: ${desktopPublicDir} (exists: ${hasDesktopUI})`);
// Serve Vite build assets (web) — immutable cache (filenames contain content hash)
app.use("/assets/*", async (c, next) => {
c.header("Cache-Control", "public, max-age=31536000, immutable");
await next();
}, serveStatic({ root: publicDir }));
app.get("/", (c) => {
try {
const html = readFileSync(webIndexPath, "utf-8");
c.header("Cache-Control", "no-cache");
return c.html(html);
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
console.error(`[Web] Failed to read HTML file: ${msg}`);
return c.html("<h1>Codex Proxy</h1><p>UI files not found. Run 'npm run build:web' first. The API is still available at /v1/chat/completions</p>");
}
});
// Desktop UI — served at /desktop for Electron
if (hasDesktopUI) {
app.use("/desktop/assets/*", async (c, next) => {
c.header("Cache-Control", "public, max-age=31536000, immutable");
await next();
}, serveStatic({
root: desktopPublicDir,
rewriteRequestPath: (path) => path.replace(/^\/desktop/, ""),
}));
app.get("/desktop", (c) => {
const html = readFileSync(desktopIndexPath, "utf-8");
c.header("Cache-Control", "no-cache");
return c.html(html);
});
} else {
app.get("/desktop", (c) => {
console.warn(`[Web] Desktop UI not found at ${desktopIndexPath}, falling back to web UI`);
return c.redirect("/");
});
}
// Mount admin subroutes
app.route("/", createHealthRoutes(accountPool));
app.route("/", createUpdateRoutes());
app.route("/", createConnectionRoutes(accountPool));
app.route("/", createSettingsRoutes());
app.route("/", createUsageStatsRoutes(accountPool, usageStats));
return app;
}
|