{"id":17821516,"url":"https://github.com/a179346/validax","last_synced_at":"2025-03-18T10:30:23.008Z","repository":{"id":37789616,"uuid":"367209198","full_name":"a179346/validax","owner":"a179346","description":"A clean way to validate JSON schema in Typescript","archived":false,"fork":false,"pushed_at":"2022-12-26T21:07:23.000Z","size":165,"stargazers_count":4,"open_issues_count":5,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-11T03:38:00.197Z","etag":null,"topics":["json-schema","json-schema-validator","nodejs","npm","npm-package","typescript","validator"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/a179346.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-05-14T00:40:08.000Z","updated_at":"2023-01-31T18:54:04.000Z","dependencies_parsed_at":"2023-01-31T01:45:44.138Z","dependency_job_id":null,"html_url":"https://github.com/a179346/validax","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a179346%2Fvalidax","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a179346%2Fvalidax/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a179346%2Fvalidax/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a179346%2Fvalidax/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/a179346","download_url":"https://codeload.github.com/a179346/validax/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243922105,"owners_count":20369350,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json-schema","json-schema-validator","nodejs","npm","npm-package","typescript","validator"],"created_at":"2024-10-27T17:17:57.409Z","updated_at":"2025-03-18T10:30:22.634Z","avatar_url":"https://github.com/a179346.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\u003ch1 align=\"center\"\u003e ⭕ Validax ⭕\u003c/h1\u003e\n\n\u003cp\u003e\n  \u003ca href=\"https://github.com/a179346/validax/actions/workflows/test.yml\" target=\"_blank\"\u003e\n    \u003cimg alt=\"Documentation\" src=\"https://github.com/a179346/validax/actions/workflows/test.yml/badge.svg\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://travis-ci.org/a179346/validax\" target=\"_blank\"\u003e\n    \u003cimg alt=\"Documentation\" src=\"https://travis-ci.org/a179346/validax.svg?branch=main\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/validax\" target=\"_blank\"\u003e\n    \u003cimg alt=\"Documentation\" src=\"https://img.shields.io/npm/v/validax?maxAge=3600)\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/a179346/validax#readme\" target=\"_blank\"\u003e\n    \u003cimg alt=\"Documentation\" src=\"https://img.shields.io/badge/documentation-yes-brightgreen.svg\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/a179346/validax/graphs/commit-activity\" target=\"_blank\"\u003e\n    \u003cimg alt=\"Maintenance\" src=\"https://img.shields.io/badge/Maintained%3F-yes-green.svg\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/a179346/validax/blob/master/LICENSE\" target=\"_blank\"\u003e\n    \u003cimg alt=\"License: MIT\" src=\"https://img.shields.io/github/license/a179346/validax\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\u003c/div\u003e\n\n\u003e A clean way to validate JSON schema in Typescript\n\n# Bookmark\n\n- [Bookmark](#bookmark)\n- [What is validax](#what-is-validax)\n- [Installation](#installation)\n- [Validax](#validax)\n  - [assert](#assert)\n  - [validate](#validate)\n- [ConstraintBuilder](#constraintbuilder)\n  - [String](#string)\n  - [Number](#number)\n  - [Boolean](#boolean)\n  - [Class](#class)\n  - [CustomError](#customerror)\n  - [inParallel](#inparallel)\n  - [inSeries](#inseries)\n  - [isOneOf](#isoneof)\n  - [ArrayOf](#arrayof)\n  - [Tuple](#tuple)\n- [CustomConstraint](#customconstraint)\n- [validateOptions](#validateoptions)\n- [Common issues](#common-issues)\n    - [1. Experimental support for decorators is a feature that is subject to change in a future release.](#1-experimental-support-for-decorators-is-a-feature-that-is-subject-to-change-in-a-future-release)\n    - [2. How to validate a nested object](#2-how-to-validate-a-nested-object)\n# What is validax\nA clean way to validate JSON schema in Typescript\n\n```ts\nimport { Validax, ValidaxSchema, ConstraintBuilder } from 'validax';\n\n@ValidaxSchema()\nclass Person {\n  @ConstraintBuilder.Number().Decorator()\n  id!: number;\n  @ConstraintBuilder.String().Decorator()\n  name!: string;\n}\n\nfunction userInput (input: any) {\n  Validax.assert(input, Person);\n  // input is Person here ...\n}\n\nuserInput({\n  id: 123,\n  name: 'John',\n});\n```\n\n# Installation\n```bash\nnpm install validax\n```\n\n# Validax\n## assert\n\n\u003e `Validax.assert(input, schema[, validateOptions])` -\u003e `asserts input is schema`\n \nassert input data match schema\n\nreference: [validateOptions](#validateoptions)\n\n```ts\nimport { Validax, ValidaxSchema, ConstraintBuilder } from 'validax';\n\n@ValidaxSchema()\nclass Person {\n  @ConstraintBuilder.String().Decorator()\n  name!: string;\n}\n\nfunction userInput (input: any) {\n  try {\n    Validax.assert(input, Person);\n    // input is Person here ...\n  } catch (error) {\n    // input is not Person\n  }\n}\n```\n## validate\n\n\u003e `Validax.validate(input, schema[, validateOptions])` -\u003e `input is schema`\n \nvalidate input data is schema\n\nreference: [validateOptions](#validateoptions)\n\n```ts\nimport { Validax, ValidaxSchema, ConstraintBuilder } from 'validax';\n\n@ValidaxSchema()\nclass Person {\n  @ConstraintBuilder.String().Decorator()\n  name!: string;\n}\n\nfunction userInput (input: any) {\n  if (Validax.validate(input, Person)) {\n    // input is Person here ...\n  }\n}\n```\n\n# ConstraintBuilder\n## String\n\n\u003e `ConstraintBuilder.String(options)` -\u003e `CustomConstraint`\n \nreturn a CustomConstraint to validate string value\n```ts\nimport { ValidaxSchema, ConstraintBuilder } from 'validax';\n\n@ValidaxSchema()\nclass Person {\n  @ConstraintBuilder.String().Decorator()\n  name!: string;\n}\n```\noptions\u003cbr\u003e\n*Optional*  \nType: `StringConstraintOptions`   \n```ts\ntype StringConstraintOptions = {\n  allowNull?: boolean,\n  allowUndefined?: boolean,\n  maxLength?: number,\n  minLength?: number,\n  regex?: RegExp,\n}\n```\n## Number\n\n\u003e `ConstraintBuilder.Number(options)` -\u003e `CustomConstraint`\n \nreturn a CustomConstraint to validate number value\n```ts\nimport { ValidaxSchema, ConstraintBuilder } from 'validax';\n\n@ValidaxSchema()\nclass Person {\n  @ConstraintBuilder.Number({ isInteger: true }).Decorator()\n  id!: number;\n}\n```\noptions\u003cbr\u003e\n*Optional*  \nType: `NumberConstraintOptions`   \n```ts\ntype NumberConstraintOptions = {\n  allowNull?: boolean,\n  allowUndefined?: boolean,\n  allowNaN?: boolean,\n  isFinite?: boolean,\n  isInteger?: boolean,\n  max?: number,\n  min?: number,\n}\n```\n## Boolean\n\n\u003e `ConstraintBuilder.Boolean(options)` -\u003e `CustomConstraint`\n \nreturn a CustomConstraint to validate boolean value\n```ts\nimport { ValidaxSchema, ConstraintBuilder } from 'validax';\n\n@ValidaxSchema()\nclass Person {\n  @ConstraintBuilder.Boolean().Decorator()\n  isVerifiedEmail!: boolean;\n}\n```\noptions\u003cbr\u003e\n*Optional*  \nType: `BooleanConstraintOptions`   \n```ts\ntype BooleanConstraintOptions = {\n  allowNull?: boolean,\n  allowUndefined?: boolean,\n}\n```\n## Class\n\n\u003e `ConstraintBuilder.Class(schema, options)` -\u003e `CustomConstraint`\n \nreturn a CustomConstraint to validate object\n```ts\nimport { ValidaxSchema, ConstraintBuilder } from 'validax';\n\n@ValidaxSchema()\nclass Person {\n  @ConstraintBuilder.String().Decorator()\n  name!: string;\n\n  @ConstraintBuilder.Class(Person, { allowNull: true }).Decorator()\n  father: Person | null;\n}\n```\noptions\u003cbr\u003e\n*Optional*  \nType: `ClassConstraintOptions`   \n```ts\ntype ClassConstraintOptions = {\n  allowNull?: boolean,\n  allowUndefined?: boolean,\n}\n```\n## CustomError\n\n\u003e `ConstraintBuilder.CustomError(constraint, error)` -\u003e `CustomConstraint`\n \nreturn a CustomConstraint throw a custom error when validate property failed\n```ts\nimport { ValidaxSchema, ConstraintBuilder } from 'validax';\n\n@ValidaxSchema()\nclass Person {\n  @ConstraintBuilder.CustomError(\n    ConstraintBuilder.String(),\n    new Error('name is invalid.')\n  ).Decorator()\n  name!: string;\n}\n```\n## inParallel\n\n\u003e `ConstraintBuilder.inParallel(constraints, error)` -\u003e `CustomConstraint`\n \nreturn a CustomConstraint with constraints\u003cbr\u003e\nshould pass one of the constraints ( || )\n```ts\nimport { ValidaxSchema, ConstraintBuilder } from 'validax';\n\n@ValidaxSchema()\nclass Person {\n  @ConstraintBuilder.inParallel([\n    ConstraintBuilder.String(),\n    ConstraintBuilder.Number()\n  ], new Error('id is invalid.')).Decorator()\n  id!: string | number;\n}\n```\n## inSeries\n\n\u003e `ConstraintBuilder.inSeries(constraints)` -\u003e `CustomConstraint`\n \nreturn a CustomConstraint with constraints\u003cbr\u003e\nshould pass all constraints ( \u0026\u0026 )\n```ts\nimport { ValidaxSchema, ConstraintBuilder } from 'validax';\n\n@ValidaxSchema()\nclass Person {\n  @ConstraintBuilder.inSeries([\n    ConstraintBuilder.isOneOf([ 1, 2, 3 ], new Error('id is invalid')),\n    ConstraintBuilder.isOneOf([ 2, 3, 4 ], new Error('id is invalid')),\n  ]).Decorator()\n  id!: 2 | 3;\n}\n```\n## isOneOf\n\n\u003e `ConstraintBuilder.isOneOf(availableVals, error)` -\u003e `CustomConstraint`\n \nreturn a CustomConstraint that check property is one of the available values\n```ts\nimport { ValidaxSchema, ConstraintBuilder } from 'validax';\n\n@ValidaxSchema()\nclass Person {\n  @ConstraintBuilder.isOneOf([ 1, 2, 3 ], new Error('id is invalid')).Decorator()\n  id!: 1 | 2 | 3;\n}\n```\n## ArrayOf\n\n\u003e `ConstraintBuilder.ArrayOf(constraint, options)` -\u003e `CustomConstraint`\n \nreturn a CustomConstraint that check property is an array of specific type\n```ts\nimport { ValidaxSchema, ConstraintBuilder } from 'validax';\n\n@ValidaxSchema()\nclass Person {\n  @ConstraintBuilder.ArrayOf(ConstraintBuilder.Number()).Decorator()\n  id!: number[];\n}\n```\noptions\u003cbr\u003e\n*Optional*  \nType: `ArrayOfConstraintOptions`   \n```ts\ntype ArrayOfConstraintOptions = {\n  allowNull?: boolean,\n  allowUndefined?: boolean,\n  maxLength?: number,\n  minLength?: number,\n}\n```\n## Tuple\n\n\u003e `ConstraintBuilder.Tuple(constraints, options)` -\u003e `CustomConstraint`\n \nreturn a CustomConstraint that check tuple value\n```ts\nimport { ValidaxSchema, ConstraintBuilder } from 'validax';\n\n@ValidaxSchema()\nclass Person {\n  @ConstraintBuilder.Tuple([\n    ConstraintBuilder.Number(),\n    ConstraintBuilder.String(),\n  ]).Decorator()\n  id!: [number, string];\n}\n```\noptions\u003cbr\u003e\n*Optional*  \nType: `TupleConstraintOptions`   \n```ts\ntype TupleConstraintOptions = {\n  allowNull?: boolean,\n  allowUndefined?: boolean,\n  allowExtraDataLength?: boolean,\n}\n```\n# CustomConstraint\n\n\u003e `new CustomConstraint(assertFunction)` -\u003e `CustomConstraint`\n```ts\nimport { ValidaxSchema, CustomConstraint } from 'validax';\n\n@ValidaxSchema()\nclass Person {\n  @new CustomConstraint((val) =\u003e {\n    if (!val || typeof val !== 'object')\n      throw new Error('foo is not an object');\n    if (typeof val.bar !== 'string')\n      throw new Error('foo.bar is not a string');\n    if (typeof val.bar2 !== 'number')\n      throw new Error('foo.bar2 is not a number');\n  }).Decorator()\n  foo!: {\n    bar: string;\n    bar2: number;\n  };\n}\n```\nassertFunction\u003cbr\u003e\n*Required*  \nType: `AssertFunction`  \n```ts\n/**\n * return void when type check is pass\n * throw error when type check is failed\n */\ntype AssertFunction = (val: any, className: string, propNames: string[], validateOptions?: validateOptions)=\u003e void | never\n```\n\n# validateOptions\n\n```ts\ninterface validateOptions {\n  // not allow other keys in object if true\n  strict?: boolean;\n}\n```\n\n# Common issues\n\n### 1. Experimental support for decorators is a feature that is subject to change in a future release.\n\u003e In `tsconfig.json`\n\u003e ```ts\n\u003e \"emitDecoratorMetadata\": true,\n\u003e \"experimentalDecorators\": true,\n\u003e ```\n\n### 2. How to validate a nested object\n\u003e [(1) ConstraintBuilder.Class](#class)\n\u003e ```ts\n\u003e import { ValidaxSchema, ConstraintBuilder } from 'validax';\n\u003e \n\u003e @ValidaxSchema()\n\u003e class Foo {\n\u003e   @ConstraintBuilder.String().Decorator()\n\u003e   bar!: string;\n\u003e   @ConstraintBuilder.Number().Decorator()\n\u003e   bar2!: number;\n\u003e }\n\u003e \n\u003e @ValidaxSchema()\n\u003e class Person {\n\u003e   @ConstraintBuilder.Class(Foo).Decorator()\n\u003e   foo!: Foo;\n\u003e }\n\u003e ```\n\n\u003e [(2) CustomConstraint](#customconstraint)\n\u003e ```ts\n\u003e import { ValidaxSchema, CustomConstraint } from 'validax';\n\u003e \n\u003e @ValidaxSchema()\n\u003e class Person {\n\u003e   @new CustomConstraint((val) =\u003e {\n\u003e     if (!val || typeof val !== 'object')\n\u003e       throw new Error('foo is not an object');\n\u003e     if (typeof val.bar !== 'string')\n\u003e       throw new Error('foo.bar is not a string');\n\u003e     if (typeof val.bar2 !== 'number')\n\u003e       throw new Error('foo.bar2 is not a number');\n\u003e   }).Decorator()\n\u003e   foo!: {\n\u003e     bar: string;\n\u003e     bar2: number;\n\u003e   };\n\u003e }\n\u003e ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa179346%2Fvalidax","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fa179346%2Fvalidax","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa179346%2Fvalidax/lists"}