mirror of
https://github.com/siop-spelev/siop2.git
synced 2026-08-08 12:41:54 +00:00
- FileStorage : putObject/getObjectStream/removeObject, bucket créé au démarrage — MinIO confiné à son implémentation (règle ESLint intacte) - documents : upload multipart (PDF/JPG/PNG, 20 Mo max, rattachement appareil OU OT requis, permission d'édition sur la CIBLE), liste filtrable, téléchargement STREAMÉ par l'API (MinIO jamais exposé), suppression ; e2e : octets téléchargés identiques aux octets envoyés - analytics : GET /analytics/summary dérivé du réel — coûts/mois (mouvements + main-d'œuvre figés), pannes par organe (bilans codés), taux de préventif, durée moyenne de résolution, top équipements - générateur OpenAPI : query params, multipart, réponse binaire (71 ops) - CI : service MinIO (bitnami) sur les jobs api et e2e - test de régression du tri « Interventions récentes » rendu déterministe (positions absolues instables sous 12 suites parallèles) ; 58 tests, 6 runs complets consécutifs verts Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
56 lines
1.8 KiB
TypeScript
56 lines
1.8 KiB
TypeScript
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
|
|
import * as Minio from 'minio';
|
|
import { loadEnv } from '../config/env';
|
|
import type { FileStorage } from './file-storage';
|
|
|
|
/** Seul fichier du dépôt autorisé à importer le SDK MinIO (règle ESLint). */
|
|
@Injectable()
|
|
export class MinioStorageService implements FileStorage, OnModuleInit {
|
|
private readonly logger = new Logger(MinioStorageService.name);
|
|
private readonly client: Minio.Client;
|
|
private readonly bucket: string;
|
|
|
|
constructor() {
|
|
const env = loadEnv();
|
|
this.bucket = env.MINIO_BUCKET;
|
|
this.client = new Minio.Client({
|
|
endPoint: env.MINIO_ENDPOINT,
|
|
port: env.MINIO_PORT,
|
|
useSSL: env.MINIO_USE_SSL === 'true',
|
|
accessKey: env.MINIO_ACCESS_KEY,
|
|
secretKey: env.MINIO_SECRET_KEY,
|
|
});
|
|
}
|
|
|
|
/** Le bucket est créé au démarrage — aucune étape manuelle au déploiement. */
|
|
async onModuleInit(): Promise<void> {
|
|
try {
|
|
if (!(await this.client.bucketExists(this.bucket))) {
|
|
await this.client.makeBucket(this.bucket);
|
|
this.logger.log(`Bucket « ${this.bucket} » créé.`);
|
|
}
|
|
} catch (e) {
|
|
// Le stockage peut être en retard au boot : /health le signalera.
|
|
this.logger.warn(`Stockage indisponible au démarrage : ${String(e)}`);
|
|
}
|
|
}
|
|
|
|
async healthCheck(): Promise<void> {
|
|
await this.client.listBuckets();
|
|
}
|
|
|
|
async putObject(key: string, body: Buffer, contentType: string): Promise<void> {
|
|
await this.client.putObject(this.bucket, key, body, body.length, {
|
|
'Content-Type': contentType,
|
|
});
|
|
}
|
|
|
|
async getObjectStream(key: string): Promise<NodeJS.ReadableStream> {
|
|
return this.client.getObject(this.bucket, key);
|
|
}
|
|
|
|
async removeObject(key: string): Promise<void> {
|
|
await this.client.removeObject(this.bucket, key);
|
|
}
|
|
}
|