[
  {
    "path": ".eslintrc.yml",
    "content": "parser: '@typescript-eslint/parser'\nplugins:\n  - '@typescript-eslint'\nparserOptions:\n  ecmaVersion: 2018\n  sourceType: module\n  project: \n    - ./tsconfig.json\n    - ./tsconfig.spec.json\nextends:\n  - 'plugin:@typescript-eslint/recommended'\n  - 'plugin:@typescript-eslint/recommended-requiring-type-checking'\n  - 'plugin:jest/recommended'\n  - 'prettier'\nrules:\n  '@typescript-eslint/explicit-member-accessibility': off\n  '@typescript-eslint/no-angle-bracket-type-assertion': off\n  '@typescript-eslint/no-parameter-properties': off\n  '@typescript-eslint/explicit-function-return-type': off\n  '@typescript-eslint/member-delimiter-style': off\n  '@typescript-eslint/no-inferrable-types': off\n  '@typescript-eslint/no-explicit-any': off\n  '@typescript-eslint/member-ordering': 'error'\n  '@typescript-eslint/no-unused-vars':\n    - 'error'\n    - args: 'none'\n  # TODO: Remove these and fixed issues once we merged all the current PRs. \n  '@typescript-eslint/ban-types': off \n  '@typescript-eslint/no-unsafe-return': off\n  '@typescript-eslint/no-unsafe-assignment': off\n  '@typescript-eslint/no-unsafe-call': off\n  '@typescript-eslint/no-unsafe-member-access': off\n  '@typescript-eslint/no-unsafe-argument': off\n  '@typescript-eslint/explicit-module-boundary-types': off\n  '@typescript-eslint/restrict-template-expressions': off\n"
  },
  {
    "path": ".gitbook.yaml",
    "content": "root: docs\nstructure:\n  readme: README.md\n  summary: docs/README.md"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n- package-ecosystem: npm\n  directory: \"/\"\n  schedule:\n    interval: daily\n    time: \"10:00\"\n    timezone: Europe/Budapest\n  open-pull-requests-limit: 0\n  versioning-strategy: increase\n  commit-message:\n    prefix: build\n    include: scope\n  ignore:\n    - dependency-name: \"husky\"\n"
  },
  {
    "path": ".github/semantic.yml",
    "content": "titleAndCommits: true\nallowMergeCommits: false\nscopes:\n  - deps\n  - deps-dev\ntypes:\n  - feat\n  - fix\n  - docs\n  - style\n  - refactor\n  - perf\n  - test\n  - build\n  - ci\n  - chore\n  - revert\n  - merge\n"
  },
  {
    "path": ".github/workflows/auto-approve-dependabot-workflow.yml",
    "content": "name: Dependabot auto-merge\non:\n  pull_request_target\njobs:\n  dependabot:\n    runs-on: ubuntu-latest\n    if: github.actor == 'dependabot[bot]'\n    steps:\n    - name: 'Auto approve PR by Dependabot'\n      uses: hmarr/auto-approve-action@v2.0.0\n      with:\n        github-token: \"${{ secrets.TYPESTACK_BOT_TOKEN }}\"\n    - name: 'Comment merge command'\n      uses: actions/github-script@v3\n      with:\n        github-token: ${{secrets.TYPESTACK_BOT_TOKEN }}\n        script: |\n          await github.issues.createComment({\n            owner: context.repo.owner,\n            repo: context.repo.repo,\n            issue_number: context.issue.number,\n            body: '@dependabot squash and merge'\n          })\n"
  },
  {
    "path": ".github/workflows/continuous-deployment-workflow.yml",
    "content": "name: CD\non:\n  release:\n    types: [created]\njobs:\n  publish:\n    name: Publish to NPM\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      - uses: actions/setup-node@v3\n        with:\n          node-version: 'lts/*'\n          registry-url: https://registry.npmjs.org\n      - run: npm ci --ignore-scripts\n      - run: npm run prettier:check\n      - run: npm run lint:check\n      - run: npm run test:ci\n      - run: npm run build:es2015\n      - run: npm run build:esm5\n      - run: npm run build:cjs\n      - run: npm run build:umd\n      - run: npm run build:types\n      - run: cp LICENSE build/LICENSE\n      - run: cp README.md build/README.md\n      - run: jq 'del(.devDependencies) | del(.scripts)' package.json > build/package.json\n      - run: npm publish ./build\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/continuous-integration-workflow.yml",
    "content": "name: CI\non: [push, pull_request]\njobs:\n  checks:\n    name: Linters\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      - uses: actions/setup-node@v3\n        with:\n          node-version: 'lts/*'\n      - run: npm ci --ignore-scripts\n      - run: npm run prettier:check\n      - run: npm run lint:check\n  tests:\n    name: Tests\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        node-version: ['lts/*', 'current']\n      fail-fast: false\n    steps:\n      - uses: actions/checkout@v3\n      - name: Setting up Node.js (v${{ matrix.node-version }}.x)\n        uses: actions/setup-node@v3\n        with:\n          node-version: ${{ matrix.node-version }}\n      - run: npm ci --ignore-scripts\n      - run: npm run test:ci\n      - name: Upload coverage to Codecov\n        uses: codecov/codecov-action@v5\n        if: ${{ matrix.node-version == 'current' && github.actor != 'dependabot[bot]' }}\n        with:\n          files: ./coverage/clover.xml\n          directory: ./coverage/lcov-report/\n          token: ${{ secrets.CODECOV_TOKEN }}\n          verbose: true\n          fail_ci_if_error: true\n  build:\n    name: Build\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      - uses: actions/setup-node@v3\n        with:\n          node-version: 'lts/*'\n      - run: npm ci --ignore-scripts\n      - run: npm run build:es2015\n      - run: npm run build:esm5\n      - run: npm run build:cjs\n      - run: npm run build:umd\n      - run: npm run build:types\n"
  },
  {
    "path": ".github/workflows/lock-closed-issues-workflow.yml",
    "content": "name: 'Lock inactive threads'\non:\n  schedule:\n    - cron: '0 0 * * *'\njobs:\n  lock:\n    name: Lock closed issues\n    runs-on: ubuntu-latest\n    steps:\n      - uses: dessant/lock-threads@v2\n        with:\n          github-token: ${{ github.token }}\n          issue-lock-inactive-days: 30\n          pr-lock-inactive-days: 30\n          issue-lock-comment: >\n            This issue has been automatically locked since there\n            has not been any recent activity after it was closed.\n            Please open a new issue for related bugs.\n          pr-lock-comment: >\n            This pull request has been automatically locked since there\n            has not been any recent activity after it was closed.\n            Please open a new issue for related bugs.\n"
  },
  {
    "path": ".gitignore",
    "content": "# Log files\r\nlogs\r\n*.log\r\n*.tmp\r\n*.tmp.*\r\nlog.txt\r\nnpm-debug.log*\r\n\r\n# Testing output\r\nlib-cov/**\r\ncoverage/**\r\n\r\n# Environment files\r\n.env\r\n\r\n# Dependency directories\r\nnode_modules\r\n\r\n# MacOS related files\r\n*.DS_Store\r\n.AppleDouble\r\n.LSOverride\r\n._*\r\nUserInterfaceState.xcuserstate\r\n\r\n# Windows related files\r\nThumbs.db\r\nDesktop.ini\r\n$RECYCLE.BIN/\r\n\r\n# IDE - Sublime\r\n*.sublime-project\r\n*.sublime-workspace\r\n\r\n# IDE - VSCode\r\n.vscode/**\r\n!.vscode/tasks.json\r\n!.vscode/launch.json\r\n\r\n# IDE - IntelliJ\r\n.idea\r\n\r\n# Compilation output folders\r\ndist/\r\nbuild/\r\ntmp/\r\nout-tsc/\r\ntemp\r\n\r\n# Files for playing around locally\r\nplayground.ts\r\nplayground.js\r\n"
  },
  {
    "path": ".prettierrc.yml",
    "content": "printWidth: 120\ntabWidth: 2\nuseTabs: false\nsemi: true\nsingleQuote: true\ntrailingComma: es5\nbracketSpacing: true\narrowParens: avoid\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\n_This changelog follows the [keep a changelog][keep-a-changelog]_ format to maintain a human readable changelog.\n\n## [0.15.1](https://github.com/typestack/class-validator/compare/v0.14.4...v0.15.1) (2026-02-26)\n\n### BREAKING CHANGES\n\n- Added options argument to IsIBAN validator ([#2618](https://github.com/typestack/class-validator/pull/2618)), which breaks any existing usage of this decorator that pass an argument to the decorator, e.g. `@IsIBAN({forbidUnknownValues: false})`\n\n### Fixed\n\n- Updated lockfile to patch vulnerabilities ([#2669](https://github.com/typestack/class-validator/pull/2669))\n- Fixed a small grammatical error in the docs ([#2596](https://github.com/typestack/class-validator/pull/2596))\n\n### Added\n\n- Added `validateIf` option to all validators, providing a lot more flexibility in using conditional validation ([#1579](https://github.com/typestack/class-validator/pull/1579))\n- Added IsISO31661Numeric validator for country codes ([#2657](https://github.com/typestack/class-validator/pull/2657))\n- Added IsISO6391 validator for language codes ([#2626](https://github.com/typestack/class-validator/pull/2626))\n- Added more versions to IsUUID validator options. ([#2647](https://github.com/typestack/class-validator/pull/2647))\n-\n\n## [0.14.4](https://github.com/typestack/class-validator/compare/v0.14.3...v0.14.4) (2026-02-25)\n\n- Updated validator.js to 13.15.22 ([#2649](https://github.com/typestack/class-validator/pull/2649))\n\n## [0.14.3](https://github.com/typestack/class-validator/compare/v0.14.1...v0.14.3) (2025-11-24)\n\n- Fixed a vulnerability by bumping validator.js ([#2638](https://github.com/typestack/class-validator/pull/2638) by [@weikangchia](https://github.com/weikangchia))\n\n## [0.14.2](https://github.com/typestack/class-validator/compare/v0.14.1...v0.14.2) (2025-05-02)\n\n#### Fixed\n\n- Fixed an issue where `forbidUnknownValues` did not default to `true` when `validatorOptions` was undefined. ([#2196](https://github.com/typestack/class-validator/pull/2196) by [@cduff](https://github.com/cduff))\n- Fixed the `ValidationMetadata.name` property to work correctly with the `@IsOptional` decorator. ([#2044](https://github.com/typestack/class-validator/pull/2044) by [@Clashsoft](https://github.com/Clashsoft))\n- Updated the Codecov configuration for continuous integration. ([#2556](https://github.com/typestack/class-validator/pull/2556) by [@haiweilian](https://github.com/haiweilian))\n- Fixed an issue where options were not passed correctly to the `@IsBase64` decorator. ([#2549](https://github.com/typestack/class-validator/pull/2549) by [@aseyfpour](https://github.com/aseyfpour))\n- Fixed argument handling for the `isBase64` function. ([#2574](https://github.com/typestack/class-validator/pull/2574) by [@braaar](https://github.com/braaar))\n\n### [0.14.1](https://github.com/typestack/class-validator/compare/v0.14.0...v0.14.1) (2024-01-12)\n\n#### Added\n\n- allow specifying options for `@IsBase64` decorator ([#1845](https://github.com/typestack/class-validator/issues/1845)) , closes [#1013](https://github.com/typestack/class-validator/issues/1013)\n- use official type for version in `@IsUUID` decorator ([#1846](https://github.com/typestack/class-validator/issues/1846)) , closes [#1497](https://github.com/typestack/class-validator/issues/1497)\n- update `@IsPhoneNumber` decorator to use max dataset ([#1857](https://github.com/typestack/class-validator/issues/1857))\n\n#### Fixed\n\n- fail for non-array constraint in `@IsIn` decorator ([#1844](https://github.com/typestack/class-validator/issues/1844)) , closes [#1693](https://github.com/typestack/class-validator/issues/1693)\n- allow number and boolean values in validation message \"$value\" tokens ([#1467](https://github.com/typestack/class-validator/issues/1467)) , closes [#921](https://github.com/typestack/class-validator/issues/921), [#1046](https://github.com/typestack/class-validator/issues/1046)\n- read nullable option in `@IsNotEmptyObject` decorator correctly ([#1555](https://github.com/typestack/class-validator/issues/1555)) , closes [#1554](https://github.com/typestack/class-validator/issues/1554)\n\n#### Changed\n\n- update `libphonenumber-js` to `^1.10.53` from `^1.10.14`\n- update various dev-dependencies\n\n### [0.14.0](https://github.com/typestack/class-validator/compare/v0.13.2...v0.14.0) (2022-12-09)\n\n### Added\n\n- add `@IsTimeZone` decorator to check if given string is valid IANA time zone\n- add `@IsISO4217CurrencyCode` decorator to check if the string is an ISO 4217 currency code\n- add `@IsStrongPassword` decorator to check if given password matches specific complexity criteria\n- add `@IsBase58` decorator to check if a string is base58 encoded\n- add `@IsTaxId` decorator to check if a given string is a valid tax ID in a given locale\n- add support for passing function as date generator in `@MinDate` and `@MaxDate` decorators\n- add option to print constraint error message instead of constraint type in validation error\n- improve decorator metadata lookup performance\n- return possible values in error message for `@IsEnum` decorator\n\n### Fixed\n\n- re-added `@types/validator` as dependency\n- fix error generation when using `@NestedValidation`\n- pass validation options correctly to validator in `@IsDateString` decorator\n- support passing `Symbol` as parameter in error message generation\n- specify supported locales for `@IsAlphanumeric` decorator\n- correctly assign decorator name in metadata instead of loosing it\n- fix various spelling errors in documentation\n- fix various spelling errors and inconsistencies in JSDoc for decorators\n\n### Changed\n\n- enable `forbidUnknownValues` option by default\n- remove documentation about deprecated schema based validation and added warning\n- update warning message logged about missing decorator metadata\n- update `libphonenumber-js` to `^1.10.14` from `^1.9.43`\n- update various dev-dependencies\n\n### BREAKING CHANGES\n\n**`forbidUnknownValues` option is enabled by default**\n\nFrom this release the `forbidUnknownValues` is enabled by default. This is the desired behavior for majority of\nuse-cases, but this change may break validation for some. The two scenarios that results in failed validation:\n\n- when attempting to validate a class instance without metadata for it\n- when using group validation and the specified validation group results in zero validation applied\n\nThe old behavior can be restored via specifying `forbidUnknownValues: false` option when calling the validate functions.\n\nFor more details see [PR #1798](https://github.com/typestack/class-validator/pull/1798) and [#1422 (comment)](https://github.com/typestack/class-validator/issues/1422#issuecomment-1317953863).\n\n**`@NestedValidation` decorator correctly assigns validation errors**\n\nUntil now the errors from a nested validation in some cases were incorrectly assigned\nto the parent instead of the child being validated. Now the validation errors are correctly assigned.\n\nFor more details see [#679](https://github.com/typestack/class-validator/issues/679).\n\n### [0.13.2](https://github.com/typestack/class-validator/compare/v0.13.1...v0.13.2) (2021-11-20)\n\n> **NOTE:** This version fixes a security vulnerability allowing denial of service attacks with a specially crafted request payload.\n> Please update as soon as possible.\n\n#### Fixed\n\n- switched to use `Array.isArray` in array checks from `instanceof` operator\n\n#### Changed\n\n- `libphonenumber-js` package updated to `1.9.43` from `1.9.7`\n- `validator` package updated to `13.5.2` from `13.5.2`\n- various dev-dependencies updated\n\n### [0.13.1](https://github.com/typestack/class-validator/compare/v0.13.0...v0.13.1) (2021-01-14)\n\n#### Added\n\n- optional mather function has been added to the `ArrayUnique` decorator\n\n#### Fixed\n\n- a typo was fixed in the error message generated by the `IsUUID` decorator\n- calling `ValidationError.toString()` doesn't result in an error when `forbidNonWhitelisted` parameter was used\n- fixed typo in error message generated by `IsIn` decorator\n- the `@types/validator` package is correctly installed\n- `inlineSources` option is enabled in tsconfig preventing various sourcemap errors when consuming the package\n\n#### Changed\n\n- various dev dependencies has been updated\n\n### [0.13.0](https://github.com/typestack/class-validator/compare/v0.12.2...v0.13.0) (2021-01-11)\n\n#### Added\n\n- **project is restructured to allow three-shaking**\n- added option to fail on first validation error (#620)\n- two new validator option is added:\n  - `always` - allows setting global default for `always` option for decorators\n  - `strictGroups` - ignore decorators with at least one group, when `ValidatorOptions.groups` is empty\n\n### Fixed\n\n- the 'any' locale is allowed in the `isPostalCode` decorator (#634)\n- the `IsDateString()` decorator now aliases the `IsISO8601()` decorator (#672)\n\n#### Changed\n\n- project tooling has been updated significantly\n- google-libphonenumber has been replaced with libphonenumber-js (this should have no effect on validation)\n- build process generates include both ES/CommonJS and UMD variations\n- various dev dependencies has been updated\n\n### [0.12.2](https://github.com/typestack/class-validator/compare/v0.12.1...v0.12.2) (2020-04-23)\n\n#### Fixed\n\n- move `tslib` from `peerDependencies` to `dependencies` ([827eff1](https://github.com/typestack/class-validator/commit/827eff1)), closes [#588](https://github.com/typestack/class-validator/issues/588)\n\n### [0.12.1](https://github.com/typestack/class-validator/compare/v0.12.0...v0.12.1) (2020-04-18)\n\n#### Fixed\n\n- apply only nested validator for ValidateNested multi-dimensional array ([c463be5](https://github.com/typestack/class-validator/commit/c463be5))\n\n### [0.12.0](https://github.com/typestack/class-validator/compare/v0.11.1...v0.12.0) (2020-04-18)\n\n#### Fixed\n\n- accept negative timezone in isDateString ([#564](https://github.com/typestack/class-validator/issues/564)) ([2012d72](https://github.com/typestack/class-validator/commit/2012d72)), closes [#565](https://github.com/typestack/class-validator/issues/565)\n- apply all decorators type PropertyDecorator ([#556](https://github.com/typestack/class-validator/issues/556)) ([5fb36e3](https://github.com/typestack/class-validator/commit/5fb36e3)), closes [#555](https://github.com/typestack/class-validator/issues/555)\n- avoiding metadataStorage from DI ([#335](https://github.com/typestack/class-validator/issues/335)) ([b57fef4](https://github.com/typestack/class-validator/commit/b57fef4)), closes [#328](https://github.com/typestack/class-validator/issues/328) [#261](https://github.com/typestack/class-validator/issues/261) [#132](https://github.com/typestack/class-validator/issues/132)\n- correct registerDecorator options argument ([7909ec6](https://github.com/typestack/class-validator/commit/7909ec6)), closes [#302](https://github.com/typestack/class-validator/issues/302)\n- IsNumberString accept isNumbericOptions as argument ([62b993f](https://github.com/typestack/class-validator/commit/62b993f)), closes [#518](https://github.com/typestack/class-validator/issues/518) [#463](https://github.com/typestack/class-validator/issues/463)\n- optional `constraints` property in ValidationError ([#465](https://github.com/typestack/class-validator/issues/465)) ([84680ad](https://github.com/typestack/class-validator/commit/84680ad)), closes [#309](https://github.com/typestack/class-validator/issues/309)\n- pass context to ValidationError for async validations ([#533](https://github.com/typestack/class-validator/issues/533)) ([4eb1216](https://github.com/typestack/class-validator/commit/4eb1216))\n- switch isLatitude & isLongitude validators ([#513](https://github.com/typestack/class-validator/issues/513)) ([5497179](https://github.com/typestack/class-validator/commit/5497179)), closes [#502](https://github.com/typestack/class-validator/issues/502)\n- switch isLatitude & isLongitude validators ([#537](https://github.com/typestack/class-validator/issues/537)) ([c27500b](https://github.com/typestack/class-validator/commit/c27500b))\n- ValidateNested support multi-dimensional arrays ([#539](https://github.com/typestack/class-validator/issues/539)) ([62678e1](https://github.com/typestack/class-validator/commit/62678e1))\n\n#### Changed\n\n- update build process to enable tree shaking ([#568](https://github.com/typestack/class-validator/issues/568)) ([11a7b8b](https://github.com/typestack/class-validator/commit/11a7b8b)), closes [#258](https://github.com/typestack/class-validator/issues/258) [#248](https://github.com/typestack/class-validator/issues/248) [#247](https://github.com/typestack/class-validator/issues/247) [#212](https://github.com/typestack/class-validator/issues/212)\n\n#### Added\n\n- sync validatorjs version from v10.11.3 to v13.0.0 ([09120b7](https://github.com/typestack/class-validator/commit/09120b7)), closes [#576](https://github.com/typestack/class-validator/issues/576) [#425](https://github.com/typestack/class-validator/issues/425)\n\n### BREAKING CHANGES\n\n- Validatorjs releases contain some breaking changes e.g. `IsMobileNumber` or `IsHexColor`. Please check validatorjs [CHANGELOG](https://github.com/validatorjs/validator.js/blob/master/CHANGELOG.md)\n- Validation functions was removed from `Validator` class to enable tree shaking.\n\n  BEFORE:\n\n  ```ts\n  import { Validator } from 'class-validator';\n\n  const validator = new Validator();\n  validator.isNotIn(value, possibleValues);\n  validator.isBoolean(value);\n  ```\n\n  AFTER:\n\n  ```ts\n  import { isNotIn, isBoolean } from 'class-validator';\n\n  isNotIn(value, possibleValues);\n  isBoolean(value);\n  ```\n\n- IsNumberString decorator arguments changed to `@IsNumberString(ValidatorJS.IsNumericOptions, ValidationOptions)`.\n\n### [0.11.1](https://github.com/typestack/class-validator/compare/v0.11.0...v0.11.1) (2020-03-18)\n\n#### Fixed\n\n- IsNumber validator now works when maxDecimalPlaces=0 ([#524](https://github.com/typestack/class-validator/issues/524)) ([b8aa922](https://github.com/typestack/class-validator/commit/b8aa922))\n\n#### Added\n\n- add all option in isuuid validator ([#452](https://github.com/typestack/class-validator/issues/452)) ([98e9382](https://github.com/typestack/class-validator/commit/98e9382))\n- add IsFirebasePushId validator ([#548](https://github.com/typestack/class-validator/issues/548)) ([e7e2e53](https://github.com/typestack/class-validator/commit/e7e2e53))\n- add options for isISO8601 validator ([#460](https://github.com/typestack/class-validator/issues/460)) ([90a6638](https://github.com/typestack/class-validator/commit/90a6638))\n\n### [0.11.0](https://github.com/typestack/class-validator/compare/v0.10.2...v0.11.0) (2019-11-01)\n\n#### Fixed\n\n- create instance of ValidationError for whitelist errors ([#434](https://github.com/typestack/class-validator/issues/434)) ([a98f5dd](https://github.com/typestack/class-validator/commit/a98f5dd)), closes [#325](https://github.com/typestack/class-validator/issues/325)\n- pass context for isDefined and custom validators ([#296](https://github.com/typestack/class-validator/issues/296)) ([0ef898e](https://github.com/typestack/class-validator/commit/0ef898e)), closes [#292](https://github.com/typestack/class-validator/issues/292)\n\n#### Added\n\n- add isHash validator ([#445](https://github.com/typestack/class-validator/issues/445)) ([c454cf9](https://github.com/typestack/class-validator/commit/c454cf9))\n- add isISSN validator ([#450](https://github.com/typestack/class-validator/issues/450)) ([4bd586e](https://github.com/typestack/class-validator/commit/4bd586e))\n- add isJWT validator ([#444](https://github.com/typestack/class-validator/issues/444)) ([874861b](https://github.com/typestack/class-validator/commit/874861b))\n- add isMACAddress validator ([#449](https://github.com/typestack/class-validator/issues/449)) ([45b7df7](https://github.com/typestack/class-validator/commit/45b7df7))\n- add support for maxDecimalPlaces on IsNumber ([#381](https://github.com/typestack/class-validator/issues/381)) ([a4dc10e](https://github.com/typestack/class-validator/commit/a4dc10e))\n\n### BREAKING CHANGES\n\n- update @types/validator from 11.1.0 to version 12.0.0 - please check it's [changelog][validator-js-release-notes]\n\n### [0.10.2](https://github.com/typestack/class-validator/compare/v0.10.1...v0.10.2) (2019-10-14)\n\n#### Fixed\n\n- apply custom constraint class validation to each item in the array ([#295](https://github.com/typestack/class-validator/issues/295)) ([5bb704e](https://github.com/typestack/class-validator/commit/5bb704e)), closes [#260](https://github.com/typestack/class-validator/issues/260)\n\n#### Added\n\n- add isLatLong, isLatitude, isLongtitude validators ([#427](https://github.com/typestack/class-validator/issues/427)) ([3fd15c4](https://github.com/typestack/class-validator/commit/3fd15c4)), closes [#415](https://github.com/typestack/class-validator/issues/415)\n- add IsObject and IsNotEmptyObject new decorators ([#334](https://github.com/typestack/class-validator/issues/334)) ([0a41aeb](https://github.com/typestack/class-validator/commit/0a41aeb))\n- support ES6 Map and Set for regular validators with each option ([#430](https://github.com/typestack/class-validator/issues/430)) ([a055bba](https://github.com/typestack/class-validator/commit/a055bba)), closes [#428](https://github.com/typestack/class-validator/issues/428)\n\n### [0.10.1](https://github.com/typestack/class-validator/compare/v0.10.0...v0.10.1) (2019-09-25)\n\n#### Fixed\n\n- add default message for isMilitaryTime validator ([#411](https://github.com/typestack/class-validator/issues/411)) ([204b7df](https://github.com/typestack/class-validator/commit/204b7df)), closes [#287](https://github.com/typestack/class-validator/issues/287)\n- add default message for isPort validator ([#404](https://github.com/typestack/class-validator/issues/404)) ([74e568c](https://github.com/typestack/class-validator/commit/74e568c))\n- add locale parameter for isAlpha and isAlphanumeric validat… ([#406](https://github.com/typestack/class-validator/issues/406)) ([2f4bf4e](https://github.com/typestack/class-validator/commit/2f4bf4e))\n\n#### Added\n\n- add `skipUndefinedProperties`, `skipNullProperties` options ([#414](https://github.com/typestack/class-validator/issues/414)) ([76c948a](https://github.com/typestack/class-validator/commit/76c948a)), closes [#308](https://github.com/typestack/class-validator/issues/308)\n\n### [0.10.0](https://github.com/typestack/class-validator/compare/v0.9.1...v0.10.0) (2019-08-10)\n\n#### Fixed\n\n- add correct signature for custom error message handler ([249c41d](https://github.com/typestack/class-validator/commit/249c41d))\n\n#### Added\n\n- add `IsISO31661Alpha3` and `IsISO31661Alpha2` validators ([#273](https://github.com/typestack/class-validator/issues/273)) ([55c57b3](https://github.com/typestack/class-validator/commit/55c57b3))\n- **IsDecimal:** implement `IsDecimal` from validatorjs ([#359](https://github.com/typestack/class-validator/issues/359)) ([b4c8e21](https://github.com/typestack/class-validator/commit/b4c8e21))\n- add `isPort` decorator ([#282](https://github.com/typestack/class-validator/issues/282)) ([36684ec](https://github.com/typestack/class-validator/commit/36684ec))\n- allow validate Map/Set ([#365](https://github.com/typestack/class-validator/issues/365)) ([f6fcdc5](https://github.com/typestack/class-validator/commit/f6fcdc5))\n- new `ValidatePromise` decorator - resolve promise before validate ([#369](https://github.com/typestack/class-validator/issues/369)) ([35ec04d](https://github.com/typestack/class-validator/commit/35ec04d))\n- replace instanceof Promise and support Promise/A+ ([#310](https://github.com/typestack/class-validator/issues/310)) ([59eac09](https://github.com/typestack/class-validator/commit/59eac09))\n- `isNumberString` now accept validator.js `IsNumericOptions` as second parameter ([#262](https://github.com/typestack/class-validator/issues/262))\n\n### BREAKING CHANGES\n\n- update @types/validator from 10.4.0 to version 10.11.2 - please check it's [changelog][validator-js-release-notes] ([cb960dd](https://github.com/typestack/class-validator/commit/cb960dd))\n- `isDateString` now check to match only entire ISO Date ([#275](https://github.com/typestack/class-validator/issues/275)) ([5012464](https://github.com/typestack/class-validator/commit/5012464))\n- remove `IsCurrencyOptions`, `IsURLOptions`, `IsEmailOptions`, `IsFQDNOptions` interfaces and replace with interfaces from `@types/validator`\n\n### [0.9.1](https://github.com/typestack/class-validator/compare/v0.9.0...v0.9.1)\n\n#### Added\n\n- added option to pass custom context for the decorators\n\n#### Fixed\n\n- validating against a schema will validate against that one instead of every registered one\n\n### [0.9.0](https://github.com/typestack/class-validator/compare/v0.8.5...v0.9.0) [BREAKING CHANGE]\n\n#### Added\n\n- updated [validator.js][validator-js] from 9.2.0 to 10.4.0 (Check it's [changelog][validator-js-release-notes] for what has changed.)\n  - until now fractional numbers was not allowed in the `IsNumberString` decorator, now they are allowed\n  - until now Gmail addresses could contain multiple dots or random text after a `+` symbol, this is not allowed anymore\n- `IsPhoneNumber` decorator has been added which uses the [google-libphonenumber][google-libphonenumber] library to validate international phone numbers accurately\n\n#### Fixed\n\n- update `IsURLOptions` to match underlying validator host list options\n- added a console warning when no metadata decorator is found as it's possibly not intended\n- the `Min` and `Max` decorator will corectly show an inclusive error message when failing\n- fixed a runtime error when `validationArguments.value` is not a string\n\n### [0.8.5](https://github.com/typestack/class-validator/compare/v0.8.4...v0.8.5)\n\n#### Fixed\n\n- remove `ansicolor` package, because it's incompatible with IE\n\n### [0.8.4](https://github.com/typestack/class-validator/compare/v0.8.3...v0.8.4)\n\n#### Added\n\n- `ValidatorOptions` now has a `forbidUnknownValues` key to prevent unknown objects to pass validation\n  - it's highly advised to turn this option on\n  - now this option defaults to `false` but will be default to `true` after the **1.0** release\n\n### [0.8.3](https://github.com/typestack/class-validator/compare/v0.8.2...v0.8.3)\n\n#### Fixed\n\n- handle when `target` property is undefined when calling `ValidationError.toString()`\n\n### [0.8.2](https://github.com/typestack/class-validator/compare/v0.8.1...v0.8.2)\n\n#### Added\n\n- added `ValidationError.toString()` method for easier debugging\n- added `printError` method to pretty-print errors in NodeJS or the browser\n\n#### Fixed\n\n- fixed wrong type info in `ValidatorOptions`\n- fixed wrong type info in `ValidationSchema` \\(the `options` key now is optional\\)\n- corrected `IsNumericString` to `IsNumberString` in the README\n- fixed type of `host_whitelist` and `host_backlist` in `IsURLOptions`\n\n### [0.8.1](https://github.com/typestack/class-validator/compare/v0.8.0...v0.8.1)\n\n#### Fixed\n\n- fixed wrong type info in `ValidatorOptions`\n\n### 0.8.0 \\[BREAKING CHANGE\\]\n\n##### Added\n\n- updated [validator.js][validator-js] from 7.0.0 to 9.2.0 (Check it's [changelog][validator-js-release-notes] for what has changed.)\n\n  This caused breaking change, if you used the `IsUrl` decorator to validate `localhost` as a valid url, from now you must use the `require_tld: false` option\n\n  ```typescript\n  @IsUrl({ require_tld: false})\n  url: string;\n  ```\n\n- added `@IsInstance` decorator and `validator.isInstance(value, target)` method.\n- changed `@IsNumber` decorator has been changed to `@IsNumber(options: IsNumberOptions)`\n- added option to strip unknown properties \\(`whitelist: true`\\)\n- added option to throw error on unknown properties \\(`forbidNonWhitelisted: true`\\)\n- added `@Allow` decorator to prevent stripping properties without other constraint\n\n#### Fixed\n\n- fixed issue with `@IsDateString` now it allow dates without fraction seconds to be set\n- fixed issue with `@IsDateString` now it allow dates without with timezones to be set\n- `@ValidateNested` correctly generates validation error on non object and non array values\n\n### 0.6.7\n\n#### Fixed\n\n- fixed issue with `@ValidateNested` when nested property is not defined and it throw an error \\(\\#59\\)\n\n### 0.6.5\n\n#### Fixed\n\n- fixed bugs with `@IsUrl`, `@IsEmail` and several other decorators\n\n### 0.6.4\n\n#### Added\n\n- added `@IsMilitaryTime` decorator.\n\n### 0.6.3\n\n#### Added\n\n- added `validateOrReject` method which rejects promise instead of returning array of errors in resolved result\n\n### 0.6.1\n\n#### Added\n\n- added `@IsArray` decorator.\n\n### 0.6.0 \\[BREAKING CHANGE\\]\n\n#### Added\n\n- breaking change with `@ValidateNested` on arrays: Validator now groups the validation errors by sub-object, rather than them all being grouped together. See \\#32 for a demonstration of the updated structure.\n- added `@ValidateIf` decorator, see conditional validation in docs.\n\n### 0.5.0 \\[BREAKING CHANGE\\]\n\n#### Added\n\n- async validations must be marked with `{ async: true }` option now.\n\n  This is optional, but it helps to determine which decorators are async to prevent their execution in `validateSync` method.\n\n- added `validateSync` method that performs non asynchronous validation and ignores validations that marked with `async: true`.\n- there is a breaking change in `registerDecorator` method. Now it accepts options object.\n- breaking change with `@ValidatorConstraint` decorator. Now it accepts option object instead of single name.\n\n### 0.4.1\n\n#### Fixed\n\n- fixed issue with wrong source maps packaged\n\n### 0.4.0 \\[BREAKING CHANGE\\]\n\n#### Added\n\n- everything should be imported from \"class-validator\" main entry point now\n- `ValidatorInterface` has been renamed to `ValidatorConstraintInterface`\n- contain can be set in the main entry point now\n- some decorator's names changed. Be aware of this\n- added few more non-string decorators\n- validator now returns array of ValidationError instead of ValidationErrorInterface. Removed old ValidationError\n- removed all other validation methods except `validator.validate`\n- finally validate method is async now, so custom async validations are supported now\n- added ability to validate inherited properties\n- added support of separate validation schemas\n- added support of default validation messages\n- added support of special tokens in validation messages\n- added support of message functions in validation options\n- added support of custom decorators\n- if no groups were specified, decorators with groups now are being ignored\n- changed signature of the `ValidationError`. Now if it has nested errors it does not return them in a flat array\n\n#### Fixed\n\n- fixed all decorators that should not work only with strings\n\n### 0.3.0\n\n#### Added\n\n- package has changed its name from `validator.ts` to `class-validator`.\n- sanitation functionality has been removed from this library. Use [class-sanitizer][class-sanitizer] instead.\n\n[class-sanitizer]: https://github.com/typestack/class-validator/class-sanitizer\n[validator-js]: https://github.com/chriso/validator.js\n[validator-js-release-notes]: https://github.com/chriso/validator.js/blob/master/CHANGELOG.md\n[google-libphonenumber]: https://github.com/ruimarinho/google-libphonenumber\n[keep-a-changelog]: https://keepachangelog.com/en/1.0.0/\n"
  },
  {
    "path": "LICENSE",
    "content": "\nThe MIT License\n\nCopyright (c) 2015-2020 TypeStack\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# class-validator\n\n![Build Status](https://github.com/typestack/class-validator/workflows/CI/badge.svg)\n[![codecov](https://codecov.io/gh/typestack/class-validator/branch/develop/graph/badge.svg)](https://codecov.io/gh/typestack/class-validator)\n[![npm version](https://badge.fury.io/js/class-validator.svg)](https://badge.fury.io/js/class-validator)\n[![install size](https://packagephobia.now.sh/badge?p=class-validator)](https://packagephobia.now.sh/result?p=class-validator)\n\nAllows use of decorator and non-decorator based validation.\nInternally uses [validator.js][1] to perform validation.\nClass-validator works on both browser and node.js platforms.\n\n## Table of Contents\n\n- [class-validator](#class-validator)\n  - [Table of Contents](#table-of-contents)\n  - [Installation](#installation)\n  - [Usage](#usage)\n    - [Passing options](#passing-options)\n  - [Validation errors](#validation-errors)\n  - [Validation messages](#validation-messages)\n  - [Validating arrays](#validating-arrays)\n  - [Validating sets](#validating-sets)\n  - [Validating maps](#validating-maps)\n  - [Validating nested objects](#validating-nested-objects)\n  - [Validating promises](#validating-promises)\n  - [Inheriting Validation decorators](#inheriting-validation-decorators)\n  - [Conditional validation](#conditional-validation)\n  - [Whitelisting](#whitelisting)\n  - [Passing context to decorators](#passing-context-to-decorators)\n  - [Skipping missing properties](#skipping-missing-properties)\n  - [Validation groups](#validation-groups)\n  - [Custom validation classes](#custom-validation-classes)\n  - [Custom validation decorators](#custom-validation-decorators)\n  - [Using service container](#using-service-container)\n  - [Synchronous validation](#synchronous-validation)\n  - [Manual validation](#manual-validation)\n  - [Validation decorators](#validation-decorators)\n  - [Defining validation schema without decorators](#defining-validation-schema-without-decorators)\n  - [Validating plain objects](#validating-plain-objects)\n  - [Samples](#samples)\n  - [Extensions](#extensions)\n  - [Release notes](#release-notes)\n  - [Contributing](#contributing)\n\n## Installation\n\n```sh\nnpm install class-validator --save\n```\n\n> Note: Please use at least npm@6 when using class-validator. From npm@6 the dependency tree is flattened, which is required by `class-validator` to function properly.\n\n## Usage\n\nCreate your class and put some validation decorators on the properties you want to validate:\n\n```typescript\nimport {\n  validate,\n  validateOrReject,\n  Contains,\n  IsInt,\n  Length,\n  IsEmail,\n  IsFQDN,\n  IsDate,\n  Min,\n  Max,\n} from 'class-validator';\n\nexport class Post {\n  @Length(10, 20)\n  title: string;\n\n  @Contains('hello')\n  text: string;\n\n  @IsInt()\n  @Min(0)\n  @Max(10)\n  rating: number;\n\n  @IsEmail()\n  email: string;\n\n  @IsFQDN()\n  site: string;\n\n  @IsDate()\n  createDate: Date;\n}\n\nlet post = new Post();\npost.title = 'Hello'; // should not pass\npost.text = 'this is a great post about hell world'; // should not pass\npost.rating = 11; // should not pass\npost.email = 'google.com'; // should not pass\npost.site = 'googlecom'; // should not pass\n\nvalidate(post).then(errors => {\n  // errors is an array of validation errors\n  if (errors.length > 0) {\n    console.log('validation failed. errors: ', errors);\n  } else {\n    console.log('validation succeed');\n  }\n});\n\nvalidateOrReject(post).catch(errors => {\n  console.log('Promise rejected (validation failed). Errors: ', errors);\n});\n// or\nasync function validateOrRejectExample(input) {\n  try {\n    await validateOrReject(input);\n  } catch (errors) {\n    console.log('Caught promise rejection (validation failed). Errors: ', errors);\n  }\n}\n```\n\n### Passing options\n\nThe `validate` function optionally expects a `ValidatorOptions` object as a second parameter:\n\n```ts\nexport interface ValidatorOptions {\n  skipMissingProperties?: boolean;\n  whitelist?: boolean;\n  forbidNonWhitelisted?: boolean;\n  groups?: string[];\n  dismissDefaultMessages?: boolean;\n  validationError?: {\n    target?: boolean;\n    value?: boolean;\n  };\n\n  forbidUnknownValues?: boolean;\n  stopAtFirstError?: boolean;\n}\n```\n\n> **IMPORTANT**\n> The `forbidUnknownValues` value is set to `true` by default and **it is highly advised to keep the default**.\n> Setting it to `false` will result unknown objects passing the validation!\n\n## Validation errors\n\nThe `validate` method returns an array of `ValidationError` objects. Each `ValidationError` is:\n\n```typescript\n{\n    target: Object; // Object that was validated.\n    property: string; // Object's property that haven't pass validation.\n    value: any; // Value that haven't pass a validation.\n    constraints?: { // Constraints that failed validation with error messages.\n        [type: string]: string;\n    };\n    children?: ValidationError[]; // Contains all nested validation errors of the property\n}\n```\n\nIn our case, when we validated a Post object, we have such an array of `ValidationError` objects:\n\n```typescript\n[{\n    target: /* post object */,\n    property: \"title\",\n    value: \"Hello\",\n    constraints: {\n        length: \"$property must be longer than or equal to 10 characters\"\n    }\n}, {\n    target: /* post object */,\n    property: \"text\",\n    value: \"this is a great post about hell world\",\n    constraints: {\n        contains: \"text must contain a hello string\"\n    }\n},\n// and other errors\n]\n```\n\nIf you don't want a `target` to be exposed in validation errors, there is a special option when you use validator:\n\n```typescript\nvalidator.validate(post, { validationError: { target: false } });\n```\n\nThis is especially useful when you send errors back over http, and you most probably don't want to expose\nthe whole target object.\n\n## Validation messages\n\nYou can specify validation message in the decorator options and that message will be returned in the `ValidationError`\nreturned by the `validate` method (in the case that validation for this field fails).\n\n```typescript\nimport { MinLength, MaxLength } from 'class-validator';\n\nexport class Post {\n  @MinLength(10, {\n    message: 'Title is too short',\n  })\n  @MaxLength(50, {\n    message: 'Title is too long',\n  })\n  title: string;\n}\n```\n\nThere are few special tokens you can use in your messages:\n\n- `$value` - the value that is being validated\n- `$property` - name of the object's property being validated\n- `$target` - name of the object's class being validated\n- `$constraint1`, `$constraint2`, ... `$constraintN` - constraints defined by specific validation type\n\nExample of usage:\n\n```typescript\nimport { MinLength, MaxLength } from 'class-validator';\n\nexport class Post {\n  @MinLength(10, {\n    // here, $constraint1 will be replaced with \"10\", and $value with actual supplied value\n    message: 'Title is too short. Minimal length is $constraint1 characters, but actual is $value',\n  })\n  @MaxLength(50, {\n    // here, $constraint1 will be replaced with \"50\", and $value with actual supplied value\n    message: 'Title is too long. Maximal length is $constraint1 characters, but actual is $value',\n  })\n  title: string;\n}\n```\n\nAlso you can provide a function, that returns a message. This allows you to create more granular messages:\n\n```typescript\nimport { MinLength, MaxLength, ValidationArguments } from 'class-validator';\n\nexport class Post {\n  @MinLength(10, {\n    message: (args: ValidationArguments) => {\n      if (args.value.length === 1) {\n        return 'Too short, minimum length is 1 character';\n      } else {\n        return 'Too short, minimum length is ' + args.constraints[0] + ' characters';\n      }\n    },\n  })\n  title: string;\n}\n```\n\nMessage function accepts `ValidationArguments` which contains the following information:\n\n- `value` - the value that is being validated\n- `constraints` - array of constraints defined by specific validation type\n- `targetName` - name of the object's class being validated\n- `object` - object that is being validated\n- `property` - name of the object's property being validated\n\n## Validating arrays\n\nIf your field is an array and you want to perform validation of each item in the array you must specify a\nspecial `each: true` decorator option:\n\n```typescript\nimport { MinLength, MaxLength } from 'class-validator';\n\nexport class Post {\n  @MaxLength(20, {\n    each: true,\n  })\n  tags: string[];\n}\n```\n\nThis will validate each item in `post.tags` array.\n\n## Validating sets\n\nIf your field is a set and you want to perform validation of each item in the set you must specify a\nspecial `each: true` decorator option:\n\n```typescript\nimport { MinLength, MaxLength } from 'class-validator';\n\nexport class Post {\n  @MaxLength(20, {\n    each: true,\n  })\n  tags: Set<string>;\n}\n```\n\nThis will validate each item in `post.tags` set.\n\n## Validating maps\n\nIf your field is a map and you want to perform validation of each item in the map you must specify a\nspecial `each: true` decorator option:\n\n```typescript\nimport { MinLength, MaxLength } from 'class-validator';\n\nexport class Post {\n  @MaxLength(20, {\n    each: true,\n  })\n  tags: Map<string, string>;\n}\n```\n\nThis will validate each item in `post.tags` map.\n\n## Validating nested objects\n\nIf your object contains nested objects and you want the validator to perform their validation too, then you need to\nuse the `@ValidateNested()` decorator:\n\n```typescript\nimport { ValidateNested } from 'class-validator';\n\nexport class Post {\n  @ValidateNested()\n  user: User;\n}\n```\n\nPlease note that nested object _must_ be an instance of a class, otherwise `@ValidateNested` won't know what class is target of validation. Check also [Validating plain objects](#validating-plain-objects).\n\nIt also works with multi-dimensional array, like :\n\n```typescript\nimport { ValidateNested } from 'class-validator';\n\nexport class Plan2D {\n  @ValidateNested()\n  matrix: Point[][];\n}\n```\n\n## Validating promises\n\nIf your object contains property with `Promise`-returned value that should be validated, then you need to use the `@ValidatePromise()` decorator:\n\n```typescript\nimport { ValidatePromise, Min } from 'class-validator';\n\nexport class Post {\n  @Min(0)\n  @ValidatePromise()\n  userId: Promise<number>;\n}\n```\n\nIt also works great with `@ValidateNested` decorator:\n\n```typescript\nimport { ValidateNested, ValidatePromise } from 'class-validator';\n\nexport class Post {\n  @ValidateNested()\n  @ValidatePromise()\n  user: Promise<User>;\n}\n```\n\n## Inheriting Validation decorators\n\nWhen you define a subclass which extends from another one, the subclass will automatically inherit the parent's decorators. If a property is redefined in the descendant, class decorators will be applied on it from both its own class and the base class.\n\n```typescript\nimport { validate } from 'class-validator';\n\nclass BaseContent {\n  @IsEmail()\n  email: string;\n\n  @IsString()\n  password: string;\n}\n\nclass User extends BaseContent {\n  @MinLength(10)\n  @MaxLength(20)\n  name: string;\n\n  @Contains('hello')\n  welcome: string;\n\n  @MinLength(20)\n  password: string;\n}\n\nlet user = new User();\n\nuser.email = 'invalid email'; // inherited property\nuser.password = 'too short'; // password wil be validated not only against IsString, but against MinLength as well\nuser.name = 'not valid';\nuser.welcome = 'helo';\n\nvalidate(user).then(errors => {\n  // ...\n}); // it will return errors for email, password, name and welcome properties\n```\n\n## Conditional validation\n\nThe conditional validation decorator (`@ValidateIf`) can be used to ignore the validators on a property when the provided condition function returns false. The condition function takes the object being validated and must return a `boolean`.\n\n```typescript\nimport { ValidateIf, IsNotEmpty } from 'class-validator';\n\nexport class Post {\n  otherProperty: string;\n\n  @ValidateIf(o => o.otherProperty === 'value')\n  @IsNotEmpty()\n  example: string;\n}\n```\n\nIn the example above, the validation rules applied to `example` won't be run unless the object's `otherProperty` is `\"value\"`.\n\nNote that when the condition is false all validation decorators are ignored, including `isDefined`.\n\n## Whitelisting\n\nEven if your object is an instance of a validation class it can contain additional properties that are not defined.\nIf you do not want to have such properties on your object, pass special flag to `validate` method:\n\n```typescript\nimport { validate } from 'class-validator';\n// ...\nvalidate(post, { whitelist: true });\n```\n\nThis will strip all properties that don't have any decorators. If no other decorator is suitable for your property,\nyou can use @Allow decorator:\n\n```typescript\nimport {validate, Allow, Min} from \"class-validator\";\n\nexport class Post {\n\n    @Allow()\n    title: string;\n\n    @Min(0)\n    views: number;\n\n    nonWhitelistedProperty: number;\n}\n\nlet post = new Post();\npost.title = 'Hello world!';\npost.views = 420;\n\npost.nonWhitelistedProperty = 69;\n(post as any).anotherNonWhitelistedProperty = \"something\";\n\nvalidate(post).then(errors => {\n  // post.nonWhitelistedProperty is not defined\n  // (post as any).anotherNonWhitelistedProperty is not defined\n  ...\n});\n```\n\nIf you would rather to have an error thrown when any non-whitelisted properties are present, pass another flag to\n`validate` method:\n\n```typescript\nimport { validate } from 'class-validator';\n// ...\nvalidate(post, { whitelist: true, forbidNonWhitelisted: true });\n```\n\n## Passing context to decorators\n\nIt's possible to pass a custom object to decorators which will be accessible on the `ValidationError` instance of the property if validation failed.\n\n```ts\nimport { validate } from 'class-validator';\n\nclass MyClass {\n  @MinLength(32, {\n    message: 'EIC code must be at least 32 characters',\n    context: {\n      errorCode: 1003,\n      developerNote: 'The validated string must contain 32 or more characters.',\n    },\n  })\n  eicCode: string;\n}\n\nconst model = new MyClass();\n\nvalidate(model).then(errors => {\n  //errors[0].contexts['minLength'].errorCode === 1003\n});\n```\n\n## Skipping missing properties\n\nSometimes you may want to skip validation of the properties that do not exist in the validating object. This is\nusually desirable when you want to update some parts of the object, and want to validate only updated parts,\nbut skip everything else, e.g. skip missing properties.\nIn such situations you will need to pass a special flag to `validate` method:\n\n```typescript\nimport { validate } from 'class-validator';\n// ...\nvalidate(post, { skipMissingProperties: true });\n```\n\nWhen skipping missing properties, sometimes you want not to skip all missing properties, some of them maybe required\nfor you, even if skipMissingProperties is set to true. For such cases you should use `@IsDefined()` decorator.\n`@IsDefined()` is the only decorator that ignores `skipMissingProperties` option.\n\n## Validation groups\n\nIn different situations you may want to use different validation schemas of the same object.\nIn such cases you can use validation groups.\n\n> **IMPORTANT**\n> Calling a validation with a group combination that would not result in a validation (eg: non existent group name)\n> will result in a unknown value error. When validating with groups the provided group combination should match at least one decorator.\n\n```typescript\nimport { validate, Min, Length } from 'class-validator';\n\nexport class User {\n  @Min(12, {\n    groups: ['registration'],\n  })\n  age: number;\n\n  @Length(2, 20, {\n    groups: ['registration', 'admin'],\n  })\n  name: string;\n}\n\nlet user = new User();\nuser.age = 10;\nuser.name = 'Alex';\n\nvalidate(user, {\n  groups: ['registration'],\n}); // this will not pass validation\n\nvalidate(user, {\n  groups: ['admin'],\n}); // this will pass validation\n\nvalidate(user, {\n  groups: ['registration', 'admin'],\n}); // this will not pass validation\n\nvalidate(user, {\n  groups: undefined, // the default\n}); // this will not pass validation since all properties get validated regardless of their groups\n\nvalidate(user, {\n  groups: [],\n}); // this will not pass validation, (equivalent to 'groups: undefined', see above)\n```\n\nThere is also a special flag `always: true` in validation options that you can use. This flag says that this validation\nmust be applied always no matter which group is used.\n\n## Validation option validateIf\n\nIf you want an individual validaton decorator to apply conditionally, you can you can use the option `validateIf` available to all validators.\nThis allows more granular control than the `@ValidateIf` decorator which toggles all validators on the property, but keep in mind that\nwith great power comes great responsibility: Take care not to create unnecessarily complex validation logic.\n\n```typescript\nclass MyClass {\n  @Min(5, {\n    message: 'min',\n    validateIf: (obj: MyClass, value) => {\n      return !obj.someOtherProperty || obj.someOtherProperty === 'min';\n    },\n  })\n  @Max(3, {\n    message: 'max',\n    validateIf: (o: MyClass) => !o.someOtherProperty || o.someOtherProperty === 'max',\n  })\n  someProperty: number;\n\n  someOtherProperty: string;\n}\n\nconst model = new MyClass();\nmodel.someProperty = 4;\nmodel.someOtherProperty = 'min';\nvalidator.validate(model); // this only validate min\n\nconst model = new MyClass();\nmodel.someProperty = 4;\nmodel.someOtherProperty = 'max';\nvalidator.validate(model); // this only validate max\n\nconst model = new MyClass();\nmodel.someProperty = 4;\nmodel.someOtherProperty = '';\nvalidator.validate(model); // this validate both\n\nconst model = new MyClass();\nmodel.someProperty = 4;\nmodel.someOtherProperty = 'other';\nvalidator.validate(model); // this validate none\n```\n\n## Custom validation classes\n\nIf you have custom validation logic you can create a _Constraint class_:\n\n1. First create a file, lets say `CustomTextLength.ts`, and define a new class:\n\n   ```typescript\n   import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments } from 'class-validator';\n\n   @ValidatorConstraint({ name: 'customText', async: false })\n   export class CustomTextLength implements ValidatorConstraintInterface {\n     validate(text: string, args: ValidationArguments) {\n       return text.length > 1 && text.length < 10; // for async validations you must return a Promise<boolean> here\n     }\n\n     defaultMessage(args: ValidationArguments) {\n       // here you can provide default error message if validation failed\n       return 'Text ($value) is too short or too long!';\n     }\n   }\n   ```\n\n   We marked our class with `@ValidatorConstraint` decorator.\n   You can also supply a validation constraint name - this name will be used as \"error type\" in ValidationError.\n   If you will not supply a constraint name - it will be auto-generated.\n\n   Our class must implement `ValidatorConstraintInterface` interface and its `validate` method,\n   which defines validation logic. If validation succeeds, method returns true, otherwise false.\n   Custom validator can be asynchronous, if you want to perform validation after some asynchronous\n   operations, simply return a promise with boolean inside in `validate` method.\n\n   Also we defined optional method `defaultMessage` which defines a default error message,\n   in the case that the decorator's implementation doesn't set an error message.\n\n2. Then you can use your new validation constraint in your class:\n\n   ```typescript\n   import { Validate } from 'class-validator';\n   import { CustomTextLength } from './CustomTextLength';\n\n   export class Post {\n     @Validate(CustomTextLength, {\n       message: 'Title is too short or long!',\n     })\n     title: string;\n   }\n   ```\n\n   Here we set our newly created `CustomTextLength` validation constraint for `Post.title`.\n\n3. And use validator as usual:\n\n   ```typescript\n   import { validate } from 'class-validator';\n\n   validate(post).then(errors => {\n     // ...\n   });\n   ```\n\nYou can also pass constraints to your validator, like this:\n\n```typescript\nimport { Validate } from 'class-validator';\nimport { CustomTextLength } from './CustomTextLength';\n\nexport class Post {\n  @Validate(CustomTextLength, [3, 20], {\n    message: 'Wrong post title',\n  })\n  title: string;\n}\n```\n\nAnd use them from `validationArguments` object:\n\n```typescript\nimport { ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator';\n\n@ValidatorConstraint()\nexport class CustomTextLength implements ValidatorConstraintInterface {\n  validate(text: string, validationArguments: ValidationArguments) {\n    return text.length > validationArguments.constraints[0] && text.length < validationArguments.constraints[1];\n  }\n}\n```\n\n## Custom validation decorators\n\nYou can also create a custom decorator. It's the most elegant way of using custom validations.\nLets create a decorator called `@IsLongerThan`:\n\n1. Create a decorator itself:\n\n   ```typescript\n   import { registerDecorator, ValidationOptions, ValidationArguments } from 'class-validator';\n\n   export function IsLongerThan(property: string, validationOptions?: ValidationOptions) {\n     return function (object: Object, propertyName: string) {\n       registerDecorator({\n         name: 'isLongerThan',\n         target: object.constructor,\n         propertyName: propertyName,\n         constraints: [property],\n         options: validationOptions,\n         validator: {\n           validate(value: any, args: ValidationArguments) {\n             const [relatedPropertyName] = args.constraints;\n             const relatedValue = (args.object as any)[relatedPropertyName];\n             return typeof value === 'string' && typeof relatedValue === 'string' && value.length > relatedValue.length; // you can return a Promise<boolean> here as well, if you want to make async validation\n           },\n         },\n       });\n     };\n   }\n   ```\n\n2. Put it to use:\n\n   ```typescript\n   import { IsLongerThan } from './IsLongerThan';\n\n   export class Post {\n     title: string;\n\n     @IsLongerThan('title', {\n       /* you can also use additional validation options, like \"groups\" in your custom validation decorators. \"each\" is not supported */\n       message: 'Text must be longer than the title',\n     })\n     text: string;\n   }\n   ```\n\nIn your custom decorators you can also use `ValidationConstraint`.\nLets create another custom validation decorator called `IsUserAlreadyExist`:\n\n1. Create a ValidationConstraint and decorator:\n\n   ```typescript\n   import {\n     registerDecorator,\n     ValidationOptions,\n     ValidatorConstraint,\n     ValidatorConstraintInterface,\n     ValidationArguments,\n   } from 'class-validator';\n\n   @ValidatorConstraint({ async: true })\n   export class IsUserAlreadyExistConstraint implements ValidatorConstraintInterface {\n     validate(userName: any, args: ValidationArguments) {\n       return UserRepository.findOneByName(userName).then(user => {\n         if (user) return false;\n         return true;\n       });\n     }\n   }\n\n   export function IsUserAlreadyExist(validationOptions?: ValidationOptions) {\n     return function (object: Object, propertyName: string) {\n       registerDecorator({\n         target: object.constructor,\n         propertyName: propertyName,\n         options: validationOptions,\n         constraints: [],\n         validator: IsUserAlreadyExistConstraint,\n       });\n     };\n   }\n   ```\n\n   note that we marked our constraint that it will by async by adding `{ async: true }` in validation options.\n\n2. And put it to use:\n\n   ```typescript\n   import { IsUserAlreadyExist } from './IsUserAlreadyExist';\n\n   export class User {\n     @IsUserAlreadyExist({\n       message: 'User $value already exists. Choose another name.',\n     })\n     name: string;\n   }\n   ```\n\n## Using service container\n\nValidator supports service container in the case if want to inject dependencies into your custom validator constraint\nclasses. Here is example how to integrate it with [typedi][2]:\n\n```typescript\nimport { Container } from 'typedi';\nimport { useContainer, Validator } from 'class-validator';\n\n// do this somewhere in the global application level:\nuseContainer(Container);\nlet validator = Container.get(Validator);\n\n// now everywhere you can inject Validator class which will go from the container\n// also you can inject classes using constructor injection into your custom ValidatorConstraint-s\n```\n\n## Synchronous validation\n\nIf you want to perform a simple non async validation you can use `validateSync` method instead of regular `validate`\nmethod. It has the same arguments as `validate` method. But note, this method **ignores** all async validations\nyou have.\n\n## Manual validation\n\nThere are several method exist in the Validator that allows to perform non-decorator based validation:\n\n```typescript\nimport { isEmpty, isBoolean } from 'class-validator';\n\nisEmpty(value);\nisBoolean(value);\n```\n\n## Validation decorators\n\n| Decorator                                              | Description                                                                                                                                                                                           |\n| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Common validation decorators**                       |                                                                                                                                                                                                       |\n| `@IsDefined(value: any)`                               | Checks if value is defined (!== undefined, !== null). This is the only decorator that ignores skipMissingProperties option.                                                                           |\n| `@IsOptional()`                                        | Checks if given value is empty (=== null, === undefined) and if so, ignores all the validators on the property.                                                                                       |\n| `@Equals(comparison: any)`                             | Checks if value equals (\"===\") comparison.                                                                                                                                                            |\n| `@NotEquals(comparison: any)`                          | Checks if value not equal (\"!==\") comparison.                                                                                                                                                         |\n| `@IsEmpty()`                                           | Checks if given value is empty (=== '', === null, === undefined).                                                                                                                                     |\n| `@IsNotEmpty()`                                        | Checks if given value is not empty (!== '', !== null, !== undefined).                                                                                                                                 |\n| `@IsIn(values: any[])`                                 | Checks if value is in an array of allowed values.                                                                                                                                                     |\n| `@IsNotIn(values: any[])`                              | Checks if value is not in an array of disallowed values.                                                                                                                                              |\n| **Type validation decorators**                         |                                                                                                                                                                                                       |\n| `@IsBoolean()`                                         | Checks if a value is a boolean.                                                                                                                                                                       |\n| `@IsDate()`                                            | Checks if the value is a date.                                                                                                                                                                        |\n| `@IsString()`                                          | Checks if the value is a string.                                                                                                                                                                      |\n| `@IsNumber(options: IsNumberOptions)`                  | Checks if the value is a number.                                                                                                                                                                      |\n| `@IsInt()`                                             | Checks if the value is an integer number.                                                                                                                                                             |\n| `@IsArray()`                                           | Checks if the value is an array                                                                                                                                                                       |\n| `@IsEnum(entity: object)`                              | Checks if the value is a valid enum                                                                                                                                                                   |\n| **Number validation decorators**                       |\n| `@IsDivisibleBy(num: number)`                          | Checks if the value is a number that's divisible by another.                                                                                                                                          |\n| `@IsPositive()`                                        | Checks if the value is a positive number greater than zero.                                                                                                                                           |\n| `@IsNegative()`                                        | Checks if the value is a negative number smaller than zero.                                                                                                                                           |\n| `@Min(min: number)`                                    | Checks if the given number is greater than or equal to given number.                                                                                                                                  |\n| `@Max(max: number)`                                    | Checks if the given number is less than or equal to given number.                                                                                                                                     |\n| **Date validation decorators**                         |\n| `@MinDate(date: Date \\| (() => Date))`                 | Checks if the value is a date that's after the specified date.                                                                                                                                        |\n| `@MaxDate(date: Date \\| (() => Date))`                 | Checks if the value is a date that's before the specified date.                                                                                                                                       |\n| **String-type validation decorators**                  |                                                                                                                                                                                                       |\n| `@IsBooleanString()`                                   | Checks if a string is a boolean (e.g. is \"true\" or \"false\" or \"1\", \"0\").                                                                                                                              |\n| `@IsDateString()`                                      | Alias for `@IsISO8601()`.                                                                                                                                                                             |\n| `@IsNumberString(options?: IsNumericOptions)`          | Checks if a string is a number.                                                                                                                                                                       |\n| **String validation decorators**                       |                                                                                                                                                                                                       |\n| `@Contains(seed: string)`                              | Checks if the string contains the seed.                                                                                                                                                               |\n| `@NotContains(seed: string)`                           | Checks if the string not contains the seed.                                                                                                                                                           |\n| `@IsAlpha()`                                           | Checks if the string contains only letters (a-zA-Z).                                                                                                                                                  |\n| `@IsAlphanumeric()`                                    | Checks if the string contains only letters and numbers.                                                                                                                                               |\n| `@IsDecimal(options?: IsDecimalOptions)`               | Checks if the string is a valid decimal value. Default IsDecimalOptions are `force_decimal=False`, `decimal_digits: '1,'`, `locale: 'en-US'`                                                          |\n| `@IsAscii()`                                           | Checks if the string contains ASCII chars only.                                                                                                                                                       |\n| `@IsBase32()`                                          | Checks if a string is base32 encoded.                                                                                                                                                                 |\n| `@IsBase58()`                                          | Checks if a string is base58 encoded.                                                                                                                                                                 |\n| `@IsBase64(options?: IsBase64Options)`                 | Checks if a string is base64 encoded.                                                                                                                                                                 |\n| `@IsIBAN()`                                            | Checks if a string is a IBAN (International Bank Account Number).                                                                                                                                     |\n| `@IsBIC()`                                             | Checks if a string is a BIC (Bank Identification Code) or SWIFT code.                                                                                                                                 |\n| `@IsByteLength(min: number, max?: number)`             | Checks if the string's length (in bytes) falls in a range.                                                                                                                                            |\n| `@IsCreditCard()`                                      | Checks if the string is a credit card.                                                                                                                                                                |\n| `@IsCurrency(options?: IsCurrencyOptions)`             | Checks if the string is a valid currency amount.                                                                                                                                                      |\n| `@IsISO4217CurrencyCode()`                             | Checks if the string is an ISO 4217 currency code.                                                                                                                                                    |\n| `@IsEthereumAddress()`                                 | Checks if the string is an Ethereum address using basic regex. Does not validate address checksums.                                                                                                   |\n| `@IsBtcAddress()`                                      | Checks if the string is a valid BTC address.                                                                                                                                                          |\n| `@IsDataURI()`                                         | Checks if the string is a data uri format.                                                                                                                                                            |\n| `@IsEmail(options?: IsEmailOptions)`                   | Checks if the string is an email.                                                                                                                                                                     |\n| `@IsFQDN(options?: IsFQDNOptions)`                     | Checks if the string is a fully qualified domain name (e.g. domain.com).                                                                                                                              |\n| `@IsFullWidth()`                                       | Checks if the string contains any full-width chars.                                                                                                                                                   |\n| `@IsHalfWidth()`                                       | Checks if the string contains any half-width chars.                                                                                                                                                   |\n| `@IsVariableWidth()`                                   | Checks if the string contains a mixture of full and half-width chars.                                                                                                                                 |\n| `@IsHexColor()`                                        | Checks if the string is a hexadecimal color.                                                                                                                                                          |\n| `@IsHSL()`                                             | Checks if the string is an HSL color based on [CSS Colors Level 4 specification](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value).                                                       |\n| `@IsRgbColor(options?: IsRgbOptions)`                  | Checks if the string is a rgb or rgba color.                                                                                                                                                          |\n| `@IsIdentityCard(locale?: string)`                     | Checks if the string is a valid identity card code.                                                                                                                                                   |\n| `@IsPassportNumber(countryCode?: string)`              | Checks if the string is a valid passport number relative to a specific country code.                                                                                                                  |\n| `@IsPostalCode(locale?: string)`                       | Checks if the string is a postal code.                                                                                                                                                                |\n| `@IsHexadecimal()`                                     | Checks if the string is a hexadecimal number.                                                                                                                                                         |\n| `@IsOctal()`                                           | Checks if the string is a octal number.                                                                                                                                                               |\n| `@IsMACAddress(options?: IsMACAddressOptions)`         | Checks if the string is a MAC Address.                                                                                                                                                                |\n| `@IsIP(version?: \"4\"\\|\"6\")`                            | Checks if the string is an IP (version 4 or 6).                                                                                                                                                       |\n| `@IsPort()`                                            | Checks if the string is a valid port number.                                                                                                                                                          |\n| `@IsISBN(version?: \"10\"\\|\"13\")`                        | Checks if the string is an ISBN (version 10 or 13).                                                                                                                                                   |\n| `@IsEAN()`                                             | Checks if the string is an if the string is an EAN (European Article Number).                                                                                                                         |\n| `@IsISIN()`                                            | Checks if the string is an ISIN (stock/security identifier).                                                                                                                                          |\n| `@IsISO8601(options?: IsISO8601Options)`               | Checks if the string is a valid ISO 8601 date format. Use the option strict = true for additional checks for a valid date.                                                                            |\n| `@IsJSON()`                                            | Checks if the string is valid JSON.                                                                                                                                                                   |\n| `@IsJWT()`                                             | Checks if the string is valid JWT.                                                                                                                                                                    |\n| `@IsObject()`                                          | Checks if the object is valid Object (null, functions, arrays will return false).                                                                                                                     |\n| `@IsNotEmptyObject()`                                  | Checks if the object is not empty.                                                                                                                                                                    |\n| `@IsLowercase()`                                       | Checks if the string is lowercase.                                                                                                                                                                    |\n| `@IsLatLong()`                                         | Checks if the string is a valid latitude-longitude coordinate in the format lat, long.                                                                                                                |\n| `@IsLatitude()`                                        | Checks if the string or number is a valid latitude coordinate.                                                                                                                                        |\n| `@IsLongitude()`                                       | Checks if the string or number is a valid longitude coordinate.                                                                                                                                       |\n| `@IsMobilePhone(locale: string)`                       | Checks if the string is a mobile phone number.                                                                                                                                                        |\n| `@IsISO6391()`                                         | Checks if the string is a valid ISO 639-1 officially assigned language code.                                                                                                                          |\n| `@IsISO31661Alpha2()`                                  | Checks if the string is a valid ISO 3166-1 alpha-2 officially assigned country code.                                                                                                                  |\n| `@IsISO31661Alpha3()`                                  | Checks if the string is a valid ISO 3166-1 alpha-3 officially assigned country code.                                                                                                                  |\n| `@IsISO31661Numeric()`                                 | Checks if the string is a valid ISO 3166-1 numeric officially assigned country code.                                                                                                                  |\n| `@IsLocale()`                                          | Checks if the string is a locale.                                                                                                                                                                     |\n| `@IsPhoneNumber(region: string)`                       | Checks if the string is a valid phone number using libphonenumber-js.                                                                                                                                 |\n| `@IsMongoId()`                                         | Checks if the string is a valid hex-encoded representation of a MongoDB ObjectId.                                                                                                                     |\n| `@IsMultibyte()`                                       | Checks if the string contains one or more multibyte chars.                                                                                                                                            |\n| `@IsNumberString(options?: IsNumericOptions)`          | Checks if the string is numeric.                                                                                                                                                                      |\n| `@IsSurrogatePair()`                                   | Checks if the string contains any surrogate pairs chars.                                                                                                                                              |\n| `@IsTaxId()`                                           | Checks if the string is a valid tax ID. Default locale is `en-US`.                                                                                                                                    |\n| `@IsUrl(options?: IsURLOptions)`                       | Checks if the string is a URL.                                                                                                                                                                        |\n| `@IsMagnetURI()`                                       | Checks if the string is a [magnet uri format](https://en.wikipedia.org/wiki/Magnet_URI_scheme).                                                                                                       |\n| `@IsUUID(version?: UUIDVersion)`                       | Checks if the string is a UUID (version 1-8, nil, max, loose, all). Also accepts array of versions.                                                                                                   |\n| `@IsFirebasePushId()`                                  | Checks if the string is a [Firebase Push ID](https://firebase.googleblog.com/2015/02/the-2120-ways-to-ensure-unique_68.html)                                                                          |\n| `@IsUppercase()`                                       | Checks if the string is uppercase.                                                                                                                                                                    |\n| `@Length(min: number, max?: number)`                   | Checks if the string's length falls in a range.                                                                                                                                                       |\n| `@MinLength(min: number)`                              | Checks if the string's length is not less than given number.                                                                                                                                          |\n| `@MaxLength(max: number)`                              | Checks if the string's length is not more than given number.                                                                                                                                          |\n| `@Matches(pattern: RegExp, modifiers?: string)`        | Checks if string matches the pattern. Either matches('foo', /foo/i) or matches('foo', 'foo', 'i').                                                                                                    |\n| `@IsMilitaryTime()`                                    | Checks if the string is a valid representation of military time in the format HH:MM.                                                                                                                  |\n| `@IsTimeZone()`                                        | Checks if the string represents a valid IANA time-zone.                                                                                                                                               |\n| `@IsHash(algorithm: string)`                           | Checks if the string is a hash The following types are supported:`md4`, `md5`, `sha1`, `sha256`, `sha384`, `sha512`, `ripemd128`, `ripemd160`, `tiger128`, `tiger160`, `tiger192`, `crc32`, `crc32b`. |\n| `@IsMimeType()`                                        | Checks if the string matches to a valid [MIME type](https://en.wikipedia.org/wiki/Media_type) format                                                                                                  |\n| `@IsSemVer()`                                          | Checks if the string is a Semantic Versioning Specification (SemVer).                                                                                                                                 |\n| `@IsISSN(options?: IsISSNOptions)`                     | Checks if the string is a ISSN.                                                                                                                                                                       |\n| `@IsISRC()`                                            | Checks if the string is a [ISRC](https://en.wikipedia.org/wiki/International_Standard_Recording_Code).                                                                                                |\n| `@IsRFC3339()`                                         | Checks if the string is a valid [RFC 3339](https://tools.ietf.org/html/rfc3339) date.                                                                                                                 |\n| `@IsStrongPassword(options?: IsStrongPasswordOptions)` | Checks if the string is a strong password.                                                                                                                                                            |\n| **Array validation decorators**                        |                                                                                                                                                                                                       |\n| `@ArrayContains(values: any[])`                        | Checks if array contains all values from the given array of values.                                                                                                                                   |\n| `@ArrayNotContains(values: any[])`                     | Checks if array does not contain any of the given values.                                                                                                                                             |\n| `@ArrayNotEmpty()`                                     | Checks if given array is not empty.                                                                                                                                                                   |\n| `@ArrayMinSize(min: number)`                           | Checks if the array's length is greater than or equal to the specified number.                                                                                                                        |\n| `@ArrayMaxSize(max: number)`                           | Checks if the array's length is less or equal to the specified number.                                                                                                                                |\n| `@ArrayUnique(identifier?: (o) => any)`                | Checks if all array's values are unique. Comparison for objects is reference-based. Optional function can be speciefied which return value will be used for the comparsion.                           |\n| **Object validation decorators**                       |\n| `@IsInstance(value: any)`                              | Checks if the property is an instance of the passed value.                                                                                                                                            |\n| **Other decorators**                                   |                                                                                                                                                                                                       |\n| `@Allow()`                                             | Prevent stripping off the property when no other constraint is specified for it.                                                                                                                      |\n\n## Defining validation schema without decorators\n\nSchema-based validation without decorators is no longer supported by `class-validator`. This feature was broken in version 0.12 and it will not be fixed. If you are interested in schema-based validation, you can find several such frameworks in [the zod readme's comparison section](https://github.com/colinhacks/zod#comparison).\n\n## Validating plain objects\n\nDue to nature of the decorators, the validated object has to be instantiated using `new Class()` syntax. If you have your class defined using class-validator decorators and you want to validate plain JS object (literal object or returned by JSON.parse), you need to transform it to the class instance via using [class-transformer](https://github.com/pleerock/class-transformer)).\n\n## Samples\n\nTake a look on samples in [./sample](https://github.com/pleerock/class-validator/tree/master/sample) for more examples of\nusages.\n\n## Extensions\n\nThere are several extensions that simplify class-validator integration with other modules or add additional validations:\n\n- [class-validator integration](https://github.com/19majkel94/class-transformer-validator) with [class-transformer](https://github.com/pleerock/class-transformer)\n- [class-validator-rule](https://github.com/yantrab/class-validator-rule)\n- [ngx-dynamic-form-builder](https://github.com/EndyKaufman/ngx-dynamic-form-builder)\n- [abarghoud/ngx-reactive-form-class-validator](https://github.com/abarghoud/ngx-reactive-form-class-validator)\n- [class-validator-extended](https://github.com/pigulla/class-validator-extended)\n\n## Release notes\n\nSee information about breaking changes and release notes [here][3].\n\n[1]: https://github.com/chriso/validator.js\n[2]: https://github.com/pleerock/typedi\n[3]: CHANGELOG.md\n\n## Contributing\n\nFor information about how to contribute to this project, see [TypeStack's general contribution guide](https://github.com/typestack/.github/blob/master/CONTRIBUTING.md).\n"
  },
  {
    "path": "codecov.yml",
    "content": "coverage:\n  range: 70..100\n  round: down\n  precision: 2\n  status:\n    project:\n      default:\n        threshold: 0%\n        paths: \n          - src/**/*.ts\ncomment: off\nignore:\n  - testing/**/*.ts\n  - src/**/*.interface.ts\n"
  },
  {
    "path": "docs/README.md",
    "content": "# Table of Contents\n\n- [Read Me](../README.md)\n- Getting Started\n  - [Installation](introduction/installation.md)\n  - [Usage with Typescript](introduction/usage-with-typescript.md)\n  - [Usage with Javascript](introduction/usage-with-javascript.md)\n  - [Dependency Injection](introduction/usage-with-di.md)\n  - [Core Principes](introduction/core-principes.md)\n- [Basic Usage](basics/README.md)\n  - [Validating objects](basics/validating-objects.md)\n  - [Validating arrays](basics/validating-arrays.md)\n  - [Validating nested objects](basics/validating-nested-objects.md)\n- [Advanced Usage](advanced/README.md)\n  - [Conditional Validation](advanced/conditional-validation.md)\n  - [Validation Groups](advanced/validation-groups.md)\n  - [Inheritance](advanced/inheritance.md)\n  - [Custom Validation Decorators](advanced/validations-decoratos.md)\n  - [Custom Validation Classes](advanced/validation-classes.md)\n- [Decorators Reference](reference/decoratos.md)\n  - [Common Decorators](reference/common-decoratos.md)\n  - [Number Decorators](reference/number-decoratos.md)\n  - [String Decorators](reference/string-decoratos.md)\n  - [Date Decorators](reference/date-decoratos.md)\n  - [Array Decorators](reference/array-decoratos.md)\n- [Recipes](recipes/README.md)\n  - [Simple Validations](https://stackblitz.com/edit/class-transformer-simple-validations)\n  - [Nested Objects](https://stackblitz.com/edit/class-transformer-nested-objects)\n  - [Using Groups](https://stackblitz.com/edit/class-transformer-using-groups)\n  - [Custom Validators](https://stackblitz.com/edit/class-transformer-custom-validator)\n  - [Custom Decorators](https://stackblitz.com/edit/class-transformer-custom-decorators)\n  - [Using Schemas](https://stackblitz.com/edit/class-transformer-schemas)\n  - [Inheritance](https://stackblitz.com/edit/class-transformer-inheritance)\n- [API Reference](api/README.md)\n  - [validate](api/validate.md)\n  - [ValidatorOptions ](api/ValidatorOptions.md)\n  - [ValidationError ](api/ValidationError.md)\n- [Change Log](../CHANGELOG.md)\n"
  },
  {
    "path": "docs/basics/validating-objects.md",
    "content": "# Validating objects\n\n```ts\nimport {\n  validate,\n  validateOrReject,\n  IsString,\n  IsInt,\n  IsDate,\n  MaxLength,\n  Min,\n  Max,\n  ValidationError,\n} from 'class-validator';\n\nexport class Book {\n  @IsString()\n  @MaxLength(255)\n  title: string;\n\n  @IsString()\n  @MaxLength(255)\n  author: string;\n\n  @IsInt()\n  @Min(0)\n  @Max(10)\n  rating: number;\n\n  @IsDate()\n  publishDate: Date;\n}\n\nconst book = new Book();\nbook.title = 'Don Quixote';\nbook.author = 'Miguel De Cervantes';\nbook.rating = 11;\nbook.publishDate = new Date();\n\nvalidate(book).then((errors: ValidationError[]) => {\n  if (errors.length > 0) {\n    console.warn('validate() - Validation failed. Errors: ', errors);\n  }\n});\n\nvalidateOrReject(book).catch((errors: ValidationError[]) => {\n  console.warn('validateOrReject() - Validation failed. Errors: ', errors);\n});\n\nawaitExample();\n\nasync function awaitExample() {\n  try {\n    await validateOrReject(book);\n  } catch (errors) {\n    console.warn('Async validateOrReject() - Validation failed. Errors: ', errors);\n  }\n}\n```\n\nRun this example on [Stackblitz](https://stackblitz.com/edit/class-validator-simple-example-u9h1ve?file=index.ts)\n"
  },
  {
    "path": "docs/introduction/installation.md",
    "content": "# Installation\n\nTo install the stable version:\n\n```\nnpm install --save class-validator\n```\n\n### Usage in the browser\n\nIf you want to use `class-validator` in the browser and you use Webpack then just import it into your project and Webpack will take care of the rest.\n\n### Next version\n\nYou can install the next version of `class-validator` via\n\n```\nnpm install --save class-validator@next\n```\n\n> Note: The next version can break anytime without notice. Do not use this in production.\n"
  },
  {
    "path": "jest.config.js",
    "content": "module.exports = {\r\n  preset: 'ts-jest',\r\n  testEnvironment: 'node',\r\n  collectCoverageFrom: ['src/**/*.ts', '!src/**/index.ts', '!src/**/*.interface.ts'],\r\n  globals: {\r\n    'ts-jest': {\r\n      tsconfig: 'tsconfig.spec.json',\r\n    },\r\n  },\r\n};\r\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"class-validator\",\n  \"version\": \"0.15.1\",\n  \"description\": \"Decorator-based property validation for classes.\",\n  \"author\": \"TypeStack contributors\",\n  \"license\": \"MIT\",\n  \"sideEffects\": false,\n  \"main\": \"./cjs/index.js\",\n  \"module\": \"./esm5/index.js\",\n  \"es2015\": \"./esm2015/index.js\",\n  \"typings\": \"./types/index.d.ts\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/typestack/class-validator.git\"\n  },\n  \"tags\": [\n    \"validator\",\n    \"validation\",\n    \"decorators\",\n    \"typescript\"\n  ],\n  \"scripts\": {\n    \"build\": \"npm run build:cjs\",\n    \"build:clean\": \"rimraf build\",\n    \"build:es2015\": \"tsc --project tsconfig.prod.esm2015.json\",\n    \"build:esm5\": \"tsc --project tsconfig.prod.esm5.json\",\n    \"build:cjs\": \"tsc --project tsconfig.prod.cjs.json\",\n    \"build:umd\": \"rollup --config rollup.config.js\",\n    \"build:types\": \"tsc --project tsconfig.prod.types.json\",\n    \"prettier:fix\": \"prettier --write \\\"**/*.{ts,md}\\\"\",\n    \"prettier:check\": \"prettier --check \\\"**/*.{ts,md}\\\"\",\n    \"lint:fix\": \"eslint --max-warnings 0 --fix --ext .ts src/\",\n    \"lint:check\": \"eslint --max-warnings 0 --ext .ts src/\",\n    \"test\": \"jest --coverage --verbose\",\n    \"test:watch\": \"jest --watch\",\n    \"test:ci\": \"jest --runInBand --no-cache --coverage --verbose\"\n  },\n  \"dependencies\": {\n    \"@types/validator\": \"^13.15.3\",\n    \"libphonenumber-js\": \"^1.11.1\",\n    \"validator\": \"^13.15.22\"\n  },\n  \"devDependencies\": {\n    \"@rollup/plugin-commonjs\": \"^25.0.7\",\n    \"@rollup/plugin-node-resolve\": \"^15.2.3\",\n    \"@types/jest\": \"^29.5.12\",\n    \"@types/node\": \"^20.12.10\",\n    \"@typescript-eslint/eslint-plugin\": \"^5.62.0\",\n    \"@typescript-eslint/parser\": \"^5.62.0\",\n    \"eslint\": \"^8.57.0\",\n    \"eslint-config-prettier\": \"^9.1.0\",\n    \"eslint-plugin-jest\": \"^27.9.0\",\n    \"husky\": \"^4.3.8\",\n    \"jest\": \"^29.7.0\",\n    \"lint-staged\": \"^15.2.2\",\n    \"prettier\": \"^2.8.8\",\n    \"reflect-metadata\": \"0.2.2\",\n    \"rimraf\": \"5.0.5\",\n    \"rollup\": \"^2.79.1\",\n    \"rollup-plugin-terser\": \"^7.0.2\",\n    \"ts-jest\": \"^29.1.2\",\n    \"ts-node\": \"^10.9.2\",\n    \"typescript\": \"^5.4.5\"\n  }\n}\n"
  },
  {
    "path": "rollup.config.js",
    "content": "import { nodeResolve } from '@rollup/plugin-node-resolve';\nimport commonjs from '@rollup/plugin-commonjs';\nimport { terser } from 'rollup-plugin-terser';\n\nexport default {\n  input: 'build/esm5/index.js',\n  output: [\n    {\n      name: 'ClassValidator',\n      format: 'umd',\n      file: 'build/bundles/class-validator.umd.js',\n      sourcemap: true,\n    },\n    {\n      name: 'ClassValidator',\n      format: 'umd',\n      file: 'build/bundles/class-validator.umd.min.js',\n      sourcemap: true,\n      plugins: [terser()],\n    },\n  ],\n  plugins: [commonjs(), nodeResolve()],\n};\n"
  },
  {
    "path": "sample/sample1-simple-validation/Post.ts",
    "content": "import {\n  Contains,\n  IsInt,\n  MinLength,\n  MaxLength,\n  IsEmail,\n  IsFQDN,\n  IsDate,\n  ArrayNotEmpty,\n  ArrayMinSize,\n  ArrayMaxSize,\n  IsEnum,\n} from '../../src/decorator/decorators';\n\nexport enum PostType {\n  Public,\n  Private,\n}\n\nexport class Post {\n  @MinLength(10)\n  @MaxLength(20)\n  title: string;\n\n  @Contains('hello')\n  text: string;\n\n  @IsInt()\n  rating: number;\n\n  @IsEmail()\n  email: string;\n\n  @IsFQDN()\n  site: string;\n\n  @IsDate()\n  createDate: Date;\n\n  @ArrayNotEmpty()\n  @ArrayMinSize(2)\n  @ArrayMaxSize(5)\n  @MinLength(3, { each: true, message: 'Tag is too short. Minimal length is $value characters' })\n  @MaxLength(50, { each: true, message: 'Tag is too long. Maximal length is $value characters' })\n  tags: string[];\n\n  @IsEnum(PostType)\n  type: PostType;\n}\n"
  },
  {
    "path": "sample/sample1-simple-validation/app.ts",
    "content": "import { validate } from '../../src/index';\nimport { Post, PostType } from './Post';\n\n// Sample1. simple validation\n\nlet post1 = new Post();\npost1.title = 'Hello world'; // should pass\npost1.text = 'this is a great post about hello world'; // should pass\npost1.rating = 10; // should pass\npost1.email = 'info@google.com'; // should pass\npost1.site = 'google.com'; // should pass\npost1.createDate = new Date(); // should pass\npost1.tags = ['abcd1', 'abcd2', 'abcd3', 'abcd4', 'abcd4']; // should pass\npost1.type = PostType.Private;\n\nvalidate(post1).then(result => {\n  console.log('1. should pass: ', result); // should pass completely, e.g. return empty array\n});\n\nlet post2 = new Post();\npost2.title = 'Hello'; // should not pass\npost2.text = 'this is a great post about hell world'; // should not pass\npost2.rating = 1.1; // should not pass\npost2.email = 'google.com'; // should not pass\npost2.site = 'googlecom'; // should not pass\npost2.type = PostType.Private; // should pass\n\n// should not pass because date property is missing\nvalidate(post2).then(result => {\n  console.log('2. should not pass: ', result); // should not pass completely, must return array of ValidationError-s\n});\n\n// Sample2. using validation options to skip properties that are not defined\n\nlet post3 = new Post();\npost3.title = 'Hello'; // should not pass\npost3.text = 'this is a great post about hell world'; // should not pass\npost3.rating = 1.1; // should not pass\npost3.email = 'google.com'; // should not pass\npost3.site = 'googlecom'; // should not pass\npost3.type = PostType.Private;\n\nvalidate(post3, { skipMissingProperties: true }).then(result => {\n  console.log('3. should not pass: ', result); // should not pass, but returned ValidationError-s should not have error about date field\n});\n\nlet post4 = new Post();\npost4.title = 'Hello world'; // should pass\npost4.text = 'this is a great post about hello world'; // should pass\npost4.rating = 10; // should pass\npost4.email = 'info@google.com'; // should pass\npost4.site = 'google.com'; // should pass\npost4.type = PostType.Private;\n\nvalidate(post4, { skipMissingProperties: true }).then(result => {\n  console.log('4. should pass: ', result); // should pass even if date is not set\n});\n\n// Sample3. using validation groups\n\nlet post5 = new Post();\npost5.title = 'Hello world'; // should pass\npost5.text = 'this is a great post about hello world'; // should pass\npost5.rating = 10; // should pass\npost5.email = 'info@google.com'; // should pass\npost5.site = 'google.com'; // should pass\npost5.type = PostType.Private;\n\nvalidate(post5, { skipMissingProperties: true }).then(result => {\n  console.log('5. should pass: ', result); // should pass even if date is not set\n});\n\n// Sample4. array validation\n\nlet post6 = new Post();\npost6.title = 'Hello world'; // should pass\npost6.text = 'this is a great post about hello world'; // should pass\npost6.rating = 10; // should pass\npost6.email = 'info@google.com'; // should pass\npost6.site = 'google.com'; // should pass\npost6.createDate = new Date(); // should pass\npost6.tags = ['abcd1', 'abcd2', 'abcd3', 'abcd4', 'abcd4'];\npost6.type = PostType.Private;\n\nvalidate(post6).then(result => {\n  console.log('6. should pass: ', result); // should pass completely, e.g. return empty array\n});\n\nlet post7 = new Post();\npost7.title = 'Hello world'; // should pass\npost7.text = 'this is a great post about hello world'; // should pass\npost7.rating = 10; // should pass\npost7.email = 'info@google.com'; // should pass\npost7.site = 'google.com'; // should pass\npost7.createDate = new Date(); // should pass\npost7.tags = ['news', 'a'];\npost7.type = PostType.Private;\n\nvalidate(post7).then(result => {\n  console.log('7. should not pass: ', result); // should not pass\n});\n\nlet post8 = new Post();\npost8.title = 'Hello world'; // should pass\npost8.text = 'this is a great post about hello world'; // should pass\npost8.rating = 10; // should pass\npost8.email = 'info@google.com'; // should pass\npost8.site = 'google.com'; // should pass\npost8.createDate = new Date(); // should pass\npost8.tags = [];\npost8.type = PostType.Private;\n\nvalidate(post8).then(result => {\n  console.log('8. should not pass: ', result); // should not pass\n});\n\nlet post9 = new Post();\npost9.title = 'Hello world'; // should pass\npost9.text = 'this is a great post about hello world'; // should pass\npost9.rating = 10; // should pass\npost9.email = 'info@google.com'; // should pass\npost9.site = 'google.com'; // should pass\npost9.createDate = new Date(); // should pass\npost9.tags = ['abcd1', 'abcd2', 'abcd3', 'abcd4', 'abcd4', 'abcd4'];\npost9.type = PostType.Private;\n\nvalidate(post9).then(result => {\n  console.log('9. should not pass: ', result); // should not pass\n});\n\nlet post10 = new Post();\npost10.title = 'Hello world'; // should pass\npost10.text = 'this is a great post about hello world'; // should pass\npost10.rating = 10; // should pass\npost10.email = 'info@google.com'; // should pass\npost10.site = 'google.com'; // should pass\npost10.createDate = new Date(); // should pass\npost10.tags = ['abcd1', 'abcd2', 'abcd3', 'abcd4', 'abcd4'];\npost10.type = PostType.Private;\n\nvalidate(post10).then(result => {\n  console.log('10. should pass: ', result); // should pass\n});\n\nlet post11 = new Post();\npost11.title = 'Hello world'; // should pass\npost11.text = 'this is a great post about hello world'; // should pass\npost11.rating = 10; // should pass\npost11.email = 'info@google.com'; // should pass\npost11.site = 'google.com'; // should pass\npost11.createDate = new Date(); // should pass\npost11.tags = null;\npost11.type = PostType.Private;\n\nvalidate(post11).then(result => {\n  console.log('11. should not pass: ', result); // should not pass\n});\n\nlet post12 = new Post();\npost12.title = 'Hello world'; // should pass\npost12.text = 'this is a great post about hello world'; // should pass\npost12.rating = 10; // should pass\npost12.email = 'info@google.com'; // should pass\npost12.site = 'google.com'; // should pass\npost12.createDate = new Date(); // should pass\npost12.tags = ['abcd1', 'abcd2', 'abcd3', 'abcd4', 'abcd4']; // should pass\npost12.type = 99; // should not pass\n\nvalidate(post1).then(result => {\n  console.log('12. should not pass: ', result); // should not pass as type is not a valid enum\n});\n"
  },
  {
    "path": "sample/sample2-using-groups/Post.ts",
    "content": "import { Contains, IsInt, Length, IsEmail, IsFQDN, IsDate } from '../../src/decorator/decorators';\n\nexport class Post {\n  @Length(10, 20, {\n    message: 'Incorrect length!',\n    groups: ['users', 'moderators'],\n  })\n  @Length(0, 20, {\n    message: 'Incorrect length!',\n    groups: ['admins'],\n  })\n  title: string;\n\n  @Contains('hello', {\n    message: 'It should contain word \"hello!\"',\n    groups: ['users', 'moderators'],\n  })\n  text: string;\n\n  @IsInt()\n  rating: number;\n\n  @IsEmail(undefined, {\n    always: true,\n  })\n  email: string;\n\n  @IsFQDN(undefined, {\n    message: 'Site address should be correct',\n    groups: ['users'],\n  })\n  site: string;\n\n  @IsDate()\n  createDate: Date;\n}\n"
  },
  {
    "path": "sample/sample2-using-groups/app.ts",
    "content": "import { Validator } from '../../src/validation/Validator';\nimport { Post } from './Post';\n\nlet validator = new Validator();\n\nlet post1 = new Post();\npost1.title = 'Hello world'; // should pass\npost1.text = 'this is a great post about hello world'; // should pass\npost1.rating = 10; // should pass\npost1.email = 'info@google.com'; // should pass\npost1.site = 'google.com'; // should pass\npost1.createDate = new Date(); // should pass\n\nvalidator.validate(post1, { groups: ['users'] }).then(result => {\n  console.log('1.1. should pass: ', result);\n});\n\nvalidator.validate(post1, { groups: ['admins'] }).then(result => {\n  console.log('1.2. should pass: ', result);\n});\n\nlet post2 = new Post();\npost2.title = 'Hi!'; // should not pass for user or moderator, but should pass for admin\npost2.text = 'this is a great post about hello world'; // should pass\npost2.rating = 10; // should pass\npost2.email = 'info@google.com'; // should pass\npost2.site = 'google.com'; // should pass\npost2.createDate = new Date(); // should pass\n\nvalidator.validate(post2, { groups: ['users'] }).then(result => {\n  console.log('2.1. should not pass: ', result);\n});\n\nvalidator.validate(post2, { groups: ['moderators'] }).then(result => {\n  console.log('2.2. should not pass: ', result);\n});\n\nvalidator.validate(post2, { groups: ['admins'] }).then(result => {\n  console.log('2.3. should pass: ', result);\n});\n\nvalidator.validate(post2, { groups: ['users', 'admins'] }).then(result => {\n  console.log('2.4. should not pass: ', result);\n});\n\nlet post3 = new Post();\npost3.title = 'Hello world'; // should not pass for user or moderator, but should pass for admin\npost3.text = 'this is a great post about hello world'; // should pass\npost3.rating = 10; // should pass\npost3.email = 'info@google.com'; // should pass\npost3.site = 'google.com'; // should pass\n// note that we dont set date\n\nvalidator.validate(post3, { groups: ['users'] }).then(result => {\n  console.log('3.1. should pass: ', result);\n});\n\nvalidator.validate(post3).then(result => {\n  console.log('3.2. should not pass: ', result);\n});\n\nlet post4 = new Post();\npost4.title = 'Hello world'; // should not pass for user or moderator, but should pass for admin\npost4.text = 'this is a great post about hello world'; // should pass\npost4.rating = 10; // should pass\npost4.email = ''; // should not pass\npost4.site = 'google.com'; // should pass\n// note that we dont set date\n\nvalidator.validate(post4, { groups: ['users'] }).then(result => {\n  console.log('4.1. should not pass: ', result);\n});\n\nvalidator.validate(post4).then(result => {\n  console.log('4.2. should not pass: ', result);\n});\n"
  },
  {
    "path": "sample/sample3-nested-objects/Post.ts",
    "content": "import { Contains, IsInt, Length, IsEmail, IsFQDN, IsDate, ValidateNested } from '../../src/decorator/decorators';\nimport { Tag } from './Tag';\n\nexport class Post {\n  @Length(10, 20, {\n    message: 'Incorrect length!',\n  })\n  title: string;\n\n  @ValidateNested()\n  tags: Tag[];\n}\n"
  },
  {
    "path": "sample/sample3-nested-objects/Tag.ts",
    "content": "import { Contains, IsInt, Length, IsEmail, IsFQDN, IsDate } from '../../src/decorator/decorators';\n\nexport class Tag {\n  @Length(10, 20, {\n    message: 'Tag is too short or long',\n  })\n  name: string;\n}\n"
  },
  {
    "path": "sample/sample3-nested-objects/app.ts",
    "content": "import { Validator } from '../../src/validation/Validator';\nimport { Post } from './Post';\nimport { Tag } from './Tag';\n\nlet validator = new Validator();\n\nlet tag1 = new Tag();\ntag1.name = 'ja';\n\nlet tag2 = new Tag();\ntag2.name = 'node.js';\n\nlet post1 = new Post();\npost1.title = 'Hello world';\npost1.tags = [tag1, tag2];\n\nvalidator.validate(post1).then(result => {\n  console.log('1. should not pass: ', result);\n});\n"
  },
  {
    "path": "sample/sample4-custom-validator/CustomTextLength.ts",
    "content": "import { ValidatorConstraintInterface } from '../../src/validation/ValidatorConstraintInterface';\nimport { ValidatorConstraint } from '../../src/decorator/decorators';\n\n@ValidatorConstraint()\nexport class CustomTextLength implements ValidatorConstraintInterface {\n  validate(text: string) {\n    return text.length > 1 && text.length < 10;\n  }\n}\n"
  },
  {
    "path": "sample/sample4-custom-validator/Post.ts",
    "content": "import {\n  Contains,\n  IsInt,\n  MinLength,\n  MaxLength,\n  IsEmail,\n  IsFQDN,\n  IsDate,\n  IsNotEmpty,\n  ArrayNotEmpty,\n  ArrayMinSize,\n  ArrayMaxSize,\n} from '../../src/decorator/decorators';\nimport { Validate } from '../../src/decorator/decorators';\nimport { CustomTextLength } from './CustomTextLength';\n\nexport class Post {\n  @Validate(CustomTextLength, {\n    message: 'Wrong post title',\n  })\n  title: string;\n}\n"
  },
  {
    "path": "sample/sample4-custom-validator/app.ts",
    "content": "import { Validator } from '../../src/validation/Validator';\nimport { Post } from './Post';\n\nlet validator = new Validator();\n\nlet post1 = new Post();\npost1.title = 'Hello world';\n\nvalidator.validate(post1).then(result => {\n  console.log('1. should not pass: ', result);\n});\n\nlet post2 = new Post();\npost2.title = 'Hello !!!';\n\nvalidator.validate(post2).then(result => {\n  console.log('2. should pass: ', result);\n});\n"
  },
  {
    "path": "sample/sample5-schemas/Post.ts",
    "content": "export class Post {\n  title: string;\n  text: string;\n  rating: number;\n  email: string;\n  site: string;\n  createDate: Date;\n  tags: string[];\n}\n"
  },
  {
    "path": "sample/sample5-schemas/app.ts",
    "content": "import { validate, registerSchema } from '../../src/index';\nimport { Post } from './Post';\n\n// load schema. we load it a bit tricky way because we output source code into separate directory, so our json resource left in another directory\nconst postSchema = require(__dirname + '/../../../../sample/sample5-schemas/post.json');\n\n// register this schema\nregisterSchema(postSchema);\n\n// Sample1. simple validation\n\nlet post1 = new Post();\npost1.title = 'Hello world'; // should pass\npost1.text = 'this is a great post about hello world'; // should pass\npost1.rating = 10; // should pass\npost1.email = 'info@google.com'; // should pass\npost1.site = 'google.com'; // should pass\npost1.createDate = new Date(); // should pass\npost1.tags = ['abcd1', 'abcd2', 'abcd3', 'abcd4', 'abcd4']; // should pass\n\nvalidate('post', post1).then(result => {\n  console.log('1. should pass: ', result); // should pass completely, e.g. return empty array\n});\n\nlet post2 = new Post();\npost2.title = 'Hello'; // should not pass\npost2.text = 'this is a great post about hell world'; // should not pass\npost2.rating = 11; // should not pass\npost2.email = 'google.com'; // should not pass\npost2.site = 'googlecom'; // should not pass\n// should not pass because date property is missing\n\nvalidate('post', post2).then(result => {\n  console.log('2. should not pass: ', result); // should not pass completely, must return array of ValidationError-s\n});\n\n// Sample2. using validation options to skip properties that are not defined\n\nlet post3 = new Post();\npost3.title = 'Hello'; // should not pass\npost3.text = 'this is a great post about hell world'; // should not pass\npost3.rating = 11; // should not pass\npost3.email = 'google.com'; // should not pass\npost3.site = 'googlecom'; // should not pass\n\nvalidate('post', post3, { skipMissingProperties: true }).then(result => {\n  console.log('3. should not pass: ', result); // should not pass, but returned ValidationError-s should not have error about date field\n});\n\nlet post4 = new Post();\npost4.title = 'Hello world'; // should pass\npost4.text = 'this is a great post about hello world'; // should pass\npost4.rating = 10; // should pass\npost4.email = 'info@google.com'; // should pass\npost4.site = 'google.com'; // should pass\n\nvalidate('post', post4, { skipMissingProperties: true }).then(result => {\n  console.log('4. should pass: ', result); // should pass even if date is not set\n});\n\n// Sample3. using validation groups\n\nlet post5 = new Post();\npost5.title = 'Hello world'; // should pass\npost5.text = 'this is a great post about hello world'; // should pass\npost5.rating = 10; // should pass\npost5.email = 'info@google.com'; // should pass\npost5.site = 'google.com'; // should pass\n\nvalidate('post', post5, { skipMissingProperties: true }).then(result => {\n  console.log('5. should pass: ', result); // should pass even if date is not set\n});\n\n// Sample4. array validation\n\nlet post6 = new Post();\npost6.title = 'Hello world'; // should pass\npost6.text = 'this is a great post about hello world'; // should pass\npost6.rating = 10; // should pass\npost6.email = 'info@google.com'; // should pass\npost6.site = 'google.com'; // should pass\npost6.createDate = new Date(); // should pass\npost6.tags = ['abcd1', 'abcd2', 'abcd3', 'abcd4', 'abcd4'];\n\nvalidate('post', post6).then(result => {\n  console.log('6. should pass: ', result); // should pass completely, e.g. return empty array\n});\n\nlet post7 = new Post();\npost7.title = 'Hello world'; // should pass\npost7.text = 'this is a great post about hello world'; // should pass\npost7.rating = 10; // should pass\npost7.email = 'info@google.com'; // should pass\npost7.site = 'google.com'; // should pass\npost7.createDate = new Date(); // should pass\npost7.tags = ['news', 'a'];\n\nvalidate('post', post7).then(result => {\n  console.log('7. should not pass: ', result); // should not pass\n});\n\nlet post8 = new Post();\npost8.title = 'Hello world'; // should pass\npost8.text = 'this is a great post about hello world'; // should pass\npost8.rating = 10; // should pass\npost8.email = 'info@google.com'; // should pass\npost8.site = 'google.com'; // should pass\npost8.createDate = new Date(); // should pass\npost8.tags = [];\n\nvalidate('post', post8).then(result => {\n  console.log('8. should not pass: ', result); // should not pass\n});\n\nlet post9 = new Post();\npost9.title = 'Hello world'; // should pass\npost9.text = 'this is a great post about hello world'; // should pass\npost9.rating = 10; // should pass\npost9.email = 'info@google.com'; // should pass\npost9.site = 'google.com'; // should pass\npost9.createDate = new Date(); // should pass\npost9.tags = ['a', 'abcd1', 'abcd2', 'abcd3', 'abcd4', 'abcd4', 'abcd4'];\n\nvalidate('post', post9).then(result => {\n  console.log('9. should not pass: ', result); // should not pass\n});\n\nlet post10 = new Post();\npost10.title = 'Hello world'; // should pass\npost10.text = 'this is a great post about hello world'; // should pass\npost10.rating = 10; // should pass\npost10.email = 'info@google.com'; // should pass\npost10.site = 'google.com'; // should pass\npost10.createDate = new Date(); // should pass\npost10.tags = ['abcd1', 'abcd2', 'abcd3', 'abcd4', 'abcd4'];\n\nvalidate('post', post10).then(result => {\n  console.log('10. should pass: ', result); // should pass\n});\n\nlet post11 = new Post();\npost11.title = 'Hello world'; // should pass\npost11.text = 'this is a great post about hello world'; // should pass\npost11.rating = 10; // should pass\npost11.email = 'info@google.com'; // should pass\npost11.site = 'google.com'; // should pass\npost11.createDate = new Date(); // should pass\npost11.tags = null;\n\nvalidate('post', post11).then(result => {\n  console.log('11. should not pass: ', result); // should not pass\n});\n"
  },
  {
    "path": "sample/sample5-schemas/post.json",
    "content": "{\n  \"name\": \"post\",\n  \"properties\": {\n    \"title\": [{\n      \"type\": \"minLength\",\n      \"constraints\": [10]\n    },\n    {\n      \"type\": \"maxLength\",\n      \"constraints\": [20]\n    }],\n    \"text\": [{\n      \"type\": \"contains\",\n      \"constraints\": [\"hello\"]\n    }],\n    \"rating\": [{\n      \"type\": \"isInt\"\n    }],\n    \"email\": [{\n      \"type\": \"isEmail\"\n    }],\n    \"site\": [{\n      \"type\": \"isFqdn\"\n    }],\n    \"createDate\": [{\n      \"type\": \"isDate\"\n    }],\n    \"tags\": [{\n      \"type\": \"arrayNotEmpty\"\n    },\n    {\n      \"type\": \"arrayMinSize\",\n      \"constraints\": [2]\n    },\n    {\n      \"type\": \"arrayMaxSize\",\n      \"constraints\": [5]\n    },\n    {\n      \"type\": \"minLength\",\n      \"each\": true,\n      \"constraints\": [3],\n      \"message\": \"Tag is too short. Minimal length is $constraint1 characters\"\n    },\n    {\n      \"type\": \"maxLength\",\n      \"each\": true,\n      \"constraints\": [50],\n      \"message\": \"Tag is too long. Maximal length is $constraint1 characters\"\n    }]\n  }\n}"
  },
  {
    "path": "sample/sample6-custom-decorator/IsLongerThan.ts",
    "content": "import { registerDecorator } from '../../src/index';\nimport { ValidationOptions } from '../../src/decorator/ValidationOptions';\nimport { ValidatorConstraintInterface } from '../../src/validation/ValidatorConstraintInterface';\nimport { ValidatorConstraint } from '../../src/decorator/decorators';\nimport { ValidationArguments } from '../../src/validation/ValidationArguments';\n\nexport function IsLongerThan(property: string, validationOptions?: ValidationOptions) {\n  return function (object: Object, propertyName: string) {\n    registerDecorator({\n      target: object.constructor,\n      propertyName: propertyName,\n      options: validationOptions,\n      constraints: [property],\n      validator: IsLongerThanConstraint,\n    });\n  };\n}\n\n@ValidatorConstraint({ name: 'isLongerThan' })\nexport class IsLongerThanConstraint implements ValidatorConstraintInterface {\n  validate(value: any, args: ValidationArguments) {\n    const [relatedPropertyName] = args.constraints;\n    const relatedValue = (args.object as any)[relatedPropertyName];\n    return typeof value === 'string' && typeof relatedValue === 'string' && value.length > relatedValue.length;\n  }\n}\n"
  },
  {
    "path": "sample/sample6-custom-decorator/IsUserAlreadyExist.ts",
    "content": "import { registerDecorator } from '../../src/index';\nimport { ValidationOptions } from '../../src/decorator/ValidationOptions';\nimport { ValidationArguments } from '../../src/validation/ValidationArguments';\n\nexport function IsUserAlreadyExist(validationOptions?: ValidationOptions) {\n  return function (object: Object, propertyName: string) {\n    registerDecorator({\n      name: 'isUserAlreadyExist',\n      async: true,\n      target: object.constructor,\n      propertyName: propertyName,\n      options: validationOptions,\n      validator: {\n        validate(value: any, args: ValidationArguments) {\n          return new Promise(ok => {\n            if (value !== 'admin' && value !== 'user') {\n              ok(true);\n            } else {\n              ok(false);\n            }\n          });\n        },\n      },\n    });\n  };\n}\n"
  },
  {
    "path": "sample/sample6-custom-decorator/User.ts",
    "content": "import { IsUserAlreadyExist } from './IsUserAlreadyExist';\nimport { IsLongerThan } from './IsLongerThan';\n\nexport class User {\n  @IsUserAlreadyExist({\n    message: 'User with name $value already exists',\n  })\n  firstName: string;\n\n  @IsLongerThan('firstName', {\n    message: \"User's last name must be longer than firstName\",\n  })\n  lastName: string;\n}\n"
  },
  {
    "path": "sample/sample6-custom-decorator/app.ts",
    "content": "import { Validator } from '../../src/validation/Validator';\nimport { User } from './User';\n\nlet validator = new Validator();\n\nlet user1 = new User();\nuser1.firstName = 'Umed';\n\nvalidator.validate(user1, { skipMissingProperties: true }).then(result => {\n  console.log('1. should pass: ', result);\n});\n\nlet user2 = new User();\nuser2.firstName = 'admin';\n\nvalidator.validate(user2, { skipMissingProperties: true }).then(result => {\n  console.log('2. should not pass: ', result);\n});\n\nlet user3 = new User();\nuser3.firstName = 'user';\n\nvalidator.validate(user3, { skipMissingProperties: true }).then(result => {\n  console.log('3. should not pass: ', result);\n});\n\nlet user4 = new User();\nuser4.firstName = 'Zak';\nuser4.lastName = 'Henry';\n\nvalidator.validate(user4).then(result => {\n  console.log('4. should pass: ', result);\n});\n\nlet user5 = new User();\nuser5.firstName = 'Henry';\nuser5.lastName = 'Zak';\n\nvalidator.validate(user5).then(result => {\n  console.log('5. should not pass: ', result);\n});\n"
  },
  {
    "path": "sample/sample7-inheritance-support/BaseContent.ts",
    "content": "import { IsEmail } from '../../src/decorator/decorators';\n\nexport class BaseContent {\n  @IsEmail()\n  email: string;\n}\n"
  },
  {
    "path": "sample/sample7-inheritance-support/Post.ts",
    "content": "import { Contains, IsInt, MinLength, MaxLength } from '../../src/decorator/decorators';\nimport { BaseContent } from './BaseContent';\n\nexport class Post extends BaseContent {\n  @MinLength(10)\n  @MaxLength(20)\n  title: string;\n\n  @Contains('hello')\n  text: string;\n\n  @IsInt()\n  rating: number;\n}\n"
  },
  {
    "path": "sample/sample7-inheritance-support/app.ts",
    "content": "import { validate } from '../../src/index';\nimport { Post } from './Post';\n\n// Sample1. simple validation\n\nlet post1 = new Post();\npost1.title = 'Hello world'; // should pass\npost1.text = 'this is a great post about hello world'; // should pass\npost1.rating = 10; // should pass\npost1.email = '@google.com'; // should not pass\n\nvalidate(post1).then(result => {\n  console.log('1. should not pass: ', result); // should not pass completely\n});\n"
  },
  {
    "path": "sample/sample8-es6-maps/Post.ts",
    "content": "import { Contains, IsInt, Length, IsEmail, IsFQDN, IsDate, ValidateNested } from '../../src/decorator/decorators';\nimport { Tag } from './Tag';\n\nexport class Post {\n  @Length(10, 20, {\n    message: 'Incorrect length!',\n  })\n  title: string;\n\n  @ValidateNested()\n  tags: Map<string, Tag>;\n}\n"
  },
  {
    "path": "sample/sample8-es6-maps/Tag.ts",
    "content": "import { Contains, IsInt, Length, IsEmail, IsFQDN, IsDate } from '../../src/decorator/decorators';\n\nexport class Tag {\n  @Length(10, 20, {\n    message: 'Tag value is too short or long',\n  })\n  value: string;\n}\n"
  },
  {
    "path": "sample/sample8-es6-maps/app.ts",
    "content": "import { Validator } from '../../src/validation/Validator';\nimport { Post } from './Post';\nimport { Tag } from './Tag';\n\nlet validator = new Validator();\n\nlet tag1 = new Tag();\ntag1.value = 'ja';\n\nlet tag2 = new Tag();\ntag2.value = 'node.js';\n\nlet post1 = new Post();\npost1.title = 'Hello world';\npost1.tags = new Map();\npost1.tags.set('tag1', tag1);\npost1.tags.set('tag2', tag2);\n\nvalidator.validate(post1).then(result => {\n  console.log('1. should not pass: ', result);\n});\n"
  },
  {
    "path": "sample/sample9-es6-sets/Post.ts",
    "content": "import { Contains, IsInt, Length, IsEmail, IsFQDN, IsDate, ValidateNested } from '../../src/decorator/decorators';\nimport { Tag } from './Tag';\n\nexport class Post {\n  @Length(10, 20, {\n    message: 'Incorrect length!',\n  })\n  title: string;\n\n  @ValidateNested()\n  tags: Set<Tag>;\n}\n"
  },
  {
    "path": "sample/sample9-es6-sets/Tag.ts",
    "content": "import { Contains, IsInt, Length, IsEmail, IsFQDN, IsDate } from '../../src/decorator/decorators';\n\nexport class Tag {\n  @Length(10, 20, {\n    message: 'Tag value is too short or long',\n  })\n  value: string;\n}\n"
  },
  {
    "path": "sample/sample9-es6-sets/app.ts",
    "content": "import { Validator } from '../../src/validation/Validator';\nimport { Post } from './Post';\nimport { Tag } from './Tag';\n\nlet validator = new Validator();\n\nlet tag1 = new Tag();\ntag1.value = 'ja';\n\nlet tag2 = new Tag();\ntag2.value = 'node.js';\n\nlet post1 = new Post();\npost1.title = 'Hello world';\npost1.tags = new Set();\npost1.tags.add(tag1);\npost1.tags.add(tag2);\n\nvalidator.validate(post1).then(result => {\n  console.log('1. should not pass: ', result);\n});\n"
  },
  {
    "path": "src/container.ts",
    "content": "/**\n * Container options.\n */\nexport interface UseContainerOptions {\n  /**\n   * If set to true, then default container will be used in the case if given container haven't returned anything.\n   */\n  fallback?: boolean;\n\n  /**\n   * If set to true, then default container will be used in the case if given container thrown an exception.\n   */\n  fallbackOnErrors?: boolean;\n}\n\n/**\n * Container to be used by this library for inversion control. If container was not implicitly set then by default\n * container simply creates a new instance of the given class.\n */\nconst defaultContainer: { get<T>(someClass: { new (...args: any[]): T } | Function): T } = new (class {\n  private instances: { type: Function; object: any }[] = [];\n  get<T>(someClass: { new (...args: any[]): T }): T {\n    let instance = this.instances.find(instance => instance.type === someClass);\n    if (!instance) {\n      instance = { type: someClass, object: new someClass() };\n      this.instances.push(instance);\n    }\n\n    return instance.object;\n  }\n})();\n\nlet userContainer: { get<T>(someClass: { new (...args: any[]): T } | Function): T };\nlet userContainerOptions: UseContainerOptions;\n\n/**\n * Sets container to be used by this library.\n */\nexport function useContainer(iocContainer: { get(someClass: any): any }, options?: UseContainerOptions): void {\n  userContainer = iocContainer;\n  userContainerOptions = options;\n}\n\n/**\n * Gets the IOC container used by this library.\n */\nexport function getFromContainer<T>(someClass: { new (...args: any[]): T } | Function): T {\n  if (userContainer) {\n    try {\n      const instance = userContainer.get(someClass);\n      if (instance) return instance;\n\n      if (!userContainerOptions || !userContainerOptions.fallback) return instance;\n    } catch (error) {\n      if (!userContainerOptions || !userContainerOptions.fallbackOnErrors) throw error;\n    }\n  }\n  return defaultContainer.get<T>(someClass);\n}\n"
  },
  {
    "path": "src/decorator/ValidationOptions.ts",
    "content": "import { ValidationArguments } from '../validation/ValidationArguments';\n\n/**\n * Options used to pass to validation decorators.\n */\nexport interface ValidationOptions {\n  /**\n   * Specifies if validated value is an array and each of its items must be validated.\n   */\n  each?: boolean;\n\n  /**\n   * Error message to be used on validation fail.\n   * Message can be either string or a function that returns a string.\n   */\n  message?: string | ((validationArguments: ValidationArguments) => string);\n\n  /**\n   * Validation groups used for this validation.\n   */\n  groups?: string[];\n\n  /**\n   * Indicates if validation must be performed always, no matter of validation groups used.\n   */\n  always?: boolean;\n\n  /*\n   * A transient set of data passed through to the validation result for response mapping\n   */\n  context?: any;\n\n  /**\n   * validation will be performed while the result is true\n   */\n  validateIf?: (object: any, value: any) => boolean;\n}\n\nexport function isValidationOptions(val: any): val is ValidationOptions {\n  if (!val) {\n    return false;\n  }\n  return (\n    'each' in val || 'message' in val || 'groups' in val || 'always' in val || 'context' in val || 'validateIf' in val\n  );\n}\n"
  },
  {
    "path": "src/decorator/array/ArrayContains.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const ARRAY_CONTAINS = 'arrayContains';\n\n/**\n * Checks if array contains all values from the given array of values.\n * If null or undefined is given then this function returns false.\n */\nexport function arrayContains(array: unknown, values: any[]): boolean {\n  if (!Array.isArray(array)) return false;\n\n  return values.every(value => array.indexOf(value) !== -1);\n}\n\n/**\n * Checks if array contains all values from the given array of values.\n * If null or undefined is given then this function returns false.\n */\nexport function ArrayContains(values: any[], validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: ARRAY_CONTAINS,\n      constraints: [values],\n      validator: {\n        validate: (value, args): boolean => arrayContains(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must contain $constraint1 values',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/array/ArrayMaxSize.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const ARRAY_MAX_SIZE = 'arrayMaxSize';\n\n/**\n * Checks if the array's length is less or equal to the specified number.\n * If null or undefined is given then this function returns false.\n */\nexport function arrayMaxSize(array: unknown, max: number): boolean {\n  return Array.isArray(array) && array.length <= max;\n}\n\n/**\n * Checks if the array's length is less or equal to the specified number.\n * If null or undefined is given then this function returns false.\n */\nexport function ArrayMaxSize(max: number, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: ARRAY_MAX_SIZE,\n      constraints: [max],\n      validator: {\n        validate: (value, args): boolean => arrayMaxSize(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must contain no more than $constraint1 elements',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/array/ArrayMinSize.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const ARRAY_MIN_SIZE = 'arrayMinSize';\n\n/**\n * Checks if the array's length is greater than or equal to the specified number.\n * If null or undefined is given then this function returns false.\n */\nexport function arrayMinSize(array: unknown, min: number): boolean {\n  return Array.isArray(array) && array.length >= min;\n}\n\n/**\n * Checks if the array's length is greater than or equal to the specified number.\n * If null or undefined is given then this function returns false.\n */\nexport function ArrayMinSize(min: number, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: ARRAY_MIN_SIZE,\n      constraints: [min],\n      validator: {\n        validate: (value, args): boolean => arrayMinSize(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must contain at least $constraint1 elements',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/array/ArrayNotContains.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const ARRAY_NOT_CONTAINS = 'arrayNotContains';\n\n/**\n * Checks if array does not contain any of the given values.\n * If null or undefined is given then this function returns false.\n */\nexport function arrayNotContains(array: unknown, values: any[]): boolean {\n  if (!Array.isArray(array)) return false;\n\n  return values.every(value => array.indexOf(value) === -1);\n}\n\n/**\n * Checks if array does not contain any of the given values.\n * If null or undefined is given then this function returns false.\n */\nexport function ArrayNotContains(values: any[], validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: ARRAY_NOT_CONTAINS,\n      constraints: [values],\n      validator: {\n        validate: (value, args): boolean => arrayNotContains(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property should not contain $constraint1 values',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/array/ArrayNotEmpty.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const ARRAY_NOT_EMPTY = 'arrayNotEmpty';\n\n/**\n * Checks if given array is not empty.\n * If null or undefined is given then this function returns false.\n */\nexport function arrayNotEmpty(array: unknown): boolean {\n  return Array.isArray(array) && array.length > 0;\n}\n\n/**\n * Checks if given array is not empty.\n * If null or undefined is given then this function returns false.\n */\nexport function ArrayNotEmpty(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: ARRAY_NOT_EMPTY,\n      validator: {\n        validate: (value, args): boolean => arrayNotEmpty(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property should not be empty', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/array/ArrayUnique.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const ARRAY_UNIQUE = 'arrayUnique';\nexport type ArrayUniqueIdentifier<T = any> = (o: T) => any;\n\n/**\n * Checks if all array's values are unique. Comparison for objects is reference-based.\n * If null or undefined is given then this function returns false.\n */\nexport function arrayUnique(array: unknown[], identifier?: ArrayUniqueIdentifier): boolean {\n  if (!Array.isArray(array)) return false;\n\n  if (identifier) {\n    array = array.map(o => (o != null ? identifier(o) : o));\n  }\n\n  const uniqueItems = array.filter((a, b, c) => c.indexOf(a) === b);\n  return array.length === uniqueItems.length;\n}\n\n/**\n * Checks if all array's values are unique. Comparison for objects is reference-based.\n * If null or undefined is given then this function returns false.\n */\nexport function ArrayUnique<T = any>(\n  identifierOrOptions?: ArrayUniqueIdentifier<T> | ValidationOptions,\n  validationOptions?: ValidationOptions\n): PropertyDecorator {\n  const identifier = typeof identifierOrOptions === 'function' ? identifierOrOptions : undefined;\n  const options = typeof identifierOrOptions !== 'function' ? identifierOrOptions : validationOptions;\n\n  return ValidateBy(\n    {\n      name: ARRAY_UNIQUE,\n      validator: {\n        validate: (value, args): boolean => arrayUnique(value, identifier),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + \"All $property's elements must be unique\", options),\n      },\n    },\n    options\n  );\n}\n"
  },
  {
    "path": "src/decorator/common/Allow.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { ValidationMetadataArgs } from '../../metadata/ValidationMetadataArgs';\nimport { ValidationTypes } from '../../validation/ValidationTypes';\nimport { ValidationMetadata } from '../../metadata/ValidationMetadata';\nimport { getMetadataStorage } from '../../metadata/MetadataStorage';\n\n/**\n * If object has both allowed and not allowed properties a validation error will be thrown.\n */\nexport function Allow(validationOptions?: ValidationOptions): PropertyDecorator {\n  return function (object: object, propertyName: string): void {\n    const args: ValidationMetadataArgs = {\n      type: ValidationTypes.WHITELIST,\n      target: object.constructor,\n      propertyName: propertyName,\n      validationOptions: validationOptions,\n    };\n    getMetadataStorage().addValidationMetadata(new ValidationMetadata(args));\n  };\n}\n"
  },
  {
    "path": "src/decorator/common/Equals.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const EQUALS = 'equals';\n\n/**\n * Checks if value matches (\"===\") the comparison.\n */\nexport function equals(value: unknown, comparison: unknown): boolean {\n  return value === comparison;\n}\n\n/**\n * Checks if value matches (\"===\") the comparison.\n */\nexport function Equals(comparison: any, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: EQUALS,\n      constraints: [comparison],\n      validator: {\n        validate: (value, args): boolean => equals(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be equal to $constraint1',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/common/IsDefined.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from './ValidateBy';\nimport { ValidationTypes } from '../../validation/ValidationTypes';\n\n// isDefined is (yet) a special case\nexport const IS_DEFINED = ValidationTypes.IS_DEFINED;\n\n/**\n * Checks if value is defined (!== undefined, !== null).\n */\nexport function isDefined<T>(value: T | undefined | null): value is T {\n  return value !== undefined && value !== null;\n}\n\n/**\n * Checks if value is defined (!== undefined, !== null).\n */\nexport function IsDefined(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_DEFINED,\n      validator: {\n        validate: (value): boolean => isDefined(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property should not be null or undefined',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/common/IsEmpty.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_EMPTY = 'isEmpty';\n\n/**\n * Checks if given value is empty (=== '', === null, === undefined).\n */\nexport function isEmpty(value: unknown): boolean {\n  return value === '' || value === null || value === undefined;\n}\n\n/**\n * Checks if given value is empty (=== '', === null, === undefined).\n */\nexport function IsEmpty(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_EMPTY,\n      validator: {\n        validate: (value, args): boolean => isEmpty(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be empty', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/common/IsIn.spec.ts",
    "content": "import { isIn } from './IsIn';\n\ndescribe('@IsIn decorator implementation', () => {\n  describe('isIn validator', () => {\n    it('should accept valid values', () => {\n      expect(isIn('A', ['A', 'B'])).toBe(true);\n      expect(isIn('A', ['B', 'C'])).toBe(false);\n      expect(isIn('A', [1, 2])).toBe(false);\n    });\n\n    it('should not accept invalid values', () => {\n      expect(isIn('A', 5 as any)).toBe(false);\n      expect(isIn('A', 'ABC' as any)).toBe(false);\n      expect(isIn('A', false as any)).toBe(false);\n    });\n  });\n});\n"
  },
  {
    "path": "src/decorator/common/IsIn.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_IN = 'isIn';\n\n/**\n * Checks if given value is in a array of allowed values.\n */\nexport function isIn(value: unknown, possibleValues: readonly unknown[]): boolean {\n  return Array.isArray(possibleValues) && possibleValues.some(possibleValue => possibleValue === value);\n}\n\n/**\n * Checks if given value is in a array of allowed values.\n */\nexport function IsIn(values: readonly any[], validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_IN,\n      constraints: [values],\n      validator: {\n        validate: (value, args): boolean => isIn(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be one of the following values: $constraint1',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/common/IsLatLong.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from './ValidateBy';\nimport isLatLongValidator from 'validator/lib/isLatLong';\n\nexport const IS_LATLONG = 'isLatLong';\n\n/**\n * Checks if a value is string in format a \"latitude,longitude\".\n */\nexport function isLatLong(value: string): boolean {\n  return typeof value === 'string' && isLatLongValidator(value);\n}\n\n/**\n * Checks if a value is string in format a \"latitude,longitude\".\n */\nexport function IsLatLong(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_LATLONG,\n      validator: {\n        validate: (value, args): boolean => isLatLong(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a latitude,longitude string',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/common/IsLatitude.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from './ValidateBy';\nimport { isLatLong } from './IsLatLong';\n\nexport const IS_LATITUDE = 'isLatitude';\n\n/**\n * Checks if a given value is a latitude.\n */\nexport function isLatitude(value: string): boolean {\n  return (typeof value === 'number' || typeof value === 'string') && isLatLong(`${value},0`);\n}\n\n/**\n * Checks if a given value is a latitude.\n */\nexport function IsLatitude(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_LATITUDE,\n      validator: {\n        validate: (value, args): boolean => isLatitude(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a latitude string or number',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/common/IsLongitude.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from './ValidateBy';\nimport { isLatLong } from './IsLatLong';\n\nexport const IS_LONGITUDE = 'isLongitude';\n\n/**\n * Checks if a given value is a longitude.\n */\nexport function isLongitude(value: string): boolean {\n  return (typeof value === 'number' || typeof value === 'string') && isLatLong(`0,${value}`);\n}\n\n/**\n * Checks if a given value is a longitude.\n */\nexport function IsLongitude(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_LONGITUDE,\n      validator: {\n        validate: (value, args): boolean => isLongitude(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a longitude string or number',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/common/IsNotEmpty.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_NOT_EMPTY = 'isNotEmpty';\n\n/**\n * Checks if given value is not empty (!== '', !== null, !== undefined).\n */\nexport function isNotEmpty(value: unknown): boolean {\n  return value !== '' && value !== null && value !== undefined;\n}\n\n/**\n * Checks if given value is not empty (!== '', !== null, !== undefined).\n */\nexport function IsNotEmpty(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_NOT_EMPTY,\n      validator: {\n        validate: (value, args): boolean => isNotEmpty(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property should not be empty', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/common/IsNotIn.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_NOT_IN = 'isNotIn';\n\n/**\n * Checks if given value not in a array of allowed values.\n */\nexport function isNotIn(value: unknown, possibleValues: readonly unknown[]): boolean {\n  return !Array.isArray(possibleValues) || !possibleValues.some(possibleValue => possibleValue === value);\n}\n\n/**\n * Checks if given value not in a array of allowed values.\n */\nexport function IsNotIn(values: readonly any[], validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_NOT_IN,\n      constraints: [values],\n      validator: {\n        validate: (value, args): boolean => isNotIn(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property should not be one of the following values: $constraint1',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/common/IsOptional.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { ValidationMetadataArgs } from '../../metadata/ValidationMetadataArgs';\nimport { ValidationTypes } from '../../validation/ValidationTypes';\nimport { ValidationMetadata } from '../../metadata/ValidationMetadata';\nimport { getMetadataStorage } from '../../metadata/MetadataStorage';\n\nexport const IS_OPTIONAL = 'isOptional';\n\n/**\n * Checks if value is missing and if so, ignores all validators.\n */\nexport function IsOptional(validationOptions?: ValidationOptions): PropertyDecorator {\n  return function (object: object, propertyName: string): void {\n    const args: ValidationMetadataArgs = {\n      type: ValidationTypes.CONDITIONAL_VALIDATION,\n      name: IS_OPTIONAL,\n      target: object.constructor,\n      propertyName: propertyName,\n      constraints: [\n        (object: any, value: any): boolean => {\n          return object[propertyName] !== null && object[propertyName] !== undefined;\n        },\n      ],\n      validationOptions: validationOptions,\n    };\n    getMetadataStorage().addValidationMetadata(new ValidationMetadata(args));\n  };\n}\n"
  },
  {
    "path": "src/decorator/common/NotEquals.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const NOT_EQUALS = 'notEquals';\n\n/**\n * Checks if value does not match (\"!==\") the comparison.\n */\nexport function notEquals(value: unknown, comparison: unknown): boolean {\n  return value !== comparison;\n}\n\n/**\n * Checks if value does not match (\"!==\") the comparison.\n */\nexport function NotEquals(comparison: any, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: NOT_EQUALS,\n      constraints: [comparison],\n      validator: {\n        validate: (value, args): boolean => notEquals(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property should not be equal to $constraint1',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/common/Validate.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { ValidationMetadataArgs } from '../../metadata/ValidationMetadataArgs';\nimport { ValidationMetadata } from '../../metadata/ValidationMetadata';\nimport { getMetadataStorage } from '../../metadata/MetadataStorage';\nimport { ValidationTypes } from '../../validation/ValidationTypes';\nimport { ConstraintMetadata } from '../../metadata/ConstraintMetadata';\n\n/**\n * Registers custom validator class.\n */\nexport function ValidatorConstraint(options?: { name?: string; async?: boolean }) {\n  return function (target: Function): void {\n    const isAsync = options && options.async;\n    let name = options && options.name ? options.name : '';\n    if (!name) {\n      name = (target as any).name;\n      if (!name)\n        // generate name if it was not given\n        name = name.replace(/\\.?([A-Z]+)/g, (x, y) => '_' + (y as string).toLowerCase()).replace(/^_/, '');\n    }\n    const metadata = new ConstraintMetadata(target, name, isAsync);\n    getMetadataStorage().addConstraintMetadata(metadata);\n  };\n}\n\n/**\n * Performs validation based on the given custom validation class.\n * Validation class must be decorated with ValidatorConstraint decorator.\n */\nexport function Validate(constraintClass: Function, validationOptions?: ValidationOptions): PropertyDecorator;\nexport function Validate(\n  constraintClass: Function,\n  constraints?: any[],\n  validationOptions?: ValidationOptions\n): PropertyDecorator;\nexport function Validate(\n  constraintClass: Function,\n  constraintsOrValidationOptions?: any[] | ValidationOptions,\n  maybeValidationOptions?: ValidationOptions\n): PropertyDecorator {\n  return function (object: object, propertyName: string): void {\n    const args: ValidationMetadataArgs = {\n      type: ValidationTypes.CUSTOM_VALIDATION,\n      target: object.constructor,\n      propertyName: propertyName,\n      constraintCls: constraintClass,\n      constraints: Array.isArray(constraintsOrValidationOptions) ? constraintsOrValidationOptions : undefined,\n      validationOptions: !Array.isArray(constraintsOrValidationOptions)\n        ? constraintsOrValidationOptions\n        : maybeValidationOptions,\n    };\n    getMetadataStorage().addValidationMetadata(new ValidationMetadata(args));\n  };\n}\n"
  },
  {
    "path": "src/decorator/common/ValidateBy.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { registerDecorator } from '../../register-decorator';\nimport { ValidationArguments } from '../../validation/ValidationArguments';\nimport { ValidatorConstraintInterface } from '../../validation/ValidatorConstraintInterface';\n\nexport interface ValidateByOptions {\n  name: string;\n  constraints?: any[];\n  validator: ValidatorConstraintInterface | Function;\n  async?: boolean;\n}\n\nexport function buildMessage(\n  impl: (eachPrefix: string, args?: ValidationArguments) => string,\n  validationOptions?: ValidationOptions\n): (validationArguments?: ValidationArguments) => string {\n  return (validationArguments?: ValidationArguments): string => {\n    const eachPrefix = validationOptions && validationOptions.each ? 'each value in ' : '';\n    return impl(eachPrefix, validationArguments);\n  };\n}\n\nexport function ValidateBy(options: ValidateByOptions, validationOptions?: ValidationOptions): PropertyDecorator {\n  return function (object: object, propertyName: string): void {\n    registerDecorator({\n      name: options.name,\n      target: object.constructor,\n      propertyName: propertyName,\n      options: validationOptions,\n      constraints: options.constraints,\n      validator: options.validator,\n    });\n  };\n}\n"
  },
  {
    "path": "src/decorator/common/ValidateIf.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { ValidationMetadataArgs } from '../../metadata/ValidationMetadataArgs';\nimport { ValidationTypes } from '../../validation/ValidationTypes';\nimport { ValidationMetadata } from '../../metadata/ValidationMetadata';\nimport { getMetadataStorage } from '../../metadata/MetadataStorage';\n\n/**\n * Ignores the other validators on a property when the provided condition function returns false.\n */\nexport function ValidateIf(\n  condition: (object: any, value: any) => boolean,\n  validationOptions?: ValidationOptions\n): PropertyDecorator {\n  return function (object: object, propertyName: string): void {\n    const args: ValidationMetadataArgs = {\n      type: ValidationTypes.CONDITIONAL_VALIDATION,\n      target: object.constructor,\n      propertyName: propertyName,\n      constraints: [condition],\n      validationOptions: validationOptions,\n    };\n    getMetadataStorage().addValidationMetadata(new ValidationMetadata(args));\n  };\n}\n"
  },
  {
    "path": "src/decorator/common/ValidateNested.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { ValidationMetadataArgs } from '../../metadata/ValidationMetadataArgs';\nimport { ValidationTypes } from '../../validation/ValidationTypes';\nimport { ValidationMetadata } from '../../metadata/ValidationMetadata';\nimport { getMetadataStorage } from '../../metadata/MetadataStorage';\n\n/**\n * Objects / object arrays marked with this decorator will also be validated.\n */\nexport function ValidateNested(validationOptions?: ValidationOptions): PropertyDecorator {\n  const opts: ValidationOptions = { ...validationOptions };\n  const eachPrefix = opts.each ? 'each value in ' : '';\n  opts.message = opts.message || eachPrefix + 'nested property $property must be either object or array';\n\n  return function (object: object, propertyName: string): void {\n    const args: ValidationMetadataArgs = {\n      type: ValidationTypes.NESTED_VALIDATION,\n      target: object.constructor,\n      propertyName: propertyName,\n      validationOptions: opts,\n    };\n    getMetadataStorage().addValidationMetadata(new ValidationMetadata(args));\n  };\n}\n"
  },
  {
    "path": "src/decorator/common/ValidatePromise.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { ValidationMetadataArgs } from '../../metadata/ValidationMetadataArgs';\nimport { ValidationTypes } from '../../validation/ValidationTypes';\nimport { ValidationMetadata } from '../../metadata/ValidationMetadata';\nimport { getMetadataStorage } from '../../metadata/MetadataStorage';\n\n/**\n * Resolve promise before validation\n */\nexport function ValidatePromise(validationOptions?: ValidationOptions): PropertyDecorator {\n  return function (object: object, propertyName: string): void {\n    const args: ValidationMetadataArgs = {\n      type: ValidationTypes.PROMISE_VALIDATION,\n      target: object.constructor,\n      propertyName: propertyName,\n      validationOptions: validationOptions,\n    };\n    getMetadataStorage().addValidationMetadata(new ValidationMetadata(args));\n  };\n}\n"
  },
  {
    "path": "src/decorator/date/MaxDate.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const MAX_DATE = 'maxDate';\n\n/**\n * Checks if the value is a date that's before the specified date.\n */\nexport function maxDate(date: unknown, maxDate: Date | (() => Date)): boolean {\n  return date instanceof Date && date.getTime() <= (maxDate instanceof Date ? maxDate : maxDate()).getTime();\n}\n\n/**\n * Checks if the value is a date that's before the specified date.\n */\nexport function MaxDate(date: Date | (() => Date), validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: MAX_DATE,\n      constraints: [date],\n      validator: {\n        validate: (value, args): boolean => maxDate(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => 'maximal allowed date for ' + eachPrefix + '$property is $constraint1',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/date/MinDate.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const MIN_DATE = 'minDate';\n\n/**\n * Checks if the value is a date that's after the specified date.\n */\nexport function minDate(date: unknown, minDate: Date | (() => Date)): boolean {\n  return date instanceof Date && date.getTime() >= (minDate instanceof Date ? minDate : minDate()).getTime();\n}\n\n/**\n * Checks if the value is a date that's after the specified date.\n */\nexport function MinDate(date: Date | (() => Date), validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: MIN_DATE,\n      constraints: [date],\n      validator: {\n        validate: (value, args): boolean => minDate(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => 'minimal allowed date for ' + eachPrefix + '$property is $constraint1',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/decorators.ts",
    "content": "// -------------------------------------------------------------------------\n// System\n// -------------------------------------------------------------------------\n\n// -------------------------------------------------------------------------\n// Common checkers\n// -------------------------------------------------------------------------\n\nexport * from './common/Allow';\nexport * from './common/IsDefined';\nexport * from './common/IsOptional';\nexport * from './common/Validate';\nexport * from './common/ValidateBy';\nexport * from './common/ValidateIf';\nexport * from './common/ValidateNested';\nexport * from './common/ValidatePromise';\nexport * from './common/IsLatLong';\nexport * from './common/IsLatitude';\nexport * from './common/IsLongitude';\nexport * from './common/Equals';\nexport * from './common/NotEquals';\nexport * from './common/IsEmpty';\nexport * from './common/IsNotEmpty';\nexport * from './common/IsIn';\nexport * from './common/IsNotIn';\n\n// -------------------------------------------------------------------------\n// Number checkers\n// -------------------------------------------------------------------------\n\nexport * from './number/IsDivisibleBy';\nexport * from './number/IsPositive';\nexport * from './number/IsNegative';\nexport * from './number/Max';\nexport * from './number/Min';\n\n// -------------------------------------------------------------------------\n// Date checkers\n// -------------------------------------------------------------------------\n\nexport * from './date/MinDate';\nexport * from './date/MaxDate';\n\n// -------------------------------------------------------------------------\n// String checkers\n// -------------------------------------------------------------------------\n\nexport * from './string/Contains';\nexport * from './string/NotContains';\nexport * from './string/IsAlpha';\nexport * from './string/IsAlphanumeric';\nexport * from './string/IsDecimal';\nexport * from './string/IsAscii';\nexport * from './string/IsBase64';\nexport * from './string/IsByteLength';\nexport * from './string/IsCreditCard';\nexport * from './string/IsCurrency';\nexport * from './string/IsEmail';\nexport * from './string/IsFQDN';\nexport * from './string/IsFullWidth';\nexport * from './string/IsHalfWidth';\nexport * from './string/IsVariableWidth';\nexport * from './string/IsHexColor';\nexport * from './string/IsHexadecimal';\nexport * from './string/IsMacAddress';\nexport * from './string/IsIP';\nexport * from './string/IsPort';\nexport * from './string/IsISBN';\nexport * from './string/IsISIN';\nexport * from './string/IsISO8601';\nexport * from './string/IsJSON';\nexport * from './string/IsJWT';\nexport * from './string/IsLowercase';\nexport * from './string/IsMobilePhone';\nexport * from './string/IsISO31661Alpha2';\nexport * from './string/IsISO31661Alpha3';\nexport * from './string/IsISO31661Numeric';\nexport * from './string/IsMongoId';\nexport * from './string/IsMultibyte';\nexport * from './string/IsSurrogatePair';\nexport * from './string/IsUrl';\nexport * from './string/IsUUID';\nexport * from './string/IsFirebasePushId';\nexport * from './string/IsUppercase';\nexport * from './string/Length';\nexport * from './string/MaxLength';\nexport * from './string/MinLength';\nexport * from './string/Matches';\nexport * from './string/IsPhoneNumber';\nexport * from './string/IsMilitaryTime';\nexport * from './string/IsHash';\nexport * from './string/IsISSN';\nexport * from './string/IsDateString';\nexport * from './string/IsBooleanString';\nexport * from './string/IsNumberString';\nexport * from './string/IsBase32';\nexport * from './string/IsBIC';\nexport * from './string/IsBtcAddress';\nexport * from './string/IsDataURI';\nexport * from './string/IsEAN';\nexport * from './string/IsEthereumAddress';\nexport * from './string/IsHSL';\nexport * from './string/IsIBAN';\nexport * from './string/IsIdentityCard';\nexport * from './string/IsISRC';\nexport * from './string/IsLocale';\nexport * from './string/IsMagnetURI';\nexport * from './string/IsMimeType';\nexport * from './string/IsOctal';\nexport * from './string/IsPassportNumber';\nexport * from './string/IsPostalCode';\nexport * from './string/IsRFC3339';\nexport * from './string/IsRgbColor';\nexport * from './string/IsSemVer';\nexport * from './string/IsStrongPassword';\nexport * from './string/IsTimeZone';\nexport * from './string/IsBase58';\nexport * from './string/is-tax-id';\nexport * from './string/is-iso4217-currency-code';\nexport * from './string/isISO6391';\n\n// -------------------------------------------------------------------------\n// Type checkers\n// -------------------------------------------------------------------------\n\nexport * from './typechecker/IsBoolean';\nexport * from './typechecker/IsDate';\nexport * from './typechecker/IsNumber';\nexport * from './typechecker/IsEnum';\nexport * from './typechecker/IsInt';\nexport * from './typechecker/IsString';\nexport * from './typechecker/IsArray';\nexport * from './typechecker/IsObject';\n\n// -------------------------------------------------------------------------\n// Array checkers\n// -------------------------------------------------------------------------\n\nexport * from './array/ArrayContains';\nexport * from './array/ArrayNotContains';\nexport * from './array/ArrayNotEmpty';\nexport * from './array/ArrayMinSize';\nexport * from './array/ArrayMaxSize';\nexport * from './array/ArrayUnique';\n\n// -------------------------------------------------------------------------\n// Object checkers\n// -------------------------------------------------------------------------\n\nexport * from './object/IsNotEmptyObject';\nexport * from './object/IsInstance';\n"
  },
  {
    "path": "src/decorator/number/IsDivisibleBy.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isDivisibleByValidator from 'validator/lib/isDivisibleBy';\n\nexport const IS_DIVISIBLE_BY = 'isDivisibleBy';\n\n/**\n * Checks if value is a number that's divisible by another.\n */\nexport function isDivisibleBy(value: unknown, num: number): boolean {\n  return typeof value === 'number' && typeof num === 'number' && isDivisibleByValidator(String(value), num);\n}\n\n/**\n * Checks if value is a number that's divisible by another.\n */\nexport function IsDivisibleBy(num: number, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_DIVISIBLE_BY,\n      constraints: [num],\n      validator: {\n        validate: (value, args): boolean => isDivisibleBy(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be divisible by $constraint1',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/number/IsNegative.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_NEGATIVE = 'isNegative';\n\n/**\n * Checks if the value is a negative number smaller than zero.\n */\nexport function isNegative(value: unknown): boolean {\n  return typeof value === 'number' && value < 0;\n}\n\n/**\n * Checks if the value is a negative number smaller than zero.\n */\nexport function IsNegative(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_NEGATIVE,\n      validator: {\n        validate: (value, args): boolean => isNegative(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a negative number',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/number/IsPositive.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_POSITIVE = 'isPositive';\n\n/**\n * Checks if the value is a positive number greater than zero.\n */\nexport function isPositive(value: unknown): boolean {\n  return typeof value === 'number' && value > 0;\n}\n\n/**\n * Checks if the value is a positive number greater than zero.\n */\nexport function IsPositive(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_POSITIVE,\n      validator: {\n        validate: (value, args): boolean => isPositive(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a positive number',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/number/Max.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const MAX = 'max';\n\n/**\n * Checks if the first number is less than or equal to the second.\n */\nexport function max(num: unknown, max: number): boolean {\n  return typeof num === 'number' && typeof max === 'number' && num <= max;\n}\n\n/**\n * Checks if the value is less than or equal to the allowed maximum value.\n */\nexport function Max(maxValue: number, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: MAX,\n      constraints: [maxValue],\n      validator: {\n        validate: (value, args): boolean => max(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must not be greater than $constraint1',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/number/Min.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const MIN = 'min';\n\n/**\n * Checks if the first number is greater than or equal to the second.\n */\nexport function min(num: unknown, min: number): boolean {\n  return typeof num === 'number' && typeof min === 'number' && num >= min;\n}\n\n/**\n * Checks if the value is greater than or equal to the allowed minimum value.\n */\nexport function Min(minValue: number, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: MIN,\n      constraints: [minValue],\n      validator: {\n        validate: (value, args): boolean => min(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must not be less than $constraint1',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/object/IsInstance.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_INSTANCE = 'isInstance';\n\n/**\n * Checks if the value is an instance of the specified object.\n */\nexport function isInstance(object: unknown, targetTypeConstructor: new (...args: any[]) => any): boolean {\n  return (\n    targetTypeConstructor && typeof targetTypeConstructor === 'function' && object instanceof targetTypeConstructor\n  );\n}\n\n/**\n * Checks if the value is an instance of the specified object.\n */\nexport function IsInstance(\n  targetType: new (...args: any[]) => any,\n  validationOptions?: ValidationOptions\n): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_INSTANCE,\n      constraints: [targetType],\n      validator: {\n        validate: (value, args): boolean => isInstance(value, args?.constraints[0]),\n        defaultMessage: buildMessage((eachPrefix, args) => {\n          if (args?.constraints[0]) {\n            return eachPrefix + `$property must be an instance of ${args?.constraints[0].name as string}`;\n          } else {\n            return eachPrefix + `${IS_INSTANCE} decorator expects and object as value, but got falsy value.`;\n          }\n        }, validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/object/IsNotEmptyObject.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport { isObject } from '../typechecker/IsObject';\n\nexport const IS_NOT_EMPTY_OBJECT = 'isNotEmptyObject';\n\n/**\n * Checks if the value is valid Object & not empty.\n * Returns false if the value is not an object or an empty valid object.\n */\nexport function isNotEmptyObject(value: unknown, options?: { nullable?: boolean }): boolean {\n  if (!isObject(value)) {\n    return false;\n  }\n\n  if (options?.nullable === false) {\n    return !Object.values(value).every(propertyValue => propertyValue === null || propertyValue === undefined);\n  }\n\n  for (const key in value) {\n    if (value.hasOwnProperty(key)) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\n/**\n * Checks if the value is valid Object & not empty.\n * Returns false if the value is not an object or an empty valid object.\n */\nexport function IsNotEmptyObject(\n  options?: { nullable?: boolean },\n  validationOptions?: ValidationOptions\n): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_NOT_EMPTY_OBJECT,\n      constraints: [options],\n      validator: {\n        validate: (value, args): boolean => isNotEmptyObject(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a non-empty object',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/Contains.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport containsValidator from 'validator/lib/contains';\n\nexport const CONTAINS = 'contains';\n\n/**\n * Checks if the string contains the seed.\n * If given value is not a string, then it returns false.\n */\nexport function contains(value: unknown, seed: string): boolean {\n  return typeof value === 'string' && containsValidator(value, seed);\n}\n\n/**\n * Checks if the string contains the seed.\n * If given value is not a string, then it returns false.\n */\nexport function Contains(seed: string, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: CONTAINS,\n      constraints: [seed],\n      validator: {\n        validate: (value, args): boolean => contains(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must contain a $constraint1 string',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsAlpha.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isAlphaValidator from 'validator/lib/isAlpha';\nimport * as ValidatorJS from 'validator';\n\nexport const IS_ALPHA = 'isAlpha';\n\n/**\n * Checks if the string contains only letters (a-zA-Z).\n * If given value is not a string, then it returns false.\n */\nexport function isAlpha(value: unknown, locale?: ValidatorJS.AlphaLocale): boolean {\n  return typeof value === 'string' && isAlphaValidator(value, locale);\n}\n\n/**\n * Checks if the string contains only letters (a-zA-Z).\n * If given value is not a string, then it returns false.\n */\nexport function IsAlpha(locale?: ValidatorJS.AlphaLocale, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_ALPHA,\n      constraints: [locale],\n      validator: {\n        validate: (value, args): boolean => isAlpha(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must contain only letters (a-zA-Z)',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsAlphanumeric.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isAlphanumericValidator from 'validator/lib/isAlphanumeric';\nimport * as ValidatorJS from 'validator';\n\nexport const IS_ALPHANUMERIC = 'isAlphanumeric';\n\n/**\n * Checks if the string contains only letters and numbers.\n * If given value is not a string, then it returns false.\n */\nexport function isAlphanumeric(value: unknown, locale?: ValidatorJS.AlphanumericLocale): boolean {\n  return typeof value === 'string' && isAlphanumericValidator(value, locale);\n}\n\n/**\n * Checks if the string contains only letters and numbers.\n * If given value is not a string, then it returns false.\n */\nexport function IsAlphanumeric(\n  locale?: ValidatorJS.AlphanumericLocale,\n  validationOptions?: ValidationOptions\n): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_ALPHANUMERIC,\n      constraints: [locale],\n      validator: {\n        validate: (value, args): boolean => isAlphanumeric(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must contain only letters and numbers',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsAscii.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isAsciiValidator from 'validator/lib/isAscii';\n\nexport const IS_ASCII = 'isAscii';\n\n/**\n * Checks if the string contains ASCII chars only.\n * If given value is not a string, then it returns false.\n */\nexport function isAscii(value: unknown): boolean {\n  return typeof value === 'string' && isAsciiValidator(value);\n}\n\n/**\n * Checks if the string contains ASCII chars only.\n * If given value is not a string, then it returns false.\n */\nexport function IsAscii(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_ASCII,\n      validator: {\n        validate: (value, args): boolean => isAscii(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must contain only ASCII characters',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsBIC.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isBICValidator from 'validator/lib/isBIC';\n\nexport const IS_BIC = 'isBIC';\n\n/**\n * Check if a string is a BIC (Bank Identification Code) or SWIFT code.\n * If given value is not a string, then it returns false.\n */\nexport function isBIC(value: unknown): boolean {\n  return typeof value === 'string' && isBICValidator(value);\n}\n\n/**\n * Check if a string is a BIC (Bank Identification Code) or SWIFT code.\n * If given value is not a string, then it returns false.\n */\nexport function IsBIC(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_BIC,\n      validator: {\n        validate: (value, args): boolean => isBIC(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a BIC or SWIFT code',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsBase32.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isBase32Validator from 'validator/lib/isBase32';\n\nexport const IS_BASE32 = 'isBase32';\n\n/**\n * Checks if a string is base32 encoded.\n * If given value is not a string, then it returns false.\n */\nexport function isBase32(value: unknown): boolean {\n  return typeof value === 'string' && isBase32Validator(value);\n}\n\n/**\n * Check if a string is base32 encoded.\n * If given value is not a string, then it returns false.\n */\nexport function IsBase32(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_BASE32,\n      validator: {\n        validate: (value, args): boolean => isBase32(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be base32 encoded', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsBase58.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isBase58Validator from 'validator/lib/isBase58';\n\nexport const IS_BASE58 = 'isBase58';\n\n/**\n * Checks if a string is base58 encoded.\n * If given value is not a string, then it returns false.\n */\nexport function isBase58(value: unknown): boolean {\n  return typeof value === 'string' && isBase58Validator(value);\n}\n\n/**\n * Checks if a string is base58 encoded.\n * If given value is not a string, then it returns false.\n */\nexport function IsBase58(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_BASE58,\n      validator: {\n        validate: (value, args): boolean => isBase58(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be base58 encoded', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsBase64.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isBase64Validator from 'validator/lib/isBase64';\nimport * as ValidatorJS from 'validator';\n\nexport const IS_BASE64 = 'isBase64';\n\n/**\n * Checks if a string is base64 encoded.\n * If given value is not a string, then it returns false.\n */\nexport function isBase64(value: unknown, options?: ValidatorJS.IsBase64Options): boolean {\n  return typeof value === 'string' && isBase64Validator(value, options);\n}\n\n/**\n * Checks if a string is base64 encoded.\n * If given value is not a string, then it returns false.\n */\nexport function IsBase64(\n  options?: ValidatorJS.IsBase64Options,\n  validationOptions?: ValidationOptions\n): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_BASE64,\n      constraints: [options],\n      validator: {\n        validate: (value, args): boolean => isBase64(value, args?.constraints[0]),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be base64 encoded', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsBooleanString.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isBooleanValidator from 'validator/lib/isBoolean';\n\nexport const IS_BOOLEAN_STRING = 'isBooleanString';\n\n/**\n * Checks if a string is a boolean.\n * If given value is not a string, then it returns false.\n */\nexport function isBooleanString(value: unknown): boolean {\n  return typeof value === 'string' && isBooleanValidator(value);\n}\n\n/**\n * Checks if a string is a boolean.\n * If given value is not a string, then it returns false.\n */\nexport function IsBooleanString(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_BOOLEAN_STRING,\n      validator: {\n        validate: (value, args): boolean => isBooleanString(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a boolean string',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsBtcAddress.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isBtcAddressValidator from 'validator/lib/isBtcAddress';\n\nexport const IS_BTC_ADDRESS = 'isBtcAddress';\n\n/**\n * Check if the string is a valid BTC address.\n * If given value is not a string, then it returns false.\n */\nexport function isBtcAddress(value: unknown): boolean {\n  return typeof value === 'string' && isBtcAddressValidator(value);\n}\n\n/**\n * Check if the string is a valid BTC address.\n * If given value is not a string, then it returns false.\n */\nexport function IsBtcAddress(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_BTC_ADDRESS,\n      validator: {\n        validate: (value, args): boolean => isBtcAddress(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a BTC address', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsByteLength.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isByteLengthValidator from 'validator/lib/isByteLength';\n\nexport const IS_BYTE_LENGTH = 'isByteLength';\n\n/**\n * Checks if the string's length (in bytes) falls in a range.\n * If given value is not a string, then it returns false.\n */\nexport function isByteLength(value: unknown, min: number, max?: number): boolean {\n  return typeof value === 'string' && isByteLengthValidator(value, { min, max });\n}\n\n/**\n * Checks if the string's length (in bytes) falls in a range.\n * If given value is not a string, then it returns false.\n */\nexport function IsByteLength(min: number, max?: number, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_BYTE_LENGTH,\n      constraints: [min, max],\n      validator: {\n        validate: (value, args): boolean => isByteLength(value, args?.constraints[0], args?.constraints[1]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + \"$property's byte length must fall into ($constraint1, $constraint2) range\",\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsCreditCard.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isCreditCardValidator from 'validator/lib/isCreditCard';\n\nexport const IS_CREDIT_CARD = 'isCreditCard';\n\n/**\n * Checks if the string is a credit card.\n * If given value is not a string, then it returns false.\n */\nexport function isCreditCard(value: unknown): boolean {\n  return typeof value === 'string' && isCreditCardValidator(value);\n}\n\n/**\n * Checks if the string is a credit card.\n * If given value is not a string, then it returns false.\n */\nexport function IsCreditCard(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_CREDIT_CARD,\n      validator: {\n        validate: (value, args): boolean => isCreditCard(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a credit card', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsCurrency.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isCurrencyValidator from 'validator/lib/isCurrency';\nimport * as ValidatorJS from 'validator';\n\nexport const IS_CURRENCY = 'isCurrency';\n\n/**\n * Checks if the string is a valid currency amount.\n * If given value is not a string, then it returns false.\n */\nexport function isCurrency(value: unknown, options?: ValidatorJS.IsCurrencyOptions): boolean {\n  return typeof value === 'string' && isCurrencyValidator(value, options);\n}\n\n/**\n * Checks if the string is a valid currency amount.\n * If given value is not a string, then it returns false.\n */\nexport function IsCurrency(\n  options?: ValidatorJS.IsCurrencyOptions,\n  validationOptions?: ValidationOptions\n): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_CURRENCY,\n      constraints: [options],\n      validator: {\n        validate: (value, args): boolean => isCurrency(value, args?.constraints[0]),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a currency', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsDataURI.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isDataURIValidator from 'validator/lib/isDataURI';\n\nexport const IS_DATA_URI = 'isDataURI';\n\n/**\n * Check if the string is a data uri format.\n * If given value is not a string, then it returns false.\n */\nexport function isDataURI(value: unknown): boolean {\n  return typeof value === 'string' && isDataURIValidator(value);\n}\n\n/**\n * Check if the string is a data uri format.\n * If given value is not a string, then it returns false.\n */\nexport function IsDataURI(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_DATA_URI,\n      validator: {\n        validate: (value, args): boolean => isDataURI(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a data uri format',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsDateString.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport * as ValidatorJS from 'validator';\nimport { isISO8601 } from './IsISO8601';\n\nexport const IS_DATE_STRING = 'isDateString';\n\n/**\n * Alias for IsISO8601 validator\n */\nexport function isDateString(value: unknown, options?: ValidatorJS.IsISO8601Options): boolean {\n  return isISO8601(value, options);\n}\n\n/**\n * Alias for IsISO8601 validator\n */\nexport function IsDateString(\n  options?: ValidatorJS.IsISO8601Options,\n  validationOptions?: ValidationOptions\n): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_DATE_STRING,\n      constraints: [options],\n      validator: {\n        validate: (value): boolean => isDateString(value, options),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a valid ISO 8601 date string',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsDecimal.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isDecimalValidator from 'validator/lib/isDecimal';\nimport * as ValidatorJS from 'validator';\n\nexport const IS_DECIMAL = 'isDecimal';\n\n/**\n * Checks if the string is a valid decimal.\n * If given value is not a string, then it returns false.\n */\nexport function isDecimal(value: unknown, options?: ValidatorJS.IsDecimalOptions): boolean {\n  return typeof value === 'string' && isDecimalValidator(value, options);\n}\n\n/**\n * Checks if the string is a valid decimal.\n * If given value is not a string, then it returns false.\n */\nexport function IsDecimal(\n  options?: ValidatorJS.IsDecimalOptions,\n  validationOptions?: ValidationOptions\n): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_DECIMAL,\n      constraints: [options],\n      validator: {\n        validate: (value, args): boolean => isDecimal(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property is not a valid decimal number.',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsEAN.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isEANValidator from 'validator/lib/isEAN';\n\nexport const IS_EAN = 'isEAN';\n\n/**\n * Check if the string is an EAN (European Article Number).\n * If given value is not a string, then it returns false.\n */\nexport function isEAN(value: unknown): boolean {\n  return typeof value === 'string' && isEANValidator(value);\n}\n\n/**\n * Check if the string is an EAN (European Article Number).\n * If given value is not a string, then it returns false.\n */\nexport function IsEAN(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_EAN,\n      validator: {\n        validate: (value, args): boolean => isEAN(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be an EAN (European Article Number)',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsEmail.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isEmailValidator from 'validator/lib/isEmail';\nimport * as ValidatorJS from 'validator';\n\nexport const IS_EMAIL = 'isEmail';\n\n/**\n * Checks if the string is an email.\n * If given value is not a string, then it returns false.\n */\nexport function isEmail(value: unknown, options?: ValidatorJS.IsEmailOptions): boolean {\n  return typeof value === 'string' && isEmailValidator(value, options);\n}\n\n/**\n * Checks if the string is an email.\n * If given value is not a string, then it returns false.\n */\nexport function IsEmail(\n  options?: ValidatorJS.IsEmailOptions,\n  validationOptions?: ValidationOptions\n): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_EMAIL,\n      constraints: [options],\n      validator: {\n        validate: (value, args): boolean => isEmail(value, args?.constraints[0]),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be an email', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsEthereumAddress.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isEthereumAddressValidator from 'validator/lib/isEthereumAddress';\n\nexport const IS_ETHEREUM_ADDRESS = 'isEthereumAddress';\n\n/**\n * Check if the string is an Ethereum address using basic regex. Does not validate address checksums.\n * If given value is not a string, then it returns false.\n */\nexport function isEthereumAddress(value: unknown): boolean {\n  return typeof value === 'string' && isEthereumAddressValidator(value);\n}\n\n/**\n * Check if the string is an Ethereum address using basic regex. Does not validate address checksums.\n * If given value is not a string, then it returns false.\n */\nexport function IsEthereumAddress(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_ETHEREUM_ADDRESS,\n      validator: {\n        validate: (value, args): boolean => isEthereumAddress(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be an Ethereum address',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsFQDN.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isFqdnValidator from 'validator/lib/isFQDN';\nimport * as ValidatorJS from 'validator';\n\nexport const IS_FQDN = 'isFqdn';\n\n/**\n * Checks if the string is a fully qualified domain name (e.g. domain.com).\n * If given value is not a string, then it returns false.\n */\nexport function isFQDN(value: unknown, options?: ValidatorJS.IsFQDNOptions): boolean {\n  return typeof value === 'string' && isFqdnValidator(value, options);\n}\n\n/**\n * Checks if the string is a fully qualified domain name (e.g. domain.com).\n * If given value is not a string, then it returns false.\n */\nexport function IsFQDN(options?: ValidatorJS.IsFQDNOptions, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_FQDN,\n      constraints: [options],\n      validator: {\n        validate: (value, args): boolean => isFQDN(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a valid domain name',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsFirebasePushId.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_FIREBASE_PUSH_ID = 'IsFirebasePushId';\n\n/**\n * Checks if the string is a Firebase Push Id\n * If given value is not a Firebase Push Id, it returns false\n */\nexport function isFirebasePushId(value: unknown): boolean {\n  const webSafeRegex = /^[a-zA-Z0-9_-]*$/;\n  return typeof value === 'string' && value.length === 20 && webSafeRegex.test(value);\n}\n\n/**\n * Checks if the string is a Firebase Push Id\n * If given value is not a Firebase Push Id, it returns false\n */\nexport function IsFirebasePushId(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_FIREBASE_PUSH_ID,\n      validator: {\n        validate: (value, args): boolean => isFirebasePushId(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a Firebase Push Id',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsFullWidth.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isFullWidthValidator from 'validator/lib/isFullWidth';\n\nexport const IS_FULL_WIDTH = 'isFullWidth';\n\n/**\n * Checks if the string contains any full-width chars.\n * If given value is not a string, then it returns false.\n */\nexport function isFullWidth(value: unknown): boolean {\n  return typeof value === 'string' && isFullWidthValidator(value);\n}\n\n/**\n * Checks if the string contains any full-width chars.\n * If given value is not a string, then it returns false.\n */\nexport function IsFullWidth(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_FULL_WIDTH,\n      validator: {\n        validate: (value, args): boolean => isFullWidth(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must contain a full-width characters',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsHSL.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isHSLValidator from 'validator/lib/isHSL';\n\nexport const IS_HSL = 'isHSL';\n\n/**\n * Check if the string is an HSL (hue, saturation, lightness, optional alpha) color based on CSS Colors Level 4 specification.\n * Comma-separated format supported. Space-separated format supported with the exception of a few edge cases (ex: hsl(200grad+.1%62%/1)).\n * If given value is not a string, then it returns false.\n */\nexport function isHSL(value: unknown): boolean {\n  return typeof value === 'string' && isHSLValidator(value);\n}\n\n/**\n * Check if the string is an HSL (hue, saturation, lightness, optional alpha) color based on CSS Colors Level 4 specification.\n * Comma-separated format supported. Space-separated format supported with the exception of a few edge cases (ex: hsl(200grad+.1%62%/1)).\n * If given value is not a string, then it returns false.\n */\nexport function IsHSL(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_HSL,\n      validator: {\n        validate: (value, args): boolean => isHSL(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a HSL color', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsHalfWidth.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isHalfWidthValidator from 'validator/lib/isHalfWidth';\n\nexport const IS_HALF_WIDTH = 'isHalfWidth';\n\n/**\n * Checks if the string contains any half-width chars.\n * If given value is not a string, then it returns false.\n */\nexport function isHalfWidth(value: unknown): boolean {\n  return typeof value === 'string' && isHalfWidthValidator(value);\n}\n\n/**\n * Checks if the string contains any half-width chars.\n * If given value is not a string, then it returns false.\n */\nexport function IsHalfWidth(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_HALF_WIDTH,\n      validator: {\n        validate: (value, args): boolean => isHalfWidth(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must contain a half-width characters',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsHash.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isHashValidator from 'validator/lib/isHash';\nimport * as ValidatorJS from 'validator';\n\nexport const IS_HASH = 'isHash';\n\n/**\n * Check if the string is a hash of type algorithm.\n * Algorithm is one of ['md4', 'md5', 'sha1', 'sha256', 'sha384', 'sha512', 'ripemd128', 'ripemd160', 'tiger128',\n * 'tiger160', 'tiger192', 'crc32', 'crc32b']\n */\nexport function isHash(value: unknown, algorithm: ValidatorJS.HashAlgorithm): boolean {\n  return typeof value === 'string' && isHashValidator(value, algorithm);\n}\n\n/**\n * Check if the string is a hash of type algorithm.\n * Algorithm is one of ['md4', 'md5', 'sha1', 'sha256', 'sha384', 'sha512', 'ripemd128', 'ripemd160', 'tiger128',\n * 'tiger160', 'tiger192', 'crc32', 'crc32b']\n */\nexport function IsHash(algorithm: string, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_HASH,\n      constraints: [algorithm],\n      validator: {\n        validate: (value, args): boolean => isHash(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a hash of type $constraint1',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsHexColor.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isHexColorValidator from 'validator/lib/isHexColor';\n\nexport const IS_HEX_COLOR = 'isHexColor';\n\n/**\n * Checks if the string is a hexadecimal color.\n * If given value is not a string, then it returns false.\n */\nexport function isHexColor(value: unknown): boolean {\n  return typeof value === 'string' && isHexColorValidator(value);\n}\n\n/**\n * Checks if the string is a hexadecimal color.\n * If given value is not a string, then it returns false.\n */\nexport function IsHexColor(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_HEX_COLOR,\n      validator: {\n        validate: (value, args): boolean => isHexColor(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a hexadecimal color',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsHexadecimal.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isHexadecimalValidator from 'validator/lib/isHexadecimal';\n\nexport const IS_HEXADECIMAL = 'isHexadecimal';\n\n/**\n * Checks if the string is a hexadecimal number.\n * If given value is not a string, then it returns false.\n */\nexport function isHexadecimal(value: unknown): boolean {\n  return typeof value === 'string' && isHexadecimalValidator(value);\n}\n\n/**\n * Checks if the string is a hexadecimal number.\n * If given value is not a string, then it returns false.\n */\nexport function IsHexadecimal(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_HEXADECIMAL,\n      validator: {\n        validate: (value, args): boolean => isHexadecimal(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a hexadecimal number',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsIBAN.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isIBANValidator, { IsIBANOptions } from 'validator/lib/isIBAN';\n\nexport const IS_IBAN = 'isIBAN';\n\n/**\n * Check if a string is a IBAN (International Bank Account Number).\n * If given value is not a string, then it returns false.\n */\nexport function isIBAN(value: unknown, options?: IsIBANOptions): boolean {\n  return typeof value === 'string' && isIBANValidator(value, options);\n}\n\n/**\n * Check if a string is a IBAN (International Bank Account Number).\n * If given value is not a string, then it returns false.\n */\nexport function IsIBAN(options?: IsIBANOptions, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_IBAN,\n      validator: {\n        validate: (value, args): boolean => isIBAN(value, options),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be an IBAN', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsIP.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isIPValidator from 'validator/lib/isIP';\n\nexport type IsIpVersion = '4' | '6' | 4 | 6;\n\nexport const IS_IP = 'isIp';\n\n/**\n * Checks if the string is an IP (version 4 or 6).\n * If given value is not a string, then it returns false.\n */\nexport function isIP(value: unknown, version?: IsIpVersion): boolean {\n  /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion */\n  const versionStr = version ? (`${version}` as '4' | '6') : undefined;\n  return typeof value === 'string' && isIPValidator(value, versionStr);\n}\n\n/**\n * Checks if the string is an IP (version 4 or 6).\n * If given value is not a string, then it returns false.\n */\nexport function IsIP(version?: IsIpVersion, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_IP,\n      constraints: [version],\n      validator: {\n        validate: (value, args): boolean => isIP(value, args?.constraints[0]),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be an ip address', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsISBN.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isIsbnValidator from 'validator/lib/isISBN';\n\nexport type IsISBNVersion = '10' | '13' | 10 | 13;\n\nexport const IS_ISBN = 'isIsbn';\n\n/**\n * Checks if the string is an ISBN (version 10 or 13).\n * If given value is not a string, then it returns false.\n */\nexport function isISBN(value: unknown, version?: IsISBNVersion): boolean {\n  /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion */\n  const versionStr = version ? (`${version}` as '10' | '13') : undefined;\n  return typeof value === 'string' && isIsbnValidator(value, versionStr);\n}\n\n/**\n * Checks if the string is an ISBN (version 10 or 13).\n * If given value is not a string, then it returns false.\n */\nexport function IsISBN(version?: IsISBNVersion, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_ISBN,\n      constraints: [version],\n      validator: {\n        validate: (value, args): boolean => isISBN(value, args?.constraints[0]),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be an ISBN', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsISIN.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isIsinValidator from 'validator/lib/isISIN';\n\nexport const IS_ISIN = 'isIsin';\n\n/**\n * Checks if the string is an ISIN (stock/security identifier).\n * If given value is not a string, then it returns false.\n */\nexport function isISIN(value: unknown): boolean {\n  return typeof value === 'string' && isIsinValidator(value);\n}\n\n/**\n * Checks if the string is an ISIN (stock/security identifier).\n * If given value is not a string, then it returns false.\n */\nexport function IsISIN(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_ISIN,\n      validator: {\n        validate: (value, args): boolean => isISIN(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be an ISIN (stock/security identifier)',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsISO31661Alpha2.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isISO31661Alpha2Validator from 'validator/lib/isISO31661Alpha2';\n\nexport const IS_ISO31661_ALPHA_2 = 'isISO31661Alpha2';\n\n/**\n * Check if the string is a valid [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) officially assigned country code.\n */\nexport function isISO31661Alpha2(value: unknown): boolean {\n  return typeof value === 'string' && isISO31661Alpha2Validator(value);\n}\n\n/**\n * Check if the string is a valid [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) officially assigned country code.\n */\nexport function IsISO31661Alpha2(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_ISO31661_ALPHA_2,\n      validator: {\n        validate: (value, args): boolean => isISO31661Alpha2(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a valid ISO31661 Alpha2 code',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsISO31661Alpha3.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isISO31661Alpha3Validator from 'validator/lib/isISO31661Alpha3';\n\nexport const IS_ISO31661_ALPHA_3 = 'isISO31661Alpha3';\n\n/**\n * Check if the string is a valid [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) officially assigned country code.\n */\nexport function isISO31661Alpha3(value: unknown): boolean {\n  return typeof value === 'string' && isISO31661Alpha3Validator(value);\n}\n\n/**\n * Check if the string is a valid [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) officially assigned country code.\n */\nexport function IsISO31661Alpha3(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_ISO31661_ALPHA_3,\n      validator: {\n        validate: (value, args): boolean => isISO31661Alpha3(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a valid ISO31661 Alpha3 code',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsISO31661Numeric.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isISO31661NumericValidator from 'validator/lib/isISO31661Numeric';\n\nexport const IS_ISO31661_NUMERIC = 'isISO31661Numeric';\n\n/**\n * Check if the string is a valid [ISO 3166-1 numeric](https://en.wikipedia.org/wiki/ISO_3166-1_numeric) officially assigned country code.\n */\nexport function isISO31661Numeric(value: unknown): boolean {\n  return typeof value === 'string' && isISO31661NumericValidator(value);\n}\n\n/**\n * Check if the string is a valid [ISO 3166-1 numeric](https://en.wikipedia.org/wiki/ISO_3166-1_numeric) officially assigned country code.\n */\nexport function IsISO31661Numeric(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_ISO31661_NUMERIC,\n      validator: {\n        validate: (value, args): boolean => isISO31661Numeric(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a valid ISO 3166-1 numeric country code',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsISO8601.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isIso8601Validator from 'validator/lib/isISO8601';\nimport * as ValidatorJS from 'validator';\n\nexport const IS_ISO8601 = 'isIso8601';\n\n/**\n * Checks if the string is a valid ISO 8601 date.\n * If given value is not a string, then it returns false.\n * Use the option strict = true for additional checks for a valid date, e.g. invalidates dates like 2019-02-29.\n */\nexport function isISO8601(value: unknown, options?: ValidatorJS.IsISO8601Options): boolean {\n  return typeof value === 'string' && isIso8601Validator(value, options);\n}\n\n/**\n * Checks if the string is a valid ISO 8601 date.\n * If given value is not a string, then it returns false.\n * Use the option strict = true for additional checks for a valid date, e.g. invalidates dates like 2019-02-29.\n */\nexport function IsISO8601(\n  options?: ValidatorJS.IsISO8601Options,\n  validationOptions?: ValidationOptions\n): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_ISO8601,\n      constraints: [options],\n      validator: {\n        validate: (value, args): boolean => isISO8601(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a valid ISO 8601 date string',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsISRC.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isISRCValidator from 'validator/lib/isISRC';\n\nexport const IS_ISRC = 'isISRC';\n\n/**\n * Check if the string is a ISRC.\n * If given value is not a string, then it returns false.\n */\nexport function isISRC(value: unknown): boolean {\n  return typeof value === 'string' && isISRCValidator(value);\n}\n\n/**\n * Check if the string is a ISRC.\n * If given value is not a string, then it returns false.\n */\nexport function IsISRC(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_ISRC,\n      validator: {\n        validate: (value, args): boolean => isISRC(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be an ISRC', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsISSN.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isISSNValidator from 'validator/lib/isISSN';\nimport * as ValidatorJS from 'validator';\n\nexport const IS_ISSN = 'isISSN';\n\n/**\n * Checks if the string is a ISSN.\n * If given value is not a string, then it returns false.\n */\nexport function isISSN(value: unknown, options?: ValidatorJS.IsISSNOptions): boolean {\n  return typeof value === 'string' && isISSNValidator(value, options);\n}\n\n/**\n * Checks if the string is a ISSN.\n * If given value is not a string, then it returns false.\n */\nexport function IsISSN(options?: ValidatorJS.IsISSNOptions, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_ISSN,\n      constraints: [options],\n      validator: {\n        validate: (value, args): boolean => isISSN(value, args?.constraints[0]),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a ISSN', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsIdentityCard.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isIdentityCardValidator from 'validator/lib/isIdentityCard';\nimport * as ValidatorJS from 'validator';\n\nexport const IS_IDENTITY_CARD = 'isIdentityCard';\n\n/**\n * Check if the string is a valid identity card code.\n * locale is one of ['ES', 'zh-TW', 'he-IL', 'ar-TN'] OR 'any'. If 'any' is used, function will check if any of the locals match.\n * Defaults to 'any'.\n * If given value is not a string, then it returns false.\n */\nexport function isIdentityCard(value: unknown, locale: ValidatorJS.IdentityCardLocale): boolean {\n  return typeof value === 'string' && isIdentityCardValidator(value, locale);\n}\n\n/**\n * Check if the string is a valid identity card code.\n * locale is one of ['ES', 'zh-TW', 'he-IL', 'ar-TN'] OR 'any'. If 'any' is used, function will check if any of the locals match.\n * Defaults to 'any'.\n * If given value is not a string, then it returns false.\n */\nexport function IsIdentityCard(\n  locale?: ValidatorJS.IdentityCardLocale,\n  validationOptions?: ValidationOptions\n): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_IDENTITY_CARD,\n      constraints: [locale],\n      validator: {\n        validate: (value, args): boolean => isIdentityCard(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a identity card number',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsJSON.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isJSONValidator from 'validator/lib/isJSON';\n\nexport const IS_JSON = 'isJson';\n\n/**\n * Checks if the string is valid JSON (note: uses JSON.parse).\n * If given value is not a string, then it returns false.\n */\nexport function isJSON(value: unknown): boolean {\n  return typeof value === 'string' && isJSONValidator(value);\n}\n\n/**\n * Checks if the string is valid JSON (note: uses JSON.parse).\n * If given value is not a string, then it returns false.\n */\nexport function IsJSON(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_JSON,\n      validator: {\n        validate: (value, args): boolean => isJSON(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a json string', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsJWT.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isJwtValidator from 'validator/lib/isJWT';\n\nexport const IS_JWT = 'isJwt';\n\n/**\n * Checks if the string is valid JWT token.\n * If given value is not a string, then it returns false.\n */\nexport function isJWT(value: unknown): boolean {\n  return typeof value === 'string' && isJwtValidator(value);\n}\n\n/**\n * Checks if the string is valid JWT token.\n * If given value is not a string, then it returns false.\n */\nexport function IsJWT(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_JWT,\n      validator: {\n        validate: (value, args): boolean => isJWT(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a jwt string', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsLocale.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isLocaleValidator from 'validator/lib/isLocale';\n\nexport const IS_LOCALE = 'isLocale';\n\n/**\n * Check if the string is a locale.\n * If given value is not a string, then it returns false.\n */\nexport function isLocale(value: unknown): boolean {\n  return typeof value === 'string' && isLocaleValidator(value);\n}\n\n/**\n * Check if the string is a locale.\n * If given value is not a string, then it returns false.\n */\nexport function IsLocale(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_LOCALE,\n      validator: {\n        validate: (value, args): boolean => isLocale(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be locale', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsLowercase.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isLowercaseValidator from 'validator/lib/isLowercase';\n\nexport const IS_LOWERCASE = 'isLowercase';\n\n/**\n * Checks if the string is lowercase.\n * If given value is not a string, then it returns false.\n */\nexport function isLowercase(value: unknown): boolean {\n  return typeof value === 'string' && isLowercaseValidator(value);\n}\n\n/**\n * Checks if the string is lowercase.\n * If given value is not a string, then it returns false.\n */\nexport function IsLowercase(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_LOWERCASE,\n      validator: {\n        validate: (value, args): boolean => isLowercase(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a lowercase string',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsMacAddress.ts",
    "content": "import { ValidationOptions, isValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isMacAddressValidator from 'validator/lib/isMACAddress';\nimport * as ValidatorJS from 'validator';\n\nexport const IS_MAC_ADDRESS = 'isMacAddress';\n\n/**\n * Check if the string is a MAC address.\n * If given value is not a string, then it returns false.\n */\nexport function isMACAddress(value: unknown, options?: ValidatorJS.IsMACAddressOptions): boolean {\n  return typeof value === 'string' && isMacAddressValidator(value, options);\n}\n\n/**\n * Check if the string is a MAC address.\n * If given value is not a string, then it returns false.\n */\nexport function IsMACAddress(\n  optionsArg?: ValidatorJS.IsMACAddressOptions,\n  validationOptionsArg?: ValidationOptions\n): PropertyDecorator;\nexport function IsMACAddress(validationOptionsArg?: ValidationOptions): PropertyDecorator;\nexport function IsMACAddress(\n  optionsOrValidationOptionsArg?: ValidatorJS.IsMACAddressOptions | ValidationOptions,\n  validationOptionsArg?: ValidationOptions\n): PropertyDecorator {\n  const options = !isValidationOptions(optionsOrValidationOptionsArg) ? optionsOrValidationOptionsArg : undefined;\n  const validationOptions = isValidationOptions(optionsOrValidationOptionsArg)\n    ? optionsOrValidationOptionsArg\n    : validationOptionsArg;\n\n  return ValidateBy(\n    {\n      name: IS_MAC_ADDRESS,\n      constraints: [options],\n      validator: {\n        validate: (value, args): boolean => isMACAddress(value, options),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a MAC Address', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsMagnetURI.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isMagnetURIValidator from 'validator/lib/isMagnetURI';\n\nexport const IS_MAGNET_URI = 'isMagnetURI';\n\n/**\n * Check if the string is a magnet uri format.\n * If given value is not a string, then it returns false.\n */\nexport function isMagnetURI(value: unknown): boolean {\n  return typeof value === 'string' && isMagnetURIValidator(value);\n}\n\n/**\n * Check if the string is a magnet uri format.\n * If given value is not a string, then it returns false.\n */\nexport function IsMagnetURI(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_MAGNET_URI,\n      validator: {\n        validate: (value, args): boolean => isMagnetURI(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be magnet uri format',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsMilitaryTime.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport matchesValidator from 'validator/lib/matches';\n\nexport const IS_MILITARY_TIME = 'isMilitaryTime';\n\n/**\n * Checks if the string represents a time without a given timezone in the format HH:MM (military)\n * If the given value does not match the pattern HH:MM, then it returns false.\n */\nexport function isMilitaryTime(value: unknown): boolean {\n  const militaryTimeRegex = /^([01]\\d|2[0-3]):?([0-5]\\d)$/;\n  return typeof value === 'string' && matchesValidator(value, militaryTimeRegex);\n}\n\n/**\n * Checks if the string represents a time without a given timezone in the format HH:MM (military)\n * If the given value does not match the pattern HH:MM, then it returns false.\n */\nexport function IsMilitaryTime(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_MILITARY_TIME,\n      validator: {\n        validate: (value, args): boolean => isMilitaryTime(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a valid representation of military time in the format HH:MM',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsMimeType.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isMimeTypeValidator from 'validator/lib/isMimeType';\n\nexport const IS_MIME_TYPE = 'isMimeType';\n\n/**\n * Check if the string matches to a valid MIME type format\n * If given value is not a string, then it returns false.\n */\nexport function isMimeType(value: unknown): boolean {\n  return typeof value === 'string' && isMimeTypeValidator(value);\n}\n\n/**\n * Check if the string matches to a valid MIME type format\n * If given value is not a string, then it returns false.\n */\nexport function IsMimeType(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_MIME_TYPE,\n      validator: {\n        validate: (value, args): boolean => isMimeType(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be MIME type format',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsMobilePhone.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isMobilePhoneValidator from 'validator/lib/isMobilePhone';\nimport * as ValidatorJS from 'validator';\n\nexport const IS_MOBILE_PHONE = 'isMobilePhone';\n\n/**\n * Checks if the string is a mobile phone number (locale is either an array of locales (e.g ['sk-SK', 'sr-RS'])\n * OR one of ['am-Am', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', ar-JO', 'ar-KW', 'ar-SA', 'ar-SY', 'ar-TN', 'be-BY',\n * 'bg-BG', 'bn-BD', 'cs-CZ', 'da-DK', 'de-DE', 'de-AT', 'el-GR', 'en-AU', 'en-CA', 'en-GB', 'en-GG', 'en-GH', 'en-HK',\n * 'en-MO', 'en-IE', 'en-IN', 'en-KE', 'en-MT', 'en-MU', 'en-NG', 'en-NZ', 'en-PK', 'en-RW', 'en-SG', 'en-SL', 'en-UG',\n * 'en-US', 'en-TZ', 'en-ZA', 'en-ZM', 'es-CL', 'es-CR', 'es-EC', 'es-ES', 'es-MX', 'es-PA', 'es-PY', 'es-UY', 'et-EE',\n * 'fa-IR', 'fi-FI', 'fj-FJ', 'fo-FO', 'fr-BE', 'fr-FR', 'fr-GF', 'fr-GP', 'fr-MQ', 'fr-RE', 'he-IL', 'hu-HU', 'id-ID',\n * 'it-IT', 'ja-JP', 'kk-KZ', 'kl-GL', 'ko-KR', 'lt-LT', 'ms-MY', 'nb-NO', 'ne-NP', 'nl-BE', 'nl-NL', 'nn-NO', 'pl-PL',\n * 'pt-BR', 'pt-PT', 'ro-RO', 'ru-RU', 'sl-SI', 'sk-SK', 'sr-RS', 'sv-SE', 'th-TH', 'tr-TR', 'uk-UA', 'vi-VN', 'zh-CN',\n * 'zh-HK', 'zh-MO', 'zh-TW']\n * If given value is not a string, then it returns false.\n */\nexport function isMobilePhone(\n  value: unknown,\n  locale?: ValidatorJS.MobilePhoneLocale,\n  options?: ValidatorJS.IsMobilePhoneOptions\n): boolean {\n  return typeof value === 'string' && isMobilePhoneValidator(value, locale, options);\n}\n\n/**\n * Checks if the string is a mobile phone number (locale is either an array of locales (e.g ['sk-SK', 'sr-RS'])\n * OR one of ['am-Am', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', ar-JO', 'ar-KW', 'ar-SA', 'ar-SY', 'ar-TN', 'be-BY',\n * 'bg-BG', 'bn-BD', 'cs-CZ', 'da-DK', 'de-DE', 'de-AT', 'el-GR', 'en-AU', 'en-CA', 'en-GB', 'en-GG', 'en-GH', 'en-HK',\n * 'en-MO', 'en-IE', 'en-IN', 'en-KE', 'en-MT', 'en-MU', 'en-NG', 'en-NZ', 'en-PK', 'en-RW', 'en-SG', 'en-SL', 'en-UG',\n * 'en-US', 'en-TZ', 'en-ZA', 'en-ZM', 'es-CL', 'es-CR', 'es-EC', 'es-ES', 'es-MX', 'es-PA', 'es-PY', 'es-UY', 'et-EE',\n * 'fa-IR', 'fi-FI', 'fj-FJ', 'fo-FO', 'fr-BE', 'fr-FR', 'fr-GF', 'fr-GP', 'fr-MQ', 'fr-RE', 'he-IL', 'hu-HU', 'id-ID',\n * 'it-IT', 'ja-JP', 'kk-KZ', 'kl-GL', 'ko-KR', 'lt-LT', 'ms-MY', 'nb-NO', 'ne-NP', 'nl-BE', 'nl-NL', 'nn-NO', 'pl-PL',\n * 'pt-BR', 'pt-PT', 'ro-RO', 'ru-RU', 'sl-SI', 'sk-SK', 'sr-RS', 'sv-SE', 'th-TH', 'tr-TR', 'uk-UA', 'vi-VN', 'zh-CN',\n * 'zh-HK', 'zh-MO', 'zh-TW']\n * If given value is not a string, then it returns false.\n */\nexport function IsMobilePhone(\n  locale?: ValidatorJS.MobilePhoneLocale,\n  options?: ValidatorJS.IsMobilePhoneOptions,\n  validationOptions?: ValidationOptions\n): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_MOBILE_PHONE,\n      constraints: [locale, options],\n      validator: {\n        validate: (value, args): boolean => isMobilePhone(value, args?.constraints[0], args?.constraints[1]),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a phone number', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsMongoId.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isMongoIdValidator from 'validator/lib/isMongoId';\n\nexport const IS_MONGO_ID = 'isMongoId';\n\n/**\n * Checks if the string is a valid hex-encoded representation of a MongoDB ObjectId.\n * If given value is not a string, then it returns false.\n */\nexport function isMongoId(value: unknown): boolean {\n  return typeof value === 'string' && isMongoIdValidator(value);\n}\n\n/**\n * Checks if the string is a valid hex-encoded representation of a MongoDB ObjectId.\n * If given value is not a string, then it returns false.\n */\nexport function IsMongoId(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_MONGO_ID,\n      validator: {\n        validate: (value, args): boolean => isMongoId(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a mongodb id', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsMultibyte.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isMultibyteValidator from 'validator/lib/isMultibyte';\n\nexport const IS_MULTIBYTE = 'isMultibyte';\n\n/**\n * Checks if the string contains one or more multibyte chars.\n * If given value is not a string, then it returns false.\n */\nexport function isMultibyte(value: unknown): boolean {\n  return typeof value === 'string' && isMultibyteValidator(value);\n}\n\n/**\n * Checks if the string contains one or more multibyte chars.\n * If given value is not a string, then it returns false.\n */\nexport function IsMultibyte(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_MULTIBYTE,\n      validator: {\n        validate: (value, args): boolean => isMultibyte(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must contain one or more multibyte chars',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsNumberString.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isNumericValidator from 'validator/lib/isNumeric';\nimport * as ValidatorJS from 'validator';\n\nexport const IS_NUMBER_STRING = 'isNumberString';\n\n/**\n * Checks if the string is numeric.\n * If given value is not a string, then it returns false.\n */\nexport function isNumberString(value: unknown, options?: ValidatorJS.IsNumericOptions): boolean {\n  return typeof value === 'string' && isNumericValidator(value, options);\n}\n\n/**\n * Checks if the string is numeric.\n * If given value is not a string, then it returns false.\n */\nexport function IsNumberString(\n  options?: ValidatorJS.IsNumericOptions,\n  validationOptions?: ValidationOptions\n): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_NUMBER_STRING,\n      constraints: [options],\n      validator: {\n        validate: (value, args): boolean => isNumberString(value, args?.constraints[0]),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a number string', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsOctal.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isOctalValidator from 'validator/lib/isOctal';\n\nexport const IS_OCTAL = 'isOctal';\n\n/**\n * Check if the string is a valid octal number.\n * If given value is not a string, then it returns false.\n */\nexport function isOctal(value: unknown): boolean {\n  return typeof value === 'string' && isOctalValidator(value);\n}\n\n/**\n * Check if the string is a valid octal number.\n * If given value is not a string, then it returns false.\n */\nexport function IsOctal(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_OCTAL,\n      validator: {\n        validate: (value, args): boolean => isOctal(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be valid octal number',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsPassportNumber.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isPassportNumberValidator from 'validator/lib/isPassportNumber';\n\nexport const IS_PASSPORT_NUMBER = 'isPassportNumber';\n\n/**\n * Check if the string is a valid passport number relative to a specific country code.\n * If given value is not a string, then it returns false.\n */\nexport function isPassportNumber(value: unknown, countryCode: string): boolean {\n  return typeof value === 'string' && isPassportNumberValidator(value, countryCode);\n}\n\n/**\n * Check if the string is a valid passport number relative to a specific country code.\n * If given value is not a string, then it returns false.\n */\nexport function IsPassportNumber(countryCode: string, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_PASSPORT_NUMBER,\n      constraints: [countryCode],\n      validator: {\n        validate: (value, args): boolean => isPassportNumber(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be valid passport number',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsPhoneNumber.spec.ts",
    "content": "import { isPhoneNumber } from './IsPhoneNumber';\n\ndescribe('@IsPhoneNumber decorator implementation', () => {\n  describe('isPhoneNumber validator', () => {\n    it('should accept valid values', () => {\n      expect(isPhoneNumber('+36 20 111 1111')).toBe(true);\n      expect(isPhoneNumber('+36 20 111 1111', 'HU')).toBe(true);\n      expect(isPhoneNumber('20 111 1111', 'HU')).toBe(true);\n    });\n\n    describe('should not accept invalid values', () => {\n      it('xxx', () => {\n        expect(isPhoneNumber('aaaaa', 'HU')).toBe(false);\n        expect(isPhoneNumber('aaaa')).toBe(false);\n      });\n\n      it('when country code do not match number', () => {\n        // US number with Hungarian locale\n        expect(isPhoneNumber('+1 213 373 4253', 'HU')).toBe(false);\n        // Hungarian number with US locale\n        expect(isPhoneNumber('+36 20 111 1111', 'US')).toBe(false);\n      });\n\n      it('when number is invalid in given locale', () => {\n        expect(isPhoneNumber('+36 00 111 1111', 'HU')).toBe(false);\n      });\n\n      it('when phone number length is incorrect', () => {\n        expect(isPhoneNumber('+36 20 111 111', 'HU')).toBe(false);\n      });\n\n      it('when there are letters after or before the phone number', () => {\n        expect(isPhoneNumber('abc +36 20 111 111', 'HU')).toBe(false);\n        expect(isPhoneNumber('+36 20 111 111 abc', 'HU')).toBe(false);\n      });\n    });\n\n    it('should not accept values with extra whitespace', () => {\n      expect(isPhoneNumber('  +36 20 111 1111', 'HU')).toBe(false);\n      expect(isPhoneNumber('+36 20 111 1111  ', 'HU')).toBe(false);\n    });\n  });\n});\n"
  },
  {
    "path": "src/decorator/string/IsPhoneNumber.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport { parsePhoneNumber, CountryCode } from 'libphonenumber-js/max';\n\nexport const IS_PHONE_NUMBER = 'isPhoneNumber';\n\n/**\n * Checks if the string is a valid phone number. To successfully validate any phone number the text must include\n * the intl. calling code, if the calling code wont be provided then the region must be set.\n *\n * @param value the potential phone number string to test\n * @param region 2 characters uppercase country code (e.g. DE, US, CH) for country specific validation.\n * If text doesn't start with the international calling code (e.g. +41), then you must set this parameter.\n */\nexport function isPhoneNumber(value: string, region?: CountryCode): boolean {\n  if (typeof value !== 'string' || value.trim() !== value) {\n    return false;\n  }\n\n  try {\n    const phoneNumber = parsePhoneNumber(value, region);\n\n    /**\n     * We fail the validation if the user provided a region code\n     * and it doesn't match with the country code of the parsed number.\n     **/\n    if (region && phoneNumber.country !== region) {\n      return false;\n    }\n\n    return phoneNumber.isValid();\n  } catch (error) {\n    return false;\n  }\n}\n\n/**\n * Checks if the string is a valid phone number. To successfully validate any phone number the text must include\n * the intl. calling code, if the calling code wont be provided then the region must be set.\n *\n * @param region 2 characters uppercase country code (e.g. DE, US, CH) for country specific validation.\n * If text doesn't start with the international calling code (e.g. +41), then you must set this parameter.\n */\nexport function IsPhoneNumber(region?: CountryCode, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_PHONE_NUMBER,\n      constraints: [region],\n      validator: {\n        validate: (value, args): boolean => isPhoneNumber(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a valid phone number',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsPort.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isPortValidator from 'validator/lib/isPort';\n\nexport const IS_PORT = 'isPort';\n\n/**\n * Check if the string is a valid port number.\n */\nexport function isPort(value: unknown): boolean {\n  return typeof value === 'string' && isPortValidator(value);\n}\n\n/**\n * Check if the string is a valid port number.\n */\nexport function IsPort(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_PORT,\n      validator: {\n        validate: (value, args): boolean => isPort(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a port', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsPostalCode.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isPostalCodeValidator from 'validator/lib/isPostalCode';\nimport * as ValidatorJS from 'validator';\n\nexport const IS_POSTAL_CODE = 'isPostalCode';\n\n/**\n * Check if the string is a postal code, in the specified locale.\n * If given value is not a string, then it returns false.\n */\nexport function isPostalCode(value: unknown, locale: 'any' | ValidatorJS.PostalCodeLocale): boolean {\n  return typeof value === 'string' && isPostalCodeValidator(value, locale);\n}\n\n/**\n * Check if the string is a postal code, in the specified locale.\n * If given value is not a string, then it returns false.\n */\nexport function IsPostalCode(\n  locale?: 'any' | ValidatorJS.PostalCodeLocale,\n  validationOptions?: ValidationOptions\n): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_POSTAL_CODE,\n      constraints: [locale],\n      validator: {\n        validate: (value, args): boolean => isPostalCode(value, args?.constraints[0]),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a postal code', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsRFC3339.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isRFC3339Validator from 'validator/lib/isRFC3339';\n\nexport const IS_RFC_3339 = 'isRFC3339';\n\n/**\n * Check if the string is a valid RFC 3339 date.\n * If given value is not a string, then it returns false.\n */\nexport function isRFC3339(value: unknown): boolean {\n  return typeof value === 'string' && isRFC3339Validator(value);\n}\n\n/**\n * Check if the string is a valid RFC 3339 date.\n * If given value is not a string, then it returns false.\n */\nexport function IsRFC3339(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_RFC_3339,\n      validator: {\n        validate: (value, args): boolean => isRFC3339(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be RFC 3339 date', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsRgbColor.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isRgbColorValidator from 'validator/lib/isRgbColor';\n\nexport const IS_RGB_COLOR = 'isRgbColor';\n\n/**\n * Check if the string is a rgb or rgba color.\n * `includePercentValues` defaults to true. If you don't want to allow to set rgb or rgba values with percents, like rgb(5%,5%,5%), or rgba(90%,90%,90%,.3), then set it to false.\n * If given value is not a string, then it returns false.\n */\nexport function isRgbColor(value: unknown, includePercentValues?: boolean): boolean {\n  return (\n    typeof value === 'string' &&\n    isRgbColorValidator(value, {\n      includePercentValues,\n    })\n  );\n}\n\n/**\n * Check if the string is a rgb or rgba color.\n * `includePercentValues` defaults to true. If you don't want to allow to set rgb or rgba values with percents, like rgb(5%,5%,5%), or rgba(90%,90%,90%,.3), then set it to false.\n * If given value is not a string, then it returns false.\n */\nexport function IsRgbColor(includePercentValues?: boolean, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_RGB_COLOR,\n      constraints: [includePercentValues],\n      validator: {\n        validate: (value, args): boolean => isRgbColor(value, args?.constraints[0]),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be RGB color', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsSemVer.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isSemVerValidator from 'validator/lib/isSemVer';\n\nexport const IS_SEM_VER = 'isSemVer';\n\n/**\n * Check if the string is a Semantic Versioning Specification (SemVer).\n * If given value is not a string, then it returns false.\n */\nexport function isSemVer(value: unknown): boolean {\n  return typeof value === 'string' && isSemVerValidator(value);\n}\n\n/**\n * Check if the string is a Semantic Versioning Specification (SemVer).\n * If given value is not a string, then it returns false.\n */\nexport function IsSemVer(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_SEM_VER,\n      validator: {\n        validate: (value, args): boolean => isSemVer(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a Semantic Versioning Specification',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsStrongPassword.ts",
    "content": "import * as validator from 'validator';\nimport { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_STRONG_PASSWORD = 'isStrongPassword';\n\n/**\n * Options to be passed to IsStrongPassword decorator.\n */\nexport type IsStrongPasswordOptions = Pick<\n  validator.StrongPasswordOptions,\n  'minLength' | 'minLowercase' | 'minUppercase' | 'minNumbers' | 'minSymbols'\n>;\n\n/**\n * Checks if the string is a strong password.\n * If given value is not a string, then it returns false.\n */\nexport function isStrongPassword(value: unknown, options?: IsStrongPasswordOptions): boolean {\n  return typeof value === 'string' && validator.isStrongPassword(value, options);\n}\n\n/**\n * Checks if the string is a strong password.\n * If given value is not a string, then it returns false.\n */\nexport function IsStrongPassword(\n  options?: IsStrongPasswordOptions,\n  validationOptions?: ValidationOptions\n): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_STRONG_PASSWORD,\n      constraints: [options],\n      validator: {\n        validate: (value, args): boolean => isStrongPassword(value, args.constraints[0]),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property is not strong enough', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsSurrogatePair.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isSurrogatePairValidator from 'validator/lib/isSurrogatePair';\n\nexport const IS_SURROGATE_PAIR = 'isSurrogatePair';\n\n/**\n * Checks if the string contains any surrogate pairs chars.\n * If given value is not a string, then it returns false.\n */\nexport function isSurrogatePair(value: unknown): boolean {\n  return typeof value === 'string' && isSurrogatePairValidator(value);\n}\n\n/**\n * Checks if the string contains any surrogate pairs chars.\n * If given value is not a string, then it returns false.\n */\nexport function IsSurrogatePair(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_SURROGATE_PAIR,\n      validator: {\n        validate: (value, args): boolean => isSurrogatePair(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must contain any surrogate pairs chars',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsTimeZone.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_TIMEZONE = 'isTimeZone';\n\n/**\n * Checks if the string represents a valid IANA timezone\n * If the given value is not a valid IANA timezone, then it returns false.\n */\nexport function isTimeZone(value: unknown): boolean {\n  try {\n    if (typeof value !== 'string') {\n      return false;\n    }\n\n    /** Specifying an invalid time-zone will raise a `RangeError: Invalid time zone specified` error. */\n    Intl.DateTimeFormat(undefined, { timeZone: value });\n\n    return true;\n  } catch (exception) {\n    return false;\n  }\n}\n\n/**\n * Checks if the string represents a valid IANA timezone\n * If the given value is not a valid IANA timezone, then it returns false.\n */\nexport function IsTimeZone(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_TIMEZONE,\n      validator: {\n        validate: (value, args): boolean => isTimeZone(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a valid IANA time-zone',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsUUID.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isUuidValidator from 'validator/lib/isUUID';\nimport * as ValidatorJS from 'validator';\n\nexport const IS_UUID = 'isUuid';\n\nexport type IsUUIDVersion = ValidatorJS.UUIDVersion | ValidatorJS.UUIDVersion[];\n\n/**\n * Checks if the string is a UUID (version 1-8, nil, max, loose, all).\n * If given value is not a string, then it returns false.\n * Supports single version or array of versions.\n */\nexport function isUUID(value: unknown, version?: IsUUIDVersion): boolean {\n  if (typeof value !== 'string') return false;\n  if (Array.isArray(version)) {\n    for (const v of version) {\n      if (isUuidValidator(value, v)) return true;\n    }\n    return false;\n  }\n  return isUuidValidator(value, version);\n}\n\n/**\n * Checks if the string is a UUID (version 1-8, nil, max, loose, all).\n * If given value is not a string, then it returns false.\n * Supports single version or array of versions.\n */\nexport function IsUUID(version?: IsUUIDVersion, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_UUID,\n      constraints: [version],\n      validator: {\n        validate: (value, args): boolean => isUUID(value, args?.constraints[0]),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a UUID', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsUppercase.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isUppercaseValidator from 'validator/lib/isUppercase';\n\nexport const IS_UPPERCASE = 'isUppercase';\n\n/**\n * Checks if the string is uppercase.\n * If given value is not a string, then it returns false.\n */\nexport function isUppercase(value: unknown): boolean {\n  return typeof value === 'string' && isUppercaseValidator(value);\n}\n\n/**\n * Checks if the string is uppercase.\n * If given value is not a string, then it returns false.\n */\nexport function IsUppercase(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_UPPERCASE,\n      validator: {\n        validate: (value, args): boolean => isUppercase(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be uppercase', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsUrl.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isUrlValidator from 'validator/lib/isURL';\nimport * as ValidatorJS from 'validator';\n\nexport const IS_URL = 'isUrl';\n\n/**\n * Checks if the string is a url.\n * If given value is not a string, then it returns false.\n */\nexport function isURL(value: string, options?: ValidatorJS.IsURLOptions): boolean {\n  return typeof value === 'string' && isUrlValidator(value, options);\n}\n\n/**\n * Checks if the string is a url.\n * If given value is not a string, then it returns false.\n */\nexport function IsUrl(options?: ValidatorJS.IsURLOptions, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_URL,\n      constraints: [options],\n      validator: {\n        validate: (value, args): boolean => isURL(value, args?.constraints[0]),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a URL address', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/IsVariableWidth.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isVariableWidthValidator from 'validator/lib/isVariableWidth';\n\nexport const IS_VARIABLE_WIDTH = 'isVariableWidth';\n\n/**\n * Checks if the string contains variable-width chars.\n * If given value is not a string, then it returns false.\n */\nexport function isVariableWidth(value: unknown): boolean {\n  return typeof value === 'string' && isVariableWidthValidator(value);\n}\n\n/**\n * Checks if the string contains variable-width chars.\n * If given value is not a string, then it returns false.\n */\nexport function IsVariableWidth(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_VARIABLE_WIDTH,\n      validator: {\n        validate: (value, args): boolean => isVariableWidth(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must contain a full-width and half-width characters',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/Length.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isLengthValidator from 'validator/lib/isLength';\n\nexport const IS_LENGTH = 'isLength';\n\n/**\n * Checks if the string's length falls in a range. Note: this function takes into account surrogate pairs.\n * If given value is not a string, then it returns false.\n */\nexport function length(value: unknown, min: number, max?: number): boolean {\n  return typeof value === 'string' && isLengthValidator(value, { min, max });\n}\n\n/**\n * Checks if the string's length falls in a range. Note: this function takes into account surrogate pairs.\n * If given value is not a string, then it returns false.\n */\nexport function Length(min: number, max?: number, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_LENGTH,\n      constraints: [min, max],\n      validator: {\n        validate: (value, args): boolean => length(value, args?.constraints[0], args?.constraints[1]),\n        defaultMessage: buildMessage((eachPrefix, args) => {\n          const isMinLength = args?.constraints[0] !== null && args?.constraints[0] !== undefined;\n          const isMaxLength = args?.constraints[1] !== null && args?.constraints[1] !== undefined;\n          if (isMinLength && (!args.value || args.value.length < args?.constraints[0])) {\n            return eachPrefix + '$property must be longer than or equal to $constraint1 characters';\n          } else if (isMaxLength && args.value.length > args?.constraints[1]) {\n            return eachPrefix + '$property must be shorter than or equal to $constraint2 characters';\n          }\n          return (\n            eachPrefix +\n            '$property must be longer than or equal to $constraint1 and shorter than or equal to $constraint2 characters'\n          );\n        }, validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/Matches.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport matchesValidator from 'validator/lib/matches';\n\nexport const MATCHES = 'matches';\n\n/**\n * Checks if string matches the pattern. Either matches('foo', /foo/i).\n * If given value is not a string, then it returns false.\n */\nexport function matches(value: string, pattern: RegExp): boolean;\nexport function matches(value: string, pattern: string, modifiers: string): boolean;\nexport function matches(value: string, pattern: RegExp | string, modifiers?: string): boolean {\n  return typeof value === 'string' && matchesValidator(value, pattern as unknown as any, modifiers);\n}\n\n/**\n * Checks if string matches the pattern. Either matches('foo', /foo/i)\n * If given value is not a string, then it returns false.\n */\nexport function Matches(pattern: RegExp, validationOptions?: ValidationOptions): PropertyDecorator;\nexport function Matches(pattern: string, modifiers?: string, validationOptions?: ValidationOptions): PropertyDecorator;\nexport function Matches(\n  pattern: RegExp | string,\n  modifiersOrAnnotationOptions?: string | ValidationOptions,\n  validationOptions?: ValidationOptions\n): PropertyDecorator {\n  let modifiers: string;\n  if (modifiersOrAnnotationOptions && modifiersOrAnnotationOptions instanceof Object && !validationOptions) {\n    validationOptions = modifiersOrAnnotationOptions;\n  } else {\n    modifiers = modifiersOrAnnotationOptions as string;\n  }\n\n  return ValidateBy(\n    {\n      name: MATCHES,\n      constraints: [pattern, modifiers],\n      validator: {\n        validate: (value, args): boolean => matches(value, args?.constraints[0], args?.constraints[1]),\n        defaultMessage: buildMessage(\n          (eachPrefix, args) => eachPrefix + '$property must match $constraint1 regular expression',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/MaxLength.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isLengthValidator from 'validator/lib/isLength';\n\nexport const MAX_LENGTH = 'maxLength';\n\n/**\n * Checks if the string's length is not more than given number. Note: this function takes into account surrogate pairs.\n * If given value is not a string, then it returns false.\n */\nexport function maxLength(value: unknown, max: number): boolean {\n  return typeof value === 'string' && isLengthValidator(value, { min: 0, max });\n}\n\n/**\n * Checks if the string's length is not more than given number. Note: this function takes into account surrogate pairs.\n * If given value is not a string, then it returns false.\n */\nexport function MaxLength(max: number, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: MAX_LENGTH,\n      constraints: [max],\n      validator: {\n        validate: (value, args): boolean => maxLength(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be shorter than or equal to $constraint1 characters',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/MinLength.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isLengthValidator from 'validator/lib/isLength';\n\nexport const MIN_LENGTH = 'minLength';\n\n/**\n * Checks if the string's length is not less than given number. Note: this function takes into account surrogate pairs.\n * If given value is not a string, then it returns false.\n */\nexport function minLength(value: unknown, min: number): boolean {\n  return typeof value === 'string' && isLengthValidator(value, { min });\n}\n\n/**\n * Checks if the string's length is not less than given number. Note: this function takes into account surrogate pairs.\n * If given value is not a string, then it returns false.\n */\nexport function MinLength(min: number, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: MIN_LENGTH,\n      constraints: [min],\n      validator: {\n        validate: (value, args): boolean => minLength(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be longer than or equal to $constraint1 characters',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/NotContains.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport containsValidator from 'validator/lib/contains';\n\nexport const NOT_CONTAINS = 'notContains';\n\n/**\n * Checks if the string does not contain the seed.\n * If given value is not a string, then it returns false.\n */\nexport function notContains(value: unknown, seed: string): boolean {\n  return typeof value === 'string' && !containsValidator(value, seed);\n}\n\n/**\n * Checks if the string does not contain the seed.\n * If given value is not a string, then it returns false.\n */\nexport function NotContains(seed: string, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: NOT_CONTAINS,\n      constraints: [seed],\n      validator: {\n        validate: (value, args): boolean => notContains(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property should not contain a $constraint1 string',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/is-iso4217-currency-code.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isISO4217Validator from 'validator/lib/isISO4217';\n\nexport const IS_ISO4217_CURRENCY_CODE = 'isISO4217CurrencyCode';\n\n/**\n * Check if the string is a valid [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) officially assigned currency code.\n */\nexport function isISO4217CurrencyCode(value: unknown): boolean {\n  return typeof value === 'string' && isISO4217Validator(value);\n}\n\n/**\n * Check if the string is a valid [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) officially assigned currency code.\n */\nexport function IsISO4217CurrencyCode(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_ISO4217_CURRENCY_CODE,\n      validator: {\n        validate: (value, args): boolean => isISO4217CurrencyCode(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a valid ISO4217 currency code',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/is-tax-id.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isTaxIDValidator from 'validator/lib/isTaxID';\n\nexport const IS_TAX_ID = 'isTaxId';\n\n/**\n * Checks if the string is a valid tax ID. Default locale is `en-US`.\n * If given value is not a string, then it returns false.\n *\n * Supported locales: bg-BG, cs-CZ, de-AT, de-DE, dk-DK, el-CY, el-GR, en-CA,\n * en-IE, en-US, es-ES, et-EE, fi-FI, fr-BE, fr-FR, fr-LU, hr-HR, hu-HU, it-IT,\n * lv-LV, mt-MT, nl-NL, pl-PL, pt-BR, pt-PT, ro-RO, sk-SK, sl-SI, sv-SE.\n */\nexport function isTaxId(value: unknown, locale?: string): boolean {\n  return typeof value === 'string' && isTaxIDValidator(value, locale || 'en-US');\n}\n\n/**\n * Checks if the string is a valid tax ID. Default locale is `en-US`.\n * If given value is not a string, then it returns false.\n *\n * Supported locales: bg-BG, cs-CZ, de-AT, de-DE, dk-DK, el-CY, el-GR, en-CA,\n * en-IE, en-US, es-ES, et-EE, fi-FI, fr-BE, fr-FR, fr-LU, hr-HR, hu-HU, it-IT,\n * lv-LV, mt-MT, nl-NL, pl-PL, pt-BR, pt-PT, ro-RO, sk-SK, sl-SI, sv-SE.\n */\nexport function IsTaxId(locale?: string, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_TAX_ID,\n      constraints: [locale],\n      validator: {\n        validate: (value, args): boolean => isTaxId(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a Tax Identification Number',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/string/isISO6391.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\nimport isISO6391Validator from 'validator/lib/isISO6391';\n\nexport const IS_ISO6391 = 'isISO6391';\n\n/**\n * Check if the string is a valid [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) officially assigned language code.\n */\nexport function isISO6391(value: unknown): boolean {\n  return typeof value === 'string' && isISO6391Validator(value);\n}\n\n/**\n * Check if the string is a valid [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) officially assigned language code.\n */\nexport function IsISO6391(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_ISO6391,\n      validator: {\n        validate: (value, args): boolean => isISO6391(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a valid ISO 639-1 language code',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/typechecker/IsArray.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_ARRAY = 'isArray';\n\n/**\n * Checks if a given value is an array\n */\nexport function isArray<T = any>(value: unknown): value is Array<T> {\n  return Array.isArray(value);\n}\n\n/**\n * Checks if a given value is an array\n */\nexport function IsArray(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_ARRAY,\n      validator: {\n        validate: (value, args): boolean => isArray(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be an array', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/typechecker/IsBoolean.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_BOOLEAN = 'isBoolean';\n\n/**\n * Checks if a given value is a boolean.\n */\nexport function isBoolean(value: unknown): value is boolean {\n  return value instanceof Boolean || typeof value === 'boolean';\n}\n\n/**\n * Checks if a value is a boolean.\n */\nexport function IsBoolean(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_BOOLEAN,\n      validator: {\n        validate: (value, args): boolean => isBoolean(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a boolean value', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/typechecker/IsDate.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_DATE = 'isDate';\n\n/**\n * Checks if a given value is a date.\n */\nexport function isDate(value: unknown): value is Date {\n  return value instanceof Date && !isNaN(value.getTime());\n}\n\n/**\n * Checks if a value is a date.\n */\nexport function IsDate(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_DATE,\n      validator: {\n        validate: (value, args): boolean => isDate(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a Date instance', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/typechecker/IsEnum.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_ENUM = 'isEnum';\n\n/**\n * Checks if a given value is the member of the provided enum.\n */\nexport function isEnum(value: unknown, entity: any): boolean {\n  const enumValues = Object.keys(entity).map(k => entity[k]);\n  return enumValues.includes(value);\n}\n\n/**\n * Returns the possible values from an enum (both simple number indexed and string indexed enums).\n */\nfunction validEnumValues(entity: any): string[] {\n  return Object.entries(entity)\n    .filter(([key, value]) => isNaN(parseInt(key)))\n    .map(([key, value]) => value as string);\n}\n\n/**\n * Checks if a given value is the member of the provided enum.\n */\nexport function IsEnum(entity: object, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_ENUM,\n      constraints: [entity, validEnumValues(entity)],\n      validator: {\n        validate: (value, args): boolean => isEnum(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be one of the following values: $constraint2',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/typechecker/IsInt.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_INT = 'isInt';\n\n/**\n * Checks if value is an integer.\n */\nexport function isInt(val: unknown): val is Number {\n  return typeof val === 'number' && Number.isInteger(val);\n}\n\n/**\n * Checks if value is an integer.\n */\nexport function IsInt(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_INT,\n      validator: {\n        validate: (value, args): boolean => isInt(value),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be an integer number',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/typechecker/IsNumber.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_NUMBER = 'isNumber';\n\n/**\n * Options to be passed to IsNumber decorator.\n */\nexport interface IsNumberOptions {\n  allowNaN?: boolean;\n  allowInfinity?: boolean;\n  maxDecimalPlaces?: number;\n}\n\n/**\n * Checks if a given value is a number.\n */\nexport function isNumber(value: unknown, options: IsNumberOptions = {}): value is number {\n  if (typeof value !== 'number') {\n    return false;\n  }\n\n  if (value === Infinity || value === -Infinity) {\n    return !!options.allowInfinity;\n  }\n\n  if (Number.isNaN(value)) {\n    return !!options.allowNaN;\n  }\n\n  if (options.maxDecimalPlaces !== undefined) {\n    let decimalPlaces = 0;\n    if (value % 1 !== 0) {\n      decimalPlaces = value.toString().split('.')[1].length;\n    }\n    if (decimalPlaces > options.maxDecimalPlaces) {\n      return false;\n    }\n  }\n\n  return Number.isFinite(value);\n}\n\n/**\n * Checks if a value is a number.\n */\nexport function IsNumber(options: IsNumberOptions = {}, validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_NUMBER,\n      constraints: [options],\n      validator: {\n        validate: (value, args): boolean => isNumber(value, args?.constraints[0]),\n        defaultMessage: buildMessage(\n          eachPrefix => eachPrefix + '$property must be a number conforming to the specified constraints',\n          validationOptions\n        ),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/typechecker/IsObject.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_OBJECT = 'isObject';\n\n/**\n * Checks if the value is valid Object.\n * Returns false if the value is not an object.\n */\nexport function isObject<T = object>(value: unknown): value is T {\n  return value != null && (typeof value === 'object' || typeof value === 'function') && !Array.isArray(value);\n}\n\n/**\n * Checks if the value is valid Object.\n * Returns false if the value is not an object.\n */\nexport function IsObject(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_OBJECT,\n      validator: {\n        validate: (value, args): boolean => isObject(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be an object', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/decorator/typechecker/IsString.ts",
    "content": "import { ValidationOptions } from '../ValidationOptions';\nimport { buildMessage, ValidateBy } from '../common/ValidateBy';\n\nexport const IS_STRING = 'isString';\n\n/**\n * Checks if a given value is a real string.\n */\nexport function isString(value: unknown): value is string {\n  return value instanceof String || typeof value === 'string';\n}\n\n/**\n * Checks if a given value is a real string.\n */\nexport function IsString(validationOptions?: ValidationOptions): PropertyDecorator {\n  return ValidateBy(\n    {\n      name: IS_STRING,\n      validator: {\n        validate: (value, args): boolean => isString(value),\n        defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be a string', validationOptions),\n      },\n    },\n    validationOptions\n  );\n}\n"
  },
  {
    "path": "src/index.ts",
    "content": "import { ValidationError } from './validation/ValidationError';\nimport { ValidatorOptions } from './validation/ValidatorOptions';\nimport { ValidationSchema } from './validation-schema/ValidationSchema';\nimport { getMetadataStorage } from './metadata/MetadataStorage';\nimport { Validator } from './validation/Validator';\nimport { getFromContainer } from './container';\n\n// -------------------------------------------------------------------------\n// Export everything api users needs\n// -------------------------------------------------------------------------\n\nexport * from './container';\nexport * from './decorator/decorators';\nexport * from './decorator/ValidationOptions';\nexport * from './validation/ValidatorConstraintInterface';\nexport * from './validation/ValidationError';\nexport * from './validation/ValidatorOptions';\nexport * from './validation/ValidationArguments';\nexport * from './validation/ValidationTypes';\nexport * from './validation/Validator';\nexport * from './validation-schema/ValidationSchema';\nexport * from './register-decorator';\nexport * from './metadata/MetadataStorage';\n\n// -------------------------------------------------------------------------\n// Shortcut methods for api users\n// -------------------------------------------------------------------------\n\n/**\n * Validates given object.\n */\nexport function validate(object: object, validatorOptions?: ValidatorOptions): Promise<ValidationError[]>;\n\n/**\n * Validates given object by a given validation schema.\n */\nexport function validate(\n  schemaName: string,\n  object: object,\n  validatorOptions?: ValidatorOptions\n): Promise<ValidationError[]>;\n\n/**\n * Validates given object by object's decorators or given validation schema.\n */\nexport function validate(\n  schemaNameOrObject: object | string,\n  objectOrValidationOptions?: object | ValidatorOptions,\n  maybeValidatorOptions?: ValidatorOptions\n): Promise<ValidationError[]> {\n  if (typeof schemaNameOrObject === 'string') {\n    return getFromContainer(Validator).validate(\n      schemaNameOrObject,\n      objectOrValidationOptions as object,\n      maybeValidatorOptions\n    );\n  } else {\n    return getFromContainer(Validator).validate(schemaNameOrObject, objectOrValidationOptions as ValidatorOptions);\n  }\n}\n\n/**\n * Validates given object and reject on error.\n */\nexport function validateOrReject(object: object, validatorOptions?: ValidatorOptions): Promise<void>;\n\n/**\n * Validates given object by a given validation schema and reject on error.\n */\nexport function validateOrReject(\n  schemaName: string,\n  object: object,\n  validatorOptions?: ValidatorOptions\n): Promise<void>;\n\n/**\n * Validates given object by object's decorators or given validation schema and reject on error.\n */\nexport function validateOrReject(\n  schemaNameOrObject: object | string,\n  objectOrValidationOptions?: object | ValidatorOptions,\n  maybeValidatorOptions?: ValidatorOptions\n): Promise<void> {\n  if (typeof schemaNameOrObject === 'string') {\n    return getFromContainer(Validator).validateOrReject(\n      schemaNameOrObject,\n      objectOrValidationOptions as object,\n      maybeValidatorOptions\n    );\n  } else {\n    return getFromContainer(Validator).validateOrReject(\n      schemaNameOrObject,\n      objectOrValidationOptions as ValidatorOptions\n    );\n  }\n}\n\n/**\n * Performs sync validation of the given object.\n * Note that this method completely ignores async validations.\n * If you want to properly perform validation you need to call validate method instead.\n */\nexport function validateSync(object: object, validatorOptions?: ValidatorOptions): ValidationError[];\n\n/**\n * Validates given object by a given validation schema.\n * Note that this method completely ignores async validations.\n * If you want to properly perform validation you need to call validate method instead.\n */\nexport function validateSync(\n  schemaName: string,\n  object: object,\n  validatorOptions?: ValidatorOptions\n): ValidationError[];\n\n/**\n * Validates given object by object's decorators or given validation schema.\n * Note that this method completely ignores async validations.\n * If you want to properly perform validation you need to call validate method instead.\n */\nexport function validateSync(\n  schemaNameOrObject: object | string,\n  objectOrValidationOptions?: object | ValidatorOptions,\n  maybeValidatorOptions?: ValidatorOptions\n): ValidationError[] {\n  if (typeof schemaNameOrObject === 'string') {\n    return getFromContainer(Validator).validateSync(\n      schemaNameOrObject,\n      objectOrValidationOptions as object,\n      maybeValidatorOptions\n    );\n  } else {\n    return getFromContainer(Validator).validateSync(schemaNameOrObject, objectOrValidationOptions as ValidatorOptions);\n  }\n}\n\n/**\n * Registers a new validation schema.\n */\nexport function registerSchema(schema: ValidationSchema): void {\n  getMetadataStorage().addValidationSchema(schema);\n}\n"
  },
  {
    "path": "src/metadata/ConstraintMetadata.ts",
    "content": "import { ValidatorConstraintInterface } from '../validation/ValidatorConstraintInterface';\nimport { getFromContainer } from '../container';\n\n/**\n * This metadata interface contains information for custom validators.\n */\nexport class ConstraintMetadata {\n  // -------------------------------------------------------------------------\n  // Properties\n  // -------------------------------------------------------------------------\n\n  /**\n   * Target class which performs validation.\n   */\n  target: Function;\n\n  /**\n   * Custom validation's name, that will be used as validation error type.\n   */\n  name: string;\n\n  /**\n   * Indicates if this validation is asynchronous or not.\n   */\n  async: boolean;\n\n  // -------------------------------------------------------------------------\n  // Constructor\n  // -------------------------------------------------------------------------\n\n  constructor(target: Function, name?: string, async: boolean = false) {\n    this.target = target;\n    this.name = name;\n    this.async = async;\n  }\n\n  // -------------------------------------------------------------------------\n  // Accessors\n  // -------------------------------------------------------------------------\n\n  /**\n   * Instance of the target custom validation class which performs validation.\n   */\n  get instance(): ValidatorConstraintInterface {\n    return getFromContainer<ValidatorConstraintInterface>(this.target);\n  }\n}\n"
  },
  {
    "path": "src/metadata/MetadataStorage.ts",
    "content": "import { ValidationMetadata } from './ValidationMetadata';\nimport { ConstraintMetadata } from './ConstraintMetadata';\nimport { ValidationSchema } from '../validation-schema/ValidationSchema';\nimport { ValidationSchemaToMetadataTransformer } from '../validation-schema/ValidationSchemaToMetadataTransformer';\nimport { getGlobal } from '../utils';\n\n/**\n * Storage all metadatas.\n */\nexport class MetadataStorage {\n  // -------------------------------------------------------------------------\n  // Private properties\n  // -------------------------------------------------------------------------\n\n  private validationMetadatas: Map<any, ValidationMetadata[]> = new Map();\n  private constraintMetadatas: Map<any, ConstraintMetadata[]> = new Map();\n\n  get hasValidationMetaData(): boolean {\n    return !!this.validationMetadatas.size;\n  }\n\n  // -------------------------------------------------------------------------\n  // Public Methods\n  // -------------------------------------------------------------------------\n\n  /**\n   * Adds a new validation metadata.\n   */\n  addValidationSchema(schema: ValidationSchema): void {\n    const validationMetadatas = new ValidationSchemaToMetadataTransformer().transform(schema);\n    validationMetadatas.forEach(validationMetadata => this.addValidationMetadata(validationMetadata));\n  }\n\n  /**\n   * Adds a new validation metadata.\n   */\n  addValidationMetadata(metadata: ValidationMetadata): void {\n    const existingMetadata = this.validationMetadatas.get(metadata.target);\n\n    if (existingMetadata) {\n      existingMetadata.push(metadata);\n    } else {\n      this.validationMetadatas.set(metadata.target, [metadata]);\n    }\n  }\n\n  /**\n   * Adds a new constraint metadata.\n   */\n  addConstraintMetadata(metadata: ConstraintMetadata): void {\n    const existingMetadata = this.constraintMetadatas.get(metadata.target);\n\n    if (existingMetadata) {\n      existingMetadata.push(metadata);\n    } else {\n      this.constraintMetadatas.set(metadata.target, [metadata]);\n    }\n  }\n\n  /**\n   * Groups metadata by their property names.\n   */\n  groupByPropertyName(metadata: ValidationMetadata[]): { [propertyName: string]: ValidationMetadata[] } {\n    const grouped: { [propertyName: string]: ValidationMetadata[] } = {};\n    metadata.forEach(metadata => {\n      if (!grouped[metadata.propertyName]) grouped[metadata.propertyName] = [];\n      grouped[metadata.propertyName].push(metadata);\n    });\n    return grouped;\n  }\n\n  /**\n   * Gets all validation metadatas for the given object with the given groups.\n   */\n  getTargetValidationMetadatas(\n    targetConstructor: Function,\n    targetSchema: string,\n    always: boolean,\n    strictGroups: boolean,\n    groups?: string[]\n  ): ValidationMetadata[] {\n    const includeMetadataBecauseOfAlwaysOption = (metadata: ValidationMetadata): boolean => {\n      // `metadata.always` overrides global default.\n      if (typeof metadata.always !== 'undefined') return metadata.always;\n\n      // `metadata.groups` overrides global default.\n      if (metadata.groups && metadata.groups.length) return false;\n\n      // Use global default.\n      return always;\n    };\n\n    const excludeMetadataBecauseOfStrictGroupsOption = (metadata: ValidationMetadata): boolean => {\n      if (strictGroups) {\n        // Validation is not using groups.\n        if (!groups || !groups.length) {\n          // `metadata.groups` has at least one group.\n          if (metadata.groups && metadata.groups.length) return true;\n        }\n      }\n\n      return false;\n    };\n\n    // get directly related to a target metadatas\n    const filteredForOriginalMetadatasSearch = this.validationMetadatas.get(targetConstructor) || [];\n    const originalMetadatas = filteredForOriginalMetadatasSearch.filter(metadata => {\n      if (metadata.target !== targetConstructor && metadata.target !== targetSchema) return false;\n      if (includeMetadataBecauseOfAlwaysOption(metadata)) return true;\n      if (excludeMetadataBecauseOfStrictGroupsOption(metadata)) return false;\n      if (groups && groups.length > 0)\n        return metadata.groups && !!metadata.groups.find(group => groups.indexOf(group) !== -1);\n\n      return true;\n    });\n\n    // get metadatas for inherited classes\n    const filteredForInheritedMetadatasSearch = [];\n    for (const [key, value] of this.validationMetadatas.entries()) {\n      if (targetConstructor.prototype instanceof key) {\n        filteredForInheritedMetadatasSearch.push(...value);\n      }\n    }\n    const inheritedMetadatas = filteredForInheritedMetadatasSearch.filter(metadata => {\n      // if target is a string it's means we validate against a schema, and there is no inheritance support for schemas\n      if (typeof metadata.target === 'string') return false;\n      if (metadata.target === targetConstructor) return false;\n      if (metadata.target instanceof Function && !(targetConstructor.prototype instanceof metadata.target))\n        return false;\n      if (includeMetadataBecauseOfAlwaysOption(metadata)) return true;\n      if (excludeMetadataBecauseOfStrictGroupsOption(metadata)) return false;\n      if (groups && groups.length > 0)\n        return metadata.groups && !!metadata.groups.find(group => groups.indexOf(group) !== -1);\n\n      return true;\n    });\n\n    // filter out duplicate metadatas, prefer original metadatas instead of inherited metadatas\n    const uniqueInheritedMetadatas = inheritedMetadatas.filter(inheritedMetadata => {\n      return !originalMetadatas.find(originalMetadata => {\n        return (\n          originalMetadata.propertyName === inheritedMetadata.propertyName &&\n          originalMetadata.type === inheritedMetadata.type\n        );\n      });\n    });\n\n    return originalMetadatas.concat(uniqueInheritedMetadatas);\n  }\n\n  /**\n   * Gets all validator constraints for the given object.\n   */\n  getTargetValidatorConstraints(target: Function): ConstraintMetadata[] {\n    return this.constraintMetadatas.get(target) || [];\n  }\n}\n\n/**\n * Gets metadata storage.\n * Metadata storage follows the best practices and stores metadata in a global variable.\n */\nexport function getMetadataStorage(): MetadataStorage {\n  const global = getGlobal();\n\n  if (!global.classValidatorMetadataStorage) {\n    global.classValidatorMetadataStorage = new MetadataStorage();\n  }\n\n  return global.classValidatorMetadataStorage;\n}\n"
  },
  {
    "path": "src/metadata/ValidationMetadata.ts",
    "content": "import { ValidationMetadataArgs } from './ValidationMetadataArgs';\nimport { ValidationArguments } from '../validation/ValidationArguments';\n\n/**\n * This metadata contains validation rules.\n */\nexport class ValidationMetadata {\n  // -------------------------------------------------------------------------\n  // Properties\n  // -------------------------------------------------------------------------\n\n  /**\n   * Validation type.\n   */\n  type: string;\n\n  /**\n   * Validator name.\n   */\n  name?: string;\n\n  /**\n   * Target class to which this validation is applied.\n   */\n  target: Function | string;\n\n  /**\n   * Property of the object to be validated.\n   */\n  propertyName: string;\n\n  /**\n   * Constraint class that performs validation. Used only for custom validations.\n   */\n  constraintCls: Function;\n\n  /**\n   * Array of constraints of this validation.\n   */\n  constraints: any[];\n\n  /**\n   * Validation message to be shown in the case of error.\n   */\n  message: string | ((args: ValidationArguments) => string);\n\n  /**\n   * Validation groups used for this validation.\n   */\n  groups: string[] = [];\n\n  /**\n   * Indicates if validation must be performed always, no matter of validation groups used.\n   */\n  always?: boolean;\n\n  /**\n   * Specifies if validated value is an array and each of its item must be validated.\n   */\n  each: boolean = false;\n\n  /*\n   * A transient set of data passed through to the validation result for response mapping\n   */\n  context?: any = undefined;\n\n  /**\n   * validation will be performed while the result is true\n   */\n  validateIf?: (object: any, value: any) => boolean;\n\n  /**\n   * Extra options specific to validation type.\n   */\n  validationTypeOptions: any;\n\n  // -------------------------------------------------------------------------\n  // Constructor\n  // -------------------------------------------------------------------------\n\n  constructor(args: ValidationMetadataArgs) {\n    this.type = args.type;\n    this.name = args.name;\n    this.target = args.target;\n    this.propertyName = args.propertyName;\n    this.constraints = args?.constraints;\n    this.constraintCls = args.constraintCls;\n    this.validationTypeOptions = args.validationTypeOptions;\n    if (args.validationOptions) {\n      this.message = args.validationOptions.message;\n      this.groups = args.validationOptions.groups;\n      this.always = args.validationOptions.always;\n      this.each = args.validationOptions.each;\n      this.context = args.validationOptions.context;\n      this.validateIf = args.validationOptions.validateIf;\n    }\n  }\n}\n"
  },
  {
    "path": "src/metadata/ValidationMetadataArgs.ts",
    "content": "import { ValidationOptions } from '../decorator/ValidationOptions';\n\n/**\n * Constructor arguments for ValidationMetadata class.\n */\nexport interface ValidationMetadataArgs {\n  /**\n   * Validation type.\n   */\n  type: string;\n\n  /**\n   * Validator name.\n   */\n  name?: string;\n\n  /**\n   * Object that is used to be validated.\n   */\n  target: Function | string;\n\n  /**\n   * Property of the object to be validated.\n   */\n  propertyName: string;\n\n  /**\n   * Constraint class that performs validation. Used only for custom validations.\n   */\n  constraintCls?: Function;\n\n  /**\n   * Array of constraints of this validation.\n   */\n  constraints?: any[];\n\n  /**\n   * Validation options.\n   */\n  validationOptions?: ValidationOptions;\n\n  /**\n   * Extra options specific to validation type.\n   */\n  validationTypeOptions?: any;\n}\n"
  },
  {
    "path": "src/register-decorator.ts",
    "content": "import { ConstraintMetadata } from './metadata/ConstraintMetadata';\nimport { ValidatorConstraintInterface } from './validation/ValidatorConstraintInterface';\nimport { ValidationMetadata } from './metadata/ValidationMetadata';\nimport { ValidationMetadataArgs } from './metadata/ValidationMetadataArgs';\nimport { ValidationTypes } from './validation/ValidationTypes';\nimport { ValidationArguments } from './validation/ValidationArguments';\nimport { getFromContainer } from './container';\nimport { MetadataStorage, getMetadataStorage } from './metadata/MetadataStorage';\nimport { ValidationOptions } from './decorator/ValidationOptions';\n\nexport interface ValidationDecoratorOptions {\n  /**\n   * Target object to be validated.\n   */\n  target: Function;\n\n  /**\n   * Target object's property name to be validated.\n   */\n  propertyName: string;\n\n  /**\n   * Name of the validation that is being registered.\n   */\n  name?: string;\n\n  /**\n   * Indicates if this decorator will perform async validation.\n   */\n  async?: boolean;\n\n  /**\n   * Validator options.\n   */\n  options?: ValidationOptions;\n\n  /**\n   * Array of validation constraints.\n   */\n  constraints?: any[];\n\n  /**\n   * Validator that performs validation.\n   */\n  validator: ValidatorConstraintInterface | Function;\n}\n\n/**\n * Registers a custom validation decorator.\n */\nexport function registerDecorator(options: ValidationDecoratorOptions): void {\n  let constraintCls: Function;\n  if (options.validator instanceof Function) {\n    constraintCls = options.validator;\n    const constraintClasses = getFromContainer(MetadataStorage).getTargetValidatorConstraints(options.validator);\n    if (constraintClasses.length > 1) {\n      throw `More than one implementation of ValidatorConstraintInterface found for validator on: ${options.target.name}:${options.propertyName}`;\n    }\n  } else {\n    const validator = options.validator;\n    constraintCls = class CustomConstraint implements ValidatorConstraintInterface {\n      validate(value: any, validationArguments?: ValidationArguments): Promise<boolean> | boolean {\n        return validator.validate(value, validationArguments);\n      }\n\n      defaultMessage(validationArguments?: ValidationArguments): string {\n        if (validator.defaultMessage) {\n          return validator.defaultMessage(validationArguments);\n        }\n\n        return '';\n      }\n    };\n    getMetadataStorage().addConstraintMetadata(new ConstraintMetadata(constraintCls, options.name, options.async));\n  }\n\n  const validationMetadataArgs: ValidationMetadataArgs = {\n    type: options.name && ValidationTypes.isValid(options.name) ? options.name : ValidationTypes.CUSTOM_VALIDATION,\n    name: options.name,\n    target: options.target,\n    propertyName: options.propertyName,\n    validationOptions: options.options,\n    constraintCls: constraintCls,\n    constraints: options.constraints,\n  };\n  getMetadataStorage().addValidationMetadata(new ValidationMetadata(validationMetadataArgs));\n}\n"
  },
  {
    "path": "src/utils/convert-to-array.util.ts",
    "content": "/**\n * Convert Map, Set to Array\n */\nexport function convertToArray<T>(val: Array<T> | Set<T> | Map<any, T>): Array<T> {\n  if (val instanceof Map) {\n    return Array.from(val.values());\n  }\n  return Array.isArray(val) ? val : Array.from(val);\n}\n"
  },
  {
    "path": "src/utils/get-global.util.ts",
    "content": "/**\n * This function returns the global object across Node and browsers.\n *\n * Note: `globalThis` is the standardized approach however it has been added to\n * Node.js in version 12. We need to include this snippet until Node 12 EOL.\n */\nexport function getGlobal() {\n  if (typeof globalThis !== 'undefined') {\n    return globalThis;\n  }\n\n  if (typeof global !== 'undefined') {\n    return global;\n  }\n\n  // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n  // @ts-ignore: Cannot find name 'window'.\n  if (typeof window !== 'undefined') {\n    // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n    // @ts-ignore: Cannot find name 'window'.\n    return window;\n  }\n\n  // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n  // @ts-ignore: Cannot find name 'self'.\n  if (typeof self !== 'undefined') {\n    // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n    // @ts-ignore: Cannot find name 'self'.\n    return self;\n  }\n}\n"
  },
  {
    "path": "src/utils/index.ts",
    "content": "export * from './convert-to-array.util';\nexport * from './get-global.util';\nexport * from './is-promise.util';\n"
  },
  {
    "path": "src/utils/is-promise.util.ts",
    "content": "// https://github.com/TylorS/typed-is-promise/blob/abf1514e1b6961adfc75765476b0debb96b2c3ae/src/index.ts\n\nexport function isPromise<T = any>(p: any): p is Promise<T> {\n  return p !== null && typeof p === 'object' && typeof p.then === 'function';\n}\n"
  },
  {
    "path": "src/validation/ValidationArguments.ts",
    "content": "/**\n * Arguments being sent to message builders - user can create message either by simply returning a string,\n * either by returning a function that accepts MessageArguments and returns a message string built based on these arguments.\n */\nexport interface ValidationArguments {\n  /**\n   * Validating value.\n   */\n  value: any;\n\n  /**\n   * Constraints set by this validation type.\n   */\n  constraints: any[];\n\n  /**\n   * Name of the target that is being validated.\n   */\n  targetName: string;\n\n  /**\n   * Object that is being validated.\n   */\n  object: object;\n\n  /**\n   * Name of the object's property being validated.\n   */\n  property: string;\n}\n"
  },
  {
    "path": "src/validation/ValidationError.ts",
    "content": "/**\n * Validation error description.\n */\nexport class ValidationError {\n  /**\n   * Object that was validated.\n   *\n   * OPTIONAL - configurable via the ValidatorOptions.validationError.target option\n   */\n  target?: object;\n\n  /**\n   * Object's property that haven't pass validation.\n   */\n  property: string;\n\n  /**\n   * Value that haven't pass a validation.\n   *\n   * OPTIONAL - configurable via the ValidatorOptions.validationError.value option\n   */\n  value?: any;\n\n  /**\n   * Constraints that failed validation with error messages.\n   */\n  constraints?: {\n    [type: string]: string;\n  };\n\n  /**\n   * Contains all nested validation errors of the property.\n   */\n  children?: ValidationError[];\n\n  /*\n   * A transient set of data passed through to the validation result for response mapping\n   */\n  contexts?: {\n    [type: string]: any;\n  };\n\n  /**\n   *\n   * @param shouldDecorate decorate the message with ANSI formatter escape codes for better readability\n   * @param hasParent true when the error is a child of an another one\n   * @param parentPath path as string to the parent of this property\n   * @param showConstraintMessages show constraint messages instead of constraint names\n   */\n  toString(\n    shouldDecorate: boolean = false,\n    hasParent: boolean = false,\n    parentPath: string = ``,\n    showConstraintMessages: boolean = false\n  ): string {\n    const boldStart = shouldDecorate ? `\\x1b[1m` : ``;\n    const boldEnd = shouldDecorate ? `\\x1b[22m` : ``;\n    const constraintsToString = () =>\n      (showConstraintMessages ? Object.values : Object.keys)(this.constraints ?? {}).join(`, `);\n    const propConstraintFailed = (propertyName: string): string =>\n      ` - property ${boldStart}${parentPath}${propertyName}${boldEnd} has failed the following constraints: ${boldStart}${constraintsToString()}${boldEnd} \\n`;\n\n    if (!hasParent) {\n      return (\n        `An instance of ${boldStart}${\n          this.target ? this.target.constructor.name : 'an object'\n        }${boldEnd} has failed the validation:\\n` +\n        (this.constraints ? propConstraintFailed(this.property) : ``) +\n        (this.children\n          ? this.children\n              .map(childError => childError.toString(shouldDecorate, true, this.property, showConstraintMessages))\n              .join(``)\n          : ``)\n      );\n    } else {\n      // we format numbers as array indexes for better readability.\n      const formattedProperty = Number.isInteger(+this.property)\n        ? `[${this.property}]`\n        : `${parentPath ? `.` : ``}${this.property}`;\n\n      if (this.constraints) {\n        return propConstraintFailed(formattedProperty);\n      } else {\n        return this.children\n          ? this.children\n              .map(childError =>\n                childError.toString(shouldDecorate, true, `${parentPath}${formattedProperty}`, showConstraintMessages)\n              )\n              .join(``)\n          : ``;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/validation/ValidationExecutor.ts",
    "content": "import { Validator } from './Validator';\nimport { ValidationError } from './ValidationError';\nimport { ValidationMetadata } from '../metadata/ValidationMetadata';\nimport { ValidatorOptions } from './ValidatorOptions';\nimport { ValidationTypes } from './ValidationTypes';\nimport { ConstraintMetadata } from '../metadata/ConstraintMetadata';\nimport { ValidationArguments } from './ValidationArguments';\nimport { ValidationUtils } from './ValidationUtils';\nimport { isPromise, convertToArray } from '../utils';\nimport { getMetadataStorage } from '../metadata/MetadataStorage';\n\n/**\n * Executes validation over given object.\n */\nexport class ValidationExecutor {\n  // -------------------------------------------------------------------------\n  // Properties\n  // -------------------------------------------------------------------------\n\n  awaitingPromises: Promise<any>[] = [];\n  ignoreAsyncValidations: boolean = false;\n\n  // -------------------------------------------------------------------------\n  // Private Properties\n  // -------------------------------------------------------------------------\n\n  private metadataStorage = getMetadataStorage();\n\n  // -------------------------------------------------------------------------\n  // Constructor\n  // -------------------------------------------------------------------------\n\n  constructor(private validator: Validator, private validatorOptions?: ValidatorOptions) {}\n\n  // -------------------------------------------------------------------------\n  // Public Methods\n  // -------------------------------------------------------------------------\n\n  execute(object: object, targetSchema: string, validationErrors: ValidationError[]): void {\n    /**\n     * If there is no metadata registered it means possibly the dependencies are not flatterned and\n     * more than one instance is used.\n     *\n     * TODO: This needs proper handling, forcing to use the same container or some other proper solution.\n     */\n    if (!this.metadataStorage.hasValidationMetaData && this.validatorOptions?.enableDebugMessages === true) {\n      console.warn(\n        `No validation metadata found. No validation will be  performed. There are multiple possible reasons:\\n` +\n          `  - There may be multiple class-validator versions installed. You will need to flatten your dependencies to fix the issue.\\n` +\n          `  - This validation runs before any file with validation decorator was parsed by NodeJS.`\n      );\n    }\n\n    const groups = this.validatorOptions ? this.validatorOptions.groups : undefined;\n    const strictGroups = (this.validatorOptions && this.validatorOptions.strictGroups) || false;\n    const always = (this.validatorOptions && this.validatorOptions.always) || false;\n    /** Forbid unknown values are turned on by default and any other value than false will enable it. */\n    const forbidUnknownValues =\n      this.validatorOptions?.forbidUnknownValues === undefined || this.validatorOptions.forbidUnknownValues !== false;\n\n    const targetMetadatas = this.metadataStorage.getTargetValidationMetadatas(\n      object.constructor,\n      targetSchema,\n      always,\n      strictGroups,\n      groups\n    );\n    const groupedMetadatas = this.metadataStorage.groupByPropertyName(targetMetadatas);\n\n    if (forbidUnknownValues && !targetMetadatas.length) {\n      const validationError = new ValidationError();\n\n      if (\n        !this.validatorOptions ||\n        !this.validatorOptions.validationError ||\n        this.validatorOptions.validationError.target === undefined ||\n        this.validatorOptions.validationError.target === true\n      )\n        validationError.target = object;\n\n      validationError.value = undefined;\n      validationError.property = undefined;\n      validationError.children = [];\n      validationError.constraints = { unknownValue: 'an unknown value was passed to the validate function' };\n\n      validationErrors.push(validationError);\n\n      return;\n    }\n\n    if (this.validatorOptions && this.validatorOptions.whitelist)\n      this.whitelist(object, groupedMetadatas, validationErrors);\n\n    // General validation\n    Object.keys(groupedMetadatas).forEach(propertyName => {\n      const value = (object as any)[propertyName];\n      const definedMetadatas = groupedMetadatas[propertyName].filter(\n        metadata => metadata.type === ValidationTypes.IS_DEFINED\n      );\n      const metadatas = groupedMetadatas[propertyName].filter(\n        metadata => metadata.type !== ValidationTypes.IS_DEFINED && metadata.type !== ValidationTypes.WHITELIST\n      );\n\n      if (\n        value instanceof Promise &&\n        metadatas.find(metadata => metadata.type === ValidationTypes.PROMISE_VALIDATION)\n      ) {\n        this.awaitingPromises.push(\n          value.then(resolvedValue => {\n            this.performValidations(object, resolvedValue, propertyName, definedMetadatas, metadatas, validationErrors);\n          })\n        );\n      } else {\n        this.performValidations(object, value, propertyName, definedMetadatas, metadatas, validationErrors);\n      }\n    });\n  }\n\n  whitelist(\n    object: any,\n    groupedMetadatas: { [propertyName: string]: ValidationMetadata[] },\n    validationErrors: ValidationError[]\n  ): void {\n    const notAllowedProperties: string[] = [];\n\n    Object.keys(object).forEach(propertyName => {\n      // does this property have no metadata?\n      if (!groupedMetadatas[propertyName] || groupedMetadatas[propertyName].length === 0)\n        notAllowedProperties.push(propertyName);\n    });\n\n    if (notAllowedProperties.length > 0) {\n      if (this.validatorOptions && this.validatorOptions.forbidNonWhitelisted) {\n        // throw errors\n        notAllowedProperties.forEach(property => {\n          const validationError: ValidationError = this.generateValidationError(object, object[property], property);\n          validationError.constraints = { [ValidationTypes.WHITELIST]: `property ${property} should not exist` };\n          validationError.children = undefined;\n          validationErrors.push(validationError);\n        });\n      } else {\n        // strip non allowed properties\n        notAllowedProperties.forEach(property => delete object[property]);\n      }\n    }\n  }\n\n  stripEmptyErrors(errors: ValidationError[]): ValidationError[] {\n    return errors.filter(error => {\n      if (error.children) {\n        error.children = this.stripEmptyErrors(error.children);\n      }\n\n      if (Object.keys(error.constraints).length === 0) {\n        if (error.children.length === 0) {\n          return false;\n        } else {\n          delete error.constraints;\n        }\n      }\n\n      return true;\n    });\n  }\n\n  // -------------------------------------------------------------------------\n  // Private Methods\n  // -------------------------------------------------------------------------\n\n  private performValidations(\n    object: any,\n    value: any,\n    propertyName: string,\n    definedMetadatas: ValidationMetadata[],\n    metadatas: ValidationMetadata[],\n    validationErrors: ValidationError[]\n  ): void {\n    const customValidationMetadatas = metadatas.filter(metadata => metadata.type === ValidationTypes.CUSTOM_VALIDATION);\n    const nestedValidationMetadatas = metadatas.filter(metadata => metadata.type === ValidationTypes.NESTED_VALIDATION);\n    const conditionalValidationMetadatas = metadatas.filter(\n      metadata => metadata.type === ValidationTypes.CONDITIONAL_VALIDATION\n    );\n\n    const validationError = this.generateValidationError(object, value, propertyName);\n    validationErrors.push(validationError);\n\n    const canValidate = this.conditionalValidations(object, value, conditionalValidationMetadatas);\n    if (!canValidate) {\n      return;\n    }\n\n    // handle IS_DEFINED validation type the special way - it should work no matter skipUndefinedProperties/skipMissingProperties is set or not\n    this.customValidations(object, value, definedMetadatas, validationError);\n    this.mapContexts(object, value, definedMetadatas, validationError);\n\n    if (value === undefined && this.validatorOptions && this.validatorOptions.skipUndefinedProperties === true) {\n      return;\n    }\n\n    if (value === null && this.validatorOptions && this.validatorOptions.skipNullProperties === true) {\n      return;\n    }\n\n    if (\n      (value === null || value === undefined) &&\n      this.validatorOptions &&\n      this.validatorOptions.skipMissingProperties === true\n    ) {\n      return;\n    }\n\n    this.customValidations(object, value, customValidationMetadatas, validationError);\n    this.nestedValidations(value, nestedValidationMetadatas, validationError);\n\n    this.mapContexts(object, value, metadatas, validationError);\n    this.mapContexts(object, value, customValidationMetadatas, validationError);\n  }\n\n  private generateValidationError(object: object, value: any, propertyName: string): ValidationError {\n    const validationError = new ValidationError();\n\n    if (\n      !this.validatorOptions ||\n      !this.validatorOptions.validationError ||\n      this.validatorOptions.validationError.target === undefined ||\n      this.validatorOptions.validationError.target === true\n    )\n      validationError.target = object;\n\n    if (\n      !this.validatorOptions ||\n      !this.validatorOptions.validationError ||\n      this.validatorOptions.validationError.value === undefined ||\n      this.validatorOptions.validationError.value === true\n    )\n      validationError.value = value;\n\n    validationError.property = propertyName;\n    validationError.children = [];\n    validationError.constraints = {};\n\n    return validationError;\n  }\n\n  private conditionalValidations(object: object, value: any, metadatas: ValidationMetadata[]): ValidationMetadata[] {\n    return metadatas\n      .map(metadata => metadata.constraints[0](object, value))\n      .reduce((resultA, resultB) => resultA && resultB, true);\n  }\n\n  private customValidations(object: object, value: any, metadatas: ValidationMetadata[], error: ValidationError): void {\n    metadatas.forEach(metadata => {\n      const getValidationArguments = () => {\n        const validationArguments: ValidationArguments = {\n          targetName: object.constructor ? (object.constructor as any).name : undefined,\n          property: metadata.propertyName,\n          object: object,\n          value: value,\n          constraints: metadata.constraints,\n        };\n        return validationArguments;\n      };\n      if (metadata.validateIf) {\n        const shouldValidate = metadata.validateIf(object, value);\n        if (!shouldValidate) return;\n      }\n      this.metadataStorage.getTargetValidatorConstraints(metadata.constraintCls).forEach(customConstraintMetadata => {\n        if (customConstraintMetadata.async && this.ignoreAsyncValidations) return;\n        if (\n          this.validatorOptions &&\n          this.validatorOptions.stopAtFirstError &&\n          Object.keys(error.constraints || {}).length > 0\n        )\n          return;\n\n        const validationArguments = getValidationArguments();\n\n        if (!metadata.each || !(Array.isArray(value) || value instanceof Set || value instanceof Map)) {\n          const validatedValue = customConstraintMetadata.instance.validate(value, validationArguments);\n          if (isPromise(validatedValue)) {\n            const promise = validatedValue.then(isValid => {\n              if (!isValid) {\n                const [type, message] = this.createValidationError(object, value, metadata, customConstraintMetadata);\n                error.constraints[type] = message;\n                if (metadata.context) {\n                  if (!error.contexts) {\n                    error.contexts = {};\n                  }\n                  error.contexts[type] = Object.assign(error.contexts[type] || {}, metadata.context);\n                }\n              }\n            });\n            this.awaitingPromises.push(promise);\n          } else {\n            if (!validatedValue) {\n              const [type, message] = this.createValidationError(object, value, metadata, customConstraintMetadata);\n              error.constraints[type] = message;\n            }\n          }\n\n          return;\n        }\n\n        // convert set and map into array\n        const arrayValue = convertToArray(value);\n        // Validation needs to be applied to each array item\n        const validatedSubValues = arrayValue.map((subValue: any) =>\n          customConstraintMetadata.instance.validate(subValue, validationArguments)\n        );\n        const validationIsAsync = validatedSubValues.some((validatedSubValue: boolean | Promise<boolean>) =>\n          isPromise(validatedSubValue)\n        );\n\n        if (validationIsAsync) {\n          // Wrap plain values (if any) in promises, so that all are async\n          const asyncValidatedSubValues = validatedSubValues.map((validatedSubValue: boolean | Promise<boolean>) =>\n            isPromise(validatedSubValue) ? validatedSubValue : Promise.resolve(validatedSubValue)\n          );\n          const asyncValidationIsFinishedPromise = Promise.all(asyncValidatedSubValues).then(\n            (flatValidatedValues: boolean[]) => {\n              const validationResult = flatValidatedValues.every((isValid: boolean) => isValid);\n              if (!validationResult) {\n                const [type, message] = this.createValidationError(object, value, metadata, customConstraintMetadata);\n                error.constraints[type] = message;\n                if (metadata.context) {\n                  if (!error.contexts) {\n                    error.contexts = {};\n                  }\n                  error.contexts[type] = Object.assign(error.contexts[type] || {}, metadata.context);\n                }\n              }\n            }\n          );\n\n          this.awaitingPromises.push(asyncValidationIsFinishedPromise);\n\n          return;\n        }\n\n        const validationResult = validatedSubValues.every((isValid: boolean) => isValid);\n        if (!validationResult) {\n          const [type, message] = this.createValidationError(object, value, metadata, customConstraintMetadata);\n          error.constraints[type] = message;\n        }\n      });\n    });\n  }\n\n  private nestedValidations(value: any, metadatas: ValidationMetadata[], error: ValidationError): void {\n    if (value === void 0) {\n      return;\n    }\n\n    metadatas.forEach(metadata => {\n      if (metadata.type !== ValidationTypes.NESTED_VALIDATION && metadata.type !== ValidationTypes.PROMISE_VALIDATION) {\n        return;\n      } else if (\n        this.validatorOptions &&\n        this.validatorOptions.stopAtFirstError &&\n        Object.keys(error.constraints || {}).length > 0\n      ) {\n        return;\n      }\n\n      if (Array.isArray(value) || value instanceof Set || value instanceof Map) {\n        // Treats Set as an array - as index of Set value is value itself and it is common case to have Object as value\n        const arrayLikeValue = value instanceof Set ? Array.from(value) : value;\n        arrayLikeValue.forEach((subValue: any, index: any) => {\n          this.performValidations(value, subValue, index.toString(), [], metadatas, error.children);\n        });\n      } else if (value instanceof Object) {\n        const targetSchema = typeof metadata.target === 'string' ? metadata.target : metadata.target.name;\n        this.execute(value, targetSchema, error.children);\n      } else {\n        const [type, message] = this.createValidationError(metadata.target as object, value, metadata);\n        error.constraints[type] = message;\n      }\n    });\n  }\n\n  private mapContexts(object: object, value: any, metadatas: ValidationMetadata[], error: ValidationError): void {\n    return metadatas.forEach(metadata => {\n      if (metadata.context) {\n        let customConstraint;\n        if (metadata.type === ValidationTypes.CUSTOM_VALIDATION) {\n          const customConstraints = this.metadataStorage.getTargetValidatorConstraints(metadata.constraintCls);\n          customConstraint = customConstraints[0];\n        }\n\n        const type = this.getConstraintType(metadata, customConstraint);\n\n        if (error.constraints[type]) {\n          if (!error.contexts) {\n            error.contexts = {};\n          }\n\n          error.contexts[type] = Object.assign(error.contexts[type] || {}, metadata.context);\n        }\n      }\n    });\n  }\n\n  private createValidationError(\n    object: object,\n    value: any,\n    metadata: ValidationMetadata,\n    customValidatorMetadata?: ConstraintMetadata\n  ): [string, string] {\n    const targetName = object.constructor ? (object.constructor as any).name : undefined;\n    const type = this.getConstraintType(metadata, customValidatorMetadata);\n    const validationArguments: ValidationArguments = {\n      targetName: targetName,\n      property: metadata.propertyName,\n      object: object,\n      value: value,\n      constraints: metadata.constraints,\n    };\n\n    let message = metadata.message || '';\n    if (\n      !metadata.message &&\n      (!this.validatorOptions || (this.validatorOptions && !this.validatorOptions.dismissDefaultMessages))\n    ) {\n      if (customValidatorMetadata && customValidatorMetadata.instance.defaultMessage instanceof Function) {\n        message = customValidatorMetadata.instance.defaultMessage(validationArguments);\n      }\n    }\n\n    const messageString = ValidationUtils.replaceMessageSpecialTokens(message, validationArguments);\n    return [type, messageString];\n  }\n\n  private getConstraintType(metadata: ValidationMetadata, customValidatorMetadata?: ConstraintMetadata): string {\n    const type = customValidatorMetadata && customValidatorMetadata.name ? customValidatorMetadata.name : metadata.type;\n    return type;\n  }\n}\n"
  },
  {
    "path": "src/validation/ValidationTypes.ts",
    "content": "/**\n * Validation types.\n */\nexport class ValidationTypes {\n  /* system */\n  static CUSTOM_VALIDATION = 'customValidation'; // done\n  static NESTED_VALIDATION = 'nestedValidation'; // done\n  static PROMISE_VALIDATION = 'promiseValidation'; // done\n  static CONDITIONAL_VALIDATION = 'conditionalValidation'; // done\n  static WHITELIST = 'whitelistValidation'; // done\n  static IS_DEFINED = 'isDefined'; // done\n\n  /**\n   * Checks if validation type is valid.\n   */\n  static isValid(type: string): boolean {\n    return (\n      type !== 'isValid' &&\n      type !== 'getMessage' &&\n      Object.keys(this)\n        .map(key => (this as any)[key])\n        .indexOf(type) !== -1\n    );\n  }\n}\n"
  },
  {
    "path": "src/validation/ValidationUtils.ts",
    "content": "import { ValidationArguments } from './ValidationArguments';\n\n/**\n * Convert the constraint to a string to be shown in an error\n */\nexport function constraintToString(constraint: unknown): string {\n  if (Array.isArray(constraint)) {\n    return constraint.join(', ');\n  }\n\n  if (typeof constraint === 'symbol') {\n    constraint = constraint.description;\n  }\n\n  return `${constraint}`;\n}\n\nexport class ValidationUtils {\n  static replaceMessageSpecialTokens(\n    message: string | ((args: ValidationArguments) => string),\n    validationArguments: ValidationArguments\n  ): string {\n    let messageString: string;\n    if (message instanceof Function) {\n      messageString = (message as (args: ValidationArguments) => string)(validationArguments);\n    } else if (typeof message === 'string') {\n      messageString = message;\n    }\n\n    if (messageString && Array.isArray(validationArguments.constraints)) {\n      validationArguments.constraints.forEach((constraint, index) => {\n        messageString = messageString.replace(\n          new RegExp(`\\\\$constraint${index + 1}`, 'g'),\n          constraintToString(constraint)\n        );\n      });\n    }\n\n    if (\n      messageString &&\n      validationArguments.value !== undefined &&\n      validationArguments.value !== null &&\n      ['string', 'boolean', 'number'].includes(typeof validationArguments.value)\n    )\n      messageString = messageString.replace(/\\$value/g, validationArguments.value);\n    if (messageString) messageString = messageString.replace(/\\$property/g, validationArguments.property);\n    if (messageString) messageString = messageString.replace(/\\$target/g, validationArguments.targetName);\n\n    return messageString;\n  }\n}\n"
  },
  {
    "path": "src/validation/Validator.ts",
    "content": "import { ValidationError } from './ValidationError';\nimport { ValidatorOptions } from './ValidatorOptions';\nimport { ValidationExecutor } from './ValidationExecutor';\nimport { ValidationOptions } from '../decorator/ValidationOptions';\n\n/**\n * Validator performs validation of the given object based on its metadata.\n */\nexport class Validator {\n  // -------------------------------------------------------------------------\n  // Public Methods\n  // -------------------------------------------------------------------------\n\n  /**\n   * Performs validation of the given object based on decorators used in given object class.\n   */\n  validate(object: object, options?: ValidatorOptions): Promise<ValidationError[]>;\n\n  /**\n   * Performs validation of the given object based on validation schema.\n   */\n  validate(schemaName: string, object: object, options?: ValidatorOptions): Promise<ValidationError[]>;\n\n  /**\n   * Performs validation of the given object based on decorators or validation schema.\n   */\n  validate(\n    objectOrSchemaName: object | string,\n    objectOrValidationOptions: object | ValidationOptions,\n    maybeValidatorOptions?: ValidatorOptions\n  ): Promise<ValidationError[]> {\n    return this.coreValidate(objectOrSchemaName, objectOrValidationOptions, maybeValidatorOptions);\n  }\n\n  /**\n   * Performs validation of the given object based on decorators used in given object class and reject on error.\n   */\n  validateOrReject(object: object, options?: ValidatorOptions): Promise<void>;\n\n  /**\n   * Performs validation of the given object based on validation schema and reject on error.\n   */\n  validateOrReject(schemaName: string, object: object, options?: ValidatorOptions): Promise<void>;\n\n  /**\n   * Performs validation of the given object based on decorators or validation schema and reject on error.\n   */\n  async validateOrReject(\n    objectOrSchemaName: object | string,\n    objectOrValidationOptions: object | ValidationOptions,\n    maybeValidatorOptions?: ValidatorOptions\n  ): Promise<void> {\n    const errors = await this.coreValidate(objectOrSchemaName, objectOrValidationOptions, maybeValidatorOptions);\n    if (errors.length) return Promise.reject(errors);\n  }\n\n  /**\n   * Performs validation of the given object based on decorators used in given object class.\n   * NOTE: This method completely ignores all async validations.\n   */\n  validateSync(object: object, options?: ValidatorOptions): ValidationError[];\n\n  /**\n   * Performs validation of the given object based on validation schema.\n   */\n  validateSync(schemaName: string, object: object, options?: ValidatorOptions): ValidationError[];\n\n  /**\n   * Performs validation of the given object based on decorators or validation schema.\n   */\n  validateSync(\n    objectOrSchemaName: object | string,\n    objectOrValidationOptions: object | ValidationOptions,\n    maybeValidatorOptions?: ValidatorOptions\n  ): ValidationError[] {\n    const object = typeof objectOrSchemaName === 'string' ? (objectOrValidationOptions as object) : objectOrSchemaName;\n    const options =\n      typeof objectOrSchemaName === 'string' ? maybeValidatorOptions : (objectOrValidationOptions as ValidationOptions);\n    const schema = typeof objectOrSchemaName === 'string' ? objectOrSchemaName : undefined;\n\n    const executor = new ValidationExecutor(this, options);\n    executor.ignoreAsyncValidations = true;\n    const validationErrors: ValidationError[] = [];\n    executor.execute(object, schema, validationErrors);\n    return executor.stripEmptyErrors(validationErrors);\n  }\n\n  // -------------------------------------------------------------------------\n  // Private Properties\n  // -------------------------------------------------------------------------\n  /**\n   * Performs validation of the given object based on decorators or validation schema.\n   * Common method for `validateOrReject` and `validate` methods.\n   */\n  private coreValidate(\n    objectOrSchemaName: object | string,\n    objectOrValidationOptions: object | ValidationOptions,\n    maybeValidatorOptions?: ValidatorOptions\n  ): Promise<ValidationError[]> {\n    const object = typeof objectOrSchemaName === 'string' ? (objectOrValidationOptions as object) : objectOrSchemaName;\n    const options =\n      typeof objectOrSchemaName === 'string' ? maybeValidatorOptions : (objectOrValidationOptions as ValidationOptions);\n    const schema = typeof objectOrSchemaName === 'string' ? objectOrSchemaName : undefined;\n\n    const executor = new ValidationExecutor(this, options);\n    const validationErrors: ValidationError[] = [];\n    executor.execute(object, schema, validationErrors);\n\n    return Promise.all(executor.awaitingPromises).then(() => {\n      return executor.stripEmptyErrors(validationErrors);\n    });\n  }\n}\n"
  },
  {
    "path": "src/validation/ValidatorConstraintInterface.ts",
    "content": "import { ValidationArguments } from './ValidationArguments';\n/**\n * Custom validators must implement this interface to provide custom validation logic.\n */\nexport interface ValidatorConstraintInterface {\n  /**\n   * Method to be called to perform custom validation over given value.\n   */\n  validate(value: any, validationArguments?: ValidationArguments): Promise<boolean> | boolean;\n\n  /**\n   * Gets default message when validation for this constraint fail.\n   */\n  defaultMessage?(validationArguments?: ValidationArguments): string;\n}\n"
  },
  {
    "path": "src/validation/ValidatorOptions.ts",
    "content": "/**\n * Options passed to validator during validation.\n */\nexport interface ValidatorOptions {\n  /**\n   * If set to true then class-validator will print extra warning messages to the console when something is not right.\n   */\n  enableDebugMessages?: boolean;\n\n  /**\n   * If set to true then validator will skip validation of all properties that are undefined in the validating object.\n   */\n  skipUndefinedProperties?: boolean;\n\n  /**\n   * If set to true then validator will skip validation of all properties that are null in the validating object.\n   */\n  skipNullProperties?: boolean;\n\n  /**\n   * If set to true then validator will skip validation of all properties that are null or undefined in the validating object.\n   */\n  skipMissingProperties?: boolean;\n\n  /**\n   * If set to true validator will strip validated object of any properties that do not have any decorators.\n   *\n   * Tip: if no other decorator is suitable for your property use @Allow decorator.\n   */\n  whitelist?: boolean;\n\n  /**\n   * If set to true, instead of stripping non-whitelisted properties validator will throw an error\n   */\n  forbidNonWhitelisted?: boolean;\n\n  /**\n   * Groups to be used during validation of the object.\n   */\n  groups?: string[];\n\n  /**\n   * Set default for `always` option of decorators. Default can be overridden in decorator options.\n   */\n  always?: boolean;\n\n  /**\n   * If [groups]{@link ValidatorOptions#groups} is not given or is empty,\n   * ignore decorators with at least one group.\n   */\n  strictGroups?: boolean;\n\n  /**\n   * If set to true, the validation will not use default messages.\n   * Error message always will be undefined if its not explicitly set.\n   */\n  dismissDefaultMessages?: boolean;\n\n  /**\n   * ValidationError special options.\n   */\n  validationError?: {\n    /**\n     * Indicates if target should be exposed in ValidationError.\n     */\n    target?: boolean;\n\n    /**\n     * Indicates if validated value should be exposed in ValidationError.\n     */\n    value?: boolean;\n  };\n\n  /**\n   * Fails validation for objects unknown to class-validator. Defaults to true.\n   *\n   * For instance, since a plain empty object has no annotations used for validation:\n   * - `validate({})` // fails.\n   * - `validate({}, { forbidUnknownValues: true })` // fails.\n   * - `validate({}, { forbidUnknownValues: false })` // passes.\n   * - `validate(new SomeAnnotatedEmptyClass(), { forbidUnknownValues: true })` // passes.\n   */\n  forbidUnknownValues?: boolean;\n\n  /**\n   * When set to true, validation of the given property will stop after encountering the first error. Defaults to false.\n   */\n  stopAtFirstError?: boolean;\n}\n"
  },
  {
    "path": "src/validation-schema/ValidationSchema.ts",
    "content": "/**\n * Validation schema is a decorator-free way of validation of your objects.\n * Also using validation schemas makes this library to be easily used with es6/es5.\n */\nexport interface ValidationSchema {\n  /**\n   * Schema name. This is required, because we tell validator to validate by this schema using its name.\n   */\n  name: string;\n\n  /**\n   * Validated properties.\n   */\n  properties: {\n    /**\n     * Name of the object's property to be validated which holds an array of validation constraints.\n     */\n    [propertyName: string]: {\n      /**\n       * Validation type. Should be one of the ValidationTypes value.\n       */\n      type: string;\n\n      /**\n       * Validator name.\n       */\n      name?: string;\n\n      /**\n       * Constraints set by validation type.\n       */\n      constraints?: any[];\n\n      /**\n       * Error message used to be used on validation fail.\n       * You can use \"$value\" to use value that was failed by validation.\n       * You can use \"$constraint1\" and \"$constraint2\" keys in the message string,\n       * and they will be replaced with constraint values if they exist.\n       * Message can be either string, either a function that returns a string.\n       * Second option allows to use values and custom messages depend of them.\n       */\n      message?: string | ((value?: any, constraint1?: any, constraint2?: any) => string);\n\n      /**\n       * Specifies if validated value is an array and each of its item must be validated.\n       */\n      each?: boolean;\n\n      /**\n       * Indicates if validation must be performed always, no matter of validation groups used.\n       */\n      always?: boolean;\n\n      /**\n       * Validation groups used for this validation.\n       */\n      groups?: string[];\n\n      /**\n       * Specific validation type options.\n       */\n      options?: any;\n    }[];\n  };\n}\n"
  },
  {
    "path": "src/validation-schema/ValidationSchemaToMetadataTransformer.ts",
    "content": "import { ValidationSchema } from './ValidationSchema';\nimport { ValidationMetadata } from '../metadata/ValidationMetadata';\nimport { ValidationMetadataArgs } from '../metadata/ValidationMetadataArgs';\nimport { ValidationOptions } from '../decorator/ValidationOptions';\n\n/**\n * Used to transform validation schemas to validation metadatas.\n */\nexport class ValidationSchemaToMetadataTransformer {\n  transform(schema: ValidationSchema): ValidationMetadata[] {\n    const metadatas: ValidationMetadata[] = [];\n    Object.keys(schema.properties).forEach(property => {\n      schema.properties[property].forEach(validation => {\n        const validationOptions: ValidationOptions = {\n          message: validation.message,\n          groups: validation.groups,\n          always: validation.always,\n          each: validation.each,\n        };\n        const args: ValidationMetadataArgs = {\n          type: validation.type,\n          name: validation.name,\n          target: schema.name,\n          propertyName: property,\n          constraints: validation.constraints,\n          validationTypeOptions: validation.options,\n          validationOptions: validationOptions,\n        };\n        metadatas.push(new ValidationMetadata(args));\n      });\n    });\n    return metadatas;\n  }\n}\n"
  },
  {
    "path": "test/functional/conditional-validation.spec.ts",
    "content": "import { IsNotEmpty, ValidateIf, IsOptional, Equals } from '../../src/decorator/decorators';\nimport { Validator } from '../../src/validation/Validator';\n\nconst validator = new Validator();\n\ndescribe('conditional validation', () => {\n  it(\"shouldn't validate a property when the condition is false\", () => {\n    expect.assertions(1);\n\n    class MyClass {\n      @ValidateIf(o => false)\n      @IsNotEmpty()\n      title: string;\n    }\n\n    const model = new MyClass();\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(0);\n    });\n  });\n\n  it('should validate a property when the condition is true', () => {\n    expect.assertions(5);\n\n    class MyClass {\n      @ValidateIf(o => true)\n      @IsNotEmpty()\n      title: string = '';\n    }\n\n    const model = new MyClass();\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].target).toEqual(model);\n      expect(errors[0].property).toEqual('title');\n      expect(errors[0].constraints).toEqual({ isNotEmpty: 'title should not be empty' });\n      expect(errors[0].value).toEqual('');\n    });\n  });\n\n  it('should pass the object being validated to the condition function', () => {\n    expect.assertions(3);\n\n    class MyClass {\n      @ValidateIf(o => {\n        expect(o).toBeInstanceOf(MyClass);\n        expect(o.title).toEqual('title');\n        return true;\n      })\n      @IsNotEmpty()\n      title: string = 'title';\n    }\n\n    const model = new MyClass();\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(0);\n    });\n  });\n\n  it('should validate a property when value is empty', () => {\n    expect.assertions(5);\n\n    class MyClass {\n      @IsOptional()\n      @Equals('test')\n      title: string = '';\n    }\n\n    const model = new MyClass();\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].target).toEqual(model);\n      expect(errors[0].property).toEqual('title');\n      expect(errors[0].constraints).toEqual({ equals: 'title must be equal to test' });\n      expect(errors[0].value).toEqual('');\n    });\n  });\n\n  it('should validate a property when value is supplied', () => {\n    class MyClass {\n      @IsOptional()\n      @Equals('test')\n      title: string = 'bad_value';\n    }\n\n    const model = new MyClass();\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].target).toEqual(model);\n      expect(errors[0].property).toEqual('title');\n      expect(errors[0].constraints).toEqual({ equals: 'title must be equal to test' });\n      expect(errors[0].value).toEqual('bad_value');\n    });\n  });\n});\n"
  },
  {
    "path": "test/functional/custom-decorators.spec.ts",
    "content": "import { Validator } from '../../src/validation/Validator';\nimport { ValidationArguments } from '../../src/validation/ValidationArguments';\nimport { registerDecorator } from '../../src/register-decorator';\nimport { ValidationOptions } from '../../src/decorator/ValidationOptions';\nimport { buildMessage, ValidatorConstraint } from '../../src/decorator/decorators';\nimport { ValidatorConstraintInterface } from '../../src/validation/ValidatorConstraintInterface';\n\nconst validator = new Validator();\n\ndescribe('decorator with inline validation', () => {\n  function IsLongerThan(property: string, validationOptions?: ValidationOptions) {\n    return function (object: object, propertyName: string): void {\n      registerDecorator({\n        target: object.constructor,\n        propertyName: propertyName,\n        options: validationOptions,\n        constraints: [property],\n        name: 'isLongerThan',\n        validator: {\n          validate(value: any, args: ValidationArguments): Promise<boolean> | boolean {\n            const [relatedPropertyName] = args.constraints;\n            const relatedValue = (args.object as any)[relatedPropertyName];\n            if (relatedValue === undefined || relatedValue === null) {\n              return true;\n            }\n\n            const result =\n              typeof value === 'string' && typeof relatedValue === 'string' && value.length > relatedValue.length;\n\n            const asPromise = validationOptions && validationOptions.context && validationOptions.context.promise;\n\n            return asPromise ? Promise.resolve(result) : result;\n          },\n        },\n      });\n    };\n  }\n\n  class MyClass {\n    @IsLongerThan('lastName', {\n      context: { foo: 'bar' },\n      message: '$property must be longer then $constraint1. Given value: $value',\n    })\n    firstName: string;\n    lastName: string;\n  }\n\n  class MyClassWithAsyncValidator {\n    @IsLongerThan('lastName', {\n      context: { foo: 'bar', promise: true },\n      message: '$property must be longer then $constraint1. Given value: $value',\n    })\n    firstName: string;\n    lastName: string;\n  }\n\n  it('if firstName is not empty and lastLame is empty then it should succeed', () => {\n    expect.assertions(1);\n    const model = new MyClass();\n    model.firstName = 'hell no world';\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(0);\n    });\n  });\n\n  it('if firstName is empty and lastLame is not empty then it should fail', () => {\n    expect.assertions(2);\n    const model = new MyClass();\n    model.firstName = '';\n    model.lastName = 'Kim';\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].constraints).toEqual({ isLongerThan: 'firstName must be longer then lastName. Given value: ' });\n    });\n  });\n\n  it('if firstName is shorter then lastLame then it should fail', () => {\n    expect.assertions(2);\n    const model = new MyClass();\n    model.firstName = 'Li';\n    model.lastName = 'Kim';\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].constraints).toEqual({\n        isLongerThan: 'firstName must be longer then lastName. Given value: Li',\n      });\n    });\n  });\n\n  it('should include context', () => {\n    expect.assertions(4);\n    const model = new MyClass();\n    const asyncModel = new MyClassWithAsyncValidator();\n    model.firstName = asyncModel.firstName = 'Paul';\n    model.lastName = asyncModel.lastName = 'Walker';\n\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].contexts).toEqual({ isLongerThan: { foo: 'bar' } });\n      return validator.validate(asyncModel).then(errors => {\n        expect(errors.length).toEqual(1);\n        expect(errors[0].contexts).toHaveProperty('isLongerThan.foo', 'bar');\n      });\n    });\n  });\n});\n\ndescribe('decorator with default message', () => {\n  function IsLonger(property: string, validationOptions?: ValidationOptions) {\n    return function (object: object, propertyName: string): void {\n      registerDecorator({\n        target: object.constructor,\n        propertyName: propertyName,\n        options: validationOptions,\n        constraints: [property],\n        name: 'isLonger',\n        validator: {\n          validate(value: any, args: ValidationArguments): boolean {\n            const [relatedPropertyName] = args.constraints;\n            const relatedValue = (args.object as any)[relatedPropertyName];\n            if (relatedValue === undefined || relatedValue === null) return true;\n\n            return typeof value === 'string' && typeof relatedValue === 'string' && value.length > relatedValue.length;\n          },\n          defaultMessage(args: ValidationArguments): string {\n            return args.property + ' must be longer then ' + args.constraints[0];\n          },\n        },\n      });\n    };\n  }\n\n  class SecondClass {\n    @IsLonger('lastName')\n    firstName: string;\n    lastName: string;\n  }\n\n  it('if firstName is not empty and lastLame is empty then it should succeed', () => {\n    expect.assertions(1);\n    const model = new SecondClass();\n    model.firstName = 'hell no world';\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(0);\n    });\n  });\n\n  it('if firstName is empty and lastLame is not empty then it should fail', () => {\n    expect.assertions(2);\n    const model = new SecondClass();\n    model.firstName = '';\n    model.lastName = 'Kim';\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].constraints).toEqual({ isLonger: 'firstName must be longer then lastName' });\n    });\n  });\n\n  it('if firstName is shorter then lastLame then it should fail', () => {\n    expect.assertions(2);\n    const model = new SecondClass();\n    model.firstName = 'Li';\n    model.lastName = 'Kim';\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].constraints).toEqual({ isLonger: 'firstName must be longer then lastName' });\n    });\n  });\n});\n\ndescribe('decorator with separate validation constraint class', () => {\n  @ValidatorConstraint({ name: 'isShortenThan' })\n  class IsShortenThanConstraint implements ValidatorConstraintInterface {\n    validate(value: any, args: ValidationArguments): boolean {\n      const [relatedPropertyName] = args.constraints;\n      const relatedValue = (args.object as any)[relatedPropertyName];\n      if (value === null || value === undefined) return true;\n\n      return typeof value === 'string' && typeof relatedValue === 'string' && value.length < relatedValue.length;\n    }\n  }\n\n  function IsShorterThan(property: string, validationOptions?: ValidationOptions) {\n    return function (object: object, propertyName: string): void {\n      registerDecorator({\n        target: object.constructor,\n        propertyName: propertyName,\n        options: validationOptions,\n        constraints: [property],\n        validator: IsShortenThanConstraint,\n      });\n    };\n  }\n\n  class MyClass {\n    firstName: string;\n\n    @IsShorterThan('firstName', {\n      message: '$property must be shorter then $constraint1. Given value: $value',\n    })\n    lastName: string;\n  }\n\n  it('if firstName is not empty and lastLame is empty then it should succeed', () => {\n    expect.assertions(1);\n    const model = new MyClass();\n    model.firstName = 'hell no world';\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(0);\n    });\n  });\n\n  it('if firstName is empty and lastLame is not empty then it should fail', () => {\n    expect.assertions(2);\n    const model = new MyClass();\n    model.firstName = '';\n    model.lastName = 'Kim';\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].constraints).toEqual({\n        isShortenThan: 'lastName must be shorter then firstName. Given value: Kim',\n      });\n    });\n  });\n\n  it('if firstName is shorter then lastLame then it should fail', () => {\n    expect.assertions(2);\n    const model = new MyClass();\n    model.firstName = 'Li';\n    model.lastName = 'Kim';\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].constraints).toEqual({\n        isShortenThan: 'lastName must be shorter then firstName. Given value: Kim',\n      });\n    });\n  });\n});\n\ndescribe('decorator with symbol constraint', () => {\n  const mySymbol = Symbol('mySymbol');\n\n  function IsSameType(property: unknown, validationOptions?: ValidationOptions) {\n    return function (object: object, propertyName: string): void {\n      registerDecorator({\n        target: object.constructor,\n        propertyName: propertyName,\n        options: validationOptions,\n        constraints: [property],\n        validator: {\n          validate(value: any, args: ValidationArguments) {\n            return typeof value === typeof args.constraints[0];\n          },\n          defaultMessage: buildMessage(\n            eachPrefix => eachPrefix + '$property must be of type ' + typeof property,\n            validationOptions\n          ),\n        },\n      });\n    };\n  }\n\n  class MyClass {\n    @IsSameType(mySymbol)\n    property: symbol;\n  }\n\n  it('if property is not a symbol then it should fail', () => {\n    expect.assertions(2);\n    const model = new MyClass();\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].constraints.customValidation).toEqual('property must be of type symbol');\n    });\n  });\n});\n"
  },
  {
    "path": "test/functional/inherited-validation.spec.ts",
    "content": "import { Contains, MinLength } from '../../src/decorator/decorators';\nimport { Validator } from '../../src/validation/Validator';\n\nconst validator = new Validator();\n\ndescribe('inherited validation', () => {\n  it('should validate inherited properties', () => {\n    expect.assertions(9);\n\n    class MyClass {\n      @Contains('hello')\n      title: string;\n    }\n\n    class MySubClass extends MyClass {\n      @MinLength(5)\n      name: string;\n    }\n\n    const model = new MySubClass();\n    model.title = 'helo world';\n    model.name = 'my';\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(2);\n      // subclass own props are validated first\n      expect(errors[0].target).toEqual(model);\n      expect(errors[0].property).toEqual('name');\n      expect(errors[0].constraints).toEqual({ minLength: 'name must be longer than or equal to 5 characters' });\n      expect(errors[0].value).toEqual('my');\n      // parent props are validated afterwards\n      expect(errors[1].target).toEqual(model);\n      expect(errors[1].property).toEqual('title');\n      expect(errors[1].constraints).toEqual({ contains: 'title must contain a hello string' });\n      expect(errors[1].value).toEqual('helo world');\n    });\n  });\n});\n"
  },
  {
    "path": "test/functional/nested-validation.spec.ts",
    "content": "import { Contains, IsDefined, MinLength, ValidateNested } from '../../src/decorator/decorators';\nimport { Validator } from '../../src/validation/Validator';\nimport { ValidationTypes } from '../../src/validation/ValidationTypes';\n\nconst validator = new Validator();\n\ndescribe('nested validation', () => {\n  it('should not validate missing nested objects', () => {\n    expect.assertions(4);\n\n    class MySubClass {\n      @MinLength(5)\n      name: string;\n    }\n\n    class MyClass {\n      @Contains('hello')\n      title: string;\n\n      @ValidateNested()\n      @IsDefined()\n      mySubClass: MySubClass;\n    }\n\n    const model: MyClass = new MyClass();\n    model.title = 'helo';\n\n    return validator.validate(model).then(errors => {\n      expect(errors[1].target).toEqual(model);\n      expect(errors[1].value).toBeUndefined();\n      expect(errors[1].property).toEqual('mySubClass');\n      expect(errors[1].constraints).toEqual({ isDefined: 'mySubClass should not be null or undefined' });\n    });\n  });\n\n  it('should validate nested objects', () => {\n    expect.assertions(55);\n\n    class MySubClass {\n      @MinLength(5)\n      name: string;\n    }\n\n    class MyClass {\n      @Contains('hello')\n      title: string;\n\n      @ValidateNested()\n      mySubClass: MySubClass;\n\n      @ValidateNested()\n      mySubClasses: MySubClass[];\n\n      @ValidateNested()\n      mySubSubClasses: MySubClass[][];\n\n      @ValidateNested()\n      mySubSubSubClasses: MySubClass[][][];\n    }\n\n    const model = new MyClass();\n    model.title = 'helo world';\n    model.mySubClass = new MySubClass();\n    model.mySubClass.name = 'my';\n    model.mySubClasses = [new MySubClass(), new MySubClass()];\n    model.mySubClasses[0].name = 'my';\n    model.mySubClasses[1].name = 'not-short';\n    model.mySubSubClasses = [[new MySubClass()]];\n    model.mySubSubClasses[0][0].name = 'sub';\n    model.mySubSubSubClasses = [[[new MySubClass()]]];\n    model.mySubSubSubClasses[0][0][0].name = 'sub';\n\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(5);\n\n      expect(errors[0].target).toEqual(model);\n      expect(errors[0].property).toEqual('title');\n      expect(errors[0].constraints).toEqual({ contains: 'title must contain a hello string' });\n      expect(errors[0].value).toEqual('helo world');\n\n      expect(errors[1].target).toEqual(model);\n      expect(errors[1].property).toEqual('mySubClass');\n      expect(errors[1].value).toEqual(model.mySubClass);\n      expect(errors[1].constraints).toBeUndefined();\n      const subError1 = errors[1].children[0];\n      expect(subError1.target).toEqual(model.mySubClass);\n      expect(subError1.property).toEqual('name');\n      expect(subError1.constraints).toEqual({ minLength: 'name must be longer than or equal to 5 characters' });\n      expect(subError1.value).toEqual('my');\n\n      expect(errors[2].target).toEqual(model);\n      expect(errors[2].property).toEqual('mySubClasses');\n      expect(errors[2].value).toEqual(model.mySubClasses);\n      expect(errors[2].constraints).toBeUndefined();\n      const subError2 = errors[2].children[0];\n      expect(subError2.target).toEqual(model.mySubClasses);\n      expect(subError2.value).toEqual(model.mySubClasses[0]);\n      expect(subError2.property).toEqual('0');\n      const subSubError = subError2.children[0];\n      expect(subSubError.target).toEqual(model.mySubClasses[0]);\n      expect(subSubError.property).toEqual('name');\n      expect(subSubError.constraints).toEqual({ minLength: 'name must be longer than or equal to 5 characters' });\n      expect(subSubError.value).toEqual('my');\n\n      expect(errors[3].target).toEqual(model);\n      expect(errors[3].property).toEqual('mySubSubClasses');\n      expect(errors[3].value).toEqual(model.mySubSubClasses);\n      expect(errors[3].constraints).toBeUndefined();\n      const subError3 = errors[3].children[0];\n      expect(subError3.target).toEqual(model.mySubSubClasses);\n      expect(subError3.value).toEqual(model.mySubSubClasses[0]);\n      expect(subError3.property).toEqual('0');\n      const subSubError3 = subError3.children[0];\n      expect(subSubError3.target).toEqual(model.mySubSubClasses[0]);\n      expect(subSubError3.value).toEqual(model.mySubSubClasses[0][0]);\n      expect(subSubError3.property).toEqual('0');\n      const subSubSubError3 = subSubError3.children[0];\n      expect(subSubSubError3.target).toEqual(model.mySubSubClasses[0][0]);\n      expect(subSubSubError3.property).toEqual('name');\n      expect(subSubSubError3.constraints).toEqual({ minLength: 'name must be longer than or equal to 5 characters' });\n      expect(subSubSubError3.value).toEqual('sub');\n\n      expect(errors[4].target).toEqual(model);\n      expect(errors[4].property).toEqual('mySubSubSubClasses');\n      expect(errors[4].value).toEqual(model.mySubSubSubClasses);\n      expect(errors[4].constraints).toBeUndefined();\n      const subError4 = errors[4].children[0];\n      expect(subError4.target).toEqual(model.mySubSubSubClasses);\n      expect(subError4.value).toEqual(model.mySubSubSubClasses[0]);\n      expect(subError4.property).toEqual('0');\n      const subSubError4 = subError4.children[0];\n      expect(subSubError4.target).toEqual(model.mySubSubSubClasses[0]);\n      expect(subSubError4.value).toEqual(model.mySubSubSubClasses[0][0]);\n      expect(subSubError4.property).toEqual('0');\n      const subSubSubError4 = subSubError4.children[0];\n      expect(subSubSubError4.target).toEqual(model.mySubSubSubClasses[0][0]);\n      expect(subSubSubError4.value).toEqual(model.mySubSubSubClasses[0][0][0]);\n      expect(subSubSubError4.property).toEqual('0');\n      const subSubSubSubError4 = subSubSubError4.children[0];\n      expect(subSubSubSubError4.target).toEqual(model.mySubSubSubClasses[0][0][0]);\n      expect(subSubSubSubError4.property).toEqual('name');\n      expect(subSubSubSubError4.constraints).toEqual({\n        minLength: 'name must be longer than or equal to 5 characters',\n      });\n      expect(subSubSubSubError4.value).toEqual('sub');\n    });\n  });\n\n  it('should validate when nested is not object', () => {\n    expect.assertions(4);\n\n    class MySubClass {\n      @MinLength(5)\n      name: string;\n    }\n\n    class MyClass {\n      @ValidateNested()\n      mySubClass: MySubClass;\n    }\n\n    const model = new MyClass();\n    model.mySubClass = 'invalidnested object' as any;\n\n    return validator.validate(model).then(errors => {\n      expect(errors[0].target).toEqual(model);\n      expect(errors[0].property).toEqual('mySubClass');\n      expect(errors[0].children.length).toEqual(0);\n      expect(errors[0].constraints).toEqual({\n        [ValidationTypes.NESTED_VALIDATION]: 'nested property mySubClass must be either object or array',\n      });\n    });\n  });\n\n  it('should validate nested set', () => {\n    expect.assertions(24);\n\n    class MySubClass {\n      @MinLength(5)\n      name: string;\n    }\n\n    class MyClass {\n      @Contains('hello')\n      title: string;\n\n      @ValidateNested()\n      mySubClass: MySubClass;\n\n      @ValidateNested()\n      mySubClasses: Set<MySubClass>;\n    }\n\n    const model = new MyClass();\n    model.title = 'helo world';\n    model.mySubClass = new MySubClass();\n    model.mySubClass.name = 'my';\n    model.mySubClasses = new Set();\n\n    const submodel1 = new MySubClass();\n    submodel1.name = 'my';\n    model.mySubClasses.add(submodel1);\n\n    const submodel2 = new MySubClass();\n    submodel2.name = 'not-short';\n    model.mySubClasses.add(submodel2);\n\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(3);\n\n      expect(errors[0].target).toEqual(model);\n      expect(errors[0].property).toEqual('title');\n      expect(errors[0].constraints).toEqual({ contains: 'title must contain a hello string' });\n      expect(errors[0].value).toEqual('helo world');\n\n      expect(errors[1].target).toEqual(model);\n      expect(errors[1].property).toEqual('mySubClass');\n      expect(errors[1].value).toEqual(model.mySubClass);\n      expect(errors[1].constraints).toBeUndefined();\n      const subError1 = errors[1].children[0];\n      expect(subError1.target).toEqual(model.mySubClass);\n      expect(subError1.property).toEqual('name');\n      expect(subError1.constraints).toEqual({ minLength: 'name must be longer than or equal to 5 characters' });\n      expect(subError1.value).toEqual('my');\n\n      expect(errors[2].target).toEqual(model);\n      expect(errors[2].property).toEqual('mySubClasses');\n      expect(errors[2].value).toEqual(model.mySubClasses);\n      expect(errors[2].constraints).toBeUndefined();\n      const subError2 = errors[2].children[0];\n      expect(subError2.target).toEqual(model.mySubClasses);\n      expect(subError2.value).toEqual(submodel1);\n      expect(subError2.property).toEqual('0');\n      const subSubError = subError2.children[0];\n      expect(subSubError.target).toEqual(submodel1);\n      expect(subSubError.property).toEqual('name');\n      expect(subSubError.constraints).toEqual({ minLength: 'name must be longer than or equal to 5 characters' });\n      expect(subSubError.value).toEqual('my');\n    });\n  });\n\n  it('should validate nested map', () => {\n    expect.assertions(24);\n\n    class MySubClass {\n      @MinLength(5)\n      name: string;\n    }\n\n    class MyClass {\n      @Contains('hello')\n      title: string;\n\n      @ValidateNested()\n      mySubClass: MySubClass;\n\n      @ValidateNested()\n      mySubClasses: Map<string, MySubClass>;\n    }\n\n    const model = new MyClass();\n    model.title = 'helo world';\n    model.mySubClass = new MySubClass();\n    model.mySubClass.name = 'my';\n    model.mySubClasses = new Map();\n\n    const submodel1 = new MySubClass();\n    submodel1.name = 'my';\n    model.mySubClasses.set('key1', submodel1);\n\n    const submodel2 = new MySubClass();\n    submodel2.name = 'not-short';\n    model.mySubClasses.set('key2', submodel2);\n\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(3);\n\n      expect(errors[0].target).toEqual(model);\n      expect(errors[0].property).toEqual('title');\n      expect(errors[0].constraints).toEqual({ contains: 'title must contain a hello string' });\n      expect(errors[0].value).toEqual('helo world');\n\n      expect(errors[1].target).toEqual(model);\n      expect(errors[1].property).toEqual('mySubClass');\n      expect(errors[1].value).toEqual(model.mySubClass);\n      expect(errors[1].constraints).toBeUndefined();\n      const subError1 = errors[1].children[0];\n      expect(subError1.target).toEqual(model.mySubClass);\n      expect(subError1.property).toEqual('name');\n      expect(subError1.constraints).toEqual({ minLength: 'name must be longer than or equal to 5 characters' });\n      expect(subError1.value).toEqual('my');\n\n      expect(errors[2].target).toEqual(model);\n      expect(errors[2].property).toEqual('mySubClasses');\n      expect(errors[2].value).toEqual(model.mySubClasses);\n      expect(errors[2].constraints).toBeUndefined();\n      const subError2 = errors[2].children[0];\n      expect(subError2.target).toEqual(model.mySubClasses);\n      expect(subError2.value).toEqual(submodel1);\n      expect(subError2.property).toEqual('key1');\n      const subSubError = subError2.children[0];\n      expect(subSubError.target).toEqual(submodel1);\n      expect(subSubError.property).toEqual('name');\n      expect(subSubError.constraints).toEqual({ minLength: 'name must be longer than or equal to 5 characters' });\n      expect(subSubError.value).toEqual('my');\n    });\n  });\n\n  it('nestedValidation should be defined as an error for the property specifying the decorator when validation fails.', () => {\n    class MySubClass {\n      @MinLength(5)\n      name: string;\n    }\n\n    class MyClass {\n      @ValidateNested()\n      nestedWithClassValue: MySubClass;\n\n      @ValidateNested()\n      nestedWithPrimitiveValue: MySubClass;\n    }\n\n    const model = new MyClass();\n    model.nestedWithClassValue = new MySubClass();\n    model.nestedWithPrimitiveValue = 'invalid' as any;\n\n    return validator.validate(model, { stopAtFirstError: true }).then(errors => {\n      expect(errors[0].property).toEqual('nestedWithClassValue');\n      expect(errors[0].children.length).toEqual(1);\n      expect(errors[0].children[0].constraints).toHaveProperty('minLength');\n      expect(errors[1].property).toEqual('nestedWithPrimitiveValue');\n      expect(errors[1].constraints).toHaveProperty('nestedValidation');\n    });\n  });\n});\n"
  },
  {
    "path": "test/functional/promise-validation.spec.ts",
    "content": "import { Contains, IsDefined, MinLength, ValidateNested, ValidatePromise } from '../../src/decorator/decorators';\nimport { Validator } from '../../src/validation/Validator';\nimport { ValidationTypes } from '../../src/validation/ValidationTypes';\n\nconst validator = new Validator();\n\ndescribe('promise validation', () => {\n  it('should not validate missing nested objects', () => {\n    expect.assertions(4);\n\n    class MySubClass {\n      @MinLength(5)\n      name: string;\n    }\n\n    class MyClass {\n      @Contains('hello')\n      title: string;\n\n      @ValidatePromise()\n      @ValidateNested()\n      @IsDefined()\n      mySubClass: Promise<MySubClass>;\n    }\n\n    const model: any = new MyClass();\n    model.title = 'helo';\n\n    return validator.validate(model).then(errors => {\n      expect(errors[1].target).toEqual(model);\n      expect(errors[1].value).toBeUndefined();\n      expect(errors[1].property).toEqual('mySubClass');\n      expect(errors[1].constraints).toEqual({ isDefined: 'mySubClass should not be null or undefined' });\n    });\n  });\n\n  it('should validate nested objects', () => {\n    expect.assertions(24);\n\n    class MySubClass {\n      @MinLength(5)\n      name: string;\n    }\n\n    class MyClass {\n      @Contains('hello')\n      title: string;\n\n      @ValidatePromise()\n      @ValidateNested()\n      mySubClass: Promise<MySubClass>;\n\n      @ValidatePromise()\n      @ValidateNested()\n      mySubClasses: Promise<MySubClass[]>;\n    }\n\n    const model = new MyClass();\n    model.title = 'helo world';\n    const mySubClass = new MySubClass();\n    mySubClass.name = 'my';\n    model.mySubClass = Promise.resolve(mySubClass);\n    const mySubClasses = [new MySubClass(), new MySubClass()];\n    mySubClasses[0].name = 'my';\n    mySubClasses[1].name = 'not-short';\n    model.mySubClasses = Promise.resolve(mySubClasses);\n    return validator.validate(model).then(errors => {\n      return Promise.all([model.mySubClass, model.mySubClasses]).then(([modelMySubClass, modelMySubClasses]) => {\n        expect(errors.length).toEqual(3);\n\n        expect(errors[0].target).toEqual(model);\n        expect(errors[0].property).toEqual('title');\n        expect(errors[0].constraints).toEqual({ contains: 'title must contain a hello string' });\n        expect(errors[0].value).toEqual('helo world');\n\n        expect(errors[1].target).toEqual(model);\n        expect(errors[1].property).toEqual('mySubClass');\n        expect(errors[1].value).toEqual(modelMySubClass);\n        expect(errors[1].constraints).toBeUndefined();\n        const subError1 = errors[1].children[0];\n        expect(subError1.target).toEqual(modelMySubClass);\n        expect(subError1.property).toEqual('name');\n        expect(subError1.constraints).toEqual({ minLength: 'name must be longer than or equal to 5 characters' });\n        expect(subError1.value).toEqual('my');\n\n        expect(errors[2].target).toEqual(model);\n        expect(errors[2].property).toEqual('mySubClasses');\n        expect(errors[2].value).toEqual(modelMySubClasses);\n        expect(errors[2].constraints).toBeUndefined();\n        const subError2 = errors[2].children[0];\n        expect(subError2.target).toEqual(modelMySubClasses);\n        expect(subError2.value).toEqual(modelMySubClasses[0]);\n        expect(subError2.property).toEqual('0');\n        const subSubError = subError2.children[0];\n        expect(subSubError.target).toEqual(modelMySubClasses[0]);\n        expect(subSubError.property).toEqual('name');\n        expect(subSubError.constraints).toEqual({ minLength: 'name must be longer than or equal to 5 characters' });\n        expect(subSubError.value).toEqual('my');\n      });\n    });\n  });\n\n  it('should validate when nested is not object', () => {\n    expect.assertions(4);\n\n    class MySubClass {\n      @MinLength(5)\n      name: string;\n    }\n\n    class MyClass {\n      @ValidatePromise()\n      @ValidateNested()\n      mySubClass: MySubClass;\n    }\n\n    const model = new MyClass();\n    model.mySubClass = 'invalidnested object' as any;\n\n    return validator.validate(model).then(errors => {\n      expect(errors[0].target).toEqual(model);\n      expect(errors[0].property).toEqual('mySubClass');\n      expect(errors[0].children.length).toEqual(0);\n      expect(errors[0].constraints).toEqual({\n        [ValidationTypes.NESTED_VALIDATION]: 'nested property mySubClass must be either object or array',\n      });\n    });\n  });\n\n  it('should validate array promise', () => {\n    expect.assertions(5);\n\n    class MyClass {\n      @ValidatePromise()\n      @MinLength(2)\n      arrProperty: Promise<string[]>;\n    }\n\n    const model = new MyClass();\n    model.arrProperty = Promise.resolve(['one']);\n\n    return validator.validate(model).then(errors => {\n      return Promise.all([model.arrProperty]).then(([modelArrProperty]) => {\n        expect(errors.length).toEqual(1);\n\n        expect(errors[0].target).toEqual(model);\n        expect(errors[0].property).toEqual('arrProperty');\n        expect(errors[0].constraints).toEqual({\n          minLength: 'arrProperty must be longer than or equal to 2 characters',\n        });\n        expect(errors[0].value).toEqual(modelArrProperty);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "test/functional/reject-validation.spec.ts",
    "content": "import { ValidationError } from './../../src/validation/ValidationError';\nimport { Contains } from '../../src/decorator/decorators';\nimport { Validator } from '../../src/validation/Validator';\n\nclass MyClass {\n  @Contains('hello', {\n    message: '$value is not valid. Your string must contain a hello word',\n  })\n  someProperty: string;\n}\n\ndescribe('validateOrReject()', () => {\n  let validator: Validator;\n  let model: MyClass;\n\n  beforeEach(() => {\n    validator = new Validator();\n    model = new MyClass();\n  });\n\n  it('should resolve promise when no error', () => {\n    expect.assertions(1);\n    model.someProperty = 'hello world';\n    return validator.validateOrReject(model).then(args => {\n      expect(args).toBeUndefined();\n    });\n  });\n\n  it('should reject promise on error', () => {\n    expect.assertions(2);\n    model.someProperty = 'hell no world';\n    return validator.validateOrReject(model).catch((errors: ValidationError[]) => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].constraints).toEqual({\n        contains: 'hell no world is not valid. Your string must contain a hello word',\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "test/functional/sync-validation.spec.ts",
    "content": "import { Validator } from '../../src/validation/Validator';\nimport { ValidationArguments } from '../../src/validation/ValidationArguments';\nimport { registerDecorator } from '../../src/register-decorator';\nimport { ValidationOptions } from '../../src/decorator/ValidationOptions';\nimport { ValidatorConstraint, Validate, IsNotEmpty } from '../../src/decorator/decorators';\nimport { ValidatorConstraintInterface } from '../../src/validation/ValidatorConstraintInterface';\n\nconst validator = new Validator();\n\ndescribe('sync validation should ignore async validation constraints', () => {\n  @ValidatorConstraint({ name: 'isShortenThan', async: true })\n  class IsShortenThanConstraint implements ValidatorConstraintInterface {\n    validate(value: any, args: ValidationArguments): Promise<boolean> {\n      return Promise.resolve(false);\n    }\n  }\n\n  function IsLonger(property: string, validationOptions?: ValidationOptions) {\n    return function (object: object, propertyName: string): void {\n      registerDecorator({\n        target: object.constructor,\n        propertyName: propertyName,\n        options: validationOptions,\n        constraints: [property],\n        async: true,\n        name: 'isLonger',\n        validator: {\n          validate(value: any, args: ValidationArguments): Promise<boolean> {\n            return Promise.resolve(false);\n          },\n        },\n      });\n    };\n  }\n\n  class SecondClass {\n    @IsLonger('lastName')\n    firstName: string;\n\n    @Validate(IsShortenThanConstraint)\n    lastName: string;\n\n    @IsNotEmpty({ message: 'name should not be empty' })\n    name: string;\n\n    @IsNotEmpty()\n    alwaysWithValue: string = 'this field always has a value';\n  }\n\n  it('should ignore async validations and validate only sync validation types', () => {\n    expect.assertions(1);\n    const model = new SecondClass();\n    model.firstName = 'such validation may lead';\n    model.firstName = 'to recursion';\n    model.name = 'Umed';\n    const errors = validator.validateSync(model);\n    expect(errors.length).toEqual(0);\n  });\n\n  it('should ignore async validations and validate only sync validation types', () => {\n    expect.assertions(2);\n    const model = new SecondClass();\n    model.firstName = 'such validation may lead';\n    model.firstName = 'to recursion';\n    model.name = '';\n    const errors = validator.validateSync(model);\n    expect(errors.length).toEqual(1);\n    expect(errors[0].constraints).toEqual({ isNotEmpty: 'name should not be empty' });\n  });\n});\n"
  },
  {
    "path": "test/functional/validation-error.spec.ts",
    "content": "import { IsString, IsUrl, IsOptional, ValidateNested, MinLength } from '../../src/decorator/decorators';\nimport { Validator } from '../../src/validation/Validator';\n\nconst validator = new Validator();\n\n/**\n * TODO: needs to split these test into\n *   - testing basic toString\n *   - testing nested objects\n *   - testing arrays\n *   - testing color codes?\n */\ndescribe('ValidationError', () => {\n  it('should correctly log error message without ANSI escape codes', async () => {\n    class NestedClass {\n      @IsString()\n      public name: string;\n\n      @IsUrl()\n      public url: string;\n\n      @IsOptional()\n      @ValidateNested()\n      public insideNested: NestedClass;\n\n      constructor(url: string, name: any, insideNested?: NestedClass) {\n        this.url = url;\n        this.name = name;\n        this.insideNested = insideNested;\n      }\n    }\n\n    class RootClass {\n      @IsString()\n      @MinLength(15)\n      public title: string;\n\n      @ValidateNested()\n      public nestedObj: NestedClass;\n\n      @ValidateNested({ each: true })\n      public nestedArr: NestedClass[];\n\n      constructor() {\n        this.title = 5 as any;\n        this.nestedObj = new NestedClass('invalid-url', 5, new NestedClass('invalid-url', 5));\n        this.nestedArr = [new NestedClass('invalid-url', 5), new NestedClass('invalid-url', 5)];\n      }\n    }\n\n    const validationErrors = await validator.validate(new RootClass());\n    expect(validationErrors).toHaveLength(3);\n    expect(validationErrors[0].toString()).toEqual(\n      'An instance of RootClass has failed the validation:\\n' +\n        ' - property title has failed the following constraints: minLength, isString \\n'\n    );\n    expect(validationErrors[1].toString()).toEqual(\n      'An instance of RootClass has failed the validation:\\n' +\n        ' - property nestedObj.name has failed the following constraints: isString \\n' +\n        ' - property nestedObj.url has failed the following constraints: isUrl \\n' +\n        ' - property nestedObj.insideNested.name has failed the following constraints: isString \\n' +\n        ' - property nestedObj.insideNested.url has failed the following constraints: isUrl \\n'\n    );\n    expect(validationErrors[2].toString()).toEqual(\n      'An instance of RootClass has failed the validation:\\n' +\n        ' - property nestedArr[0].name has failed the following constraints: isString \\n' +\n        ' - property nestedArr[0].url has failed the following constraints: isUrl \\n' +\n        ' - property nestedArr[1].name has failed the following constraints: isString \\n' +\n        ' - property nestedArr[1].url has failed the following constraints: isUrl \\n'\n    );\n    expect(validationErrors[0].toString(undefined, undefined, undefined, true)).toEqual(\n      'An instance of RootClass has failed the validation:\\n' +\n        ' - property title has failed the following constraints: title must be longer than or equal to 15 characters, title must be a string \\n'\n    );\n    expect(validationErrors[1].toString(undefined, undefined, undefined, true)).toEqual(\n      'An instance of RootClass has failed the validation:\\n' +\n        ' - property nestedObj.name has failed the following constraints: name must be a string \\n' +\n        ' - property nestedObj.url has failed the following constraints: url must be a URL address \\n' +\n        ' - property nestedObj.insideNested.name has failed the following constraints: name must be a string \\n' +\n        ' - property nestedObj.insideNested.url has failed the following constraints: url must be a URL address \\n'\n    );\n    expect(validationErrors[2].toString(undefined, undefined, undefined, true)).toEqual(\n      'An instance of RootClass has failed the validation:\\n' +\n        ' - property nestedArr[0].name has failed the following constraints: name must be a string \\n' +\n        ' - property nestedArr[0].url has failed the following constraints: url must be a URL address \\n' +\n        ' - property nestedArr[1].name has failed the following constraints: name must be a string \\n' +\n        ' - property nestedArr[1].url has failed the following constraints: url must be a URL address \\n'\n    );\n  });\n});\n"
  },
  {
    "path": "test/functional/validation-functions-and-decorators.spec.ts",
    "content": "import {\n  IsBooleanString,\n  IsPositive,\n  IsLatLong,\n  IsLongitude,\n  IsLatitude,\n  IsNegative,\n  Contains,\n  Equals,\n  MinDate,\n  MaxDate,\n  IsAlpha,\n  IsAlphanumeric,\n  IsAscii,\n  IsDecimal,\n  IsBase64,\n  IsBoolean,\n  IsByteLength,\n  IsCreditCard,\n  IsCurrency,\n  IsDate,\n  IsDivisibleBy,\n  IsEmail,\n  IsEnum,\n  IsFQDN,\n  IsFullWidth,\n  IsHalfWidth,\n  IsVariableWidth,\n  IsHexColor,\n  IsHexadecimal,\n  IsIP,\n  IsISBN,\n  IsISO8601,\n  IsIn,\n  IsInt,\n  IsJSON,\n  IsJWT,\n  IsObject,\n  IsNotEmptyObject,\n  Length,\n  IsLowercase,\n  IsMongoId,\n  IsMultibyte,\n  IsNumberString,\n  IsSurrogatePair,\n  IsUrl,\n  IsUUID,\n  IsUppercase,\n  Matches,\n  MinLength,\n  MaxLength,\n  Min,\n  Max,\n  IsNotEmpty,\n  IsMilitaryTime,\n  ArrayNotEmpty,\n  ArrayMinSize,\n  ArrayMaxSize,\n  NotEquals,\n  IsEmpty,\n  IsDefined,\n  IsNotIn,\n  IsNumber,\n  IsString,\n  NotContains,\n  ArrayContains,\n  ArrayNotContains,\n  ArrayUnique,\n  IsArray,\n  IsDateString,\n  IsInstance,\n  IsPhoneNumber,\n  IsISO31661Alpha2,\n  IsISO31661Alpha3,\n  IsISO31661Numeric,\n  IsHash,\n  IsMACAddress,\n  IsISSN,\n  IsFirebasePushId,\n  isDefined,\n  isNumber,\n  isURL,\n  isBoolean,\n  isString,\n  isInt,\n  isArray,\n  isEnum,\n  contains,\n  isObject,\n  isNotEmptyObject,\n  isInstance,\n  notContains,\n  isAlpha,\n  isAlphanumeric,\n  isAscii,\n  isDecimal,\n  isBase64,\n  isByteLength,\n  isCreditCard,\n  isCurrency,\n  isEmail,\n  isFQDN,\n  isFullWidth,\n  isHalfWidth,\n  isVariableWidth,\n  isHexColor,\n  isHexadecimal,\n  isMACAddress,\n  isISBN,\n  isISO8601,\n  isIP,\n  isJSON,\n  isJWT,\n  isLowercase,\n  isMongoId,\n  isMultibyte,\n  isSurrogatePair,\n  isUUID,\n  isUppercase,\n  length,\n  minLength,\n  maxLength,\n  isFirebasePushId,\n  equals,\n  notEquals,\n  isEmpty,\n  isNotEmpty,\n  isIn,\n  isNotIn,\n  isDateString,\n  isDivisibleBy,\n  isPositive,\n  isNegative,\n  min,\n  max,\n  isBooleanString,\n  isNumberString,\n  matches,\n  isHash,\n  isISSN,\n  arrayContains,\n  arrayNotContains,\n  arrayMinSize,\n  arrayMaxSize,\n  arrayUnique,\n  arrayNotEmpty,\n  minDate,\n  maxDate,\n  isDate,\n  IsEAN,\n  isEAN,\n  IsEthereumAddress,\n  isEthereumAddress,\n  IsBtcAddress,\n  isBtcAddress,\n  IsDataURI,\n  isDataURI,\n  IsHSL,\n  isHSL,\n  IsRgbColor,\n  isRgbColor,\n  isIdentityCard,\n  IsIdentityCard,\n  IsBase32,\n  isBase32,\n  IsIBAN,\n  isIBAN,\n  IsBIC,\n  isBIC,\n  IsISRC,\n  isISRC,\n  IsRFC3339,\n  isRFC3339,\n  IsLocale,\n  isLocale,\n  IsMagnetURI,\n  isMagnetURI,\n  IsMimeType,\n  isMimeType,\n  isOctal,\n  IsOctal,\n  IsPassportNumber,\n  isPassportNumber,\n  IsPostalCode,\n  isPostalCode,\n  IsSemVer,\n  isSemVer,\n  IsStrongPassword,\n  isStrongPassword,\n  IsStrongPasswordOptions,\n  IsTimeZone,\n  IsBase58,\n  isBase58,\n  isTaxId,\n  IsTaxId,\n  IsISO4217CurrencyCode,\n  IsISO6391,\n} from '../../src/decorator/decorators';\nimport { Validator } from '../../src/validation/Validator';\nimport { ValidatorOptions } from '../../src/validation/ValidatorOptions';\nimport { constraintToString } from '../../src/validation/ValidationUtils';\nimport * as ValidatorJS from 'validator';\n\nfunction checkValidValues(\n  object: { someProperty: any },\n  values: any[],\n  validatorOptions?: ValidatorOptions\n): Promise<any> {\n  const validator = new Validator();\n  const promises = values.map(value => {\n    object.someProperty = value;\n    return validator.validate(object, validatorOptions).then(errors => {\n      expect(errors.length).toEqual(0);\n      if (errors.length !== 0) {\n        console.log(`Unexpected errors: ${JSON.stringify(errors)}`);\n        throw new Error('Unexpected validation errors');\n      }\n    });\n  });\n\n  return Promise.all(promises);\n}\n\nfunction checkInvalidValues(\n  object: { someProperty: any },\n  values: any[],\n  validatorOptions?: ValidatorOptions\n): Promise<any> {\n  const validator = new Validator();\n  const promises = values.map(value => {\n    object.someProperty = value;\n    return validator\n      .validate(object, validatorOptions)\n      .then(errors => {\n        expect(errors.length).toEqual(1);\n        if (errors.length !== 1) {\n          throw new Error('Missing validation errors');\n        }\n      })\n      .catch(error => {\n        console.log(error);\n      });\n  });\n\n  return Promise.all(promises);\n}\n\nfunction checkReturnedError(\n  object: { someProperty: any },\n  values: any[],\n  validationType: string,\n  message: string,\n  validatorOptions?: ValidatorOptions\n): Promise<any> {\n  const validator = new Validator();\n  const promises = values.map(value => {\n    object.someProperty = value;\n    return validator.validate(object, validatorOptions).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].target).toEqual(object);\n      expect(errors[0].property).toEqual('someProperty');\n      expect(errors[0].constraints).toEqual({ [validationType]: message });\n      expect(errors[0].value).toEqual(value);\n    });\n  });\n\n  return Promise.all(promises);\n}\n\ndescribe('IsDefined', () => {\n  const validValues = [0, 1, true, false, '', '0', '1234', -1];\n  const invalidValues: any[] = [null, undefined];\n\n  class MyClass {\n    @IsDefined()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if validator.validate said that its valid with skipUndefinedProperties set to true', () => {\n    return checkValidValues(new MyClass(), validValues, { skipUndefinedProperties: true });\n  });\n\n  it('should fail if validator.validate said that its invalid with skipUndefinedProperties set to true', () => {\n    return checkInvalidValues(new MyClass(), invalidValues, { skipUndefinedProperties: true });\n  });\n\n  it('should not fail if validator.validate said that its valid with skipNullProperties set to true', () => {\n    return checkValidValues(new MyClass(), validValues, { skipNullProperties: true });\n  });\n\n  it('should fail if validator.validate said that its invalid with skipNullProperties set to true', () => {\n    return checkInvalidValues(new MyClass(), invalidValues, { skipNullProperties: true });\n  });\n\n  it('should not fail if validator.validate said that its valid with skipMissingProperties set to true', () => {\n    return checkValidValues(new MyClass(), validValues, { skipMissingProperties: true });\n  });\n\n  it('should fail if validator.validate said that its invalid with skipMissingProperties set to true', () => {\n    return checkInvalidValues(new MyClass(), invalidValues, { skipMissingProperties: true });\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isDefined(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isDefined(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isDefined';\n    const message = 'someProperty should not be null or undefined';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('Equals', () => {\n  const constraint = 'Alex';\n  const validValues = ['Alex'];\n  const invalidValues = ['Alexxx'];\n\n  class MyClass {\n    @Equals(constraint)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(equals(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(equals(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'equals';\n    const message = 'someProperty must be equal to ' + constraintToString(constraint);\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('NotEquals', () => {\n  const constraint = 'Alex';\n  const validValues = ['Alexxx'];\n  const invalidValues = ['Alex'];\n\n  class MyClass {\n    @NotEquals(constraint)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(notEquals(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(notEquals(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'notEquals';\n    const message = 'someProperty should not be equal to ' + constraintToString(constraint);\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsEmpty', () => {\n  const validValues = [null, undefined, ''];\n  const invalidValues = ['0', 0, 1, false, true];\n\n  class MyClass {\n    @IsEmpty()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isEmpty(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isEmpty(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isEmpty';\n    const message = 'someProperty must be empty';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsNotEmpty', () => {\n  const validValues = ['a', 'abc'];\n  const invalidValues = ['', undefined, null];\n\n  class MyClass {\n    @IsNotEmpty()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isNotEmpty(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isNotEmpty(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isNotEmpty';\n    const message = 'someProperty should not be empty';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsIn', () => {\n  const constraint = ['foo', 'bar'] as const;\n  const validValues = ['foo', 'bar'];\n  const invalidValues = ['foobar', 'barfoo', ''];\n\n  class MyClass {\n    @IsIn(constraint)\n    someProperty: string[];\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isIn(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isIn(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isIn';\n    const message = 'someProperty must be one of the following values: ' + constraintToString(constraint);\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsNotIn', () => {\n  const constraint = ['foo', 'bar'] as const;\n  const validValues = ['foobar', 'barfoo', ''];\n  const invalidValues = ['foo', 'bar'];\n\n  class MyClass {\n    @IsNotIn(constraint)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isNotIn(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isNotIn(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isNotIn';\n    const message = 'someProperty should not be one of the following values: ' + constraintToString(constraint);\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\n// -------------------------------------------------------------------------\n// Specifications: type check\n// -------------------------------------------------------------------------\n\ndescribe('IsBoolean', () => {\n  const validValues = [true, false];\n  const invalidValues = [0, 1, 'true', null, undefined];\n\n  class MyClass {\n    @IsBoolean()\n    someProperty: any;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isBoolean(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isBoolean(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isBoolean';\n    const message = 'someProperty must be a boolean value';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsLatLong', () => {\n  const validValues = ['27.6945311,85.3446311', '27.675509,85.2100893'];\n  const invalidValues = ['276945311,853446311', 'asas,as.as12'];\n\n  class MyClass {\n    @IsLatLong()\n    someProperty: any;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n});\n\ndescribe('IsLatitude', () => {\n  const validValues = ['27.6945311', '27.675509', 27.675509];\n  const invalidValues = ['276945311', 'asas', 1234222, 5678921];\n\n  class MyClass {\n    @IsLatitude()\n    someProperty: any;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n});\n\ndescribe('IsLongitude', () => {\n  const validValues = ['85.3446311', '85.2100893', 85.2100893];\n  const invalidValues = ['853446311', 'as.as12', 12345, 737399];\n\n  class MyClass {\n    @IsLongitude()\n    someProperty: any;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n});\n\ndescribe('IsDate', () => {\n  const validValues = [new Date()];\n  const invalidValues = [1, true, false, 'Mon Aug 17 2015 00:24:56 GMT-0500 (CDT)', '2009-05-19 14:39:22-06:00'];\n\n  class MyClass {\n    @IsDate()\n    someProperty: Date;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isDate(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isDate(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isDate';\n    const message = 'someProperty must be a Date instance';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsNumber', () => {\n  const validValues = [0, 1, 2, 3, 4, 5.4, -10];\n  const invalidValues = ['1', '0', true, false, '-100', 'abc', undefined, null];\n\n  class MyClass {\n    @IsNumber()\n    someProperty: number;\n  }\n\n  class NaNTestClass {\n    @IsNumber({ allowNaN: true })\n    someProperty: number;\n  }\n\n  class InfinityTestClass {\n    @IsNumber({ allowInfinity: true })\n    someProperty: number;\n  }\n\n  class MaxDecimalPlacesTest {\n    @IsNumber({ maxDecimalPlaces: 3 })\n    someProperty: number;\n  }\n\n  class ZeroDecimalPlacesTest {\n    @IsNumber({ maxDecimalPlaces: 0 })\n    someProperty: number;\n  }\n\n  it('should fail if NaN passed without allowing NaN values', () => {\n    return checkInvalidValues(new MyClass(), [NaN]);\n  });\n\n  it('should fail if Infinity passed without allowing NaN values', () => {\n    return checkInvalidValues(new MyClass(), [Infinity, -Infinity]);\n  });\n\n  it('should not fail if NaN passed and NaN as value is allowed', () => {\n    return checkValidValues(new NaNTestClass(), [NaN]);\n  });\n\n  it('should not fail if Infinity passed and Infinity as value is allowed', () => {\n    return checkValidValues(new InfinityTestClass(), [Infinity, -Infinity]);\n  });\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isNumber(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isNumber(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isNumber';\n    const message = 'someProperty must be a number conforming to the specified constraints';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n\n  it('should pass if number of decimal places within maxDecimalPlaces', () => {\n    return checkValidValues(new MaxDecimalPlacesTest(), [1.123]);\n  });\n\n  it('should fail if number of decimal places exceeds maxDecimalPlaces', () => {\n    return checkInvalidValues(new MaxDecimalPlacesTest(), [1.1234]);\n  });\n\n  it('should pass if number of decimal places is zero', () => {\n    return checkValidValues(new ZeroDecimalPlacesTest(), [-10, -1, 0, 1, 10]);\n  });\n\n  it('should fail if number of decimal places is not zero', () => {\n    return checkInvalidValues(new ZeroDecimalPlacesTest(), [-11.1, -2.2, -0.1, 0.1, 2.2, 11.1]);\n  });\n});\n\ndescribe('IsInt', () => {\n  const validValues = [2, 4, 100, 1000];\n  const invalidValues = ['01', '-01', '000', '100e10', '123.123', '   ', '', 2.5, -0.1];\n\n  class MyClass {\n    @IsInt()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isInt(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isInt(value as any)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isInt';\n    const message = 'someProperty must be an integer number';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsString', () => {\n  const validValues = ['true', 'false', 'hello', '0', '', '1'];\n  const invalidValues = [true, false, 1, 2, null, undefined];\n\n  class MyClass {\n    @IsString()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isString(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isString(value as any)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isString';\n    const message = 'someProperty must be a string';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsDateString', () => {\n  const validValues = [\n    '2017-06-06T17:04:42.081Z',\n    '2017-06-06T17:04:42.081',\n    '2018-01-04T08:15:30',\n    '2018-01-04T08:15:30Z',\n    '2018-01-04T08:15:30+04:00',\n    '2018-01-04T08:15:30+04',\n    '2020-03-26T11:00:01-03:00',\n    '2020-03-26T11:00:01-03',\n    '2019-09-03T20:16:24.12Z',\n  ];\n  const invalidValues = [\n    true,\n    false,\n    1,\n    2,\n    null,\n    undefined,\n    'text',\n    'text2018-01-04T08:15:30+04',\n    '2018-01-04T08:15:30Ztext',\n    '2009-02-29', // non-existent-day\n    '2019-18-13T22:14:14.761Z', // month greater than 12\n    '2019-12-39T22:14:14.761Z', // day greater than 31\n    '2019-12-31T29:14:14.761Z', // hour greater than 24\n    '2019-00-31T29:14:14.761Z', // month of 0\n    '2019-01-00T29:14:14.761Z', // day of 0\n    '2019-09-03T20:16:24.12-5:00', // single digit hour in timezone offset\n    '2019-09-03T20:16:24.12+5:00',\n    '2019-09-03T20:16:24.12-05:0', // single digit minute in timezone offset\n    '2019-09-03T20:16:24.12+05:0',\n  ];\n\n  class MyClass {\n    @IsDateString({ strict: true })\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isDateString(value, { strict: true })).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isDateString(value as any, { strict: true })).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isDateString';\n    const message = 'someProperty must be a valid ISO 8601 date string';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsArray', () => {\n  const validValues = [[], [1, 2, 3], [0, 0, 0], [''], [0], [undefined], [{}], []];\n  const invalidValues = [true, false, 1, {}, null, undefined];\n\n  class MyClass {\n    @IsArray()\n    someProperty: string[];\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isArray(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isArray(value as any)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isArray';\n    const message = 'someProperty must be an array';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsEnum', () => {\n  enum MyDefaultIndexedEnum {\n    First,\n    Second,\n  }\n\n  enum MyCustomIndexedEnum {\n    First = 1,\n    Second = 999,\n  }\n\n  enum MyStringEnum {\n    First = 'first',\n    Second = 'second',\n  }\n\n  const validValues = [MyCustomIndexedEnum.First, MyCustomIndexedEnum.Second];\n  const validStringValues = [MyStringEnum.First, MyStringEnum.Second];\n  const invalidValues = [true, false, 42, {}, null, undefined, 'F2irst'];\n\n  class MyClassOne {\n    @IsEnum(MyDefaultIndexedEnum)\n    someProperty: MyDefaultIndexedEnum;\n  }\n\n  class MyClassTwo {\n    @IsEnum(MyCustomIndexedEnum)\n    someProperty: MyCustomIndexedEnum;\n  }\n\n  class MyClassThree {\n    @IsEnum(MyStringEnum)\n    someProperty: MyStringEnum;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClassTwo(), validValues);\n  });\n\n  it('should not fail if validator.validate said that its valid (string enum)', () => {\n    return checkValidValues(new MyClassThree(), validStringValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClassTwo(), invalidValues);\n  });\n\n  it('should fail if validator.validate said that its invalid (string enum)', () => {\n    return checkInvalidValues(new MyClassThree(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isEnum(value, MyCustomIndexedEnum)).toBeTruthy());\n  });\n\n  it('should not fail if method in validator said that its valid (string enum)', () => {\n    validStringValues.forEach(value => expect(isEnum(value, MyStringEnum)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isEnum(value, MyCustomIndexedEnum)).toBeFalsy());\n  });\n\n  it('should fail if method in validator said that its invalid (string enum)', () => {\n    invalidValues.forEach(value => expect(isEnum(value, MyStringEnum)).toBeFalsy());\n  });\n\n  it('should return error with proper message for default indexed enum', () => {\n    const validationType = 'isEnum';\n    const message = 'someProperty must be one of the following values: 0, 1';\n    return checkReturnedError(new MyClassOne(), invalidValues, validationType, message);\n  });\n\n  it('should return error with proper message for custom indexed enum', () => {\n    const validationType = 'isEnum';\n    const message = 'someProperty must be one of the following values: 1, 999';\n    return checkReturnedError(new MyClassTwo(), invalidValues, validationType, message);\n  });\n\n  it('should return error with proper message for string enum', () => {\n    const validationType = 'isEnum';\n    const message = 'someProperty must be one of the following values: first, second';\n    return checkReturnedError(new MyClassThree(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsDivisibleBy', () => {\n  const constraint = 2;\n  const validValues = [2, 4, 100, 1000];\n  const invalidValues = ['', undefined, null];\n\n  class MyClass {\n    @IsDivisibleBy(constraint)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isDivisibleBy(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isDivisibleBy(value as any, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isDivisibleBy';\n    const message = 'someProperty must be divisible by ' + constraintToString(constraint);\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsPositive', () => {\n  const validValues = [3, 5000];\n  const invalidValues = [\n    '-1',\n    '-2',\n    '0',\n    '1',\n    '2',\n    '3',\n    '4',\n    '5',\n    '6',\n    '7',\n    '8',\n    '9',\n    '100000',\n    -500,\n    -123,\n    -1,\n    '   ',\n    '',\n  ];\n\n  class MyClass {\n    @IsPositive()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isPositive(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isPositive(value as any)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isPositive';\n    const message = 'someProperty must be a positive number';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsNegative', () => {\n  const validValues = [-3, -5000, -0.1];\n  const invalidValues = [\n    '-1',\n    '-2',\n    '0',\n    '1',\n    '2',\n    '3',\n    '4',\n    '5',\n    '6',\n    '7',\n    '8',\n    '9',\n    '100000',\n    500,\n    123,\n    1,\n    '   ',\n    '',\n  ];\n\n  class MyClass {\n    @IsNegative()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isNegative(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isNegative(value as any)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isNegative';\n    const message = 'someProperty must be a negative number';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('Min', () => {\n  const constraint = 10;\n  const validValues = [10, 11, 20, 30, 40];\n  const invalidValues = [2, 3, 4, 5, 6, 7, 8, 9, -10];\n\n  class MyClass {\n    @Min(constraint)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(min(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(min(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'min';\n    const message = 'someProperty must not be less than ' + constraintToString(constraint);\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('Max', () => {\n  const constraint = 10;\n  const validValues = [1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 10];\n  const invalidValues = [11, 20, 30, 40];\n\n  class MyClass {\n    @Max(constraint)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(max(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(max(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'max';\n    const message = 'someProperty must not be greater than ' + constraintToString(constraint);\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('MinDate', () => {\n  const constraint = new Date(1995, 11, 17);\n  const validValues = [new Date()];\n  const invalidValues = [new Date(1994, 11, 17)];\n\n  class MyClass {\n    @MinDate(constraint)\n    someProperty: Date;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(minDate(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(minDate(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'minDate';\n    const message = 'minimal allowed date for someProperty is ' + constraintToString(constraint);\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('MaxDate', () => {\n  const constraint = new Date(1995, 11, 17);\n  const validValues = [new Date(1994, 11, 17)];\n  const invalidValues = [new Date()];\n\n  class MyClass {\n    @MaxDate(constraint)\n    someProperty: Date;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(maxDate(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(maxDate(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'maxDate';\n    const message = 'maximal allowed date for someProperty is ' + constraintToString(constraint);\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('MinDate function constraint', () => {\n  const constraint = () => new Date(1995, 11, 17);\n  const validValues = [new Date()];\n  const invalidValues = [new Date(1994, 11, 17)];\n\n  class MyClass {\n    @MinDate(constraint)\n    someProperty: Date;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(minDate(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(minDate(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'minDate';\n    const message = 'minimal allowed date for someProperty is ' + constraintToString(constraint);\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('MaxDate function constraint', () => {\n  const constraint = () => new Date(1995, 11, 17);\n  const validValues = [new Date(1994, 11, 17)];\n  const invalidValues = [new Date()];\n\n  class MyClass {\n    @MaxDate(constraint)\n    someProperty: Date;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(maxDate(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(maxDate(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'maxDate';\n    const message = 'maximal allowed date for someProperty is ' + constraintToString(constraint);\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsBooleanString', () => {\n  const validValues = ['1', '0', 'true', 'false'];\n  const invalidValues = ['2', '3', 'falze'];\n\n  class MyClass {\n    @IsBooleanString()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isBooleanString(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isBooleanString(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isBooleanString';\n    const message = 'someProperty must be a boolean string';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsNumberString', () => {\n  const validValues = ['123', '123.123', '00123', '-00123', '0', '-0', '+123'];\n  const invalidValues = [' ', '.'];\n\n  class MyClass {\n    @IsNumberString()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isNumberString(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isNumberString(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isNumberString';\n    const message = 'someProperty must be a number string';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('Contains', () => {\n  const constraint = 'hello';\n  const validValues = ['hello world'];\n  const invalidValues = [null, undefined, 'bye world'];\n\n  class MyClass {\n    @Contains(constraint)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(contains(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(contains(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'contains';\n    const message = 'someProperty must contain a ' + constraintToString(constraint) + ' string';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('NotContains', () => {\n  const constraint = 'hello';\n  const validValues = ['bye world'];\n  const invalidValues = [null, undefined, 'hello world'];\n\n  class MyClass {\n    @NotContains(constraint)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(notContains(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(notContains(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'notContains';\n    const message = 'someProperty should not contain a ' + constraintToString(constraint) + ' string';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsAlpha', () => {\n  const constraint = 'en-GB';\n  const validValues = ['hellomynameisalex'];\n  const invalidValues = [null, undefined, 'hello1mynameisalex'];\n\n  class MyClass {\n    @IsAlpha()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isAlpha(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isAlpha(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isAlpha';\n    const message = 'someProperty must contain only letters (a-zA-Z)';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsAlphanumeric', () => {\n  const constraint = '';\n  const validValues = ['hellomyname1salex'];\n  const invalidValues = [null, undefined, 'hell*mynameisalex'];\n\n  class MyClass {\n    @IsAlphanumeric()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isAlphanumeric(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isAlphanumeric(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isAlphanumeric';\n    const message = 'someProperty must contain only letters and numbers';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsAscii', () => {\n  const constraint = '';\n  const validValues = ['hellomyname1salex'];\n  const invalidValues = [null, undefined, 'hell*mynameisлеха'];\n\n  class MyClass {\n    @IsAscii()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isAscii(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isAscii(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isAscii';\n    const message = 'someProperty must contain only ASCII characters';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsDecimal', () => {\n  const validValues = [\n    '100.0',\n    '100.1',\n    '100.3',\n    '100.4',\n    '100.5',\n    '100.6',\n    '100.7',\n    '100.8',\n    '100.9',\n    '1.9',\n    '-1.9',\n    '-124.1',\n  ];\n\n  const invalidValues = [\n    null,\n    undefined,\n    'hello',\n    '',\n    '1',\n    '1.',\n    '1,',\n    '-1',\n    '100',\n    '100,100',\n    '100.23',\n    '100.214141',\n    '100,23',\n    '100,2143192',\n  ];\n\n  const isDecimalOptions: ValidatorJS.IsDecimalOptions = {\n    // eslint-disable-next-line @typescript-eslint/camelcase\n    force_decimal: true,\n    // eslint-disable-next-line @typescript-eslint/camelcase\n    decimal_digits: '1',\n    locale: 'en-US',\n  };\n\n  class MyClass {\n    @IsDecimal(isDecimalOptions)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isDecimal(value, isDecimalOptions)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isDecimal(value, isDecimalOptions)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isDecimal';\n    const message = 'someProperty is not a valid decimal number.';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsBase32', () => {\n  const constraint = '';\n  const validValues = [\n    'ZG======',\n    'JBSQ====',\n    'JBSWY===',\n    'JBSWY3A=',\n    'JBSWY3DP',\n    'JBSWY3DPEA======',\n    'K5SWYY3PNVSSA5DPEBXG6ZA=',\n    'K5SWYY3PNVSSA5DPEBXG6===',\n  ];\n  const invalidValues = [\n    null,\n    undefined,\n    '12345',\n    '',\n    'JBSWY3DPtesting123',\n    'ZG=====',\n    'Z======',\n    'Zm=8JBSWY3DP',\n    '=m9vYg==',\n    'Zm9vYm/y====',\n  ];\n\n  class MyClass {\n    @IsBase32()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isBase32(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isBase32(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isBase32';\n    const message = 'someProperty must be base32 encoded';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsBase64', () => {\n  const constraint = '';\n  const validValues = ['aGVsbG8='];\n  const invalidValues = [null, undefined, 'hell*mynameisalex'];\n\n  const validBase64UrlValues = ['dGVzdA', 'dGV_zdA'];\n  const invalidBase64UrlValues = [null, undefined, 'dGVzdA=', 'MTIzNDU2Nzg5!!', 'SGVsbG8+V29ybGQ='];\n\n  class MyClass {\n    @IsBase64()\n    someProperty: string;\n  }\n\n  class MyClassWithConstraint {\n    @IsBase64({ urlSafe: true })\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', async () => {\n    await checkValidValues(new MyClass(), validValues);\n    await checkValidValues(new MyClassWithConstraint(), validBase64UrlValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', async () => {\n    await checkInvalidValues(new MyClass(), invalidValues);\n    await checkInvalidValues(new MyClassWithConstraint(), invalidBase64UrlValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isBase64(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isBase64(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isBase64';\n    const message = 'someProperty must be base64 encoded';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsIBAN', () => {\n  const constraint = '';\n  const validValues = ['GR96 0810 0010 0000 0123 4567 890'];\n  const invalidValues = [null, undefined, 'XX22YYY1234567890123'];\n\n  class MyClass {\n    @IsIBAN()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isIBAN(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isIBAN(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isIBAN';\n    const message = 'someProperty must be an IBAN';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsBIC', () => {\n  const constraint = '';\n  const validValues = ['SBICKEN1345'];\n  const invalidValues = [null, undefined, 'SBIC23NXXX'];\n\n  class MyClass {\n    @IsBIC()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isBIC(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isBIC(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isBIC';\n    const message = 'someProperty must be a BIC or SWIFT code';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsEthereumAddress', () => {\n  const constraint = '';\n  const validValues = ['0x683E07492fBDfDA84457C16546ac3f433BFaa128'];\n  const invalidValues = [null, undefined, '0xFCb5AFB808b5679b4911230Aa41FfCD0cd335b422222'];\n\n  class MyClass {\n    @IsEthereumAddress()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isEthereumAddress(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isEthereumAddress(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isEthereumAddress';\n    const message = 'someProperty must be an Ethereum address';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsBtcAddress', () => {\n  const constraint = '';\n  const validValues = ['bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq'];\n  const invalidValues = [null, undefined, 'pp8skudq3x5hzw8ew7vzsw8tn4k8wxsqsv0lt0mf3g'];\n\n  class MyClass {\n    @IsBtcAddress()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isBtcAddress(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isBtcAddress(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isBtcAddress';\n    const message = 'someProperty must be a BTC address';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsDataURI', () => {\n  const constraint = '';\n  const validValues = ['data:text/html;charset=US-ASCII,%3Ch1%3EHello!%3C%2Fh1%3E'];\n  const invalidValues = [null, undefined, 'data:HelloWorld'];\n\n  class MyClass {\n    @IsDataURI()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isDataURI(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isDataURI(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isDataURI';\n    const message = 'someProperty must be a data uri format';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsHSL', () => {\n  const constraint = '';\n  const validValues = ['hsl(-540, 03%, 4%)'];\n  const invalidValues = [null, undefined, 'hsl(-0160, 100%, 100a)'];\n\n  class MyClass {\n    @IsHSL()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isHSL(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isHSL(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isHSL';\n    const message = 'someProperty must be a HSL color';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsRgbColor', () => {\n  const constraint = '';\n  const validValues = ['rgba(255,255,255,0.1)'];\n  const invalidValues = [null, undefined, 'rgba(0,0,0)'];\n\n  class MyClass {\n    @IsRgbColor()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isRgbColor(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isRgbColor(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isRgbColor';\n    const message = 'someProperty must be RGB color';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsIdentityCard', () => {\n  const constraint = 'he-IL';\n  const validValues = ['335240479'];\n  const invalidValues = [null, undefined, 'A1234567L'];\n\n  class MyClass {\n    @IsIdentityCard(constraint)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isIdentityCard(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isIdentityCard(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isIdentityCard';\n    const message = 'someProperty must be a identity card number';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsEAN', () => {\n  const constraint = '';\n  const validValues = ['9771234567003'];\n  const invalidValues = [null, undefined, '079777681629'];\n\n  class MyClass {\n    @IsEAN()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isEAN(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isEAN(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isEAN';\n    const message = 'someProperty must be an EAN (European Article Number)';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsISRC', () => {\n  const constraint = '';\n  const validValues = ['GBAYE6800011'];\n  const invalidValues = [null, undefined, 'SRC15705223'];\n\n  class MyClass {\n    @IsISRC()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isISRC(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isISRC(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isISRC';\n    const message = 'someProperty must be an ISRC';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsRFC3339', () => {\n  const constraint = '';\n  const validValues = ['2010-02-18t00:23:23.33+06:00'];\n  const invalidValues = [null, undefined, '2009-05-31 14:60:55Z'];\n\n  class MyClass {\n    @IsRFC3339()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isRFC3339(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isRFC3339(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isRFC3339';\n    const message = 'someProperty must be RFC 3339 date';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsLocale', () => {\n  const constraint = '';\n  const validValues = ['en_US_POSIX'];\n  const invalidValues = [null, undefined, 'lo_POP'];\n\n  class MyClass {\n    @IsLocale()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isLocale(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isLocale(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isLocale';\n    const message = 'someProperty must be locale';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsMagnetURI', () => {\n  const constraint = '';\n  const validValues = ['magnet:?xt=urn:btih:1GSHJVBDVDVJFYEHKFHEFIO8573898434JBFEGHD&dn=foo&tr=udp://foo.com:1337'];\n  const invalidValues = [\n    null,\n    undefined,\n    'magnet:?xt=uarn:btih:MCJDCYUFHEUD6E2752T7UJNEKHSUGEJFGTFHVBJS&dn=bar&tr=udp://bar.com:1337',\n  ];\n\n  class MyClass {\n    @IsMagnetURI()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isMagnetURI(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isMagnetURI(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isMagnetURI';\n    const message = 'someProperty must be magnet uri format';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsMimeType', () => {\n  const constraint = '';\n  const validValues = ['multipart/form-data; boundary=something; charset=utf-8'];\n  const invalidValues = [null, undefined, 'font/woff2; charset=utf-8'];\n\n  class MyClass {\n    @IsMimeType()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isMimeType(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isMimeType(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isMimeType';\n    const message = 'someProperty must be MIME type format';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsOctal', () => {\n  const constraint = '';\n  const validValues = ['0o01234567'];\n  const invalidValues = [null, undefined, '00c12345670c'];\n\n  class MyClass {\n    @IsOctal()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isOctal(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isOctal(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isOctal';\n    const message = 'someProperty must be valid octal number';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsPassportNumber', () => {\n  const constraint = 'DE';\n  const validValues = ['C26VMVVC3'];\n  const invalidValues = [null, undefined, 'AS0123456'];\n\n  class MyClass {\n    @IsPassportNumber(constraint)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isPassportNumber(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isPassportNumber(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isPassportNumber';\n    const message = 'someProperty must be valid passport number';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsPostalCode', () => {\n  const constraint = 'BR';\n  const validValues = ['39100-000'];\n  const invalidValues = [null, undefined, '13165-00'];\n\n  class MyClass {\n    @IsPostalCode(constraint)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isPostalCode(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isPostalCode(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isPostalCode';\n    const message = 'someProperty must be a postal code';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsSemVer', () => {\n  const constraint = '';\n  const validValues = ['1.1.2+meta-valid'];\n  const invalidValues = [null, undefined, '1.0.0-alpha_beta'];\n\n  class MyClass {\n    @IsSemVer()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isSemVer(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isSemVer(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isSemVer';\n    const message = 'someProperty must be a Semantic Versioning Specification';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsByteLength', () => {\n  const constraint1 = 2;\n  const constraint2 = 20;\n  const validValues = ['hellostring'];\n  const invalidValues = [null, undefined, 'helloveryveryveryverylongstring'];\n\n  class MyClass {\n    @IsByteLength(constraint1, constraint2)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isByteLength(value, constraint1, constraint2)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isByteLength(value, constraint1, constraint2)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isByteLength';\n    const message =\n      \"someProperty's byte length must fall into (\" +\n      constraintToString(constraint1) +\n      ', ' +\n      constraintToString(constraint2) +\n      ') range';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsTaxId', () => {\n  const constraint = 'bg-BG';\n  const validValues = ['7501010010', '0101010012', '0111010010', '7521010014', '7541010019'];\n  const invalidValues = [null, undefined, '750101001', '75010100101', '75-01010/01 0', '7521320010', '7501010019'];\n\n  class MyClass {\n    @IsTaxId(constraint)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isTaxId(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isTaxId(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isTaxId';\n    const message = 'someProperty must be a Tax Identification Number';\n    checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsCreditCard', () => {\n  const validValues = [\n    '375556917985515',\n    '36050234196908',\n    '4716461583322103',\n    '4716-2210-5188-5662',\n    '4929 7226 5379 7141',\n    '5398228707871527',\n  ];\n  const invalidValues = [null, undefined, 'foo', 'foo', '5398228707871528'];\n\n  class MyClass {\n    @IsCreditCard()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isCreditCard(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isCreditCard(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isCreditCard';\n    const message = 'someProperty must be a credit card';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsCurrency', () => {\n  const validValues = [\n    '-$10,123.45',\n    '$10,123.45',\n    '$10123.45',\n    '10,123.45',\n    '10123.45',\n    '10,123',\n    '1,123,456',\n    '1123456',\n    '1.39',\n    '.03',\n    '0.10',\n    '$0.10',\n    '-$0.01',\n    '-$.99',\n    '$100,234,567.89',\n    '$10,123',\n    '10,123',\n    '-10123',\n  ];\n  const invalidValues = [\n    null,\n    undefined,\n    '1.234',\n    '$1.1',\n    '$ 32.50',\n    '500$',\n    '.0001',\n    '$.001',\n    '$0.001',\n    '12,34.56',\n    '123456,123,123456',\n    '123,4',\n    ',123',\n    '$-,123',\n    '$',\n    '.',\n    ',',\n    '00',\n    '$-',\n    '$-,.',\n    '-',\n    '-$',\n    '',\n    '- $',\n  ];\n\n  class MyClass {\n    @IsCurrency()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isCurrency(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isCurrency(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isCurrency';\n    const message = 'someProperty must be a currency';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsEmail', () => {\n  const validValues = [\n    'foo@bar.com',\n    'x@x.au',\n    'foo@bar.com.au',\n    'foo+bar@bar.com',\n    'hans.m端ller@test.com',\n    'hans@m端ller.com',\n    'test|123@m端ller.com',\n    '\"foobar\"@example.com',\n    '\"  foo  m端ller \"@example.com',\n    '\"foo\\\\@bar\"@example.com',\n  ];\n  const invalidValues = [\n    null,\n    undefined,\n    'invalidemail@',\n    'invalid.com',\n    '@invalid.com',\n    'foo@bar.com.',\n    'somename@ｇｍａｉｌ.com',\n    'foo@bar.co.uk.',\n    'z@co.c',\n    'gmail...ignores...dots...@gmail.com',\n    'ｇｍａｉｌｇｍａｉｌｇｍａｉｌｇｍａｉｌｇｍａｉｌ@gmail.com',\n  ];\n\n  class MyClass {\n    @IsEmail()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => {\n      expect(isEmail(value)).toBeTruthy();\n    });\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isEmail(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isEmail';\n    const message = 'someProperty must be an email';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsFQDN', () => {\n  const validValues = [\n    'domain.com',\n    'dom.plato',\n    'a.domain.co',\n    'foo--bar.com',\n    'xn--froschgrn-x9a.com',\n    'rebecca.blackfriday',\n  ];\n  const invalidValues = [\n    null,\n    undefined,\n    'abc',\n    '256.0.0.0',\n    '_.com',\n    '*.some.com',\n    's!ome.com',\n    'domain.com/',\n    '/more.com',\n  ];\n\n  class MyClass {\n    @IsFQDN()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isFQDN(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isFQDN(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isFqdn';\n    const message = 'someProperty must be a valid domain name';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsFullWidth', () => {\n  const validValues = ['ひらがな・カタカナ、．漢字', '３ー０　ａ＠ｃｏｍ', 'Ｆｶﾀｶﾅﾞﾬ', 'Good＝Parts'];\n  const invalidValues = [null, undefined, 'abc', 'abc123'];\n\n  class MyClass {\n    @IsFullWidth()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isFullWidth(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isFullWidth(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isFullWidth';\n    const message = 'someProperty must contain a full-width characters';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsHalfWidth', () => {\n  const validValues = ['l-btn_02--active', 'abc123い', 'ｶﾀｶﾅﾞﾬ￩'];\n  const invalidValues = [null, undefined, 'あいうえお', '００１１'];\n\n  class MyClass {\n    @IsHalfWidth()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isHalfWidth(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isHalfWidth(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isHalfWidth';\n    const message = 'someProperty must contain a half-width characters';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsVariableWidth', () => {\n  const validValues = ['ひらがなカタカナ漢字ABCDE', '３ー０123', 'Ｆｶﾀｶﾅﾞﾬ', 'Good＝Parts'];\n  const invalidValues = [\n    null,\n    undefined,\n    'abc',\n    'abc123',\n    '!\"#$%&()<>/+=-_? ~^|.,@`{}[]',\n    'ひらがな・カタカナ、．漢字',\n    '１２３４５６',\n    'ｶﾀｶﾅﾞﾬ',\n  ];\n\n  class MyClass {\n    @IsVariableWidth()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isVariableWidth(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isVariableWidth(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isVariableWidth';\n    const message = 'someProperty must contain a full-width and half-width characters';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsHexColor', () => {\n  const validValues = ['#ff0034', '#CCCCCC', 'fff', '#f00'];\n  const invalidValues = [null, undefined, '#ff', '#xxxx', '#ff12FG'];\n\n  class MyClass {\n    @IsHexColor()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    invalidValues.forEach(value => expect(isHexColor(value)).toBeFalsy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    validValues.forEach(value => expect(isHexColor(value)).toBeTruthy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isHexColor';\n    const message = 'someProperty must be a hexadecimal color';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsHexadecimal', () => {\n  const validValues = ['deadBEEF', 'ff0044'];\n  const invalidValues = [null, undefined, 'abcdefg', '', '..'];\n\n  class MyClass {\n    @IsHexadecimal()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isHexadecimal(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isHexadecimal(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isHexadecimal';\n    const message = 'someProperty must be a hexadecimal number';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsMACAddress', () => {\n  const validValues = ['ab:ab:ab:ab:ab:ab', 'FF:FF:FF:FF:FF:FF', '01:02:03:04:05:ab', '01:AB:03:04:05:06'];\n  const invalidValues = [\n    null,\n    undefined,\n    'abc',\n    '01:02:03:04:05',\n    '01:02:03:04::ab',\n    '1:2:3:4:5:6',\n    'AB:CD:EF:GH:01:02',\n    'A9C5 D4 9F EB D3',\n    '01-02 03:04 05 ab',\n  ];\n\n  class MyClass {\n    @IsMACAddress()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isMACAddress(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isMACAddress(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isMacAddress';\n    const message = 'someProperty must be a MAC Address';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsIP', () => {\n  const validValues = [\n    '127.0.0.1',\n    '0.0.0.0',\n    '255.255.255.255',\n    '1.2.3.4',\n    '::1',\n    '2001:db8:0000:1:1:1:1:1',\n    '2001:41d0:2:a141::1',\n    '::ffff:127.0.0.1',\n    '::0000',\n    '0000::',\n    '1::',\n    '1111:1:1:1:1:1:1:1',\n    'fe80::a6db:30ff:fe98:e946',\n    '::',\n    '::ffff:127.0.0.1',\n    '0:0:0:0:0:ffff:127.0.0.1',\n  ];\n  const invalidValues = [\n    null,\n    undefined,\n    'abc',\n    '256.0.0.0',\n    '0.0.0.256',\n    '26.0.0.256',\n    '::banana',\n    'banana::',\n    '::1banana',\n    '::1::',\n    '1:',\n    ':1',\n    ':1:1:1::2',\n    '1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1',\n    '::11111',\n    '11111:1:1:1:1:1:1:1',\n    '2001:db8:0000:1:1:1:1::1',\n    '0:0:0:0:0:0:ffff:127.0.0.1',\n    '0:0:0:0:ffff:127.0.0.1',\n  ];\n\n  class MyClass {\n    @IsIP()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isIP(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isIP(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isIp';\n    const message = 'someProperty must be an ip address';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsISBN version 10', () => {\n  const validValues = [\n    '3836221195',\n    '3-8362-2119-5',\n    '3 8362 2119 5',\n    '1617290858',\n    '1-61729-085-8',\n    '1 61729 085-8',\n    '0007269706',\n    '0-00-726970-6',\n    '0 00 726970 6',\n    '3423214120',\n    '3-423-21412-0',\n    '3 423 21412 0',\n    '340101319X',\n    '3-401-01319-X',\n    '3 401 01319 X',\n  ];\n  const invalidValues = [\n    null,\n    undefined,\n    '3423214121',\n    '3-423-21412-1',\n    '3 423 21412 1',\n    '978-3836221191',\n    '9783836221191',\n    '123456789a',\n    'foo',\n  ];\n\n  class MyClass {\n    @IsISBN(10)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isISBN(value, '10')).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isISBN(value, '10')).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isIsbn';\n    const message = 'someProperty must be an ISBN';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsISBN version 13', () => {\n  const validValues = [\n    '9783836221191',\n    '978-3-8362-2119-1',\n    '978 3 8362 2119 1',\n    '9783401013190',\n    '978-3401013190',\n    '978 3401013190',\n    '9784873113685',\n    '978-4-87311-368-5',\n    '978 4 87311 368 5',\n  ];\n  const invalidValues = [\n    null,\n    undefined,\n    '9783836221190',\n    '978-3-8362-2119-0',\n    '978 3 8362 2119 0',\n    '3836221195',\n    '3-8362-2119-5',\n    '3 8362 2119 5',\n    '01234567890ab',\n    'foo',\n    '',\n  ];\n\n  class MyClass {\n    @IsISBN(13)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isISBN(value, '13')).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isISBN(value, '13')).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isIsbn';\n    const message = 'someProperty must be an ISBN';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsISO8601', () => {\n  const validValues = [\n    '2009-12T12:34',\n    '2009',\n    '2009-05-19',\n    '2009-05-19',\n    '20090519',\n    '2009123',\n    '2009-05',\n    '2009-123',\n    '2009-222',\n    '2009-001',\n    '2009-W01-1',\n    '2009-W51-1',\n    '2009-W511',\n    '2009-W33',\n    '2009W511',\n    '2009-05-19',\n    '2009-05-19 00:00',\n    '2009-05-19 14',\n    '2009-05-19 14:31',\n    '2009-05-19 14:39:22',\n    '2009-05-19T14:39Z',\n    '2009-W21-2',\n    '2009-W21-2T01:22',\n    '2009-139',\n    '2009-05-19 14:39:22-06:00',\n    '2009-05-19 14:39:22+0600',\n    '2009-05-19 14:39:22-01',\n    '20090621T0545Z',\n    '2007-04-06T00:00',\n    '2007-04-05T24:00',\n    '2010-02-18T16:23:48.5',\n    '2010-02-18T16:23:48,444',\n    '2010-02-18T16:23:48,3-06:00',\n    '2010-02-18T16:23.4',\n    '2010-02-18T16:23,25',\n    '2010-02-18T16:23.33+0600',\n    '2010-02-18T16.23334444',\n    '2010-02-18T16,2283',\n    '2009-05-19 143922.500',\n    '2009-05-19 1439,55',\n  ];\n  const invalidValues = [\n    null,\n    undefined,\n    '200905',\n    '2009367',\n    '2009-',\n    '2007-04-05T24:50',\n    '2009-000',\n    '2009-M511',\n    '2009M511',\n    '2009-05-19T14a39r',\n    '2009-05-19T14:3924',\n    '2009-0519',\n    '2009-05-1914:39',\n    '2009-05-19 14:',\n    '2009-05-19r14:39',\n    '2009-05-19 14a39a22',\n    '200912-01',\n    '2009-05-19 14:39:22+06a00',\n    '2009-05-19 146922.500',\n    '2010-02-18T16.5:23.35:48',\n    '2010-02-18T16:23.35:48',\n    '2010-02-18T16:23.35:48.45',\n    '2009-05-19 14.5.44',\n    '2010-02-18T16:23.33.600',\n    '2010-02-18T16,25:23:48,444',\n    '2009-02-29',\n  ];\n\n  class MyClass {\n    @IsISO8601({ strict: true })\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isISO8601(value, { strict: true })).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isISO8601(value, { strict: true })).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isIso8601';\n    const message = 'someProperty must be a valid ISO 8601 date string';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsJSON', () => {\n  const validValues = ['{ \"key\": \"value\" }', '{}'];\n  const invalidValues = [null, undefined, '{ key: \"value\" }', \"{ 'key': 'value' }\", 'null', '1234', 'false', '\"nope\"'];\n\n  class MyClass {\n    @IsJSON()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isJSON(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isJSON(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isJson';\n    const message = 'someProperty must be a json string';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsJWT', () => {\n  const validValues = [\n    'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dnZWRJbkFzIjoiYWRtaW4iLCJpYXQiOjE0MjI3Nzk2Mzh9.gzSraSYS8EXBxLN_oWnFSRgCzcmJmMjLiuyu5CSpyHI',\n    'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb3JlbSI6Imlwc3VtIn0.ymiJSsMJXR6tMSr8G9usjQ15_8hKPDv_CArLhxw28MI',\n    'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkb2xvciI6InNpdCIsImFtZXQiOlsibG9yZW0iLCJpcHN1bSJdfQ.rRpe04zbWbbJjwM43VnHzAboDzszJtGrNsUxaqQ-GQ8',\n    'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqb2huIjp7ImFnZSI6MjUsImhlaWdodCI6MTg1fSwiamFrZSI6eyJhZ2UiOjMwLCJoZWlnaHQiOjI3MH19.YRLPARDmhGMC3BBk_OhtwwK21PIkVCqQe8ncIRPKo-E',\n  ];\n  const invalidValues = [\n    'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',\n    '$Zs.ewu.su84',\n    'ks64$S/9.dy$§kz.3sd73b',\n    'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ', // No signature\n  ];\n\n  class MyClass {\n    @IsJWT()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isJWT(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isJWT(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isJwt';\n    const message = 'someProperty must be a jwt string';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsObject', () => {\n  const validValues = [{ key: 'value' }, { key: 'value' }, {}];\n  const invalidValues: any[] = [\n    null,\n    undefined,\n    '{ key: \"value\" }',\n    \"{ 'key': 'value' }\",\n    'string',\n    1234,\n    false,\n    '[]',\n    [],\n    [{ key: 'value' }],\n  ];\n\n  class MyClass {\n    @IsObject()\n    someProperty: object;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isObject(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isObject(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isObject';\n    const message = 'someProperty must be an object';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsNotEmptyObject', () => {\n  const validValues = [{ key: 'value' }, { key: 'value' }, { key: undefined }, { key: null }];\n  const invalidValues = [\n    null,\n    undefined,\n    '{ key: \"value\" }',\n    \"{ 'key': 'value' }\",\n    'string',\n    1234,\n    false,\n    {},\n    [],\n    [{ key: 'value' }],\n  ];\n\n  class MyClass {\n    @IsNotEmptyObject()\n    someProperty: object;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isNotEmptyObject(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isNotEmptyObject(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isNotEmptyObject';\n    const message = 'someProperty must be a non-empty object';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n\n  describe('with `nullable` option', () => {\n    const nullableValidValues = validValues;\n    const nullableInvalidValues = invalidValues;\n    const nonNullableValidValues = [{ key: 'value' }, { key: 'value' }];\n    const nonNullableInvalidValues = [\n      null,\n      undefined,\n      '{ key: \"value\" }',\n      \"{ 'key': 'value' }\",\n      'string',\n      1234,\n      false,\n      {},\n      { key: undefined },\n      { key: null },\n      [],\n      [{ key: 'value' }],\n    ];\n    class NullableMyClass {\n      @IsNotEmptyObject({ nullable: true })\n      someProperty: object;\n    }\n    class NonNullableMyClass {\n      @IsNotEmptyObject({ nullable: false })\n      someProperty: object;\n    }\n\n    it('should not fail if validator.validate said that its valid', async () => {\n      await checkValidValues(new NullableMyClass(), nullableValidValues);\n      await checkValidValues(new NonNullableMyClass(), nonNullableValidValues);\n    });\n\n    it('should fail if validator.validate said that its valid', async () => {\n      await checkInvalidValues(new NullableMyClass(), nullableInvalidValues);\n      await checkInvalidValues(new NonNullableMyClass(), nonNullableInvalidValues);\n    });\n\n    it('should not fail if method in validator said that its valid', () => {\n      nullableValidValues.forEach(value => expect(isNotEmptyObject(value, { nullable: true })).toBeTruthy());\n      nonNullableValidValues.forEach(value => expect(isNotEmptyObject(value, { nullable: false })).toBeTruthy());\n    });\n\n    it('should fail if method in validator said that its invalid', () => {\n      nullableInvalidValues.forEach(value => expect(isNotEmptyObject(value, { nullable: true })).toBeFalsy());\n      nonNullableInvalidValues.forEach(value => expect(isNotEmptyObject(value, { nullable: false })).toBeFalsy());\n    });\n  });\n});\n\ndescribe('IsLowercase', () => {\n  const validValues = ['abc', 'abc123', 'this is lowercase.', 'tr竪s 端ber'];\n  const invalidValues = [null, undefined, 'fooBar', '123A'];\n\n  class MyClass {\n    @IsLowercase()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isLowercase(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isLowercase(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isLowercase';\n    const message = 'someProperty must be a lowercase string';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsMongoId', () => {\n  const validValues = ['507f1f77bcf86cd799439011'];\n  const invalidValues = [\n    null,\n    undefined,\n    '507f1f77bcf86cd7994390',\n    '507f1f77bcf86cd79943901z',\n    '',\n    '507f1f77bcf86cd799439011 ',\n  ];\n\n  class MyClass {\n    @IsMongoId()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isMongoId(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isMongoId(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isMongoId';\n    const message = 'someProperty must be a mongodb id';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsMultibyte', () => {\n  const validValues = [\n    'ひらがな・カタカナ、．漢字',\n    'あいうえお foobar',\n    'test＠example.com',\n    '1234abcDEｘｙｚ',\n    'ｶﾀｶﾅ',\n    '中文',\n  ];\n  const invalidValues = [null, undefined, 'abc', 'abc123', '<>@\" *.'];\n\n  class MyClass {\n    @IsMultibyte()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isMultibyte(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isMultibyte(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isMultibyte';\n    const message = 'someProperty must contain one or more multibyte chars';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsSurrogatePair', () => {\n  const validValues = ['𠮷野𠮷', '𩸽', 'ABC千𥧄1-2-3'];\n  const invalidValues = [null, undefined, '吉野竈', '鮪', 'ABC1-2-3'];\n\n  class MyClass {\n    @IsSurrogatePair()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isSurrogatePair(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isSurrogatePair(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isSurrogatePair';\n    const message = 'someProperty must contain any surrogate pairs chars';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsUrl', () => {\n  const validValues = [\n    'foobar.com',\n    'www.foobar.com',\n    'foobar.com/',\n    'valid.au',\n    'http://www.foobar.com/',\n    'http://www.foobar.com:23/',\n    'http://www.foobar.com:65535/',\n    'http://www.foobar.com:5/',\n    'https://www.foobar.com/',\n    'ftp://www.foobar.com/',\n    'http://www.foobar.com/~foobar',\n    'http://user:pass@www.foobar.com/',\n    'http://user:@www.foobar.com/',\n    'http://127.0.0.1/',\n    'http://10.0.0.0/',\n    'http://189.123.14.13/',\n    'http://duckduckgo.com/?q=%2F',\n    'http://foobar.com/t$-_.+!*\"(),',\n    'http://foobar.com/?foo=bar#baz=qux',\n    'http://foobar.com?foo=bar',\n    'http://foobar.com#baz=qux',\n    'http://www.xn--froschgrn-x9a.net/',\n    'http://xn--froschgrn-x9a.com/',\n    'http://foo--bar.com',\n    'http://høyfjellet.no',\n    'http://xn--j1aac5a4g.xn--j1amh',\n  ];\n  const invalidValues = [\n    null,\n    undefined,\n    'xyz://foobar.com',\n    'invalid/',\n    'invalid.x',\n    'invalid.',\n    '.com',\n    'http://com/',\n    'http://300.0.0.1/',\n    'mailto:foo@bar.com',\n    'rtmp://foobar.com',\n    'http://www.xn--.com/',\n    'http://xn--.com/',\n    'http://www.foobar.com:0/',\n    'http://www.foobar.com:70000/',\n    'http://www.foobar.com:99999/',\n    'http://www.-foobar.com/',\n    'http://www.foobar-.com/',\n    'http://foobar/# lol',\n    'http://foobar/? lol',\n    'http://foobar/ lol/',\n    'http://lol @foobar.com/',\n    'http://lol:lol @foobar.com/',\n    'http://lol:lol:lol@foobar.com/',\n    'http://lol: @foobar.com/',\n    'http://www.foo_bar.com/',\n    'http://www.foobar.com/\\t',\n    'http://\\n@www.foobar.com/',\n    '',\n    'http://localhost:61500this is an invalid url!!!!',\n    'http://foobar.com/' + new Array(2083).join('f'),\n    'http://*.foo.com',\n    '*.foo.com',\n    '!.foo.com',\n    'http://example.com.',\n    '////foobar.com',\n    'http:////foobar.com',\n  ];\n\n  class MyClass {\n    @IsUrl()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isURL(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isURL(value)).toBeFalsy());\n  });\n\n  it('should fail on localhost without require_tld option', () => {\n    expect(isURL('http://localhost:3000/')).toBeFalsy();\n  });\n\n  it('should pass on localhost with require_tld option', () => {\n    // eslint-disable-next-line @typescript-eslint/camelcase\n    expect(isURL('http://localhost:3000/', { require_tld: false })).toBeTruthy();\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isUrl';\n    const message = 'someProperty must be a URL address';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsUUID', () => {\n  const validValues = [\n    'A987FBC9-4BED-3078-8F07-9141BA07C9F3', // v3\n    'A987FBC9-4BED-4078-8F07-9141BA07C9F3', // v4\n    'A987FBC9-4BED-5078-AF07-9141BA07C9F3', // v5\n    'e32c8312-5012-11e8-a3b3-069326100140', // v1\n    '00000000-0000-2000-8000-000000000000', // v2\n    '1ec9414c-232a-6b00-b3c8-9e6bdec7bc00', // v6\n    '017f22e2-79b0-7cc3-98c4-dc0c0c07398f', // v7\n    'a0eebc99-9c0b-8ef8-bb6d-6bb9bd380a11', // v8\n    '00000000-0000-0000-0000-000000000000', // nil\n    'ffffffff-ffff-ffff-ffff-ffffffffffff', // max\n  ];\n  const invalidValues = [\n    null,\n    undefined,\n    '',\n    'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n    'A987FBC9-4BED-3078-CF07-9141BA07C9F3xxx',\n    'A987FBC94BED3078CF079141BA07C9F3',\n    '934859',\n    '987FBC9-4BED-3078-CF07A-9141BA07C9F3',\n    'AAAAAAAA-1111-1111-AAAG-111111111111',\n    'A987FBC9-4BED-3078-CF07-9141BA07C9F3', // does not conform to RFC9562 UUID\n  ];\n\n  class MyClass {\n    @IsUUID()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isUUID(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isUUID(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isUuid';\n    const message = 'someProperty must be a UUID';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsUUID v3', () => {\n  const validValues = [\n    'A987FBC9-4BED-3078-8F07-9141BA07C9F3',\n    'A987FBC9-4BED-3078-9F07-9141BA07C9F3',\n    'A987FBC9-4BED-3078-AF07-9141BA07C9F3',\n    'A987FBC9-4BED-3078-BF07-9141BA07C9F3',\n  ];\n  const invalidValues = [\n    null,\n    undefined,\n    '',\n    'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n    '934859',\n    'AAAAAAAA-1111-1111-AAAG-111111111111',\n    'A987FBC9-4BED-4078-8F07-9141BA07C9F3',\n    'A987FBC9-4BED-5078-AF07-9141BA07C9F3',\n    'A987FBC9-4BED-3078-CF07-9141BA07C9F3', // does not conform to RFC9562 UUID\n  ];\n\n  class MyClass {\n    @IsUUID('3')\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isUUID(value, '3')).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isUUID(value, '3')).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isUuid';\n    const message = 'someProperty must be a UUID';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsUUID v4', () => {\n  const validValues = [\n    '713ae7e3-cb32-45f9-adcb-7c4fa86b90c1',\n    '625e63f3-58f5-40b7-83a1-a72ad31acffb',\n    '57b73598-8764-4ad0-a76a-679bb6640eb1',\n    '9c858901-8a57-4791-81fe-4c455b099bc9',\n  ];\n  const invalidValues = [\n    null,\n    undefined,\n    '',\n    'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n    '934859',\n    'AAAAAAAA-1111-1111-AAAG-111111111111',\n    'A987FBC9-4BED-5078-AF07-9141BA07C9F3',\n    'A987FBC9-4BED-3078-CF07-9141BA07C9F3',\n  ];\n\n  class MyClass {\n    @IsUUID('4')\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isUUID(value, '4')).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isUUID(value, '4')).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isUuid';\n    const message = 'someProperty must be a UUID';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsUUID v5', () => {\n  const validValues = [\n    '987FBC97-4BED-5078-AF07-9141BA07C9F3',\n    '987FBC97-4BED-5078-BF07-9141BA07C9F3',\n    '987FBC97-4BED-5078-8F07-9141BA07C9F3',\n    '987FBC97-4BED-5078-9F07-9141BA07C9F3',\n  ];\n  const invalidValues = [\n    null,\n    undefined,\n    '',\n    'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n    '934859',\n    'AAAAAAAA-1111-1111-AAAG-111111111111',\n    '9c858901-8a57-4791-81fe-4c455b099bc9',\n    'A987FBC9-4BED-3078-CF07-9141BA07C9F3',\n  ];\n\n  class MyClass {\n    @IsUUID('5')\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isUUID(value, '5')).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isUUID(value, '5')).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isUuid';\n    const message = 'someProperty must be a UUID';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsUUID v1', () => {\n  const validValues = ['e32c8312-5012-11e8-a3b3-069326100140', 'd9428888-122b-11e1-b85c-61cd3cbb3210'];\n  const invalidValues = [\n    null,\n    undefined,\n    '',\n    'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n    '934859',\n    'AAAAAAAA-1111-1111-AAAG-111111111111',\n    'A987FBC9-4BED-3078-8F07-9141BA07C9F3', // v3\n    '713ae7e3-cb32-45f9-adcb-7c4fa86b90c1', // v4\n  ];\n\n  class MyClass {\n    @IsUUID('1')\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isUUID(value, '1')).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isUUID(value, '1')).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isUuid';\n    const message = 'someProperty must be a UUID';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsUUID v2', () => {\n  const validValues = ['00000000-0000-2000-8000-000000000000'];\n  const invalidValues = [\n    null,\n    undefined,\n    '',\n    'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n    '934859',\n    'AAAAAAAA-1111-1111-AAAG-111111111111',\n    'A987FBC9-4BED-3078-8F07-9141BA07C9F3', // v3\n    '713ae7e3-cb32-45f9-adcb-7c4fa86b90c1', // v4\n  ];\n\n  class MyClass {\n    @IsUUID('2')\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isUUID(value, '2')).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isUUID(value, '2')).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isUuid';\n    const message = 'someProperty must be a UUID';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsUUID v6', () => {\n  const validValues = ['1ec9414c-232a-6b00-b3c8-9e6bdec7bc00'];\n  const invalidValues = [\n    null,\n    undefined,\n    '',\n    'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n    '934859',\n    'AAAAAAAA-1111-1111-AAAG-111111111111',\n    'A987FBC9-4BED-3078-8F07-9141BA07C9F3', // v3\n    '713ae7e3-cb32-45f9-adcb-7c4fa86b90c1', // v4\n  ];\n\n  class MyClass {\n    @IsUUID('6')\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isUUID(value, '6')).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isUUID(value, '6')).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isUuid';\n    const message = 'someProperty must be a UUID';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsUUID v7', () => {\n  const validValues = ['017f22e2-79b0-7cc3-98c4-dc0c0c07398f'];\n  const invalidValues = [\n    null,\n    undefined,\n    '',\n    'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n    '934859',\n    'AAAAAAAA-1111-1111-AAAG-111111111111',\n    'A987FBC9-4BED-3078-8F07-9141BA07C9F3', // v3\n    '713ae7e3-cb32-45f9-adcb-7c4fa86b90c1', // v4\n  ];\n\n  class MyClass {\n    @IsUUID('7')\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isUUID(value, '7')).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isUUID(value, '7')).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isUuid';\n    const message = 'someProperty must be a UUID';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsUUID v8', () => {\n  const validValues = ['a0eebc99-9c0b-8ef8-bb6d-6bb9bd380a11'];\n  const invalidValues = [\n    null,\n    undefined,\n    '',\n    'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n    '934859',\n    'AAAAAAAA-1111-1111-AAAG-111111111111',\n    'A987FBC9-4BED-3078-8F07-9141BA07C9F3', // v3\n    '713ae7e3-cb32-45f9-adcb-7c4fa86b90c1', // v4\n  ];\n\n  class MyClass {\n    @IsUUID('8')\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isUUID(value, '8')).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isUUID(value, '8')).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isUuid';\n    const message = 'someProperty must be a UUID';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsUUID nil', () => {\n  const validValues = ['00000000-0000-0000-0000-000000000000'];\n  const invalidValues = [\n    null,\n    undefined,\n    '',\n    'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n    '934859',\n    'AAAAAAAA-1111-1111-AAAG-111111111111',\n    'A987FBC9-4BED-3078-8F07-9141BA07C9F3', // v3\n    '713ae7e3-cb32-45f9-adcb-7c4fa86b90c1', // v4\n  ];\n\n  class MyClass {\n    @IsUUID('nil')\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isUUID(value, 'nil')).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isUUID(value, 'nil')).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isUuid';\n    const message = 'someProperty must be a UUID';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsUUID max', () => {\n  const validValues = ['ffffffff-ffff-ffff-ffff-ffffffffffff'];\n  const invalidValues = [\n    null,\n    undefined,\n    '',\n    'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n    '934859',\n    'AAAAAAAA-1111-1111-AAAG-111111111111',\n    'A987FBC9-4BED-3078-8F07-9141BA07C9F3', // v3\n    '713ae7e3-cb32-45f9-adcb-7c4fa86b90c1', // v4\n  ];\n\n  class MyClass {\n    @IsUUID('max')\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isUUID(value, 'max')).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isUUID(value, 'max')).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isUuid';\n    const message = 'someProperty must be a UUID';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsUUID all', () => {\n  const validValues = [\n    'A987FBC9-4BED-3078-8F07-9141BA07C9F3', // v3\n    '713ae7e3-cb32-45f9-adcb-7c4fa86b90c1', // v4\n    '987FBC97-4BED-5078-AF07-9141BA07C9F3', // v5\n    'e32c8312-5012-11e8-a3b3-069326100140', // v1\n    '00000000-0000-2000-8000-000000000000', // v2\n    '1ec9414c-232a-6b00-b3c8-9e6bdec7bc00', // v6\n    '017f22e2-79b0-7cc3-98c4-dc0c0c07398f', // v7\n    'a0eebc99-9c0b-8ef8-bb6d-6bb9bd380a11', // v8\n    '00000000-0000-0000-0000-000000000000', // nil\n    'ffffffff-ffff-ffff-ffff-ffffffffffff', // max\n  ];\n  const invalidValues = [\n    null,\n    undefined,\n    '',\n    'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n    '934859',\n    'AAAAAAAA-1111-1111-AAAG-111111111111',\n  ];\n\n  class MyClass {\n    @IsUUID('all')\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isUUID(value, 'all')).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isUUID(value, 'all')).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isUuid';\n    const message = 'someProperty must be a UUID';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsUUID loose', () => {\n  const validValues = [\n    'A987FBC9-4BED-3078-8F07-9141BA07C9F3',\n    'A987FBC9-4BED-3078-CF07-9141BA07C9F3',\n    'A987FBC9-4BED-0078-0F07-9141BA07C9F3',\n    'a987fbc9-4bed-3078-1234-9141ba07c9f3',\n  ];\n  const invalidValues = [\n    null,\n    undefined,\n    '',\n    'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n    '934859',\n    'AAAAAAAA-1111-1111-AAAG-111111111111',\n    '{A987FBC9-4BED-3078-8F07-9141BA07C9F3}',\n    'A987FBC94BED30788F079141BA07C9F3',\n  ];\n\n  class MyClass {\n    @IsUUID('loose')\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isUUID(value, 'loose')).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isUUID(value, 'loose')).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isUuid';\n    const message = 'someProperty must be a UUID';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsUUID with version array', () => {\n  const validValues = ['017f22e2-79b0-7cc3-98c4-dc0c0c07398f', '00000000-0000-0000-0000-000000000000'];\n  const invalidValues = [\n    null,\n    undefined,\n    '',\n    'A987FBC9-4BED-3078-8F07-9141BA07C9F3',\n    '713ae7e3-cb32-45f9-adcb-7c4fa86b90c1',\n  ];\n\n  class MyClass {\n    @IsUUID(['7', 'nil'])\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isUUID(value, ['7', 'nil'])).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isUUID(value, ['7', 'nil'])).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isUuid';\n    const message = 'someProperty must be a UUID';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsFirebasePushId', () => {\n  const validValues = [\n    '-M-Jh_1KAH5rYJF_7-kY',\n    '-M1yvu7FKe87rR_62NH7',\n    '-M1jVySxQQPktYyXA2qE',\n    '-JhLeOlGIEjaIOFHR0xd',\n    '-JhQ76OEK_848CkIFhAq',\n    '-JhQ7APk0UtyRTFO9-TS',\n  ];\n  const invalidValues = [\n    null,\n    undefined,\n    true,\n    false,\n    '',\n    '5584fa9e-6146-497a-85c9-dbb459ef7b74',\n    'Steve',\n    'dbfa63ea-2c1f-4cf8-b6b9-192b070b558c',\n  ];\n\n  class MyClass {\n    @IsFirebasePushId()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isFirebasePushId(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isFirebasePushId(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'IsFirebasePushId';\n    const message = 'someProperty must be a Firebase Push Id';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsUppercase', () => {\n  const validValues = ['ABC', 'ABC123', 'ALL CAPS IS FUN.', '   .'];\n  const invalidValues = [null, undefined, 'fooBar', '123abc'];\n\n  class MyClass {\n    @IsUppercase()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isUppercase(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isUppercase(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isUppercase';\n    const message = 'someProperty must be uppercase';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('Length', () => {\n  const constraint1 = 2;\n  const constraint2 = 3;\n  const validValues = ['abc', 'de'];\n  const invalidValues = [null, undefined, '', 'a', 'abcd'];\n\n  class MyClass {\n    @Length(constraint1, constraint2)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(length(value, constraint1, constraint2)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(length(value, constraint1, constraint2)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isLength';\n    const message = 'someProperty must be longer than or equal to ' + constraintToString(constraint1) + ' characters';\n    return checkReturnedError(new MyClass(), ['', 'a'], validationType, message);\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isLength';\n    const message = 'someProperty must be shorter than or equal to ' + constraintToString(constraint2) + ' characters';\n    return checkReturnedError(new MyClass(), ['aaaa', 'azzazza'], validationType, message);\n  });\n});\n\ndescribe('MinLength', () => {\n  const constraint1 = 10;\n  const validValues = ['helloworld', 'hello how are you'];\n  const invalidValues = [null, undefined, 'hellowar', 'howareyou'];\n\n  class MyClass {\n    @MinLength(constraint1)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(minLength(value, constraint1)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(minLength(value, constraint1)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'minLength';\n    const message = 'someProperty must be longer than or equal to ' + constraintToString(constraint1) + ' characters';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('MaxLength', () => {\n  const constraint1 = 10;\n  const validValues = ['hellowar', 'howareyou', 'helloworld'];\n  const invalidValues = [null, undefined, 'helloworld!', 'hello how are you'];\n\n  class MyClass {\n    @MaxLength(constraint1)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(maxLength(value, constraint1)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(maxLength(value, constraint1)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'maxLength';\n    const message = 'someProperty must be shorter than or equal to ' + constraintToString(constraint1) + ' characters';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('Matches pattern RegExp', () => {\n  const constraint = /abc/;\n  const validValues = ['abc', 'abcdef', '123abc'];\n  const invalidValues = [null, undefined, 'acb', 'Abc'];\n\n  class MyClass {\n    @Matches(constraint)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(matches(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(matches(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'matches';\n    const message = 'someProperty must match ' + constraintToString(constraint) + ' regular expression';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('Matches pattern string with modifier', () => {\n  const constraint = 'abc';\n  const modifier = 'i';\n  const validValues = ['abc', 'abcdef', '123abc', 'AbC'];\n  const invalidValues = [null, undefined, 'acb'];\n\n  class MyClass {\n    @Matches(constraint, modifier)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(matches(value, constraint, modifier)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(matches(value, constraint, modifier)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'matches';\n    const message = 'someProperty must match ' + constraintToString(constraint) + ' regular expression';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsMilitaryTime', () => {\n  class MyClass {\n    @IsMilitaryTime()\n    someProperty: string;\n  }\n\n  it('should not fail for a valid time in the format HH:MM', () => {\n    const validValues = ['10:22', '12:03', '16:32', '23:59', '00:00'];\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail for invalid time format', () => {\n    const invalidValues = ['23:61', '25:00', '08:08 pm', '04:00am'];\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should fail for invalid values', () => {\n    const invalidValues = [undefined, null, '23:00 and invalid counterpart'];\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n});\n\ndescribe('IsTimeZone', () => {\n  class MyClass {\n    @IsTimeZone()\n    someProperty: string;\n  }\n\n  it('should not fail for a valid IANA timezones', () => {\n    const validValues = ['Asia/Kathmandu', 'America/New_York', 'Europe/Paris', 'Europe/Berlin'];\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail for invalid timezone format', () => {\n    const invalidValues = ['Asia/Pokhara', 'America', 'New_York', '/Paris'];\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should fail for invalid values', () => {\n    const invalidValues = [undefined, null, 'Asia-Kathmandu'];\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n});\n\ndescribe('isPhoneNumber', () => {\n  describe('with region', () => {\n    const validValues = [\n      '+41 311111111',\n      '+41 31 633 60 01',\n      '+41 79 4 666 666',\n      '+41 75 416 20 30',\n      '+41 (0)311111111',\n      '+41 (0)31 633 60 01',\n      '+41 (0)79 4 666 666',\n      '+41 (0)75 416 20 30',\n    ];\n    const invalidValues = [undefined, null, 'asdf', '1'];\n\n    class MyClass {\n      @IsPhoneNumber('CH')\n      someProperty: string;\n    }\n\n    it('should not fail if validator.validate said that its valid', () => {\n      return checkValidValues(new MyClass(), validValues);\n    });\n\n    it('should fail if validator.validate said that its invalid', () => {\n      return checkInvalidValues(new MyClass(), invalidValues);\n    });\n  });\n\n  describe('no region', () => {\n    const validValues = [\n      '+41 311111111',\n      '+41 31 633 60 01',\n      '+41 79 4 666 666',\n      '+41 75 416 20 30',\n      '+41 (0)311111111',\n      '+41 (0)31 633 60 01',\n      '+41 (0)79 4 666 666',\n      '+41 (0)75 416 20 30',\n      '+49 9072 1111',\n    ];\n    const invalidValues = [\n      '0311111111',\n      '031 633 60 01',\n      '079 4 666 666',\n      '075 416 20 30',\n      undefined,\n      null,\n      'asdf',\n      '1',\n    ];\n\n    class MyClass {\n      @IsPhoneNumber(null)\n      someProperty: string;\n    }\n\n    it('should not fail if validator.validate said that its valid', () => {\n      return checkValidValues(new MyClass(), validValues);\n    });\n\n    it('should fail if validator.validate said that its invalid', () => {\n      return checkInvalidValues(new MyClass(), invalidValues);\n    });\n  });\n});\n\ndescribe('IsISO31661Alpha2', () => {\n  class MyClass {\n    @IsISO31661Alpha2()\n    someProperty: string;\n  }\n\n  it('should not fail for a valid ISO31661 Alpha2 code', () => {\n    const validValues = ['AD', 'AE', 'AF', 'AG'];\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail for invalid values', () => {\n    const invalidValues = [undefined, null, '', 'AFR'];\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n});\n\ndescribe('IsISO31661Alpha3', () => {\n  class MyClass {\n    @IsISO31661Alpha3()\n    someProperty: string;\n  }\n\n  it('should not fail for a valid ISO31661 Alpha3 code', () => {\n    const validValues = ['ABW', 'HND', 'KHM', 'RWA'];\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail for invalid values', () => {\n    const invalidValues = [undefined, null, '', 'FR', 'fR', 'GB', 'PT', 'CM', 'JP', 'PM', 'ZW'];\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n});\n\ndescribe('IsISO31661Numeric', () => {\n  class MyClass {\n    @IsISO31661Numeric()\n    someProperty: string;\n  }\n\n  it('should not fail for a valid ISO 3166-1 numeric country code', () => {\n    const validValues = ['056', '208', '276', '528', '804'];\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail for invalid values', () => {\n    const invalidValues = [undefined, null, '', 'NL', 'NLD', '42', '000', '999'];\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n});\n\ndescribe('isHash', () => {\n  function testHash(algorithm: ValidatorJS.HashAlgorithm, validValues: any[], invalidValues: any[]): void {\n    class MyClass {\n      @IsHash(algorithm)\n      someProperty: string;\n    }\n\n    it('should not fail if validator.validate said that its valid', () => {\n      return checkValidValues(new MyClass(), validValues);\n    });\n\n    it('should fail if validator.validate said that its invalid', () => {\n      return checkInvalidValues(new MyClass(), invalidValues);\n    });\n\n    it('should not fail if method in validator said that its valid', () => {\n      validValues.forEach(value => expect(isHash(value, algorithm)).toBeTruthy());\n    });\n\n    it('should fail if method in validator said that its invalid', () => {\n      invalidValues.forEach(value => expect(isHash(value, algorithm)).toBeFalsy());\n    });\n\n    it('should return error object with proper data', () => {\n      const validationType = 'isHash';\n      const message = `someProperty must be a hash of type ${algorithm}`;\n      return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n    });\n  }\n\n  for (const algorithm of ['md5', 'md4', 'ripemd128', 'tiger128']) {\n    const validValues = [\n      'd94f3f016ae679c3008de268209132f2',\n      '751adbc511ccbe8edf23d486fa4581cd',\n      '88dae00e614d8f24cfd5a8b3f8002e93',\n      '0bf1c35032a71a14c2f719e5a14c1e96',\n    ];\n    const invalidValues = [\n      undefined,\n      null,\n      'q94375dj93458w34',\n      '39485729348',\n      '%&FHKJFvk',\n      'KYT0bf1c35032a71a14c2f719e5a1',\n    ];\n\n    testHash(algorithm as ValidatorJS.HashAlgorithm, validValues, invalidValues);\n  }\n\n  for (const algorithm of ['crc32', 'crc32b']) {\n    const validValues = ['d94f3f01', '751adbc5', '88dae00e', '0bf1c350'];\n    const invalidValues = [\n      undefined,\n      null,\n      'KYT0bf1c35032a71a14c2f719e5a14c1',\n      'q94375dj93458w34',\n      'q943',\n      '39485729348',\n      '%&FHKJFvk',\n    ];\n\n    testHash(algorithm as ValidatorJS.HashAlgorithm, validValues, invalidValues);\n  }\n\n  for (const algorithm of ['sha1', 'tiger160', 'ripemd160']) {\n    const validValues = [\n      '3ca25ae354e192b26879f651a51d92aa8a34d8d3',\n      'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d',\n      'beb8c3f30da46be179b8df5f5ecb5e4b10508230',\n      'efd5d3b190e893ed317f38da2420d63b7ae0d5ed',\n    ];\n    const invalidValues = [\n      undefined,\n      null,\n      'KYT0bf1c35032a71a14c2f719e5a14c1',\n      'KYT0bf1c35032a71a14c2f719e5a14c1dsjkjkjkjkkjk',\n      'q94375dj93458w34',\n      '39485729348',\n      '%&FHKJFvk',\n    ];\n\n    testHash(algorithm as ValidatorJS.HashAlgorithm, validValues, invalidValues);\n  }\n\n  for (const algorithm of ['sha256']) {\n    const validValues = [\n      '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824',\n      '1d996e033d612d9af2b44b70061ee0e868bfd14c2dd90b129e1edeb7953e7985',\n      '80f70bfeaed5886e33536bcfa8c05c60afef5a0e48f699a7912d5e399cdcc441',\n      '579282cfb65ca1f109b78536effaf621b853c9f7079664a3fbe2b519f435898c',\n    ];\n    const invalidValues = [\n      undefined,\n      null,\n      'KYT0bf1c35032a71a14c2f719e5a14c1',\n      'KYT0bf1c35032a71a14c2f719e5a14c1dsjkjkjkjkkjk',\n      'q94375dj93458w34',\n      '39485729348',\n      '%&FHKJFvk',\n    ];\n\n    testHash(algorithm as ValidatorJS.HashAlgorithm, validValues, invalidValues);\n  }\n\n  for (const algorithm of ['sha384']) {\n    const validValues = [\n      '3fed1f814d28dc5d63e313f8a601ecc4836d1662a19365cbdcf6870f6b56388850b58043f7ebf2418abb8f39c3a42e31',\n      'b330f4e575db6e73500bd3b805db1a84b5a034e5d21f0041d91eec85af1dfcb13e40bb1c4d36a72487e048ac6af74b58',\n      'bf547c3fc5841a377eb1519c2890344dbab15c40ae4150b4b34443d2212e5b04aa9d58865bf03d8ae27840fef430b891',\n      'fc09a3d11368386530f985dacddd026ae1e44e0e297c805c3429d50744e6237eb4417c20ffca8807b071823af13a3f65',\n    ];\n    const invalidValues = [\n      undefined,\n      null,\n      'KYT0bf1c35032a71a14c2f719e5a14c1',\n      'KYT0bf1c35032a71a14c2f719e5a14c1dsjkjkjkjkkjk',\n      'q94375dj93458w34',\n      '39485729348',\n      '%&FHKJFvk',\n    ];\n\n    testHash(algorithm as ValidatorJS.HashAlgorithm, validValues, invalidValues);\n  }\n\n  for (const algorithm of ['sha512']) {\n    const validValues = [\n      '9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043',\n      '83c586381bf5ba94c8d9ba8b6b92beb0997d76c257708742a6c26d1b7cbb9269af92d527419d5b8475f2bb6686d2f92a6649b7f174c1d8306eb335e585ab5049',\n      '45bc5fa8cb45ee408c04b6269e9f1e1c17090c5ce26ffeeda2af097735b29953ce547e40ff3ad0d120e5361cc5f9cee35ea91ecd4077f3f589b4d439168f91b9',\n      '432ac3d29e4f18c7f604f7c3c96369a6c5c61fc09bf77880548239baffd61636d42ed374f41c261e424d20d98e320e812a6d52865be059745fdb2cb20acff0ab',\n    ];\n    const invalidValues = [\n      undefined,\n      null,\n      'KYT0bf1c35032a71a14c2f719e5a14c1',\n      'KYT0bf1c35032a71a14c2f719e5a14c1dsjkjkjkjkkjk',\n      'q94375dj93458w34',\n      '39485729348',\n      '%&FHKJFvk',\n    ];\n\n    testHash(algorithm as ValidatorJS.HashAlgorithm, validValues, invalidValues);\n  }\n\n  for (const algorithm of ['tiger192']) {\n    const validValues = [\n      '6281a1f098c5e7290927ed09150d43ff3990a0fe1a48267c',\n      '56268f7bc269cf1bc83d3ce42e07a85632394737918f4760',\n      '46fc0125a148788a3ac1d649566fc04eb84a746f1a6e4fa7',\n      '7731ea1621ae99ea3197b94583d034fdbaa4dce31a67404a',\n    ];\n    const invalidValues = [\n      undefined,\n      null,\n      'KYT0bf1c35032a71a14c2f719e5a14c1',\n      'KYT0bf1c35032a71a14c2f719e5a14c1dsjkjkjkjkkjk',\n      'q94375dj93458w34',\n      '39485729348',\n      '%&FHKJFvk',\n    ];\n\n    testHash(algorithm as ValidatorJS.HashAlgorithm, validValues, invalidValues);\n  }\n});\n\ndescribe('IsISSN', () => {\n  const validValues = ['0378-5955', '0000-0000', '2434-561X', '2434-561x', '01896016', '20905076'];\n  const invalidValues = [\n    null,\n    undefined,\n    '0378-5954',\n    '0000-0001',\n    '0378-123',\n    '037-1234',\n    '0',\n    '2434-561c',\n    '1684-5370',\n    '19960791',\n    '',\n  ];\n\n  class MyClass {\n    @IsISSN()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isISSN(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isISSN(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isISSN';\n    const message = 'someProperty must be a ISSN';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsISSN with options', () => {\n  // eslint-disable-next-line @typescript-eslint/camelcase\n  const options = { case_sensitive: true, require_hyphen: true };\n  const validValues = ['2434-561X', '0378-5955'];\n  const invalidValues = [null, undefined, '2434-561x', '2434561X', '2434561x', '03785955'];\n\n  class MyClass {\n    @IsISSN(options)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isISSN(value, options)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isISSN(value, options)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isISSN';\n    const message = 'someProperty must be a ISSN';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('ArrayContains', () => {\n  const constraint = ['superman'];\n  const validValues = [\n    ['world', 'hello', 'superman'],\n    ['world', 'superman', 'hello'],\n    ['superman', 'world', 'hello'],\n  ];\n  const invalidValues = [null, undefined, ['world', 'hello']];\n\n  class MyClass {\n    @ArrayContains(constraint)\n    someProperty: string[];\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(arrayContains(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(arrayContains(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'arrayContains';\n    const message = 'someProperty must contain ' + constraintToString(constraint) + ' values';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('ArrayNotContains', () => {\n  const constraint = ['superman'];\n  const validValues = [['world', 'hello']];\n  const invalidValues = [\n    null,\n    undefined,\n    ['world', 'hello', 'superman'],\n    ['world', 'superman', 'hello'],\n    ['superman', 'world', 'hello'],\n  ];\n\n  class MyClass {\n    @ArrayNotContains(constraint)\n    someProperty: string[];\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(arrayNotContains(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(arrayNotContains(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'arrayNotContains';\n    const message = 'someProperty should not contain ' + constraintToString(constraint) + ' values';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('ArrayNotEmpty', () => {\n  const validValues = [\n    [0],\n    [''],\n    [null],\n    [undefined],\n    [false],\n    ['world', 'hello', 'superman'],\n    ['world', 'superman', 'hello'],\n    ['superman', 'world', 'hello'],\n  ];\n  const invalidValues: any[] = [null, undefined, []];\n\n  class MyClass {\n    @ArrayNotEmpty()\n    someProperty: string[];\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(arrayNotEmpty(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(arrayNotEmpty(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'arrayNotEmpty';\n    const message = 'someProperty should not be empty';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('ArrayMinSize', () => {\n  const constraint = 2;\n  const validValues = [['world', 'hello']];\n  const invalidValues = [null, undefined, ['hi']];\n\n  class MyClass {\n    @ArrayMinSize(constraint)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(arrayMinSize(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(arrayMinSize(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'arrayMinSize';\n    const message = 'someProperty must contain at least ' + constraintToString(constraint) + ' elements';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('ArrayMaxSize', () => {\n  const constraint = 2;\n  const validValues = [['world', 'hello']];\n  const invalidValues = [null, undefined, ['hi', 'hello', 'javascript']];\n\n  class MyClass {\n    @ArrayMaxSize(constraint)\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(arrayMaxSize(value, constraint)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(arrayMaxSize(value, constraint)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'arrayMaxSize';\n    const message = 'someProperty must contain no more than ' + constraintToString(constraint) + ' elements';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('ArrayUnique', () => {\n  const validValues = [\n    ['world', 'hello', 'superman'],\n    ['world', 'superman', 'hello'],\n    ['superman', 'world', 'hello'],\n    ['1', '2', null, undefined],\n  ];\n  const invalidValues: any[] = [\n    null,\n    undefined,\n    ['world', 'hello', 'hello'],\n    ['world', 'hello', 'world'],\n    ['1', '1', '1'],\n  ];\n\n  class MyClass {\n    @ArrayUnique()\n    someProperty: string[];\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(arrayUnique(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(arrayUnique(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'arrayUnique';\n    const message = \"All someProperty's elements must be unique\";\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('ArrayUnique with identifier', () => {\n  const identifier = o => o.name;\n  const validValues = [\n    ['world', 'hello', 'superman'],\n    ['world', 'superman', 'hello'],\n    ['superman', 'world', 'hello'],\n    ['1', '2', null, undefined],\n  ].map(list => list.map(name => ({ name })));\n  const invalidValues: any[] = [\n    null,\n    undefined,\n    ['world', 'hello', 'hello'],\n    ['world', 'hello', 'world'],\n    ['1', '1', '1'],\n  ].map(list => list?.map(name => (name != null ? { name } : name)));\n\n  class MyClass {\n    @ArrayUnique(identifier)\n    someProperty: { name: string }[];\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(arrayUnique(value, identifier)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(arrayUnique(value, identifier)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'arrayUnique';\n    const message = \"All someProperty's elements must be unique\";\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('isInstance', () => {\n  class MySubClass {\n    // Empty\n  }\n\n  class WrongSubClass {\n    // Empty\n  }\n\n  class MyClass {\n    @IsInstance(MySubClass)\n    someProperty: MySubClass;\n  }\n\n  const validValues = [new MySubClass()];\n  const invalidValues = [null, undefined, 15, 'something', new WrongSubClass(), (): null => null];\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isInstance(value, MySubClass)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isInstance(value, MySubClass)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isInstance';\n    const message = 'someProperty must be an instance of MySubClass';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsStrongPassword', () => {\n  class MyClass {\n    @IsStrongPassword()\n    someProperty: string;\n  }\n\n  const validValues = ['Abcdef1!'];\n  const invalidValues = [null, undefined, 'Abcde1!', 'abcdef1!', 'ABCDEF1!', 'Abcdefg!', 'Abcdefg1'];\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isStrongPassword(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isStrongPassword(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isStrongPassword';\n    const message = 'someProperty is not strong enough';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsStrongPassword with options', () => {\n  const options: IsStrongPasswordOptions = {\n    minLength: 12,\n    minLowercase: 2,\n    minUppercase: 2,\n    minNumbers: 2,\n    minSymbols: 2,\n  };\n\n  class MyClass {\n    @IsStrongPassword(options)\n    someProperty: string;\n  }\n\n  const validValues = ['ABcdefgh12!#'];\n  const invalidValues = [\n    null,\n    undefined,\n    'ABcdefg12!#',\n    'Abcdefgh12!#',\n    'ABcDEFGH12!#',\n    'ABcdefghi1!#',\n    'ABcdefghi12!',\n  ];\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isStrongPassword(value, options)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isStrongPassword(value, options)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isStrongPassword';\n    const message = 'someProperty is not strong enough';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsBase58', () => {\n  const constraint = '';\n  const validValues = ['4Fcj4ooZqEQiyH68xykKJFnwZbePBCxgTjwQVtce1VyS'];\n  const invalidValues = [null, undefined, 'my*name-isKinggodHoon'];\n\n  class MyClass {\n    @IsBase58()\n    someProperty: string;\n  }\n\n  it('should not fail if validator.validate said that its valid', () => {\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail if validator.validate said that its invalid', () => {\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n\n  it('should not fail if method in validator said that its valid', () => {\n    validValues.forEach(value => expect(isBase58(value)).toBeTruthy());\n  });\n\n  it('should fail if method in validator said that its invalid', () => {\n    invalidValues.forEach(value => expect(isBase58(value)).toBeFalsy());\n  });\n\n  it('should return error object with proper data', () => {\n    const validationType = 'isBase58';\n    const message = 'someProperty must be base58 encoded';\n    return checkReturnedError(new MyClass(), invalidValues, validationType, message);\n  });\n});\n\ndescribe('IsISO4217', () => {\n  class MyClass {\n    @IsISO4217CurrencyCode()\n    someProperty: string;\n  }\n\n  it('should not fail for a valid ISO4217 code', () => {\n    const validValues = ['EUR', 'USD', 'BDT', 'LRD'];\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail for invalid values', () => {\n    const invalidValues = [undefined, null, '', 'USS'];\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n});\n\ndescribe('IsISO6391', () => {\n  class MyClass {\n    @IsISO6391()\n    someProperty: string;\n  }\n\n  it('should not fail for a valid ISO 639-1 language code', () => {\n    const validValues = ['de', 'en', 'eo', 'fy', 'nl'];\n    return checkValidValues(new MyClass(), validValues);\n  });\n\n  it('should fail for invalid values', () => {\n    const invalidValues = [undefined, null, '', 'FR', 'xx', 'tok'];\n    return checkInvalidValues(new MyClass(), invalidValues);\n  });\n});\n"
  },
  {
    "path": "test/functional/validation-options.spec.ts",
    "content": "import {\n  Contains,\n  Equals,\n  IsDefined,\n  Matches,\n  Max,\n  MinLength,\n  IsArray,\n  Validate,\n  ValidateNested,\n  ValidatorConstraint,\n  IsOptional,\n  Min,\n} from '../../src/decorator/decorators';\nimport { Validator } from '../../src/validation/Validator';\nimport {\n  registerDecorator,\n  ValidationArguments,\n  ValidationError,\n  ValidationOptions,\n  ValidatorConstraintInterface,\n  isValidationOptions,\n} from '../../src';\n\nconst validator = new Validator();\n\ndescribe('message', () => {\n  it('should contain a custom message', () => {\n    class MyClass {\n      @Contains('hello', {\n        message: 'String is not valid. You string must contain a hello word',\n      })\n      someProperty: string;\n    }\n\n    const model = new MyClass();\n    // TODO: Why is this commented out?\n    // model.someProperty = \"hell no world\";\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].constraints).toEqual({ contains: 'String is not valid. You string must contain a hello word' });\n    });\n  });\n\n  it('$value token should be replaced in a custom message', () => {\n    class MyClass {\n      @Contains('hello', {\n        message: '$value is not valid. You string must contain a hello word',\n      })\n      someProperty: string;\n    }\n\n    const model = new MyClass();\n    model.someProperty = 'hell no world';\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].constraints).toEqual({\n        contains: 'hell no world is not valid. You string must contain a hello word',\n      });\n    });\n  });\n\n  it('$value token should be replaced in a custom message with a string', () => {\n    class MyClass {\n      @MinLength(2, {\n        message: args => {\n          if (args.value.length < 2) {\n            return '$value is too short, minimum length is $constraint1 characters $property';\n          }\n        },\n      })\n      name: string;\n    }\n\n    const model = new MyClass();\n    model.name = '';\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].constraints).toEqual({ minLength: ' is too short, minimum length is 2 characters name' });\n    });\n  });\n\n  it('$value token should be replaced in a custom message with a number', () => {\n    class MyClass {\n      @Max(100, { message: 'Maximum value is $constraint1, but actual is $value' })\n      val: number = 50;\n    }\n\n    const model = new MyClass();\n    model.val = 101;\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].constraints).toEqual({\n        max: 'Maximum value is 100, but actual is 101',\n      });\n    });\n  });\n\n  it('$value token should be replaced in a custom message with a boolean', () => {\n    class MyClass {\n      @Equals(true, { message: 'Value must be $constraint1, but actual is $value' })\n      val: boolean = false;\n    }\n\n    const model = new MyClass();\n    model.val = false;\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].constraints).toEqual({\n        equals: 'Value must be true, but actual is false',\n      });\n    });\n  });\n\n  it('$constraint1 token should be replaced in a custom message', () => {\n    class MyClass {\n      @Contains('hello', {\n        message: 'String is not valid. You string must contain a $constraint1 word',\n      })\n      someProperty: string;\n    }\n\n    const model = new MyClass();\n    model.someProperty = 'hell no world';\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].constraints).toEqual({ contains: 'String is not valid. You string must contain a hello word' });\n    });\n  });\n\n  it('$target token should be replaced in a custom message', () => {\n    class MyClass {\n      @Contains('hello', {\n        message: '$target is not valid.',\n      })\n      someProperty: string;\n    }\n\n    const model = new MyClass();\n    model.someProperty = 'hell no world';\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].constraints).toEqual({ contains: 'MyClass is not valid.' });\n    });\n  });\n\n  it('$property token should be replaced in a custom message', () => {\n    class MyClass {\n      @Contains('hello', {\n        message: '$property is not valid.',\n      })\n      someProperty: string;\n    }\n\n    const model = new MyClass();\n    model.someProperty = 'hell no world';\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].constraints).toEqual({ contains: 'someProperty is not valid.' });\n    });\n  });\n\n  it('should replace all token', () => {\n    class MyClass {\n      @Contains('hello', {\n        message: '$target#$property is not valid: $value must contain a $constraint1 word',\n      })\n      someProperty: string;\n    }\n\n    const model = new MyClass();\n    model.someProperty = 'hell no world';\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].constraints).toEqual({\n        contains: 'MyClass#someProperty is not valid: hell no world must contain a hello word',\n      });\n    });\n  });\n});\n\ndescribe('each', () => {\n  describe('Array', () => {\n    it('should apply validation to each item in the array', () => {\n      class MyClass {\n        @Contains('hello', {\n          each: true,\n        })\n        someProperty: string[];\n      }\n\n      const model = new MyClass();\n      model.someProperty = ['hell no world', 'hello', 'helo world', 'hello world', 'hello dear friend'];\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(1);\n        expect(errors[0].constraints).toEqual({ contains: 'each value in someProperty must contain a hello string' });\n        expect(errors[0].value).toEqual(model.someProperty);\n        expect(errors[0].target).toEqual(model);\n        expect(errors[0].property).toEqual('someProperty');\n      });\n    });\n\n    it('should apply validation via custom constraint class to array items (but not array itself)', () => {\n      @ValidatorConstraint({ name: 'customIsNotArrayConstraint', async: false })\n      class CustomIsNotArrayConstraint implements ValidatorConstraintInterface {\n        validate(value: any): boolean {\n          return !Array.isArray(value);\n        }\n      }\n\n      class MyClass {\n        @Validate(CustomIsNotArrayConstraint, {\n          each: true,\n        })\n        someArrayOfNonArrayItems: string[];\n      }\n\n      const model = new MyClass();\n      model.someArrayOfNonArrayItems = ['not array', 'also not array', 'not array at all'];\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(0);\n      });\n    });\n\n    it('should apply validation via custom constraint class with synchronous logic to each item in the array', () => {\n      @ValidatorConstraint({ name: 'customContainsHelloConstraint', async: false })\n      class CustomContainsHelloConstraint implements ValidatorConstraintInterface {\n        validate(value: any): boolean {\n          return !Array.isArray(value) && String(value).includes('hello');\n        }\n      }\n\n      class MyClass {\n        @Validate(CustomContainsHelloConstraint, {\n          each: true,\n        })\n        someProperty: string[];\n      }\n\n      const model = new MyClass();\n      model.someProperty = ['hell no world', 'hello', 'helo world', 'hello world', 'hello dear friend'];\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(1);\n        expect(errors[0].constraints).toEqual({ customContainsHelloConstraint: '' });\n        expect(errors[0].value).toEqual(model.someProperty);\n        expect(errors[0].target).toEqual(model);\n        expect(errors[0].property).toEqual('someProperty');\n      });\n    });\n\n    it('should apply validation via custom constraint class with async logic to each item in the array', () => {\n      @ValidatorConstraint({ name: 'customAsyncContainsHelloConstraint', async: true })\n      class CustomAsyncContainsHelloConstraint implements ValidatorConstraintInterface {\n        validate(value: any): Promise<boolean> {\n          const isValid = !Array.isArray(value) && String(value).includes('hello');\n          return Promise.resolve(isValid);\n        }\n      }\n\n      class MyClass {\n        @Validate(CustomAsyncContainsHelloConstraint, {\n          each: true,\n        })\n        someProperty: string[];\n      }\n\n      const model = new MyClass();\n      model.someProperty = ['hell no world', 'hello', 'helo world', 'hello world', 'hello dear friend'];\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(1);\n        expect(errors[0].constraints).toEqual({ customAsyncContainsHelloConstraint: '' });\n        expect(errors[0].value).toEqual(model.someProperty);\n        expect(errors[0].target).toEqual(model);\n        expect(errors[0].property).toEqual('someProperty');\n      });\n    });\n\n    it('should apply validation via custom constraint class with mixed (synchronous + async) logic to each item in the array', () => {\n      @ValidatorConstraint({ name: 'customMixedContainsHelloConstraint', async: true })\n      class CustomMixedContainsHelloConstraint implements ValidatorConstraintInterface {\n        validate(value: any): boolean | Promise<boolean> {\n          const isValid = !Array.isArray(value) && String(value).includes('hello');\n          return isValid ? isValid : Promise.resolve(isValid);\n        }\n      }\n\n      class MyClass {\n        @Validate(CustomMixedContainsHelloConstraint, {\n          each: true,\n        })\n        someProperty: string[];\n      }\n\n      const model = new MyClass();\n      model.someProperty = ['hell no world', 'hello', 'helo world', 'hello world', 'hello dear friend'];\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(1);\n        expect(errors[0].constraints).toEqual({ customMixedContainsHelloConstraint: '' });\n        expect(errors[0].value).toEqual(model.someProperty);\n        expect(errors[0].target).toEqual(model);\n        expect(errors[0].property).toEqual('someProperty');\n      });\n    });\n  });\n\n  describe('Set', () => {\n    it('should apply validation to each item in the Set', () => {\n      class MyClass {\n        @Contains('hello', {\n          each: true,\n        })\n        someProperty: Set<string>;\n      }\n\n      const model = new MyClass();\n      model.someProperty = new Set<string>([\n        'hell no world',\n        'hello',\n        'helo world',\n        'hello world',\n        'hello dear friend',\n      ]);\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(1);\n        expect(errors[0].constraints).toEqual({ contains: 'each value in someProperty must contain a hello string' });\n        expect(errors[0].value).toEqual(model.someProperty);\n        expect(errors[0].target).toEqual(model);\n        expect(errors[0].property).toEqual('someProperty');\n      });\n    });\n\n    it('should apply validation via custom constraint class to Set items (but not Set itself)', () => {\n      @ValidatorConstraint({ name: 'customIsNotSetConstraint', async: false })\n      class CustomIsNotSetConstraint implements ValidatorConstraintInterface {\n        validate(value: any): boolean {\n          return !(value instanceof Set);\n        }\n      }\n\n      class MyClass {\n        @Validate(CustomIsNotSetConstraint, {\n          each: true,\n        })\n        someSetOfNonSetItems: Set<string>;\n      }\n\n      const model = new MyClass();\n      model.someSetOfNonSetItems = new Set<string>(['not array', 'also not array', 'not array at all']);\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(0);\n      });\n    });\n\n    it('should apply validation via custom constraint class with synchronous logic to each item in the Set', () => {\n      @ValidatorConstraint({ name: 'customContainsHelloConstraint', async: false })\n      class CustomContainsHelloConstraint implements ValidatorConstraintInterface {\n        validate(value: any): boolean {\n          return !(value instanceof Set) && String(value).includes('hello');\n        }\n      }\n\n      class MyClass {\n        @Validate(CustomContainsHelloConstraint, {\n          each: true,\n        })\n        someProperty: Set<string>;\n      }\n\n      const model = new MyClass();\n      model.someProperty = new Set<string>([\n        'hell no world',\n        'hello',\n        'helo world',\n        'hello world',\n        'hello dear friend',\n      ]);\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(1);\n        expect(errors[0].constraints).toEqual({ customContainsHelloConstraint: '' });\n        expect(errors[0].value).toEqual(model.someProperty);\n        expect(errors[0].target).toEqual(model);\n        expect(errors[0].property).toEqual('someProperty');\n      });\n    });\n\n    it('should apply validation via custom constraint class with async logic to each item in the Set', () => {\n      @ValidatorConstraint({ name: 'customAsyncContainsHelloConstraint', async: true })\n      class CustomAsyncContainsHelloConstraint implements ValidatorConstraintInterface {\n        validate(value: any): Promise<boolean> {\n          const isValid = !(value instanceof Set) && String(value).includes('hello');\n          return Promise.resolve(isValid);\n        }\n      }\n\n      class MyClass {\n        @Validate(CustomAsyncContainsHelloConstraint, {\n          each: true,\n        })\n        someProperty: Set<string>;\n      }\n\n      const model = new MyClass();\n      model.someProperty = new Set<string>([\n        'hell no world',\n        'hello',\n        'helo world',\n        'hello world',\n        'hello dear friend',\n      ]);\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(1);\n        expect(errors[0].constraints).toEqual({ customAsyncContainsHelloConstraint: '' });\n        expect(errors[0].value).toEqual(model.someProperty);\n        expect(errors[0].target).toEqual(model);\n        expect(errors[0].property).toEqual('someProperty');\n      });\n    });\n\n    it('should apply validation via custom constraint class with mixed (synchronous + async) logic to each item in the Set', () => {\n      @ValidatorConstraint({ name: 'customMixedContainsHelloConstraint', async: true })\n      class CustomMixedContainsHelloConstraint implements ValidatorConstraintInterface {\n        validate(value: any): boolean | Promise<boolean> {\n          const isValid = !(value instanceof Set) && String(value).includes('hello');\n          return isValid ? isValid : Promise.resolve(isValid);\n        }\n      }\n\n      class MyClass {\n        @Validate(CustomMixedContainsHelloConstraint, {\n          each: true,\n        })\n        someProperty: Set<string>;\n      }\n\n      const model = new MyClass();\n      model.someProperty = new Set<string>([\n        'hell no world',\n        'hello',\n        'helo world',\n        'hello world',\n        'hello dear friend',\n      ]);\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(1);\n        expect(errors[0].constraints).toEqual({ customMixedContainsHelloConstraint: '' });\n        expect(errors[0].value).toEqual(model.someProperty);\n        expect(errors[0].target).toEqual(model);\n        expect(errors[0].property).toEqual('someProperty');\n      });\n    });\n  });\n\n  describe('Map', () => {\n    it('should apply validation to each item in the Map', () => {\n      class MyClass {\n        @Contains('hello', {\n          each: true,\n        })\n        someProperty: Map<string, string>;\n      }\n\n      const model = new MyClass();\n      model.someProperty = new Map<string, string>([\n        ['key1', 'hell no world'],\n        ['key2', 'hello'],\n        ['key3', 'helo world'],\n        ['key4', 'hello world'],\n        ['key5', 'hello dear friend'],\n      ]);\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(1);\n        expect(errors[0].constraints).toEqual({ contains: 'each value in someProperty must contain a hello string' });\n        expect(errors[0].value).toEqual(model.someProperty);\n        expect(errors[0].target).toEqual(model);\n        expect(errors[0].property).toEqual('someProperty');\n      });\n    });\n\n    it('should apply validation via custom constraint class to Map items (but not Map itself)', () => {\n      @ValidatorConstraint({ name: 'customIsNotMapConstraint', async: false })\n      class CustomIsNotMapConstraint implements ValidatorConstraintInterface {\n        validate(value: any): boolean {\n          return !(value instanceof Map);\n        }\n      }\n\n      class MyClass {\n        @Validate(CustomIsNotMapConstraint, {\n          each: true,\n        })\n        someArrayOfNonArrayItems: Map<string, string>;\n      }\n\n      const model = new MyClass();\n      model.someArrayOfNonArrayItems = new Map<string, string>([\n        ['key1', 'not array'],\n        ['key2', 'also not array'],\n        ['key3', 'not array at all'],\n      ]);\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(0);\n      });\n    });\n\n    it('should apply validation via custom constraint class with synchronous logic to each item in the Map', () => {\n      @ValidatorConstraint({ name: 'customContainsHelloConstraint', async: false })\n      class CustomContainsHelloConstraint implements ValidatorConstraintInterface {\n        validate(value: any): boolean {\n          return !(value instanceof Map) && String(value).includes('hello');\n        }\n      }\n\n      class MyClass {\n        @Validate(CustomContainsHelloConstraint, {\n          each: true,\n        })\n        someProperty: Map<string, string>;\n      }\n\n      const model = new MyClass();\n      model.someProperty = new Map<string, string>([\n        ['key1', 'hell no world'],\n        ['key2', 'hello'],\n        ['key3', 'helo world'],\n        ['key4', 'hello world'],\n        ['key5', 'hello dear friend'],\n      ]);\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(1);\n        expect(errors[0].constraints).toEqual({ customContainsHelloConstraint: '' });\n        expect(errors[0].value).toEqual(model.someProperty);\n        expect(errors[0].target).toEqual(model);\n        expect(errors[0].property).toEqual('someProperty');\n      });\n    });\n\n    it('should apply validation via custom constraint class with async logic to each item in the Map', () => {\n      @ValidatorConstraint({ name: 'customAsyncContainsHelloConstraint', async: true })\n      class CustomAsyncContainsHelloConstraint implements ValidatorConstraintInterface {\n        validate(value: any): Promise<boolean> {\n          const isValid = !(value instanceof Map) && String(value).includes('hello');\n          return Promise.resolve(isValid);\n        }\n      }\n\n      class MyClass {\n        @Validate(CustomAsyncContainsHelloConstraint, {\n          each: true,\n        })\n        someProperty: Map<string, string>;\n      }\n\n      const model = new MyClass();\n      model.someProperty = new Map<string, string>([\n        ['key1', 'hell no world'],\n        ['key2', 'hello'],\n        ['key3', 'helo world'],\n        ['key4', 'hello world'],\n        ['key5', 'hello dear friend'],\n      ]);\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(1);\n        expect(errors[0].constraints).toEqual({ customAsyncContainsHelloConstraint: '' });\n        expect(errors[0].value).toEqual(model.someProperty);\n        expect(errors[0].target).toEqual(model);\n        expect(errors[0].property).toEqual('someProperty');\n      });\n    });\n\n    it('should apply validation via custom constraint class with mixed (synchronous + async) logic to each item in the Map', () => {\n      @ValidatorConstraint({ name: 'customMixedContainsHelloConstraint', async: true })\n      class CustomMixedContainsHelloConstraint implements ValidatorConstraintInterface {\n        validate(value: any): boolean | Promise<boolean> {\n          const isValid = !(value instanceof Map) && String(value).includes('hello');\n          return isValid ? isValid : Promise.resolve(isValid);\n        }\n      }\n\n      class MyClass {\n        @Validate(CustomMixedContainsHelloConstraint, {\n          each: true,\n        })\n        someProperty: Map<string, string>;\n      }\n\n      const model = new MyClass();\n      model.someProperty = new Map<string, string>([\n        ['key1', 'hell no world'],\n        ['key2', 'hello'],\n        ['key3', 'helo world'],\n        ['key4', 'hello world'],\n        ['key5', 'hello dear friend'],\n      ]);\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(1);\n        expect(errors[0].constraints).toEqual({ customMixedContainsHelloConstraint: '' });\n        expect(errors[0].value).toEqual(model.someProperty);\n        expect(errors[0].target).toEqual(model);\n        expect(errors[0].property).toEqual('someProperty');\n      });\n    });\n  });\n});\n\ndescribe('groups', () => {\n  function expectTitleContains(error: ValidationError): void {\n    expect(error.constraints).toEqual({ contains: 'title must contain a hello string' });\n  }\n\n  function expectTextContains(error: ValidationError): void {\n    expect(error.constraints).toEqual({ contains: 'text must contain a bye string' });\n  }\n\n  class MyClass {\n    @Contains('hello', {\n      groups: ['title-validation'],\n    })\n    title: string;\n\n    @Contains('bye', {\n      groups: ['text-validation'],\n    })\n    text: string;\n  }\n\n  const validTitle = new MyClass();\n  validTitle.title = 'hello world';\n  validTitle.text = 'hello world';\n\n  const validText = new MyClass();\n  validText.title = 'bye world';\n  validText.text = 'bye world';\n\n  const validBoth = new MyClass();\n  validBoth.title = 'hello world';\n  validBoth.text = 'bye world';\n\n  const validNone = new MyClass();\n  validNone.title = 'bye world';\n  validNone.text = 'hello world';\n\n  describe('should validate only properties of the given group: title-validation', () => {\n    it('with valid title', () => {\n      return validator.validate(validTitle, { groups: ['title-validation'] }).then(errors => {\n        expect(errors.length).toEqual(0);\n      });\n    });\n\n    it('with valid text', () => {\n      return validator.validate(validText, { groups: ['title-validation'] }).then(errors => {\n        expect(errors.length).toEqual(1);\n        expectTitleContains(errors[0]);\n      });\n    });\n\n    it('with both valid', () => {\n      return validator.validate(validBoth, { groups: ['title-validation'] }).then(errors => {\n        expect(errors.length).toEqual(0);\n      });\n    });\n\n    it('with none valid', () => {\n      return validator.validate(validNone, { groups: ['title-validation'] }).then(errors => {\n        expect(errors.length).toEqual(1);\n        expectTitleContains(errors[0]);\n      });\n    });\n  });\n\n  describe('should validate only properties of the given group: text-validation', () => {\n    it('with valid title', () => {\n      return validator.validate(validTitle, { groups: ['text-validation'] }).then(errors => {\n        expect(errors.length).toEqual(1);\n        expectTextContains(errors[0]);\n      });\n    });\n\n    it('with valid text', () => {\n      return validator.validate(validText, { groups: ['text-validation'] }).then(errors => {\n        expect(errors.length).toEqual(0);\n      });\n    });\n\n    it('with both valid', () => {\n      return validator.validate(validBoth, { groups: ['text-validation'] }).then(errors => {\n        expect(errors.length).toEqual(0);\n      });\n    });\n\n    it('with none valid', () => {\n      return validator.validate(validNone, { groups: ['text-validation'] }).then(errors => {\n        expect(errors.length).toEqual(1);\n        expectTextContains(errors[0]);\n      });\n    });\n  });\n\n  describe('should validate only properties of the given groups: both groups', () => {\n    it('with valid title', () => {\n      return validator.validate(validTitle, { groups: ['title-validation', 'text-validation'] }).then(errors => {\n        expect(errors.length).toEqual(1);\n        expectTextContains(errors[0]);\n      });\n    });\n\n    it('with valid text', () => {\n      return validator.validate(validText, { groups: ['title-validation', 'text-validation'] }).then(errors => {\n        expect(errors.length).toEqual(1);\n        expectTitleContains(errors[0]);\n      });\n    });\n\n    it('with both valid', () => {\n      return validator.validate(validBoth, { groups: ['title-validation', 'text-validation'] }).then(errors => {\n        expect(errors.length).toEqual(0);\n      });\n    });\n\n    it('with none valid', () => {\n      return validator.validate(validNone, { groups: ['title-validation', 'text-validation'] }).then(errors => {\n        expect(errors.length).toEqual(2);\n        expectTitleContains(errors[0]);\n        expectTextContains(errors[1]);\n      });\n    });\n  });\n\n  describe('should validate all if no group is given', () => {\n    it('with valid title', () => {\n      // todo: all or without? what is better expected behaviour?\n      return validator.validate(validTitle).then(errors => {\n        expect(errors.length).toEqual(1);\n        expectTextContains(errors[0]);\n      });\n    });\n\n    it('with valid text', () => {\n      // todo: all or without? what is better expected behaviour?\n      return validator.validate(validText).then(errors => {\n        expect(errors.length).toEqual(1);\n        expectTitleContains(errors[0]);\n      });\n    });\n\n    it('with both valid', () => {\n      // todo: all or without? what is better expected behaviour?\n      return validator.validate(validBoth).then(errors => {\n        expect(errors.length).toEqual(0);\n      });\n    });\n\n    it('with none valid', () => {\n      // todo: all or without? what is better expected behaviour?\n      return validator.validate(validNone).then(errors => {\n        expect(errors.length).toEqual(2);\n        expectTitleContains(errors[0]);\n        expectTextContains(errors[1]);\n      });\n    });\n  });\n\n  describe('should validate all groups if empty group array is given', () => {\n    it('with valid title', () => {\n      return validator.validate(validTitle, { groups: [] }).then(errors => {\n        expect(errors.length).toEqual(1);\n        expectTextContains(errors[0]);\n      });\n    });\n\n    it('with valid text', () => {\n      return validator.validate(validText, { groups: [] }).then(errors => {\n        expect(errors.length).toEqual(1);\n        expectTitleContains(errors[0]);\n      });\n    });\n\n    it('with both valid', () => {\n      return validator.validate(validBoth, { groups: [] }).then(errors => {\n        expect(errors.length).toEqual(0);\n      });\n    });\n\n    it('with none valid', () => {\n      return validator.validate(validNone, { groups: [] }).then(errors => {\n        expect(errors.length).toEqual(2);\n        expectTitleContains(errors[0]);\n        expectTextContains(errors[1]);\n      });\n    });\n  });\n\n  describe('multiple groups per property', () => {\n    class MyClass {\n      @Contains('hello', { groups: ['contains'] })\n      @Matches(/.*stranger.*/, { groups: ['matches'] })\n      title: string;\n    }\n\n    function expectTitleMatches(error: ValidationError): void {\n      expect(error.constraints).toEqual({ matches: 'title must match /.*stranger.*/ regular expression' });\n    }\n\n    const validContains = new MyClass();\n    validContains.title = 'hello';\n\n    const validMatches = new MyClass();\n    validMatches.title = 'stranger';\n\n    const validBoth = new MyClass();\n    validBoth.title = 'hello stranger';\n\n    const validNone = new MyClass();\n    validNone.title = 'howdy rowdy';\n\n    describe('group: contains', () => {\n      it('with valid contains', () => {\n        return validator.validate(validContains, { groups: ['contains'] }).then(errors => {\n          expect(errors.length).toEqual(0);\n        });\n      });\n\n      it('with valid matches', () => {\n        return validator.validate(validMatches, { groups: ['contains'] }).then(errors => {\n          expect(errors.length).toEqual(1);\n          expectTitleContains(errors[0]);\n        });\n      });\n\n      it('with valid both', () => {\n        return validator.validate(validBoth, { groups: ['contains'] }).then(errors => {\n          expect(errors.length).toEqual(0);\n        });\n      });\n\n      it('with valid none', () => {\n        return validator.validate(validNone, { groups: ['contains'] }).then(errors => {\n          expect(errors.length).toEqual(1);\n          expectTitleContains(errors[0]);\n        });\n      });\n    });\n\n    describe('group: matches', () => {\n      it('with valid contains', () => {\n        return validator.validate(validContains, { groups: ['matches'] }).then(errors => {\n          expect(errors.length).toEqual(1);\n          expectTitleMatches(errors[0]);\n        });\n      });\n\n      it('with valid matches', () => {\n        return validator.validate(validMatches, { groups: ['matches'] }).then(errors => {\n          expect(errors.length).toEqual(0);\n        });\n      });\n\n      it('with valid both', () => {\n        return validator.validate(validBoth, { groups: ['matches'] }).then(errors => {\n          expect(errors.length).toEqual(0);\n        });\n      });\n\n      it('with valid none', () => {\n        return validator.validate(validNone, { groups: ['matches'] }).then(errors => {\n          expect(errors.length).toEqual(1);\n          expectTitleMatches(errors[0]);\n        });\n      });\n    });\n\n    describe('groups: contains & matches', () => {\n      it('with valid contains', () => {\n        return validator.validate(validContains, { groups: ['contains', 'matches'] }).then(errors => {\n          expect(errors.length).toEqual(1);\n          expectTitleMatches(errors[0]);\n        });\n      });\n\n      it('with valid matches', () => {\n        return validator.validate(validMatches, { groups: ['contains', 'matches'] }).then(errors => {\n          expect(errors.length).toEqual(1);\n          expectTitleContains(errors[0]);\n        });\n      });\n\n      it('with valid both', () => {\n        return validator.validate(validBoth, { groups: ['contains', 'matches'] }).then(errors => {\n          expect(errors.length).toEqual(0);\n        });\n      });\n\n      it('with valid none', () => {\n        return validator.validate(validNone, { groups: ['contains', 'matches'] }).then(errors => {\n          expect(errors.length).toEqual(1);\n          expect(errors[0].constraints).toEqual({\n            contains: 'title must contain a hello string',\n            matches: 'title must match /.*stranger.*/ regular expression',\n          });\n        });\n      });\n    });\n  });\n\n  describe('ValidationOptions.always', function () {\n    class MyClass {\n      @Contains('noOptions')\n      noOptions: string;\n\n      @Contains('groupA', {\n        groups: ['A'],\n      })\n      groupA: string;\n\n      @Contains('alwaysFalse', {\n        always: false,\n      })\n      alwaysFalse: string;\n\n      @Contains('alwaysTrue', {\n        always: true,\n      })\n      alwaysTrue: string;\n    }\n\n    const model1 = new MyClass();\n    model1.noOptions = 'XXX';\n    model1.groupA = 'groupA';\n    model1.alwaysFalse = 'alwaysFalse';\n    model1.alwaysTrue = 'alwaysTrue';\n\n    const model2 = new MyClass();\n    model2.noOptions = 'noOptions';\n    model2.groupA = 'XXX';\n    model2.alwaysFalse = 'alwaysFalse';\n    model2.alwaysTrue = 'alwaysTrue';\n\n    const model3 = new MyClass();\n    model3.noOptions = 'noOptions';\n    model3.groupA = 'groupA';\n    model3.alwaysFalse = 'XXX';\n    model3.alwaysTrue = 'alwaysTrue';\n\n    const model4 = new MyClass();\n    model4.noOptions = 'noOptions';\n    model4.groupA = 'groupA';\n    model4.alwaysFalse = 'alwaysFalse';\n    model4.alwaysTrue = 'XXX';\n\n    it('should validate decorator without options', function () {\n      return validator.validate(model1, { always: true, groups: ['A'] }).then(errors => {\n        expect(errors).toHaveLength(1);\n      });\n    });\n\n    it('should not validate decorator with groups if validating without matching groups', function () {\n      return validator.validate(model2, { always: true, groups: ['B'] }).then(errors => {\n        expect(errors).toHaveLength(0);\n      });\n    });\n\n    it('should not validate decorator with always set to false', function () {\n      return validator.validate(model3, { always: true, groups: ['A'] }).then(errors => {\n        expect(errors).toHaveLength(0);\n      });\n    });\n\n    it('should validate decorator with always set to true', function () {\n      return validator.validate(model4, { always: true, groups: ['A'] }).then(errors => {\n        expect(errors).toHaveLength(1);\n      });\n    });\n  });\n\n  describe('strictGroups', function () {\n    class MyPayload {\n      /**\n       * Since forbidUnknownValues defaults to true, we must add a property to\n       * register the class in the metadata storage. Otherwise the unknown value check\n       * would take priority (first check) and exit without running the grouping logic.\n       *\n       * To solve this we register this property with always: true, so at least a single\n       * metadata is returned for each validation preventing the unknown value was passed error.\n       */\n      @IsOptional({ always: true })\n      propertyToRegisterClass: string;\n\n      @Contains('hello', { groups: ['A'] })\n      title: string;\n    }\n\n    const instance = new MyPayload();\n\n    it('should ignore decorators with groups if validating without groups', function () {\n      return validator.validate(instance, { strictGroups: true }).then(errors => {\n        expect(errors).toHaveLength(0);\n      });\n    });\n\n    it('should ignore decorators with groups if validating with empty groups array', function () {\n      return validator.validate(instance, { strictGroups: true, groups: [] }).then(errors => {\n        expect(errors).toHaveLength(0);\n      });\n    });\n\n    it('should include decorators with groups if validating with matching groups', function () {\n      return validator.validate(instance, { strictGroups: true, groups: ['A'] }).then(errors => {\n        expect(errors).toHaveLength(1);\n        expectTitleContains(errors[0]);\n      });\n    });\n\n    it('should not include decorators with groups if validating with different groups', function () {\n      return validator.validate(instance, { strictGroups: true, groups: ['B'] }).then(errors => {\n        expect(errors).toHaveLength(0);\n      });\n    });\n  });\n\n  describe('always', () => {\n    class MyClass {\n      @Contains('hello', {\n        groups: ['sometimes'],\n      })\n      title: string;\n\n      @Contains('bye', {\n        groups: ['always'],\n        always: true,\n      })\n      text: string;\n    }\n\n    const model = new MyClass();\n\n    it('should always validate a marked field even if another group is specified', () => {\n      return validator.validate(model, { groups: ['sometimes'] }).then(errors => {\n        expect(errors.length).toEqual(2);\n        expectTitleContains(errors[0]);\n        expectTextContains(errors[1]);\n      });\n    });\n\n    it('should always validate a marked field if its group is specified also (doubly enabled)', () => {\n      return validator.validate(model, { groups: ['always'] }).then(errors => {\n        expect(errors.length).toEqual(1);\n        expectTextContains(errors[0]);\n      });\n    });\n\n    it('should always validate *all* fields if group is not specified', () => {\n      return validator.validate(model, { groups: undefined }).then(errors => {\n        expect(errors.length).toEqual(2);\n        expectTitleContains(errors[0]);\n        expectTextContains(errors[1]);\n      });\n    });\n\n    it('should always validate *all* fields if groups array is empty', () => {\n      return validator.validate(model, { groups: [] }).then(errors => {\n        expect(errors.length).toEqual(2);\n        expectTitleContains(errors[0]);\n        expectTextContains(errors[1]);\n      });\n    });\n  });\n\n  describe('groups - nested', () => {\n    class Nested {\n      @Contains('hello', {\n        groups: ['always'],\n        always: true,\n      })\n      text: string;\n    }\n\n    class Root {\n      @ValidateNested({ groups: ['always'], always: true })\n      always = new Nested();\n\n      @ValidateNested({ groups: ['sometimes'] })\n      sometimes = new Nested();\n\n      @ValidateNested({ groups: ['other'] })\n      other = new Nested();\n    }\n\n    const model = new Root();\n\n    function expectChildConstraint(error: ValidationError, childName: string): void {\n      expect(error.property).toEqual(childName);\n      expect(error.children.length).toEqual(1);\n      expect(error.children[0].property).toEqual('text');\n      expect(error.children[0].constraints).toEqual({ contains: 'text must contain a hello string' });\n    }\n\n    it('should validate all children if no group is given', () => {\n      return validator.validate(model, { groups: undefined }).then(errors => {\n        expect(errors.length).toEqual(3);\n        expectChildConstraint(errors[0], 'always');\n        expectChildConstraint(errors[1], 'sometimes');\n        expectChildConstraint(errors[2], 'other');\n      });\n    });\n\n    it('should validate only the given group + always', () => {\n      return validator.validate(model, { groups: ['sometimes'] }).then(errors => {\n        expect(errors.length).toEqual(2);\n        expectChildConstraint(errors[0], 'always');\n        expectChildConstraint(errors[1], 'sometimes');\n      });\n    });\n\n    it('should validate only the given group + always', () => {\n      return validator.validate(model, { groups: ['always'] }).then(errors => {\n        expect(errors.length).toEqual(1);\n        expectChildConstraint(errors[0], 'always');\n      });\n    });\n  });\n});\n\ndescribe('context', () => {\n  it('should map context', () => {\n    function IsLongerThan(property: string, validationOptions?: ValidationOptions) {\n      return function (object: object, propertyName: string): void {\n        registerDecorator({\n          target: object.constructor,\n          propertyName: propertyName,\n          options: validationOptions,\n          constraints: [property],\n          name: 'isLongerThan',\n          validator: {\n            validate(value: any, args: ValidationArguments): boolean {\n              const [relatedPropertyName] = args.constraints;\n              const relatedValue = (args.object as any)[relatedPropertyName];\n              if (relatedValue === undefined || relatedValue === null) return true;\n\n              return (\n                typeof value === 'string' && typeof relatedValue === 'string' && value.length > relatedValue.length\n              );\n            },\n          },\n        });\n      };\n    }\n\n    class MyClass {\n      @Contains('hello', {\n        message: 'String is not valid. You string must contain a hello word',\n        context: {\n          hi: 'there',\n        },\n      })\n      someProperty: string;\n\n      @Contains('bye', {\n        message: 'String is not valid. You string must contain a bye word',\n        context: {\n          bye: 'now',\n        },\n      })\n      someOtherProperty: string;\n\n      @IsDefined({\n        context: {\n          foo: 'bar',\n        },\n      })\n      requiredProperty: string;\n\n      @IsLongerThan('lastName', {\n        context: { baz: 'qux' },\n        message: '$property must be longer then $constraint1. Given value: $value',\n      })\n      firstName: string;\n\n      lastName: string;\n    }\n\n    const model = new MyClass();\n    model.firstName = 'Short';\n    model.lastName = 'LongerThanFirstName';\n\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(4);\n      expect(errors[0].contexts['contains']).toEqual({ hi: 'there' });\n      expect(errors[1].contexts['contains']).toEqual({ bye: 'now' });\n      expect(errors[2].contexts['isDefined']).toEqual({ foo: 'bar' });\n      expect(errors[3].contexts['isLongerThan']).toEqual({ baz: 'qux' });\n    });\n  });\n\n  it('should map multiple context on a single property for different constraints', () => {\n    class MyClass {\n      @Contains('hello', {\n        message: 'String is not valid. You string must contain a hello word',\n        context: {\n          hi: 'there',\n        },\n      })\n      @MinLength(20, {\n        context: {\n          whats: 'up',\n        },\n      })\n      someProperty: string;\n    }\n\n    const model = new MyClass();\n    model.someProperty = 'bippity';\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].contexts['contains']).toEqual({ hi: 'there' });\n      expect(errors[0].contexts['minLength']).toEqual({ whats: 'up' });\n    });\n  });\n\n  it('should not map no context', () => {\n    class MyClass {\n      @Contains('hello', {\n        message: 'String is not valid. You string must contain a hello word',\n      })\n      someProperty: string;\n\n      @Contains('bye', {\n        message: 'String is not valid. You string must contain a bye word',\n        context: {\n          bye: 'now',\n        },\n      })\n      someOtherProperty: string;\n    }\n\n    const model = new MyClass();\n    // model.someProperty = \"hell no world\";\n    return validator.validate(model).then(errors => {\n      expect(errors.length).toEqual(2);\n      expect(errors[0].contexts).toBeUndefined();\n      expect(errors[1].contexts['contains']).toEqual({ bye: 'now' });\n    });\n  });\n\n  it('should stop at first error.', () => {\n    class MySubClass {\n      @IsDefined({\n        message: 'isDefined',\n      })\n      name: string;\n    }\n\n    class MyClass {\n      @IsDefined({\n        message: 'isDefined',\n      })\n      @Contains('hello', {\n        message: 'String is not valid. You string must contain a hello word',\n      })\n      sameProperty: string;\n\n      @ValidateNested()\n      @IsArray()\n      nestedWithPrimitiveValue: MySubClass[];\n    }\n\n    const model = new MyClass();\n    model.nestedWithPrimitiveValue = 'invalid' as any;\n\n    const hasStopAtFirstError = validator.validate(model, { stopAtFirstError: true }).then(errors => {\n      expect(errors.length).toEqual(2);\n      expect(Object.keys(errors[0].constraints).length).toBe(1);\n      expect(errors[0].constraints['isDefined']).toBe('isDefined');\n      expect(Object.keys(errors[1].constraints).length).toBe(1);\n      expect(errors[1].constraints).toHaveProperty('isArray');\n    });\n    const hasNotStopAtFirstError = validator.validate(model, { stopAtFirstError: false }).then(errors => {\n      expect(errors.length).toEqual(2);\n      expect(Object.keys(errors[0].constraints).length).toBe(2);\n      expect(errors[0].constraints).toHaveProperty('contains');\n      expect(errors[0].constraints).toHaveProperty('isDefined');\n      expect(Object.keys(errors[1].constraints).length).toBe(2);\n      expect(errors[1].constraints).toHaveProperty('isArray');\n      expect(errors[1].constraints).toHaveProperty('nestedValidation');\n    });\n\n    return Promise.all([hasStopAtFirstError, hasNotStopAtFirstError]);\n  });\n});\n\ndescribe('validateIf', () => {\n  class MyClass {\n    @Min(5, {\n      message: 'min',\n      validateIf: (obj: MyClass, value) => {\n        return !obj.someOtherProperty || obj.someOtherProperty === 'min';\n      },\n    })\n    @Max(3, {\n      message: 'max',\n      validateIf: (o: MyClass) => !o.someOtherProperty || o.someOtherProperty === 'max',\n    })\n    someProperty: number;\n\n    someOtherProperty: string;\n  }\n\n  describe('should validate if validateIf return true.', () => {\n    it('should be true', () => {\n      const result = isValidationOptions({\n        validateIf: (obj: MyClass, value) => {\n          return obj.someOtherProperty;\n        },\n      });\n      expect(result).toEqual(true);\n    });\n\n    it('should only validate min', () => {\n      const model = new MyClass();\n      model.someProperty = 4;\n      model.someOtherProperty = 'min';\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(1);\n        expect(errors[0].constraints['min']).toBe('min');\n        expect(errors[0].constraints['max']).toBe(undefined);\n      });\n    });\n    it('should only validate max', () => {\n      const model = new MyClass();\n      model.someProperty = 4;\n      model.someOtherProperty = 'max';\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(1);\n        expect(errors[0].constraints['min']).toBe(undefined);\n        expect(errors[0].constraints['max']).toBe('max');\n      });\n    });\n    it('should validate both', () => {\n      const model = new MyClass();\n      model.someProperty = 4;\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(1);\n        expect(errors[0].constraints['min']).toBe('min');\n        expect(errors[0].constraints['max']).toBe('max');\n      });\n    });\n    it('should validate none', () => {\n      const model = new MyClass();\n      model.someProperty = 4;\n      model.someOtherProperty = 'other';\n      return validator.validate(model).then(errors => {\n        expect(errors.length).toEqual(0);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "test/functional/validator-options.spec.ts",
    "content": "import { IsNotEmpty } from '../../src/decorator/decorators';\nimport { Validator } from '../../src/validation/Validator';\n\nconst validator = new Validator();\n\ndescribe('validator options', () => {\n  it('should not return target in validation error if validationError: { target: false } is set', () => {\n    class MyClass {\n      @IsNotEmpty()\n      title: string = '';\n      isActive: boolean;\n    }\n\n    const model = new MyClass();\n    model.title = '';\n    return validator\n      .validate(model, { skipMissingProperties: true, validationError: { target: false } })\n      .then(errors => {\n        expect(errors.length).toEqual(1);\n        expect(errors[0].target).toBeUndefined();\n        expect(errors[0].property).toEqual('title');\n        expect(errors[0].constraints).toEqual({ isNotEmpty: 'title should not be empty' });\n        expect(errors[0].value).toEqual('');\n      });\n  });\n\n  it('should returns error on unknown objects if forbidUnknownValues is true', function () {\n    const anonymousObject = { badKey: 'This should not pass.' };\n\n    return validator.validate(anonymousObject, { forbidUnknownValues: true }).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].target).toEqual(anonymousObject);\n      expect(errors[0].property).toEqual(undefined);\n      expect(errors[0].value).toEqual(undefined);\n      expect(errors[0].children).toBeInstanceOf(Array);\n      expect(errors[0].constraints).toEqual({ unknownValue: 'an unknown value was passed to the validate function' });\n    });\n  });\n\n  it('should return no error on unknown objects if forbidUnknownValues is false', function () {\n    const anonymousObject = { badKey: 'This should not pass.' };\n\n    return validator.validate(anonymousObject, { forbidUnknownValues: false }).then(errors => {\n      expect(errors.length).toEqual(0);\n    });\n  });\n\n  it(`should return error on unknown objects if no options object argument is passed`, () => {\n    const anonymousObject = { badKey: 'This should not pass.' };\n\n    return validator.validate(anonymousObject, undefined).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].target).toEqual(anonymousObject);\n      expect(errors[0].property).toEqual(undefined);\n      expect(errors[0].value).toEqual(undefined);\n      expect(errors[0].children).toBeInstanceOf(Array);\n      expect(errors[0].constraints).toEqual({ unknownValue: 'an unknown value was passed to the validate function' });\n    });\n  });\n\n  it(`should return error on unknown objects if empty options object argument passed`, () => {\n    const anonymousObject = { badKey: 'This should not pass.' };\n\n    return validator.validate(anonymousObject, {}).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].target).toEqual(anonymousObject);\n      expect(errors[0].property).toEqual(undefined);\n      expect(errors[0].value).toEqual(undefined);\n      expect(errors[0].children).toBeInstanceOf(Array);\n      expect(errors[0].constraints).toEqual({ unknownValue: 'an unknown value was passed to the validate function' });\n    });\n  });\n\n  it(`should return error on unknown objects if options object argument passed with forbidUnknownValues undefined`, () => {\n    const anonymousObject = { badKey: 'This should not pass.' };\n\n    return validator.validate(anonymousObject, { forbidUnknownValues: undefined }).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].target).toEqual(anonymousObject);\n      expect(errors[0].property).toEqual(undefined);\n      expect(errors[0].value).toEqual(undefined);\n      expect(errors[0].children).toBeInstanceOf(Array);\n      expect(errors[0].constraints).toEqual({ unknownValue: 'an unknown value was passed to the validate function' });\n    });\n  });\n});\n"
  },
  {
    "path": "test/functional/whitelist-validation.spec.ts",
    "content": "import { Allow, IsDefined, IsOptional, Min } from '../../src/decorator/decorators';\nimport { Validator } from '../../src/validation/Validator';\nimport { ValidationTypes } from '../../src';\n\nconst validator = new Validator();\n\ndescribe('whitelist validation', () => {\n  it('should strip non whitelisted properties, but leave whitelisted untouched', () => {\n    class MyClass {\n      @IsDefined()\n      title: string;\n\n      @Min(0)\n      views: number;\n    }\n\n    const model: any = new MyClass();\n\n    model.title = 'hello';\n    model.views = 56;\n    model.unallowedProperty = 42;\n    return validator.validate(model, { whitelist: true }).then(errors => {\n      expect(errors.length).toEqual(0);\n      expect(model.unallowedProperty).toBeUndefined();\n      expect(model.title).toEqual('hello');\n      expect(model.views).toEqual(56);\n    });\n  });\n\n  it('should be able to whitelist with @Allow', () => {\n    class MyClass {\n      @Allow()\n      views: number;\n    }\n\n    const model: any = new MyClass();\n\n    model.views = 420;\n    model.unallowedProperty = 'non-whitelisted';\n\n    return validator.validate(model, { whitelist: true }).then(errors => {\n      expect(errors.length).toEqual(0);\n      expect(model.unallowedProperty).toBeUndefined();\n      expect(model.views).toEqual(420);\n    });\n  });\n\n  it('should throw an error when forbidNonWhitelisted flag is set', () => {\n    class MyPayload {\n      /**\n       * Since forbidUnknownValues defaults to true, we must add a property to\n       * register the class in the metadata storage. Otherwise the unknown value check\n       * would take priority (first check) and exit without running the whitelist logic.\n       */\n      @IsOptional()\n      propertyToRegisterClass: string;\n\n      nonDecorated: string;\n\n      constructor(nonDecorated: string) {\n        this.nonDecorated = nonDecorated;\n      }\n    }\n\n    const instance = new MyPayload('non-whitelisted');\n\n    return validator.validate(instance, { whitelist: true, forbidNonWhitelisted: true }).then(errors => {\n      expect(errors.length).toEqual(1);\n      expect(errors[0].target).toEqual(instance);\n      expect(errors[0].property).toEqual('nonDecorated');\n      expect(errors[0].constraints).toHaveProperty(ValidationTypes.WHITELIST);\n      expect(() => errors[0].toString()).not.toThrow();\n    });\n  });\n});\n"
  },
  {
    "path": "test/utils.spec.ts",
    "content": "import { convertToArray } from '../src/utils';\n\ndescribe('convertToArray', () => {\n  it('convert Set into array', () => {\n    const setExample = new Set<string>();\n    setExample.add('hello');\n    setExample.add('world');\n    const newArr = convertToArray(setExample);\n    expect(newArr).toBeInstanceOf(Array);\n    expect(newArr.length).toEqual(2);\n    expect(newArr).toContain('hello');\n    expect(newArr).toContain('world');\n  });\n\n  it('convert Map into array of values', () => {\n    const map = new Map<string, string>();\n    map.set('key1', 'hello');\n    map.set('key2', 'world');\n    const newArr = convertToArray(map);\n    expect(newArr).toBeInstanceOf(Array);\n    expect(newArr.length).toEqual(2);\n    expect(newArr).toContain('hello');\n    expect(newArr).toContain('world');\n  });\n\n  it('should return array untouched', () => {\n    const arr = ['hello', 'world'];\n    expect(arr).toBeInstanceOf(Array);\n    expect(arr.length).toEqual(2);\n    expect(arr).toContain('hello');\n    expect(arr).toContain('world');\n  });\n});\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\r\n  \"compilerOptions\": {\r\n    \"module\": \"commonjs\",\r\n    \"moduleResolution\": \"node\",\r\n    \"target\": \"es2018\",\r\n    \"lib\": [\"es2018\"],\r\n    \"outDir\": \"build/node\",\r\n    \"rootDir\": \"./src\",\r\n    \"strict\": true,\r\n    \"sourceMap\": true,\r\n    \"inlineSources\": true,\r\n    \"removeComments\": false,\r\n    \"esModuleInterop\": true,\r\n    \"experimentalDecorators\": true,\r\n    \"emitDecoratorMetadata\": true,\r\n    \"forceConsistentCasingInFileNames\": true\r\n  },\r\n  \"exclude\": [\"build\", \"node_modules\", \"sample\", \"**/*.spec.ts\", \"test/**\"]\r\n}\r\n"
  },
  {
    "path": "tsconfig.prod.cjs.json",
    "content": "{\n  \"extends\": \"./tsconfig.prod.json\",\n  \"compilerOptions\": {\n    \"module\": \"CommonJS\",\n    \"outDir\": \"build/cjs\"\n  },\n}\n"
  },
  {
    "path": "tsconfig.prod.esm2015.json",
    "content": "{\n  \"extends\": \"./tsconfig.prod.json\",\n  \"compilerOptions\": {\n    \"module\": \"ES2015\",\n    \"outDir\": \"build/esm2015\",\n  },\n}\n"
  },
  {
    "path": "tsconfig.prod.esm5.json",
    "content": "{\n  \"extends\": \"./tsconfig.prod.json\",\n  \"compilerOptions\": {\n    \"module\": \"ES2015\",\n    \"target\": \"ES5\",\n    \"outDir\": \"build/esm5\",\n    \"downlevelIteration\": true,\n  },\n}\n"
  },
  {
    "path": "tsconfig.prod.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"strict\": false,\n    \"declaration\": false,\n  },\n}\n"
  },
  {
    "path": "tsconfig.prod.types.json",
    "content": "{\n  \"extends\": \"./tsconfig.prod.json\",\n  \"compilerOptions\": {\n    \"declaration\": true,\n    \"emitDeclarationOnly\": true,\n    \"outDir\": \"build/types\",\n  },\n}\n"
  },
  {
    "path": "tsconfig.spec.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"strict\": false,\n    \"strictPropertyInitialization\": false,\n    \"sourceMap\": true,\n    \"removeComments\": true,\n    \"noImplicitAny\": false,\n  },\n  \"exclude\": [\"node_modules\"]\n}\n"
  }
]