Alexander Whitestone
AI infrastructure & Lightning-native agents.
enterimport express, { type Express } from "express"; import cors from "cors"; import path from "path"; import { fileURLToPath } from "url"; import router from "./routes/index.js"; import adminRelayPanelRouter from "./routes/admin-relay-panel.js"; import { responseTimeMiddleware } from "./middlewares/response-time.js"; const app: Express = express(); app.set("trust proxy", 1); // ── CORS (#5) ──────────────────────────────────────────────────────────────── // CORS_ORIGINS = comma-separated list of allowed origins. // Default in production: alexanderwhitestone.com (and www. variant). // Default in development: all origins permitted. const isProd = process.env["NODE_ENV"] === "production"; const rawOrigins = process.env["CORS_ORIGINS"]; const allowedOrigins: string[] = rawOrigins ? rawOrigins.split(",").map((o) => o.trim()).filter(Boolean) : isProd ? [ "https://alexanderwhitestone.com", "https://www.alexanderwhitestone.com", "https://alexanderwhitestone.ai", "https://www.alexanderwhitestone.ai", "https://hermes.tailb74b2d.ts.net", ] : []; app.use( cors({ origin: allowedOrigins.length === 0 ? true : (origin, callback) => { if (!origin || allowedOrigins.includes(origin)) { callback(null, true); } else { callback(new Error(`CORS: origin '${origin}' not allowed`)); } }, credentials: true, methods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"], allowedHeaders: ["Content-Type", "Authorization", "X-Session-Token", "X-Nostr-Token"], exposedHeaders: ["X-Session-Token", "X-Nostr-Token"], }), ); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(responseTimeMiddleware); app.use("/api", router); // ── Relay admin panel at /admin/relay ──────────────────────────────────────── // Served outside /api so the URL is clean: /admin/relay (not /api/admin/relay). app.use(adminRelayPanelRouter); // ── Tower (Matrix 3D frontend) ─────────────────────────────────────────────── // Serve the pre-built Three.js world at /tower. WS client auto-connects to // /api/ws on the same host. // // Path resolution strategy: // ESM dev (tsx ./src/index.ts): import.meta.url is a file:// URL; resolve 3 // levels up from src/ to reach the workspace root. // CJS prod bundle (node dist/index.cjs): import.meta is {} (empty), so fall // back to process.cwd(). The run command is issued from the workspace root, // so process.cwd() == workspace root. const towerDist = (() => { try { const metaUrl: string | undefined = (import.meta as { url?: string }).url; if (metaUrl && metaUrl.startsWith("file:")) { return path.resolve(path.dirname(fileURLToPath(metaUrl)), "../../..", "the-matrix", "dist"); } } catch {} // CJS bundle: run command is `node artifacts/api-server/dist/index.cjs` from workspace root return path.join(process.cwd(), "the-matrix", "dist"); })(); app.use("/tower", express.static(towerDist)); app.get("/tower/*splat", (_req, res) => res.sendFile(path.join(towerDist, "index.html"))); // Vite builds asset references as absolute /assets/... paths. // Mirror them at the root so the browser can load them from /tower. app.use("/assets", express.static(path.join(towerDist, "assets"))); app.use("/sw.js", express.static(path.join(towerDist, "sw.js"))); app.use("/manifest.json", express.static(path.join(towerDist, "manifest.json"))); app.get("/", (_req, res) => { res.setHeader("Content-Type", "text/html"); res.send(`
AI infrastructure & Lightning-native agents.
enter