import { INestApplication } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { execSync } from 'child_process'; const basicAuth = require('express-basic-auth'); const getBranchName = (): string => { // First, try to get from environment variable (for Docker/Hugging Face) if (process.env.BRANCH_NAME) { return process.env.BRANCH_NAME; } // Fallback to git command (for local development) try { return execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8', cwd: process.cwd(), }).trim(); } catch (error: any) { console.warn('Could not get git branch name:', error.message); return 'unknown'; } }; export const setupSwagger = (app: INestApplication) => { const configService = app.get(ConfigService); const swaggerPassword = configService.get('SWAGGER_PASSWORD'); const isApiTokenEnabled = configService.get('API_TOKEN_ENABLED') === 'true'; app.use( ['/api'], basicAuth({ challenge: true, users: { admin: swaggerPassword }, }), ); const configBuilder = new DocumentBuilder() .addBearerAuth() .setTitle(`StreamFlix API: ${getBranchName()}`) .setDescription('The StreamFlix API documentation') .setVersion('1.0.0'); if (isApiTokenEnabled) { configBuilder.addApiKey( { type: 'apiKey', name: 'x-api-token', in: 'header', }, 'x-api-token', ); } const config = configBuilder.build(); const documentOptions = isApiTokenEnabled ? { operationIdFactory: (controllerKey: string, methodKey: string) => methodKey, } : undefined; const document = SwaggerModule.createDocument(app, config, documentOptions); // Apply security globally if API token is enabled if (isApiTokenEnabled && document.components?.securitySchemes) { document.security = [{ 'x-api-token': [] }]; } SwaggerModule.setup('api', app, document, { customCss: '.swagger-ui { background: #E6F3FF; }', swaggerOptions: { persistAuthorization: true, }, }); };