File size: 3,461 Bytes
423c2fb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
78
79
80
81
82
import express, { type Express } from "express";
import cors from "cors";
import pinoHttp from "pino-http";
import router from "./routes";
import { logger } from "./lib/logger";
import { createBareServer } from "@nebula-services/bare-server-node";
import path from "path";
import { fileURLToPath } from "url";
import { createRequire } from "module";
import type { IncomingMessage } from "http";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const require = createRequire(import.meta.url);

// ─── Bare servers (1-5) ───────────────────────────────────────────────────────
export const bare1 = createBareServer("/api/bare/",  { logErrors: false, blockLocal: false });
export const bare2 = createBareServer("/api/bare2/", { logErrors: false, blockLocal: false });
export const bare3 = createBareServer("/api/bare3/", { logErrors: false, blockLocal: false });
export const bare4 = createBareServer("/api/bare4/", { logErrors: false, blockLocal: false });
export const bare5 = createBareServer("/api/bare5/", { logErrors: false, blockLocal: false });

export const bares = [bare1, bare2, bare3, bare4, bare5];

// ─── Wisp server (optional β€” install wisp-server-node to enable) ──────────────
type WispHandler = (req: IncomingMessage, socket: any, head: Buffer) => void;
export let wispHandler: WispHandler | null = null;

try {
  const wisp = require("wisp-server-node");
  wispHandler = wisp.routeRequest ?? wisp.default?.routeRequest ?? null;
  if (wispHandler) logger.info("Wisp protocol enabled at /api/wisp");
} catch {
  logger.warn("wisp-server-node not installed β€” Wisp disabled. Run: pnpm --filter @workspace/api-server add wisp-server-node");
}

// ─── Express app ──────────────────────────────────────────────────────────────
const app: Express = express();

app.use(
  pinoHttp({
    logger,
    serializers: {
      req(req) { return { id: req.id, method: req.method, url: req.url?.split("?")[0] }; },
      res(res) { return { statusCode: res.statusCode }; },
    },
  }),
);
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

function resolvePkgDist(pkg: string): string {
  const mainPath = require.resolve(pkg);
  const pkgRoot = path.dirname(path.dirname(mainPath));
  return path.join(pkgRoot, "dist");
}

app.use(
  "/api/baremod",
  express.static(resolvePkgDist("@mercuryworkshop/bare-as-module3"), { index: false }),
);

app.use("/api", router);

// ─── Static frontend (production only) ───────────────────────────────────────
// In Docker/production, the Vite-built frontend lives at ../public relative to dist/
if (process.env.NODE_ENV === "production") {
  const staticDir = path.join(__dirname, "../public");
  app.use(express.static(staticDir));
  // SPA fallback β€” send index.html for any unmatched route that isn't /api or a proxy route
  app.use((req, res, next) => {
    const p = req.path;
    if (!p.startsWith("/api") && !p.startsWith("/service") && !p.startsWith("/baremux")) {
      res.sendFile(path.join(staticDir, "index.html"));
    } else {
      next();
    }
  });
}

export default app;