rspace-online/modules/cart/standalone.ts

59 lines
1.7 KiB
TypeScript

/**
* Cart standalone server — independent deployment at rcart.online.
*/
import { Hono } from "hono";
import { cors } from "hono/cors";
import { resolve } from "node:path";
import { cartModule } from "./mod";
const PORT = Number(process.env.PORT) || 3000;
const DIST_DIR = resolve(import.meta.dir, "../../dist");
const app = new Hono();
app.use("/api/*", cors({
origin: "*",
exposeHeaders: ["X-PAYMENT-REQUIRED", "X-PAYMENT-RESPONSE"],
allowHeaders: ["Content-Type", "Authorization", "X-PAYMENT", "X-PAYMENT-RESPONSE"],
}));
app.get("/.well-known/webauthn", (c) => {
return c.json(
{ origins: ["https://rspace.online"] },
200,
{ "Access-Control-Allow-Origin": "*", "Cache-Control": "public, max-age=3600" }
);
});
app.route("/", cartModule.routes);
function getContentType(path: string): string {
if (path.endsWith(".html")) return "text/html";
if (path.endsWith(".js")) return "application/javascript";
if (path.endsWith(".css")) return "text/css";
if (path.endsWith(".json")) return "application/json";
if (path.endsWith(".svg")) return "image/svg+xml";
if (path.endsWith(".png")) return "image/png";
if (path.endsWith(".ico")) return "image/x-icon";
return "application/octet-stream";
}
Bun.serve({
port: PORT,
async fetch(req) {
const url = new URL(req.url);
if (url.pathname !== "/" && !url.pathname.startsWith("/api/")) {
const assetPath = url.pathname.slice(1);
if (assetPath.includes(".")) {
const file = Bun.file(resolve(DIST_DIR, assetPath));
if (await file.exists()) {
return new Response(file, { headers: { "Content-Type": getContentType(assetPath) } });
}
}
}
return app.fetch(req);
},
});
console.log(`rCart standalone server running on http://localhost:${PORT}`);