- execute: actually call isInScheduleWindow/waitForWindow/sleepBetweenJobs in runSequential (they were dead code); emit queue_status SSE events (running/paused/sleeping/idle) so the pipeline's existing QueueStatus listener lights up - review: POST /:id/retry resets an errored plan to approved, wipes old done/error jobs, rebuilds command from current decisions, queues fresh job - scan: dev-mode DELETE now also wipes jobs + subtitle_files (previously orphaned after every dev reset) - biome: migrate config to 2.4 schema, autoformat 68 files (strings + indentation), relax opinionated a11y/hooks-deps/index-key rules that don't fit this codebase - routeTree.gen.ts regenerated after /nodes removal
77 lines
3.1 KiB
TypeScript
77 lines
3.1 KiB
TypeScript
import { Hono } from "hono";
|
|
import { serveStatic } from "hono/bun";
|
|
import { cors } from "hono/cors";
|
|
import dashboardRoutes from "./api/dashboard";
|
|
import executeRoutes from "./api/execute";
|
|
import pathsRoutes from "./api/paths";
|
|
import reviewRoutes from "./api/review";
|
|
import scanRoutes from "./api/scan";
|
|
import setupRoutes from "./api/setup";
|
|
import subtitlesRoutes from "./api/subtitles";
|
|
import { getDb } from "./db/index";
|
|
import { log } from "./lib/log";
|
|
|
|
const app = new Hono();
|
|
|
|
// ─── CORS (dev: Vite on :5173 talks to Hono on :3000) ────────────────────────
|
|
|
|
app.use("/api/*", cors({ origin: ["http://localhost:5173", "http://localhost:3000"] }));
|
|
|
|
// ─── Request logging ──────────────────────────────────────────────────────────
|
|
|
|
app.use("/api/*", async (c, next) => {
|
|
const start = Date.now();
|
|
await next();
|
|
const ms = Date.now() - start;
|
|
// Skip noisy SSE/polling endpoints
|
|
if (c.req.path.endsWith("/events")) return;
|
|
log(`${c.req.method} ${c.req.path} → ${c.res.status} (${ms}ms)`);
|
|
});
|
|
|
|
// ─── API routes ───────────────────────────────────────────────────────────────
|
|
|
|
import pkg from "../package.json";
|
|
|
|
app.get("/api/version", (c) => c.json({ version: pkg.version }));
|
|
app.route("/api/dashboard", dashboardRoutes);
|
|
app.route("/api/setup", setupRoutes);
|
|
app.route("/api/scan", scanRoutes);
|
|
app.route("/api/review", reviewRoutes);
|
|
app.route("/api/execute", executeRoutes);
|
|
app.route("/api/subtitles", subtitlesRoutes);
|
|
app.route("/api/paths", pathsRoutes);
|
|
|
|
// ─── Static assets (production: serve Vite build) ────────────────────────────
|
|
|
|
app.use("/assets/*", serveStatic({ root: "./dist" }));
|
|
app.use("/favicon.ico", serveStatic({ path: "./dist/favicon.ico" }));
|
|
|
|
// ─── SPA fallback ─────────────────────────────────────────────────────────────
|
|
// All non-API routes serve the React index.html so TanStack Router handles them.
|
|
|
|
app.get("*", (c) => {
|
|
const _accept = c.req.header("Accept") ?? "";
|
|
if (c.req.path.startsWith("/api/")) return c.notFound();
|
|
// In dev the Vite server handles the SPA. In production serve dist/index.html.
|
|
try {
|
|
const html = Bun.file("./dist/index.html").text();
|
|
return html.then((text) => c.html(text));
|
|
} catch {
|
|
return c.text("Run `bun build` first to generate the frontend.", 503);
|
|
}
|
|
});
|
|
|
|
// ─── Start ────────────────────────────────────────────────────────────────────
|
|
|
|
const port = Number(process.env.PORT ?? "3000");
|
|
|
|
log(`netfelix-audio-fix v${pkg.version} starting on http://localhost:${port}`);
|
|
|
|
getDb();
|
|
|
|
export default {
|
|
port,
|
|
fetch: app.fetch,
|
|
idleTimeout: 0,
|
|
};
|