add production stuff

This commit is contained in:
2026-02-12 19:22:40 +01:00
parent 08d2165a70
commit da131834ce
3 changed files with 36 additions and 6 deletions
+2 -1
View File
@@ -2,7 +2,8 @@
PORT=8000
NODE_ENV=production
DATABASE_URL=file:/app/prisma/dev.db
FRONTEND_URL=http://localhost:6767
FRONTEND_URL=https://draw.louiscreates.com
API_BASE_PATH=/api
# Keep disabled unless traffic always comes through a trusted reverse proxy.
TRUST_PROXY=false
AUTH_MODE=local
+18
View File
@@ -12,6 +12,7 @@ interface Config {
nodeEnv: string;
databaseUrl?: string;
frontendUrl?: string;
apiBasePath: string;
authMode: AuthMode;
jwtSecret: string;
jwtAccessExpiresIn: string;
@@ -82,6 +83,22 @@ const parseFrontendUrl = (raw: string | undefined): string | undefined => {
return normalized.length > 0 ? normalized : undefined;
};
const parseApiBasePath = (raw: string | undefined): string => {
const fallback = "/api";
if (!raw || raw.trim().length === 0) return fallback;
const trimmed = raw.trim();
if (trimmed === "/") return "/";
const withLeadingSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
const withoutTrailingSlash =
withLeadingSlash.length > 1 && withLeadingSlash.endsWith("/")
? withLeadingSlash.slice(0, -1)
: withLeadingSlash;
return withoutTrailingSlash.length > 0 ? withoutTrailingSlash : fallback;
};
const resolveDatabaseUrl = (rawUrl?: string) => {
const backendRoot = path.resolve(__dirname, "../");
const defaultDbPath = path.resolve(backendRoot, "prisma/dev.db");
@@ -189,6 +206,7 @@ export const config: Config = {
nodeEnv: getOptionalEnv("NODE_ENV", "development"),
databaseUrl: process.env.DATABASE_URL,
frontendUrl: parseFrontendUrl(process.env.FRONTEND_URL),
apiBasePath: parseApiBasePath(process.env.API_BASE_PATH),
authMode: resolvedAuthMode,
jwtSecret: resolveJwtSecret(getOptionalEnv("NODE_ENV", "development")),
jwtAccessExpiresIn: getOptionalEnv("JWT_ACCESS_EXPIRES_IN", "15m"),
+16 -5
View File
@@ -59,6 +59,7 @@ const normalizeOrigins = (rawOrigins?: string | null): string[] => {
const allowedOrigins = normalizeOrigins(config.frontendUrl);
console.log("Allowed origins:", allowedOrigins);
console.log("API base path:", config.apiBasePath);
const isDev = (process.env.NODE_ENV || "development") !== "production";
const isLocalDevOrigin = (origin: string): boolean => {
@@ -132,6 +133,10 @@ if (trustProxyValue === true) {
const httpServer = createServer(app);
const io = new Server(httpServer, {
path:
config.apiBasePath === "/"
? "/socket.io"
: `${config.apiBasePath}/socket.io`,
cors: {
origin: (origin, cb) => cb(null, isAllowedOrigin(origin ?? undefined)),
credentials: true,
@@ -329,15 +334,18 @@ const generalRateLimiter = rateLimit({
app.use(generalRateLimiter);
const apiApp = express();
app.use(config.apiBasePath, apiApp);
registerCsrfProtection({
app,
app: apiApp,
isAllowedOrigin,
maxRequestsPerWindow: config.csrfMaxRequests,
enableDebugLogging: process.env.DEBUG_CSRF === "true",
});
// Authentication routes (no CSRF required, uses JWT)
app.use("/auth", authRouter);
apiApp.use("/auth", authRouter);
// Files field can contain arbitrary file metadata, so we use unknown and validate structure
const filesFieldSchema = z
@@ -556,13 +564,13 @@ registerSocketHandlers({
jwtSecret: config.jwtSecret,
});
app.get("/health", (req, res) => {
apiApp.get("/health", (req, res) => {
res.status(200).json({ status: "ok" });
});
// Health check endpoint doesn't require auth
registerDashboardRoutes(app, {
registerDashboardRoutes(apiApp, {
prisma,
requireAuth,
asyncHandler,
@@ -584,7 +592,7 @@ registerDashboardRoutes(app, {
});
registerImportExportRoutes({
app,
app: apiApp,
prisma,
requireAuth,
asyncHandler,
@@ -622,5 +630,8 @@ if (isMain) {
console.log(`Server running on port ${PORT}`);
console.log(`Environment: ${config.nodeEnv}`);
console.log(`Frontend URL: ${config.frontendUrl}`);
console.log(
`API endpoints: ${config.apiBasePath === "/" ? "/" : `${config.apiBasePath}/`}*`
);
});
}