Skip to content

Commit b564f8d

Browse files
feat: add @IsTaxID decorator (#1822)
Co-authored-by: Klaudiusz <[email protected]>
1 parent dbab07a commit b564f8d

File tree

4 files changed

+79
-0
lines changed

4 files changed

+79
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,7 @@ isBoolean(value);
883883
| `@IsMultibyte()` | Checks if the string contains one or more multibyte chars. |
884884
| `@IsNumberString(options?: IsNumericOptions)` | Checks if the string is numeric. |
885885
| `@IsSurrogatePair()` | Checks if the string contains any surrogate pairs chars. |
886+
| `@IsTaxId()` | Checks if the string is a valid tax ID. Default locale is `en-US`.
886887
| `@IsUrl(options?: IsURLOptions)` | Checks if the string is a URL. |
887888
| `@IsMagnetURI()` | Checks if the string is a [magnet uri format](https://en.wikipedia.org/wiki/Magnet_URI_scheme). |
888889
| `@IsUUID(version?: "3"\|"4"\|"5"\|"all")` | Checks if the string is a UUID (version 3, 4, 5 or all ). |

src/decorator/decorators.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ export * from './string/IsSemVer';
114114
export * from './string/IsStrongPassword';
115115
export * from './string/IsTimeZone';
116116
export * from './string/IsBase58';
117+
export * from './string/is-tax-id';
117118

118119
// -------------------------------------------------------------------------
119120
// Type checkers

src/decorator/string/is-tax-id.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { ValidationOptions } from '../ValidationOptions';
2+
import { buildMessage, ValidateBy } from '../common/ValidateBy';
3+
import isTaxIDValidator from 'validator/lib/isTaxID';
4+
5+
export const IS_TAX_ID = 'isTaxId';
6+
7+
/**
8+
* Checks if the string is a valid tax ID. Default locale is `en-US`.
9+
* If given value is not a string, then it returns false.
10+
*
11+
* Supported locales: bg-BG, cs-CZ, de-AT, de-DE, dk-DK, el-CY, el-GR, en-CA,
12+
* en-IE, en-US, es-ES, et-EE, fi-FI, fr-BE, fr-FR, fr-LU, hr-HR, hu-HU, it-IT,
13+
* lv-LV, mt-MT, nl-NL, pl-PL, pt-BR, pt-PT, ro-RO, sk-SK, sl-SI, sv-SE.
14+
*/
15+
export function isTaxId(value: unknown, locale?: string): boolean {
16+
return typeof value === 'string' && isTaxIDValidator(value, locale || 'en-US');
17+
}
18+
19+
/**
20+
* Checks if the string is a valid tax ID. Default locale is `en-US`.
21+
* If given value is not a string, then it returns false.
22+
*
23+
* Supported locales: bg-BG, cs-CZ, de-AT, de-DE, dk-DK, el-CY, el-GR, en-CA,
24+
* en-IE, en-US, es-ES, et-EE, fi-FI, fr-BE, fr-FR, fr-LU, hr-HR, hu-HU, it-IT,
25+
* lv-LV, mt-MT, nl-NL, pl-PL, pt-BR, pt-PT, ro-RO, sk-SK, sl-SI, sv-SE.
26+
*/
27+
export function IsTaxId(locale?: string, validationOptions?: ValidationOptions): PropertyDecorator {
28+
return ValidateBy(
29+
{
30+
name: IS_TAX_ID,
31+
constraints: [locale],
32+
validator: {
33+
validate: (value, args): boolean => isTaxId(value, args?.constraints[0]),
34+
defaultMessage: buildMessage(
35+
eachPrefix => eachPrefix + '$property must be a Tax Identification Number',
36+
validationOptions
37+
),
38+
},
39+
},
40+
validationOptions
41+
);
42+
}

test/functional/validation-functions-and-decorators.spec.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ import {
190190
IsTimeZone,
191191
IsBase58,
192192
isBase58,
193+
isTaxId,
194+
IsTaxId,
193195
} from '../../src/decorator/decorators';
194196
import { Validator } from '../../src/validation/Validator';
195197
import { ValidatorOptions } from '../../src/validation/ValidatorOptions';
@@ -2304,6 +2306,39 @@ describe('IsByteLength', () => {
23042306
});
23052307
});
23062308

2309+
describe('IsTaxId', () => {
2310+
const constraint = 'bg-BG';
2311+
const validValues = ['7501010010', '0101010012', '0111010010', '7521010014', '7541010019'];
2312+
const invalidValues = [null, undefined, '750101001', '75010100101', '75-01010/01 0', '7521320010', '7501010019'];
2313+
2314+
class MyClass {
2315+
@IsTaxId(constraint)
2316+
someProperty: string;
2317+
}
2318+
2319+
it('should not fail if validator.validate said that its valid', () => {
2320+
return checkValidValues(new MyClass(), validValues);
2321+
});
2322+
2323+
it('should fail if validator.validate said that its invalid', () => {
2324+
return checkInvalidValues(new MyClass(), invalidValues);
2325+
});
2326+
2327+
it('should not fail if method in validator said that its valid', () => {
2328+
validValues.forEach(value => expect(isTaxId(value, constraint)).toBeTruthy());
2329+
});
2330+
2331+
it('should fail if method in validator said that its invalid', () => {
2332+
invalidValues.forEach(value => expect(isTaxId(value, constraint)).toBeFalsy());
2333+
});
2334+
2335+
it('should return error object with proper data', () => {
2336+
const validationType = 'isTaxId';
2337+
const message = 'someProperty must be a Tax Identification Number';
2338+
checkReturnedError(new MyClass(), invalidValues, validationType, message);
2339+
});
2340+
});
2341+
23072342
describe('IsCreditCard', () => {
23082343
const validValues = [
23092344
'375556917985515',

0 commit comments

Comments
 (0)