Repository: nestjs/nest
Pull request #10515 (2022-11-03 14:58:44)

feat(common): Allow adding custom validators to ParseFilePipeBuilder
## PR Checklist
Please check if your PR fulfills the following requirements:

- [x] The commit message follows our guidelines: https://github.com/nestjs/nest/blob/master/CONTRIBUTING.md
- [x] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)


## PR Type
What kind of change does this PR introduce?

<!-- Please check the one that applies to this PR using "x". -->
- [ ] Bugfix
- [x] Feature
- [ ] Code style update (formatting, local variables)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] CI related changes
- [ ] Other... Please describe:

## What is the current behavior?
Currently it is not possible to add custom file validators using the `ParseFilePipeBuilder`.

## What is the new behavior?
This PR adds an `addValidator(validator: FileValidator)` function, which can be used to add additional validators.

## Does this PR introduce a breaking change?
- [ ] Yes
- [x] No

## Other information

My use-case for this feature is adding a [file-type](https://github.com/sindresorhus/file-type) based mime validator. This change would also allow extending the `ParseFilePipeBuilder` class with custom builder functions.


Patch:
diff --git a/packages/common/pipes/file/parse-file-pipe.builder.ts b/packages/common/pipes/file/parse-file-pipe.builder.ts
index 7835322d9..fafbe78fe 100644
--- a/packages/common/pipes/file/parse-file-pipe.builder.ts
+++ b/packages/common/pipes/file/parse-file-pipe.builder.ts
@@ -14,12 +14,15 @@ export class ParseFilePipeBuilder {
   private validators: FileValidator[] = [];
 
   addMaxSizeValidator(options: MaxFileSizeValidatorOptions) {
-    this.validators.push(new MaxFileSizeValidator(options));
-    return this;
+    return this.addValidator(new MaxFileSizeValidator(options));
   }
 
   addFileTypeValidator(options: FileTypeValidatorOptions) {
-    this.validators.push(new FileTypeValidator(options));
+    return this.addValidator(new FileTypeValidator(options));
+  }
+
+  addValidator(validator: FileValidator) {
+    this.validators.push(validator);
     return this;
   }
 


Test patch:
diff --git a/packages/common/test/pipes/file/parse-file-pipe.builder.spec.ts b/packages/common/test/pipes/file/parse-file-pipe.builder.spec.ts
index 8c31904aa..43f1b29a1 100644
--- a/packages/common/test/pipes/file/parse-file-pipe.builder.spec.ts
+++ b/packages/common/test/pipes/file/parse-file-pipe.builder.spec.ts
@@ -1,6 +1,8 @@
 import { expect } from 'chai';
 import {
   FileTypeValidator,
+  FileTypeValidatorOptions,
+  FileValidator,
   MaxFileSizeValidator,
   ParseFilePipeBuilder,
 } from '../../../pipes';
@@ -50,6 +52,32 @@ describe('ParseFilePipeBuilder', () => {
       });
     });
 
+    describe('when custom validator was chained', () => {
+      it('should return a ParseFilePipe with TestFileValidator and given options', () => {
+        class TestFileValidator extends FileValidator<{ name: string }> {
+          buildErrorMessage(file: any): string {
+            return 'TestFileValidator failed';
+          }
+
+          isValid(file: any): boolean | Promise<boolean> {
+            return true;
+          }
+        }
+
+        const options = {
+          name: 'test',
+        };
+
+        const parseFilePipe = parseFilePipeBuilder
+          .addValidator(new TestFileValidator(options))
+          .build();
+
+        expect(parseFilePipe.getValidators()).to.deep.include(
+          new TestFileValidator(options),
+        );
+      });
+    });
+
     describe('when it is called twice with different validators', () => {
       it('should not reuse validators', () => {
         const maxSizeValidatorOptions = {