Skip to content

Commit 1fde8a9

Browse files
merge: release 0.13.1 (#872)
2 parents e5edb82 + fb15fe1 commit 1fde8a9

17 files changed

+1646
-2262
lines changed

.eslintrc.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ rules:
3232
'@typescript-eslint/no-unsafe-call': off
3333
'@typescript-eslint/no-unsafe-member-access': off
3434
'@typescript-eslint/explicit-module-boundary-types': off
35+
'@typescript-eslint/restrict-template-expressions': off

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
## [0.13.1](https://github.com/typestack/class-validator/compare/v0.13.0...v0.13.1) (2021-01-14)
2+
3+
### Added
4+
5+
- optional mather function has been added to the `ArrayUnique` decorator
6+
7+
### Fixed
8+
9+
- a typo was fixed in the error message generated by the `IsUUID` decorator
10+
- calling `ValidationError.toString()` doesn't result in an error when `forbidNonWhitelisted` parameter was used
11+
- fixed typo in error message generated by `IsIn` decorator
12+
- the `@types/validator` package is correctly installed
13+
- `inlineSources` option is enabled in tsconfig preventing various sourcemap errors when consuming the package
14+
15+
### Changed
16+
17+
- various dev dependencies has been updated
18+
119
## [0.13.0](https://github.com/typestack/class-validator/compare/v0.12.2...v0.13.0) (2021-01-11)
220

321
### Added

README.md

Lines changed: 112 additions & 110 deletions
Large diffs are not rendered by default.

package-lock.json

Lines changed: 1352 additions & 2074 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "class-validator",
3-
"version": "0.13.0",
3+
"version": "0.13.1",
44
"description": "Decorator-based property validation for classes.",
55
"author": "TypeStack contributors",
66
"license": "MIT",
@@ -36,30 +36,30 @@
3636
"test:ci": "jest --runInBand --no-cache --coverage --verbose"
3737
},
3838
"dependencies": {
39-
"libphonenumber-js": "^1.7.57",
40-
"validator": "^13.1.1"
39+
"@types/validator": "^13.1.3",
40+
"libphonenumber-js": "^1.9.7",
41+
"validator": "^13.5.2"
4142
},
4243
"devDependencies": {
43-
"@rollup/plugin-commonjs": "^15.0.0",
44-
"@rollup/plugin-node-resolve": "^9.0.0",
45-
"@types/jest": "^26.0.14",
46-
"@types/node": "^14.6.4",
47-
"@types/validator": "^13.1.0",
48-
"@typescript-eslint/eslint-plugin": "^3.10.1",
49-
"@typescript-eslint/parser": "^3.10.1",
50-
"eslint": "^7.8.1",
51-
"eslint-config-prettier": "^6.11.0",
52-
"eslint-plugin-jest": "^23.20.0",
53-
"husky": "^4.3.0",
54-
"jest": "^26.4.2",
55-
"lint-staged": "^10.4.0",
56-
"prettier": "^2.1.1",
44+
"@rollup/plugin-commonjs": "^17.0.0",
45+
"@rollup/plugin-node-resolve": "^11.0.1",
46+
"@types/jest": "^26.0.20",
47+
"@types/node": "^14.14.20",
48+
"@typescript-eslint/eslint-plugin": "^4.13.0",
49+
"@typescript-eslint/parser": "^4.13.0",
50+
"eslint": "^7.17.0",
51+
"eslint-config-prettier": "^7.1.0",
52+
"eslint-plugin-jest": "^24.1.3",
53+
"husky": "^4.3.7",
54+
"jest": "^26.6.3",
55+
"lint-staged": "^10.5.3",
56+
"prettier": "^2.2.1",
5757
"reflect-metadata": "0.1.13",
5858
"rimraf": "3.0.2",
59-
"rollup": "^2.26.11",
59+
"rollup": "^2.36.1",
6060
"rollup-plugin-terser": "^7.0.2",
61-
"ts-jest": "^26.3.0",
62-
"ts-node": "^9.0.0",
63-
"typescript": "^4.0.2"
61+
"ts-jest": "^26.4.4",
62+
"ts-node": "^9.1.1",
63+
"typescript": "^4.1.3"
6464
}
6565
}

src/decorator/array/ArrayMaxSize.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ import { buildMessage, ValidateBy } from '../common/ValidateBy';
44
export const ARRAY_MAX_SIZE = 'arrayMaxSize';
55

66
/**
7-
* Checks if array's length is as maximal this number.
7+
* Checks if the array's length is less or equal to the specified number.
88
* If null or undefined is given then this function returns false.
99
*/
1010
export function arrayMaxSize(array: unknown, max: number): boolean {
1111
return array instanceof Array && array.length <= max;
1212
}
1313

1414
/**
15-
* Checks if array's length is as maximal this number.
15+
* Checks if the array's length is less or equal to the specified number.
1616
* If null or undefined is given then this function returns false.
1717
*/
1818
export function ArrayMaxSize(max: number, validationOptions?: ValidationOptions): PropertyDecorator {

src/decorator/array/ArrayMinSize.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ import { buildMessage, ValidateBy } from '../common/ValidateBy';
44
export const ARRAY_MIN_SIZE = 'arrayMinSize';
55

66
/**
7-
* Checks if array's length is as minimal this number.
7+
* Checks if the array's length is greater than or equal to the specified number.
88
* If null or undefined is given then this function returns false.
99
*/
1010
export function arrayMinSize(array: unknown, min: number): boolean {
1111
return array instanceof Array && array.length >= min;
1212
}
1313

1414
/**
15-
* Checks if array's length is as minimal this number.
15+
* Checks if the array's length is greater than or equal to the specified number.
1616
* If null or undefined is given then this function returns false.
1717
*/
1818
export function ArrayMinSize(min: number, validationOptions?: ValidationOptions): PropertyDecorator {

src/decorator/array/ArrayUnique.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@ import { ValidationOptions } from '../ValidationOptions';
22
import { buildMessage, ValidateBy } from '../common/ValidateBy';
33

44
export const ARRAY_UNIQUE = 'arrayUnique';
5+
export type ArrayUniqueIdentifier<T = any> = (o: T) => any;
56

67
/**
78
* Checks if all array's values are unique. Comparison for objects is reference-based.
89
* If null or undefined is given then this function returns false.
910
*/
10-
export function arrayUnique(array: unknown): boolean {
11+
export function arrayUnique(array: unknown[], identifier?: ArrayUniqueIdentifier): boolean {
1112
if (!(array instanceof Array)) return false;
1213

14+
if (identifier) {
15+
array = array.map(o => (o != null ? identifier(o) : o));
16+
}
17+
1318
const uniqueItems = array.filter((a, b, c) => c.indexOf(a) === b);
1419
return array.length === uniqueItems.length;
1520
}
@@ -18,18 +23,21 @@ export function arrayUnique(array: unknown): boolean {
1823
* Checks if all array's values are unique. Comparison for objects is reference-based.
1924
* If null or undefined is given then this function returns false.
2025
*/
21-
export function ArrayUnique(validationOptions?: ValidationOptions): PropertyDecorator {
26+
export function ArrayUnique<T = any>(
27+
identifierOrOptions?: ArrayUniqueIdentifier<T> | ValidationOptions,
28+
validationOptions?: ValidationOptions
29+
): PropertyDecorator {
30+
const identifier = typeof identifierOrOptions === 'function' ? identifierOrOptions : undefined;
31+
const options = typeof identifierOrOptions !== 'function' ? identifierOrOptions : validationOptions;
32+
2233
return ValidateBy(
2334
{
2435
name: ARRAY_UNIQUE,
2536
validator: {
26-
validate: (value, args): boolean => arrayUnique(value),
27-
defaultMessage: buildMessage(
28-
eachPrefix => eachPrefix + "All $property's elements must be unique",
29-
validationOptions
30-
),
37+
validate: (value, args): boolean => arrayUnique(value, identifier),
38+
defaultMessage: buildMessage(eachPrefix => eachPrefix + "All $property's elements must be unique", options),
3139
},
3240
},
33-
validationOptions
41+
options
3442
);
3543
}

src/decorator/string/IsPhoneNumber.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import { parsePhoneNumberFromString, CountryCode } from 'libphonenumber-js';
55
export const IS_PHONE_NUMBER = 'isPhoneNumber';
66

77
/**
8-
* Checks if the string is a valid phone number.
8+
* Checks if the string is a valid phone number. To successfully validate any phone number the text must include
9+
* the intl. calling code, if the calling code wont be provided then the region must be set.
10+
*
911
* @param value the potential phone number string to test
10-
* @param {string} region 2 characters uppercase country code (e.g. DE, US, CH).
11-
* If users must enter the intl. prefix (e.g. +41), then you may pass "ZZ" or null as region.
12+
* @param region 2 characters uppercase country code (e.g. DE, US, CH) for country specific validation.
13+
* If text doesn't start with the international calling code (e.g. +41), then you must set this parameter.
1214
*/
13-
export function isPhoneNumber(value: string, region: CountryCode | undefined): boolean {
15+
export function isPhoneNumber(value: string, region?: CountryCode): boolean {
1416
try {
1517
const phoneNum = parsePhoneNumberFromString(value, region);
1618
const result = phoneNum?.isValid();
@@ -22,14 +24,13 @@ export function isPhoneNumber(value: string, region: CountryCode | undefined): b
2224
}
2325

2426
/**
25-
* Checks if the string is a valid phone number.
26-
* @param region 2 characters uppercase country code (e.g. DE, US, CH).
27-
* If users must enter the intl. prefix (e.g. +41), then you may pass "ZZ" or null as region.
27+
* Checks if the string is a valid phone number. To successfully validate any phone number the text must include
28+
* the intl. calling code, if the calling code wont be provided then the region must be set.
29+
*
30+
* @param region 2 characters uppercase country code (e.g. DE, US, CH) for country specific validation.
31+
* If text doesn't start with the international calling code (e.g. +41), then you must set this parameter.
2832
*/
29-
export function IsPhoneNumber(
30-
region: CountryCode | undefined,
31-
validationOptions?: ValidationOptions
32-
): PropertyDecorator {
33+
export function IsPhoneNumber(region?: CountryCode, validationOptions?: ValidationOptions): PropertyDecorator {
3334
return ValidateBy(
3435
{
3536
name: IS_PHONE_NUMBER,

src/decorator/string/IsUUID.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export function IsUUID(version?: UUIDVersion, validationOptions?: ValidationOpti
2525
constraints: [version],
2626
validator: {
2727
validate: (value, args): boolean => isUUID(value, args.constraints[0]),
28-
defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be an UUID', validationOptions),
28+
defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a UUID', validationOptions),
2929
},
3030
},
3131
validationOptions

src/validation/ValidationError.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export class ValidationError {
3131
/**
3232
* Contains all nested validation errors of the property.
3333
*/
34-
children: ValidationError[];
34+
children?: ValidationError[];
3535

3636
/*
3737
* A transient set of data passed through to the validation result for response mapping
@@ -60,7 +60,9 @@ export class ValidationError {
6060
this.target ? this.target.constructor.name : 'an object'
6161
}${boldEnd} has failed the validation:\n` +
6262
(this.constraints ? propConstraintFailed(this.property) : ``) +
63-
this.children.map(childError => childError.toString(shouldDecorate, true, this.property)).join(``)
63+
(this.children
64+
? this.children.map(childError => childError.toString(shouldDecorate, true, this.property)).join(``)
65+
: ``)
6466
);
6567
} else {
6668
// we format numbers as array indexes for better readability.
@@ -72,8 +74,10 @@ export class ValidationError {
7274
return propConstraintFailed(formattedProperty);
7375
} else {
7476
return this.children
75-
.map(childError => childError.toString(shouldDecorate, true, `${parentPath}${formattedProperty}`))
76-
.join(``);
77+
? this.children
78+
.map(childError => childError.toString(shouldDecorate, true, `${parentPath}${formattedProperty}`))
79+
.join(``)
80+
: ``;
7781
}
7882
}
7983
}

src/validation/ValidationExecutor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export class ValidationExecutor {
4343
*
4444
* TODO: This needs proper handling, forcing to use the same container or some other proper solution.
4545
*/
46-
if (!this.metadataStorage.hasValidationMetaData) {
46+
if (!this.metadataStorage.hasValidationMetaData && this.validatorOptions?.enableDebugMessages === true) {
4747
console.warn(
4848
`No metadata found. There is more than once class-validator version installed probably. You need to flatten your dependencies.`
4949
);

src/validation/ValidationUtils.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
import { ValidationArguments } from './ValidationArguments';
22

3+
/**
4+
* Convert the constraint to a string to be shown in an error
5+
*/
6+
export function constraintToString(constraint: unknown): string {
7+
if (Array.isArray(constraint)) {
8+
return constraint.join(', ');
9+
}
10+
11+
return `${constraint}`;
12+
}
13+
314
export class ValidationUtils {
415
static replaceMessageSpecialTokens(
516
message: string | ((args: ValidationArguments) => string),
@@ -14,7 +25,10 @@ export class ValidationUtils {
1425

1526
if (messageString && validationArguments.constraints instanceof Array) {
1627
validationArguments.constraints.forEach((constraint, index) => {
17-
messageString = messageString.replace(new RegExp(`\\$constraint${index + 1}`, 'g'), constraint);
28+
messageString = messageString.replace(
29+
new RegExp(`\\$constraint${index + 1}`, 'g'),
30+
constraintToString(constraint)
31+
);
1832
});
1933
}
2034

src/validation/ValidatorOptions.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
* Options passed to validator during validation.
33
*/
44
export interface ValidatorOptions {
5+
/**
6+
* If set to true then class-validator will print extra warning messages to the console when something is not right.
7+
*/
8+
enableDebugMessages?: boolean;
9+
510
/**
611
* If set to true then validator will skip validation of all properties that are undefined in the validating object.
712
*/

0 commit comments

Comments
 (0)