import { NestFactory } from "@nestjs/core"; import { ValidationPipe } from "@nestjs/common"; import cookieParser from "cookie-parser"; import { AppModule } from "./app.module"; import { getTrustedOrigins } from "./auth/auth.config"; import { GlobalExceptionFilter } from "./filters/global-exception.filter"; function getPort(): number { const portEnv = process.env.PORT; if (portEnv === undefined || portEnv === "") { return 3001; } const port = parseInt(portEnv, 10); if (isNaN(port)) { throw new Error(`Invalid PORT environment variable: "${portEnv}". PORT must be a number.`); } if (port < 1 || port > 65535) { throw new Error( `Invalid PORT environment variable: ${String(port)}. PORT must be between 1 and 65535.` ); } return port; } async function bootstrap() { const app = await NestFactory.create(AppModule); // Enable cookie parser for session handling app.use(cookieParser()); // Enable global validation pipe with transformation app.useGlobalPipes( new ValidationPipe({ transform: true, whitelist: true, forbidNonWhitelisted: true, transformOptions: { enableImplicitConversion: false, }, }) ); app.useGlobalFilters(new GlobalExceptionFilter()); // Configure CORS for cookie-based authentication // Origin list is shared with BetterAuth trustedOrigins via getTrustedOrigins() const trustedOrigins = getTrustedOrigins(); console.log(`[CORS] Trusted origins: ${JSON.stringify(trustedOrigins)}`); app.enableCors({ origin: trustedOrigins, credentials: true, // Required for cookie-based authentication methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"], allowedHeaders: ["Content-Type", "Authorization", "Cookie", "X-CSRF-Token", "X-Workspace-Id"], exposedHeaders: ["Set-Cookie"], maxAge: 86400, // 24 hours - cache preflight requests }); const port = getPort(); await app.listen(port); console.log(`API running on http://localhost:${String(port)}`); } bootstrap().catch((err: unknown) => { const isProduction = process.env.NODE_ENV === "production"; const errorMessage = err instanceof Error ? err.message : String(err); const errorStack = err instanceof Error ? err.stack : undefined; if (isProduction) { console.error( JSON.stringify({ level: "error", message: "Failed to start application", error: errorMessage, timestamp: new Date().toISOString(), }) ); } else { console.error("Failed to start application:", errorMessage); if (errorStack) { console.error(errorStack); } } process.exit(1); });