import { Controller, Post, Get, Param, Res, UploadedFile, UseInterceptors, Body, HttpCode, HttpStatus, Logger, } from '@nestjs/common'; import type { Response } from 'express'; import * as path from 'path'; import * as fs from 'fs'; import { FileInterceptor } from '@nestjs/platform-express'; import { HarConverterService } from './har-converter.service'; import type { UploadHarDto, ConversionResult } from './dto/upload-har.dto'; import { AppError, ErrorCode } from '../common/errors/app.error'; @Controller('api/har-converter') export class HarConverterController { private readonly logger = new Logger(HarConverterController.name); constructor(private readonly converterService: HarConverterService) {} @Post('convert') @HttpCode(HttpStatus.OK) @UseInterceptors(FileInterceptor('file')) async convertHarToSwagger( @UploadedFile() file: any, @Body() dto: UploadHarDto, ): Promise { this.logger.log('Received HAR conversion request'); if (!file) { throw new AppError('No file uploaded', ErrorCode.VALIDATION_ERROR, { service: 'HarConverterController', function: 'convertHarToSwagger', }); } if (!file.originalname.endsWith('.har')) { throw new AppError( 'Invalid file type. Only .har files are accepted', ErrorCode.VALIDATION_ERROR, { service: 'HarConverterController', function: 'convertHarToSwagger', payload: { fileName: file.originalname }, }, ); } const startTime = Date.now(); try { const fileContent = file.buffer.toString('utf-8'); const result = await this.converterService.convertHarToSwagger( fileContent, dto, ); const conversionTime = Date.now() - startTime; this.logger.log( `Conversion completed in ${conversionTime}ms - ${result.totalEndpoints} endpoints`, ); return { swagger: result.swagger, downloadUrl: result.downloadUrl, totalEndpoints: result.totalEndpoints, conversionTime, }; } catch (error) { if (error instanceof AppError) { throw error; } throw new AppError( 'Failed to convert HAR file', ErrorCode.INTERNAL_ERROR, { service: 'HarConverterController', function: 'convertHarToSwagger', originalError: error as Error, }, ); } } @Get('download/:fileId') @HttpCode(HttpStatus.OK) downloadSwaggerFile( @Param('fileId') fileId: string, @Res() res: Response, ): void { this.logger.log(`Download request for file: ${fileId}`); try { const uploadsDir = path.join(process.cwd(), 'uploads', 'swagger'); const fileName = `swagger-${fileId}.json`; const filePath = path.join(uploadsDir, fileName); if (!fs.existsSync(filePath)) { throw new AppError('File not found', ErrorCode.VALIDATION_ERROR, { service: 'HarConverterController', function: 'downloadSwaggerFile', payload: { fileId }, }); } res.setHeader('Content-Type', 'application/json'); res.setHeader( 'Content-Disposition', `attachment; filename="swagger-${fileId}.json"`, ); const fileStream = fs.createReadStream(filePath); fileStream.pipe(res); this.logger.log(`File downloaded successfully: ${fileName}`); } catch (error) { if (error instanceof AppError) { throw error; } throw new AppError( 'Failed to download file', ErrorCode.INTERNAL_ERROR, { service: 'HarConverterController', function: 'downloadSwaggerFile', originalError: error as Error, }, ); } } }