Something went wrong. Try again.
because I got bored of customising my CV for every job
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101import { createHash } from "node:crypto";import { readFile, unlink } from "node:fs/promises";import type { User as DomainUser } from "@cv/core";import { JwtAuthGuard } from "@cv/auth";import { validateFile } from "@cv/file-upload";import { BadRequestException, Body, Controller, Logger, Post, Req, UploadedFile, UseGuards, UseInterceptors,} from "@nestjs/common";import { FileInterceptor } from "@nestjs/platform-express";import { FileImportSource } from "@/modules/data-import/sources/file-import-source";import { ImportService } from "@/modules/data-import/import.service";
@Controller("api/cv-parser")export class FileUploadController { private readonly logger = new Logger(FileUploadController.name);
constructor( private readonly importService: ImportService, private readonly fileImportSource: FileImportSource, ) {}
@Post("upload") @UseGuards(JwtAuthGuard) @UseInterceptors(FileInterceptor("file")) async upload( @Req() req: { user: DomainUser }, @Body("profileId") profileId: string, @UploadedFile() file?: Express.Multer.File, ) { if (!file) { throw new BadRequestException("No file provided"); }
if (!profileId) { throw new BadRequestException("profileId is required"); }
const filePath = file.path;
try { const buffer = file.buffer ?? (await readFile(filePath));
const validation = validateFile({ buffer, mimeType: file.mimetype, originalName: file.originalname, sizeBytes: file.size, });
if (!validation.valid) { throw new Error(`File validation failed: ${validation.error}`); }
const fingerprint = createHash("sha256").update(buffer).digest("hex");
const userFile = await this.importService.createImport( req.user, profileId, this.fileImportSource, { fileName: file.originalname, mimeType: file.mimetype, sizeBytes: file.size, fingerprint, }, { buffer, mimeType: file.mimetype }, );
return { userFileId: userFile.id, status: userFile.status, fileName: userFile.fileName, sizeBytes: userFile.sizeBytes, }; } catch (error) { this.logger.error(`File upload failed: ${error instanceof Error ? error.message : error}`, error instanceof Error ? error.stack : undefined);
const message = error instanceof Error ? error.message : "Failed to process file";
throw new BadRequestException(message); } finally { if (filePath) { try { await unlink(filePath); } catch (err) { this.logger.warn(`Failed to clean up temporary file ${filePath}: ${err instanceof Error ? err.message : err}`); } } } }}