Picsur/backend/src/decorators/multipart/postfile.pipe.ts

48 lines
1.5 KiB
TypeScript

import { Multipart, MultipartFields, MultipartFile } from '@fastify/multipart';
import { Injectable, Logger, PipeTransform, Scope } from '@nestjs/common';
import { FastifyRequest } from 'fastify';
import { Fail, FT } from 'picsur-shared/dist/types';
import { MultipartConfigService } from '../../config/early/multipart.config.service';
@Injectable({ scope: Scope.REQUEST })
export class PostFilePipe implements PipeTransform {
private readonly logger = new Logger(PostFilePipe.name);
constructor(
private readonly multipartConfigService: MultipartConfigService,
) {}
async transform({ req }: { req: FastifyRequest }) {
if (!req.isMultipart()) throw Fail(FT.UsrValidation, 'Invalid file');
// Only one file is allowed
const file = await req.file({
limits: {
...this.multipartConfigService.getLimits(),
files: 1,
},
});
if (file === undefined) throw Fail(FT.UsrValidation, 'Invalid file');
// Remove empty fields
const allFields: Multipart[] = Object.values(file.fields).filter(
(entry) => entry,
) as any;
// Remove non-file fields
const files: MultipartFile[] = allFields.filter(
(entry) => (entry as any).file !== undefined,
) as MultipartFile[];
if (files.length !== 1) throw Fail(FT.UsrValidation, 'Invalid file');
// Return a buffer of the file
try {
return await files[0]?.toBuffer();
} catch (e) {
this.logger.warn(e);
throw Fail(FT.Internal, 'Invalid file');
}
}
}