Compare commits

...

85 Commits

Author SHA1 Message Date
Kamil Myśliwiec
e88b270cb5 chore(release): publish v10.4.22 release 2026-01-10 17:26:41 +01:00
Kamil Myśliwiec
58ebae0877 chore: revert lerna change 2026-01-10 16:49:21 +01:00
Kamil Myśliwiec
a2d4a75865 chore(release): publish v10.4.22 release 2026-01-10 16:48:01 +01:00
Kamil Myśliwiec
99a1f7f3d3 chore: revert lerna change 2026-01-10 16:47:16 +01:00
Kamil Myśliwiec
178df3d627 chore(release): publish v10.4.22 release 2026-01-10 16:46:46 +01:00
Kamil Myśliwiec
3f10aab750 chore: revert lerna change 2026-01-10 16:46:18 +01:00
Kamil Myśliwiec
44969b12ae chore(release): publish v10.4.22 release 2026-01-10 16:44:58 +01:00
Kamil Mysliwiec
d492171fd1 Merge pull request #16178 from Xilis/fix/body-parser-qs-cve
fix(express): Update body-parser to 1.20.4 for CVE-2025-15284
2026-01-10 16:43:18 +01:00
Sašo Vučič
b9ec98fee7 fix(express): Update body-parser to 1.20.4 for CVE-2025-15284 2026-01-09 20:23:55 +01:00
Kamil Myśliwiec
fd11464a6e chore(release): publish v10.4.21 release 2026-01-08 10:41:01 +01:00
Kamil Myśliwiec
cd2bd3e1b4 chore: upgrade lerna to the latest version 2026-01-08 10:40:26 +01:00
Kamil Myśliwiec
d96149c87b chore: upgrade lerna to the latest version 2026-01-08 10:39:07 +01:00
Kamil Myśliwiec
2e55ee1883 chore: upgrade lerna to the latest version 2026-01-08 10:37:58 +01:00
Kamil Myśliwiec
e7f9ade559 chore(@nestjs) publish v10.4.21 release 2026-01-08 10:36:23 +01:00
Kamil Myśliwiec
a74f89ac10 chore: revert lerna version 2026-01-08 10:36:01 +01:00
Kamil Myśliwiec
5a59810c9c chore(@nestjs) publish v10.4.21 release 2026-01-08 10:35:08 +01:00
Kamil Myśliwiec
3d4fa469c9 chore: add force publish flag 2026-01-08 10:34:45 +01:00
Kamil Myśliwiec
79cd7bc949 chore: add publish legacy 2026-01-08 10:22:59 +01:00
Kamil Mysliwiec
5ab165a60d Merge pull request #16157 from Xilis/fix/express-version-flexibility
fix(express): Update express to 4.22.1 to address CVE-2025-15284
2026-01-08 10:20:19 +01:00
Sašo Vučič
eb0f29d3b7 fix(express): update express to 4.22.1 to address CVE-2025-15284
Refs: CVE-2025-15284
2026-01-05 10:45:45 +01:00
Kamil Myśliwiec
f8021ab3e9 chore(@nestjs) publish v10.4.20 release 2025-07-23 09:43:14 +02:00
Kamil Myśliwiec
0402529e56 chore: bump multer 2025-07-23 09:40:16 +02:00
Kamil Myśliwiec
5ce44905c0 chore(@nestjs) publish v10.4.19 release 2025-06-09 08:55:38 +02:00
Kamil Myśliwiec
e3a69525ce chore: update lerna.json 2025-06-09 08:55:16 +02:00
Kamil Myśliwiec
82f9fed477 chore(@nestjs) publish v10.4.19 release 2025-06-09 08:54:00 +02:00
Kamil Myśliwiec
9e9c3c1c6e chore: update lerna.json 2025-06-09 08:52:21 +02:00
Kamil Myśliwiec
421a5802ff chore(@nestjs) publish v10.4.19 release 2025-06-09 08:50:29 +02:00
Kamil Myśliwiec
2e9f312e9d chore(common): bump multer to 2.0.1 2025-06-09 08:40:15 +02:00
Kamil Myśliwiec
9da1249256 chore(@nestjs) publish v10.4.18 release 2025-05-26 14:20:26 +02:00
Kamil Myśliwiec
ae40d669e5 chore: bump multer to v2 2025-05-26 14:18:08 +02:00
Kamil Myśliwiec
dc2a3c0d31 chore(@nestjs) publish v10.4.17 release 2025-04-15 18:10:25 +02:00
Kamil Myśliwiec
c4fb432637 chore(common): temporarily move file-type to regular deps 2025-04-15 18:09:55 +02:00
Kamil Myśliwiec
6c8aec63b4 chore(@nestjs) publish v10.4.16 release 2025-04-14 10:36:17 +02:00
Kamil Myśliwiec
bce9a49214 Merge branch 'Chathula-fix-nest-common-mime-validator' into 10.4.15 2025-04-14 10:35:17 +02:00
Kamil Myśliwiec
2b9e132f6a chore: update outdated tests, make file-type optional 2025-04-14 10:34:43 +02:00
Chathula
cb0d6506b3 chore: remove duplicate packages 2025-04-11 15:42:50 +02:00
Kamil Myśliwiec
6196ab2150 Merge branch 'Chathula-fix-nestjs-common-mime-validator' 2025-04-11 15:15:54 +02:00
Kamil Myśliwiec
0ac7959927 chore: minor tweaks 2025-04-11 15:15:27 +02:00
Chathula
983216b10e chore: update package lock 2025-04-11 15:07:40 +02:00
Kamil Mysliwiec
312a54ae2e Update packages/common/pipes/file/file-type.validator.ts 2025-04-11 15:02:01 +02:00
Chathula
a28fc033f4 refactor(common): move back file type validator options type 2025-04-11 15:02:01 +02:00
Chathula
07b4b3829e refactor(common): move file-type package to peer dependencies 2025-04-11 15:02:01 +02:00
Chathula
0b7af8ab07 refactor(common): refactor code to use simple eval 2025-04-11 15:02:00 +02:00
Chathula
6953b7a79e fix(common): used eval import 2025-04-11 15:01:57 +02:00
Chathula
1f20f52731 refactor(common): removed async keyword 2025-04-11 15:01:34 +02:00
Chathula
08840c57df fix: remove unused e2e test 2025-04-11 15:01:33 +02:00
Chathula
cddbcd1897 fix(common): update file mime package and add param skip magic numbers 2025-04-11 15:01:30 +02:00
Chathula
890fde4ef0 refactor: revert import change 2025-04-11 15:00:26 +02:00
Chathula
5ae8168617 fix: changed file-type import to promise 2025-04-11 15:00:26 +02:00
Chathula
38a77e2336 chore: update import paths 2025-04-11 15:00:25 +02:00
Chathula
d90cc8dcf2 chore: handles undefined 2025-04-11 15:00:25 +02:00
Chathula
2260e00bab chore: update validations 2025-04-11 15:00:25 +02:00
Chathula
cda46a219a chore: refactor validation code 2025-04-11 15:00:25 +02:00
Chathula
23308c7d4a fix: rename magic file type validator to file type validator 2025-04-11 15:00:20 +02:00
Chathula
f37603a708 chore: update file type import 2025-04-11 14:59:41 +02:00
Chathula
d57f934a3c chore: update exports in pipe 2025-04-11 14:59:41 +02:00
Chathula
059592944b fix: switch to magic file validator by default 2025-04-11 14:59:37 +02:00
Chathula
5feec1f861 fix: fixed sample typo 2025-04-11 14:59:21 +02:00
Chathula
ca1bd82bf9 chore: export magic file type validator 2025-04-11 14:59:16 +02:00
Chathula
7f37b492c9 revert sample file upload changes 2025-04-11 14:58:53 +02:00
Chathula
c6240a0840 chore: use load-esm to use file type package 2025-04-11 14:58:45 +02:00
Chathula
a203e07f48 chore: add file type package to package.json 2025-04-11 14:58:11 +02:00
Chathula
315fe55648 fix(common): introduce magic file type validator to nestjs common 2025-04-11 14:58:08 +02:00
Kamil Mysliwiec
14c6cd0e02 Update packages/common/pipes/file/file-type.validator.ts 2025-04-11 14:55:40 +02:00
Chathula
d51f9b6c9d refactor(common): move back file type validator options type 2025-04-11 14:55:36 +02:00
Chathula
18750bd800 refactor(common): move file-type package to peer dependencies 2025-04-11 14:55:17 +02:00
Chathula
f6f4baf53d refactor(common): refactor code to use simple eval 2025-04-11 14:55:17 +02:00
Chathula
010607f172 fix(common): used eval import 2025-04-11 14:55:03 +02:00
Chathula
69fd0e9ddf refactor(common): removed async keyword 2025-04-11 14:54:23 +02:00
Chathula
579d68a6ec refactor: revert import change 2025-04-11 14:50:22 +02:00
Chathula
dd19ac8f06 fix: changed file-type import to promise 2025-04-11 14:50:22 +02:00
Chathula
c571796093 chore: update import paths 2025-04-11 14:50:22 +02:00
Chathula
100d3c0dc8 chore: handles undefined 2025-04-11 14:50:21 +02:00
Chathula
db2fe5b5aa chore: update validations 2025-04-11 14:50:21 +02:00
Chathula
30e4acae29 chore: refactor validation code 2025-04-11 14:50:21 +02:00
Chathula
4a2c6e020e fix: rename magic file type validator to file type validator 2025-04-11 14:50:18 +02:00
Chathula
b03302cf26 chore: update file type import 2025-04-11 14:45:09 +02:00
Chathula
fdebabd003 chore: update exports in pipe 2025-04-11 14:45:09 +02:00
Chathula
e1229b124d fix: switch to magic file validator by default 2025-04-11 14:45:06 +02:00
Chathula
4d21f1e491 fix: fixed sample typo 2025-04-11 14:44:45 +02:00
Chathula
0ff055834c chore: export magic file type validator 2025-04-11 14:44:45 +02:00
Chathula
d7a6952f19 revert sample file upload changes 2025-04-11 14:44:45 +02:00
Chathula
ac04c340f3 chore: use load-esm to use file type package 2025-04-11 14:44:39 +02:00
Chathula
598ee4f265 chore: add file type package to package.json 2025-04-11 14:40:54 +02:00
Chathula
3dc367bbb1 fix(common): introduce magic file type validator to nestjs common 2025-04-11 14:40:07 +02:00
20 changed files with 35908 additions and 17252 deletions

View File

@@ -1,7 +1,5 @@
{
"lerna": "2.4.0",
"packages": [
"packages/*"
],
"version": "10.4.15"
"packages": ["packages/*"],
"version": "10.4.22",
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
}

52761
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -41,12 +41,13 @@
"lint:packages": "eslint 'packages/**/**.ts' --ignore-pattern 'packages/**/*.spec.ts'",
"lint:spec": "eslint 'packages/**/**.spec.ts'",
"prerelease": "gulp copy-misc",
"publish": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --force-publish --access public --exact -m \"chore(@nestjs) publish %s release\"",
"publish": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --force-publish --exact -m \"chore(release): publish %s release\"",
"prepublishOnly": "npm run changelog | pbcopy",
"publish:beta": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --npm-tag=beta --access public -m \"chore(@nestjs) publish %s release\"",
"publish:next": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --npm-tag=next --access public --skip-git -m \"chore(@nestjs) publish %s release\"",
"publish:rc": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --npm-tag=rc --access public -m \"chore(@nestjs) publish %s release\"",
"publish:test": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --force-publish --access public --npm-tag=test --skip-git -m \"chore(@nestjs) publish %s release\"",
"publish:legacy": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --npm-tag=legacy --force-publish -m \"chore(release): publish %s release\"",
"publish:beta": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --npm-tag=beta -m \"chore(release): publish %s release\"",
"publish:next": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --npm-tag=next --skip-git -m \"chore(release): publish %s release\"",
"publish:rc": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --npm-tag=rc -m \"chore(release): publish %s release\"",
"publish:test": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --force-publish --npm-tag=test --skip-git -m \"chore(release): publish %s release\"",
"prepare": "husky"
},
"lint-staged": {
@@ -63,9 +64,10 @@
"class-transformer": "0.5.1",
"class-validator": "0.14.1",
"cors": "2.8.5",
"express": "4.21.2",
"express": "4.22.1",
"fast-json-stringify": "6.0.0",
"fast-safe-stringify": "2.1.1",
"file-type": "20.4.1",
"iterare": "1.2.1",
"object-hash": "3.0.0",
"path-to-regexp": "3.3.0",
@@ -74,7 +76,7 @@
"socket.io": "4.8.1",
"tslib": "2.8.1",
"uid": "2.0.2",
"uuid": "11.0.3"
"uuid": "11.1.0"
},
"devDependencies": {
"@apollo/server": "4.11.2",
@@ -111,7 +113,7 @@
"amqp-connection-manager": "4.1.14",
"amqplib": "0.10.5",
"artillery": "2.0.21",
"body-parser": "1.20.3",
"body-parser": "1.20.4",
"bytes": "3.1.2",
"cache-manager": "5.7.6",
"cache-manager-redis-store": "3.0.1",
@@ -131,8 +133,8 @@
"fancy-log": "2.0.0",
"fastify": "4.28.1",
"graphql": "16.9.0",
"graphql-tools": "9.0.5",
"graphql-subscriptions": "2.0.0",
"graphql-tools": "9.0.5",
"gulp": "5.0.0",
"gulp-clang-format": "1.0.27",
"gulp-clean": "0.4.0",
@@ -145,7 +147,7 @@
"ioredis": "5.4.1",
"json-loader": "0.5.7",
"kafkajs": "2.2.4",
"lerna": "2.11.0",
"lerna": "9.0.3",
"lerna-changelog": "2.2.0",
"light-my-request": "6.3.0",
"lint-staged": "15.2.10",

View File

@@ -1,6 +1,6 @@
{
"name": "@nestjs/common",
"version": "10.4.15",
"version": "10.4.22",
"description": "Nest - modern, fast, powerful node.js web framework (@common)",
"author": "Kamil Mysliwiec",
"homepage": "https://nestjs.com",
@@ -18,6 +18,7 @@
},
"license": "MIT",
"dependencies": {
"file-type": "20.4.1",
"iterare": "1.2.1",
"tslib": "2.8.1",
"uid": "2.0.2"
@@ -35,5 +36,6 @@
"class-transformer": {
"optional": true
}
}
},
"gitHead": "a2d4a7586573f5965935525be5ce757fc502b154"
}

View File

@@ -3,14 +3,19 @@ import { IFile } from './interfaces';
export type FileTypeValidatorOptions = {
fileType: string | RegExp;
/**
* If `true`, the validator will skip the magic numbers validation.
* This can be useful when you can't identify some files as there are no common magic numbers available for some file types.
* @default false
*/
skipMagicNumbersValidation?: boolean;
};
/**
* Defines the built-in FileType File Validator. It validates incoming files mime-type
* matching a string or a regular expression. Note that this validator uses a naive strategy
* to check the mime-type and could be fooled if the client provided a file with renamed extension.
* (for instance, renaming a 'malicious.bat' to 'malicious.jpeg'). To handle such security issues
* with more reliability, consider checking against the file's [magic-numbers](https://en.wikipedia.org/wiki/Magic_number_%28programming%29)
* 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
* than just checking the mimetype string.
*
* @see [File Validators](https://docs.nestjs.com/techniques/file-upload#validators)
*
@@ -20,19 +25,42 @@ export class FileTypeValidator extends FileValidator<
FileTypeValidatorOptions,
IFile
> {
buildErrorMessage(): string {
buildErrorMessage(file?: IFile): string {
if (file?.mimetype) {
return `Validation failed (current file type is ${file.mimetype}, expected type is ${this.validationOptions.fileType})`;
}
return `Validation failed (expected type is ${this.validationOptions.fileType})`;
}
isValid(file?: IFile): boolean {
async isValid(file?: IFile): Promise<boolean> {
if (!this.validationOptions) {
return true;
}
return (
!!file &&
'mimetype' in file &&
!!file.mimetype.match(this.validationOptions.fileType)
);
const isFileValid = !!file && 'mimetype' in file;
if (this.validationOptions.skipMagicNumbersValidation) {
return (
isFileValid && !!file.mimetype.match(this.validationOptions.fileType)
);
}
if (!isFileValid || !file.buffer) {
return false;
}
try {
const { fileTypeFromBuffer } = (await eval(
'import ("file-type")',
)) as typeof import('file-type');
const fileType = await fileTypeFromBuffer(file.buffer);
return (
!!fileType && !!fileType.mime.match(this.validationOptions.fileType)
);
} catch {
return false;
}
}
}

View File

@@ -1,4 +1,5 @@
export interface IFile {
mimetype: string;
size: number;
buffer?: Buffer;
}

View File

@@ -1,89 +1,195 @@
import { expect } from 'chai';
import { IFile } from '../../../../common/pipes/file/interfaces';
import { FileTypeValidator } from '../../../pipes';
describe('FileTypeValidator', () => {
describe('isValid', () => {
it('should return true when the file mimetype is the same as the specified', () => {
it('should return true when the file buffer matches the specified type', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: 'image/jpeg',
});
const jpegBuffer = Buffer.from([
0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46,
]);
const requestFile = {
mimetype: 'image/jpeg',
} as any;
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 mimetype ends with the specified option type', () => {
it('should return true when the file buffer matches the specified file extension', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: 'jpeg',
});
const jpegBuffer = Buffer.from([
0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46,
]);
const requestFile = {
mimetype: 'image/jpeg',
} as any;
expect(fileTypeValidator.isValid(requestFile)).to.equal(true);
buffer: jpegBuffer,
} as IFile;
expect(await fileTypeValidator.isValid(requestFile)).to.equal(true);
});
it('should return true when the file mimetype matches the specified regexp', () => {
it('should return true when the file buffer matches the specified regexp', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: /word/,
fileType: /^image\//,
});
const jpegBuffer = Buffer.from([
0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46,
]);
const requestFile = {
mimetype: 'application/msword',
} as any;
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 false when the file mimetype is different from the specified', () => {
it('should return false when the file buffer does not match the specified type', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: 'image/jpeg',
});
const pngBuffer = Buffer.from([
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
]);
const requestFile = {
mimetype: 'image/jpeg', // Spoofed mimetype
buffer: pngBuffer,
} as IFile;
expect(await fileTypeValidator.isValid(requestFile)).to.equal(false);
});
it('should return false when the file buffer does not match the specified file extension', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: 'jpeg',
});
const pngBuffer = Buffer.from([
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
]);
const requestFile = {
mimetype: 'image/png',
} as any;
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 mimetype does not match the provided regexp', () => {
it('should return false when no buffer is provided', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: /mp4/,
fileType: 'image/jpeg',
});
const requestFile = {
mimetype: 'image/png',
} as any;
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 the file mimetype was not provided', () => {
it('should return false when no file is provided', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: 'image/jpeg',
});
const requestFile = {} as any;
expect(fileTypeValidator.isValid(requestFile)).to.equal(false);
expect(await fileTypeValidator.isValid()).to.equal(false);
});
it('should return false when no file provided', () => {
it('should return false when no buffer is provided', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: 'image/jpeg',
});
expect(fileTypeValidator.isValid()).to.equal(false);
const requestFile = {
mimetype: 'image/jpeg',
} as IFile;
expect(await fileTypeValidator.isValid(requestFile)).to.equal(false);
});
it('should return true when the file buffer matches the specified regexp', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: /^image\//,
});
const jpegBuffer = Buffer.from([
0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46,
]);
const requestFile = {
mimetype: 'image/jpeg',
buffer: jpegBuffer,
} as IFile;
expect(await fileTypeValidator.isValid(requestFile)).to.equal(true);
});
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,
]);
const requestFile = {
mimetype: 'image/jpeg',
buffer: jpegBuffer,
} as IFile;
expect(await fileTypeValidator.isValid(requestFile)).to.equal(true);
});
it('should skip magic numbers validation when the skipMagicNumbersValidation is true', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: 'image/jpeg',
skipMagicNumbersValidation: true,
});
const requestFile = {
mimetype: 'image/jpeg',
} as IFile;
expect(await fileTypeValidator.isValid(requestFile)).to.equal(true);
});
it('should return false when the file buffer does not match any known type', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: 'unknown/type',
});
const unknownBuffer = Buffer.from([
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
]);
const requestFile = {
mimetype: 'unknown/type',
buffer: unknownBuffer,
} as IFile;
expect(await fileTypeValidator.isValid(requestFile)).to.equal(false);
});
it('should return false when the buffer is empty', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: 'image/jpeg',
});
const emptyBuffer = Buffer.from([]);
const requestFile = {
mimetype: 'image/jpeg',
buffer: emptyBuffer,
} as IFile;
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,
@@ -93,5 +199,85 @@ describe('FileTypeValidator', () => {
`Validation failed (expected type is ${fileType})`,
);
});
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({
fileType,
});
const file = { mimetype: currentFileType } as IFile;
expect(fileTypeValidator.buildErrorMessage(file)).to.equal(
`Validation failed (current file type is ${currentFileType}, expected type is ${fileType})`,
);
});
it('should handle regexp file type in error message', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: /^image\//,
});
const file = { mimetype: 'application/pdf' } as IFile;
expect(fileTypeValidator.buildErrorMessage(file)).to.equal(
`Validation failed (current file type is application/pdf, expected type is /^image\\//)`,
);
});
it('should handle file extension in error message', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: 'jpeg',
});
const file = { mimetype: 'image/png' } as IFile;
expect(fileTypeValidator.buildErrorMessage(file)).to.equal(
'Validation failed (current file type is image/png, expected type is jpeg)',
);
});
it('should handle regexp file type in error message', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: /^image\//,
});
const file = { mimetype: 'application/pdf' } as IFile;
expect(fileTypeValidator.buildErrorMessage(file)).to.equal(
`Validation failed (current file type is application/pdf, expected type is /^image\\//)`,
);
});
it('should handle file extension in error message', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: 'jpeg',
});
const file = { mimetype: 'image/png' } as IFile;
expect(fileTypeValidator.buildErrorMessage(file)).to.equal(
'Validation failed (current file type is image/png, expected type is jpeg)',
);
});
it('should handle regexp file type in error message', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: /^image\//,
});
const file = { mimetype: 'application/pdf' } as IFile;
expect(fileTypeValidator.buildErrorMessage(file)).to.equal(
`Validation failed (current file type is application/pdf, expected type is /^image\\//)`,
);
});
it('should handle file extension in error message', async () => {
const fileTypeValidator = new FileTypeValidator({
fileType: 'jpeg',
});
const file = { mimetype: 'image/png' } as IFile;
expect(fileTypeValidator.buildErrorMessage(file)).to.equal(
'Validation failed (current file type is image/png, expected type is jpeg)',
);
});
});
});

View File

@@ -1,9 +1,9 @@
import { expect } from 'chai';
import {
FileTypeValidator,
FileValidator,
MaxFileSizeValidator,
ParseFilePipeBuilder,
FileTypeValidator,
} from '../../../pipes';
describe('ParseFilePipeBuilder', () => {

View File

@@ -1,6 +1,6 @@
{
"name": "@nestjs/core",
"version": "10.4.15",
"version": "10.4.22",
"description": "Nest - modern, fast, powerful node.js web framework (@core)",
"author": "Kamil Mysliwiec",
"license": "MIT",
@@ -36,7 +36,7 @@
"uid": "2.0.2"
},
"devDependencies": {
"@nestjs/common": "10.4.15"
"@nestjs/common": "^10.4.22"
},
"peerDependencies": {
"@nestjs/common": "^10.0.0",
@@ -56,5 +56,6 @@
"@nestjs/platform-express": {
"optional": true
}
}
},
"gitHead": "a2d4a7586573f5965935525be5ce757fc502b154"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@nestjs/microservices",
"version": "10.4.15",
"version": "10.4.22",
"description": "Nest - modern, fast, powerful node.js web framework (@microservices)",
"author": "Kamil Mysliwiec",
"license": "MIT",
@@ -22,8 +22,8 @@
"tslib": "2.8.1"
},
"devDependencies": {
"@nestjs/common": "10.4.15",
"@nestjs/core": "10.4.15"
"@nestjs/common": "^10.4.22",
"@nestjs/core": "^10.4.22"
},
"peerDependencies": {
"@grpc/grpc-js": "*",
@@ -68,5 +68,6 @@
"amqp-connection-manager": {
"optional": true
}
}
},
"gitHead": "a2d4a7586573f5965935525be5ce757fc502b154"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@nestjs/platform-express",
"version": "10.4.15",
"version": "10.4.22",
"description": "Nest - modern, fast, powerful node.js web framework (@platform-express)",
"author": "Kamil Mysliwiec",
"license": "MIT",
@@ -18,18 +18,19 @@
"access": "public"
},
"dependencies": {
"body-parser": "1.20.3",
"body-parser": "1.20.4",
"cors": "2.8.5",
"express": "4.21.2",
"multer": "1.4.4-lts.1",
"express": "4.22.1",
"multer": "2.0.2",
"tslib": "2.8.1"
},
"devDependencies": {
"@nestjs/common": "10.4.15",
"@nestjs/core": "10.4.15"
"@nestjs/common": "^10.4.22",
"@nestjs/core": "^10.4.22"
},
"peerDependencies": {
"@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0"
}
},
"gitHead": "a2d4a7586573f5965935525be5ce757fc502b154"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@nestjs/platform-fastify",
"version": "10.4.15",
"version": "10.4.22",
"description": "Nest - modern, fast, powerful node.js web framework (@platform-fastify)",
"author": "Kamil Mysliwiec",
"license": "MIT",
@@ -39,5 +39,6 @@
"@fastify/view": {
"optional": true
}
}
},
"gitHead": "a2d4a7586573f5965935525be5ce757fc502b154"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@nestjs/platform-socket.io",
"version": "10.4.15",
"version": "10.4.22",
"description": "Nest - modern, fast, powerful node.js web framework (@platform-socket.io)",
"author": "Kamil Mysliwiec",
"license": "MIT",
@@ -25,5 +25,6 @@
"@nestjs/common": "^10.0.0",
"@nestjs/websockets": "^10.0.0",
"rxjs": "^7.1.0"
}
},
"gitHead": "a2d4a7586573f5965935525be5ce757fc502b154"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@nestjs/platform-ws",
"version": "10.4.15",
"version": "10.4.22",
"description": "Nest - modern, fast, powerful node.js web framework (@platform-ws)",
"author": "Kamil Mysliwiec",
"license": "MIT",
@@ -25,5 +25,6 @@
"@nestjs/common": "^10.0.0",
"@nestjs/websockets": "^10.0.0",
"rxjs": "^7.1.0"
}
},
"gitHead": "a2d4a7586573f5965935525be5ce757fc502b154"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@nestjs/testing",
"version": "10.4.15",
"version": "10.4.22",
"description": "Nest - modern, fast, powerful node.js web framework (@testing)",
"author": "Kamil Mysliwiec",
"license": "MIT",
@@ -33,5 +33,6 @@
"@nestjs/platform-express": {
"optional": true
}
}
},
"gitHead": "a2d4a7586573f5965935525be5ce757fc502b154"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@nestjs/websockets",
"version": "10.4.15",
"version": "10.4.22",
"description": "Nest - modern, fast, powerful node.js web framework (@websockets)",
"author": "Kamil Mysliwiec",
"license": "MIT",
@@ -18,8 +18,8 @@
"tslib": "2.8.1"
},
"devDependencies": {
"@nestjs/common": "10.4.15",
"@nestjs/core": "10.4.15"
"@nestjs/common": "^10.4.22",
"@nestjs/core": "^10.4.22"
},
"peerDependencies": {
"@nestjs/common": "^10.0.0",
@@ -32,5 +32,6 @@
"@nestjs/platform-socket.io": {
"optional": true
}
}
},
"gitHead": "a2d4a7586573f5965935525be5ce757fc502b154"
}

View File

@@ -32,14 +32,14 @@ describe('E2E FileTest', () => {
it('should allow for file uploads that pass validation', async () => {
return request(app.getHttpServer())
.post('/file/pass-validation')
.attach('file', './package.json')
.attach('file', './resources/nestjs.jpg')
.field('name', 'test')
.expect(201)
.expect({
body: {
name: 'test',
},
file: readFileSync('./package.json').toString(),
file: readFileSync('./resources/nestjs.jpg').toString(),
});
});

View File

@@ -16,7 +16,7 @@
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./e2e/jest-e2e.json"
"test:e2e": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest --config ./e2e/jest-e2e.json"
},
"dependencies": {
"@nestjs/common": "10.4.13",

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

View File

@@ -40,7 +40,7 @@ export class AppController {
@UploadedFile(
new ParseFilePipeBuilder()
.addFileTypeValidator({
fileType: 'json',
fileType: 'jpeg',
})
.build({
fileIsRequired: false,