From efaa6ad4685945473bb70c14da38273cb6b471d7 Mon Sep 17 00:00:00 2001 From: Jin Woo Won Date: Thu, 27 Jun 2024 14:46:05 -0400 Subject: [PATCH 1/2] Add IsVatId decorator --- README.md | 1 + src/decorator/decorators.ts | 1 + src/decorator/string/IsVatId.ts | 36 +++++++++++++++++++ ...alidation-functions-and-decorators.spec.ts | 32 +++++++++++++++++ 4 files changed, 70 insertions(+) create mode 100644 src/decorator/string/IsVatId.ts diff --git a/README.md b/README.md index 886712dd76..c851e7804b 100644 --- a/README.md +++ b/README.md @@ -884,6 +884,7 @@ isBoolean(value); | `@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. | +| `@IsVatId(countryCode: string)` | Checks if the string is a [valid VAT identification number for the country](https://taxation-customs.ec.europa.eu/vat-identification-numbers_en). | `@IsMagnetURI()` | Checks if the string is a [magnet uri format](https://en.wikipedia.org/wiki/Magnet_URI_scheme). | | `@IsUUID(version?: UUIDVersion)` | Checks if the string is a UUID (version 3, 4, 5 or all ). | | `@IsFirebasePushId()` | Checks if the string is a [Firebase Push ID](https://firebase.googleblog.com/2015/02/the-2120-ways-to-ensure-unique_68.html) | diff --git a/src/decorator/decorators.ts b/src/decorator/decorators.ts index d449e9301a..4f57599e84 100644 --- a/src/decorator/decorators.ts +++ b/src/decorator/decorators.ts @@ -116,6 +116,7 @@ export * from './string/IsTimeZone'; export * from './string/IsBase58'; export * from './string/is-tax-id'; export * from './string/is-iso4217-currency-code'; +export * from './string/IsVatId'; // ------------------------------------------------------------------------- // Type checkers diff --git a/src/decorator/string/IsVatId.ts b/src/decorator/string/IsVatId.ts new file mode 100644 index 0000000000..72429f22b1 --- /dev/null +++ b/src/decorator/string/IsVatId.ts @@ -0,0 +1,36 @@ +import { ValidationOptions } from '../ValidationOptions'; +import { buildMessage, ValidateBy } from '../common/ValidateBy'; +import isVatIdValidator from 'validator/lib/isVat'; + +export const IS_VAT_ID = 'isVat'; + +/** + * Checks if the string is a VAT (value-added tax) identification number. + * If given value is not a string, then it returns false. + */ +export function isVatId(value: unknown, countryCode: string): boolean { + try { + const isVatId = typeof value === 'string' && isVatIdValidator(value, countryCode); + return isVatId; + } catch (error) { + return false; + } +} + +/** + * Checks if the string is a VAT (value-added tax) identification number. + * If given value is not a string, then it returns false. + */ +export function IsVatId(countryCode?: string, validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_VAT_ID, + constraints: [countryCode], + validator: { + validate: (value, args): boolean => isVatId(value, args?.constraints[0]), + defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a VAT ID', validationOptions), + }, + }, + validationOptions + ); +} diff --git a/test/functional/validation-functions-and-decorators.spec.ts b/test/functional/validation-functions-and-decorators.spec.ts index 78ceddcd6d..6eb3733593 100644 --- a/test/functional/validation-functions-and-decorators.spec.ts +++ b/test/functional/validation-functions-and-decorators.spec.ts @@ -193,6 +193,7 @@ import { isTaxId, IsTaxId, IsISO4217CurrencyCode, + IsVatId, } from '../../src/decorator/decorators'; import { Validator } from '../../src/validation/Validator'; import { ValidatorOptions } from '../../src/validation/ValidatorOptions'; @@ -4779,3 +4780,34 @@ describe('IsISO4217', () => { return checkInvalidValues(new MyClass(), invalidValues); }); }); + +describe('IsVatId', () => { + class MyClass { + @IsVatId('AT') + someProperty: string; + } + + class MyInvalidClass { + @IsVatId('ZZ') + someProperty: string; + } + + const validAtVatIds = ['U12345678', 'U01234567']; + const invalidAtVatIds = ['12345678','000', 'abcdefgh']; + + it('should not fail for a valid VAT id for valid country code', () => { + return checkValidValues(new MyClass(), validAtVatIds); + }); + + it('should fail for invalid country code', () => { + return checkInvalidValues(new MyInvalidClass(), validAtVatIds); + }); + + it('should fail for invalid VAT id for valid country code', () => { + return checkInvalidValues(new MyClass(), invalidAtVatIds); + }); + + it('should fail for invalid VAT id for invalid country code', () => { + return checkInvalidValues(new MyInvalidClass(), invalidAtVatIds); + }); +}); From 9ce27dadcb01e87f12b2c5df9ea63be13f136830 Mon Sep 17 00:00:00 2001 From: Jin Woo Won Date: Thu, 27 Jun 2024 14:54:42 -0400 Subject: [PATCH 2/2] Run prettier and lint --- README.md | 2 +- test/functional/validation-functions-and-decorators.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c851e7804b..5d8cced029 100644 --- a/README.md +++ b/README.md @@ -884,7 +884,7 @@ isBoolean(value); | `@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. | -| `@IsVatId(countryCode: string)` | Checks if the string is a [valid VAT identification number for the country](https://taxation-customs.ec.europa.eu/vat-identification-numbers_en). +| `@IsVatId(countryCode: string)` | Checks if the string is a [valid VAT identification number for the country](https://taxation-customs.ec.europa.eu/vat-identification-numbers_en). | | `@IsMagnetURI()` | Checks if the string is a [magnet uri format](https://en.wikipedia.org/wiki/Magnet_URI_scheme). | | `@IsUUID(version?: UUIDVersion)` | Checks if the string is a UUID (version 3, 4, 5 or all ). | | `@IsFirebasePushId()` | Checks if the string is a [Firebase Push ID](https://firebase.googleblog.com/2015/02/the-2120-ways-to-ensure-unique_68.html) | diff --git a/test/functional/validation-functions-and-decorators.spec.ts b/test/functional/validation-functions-and-decorators.spec.ts index 6eb3733593..dee6d451e5 100644 --- a/test/functional/validation-functions-and-decorators.spec.ts +++ b/test/functional/validation-functions-and-decorators.spec.ts @@ -4793,7 +4793,7 @@ describe('IsVatId', () => { } const validAtVatIds = ['U12345678', 'U01234567']; - const invalidAtVatIds = ['12345678','000', 'abcdefgh']; + const invalidAtVatIds = ['12345678', '000', 'abcdefgh']; it('should not fail for a valid VAT id for valid country code', () => { return checkValidValues(new MyClass(), validAtVatIds);