From 6953b7a79e3e326eac01875806ee3f984fe702da Mon Sep 17 00:00:00 2001 From: Chathula Date: Wed, 9 Apr 2025 16:23:21 +0200 Subject: [PATCH] fix(common): used eval import --- package.json | 2 +- packages/common/package.json | 2 +- .../common/pipes/file/file-type.validator.ts | 17 ++++-- .../pipes/file/file-type.validator.spec.ts | 60 +++++++++---------- 4 files changed, 45 insertions(+), 36 deletions(-) diff --git a/package.json b/package.json index f070bf8b0..d33da79d7 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "express": "4.21.2", "fast-json-stringify": "6.0.0", "fast-safe-stringify": "2.1.1", - "file-type-checker": "1.1.4", + "file-type": "20.4.1", "iterare": "1.2.1", "object-hash": "3.0.0", "path-to-regexp": "3.3.0", diff --git a/packages/common/package.json b/packages/common/package.json index 846e45e3c..dc9ffa752 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -18,7 +18,7 @@ }, "license": "MIT", "dependencies": { - "file-type-checker": "1.1.4", + "file-type": "20.4.1", "iterare": "1.2.1", "tslib": "2.8.1", "uid": "2.0.2" diff --git a/packages/common/pipes/file/file-type.validator.ts b/packages/common/pipes/file/file-type.validator.ts index 0c608e3e6..761ce42a9 100644 --- a/packages/common/pipes/file/file-type.validator.ts +++ b/packages/common/pipes/file/file-type.validator.ts @@ -1,7 +1,14 @@ -import * as fileTypeChecker from 'file-type-checker'; import { FileValidator } from './file-validator.interface'; import { FileTypeValidatorOptions, IFile } from './interfaces'; +const importEsmPackage = async ( + packageName: string, +): Promise => + // eslint-disable-next-line @typescript-eslint/no-implied-eval + new Function(`return import('${packageName}')`)().then( + (loadedModule: any) => loadedModule['default'] ?? loadedModule, + ); + /** * Defines the built-in FileTypeValidator. It validates incoming files by examining * their magic numbers using the file-type package, providing more reliable file type validation @@ -22,7 +29,7 @@ export class FileTypeValidator extends FileValidator< return `Validation failed (expected type is ${this.validationOptions.fileType})`; } - isValid(file?: IFile): boolean { + async isValid(file?: IFile): Promise { if (!this.validationOptions) { return true; } @@ -40,10 +47,12 @@ export class FileTypeValidator extends FileValidator< } try { - const fileType = fileTypeChecker.detectFile(file.buffer); + const { fileTypeFromBuffer } = await importEsmPackage('file-type'); + + const fileType = await fileTypeFromBuffer(file.buffer); return ( - !!fileType && !!fileType.mimeType.match(this.validationOptions.fileType) + !!fileType && !!fileType.mime.match(this.validationOptions.fileType) ); } catch { return false; diff --git a/packages/common/test/pipes/file/file-type.validator.spec.ts b/packages/common/test/pipes/file/file-type.validator.spec.ts index b86933514..43e0831ad 100644 --- a/packages/common/test/pipes/file/file-type.validator.spec.ts +++ b/packages/common/test/pipes/file/file-type.validator.spec.ts @@ -4,7 +4,7 @@ import { FileTypeValidator } from '../../../pipes'; describe('FileTypeValidator', () => { describe('isValid', () => { - it('should return true when the file buffer matches the specified type', () => { + it('should return true when the file buffer matches the specified type', async () => { const fileTypeValidator = new FileTypeValidator({ fileType: 'image/jpeg', }); @@ -17,10 +17,10 @@ describe('FileTypeValidator', () => { buffer: jpegBuffer, } as IFile; - expect(fileTypeValidator.isValid(requestFile)).to.equal(true); + expect(await fileTypeValidator.isValid(requestFile)).to.equal(true); }); - it('should return true when the file buffer matches the specified file extension', () => { + it('should return true when the file buffer matches the specified file extension', async () => { const fileTypeValidator = new FileTypeValidator({ fileType: 'jpeg', }); @@ -32,10 +32,10 @@ describe('FileTypeValidator', () => { mimetype: 'image/jpeg', buffer: jpegBuffer, } as IFile; - expect(fileTypeValidator.isValid(requestFile)).to.equal(true); + expect(await fileTypeValidator.isValid(requestFile)).to.equal(true); }); - it('should return true when the file buffer matches the specified regexp', () => { + it('should return true when the file buffer matches the specified regexp', async () => { const fileTypeValidator = new FileTypeValidator({ fileType: /^image\//, }); @@ -48,10 +48,10 @@ describe('FileTypeValidator', () => { buffer: jpegBuffer, } as IFile; - expect(fileTypeValidator.isValid(requestFile)).to.equal(true); + expect(await fileTypeValidator.isValid(requestFile)).to.equal(true); }); - it('should return false when the file buffer does not match the specified type', () => { + it('should return false when the file buffer does not match the specified type', async () => { const fileTypeValidator = new FileTypeValidator({ fileType: 'image/jpeg', }); @@ -64,10 +64,10 @@ describe('FileTypeValidator', () => { buffer: pngBuffer, } as IFile; - expect(fileTypeValidator.isValid(requestFile)).to.equal(false); + expect(await fileTypeValidator.isValid(requestFile)).to.equal(false); }); - it('should return false when the file buffer does not match the specified file extension', () => { + it('should return false when the file buffer does not match the specified file extension', async () => { const fileTypeValidator = new FileTypeValidator({ fileType: 'jpeg', }); @@ -80,10 +80,10 @@ describe('FileTypeValidator', () => { buffer: pngBuffer, } as IFile; - expect(fileTypeValidator.isValid(requestFile)).to.equal(false); + expect(await fileTypeValidator.isValid(requestFile)).to.equal(false); }); - it('should return false when no buffer is provided', () => { + it('should return false when no buffer is provided', async () => { const fileTypeValidator = new FileTypeValidator({ fileType: 'image/jpeg', }); @@ -92,18 +92,18 @@ describe('FileTypeValidator', () => { mimetype: 'image/jpeg', } as IFile; - expect(fileTypeValidator.isValid(requestFile)).to.equal(false); + expect(await fileTypeValidator.isValid(requestFile)).to.equal(false); }); - it('should return false when no file is provided', () => { + it('should return false when no file is provided', async () => { const fileTypeValidator = new FileTypeValidator({ fileType: 'image/jpeg', }); - expect(fileTypeValidator.isValid()).to.equal(false); + expect(await fileTypeValidator.isValid()).to.equal(false); }); - it('should return false when no buffer is provided', () => { + it('should return false when no buffer is provided', async () => { const fileTypeValidator = new FileTypeValidator({ fileType: 'image/jpeg', }); @@ -112,10 +112,10 @@ describe('FileTypeValidator', () => { mimetype: 'image/jpeg', } as IFile; - expect(fileTypeValidator.isValid(requestFile)).to.equal(false); + expect(await fileTypeValidator.isValid(requestFile)).to.equal(false); }); - it('should return true when the file buffer matches the specified regexp', () => { + it('should return true when the file buffer matches the specified regexp', async () => { const fileTypeValidator = new FileTypeValidator({ fileType: /^image\//, }); @@ -128,10 +128,10 @@ describe('FileTypeValidator', () => { buffer: jpegBuffer, } as IFile; - expect(fileTypeValidator.isValid(requestFile)).to.equal(true); + expect(await fileTypeValidator.isValid(requestFile)).to.equal(true); }); - it('should return true when no validation options are provided', () => { + it('should return true when no validation options are provided', async () => { const fileTypeValidator = new FileTypeValidator({} as any); const jpegBuffer = Buffer.from([ 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, @@ -141,10 +141,10 @@ describe('FileTypeValidator', () => { buffer: jpegBuffer, } as IFile; - expect(fileTypeValidator.isValid(requestFile)).to.equal(true); + expect(await fileTypeValidator.isValid(requestFile)).to.equal(true); }); - it('should skip magic numbers validation when the skipMagicNumbersValidation is true', () => { + it('should skip magic numbers validation when the skipMagicNumbersValidation is true', async () => { const fileTypeValidator = new FileTypeValidator({ fileType: 'image/jpeg', skipMagicNumbersValidation: true, @@ -154,10 +154,10 @@ describe('FileTypeValidator', () => { mimetype: 'image/jpeg', } as IFile; - expect(fileTypeValidator.isValid(requestFile)).to.equal(true); + expect(await fileTypeValidator.isValid(requestFile)).to.equal(true); }); - it('should return false when the file buffer does not match any known type', () => { + it('should return false when the file buffer does not match any known type', async () => { const fileTypeValidator = new FileTypeValidator({ fileType: 'unknown/type', }); @@ -170,10 +170,10 @@ describe('FileTypeValidator', () => { buffer: unknownBuffer, } as IFile; - expect(fileTypeValidator.isValid(requestFile)).to.equal(false); + expect(await fileTypeValidator.isValid(requestFile)).to.equal(false); }); - it('should return false when the buffer is empty', () => { + it('should return false when the buffer is empty', async () => { const fileTypeValidator = new FileTypeValidator({ fileType: 'image/jpeg', }); @@ -184,12 +184,12 @@ describe('FileTypeValidator', () => { buffer: emptyBuffer, } as IFile; - expect(fileTypeValidator.isValid(requestFile)).to.equal(false); + expect(await fileTypeValidator.isValid(requestFile)).to.equal(false); }); }); describe('buildErrorMessage', () => { - it('should return a string with the format "Validation failed (expected type is #fileType)"', () => { + it('should return a string with the format "Validation failed (expected type is #fileType)"', async () => { const fileType = 'image/jpeg'; const fileTypeValidator = new FileTypeValidator({ fileType, @@ -200,7 +200,7 @@ describe('FileTypeValidator', () => { ); }); - it('should include the file type in the error message when a file is provided', () => { + it('should include the file type in the error message when a file is provided', async () => { const currentFileType = 'image/png'; const fileType = 'image/jpeg'; const fileTypeValidator = new FileTypeValidator({ @@ -214,7 +214,7 @@ describe('FileTypeValidator', () => { ); }); - it('should handle regexp file type in error message', () => { + it('should handle regexp file type in error message', async () => { const fileTypeValidator = new FileTypeValidator({ fileType: /^image\//, }); @@ -225,7 +225,7 @@ describe('FileTypeValidator', () => { ); }); - it('should handle file extension in error message', () => { + it('should handle file extension in error message', async () => { const fileTypeValidator = new FileTypeValidator({ fileType: 'jpeg', });