import { Hono } from "hono"; import { serveStatic } from "@hono/node-server/serve-static"; import { readFile } from "node:fs/promises"; import path from "node:path"; import { LIMITS } from "../shared/types"; import { createCatalogRepo } from "./catalog-repo"; import { openDatabase } from "./db"; import type { Env } from "./env"; import { HttpError } from "./errors"; import { createRateLimiter } from "./rate-limit"; import { catalogRoutes } from "./routes/catalogs"; export async function createApp(env: Env, options?: { now?: () => number }) { const db = await openDatabase(env.databasePath); const repo = createCatalogRepo(db); const limiter = createRateLimiter( LIMITS.maxCreatesPerHour, LIMITS.rateWindowMs, options?.now, ); const app = new Hono(); app.onError((err, c) => { if (err instanceof HttpError) { return c.json({ error: err.message }, err.status as 400); } console.error(err); return c.json({ error: "خطای داخلی سرور" }, 500); }); app.route("/api", catalogRoutes({ env, repo, limiter })); if (env.isProduction) { const dist = "./dist"; app.use("/*", serveStatic({ root: dist })); app.get("*", async (c) => { const html = await readFile(path.join("dist", "index.html"), "utf8"); return c.html(html); }); } return app; }