ceo-api/src/main.ts

69 lines
2.2 KiB
TypeScript

import 'reflect-metadata';
import helmet from 'helmet';
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { Logger } from 'nestjs-pino';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { migrate } from 'drizzle-orm/node-postgres/migrator';
import { AppModule } from './app.module';
import { db } from './db/client';
const REQUIRED_ENV_VARS = [
'DATABASE_URL',
'REDIS_URL',
'SUPABASE_URL',
'SUPABASE_SERVICE_ROLE_KEY',
] as const;
function validateEnv(): void {
const missing = REQUIRED_ENV_VARS.filter((key) => !process.env[key]);
if (missing.length > 0) {
throw new Error(`Missing required environment variables: ${missing.join(', ')}`);
}
if (!process.env.SUPABASE_JWT_SECRET) {
console.warn('[WARN] SUPABASE_JWT_SECRET not set — JWT verification will use GoTrue round-trip');
}
}
async function bootstrap() {
validateEnv();
// Apply pending DB migrations — skip if schema was pre-initialized via drizzle push
try {
await migrate(db, { migrationsFolder: './drizzle' });
} catch (err) {
const msg = (err as Error & { message: string }).message ?? '';
if (msg.includes('already exists')) {
console.warn('[bootstrap] Schema already initialized — migration skipped. Run db:migrate manually if needed.');
} else {
throw err;
}
}
const app = await NestFactory.create(AppModule, { bufferLogs: true });
app.useLogger(app.get(Logger));
app.use(helmet());
app.setGlobalPrefix('v1', { exclude: ['health'] });
app.useGlobalPipes(
new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true, transform: true }),
);
const rawOrigins = process.env.CORS_ORIGINS ?? 'http://localhost:3000';
const allowedOrigins = rawOrigins.split(',').map((o) => o.trim()).filter(Boolean);
app.enableCors({ origin: allowedOrigins, credentials: true });
if (process.env.SWAGGER_ENABLED === 'true') {
const config = new DocumentBuilder()
.setTitle('CEO OS API')
.setVersion('0.1.0')
.addBearerAuth()
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('docs', app, document);
}
const port = process.env.PORT ?? 3001;
await app.listen(port);
}
bootstrap();