import "reflect-metadata"; import "dotenv/config"; import { NestFactory } from "@nestjs/core"; import { ValidationPipe } from "@nestjs/common"; import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger"; import { AppModule } from "./app.module"; import { ensurePaymentSchema } from "./config/ensure-schema"; async function bootstrap() { // The edr_payment database/schema must exist before TypeORM boots (migrationsRun: true). await ensurePaymentSchema(); // rawBody: true buffers the unparsed request body onto req.rawBody so webhook handlers // (e.g. Waafi HMAC verification) can sign over the exact bytes the provider signed. const app = await NestFactory.create(AppModule, { rawBody: true }); app.useGlobalPipes( new ValidationPipe({ whitelist: true, transform: true, forbidUnknownValues: false, }), ); const config = new DocumentBuilder() .setTitle("EDR Payment API") .setDescription( "Platform payment microservice: payment intents, provider integration, the single " + "registered webhook per provider, and reliable (outbox) notification of the owning app. " + "Internal endpoints (/payments/*) require the x-service-token header; /webhooks/* is the " + "only public surface. See docs/payment-service/.", ) .setVersion("1.0.0") .addApiKey( { type: "apiKey", name: "x-service-token", in: "header" }, "service-token", ) .build(); SwaggerModule.setup( "api-docs", app, SwaggerModule.createDocument(app, config), { customSiteTitle: "EDR Payment API", swaggerOptions: { persistAuthorization: true }, }, ); const port = process.env.PORT ?? 3003; await app.listen(port); console.log(`🚀 EDR Payment API running on port ${port}`); console.log(`📚 Swagger: http://localhost:${port}/api-docs`); } bootstrap();