Skip to content
Merged
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,7 @@ isBoolean(value);
| `@IsMultibyte()` | Checks if the string contains one or more multibyte chars. |
| `@IsNumberString(options?: IsNumericOptions)` | Checks if the string is numeric. |
| `@IsSurrogatePair()` | Checks if the string contains any surrogate pairs chars. |
| `@IsTaxId()` | Checks if the string is a valid tax ID. Default locale is `en-US`.
| `@IsUrl(options?: IsURLOptions)` | Checks if the string is a URL. |
| `@IsMagnetURI()` | Checks if the string is a [magnet uri format](https://en.wikipedia.org/wiki/Magnet_URI_scheme). |
| `@IsUUID(version?: "3"\|"4"\|"5"\|"all")` | Checks if the string is a UUID (version 3, 4, 5 or all ). |
Expand Down
1 change: 1 addition & 0 deletions src/decorator/decorators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export * from './string/IsSemVer';
export * from './string/IsStrongPassword';
export * from './string/IsTimeZone';
export * from './string/IsBase58';
export * from './string/is-tax-id';

// -------------------------------------------------------------------------
// Type checkers
Expand Down
42 changes: 42 additions & 0 deletions src/decorator/string/is-tax-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { ValidationOptions } from '../ValidationOptions';
import { buildMessage, ValidateBy } from '../common/ValidateBy';
import isTaxIDValidator from 'validator/lib/isTaxID';

export const IS_TAX_ID = 'isTaxId';

/**
* Checks if the string is a valid tax ID. Default locale is `en-US`.
* If given value is not a string, then it returns false.
*
* Supported locales: bg-BG, cs-CZ, de-AT, de-DE, dk-DK, el-CY, el-GR, en-CA,
* en-IE, en-US, es-ES, et-EE, fi-FI, fr-BE, fr-FR, fr-LU, hr-HR, hu-HU, it-IT,
* lv-LV, mt-MT, nl-NL, pl-PL, pt-BR, pt-PT, ro-RO, sk-SK, sl-SI, sv-SE.
*/
export function isTaxId(value: unknown, locale?: string): boolean {
return typeof value === 'string' && isTaxIDValidator(value, locale || 'en-US');
}

/**
* Checks if the string is a valid tax ID. Default locale is `en-US`.
* If given value is not a string, then it returns false.
*
* Supported locales: bg-BG, cs-CZ, de-AT, de-DE, dk-DK, el-CY, el-GR, en-CA,
* en-IE, en-US, es-ES, et-EE, fi-FI, fr-BE, fr-FR, fr-LU, hr-HR, hu-HU, it-IT,
* lv-LV, mt-MT, nl-NL, pl-PL, pt-BR, pt-PT, ro-RO, sk-SK, sl-SI, sv-SE.
*/
export function IsTaxId(locale?: string, validationOptions?: ValidationOptions): PropertyDecorator {
return ValidateBy(
{
name: IS_TAX_ID,
constraints: [locale],
validator: {
validate: (value, args): boolean => isTaxId(value, args?.constraints[0]),
defaultMessage: buildMessage(
eachPrefix => eachPrefix + '$property must be a Tax Identification Number',
validationOptions
),
},
},
validationOptions
);
}
35 changes: 35 additions & 0 deletions test/functional/validation-functions-and-decorators.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ import {
IsTimeZone,
IsBase58,
isBase58,
isTaxId,
IsTaxId,
} from '../../src/decorator/decorators';
import { Validator } from '../../src/validation/Validator';
import { ValidatorOptions } from '../../src/validation/ValidatorOptions';
Expand Down Expand Up @@ -2304,6 +2306,39 @@ describe('IsByteLength', () => {
});
});

describe('IsTaxId', () => {
const constraint = 'bg-BG';
const validValues = ['7501010010', '0101010012', '0111010010', '7521010014', '7541010019'];
const invalidValues = [null, undefined, '750101001', '75010100101', '75-01010/01 0', '7521320010', '7501010019'];

class MyClass {
@IsTaxId(constraint)
someProperty: string;
}

it('should not fail if validator.validate said that its valid', () => {
return checkValidValues(new MyClass(), validValues);
});

it('should fail if validator.validate said that its invalid', () => {
return checkInvalidValues(new MyClass(), invalidValues);
});

it('should not fail if method in validator said that its valid', () => {
validValues.forEach(value => expect(isTaxId(value, constraint)).toBeTruthy());
});

it('should fail if method in validator said that its invalid', () => {
invalidValues.forEach(value => expect(isTaxId(value, constraint)).toBeFalsy());
});

it('should return error object with proper data', () => {
const validationType = 'isTaxId';
const message = 'someProperty must be a Tax Identification Number';
checkReturnedError(new MyClass(), invalidValues, validationType, message);
});
});

describe('IsCreditCard', () => {
const validValues = [
'375556917985515',
Expand Down