1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const tslib_1 = require("tslib");
|
4 | const decorators_1 = require("../decorators");
|
5 | const core_1 = require("../decorators/core");
|
6 | const index_1 = require("../index");
|
7 | const load_package_util_1 = require("../utils/load-package.util");
|
8 | const shared_utils_1 = require("../utils/shared.utils");
|
9 | let classValidator = {};
|
10 | let classTransformer = {};
|
11 | let ValidationPipe = class ValidationPipe {
|
12 | constructor(options) {
|
13 | options = options || {};
|
14 | const { transform, disableErrorMessages, transformOptions, validateCustomDecorators } = options, validatorOptions = tslib_1.__rest(options, ["transform", "disableErrorMessages", "transformOptions", "validateCustomDecorators"]);
|
15 | this.isTransformEnabled = !!transform;
|
16 | this.validatorOptions = validatorOptions;
|
17 | this.transformOptions = transformOptions;
|
18 | this.isDetailedOutputDisabled = disableErrorMessages;
|
19 | this.validateCustomDecorators = validateCustomDecorators || false;
|
20 | this.exceptionFactory =
|
21 | options.exceptionFactory ||
|
22 | (errors => new index_1.BadRequestException(this.isDetailedOutputDisabled ? undefined : errors));
|
23 | classValidator = load_package_util_1.loadPackage('class-validator', 'ValidationPipe', () => require('class-validator'));
|
24 | classTransformer = load_package_util_1.loadPackage('class-transformer', 'ValidationPipe', () => require('class-transformer'));
|
25 | }
|
26 | async transform(value, metadata) {
|
27 | const { metatype } = metadata;
|
28 | if (!metatype || !this.toValidate(metadata)) {
|
29 | return value;
|
30 | }
|
31 | value = this.toEmptyIfNil(value);
|
32 | const isPrimitive = this.isPrimitive(value);
|
33 | this.stripProtoKeys(value);
|
34 | let entity = classTransformer.plainToClass(metatype, value, this.transformOptions);
|
35 | const originalEntity = entity;
|
36 | const isCtorNotEqual = entity.constructor !== metatype;
|
37 | if (isCtorNotEqual && !isPrimitive) {
|
38 | entity.constructor = metatype;
|
39 | }
|
40 | else if (isCtorNotEqual) {
|
41 |
|
42 |
|
43 |
|
44 | entity = { constructor: metatype };
|
45 | }
|
46 | const errors = await classValidator.validate(entity, this.validatorOptions);
|
47 | if (errors.length > 0) {
|
48 | throw this.exceptionFactory(errors);
|
49 | }
|
50 | if (isPrimitive) {
|
51 |
|
52 |
|
53 | entity = originalEntity;
|
54 | }
|
55 | return this.isTransformEnabled
|
56 | ? entity
|
57 | : Object.keys(this.validatorOptions).length > 0
|
58 | ? classTransformer.classToPlain(entity, this.transformOptions)
|
59 | : value;
|
60 | }
|
61 | toValidate(metadata) {
|
62 | const { metatype, type } = metadata;
|
63 | if (type === 'custom' && !this.validateCustomDecorators) {
|
64 | return false;
|
65 | }
|
66 | const types = [String, Boolean, Number, Array, Object];
|
67 | return !types.some(t => metatype === t) && !shared_utils_1.isNil(metatype);
|
68 | }
|
69 | toEmptyIfNil(value) {
|
70 | return shared_utils_1.isNil(value) ? {} : value;
|
71 | }
|
72 | stripProtoKeys(value) {
|
73 | delete value.__proto__;
|
74 | const keys = Object.keys(value);
|
75 | keys
|
76 | .filter(key => typeof value[key] === 'object' && value[key])
|
77 | .forEach(key => this.stripProtoKeys(value[key]));
|
78 | }
|
79 | isPrimitive(value) {
|
80 | return ['number', 'boolean', 'string'].includes(typeof value);
|
81 | }
|
82 | };
|
83 | ValidationPipe = tslib_1.__decorate([
|
84 | core_1.Injectable(),
|
85 | tslib_1.__param(0, decorators_1.Optional()),
|
86 | tslib_1.__metadata("design:paramtypes", [Object])
|
87 | ], ValidationPipe);
|
88 | exports.ValidationPipe = ValidationPipe;
|