Skip to content

Commit

Permalink
merge: release 0.13.1 (#872)
Browse files Browse the repository at this point in the history
  • Loading branch information
NoNameProvided committed Jan 14, 2021
2 parents e5edb82 + fb15fe1 commit 1fde8a9
Show file tree
Hide file tree
Showing 17 changed files with 1,646 additions and 2,262 deletions.
1 change: 1 addition & 0 deletions .eslintrc.yml
Expand Up @@ -32,3 +32,4 @@ rules:
'@typescript-eslint/no-unsafe-call': off
'@typescript-eslint/no-unsafe-member-access': off
'@typescript-eslint/explicit-module-boundary-types': off
'@typescript-eslint/restrict-template-expressions': off
18 changes: 18 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,21 @@
## [0.13.1](https://github.com/typestack/class-validator/compare/v0.13.0...v0.13.1) (2021-01-14)

### Added

- optional mather function has been added to the `ArrayUnique` decorator

### Fixed

- a typo was fixed in the error message generated by the `IsUUID` decorator
- calling `ValidationError.toString()` doesn't result in an error when `forbidNonWhitelisted` parameter was used
- fixed typo in error message generated by `IsIn` decorator
- the `@types/validator` package is correctly installed
- `inlineSources` option is enabled in tsconfig preventing various sourcemap errors when consuming the package

### Changed

- various dev dependencies has been updated

## [0.13.0](https://github.com/typestack/class-validator/compare/v0.12.2...v0.13.0) (2021-01-11)

### Added
Expand Down
222 changes: 112 additions & 110 deletions README.md

Large diffs are not rendered by default.

3,426 changes: 1,352 additions & 2,074 deletions package-lock.json

Large diffs are not rendered by default.

42 changes: 21 additions & 21 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "class-validator",
"version": "0.13.0",
"version": "0.13.1",
"description": "Decorator-based property validation for classes.",
"author": "TypeStack contributors",
"license": "MIT",
Expand Down Expand Up @@ -36,30 +36,30 @@
"test:ci": "jest --runInBand --no-cache --coverage --verbose"
},
"dependencies": {
"libphonenumber-js": "^1.7.57",
"validator": "^13.1.1"
"@types/validator": "^13.1.3",
"libphonenumber-js": "^1.9.7",
"validator": "^13.5.2"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^15.0.0",
"@rollup/plugin-node-resolve": "^9.0.0",
"@types/jest": "^26.0.14",
"@types/node": "^14.6.4",
"@types/validator": "^13.1.0",
"@typescript-eslint/eslint-plugin": "^3.10.1",
"@typescript-eslint/parser": "^3.10.1",
"eslint": "^7.8.1",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-jest": "^23.20.0",
"husky": "^4.3.0",
"jest": "^26.4.2",
"lint-staged": "^10.4.0",
"prettier": "^2.1.1",
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-node-resolve": "^11.0.1",
"@types/jest": "^26.0.20",
"@types/node": "^14.14.20",
"@typescript-eslint/eslint-plugin": "^4.13.0",
"@typescript-eslint/parser": "^4.13.0",
"eslint": "^7.17.0",
"eslint-config-prettier": "^7.1.0",
"eslint-plugin-jest": "^24.1.3",
"husky": "^4.3.7",
"jest": "^26.6.3",
"lint-staged": "^10.5.3",
"prettier": "^2.2.1",
"reflect-metadata": "0.1.13",
"rimraf": "3.0.2",
"rollup": "^2.26.11",
"rollup": "^2.36.1",
"rollup-plugin-terser": "^7.0.2",
"ts-jest": "^26.3.0",
"ts-node": "^9.0.0",
"typescript": "^4.0.2"
"ts-jest": "^26.4.4",
"ts-node": "^9.1.1",
"typescript": "^4.1.3"
}
}
4 changes: 2 additions & 2 deletions src/decorator/array/ArrayMaxSize.ts
Expand Up @@ -4,15 +4,15 @@ import { buildMessage, ValidateBy } from '../common/ValidateBy';
export const ARRAY_MAX_SIZE = 'arrayMaxSize';

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

/**
* Checks if array's length is as maximal this number.
* Checks if the array's length is less or equal to the specified number.
* If null or undefined is given then this function returns false.
*/
export function ArrayMaxSize(max: number, validationOptions?: ValidationOptions): PropertyDecorator {
Expand Down
4 changes: 2 additions & 2 deletions src/decorator/array/ArrayMinSize.ts
Expand Up @@ -4,15 +4,15 @@ import { buildMessage, ValidateBy } from '../common/ValidateBy';
export const ARRAY_MIN_SIZE = 'arrayMinSize';

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

/**
* Checks if array's length is as minimal this number.
* Checks if the array's length is greater than or equal to the specified number.
* If null or undefined is given then this function returns false.
*/
export function ArrayMinSize(min: number, validationOptions?: ValidationOptions): PropertyDecorator {
Expand Down
24 changes: 16 additions & 8 deletions src/decorator/array/ArrayUnique.ts
Expand Up @@ -2,14 +2,19 @@ import { ValidationOptions } from '../ValidationOptions';
import { buildMessage, ValidateBy } from '../common/ValidateBy';

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

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

if (identifier) {
array = array.map(o => (o != null ? identifier(o) : o));
}

const uniqueItems = array.filter((a, b, c) => c.indexOf(a) === b);
return array.length === uniqueItems.length;
}
Expand All @@ -18,18 +23,21 @@ export function arrayUnique(array: unknown): boolean {
* Checks if all array's values are unique. Comparison for objects is reference-based.
* If null or undefined is given then this function returns false.
*/
export function ArrayUnique(validationOptions?: ValidationOptions): PropertyDecorator {
export function ArrayUnique<T = any>(
identifierOrOptions?: ArrayUniqueIdentifier<T> | ValidationOptions,
validationOptions?: ValidationOptions
): PropertyDecorator {
const identifier = typeof identifierOrOptions === 'function' ? identifierOrOptions : undefined;
const options = typeof identifierOrOptions !== 'function' ? identifierOrOptions : validationOptions;

return ValidateBy(
{
name: ARRAY_UNIQUE,
validator: {
validate: (value, args): boolean => arrayUnique(value),
defaultMessage: buildMessage(
eachPrefix => eachPrefix + "All $property's elements must be unique",
validationOptions
),
validate: (value, args): boolean => arrayUnique(value, identifier),
defaultMessage: buildMessage(eachPrefix => eachPrefix + "All $property's elements must be unique", options),
},
},
validationOptions
options
);
}
23 changes: 12 additions & 11 deletions src/decorator/string/IsPhoneNumber.ts
Expand Up @@ -5,12 +5,14 @@ import { parsePhoneNumberFromString, CountryCode } from 'libphonenumber-js';
export const IS_PHONE_NUMBER = 'isPhoneNumber';

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

/**
* Checks if the string is a valid phone number.
* @param region 2 characters uppercase country code (e.g. DE, US, CH).
* If users must enter the intl. prefix (e.g. +41), then you may pass "ZZ" or null as region.
* Checks if the string is a valid phone number. To successfully validate any phone number the text must include
* the intl. calling code, if the calling code wont be provided then the region must be set.
*
* @param region 2 characters uppercase country code (e.g. DE, US, CH) for country specific validation.
* If text doesn't start with the international calling code (e.g. +41), then you must set this parameter.
*/
export function IsPhoneNumber(
region: CountryCode | undefined,
validationOptions?: ValidationOptions
): PropertyDecorator {
export function IsPhoneNumber(region?: CountryCode, validationOptions?: ValidationOptions): PropertyDecorator {
return ValidateBy(
{
name: IS_PHONE_NUMBER,
Expand Down
2 changes: 1 addition & 1 deletion src/decorator/string/IsUUID.ts
Expand Up @@ -25,7 +25,7 @@ export function IsUUID(version?: UUIDVersion, validationOptions?: ValidationOpti
constraints: [version],
validator: {
validate: (value, args): boolean => isUUID(value, args.constraints[0]),
defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be an UUID', validationOptions),
defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a UUID', validationOptions),
},
},
validationOptions
Expand Down
12 changes: 8 additions & 4 deletions src/validation/ValidationError.ts
Expand Up @@ -31,7 +31,7 @@ export class ValidationError {
/**
* Contains all nested validation errors of the property.
*/
children: ValidationError[];
children?: ValidationError[];

/*
* A transient set of data passed through to the validation result for response mapping
Expand Down Expand Up @@ -60,7 +60,9 @@ export class ValidationError {
this.target ? this.target.constructor.name : 'an object'
}${boldEnd} has failed the validation:\n` +
(this.constraints ? propConstraintFailed(this.property) : ``) +
this.children.map(childError => childError.toString(shouldDecorate, true, this.property)).join(``)
(this.children
? this.children.map(childError => childError.toString(shouldDecorate, true, this.property)).join(``)
: ``)
);
} else {
// we format numbers as array indexes for better readability.
Expand All @@ -72,8 +74,10 @@ export class ValidationError {
return propConstraintFailed(formattedProperty);
} else {
return this.children
.map(childError => childError.toString(shouldDecorate, true, `${parentPath}${formattedProperty}`))
.join(``);
? this.children
.map(childError => childError.toString(shouldDecorate, true, `${parentPath}${formattedProperty}`))
.join(``)
: ``;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/validation/ValidationExecutor.ts
Expand Up @@ -43,7 +43,7 @@ export class ValidationExecutor {
*
* TODO: This needs proper handling, forcing to use the same container or some other proper solution.
*/
if (!this.metadataStorage.hasValidationMetaData) {
if (!this.metadataStorage.hasValidationMetaData && this.validatorOptions?.enableDebugMessages === true) {
console.warn(
`No metadata found. There is more than once class-validator version installed probably. You need to flatten your dependencies.`
);
Expand Down
16 changes: 15 additions & 1 deletion src/validation/ValidationUtils.ts
@@ -1,5 +1,16 @@
import { ValidationArguments } from './ValidationArguments';

/**
* Convert the constraint to a string to be shown in an error
*/
export function constraintToString(constraint: unknown): string {
if (Array.isArray(constraint)) {
return constraint.join(', ');
}

return `${constraint}`;
}

export class ValidationUtils {
static replaceMessageSpecialTokens(
message: string | ((args: ValidationArguments) => string),
Expand All @@ -14,7 +25,10 @@ export class ValidationUtils {

if (messageString && validationArguments.constraints instanceof Array) {
validationArguments.constraints.forEach((constraint, index) => {
messageString = messageString.replace(new RegExp(`\\$constraint${index + 1}`, 'g'), constraint);
messageString = messageString.replace(
new RegExp(`\\$constraint${index + 1}`, 'g'),
constraintToString(constraint)
);
});
}

Expand Down
5 changes: 5 additions & 0 deletions src/validation/ValidatorOptions.ts
Expand Up @@ -2,6 +2,11 @@
* Options passed to validator during validation.
*/
export interface ValidatorOptions {
/**
* If set to true then class-validator will print extra warning messages to the console when something is not right.
*/
enableDebugMessages?: boolean;

/**
* If set to true then validator will skip validation of all properties that are undefined in the validating object.
*/
Expand Down

0 comments on commit 1fde8a9

Please sign in to comment.