From f7f706e1e1e547e54745b23e596ac141926750cc Mon Sep 17 00:00:00 2001 From: z3n Date: Fri, 26 Jun 2026 12:02:13 +0000 Subject: [PATCH] back(uploads): I/O fichiers en async (non bloquant) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit readFileSync/existsSync/mkdirSync -> fs/promises (readFile, mkdir recursive idempotent). detectMainFile devient async. Retire l'import fs sync inutilisé. Co-Authored-By: Claude Opus 4.8 --- .../src/modules/uploads/uploads.controller.ts | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/back/src/modules/uploads/uploads.controller.ts b/back/src/modules/uploads/uploads.controller.ts index d3aca50..2d18ec9 100644 --- a/back/src/modules/uploads/uploads.controller.ts +++ b/back/src/modules/uploads/uploads.controller.ts @@ -9,7 +9,6 @@ import { } from '@nestjs/common'; import { FilesInterceptor } from '@nestjs/platform-express'; import { diskStorage } from 'multer'; -import * as fs from 'fs'; import * as fsPromises from 'fs/promises'; import * as path from 'path'; import * as os from 'os'; @@ -69,11 +68,13 @@ export class UploadsController { } /* Lire tous les contenus en mémoire avant toute suppression */ - const fileContents = files.map((file) => ({ - name: file.originalname, - path: file.path, - content: fs.readFileSync(file.path, 'utf-8'), - })); + const fileContents = await Promise.all( + files.map(async (file) => ({ + name: file.originalname, + path: file.path, + content: await fsPromises.readFile(file.path, 'utf-8'), + })), + ); /* Nettoyage immédiat des fichiers temporaires */ for (const file of files) { @@ -197,11 +198,9 @@ export class UploadsController { if (!body.name) throw new BadRequestException('name is required'); if (!body.convention) throw new BadRequestException('convention is required'); - /* Crée le répertoire si absent */ + /* Crée le répertoire si absent (mkdir recursive est idempotent) */ const uploadDir = path.join(os.tmpdir(), 'datacat-uploads'); - if (!fs.existsSync(uploadDir)) { - fs.mkdirSync(uploadDir, { recursive: true }); - } + await fsPromises.mkdir(uploadDir, { recursive: true }); let yamlContent: string; let detectedType: ApiType | null = null; @@ -211,7 +210,7 @@ export class UploadsController { yamlContent = ''; } else if (files.length === 1) { /* Cas simple : un seul fichier */ - yamlContent = fs.readFileSync(files[0].path, 'utf-8'); + yamlContent = await fsPromises.readFile(files[0].path, 'utf-8'); /* Validation syntaxique YAML */ this.validateYamlSyntax(yamlContent, files[0].originalname); @@ -219,7 +218,7 @@ export class UploadsController { detectedType = this.detectTypeFromContent(yamlContent); } else { /* Cas multi-fichiers : détecter le fichier principal et bundler */ - const { mainFile, type } = this.detectMainFile(files); + const { mainFile, type } = await this.detectMainFile(files); detectedType = type; this.logger.log(`Multi-file upload: main=${mainFile.originalname}, type=${type}, total=${files.length} files`); @@ -310,9 +309,11 @@ export class UploadsController { return null; } - private detectMainFile(files: Express.Multer.File[]): { mainFile: Express.Multer.File; type: ApiType } { + private async detectMainFile( + files: Express.Multer.File[], + ): Promise<{ mainFile: Express.Multer.File; type: ApiType }> { for (const file of files) { - const content = fs.readFileSync(file.path, 'utf-8'); + const content = await fsPromises.readFile(file.path, 'utf-8'); const type = this.detectTypeFromContent(content); if (type) { return { mainFile: file, type };