1.7.0 • Published 3 years ago

validax v1.7.0

Weekly downloads
-
License
ISC
Repository
github
Last release
3 years ago

Bookmark Build Status

What is validax

A clean way to validate JSON schema in Typescript

import { Validax, ValidaxSchema, ConstraintBuilder } from 'validax';

@ValidaxSchema()
class Person {
  @ConstraintBuilder.Number().Decorator()
  id!: number;
  @ConstraintBuilder.String().Decorator()
  name!: string;
}

function userInput (input: any) {
  Validax.assert(input, Person);
  // input is Person here ...
}

userInput({
  id: 123,
  name: 'John',
});

Installation

npm install validax

Validax

assert

Validax.assert(input, schema) -> asserts input is schema

assert input data match schema

import { Validax, ValidaxSchema, ConstraintBuilder } from 'validax';

@ValidaxSchema()
class Person {
  @ConstraintBuilder.String().Decorator()
  name!: string;
}

function userInput (input: any) {
  try {
    Validax.assert(input, Person);
    // input is Person here ...
  } catch (error) {
    // input is not Person
  }
}

validate

Validax.validate(input, schema) -> input is schema

validate input data is schema

import { Validax, ValidaxSchema, ConstraintBuilder } from 'validax';

@ValidaxSchema()
class Person {
  @ConstraintBuilder.String().Decorator()
  name!: string;
}

function userInput (input: any) {
  if (Validax.validate(input, Person)) {
    // input is Person here ...
  }
}

ConstraintBuilder

String

ConstraintBuilder.String(options) -> CustomConstraint

return a CustomConstraint to validate string value

import { ValidaxSchema, ConstraintBuilder } from 'validax';

@ValidaxSchema()
class Person {
  @ConstraintBuilder.String().Decorator()
  name!: string;
}

options Optional
Type: StringConstraintOptions

type StringConstraintOptions = {
  allowNull?: boolean,
  allowUndefined?: boolean,
  maxLength?: number,
  minLength?: number,
  regex?: RegExp,
}

Number

ConstraintBuilder.Number(options) -> CustomConstraint

return a CustomConstraint to validate number value

import { ValidaxSchema, ConstraintBuilder } from 'validax';

@ValidaxSchema()
class Person {
  @ConstraintBuilder.Number({ isInteger: true }).Decorator()
  id!: number;
}

options Optional
Type: NumberConstraintOptions

type NumberConstraintOptions = {
  allowNull?: boolean,
  allowUndefined?: boolean,
  allowNaN?: boolean,
  isFinite?: boolean,
  isInteger?: boolean,
  max?: number,
  min?: number,
}

Boolean

ConstraintBuilder.Boolean(options) -> CustomConstraint

return a CustomConstraint to validate boolean value

import { ValidaxSchema, ConstraintBuilder } from 'validax';

@ValidaxSchema()
class Person {
  @ConstraintBuilder.Boolean().Decorator()
  isVerifiedEmail!: boolean;
}

options Optional
Type: BooleanConstraintOptions

type BooleanConstraintOptions = {
  allowNull?: boolean,
  allowUndefined?: boolean,
}

Class

ConstraintBuilder.Class(schema, options) -> CustomConstraint

return a CustomConstraint to validate object

import { ValidaxSchema, ConstraintBuilder } from 'validax';

@ValidaxSchema()
class Person {
  @ConstraintBuilder.String().Decorator()
  name!: string;

  @ConstraintBuilder.Class(Person, { allowNull: true }).Decorator()
  father: Person | null;
}

options Optional
Type: ClassConstraintOptions

type ClassConstraintOptions = {
  allowNull?: boolean,
  allowUndefined?: boolean,
}

CustomError

ConstraintBuilder.CustomError(constraint, error) -> CustomConstraint

return a CustomConstraint throw a custom error when validate property failed

import { ValidaxSchema, ConstraintBuilder } from 'validax';

@ValidaxSchema()
class Person {
  @ConstraintBuilder.CustomError(
    ConstraintBuilder.String(),
    new Error('name is invalid.')
  ).Decorator()
  name!: string;
}

inParallel

ConstraintBuilder.inParallel(constraints, error) -> CustomConstraint

return a CustomConstraint with constraints should pass one of the constraints ( || )

import { ValidaxSchema, ConstraintBuilder } from 'validax';

@ValidaxSchema()
class Person {
  @ConstraintBuilder.inParallel([
    ConstraintBuilder.String(),
    ConstraintBuilder.Number()
  ], new Error('id is invalid.')).Decorator()
  id!: string | number;
}

inSeries

ConstraintBuilder.inSeries(constraints) -> CustomConstraint

return a CustomConstraint with constraints should pass all constraints ( && )

import { ValidaxSchema, ConstraintBuilder } from 'validax';

@ValidaxSchema()
class Person {
  @ConstraintBuilder.inSeries([
    ConstraintBuilder.isOneOf([ 1, 2, 3 ], new Error('id is invalid')),
    ConstraintBuilder.isOneOf([ 2, 3, 4 ], new Error('id is invalid')),
  ]).Decorator()
  id!: 2 | 3;
}

isOneOf

ConstraintBuilder.isOneOf(availableVals, error) -> CustomConstraint

return a CustomConstraint that check property is one of the available values

import { ValidaxSchema, ConstraintBuilder } from 'validax';

@ValidaxSchema()
class Person {
  @ConstraintBuilder.isOneOf([ 1, 2, 3 ], new Error('id is invalid')).Decorator()
  id!: 1 | 2 | 3;
}

ArrayOf

ConstraintBuilder.ArrayOf(constraint, options) -> CustomConstraint

return a CustomConstraint that check property is an array of specific type

import { ValidaxSchema, ConstraintBuilder } from 'validax';

@ValidaxSchema()
class Person {
  @ConstraintBuilder.ArrayOf(ConstraintBuilder.Number()).Decorator()
  id!: number[];
}

options Optional
Type: ArrayOfConstraintOptions

type ArrayOfConstraintOptions = {
  allowNull?: boolean,
  allowUndefined?: boolean,
  maxLength?: number,
  minLength?: number,
}

Tuple

ConstraintBuilder.Tuple(constraints, options) -> CustomConstraint

return a CustomConstraint that check tuple value

import { ValidaxSchema, ConstraintBuilder } from 'validax';

@ValidaxSchema()
class Person {
  @ConstraintBuilder.Tuple([
    ConstraintBuilder.Number(),
    ConstraintBuilder.String(),
  ]).Decorator()
  id!: [number, string];
}

options Optional
Type: TupleConstraintOptions

type TupleConstraintOptions = {
  allowNull?: boolean,
  allowUndefined?: boolean,
  allowExtraDataLength?: boolean,
}

CustomConstraint

new CustomConstraint(assertFunction) -> CustomConstraint

import { ValidaxSchema, CustomConstraint } from 'validax';

@ValidaxSchema() class Person { @new CustomConstraint((val) => { if (!val || typeof val !== 'object') throw new Error('foo is not an object'); if (typeof val.bar !== 'string') throw new Error('foo.bar is not a string'); if (typeof val.bar2 !== 'number') throw new Error('foo.bar2 is not a number'); }).Decorator() foo!: { bar: string; bar2: number; }; }

assertFunction<br>
*Required*  
Type: `AssertFunction`  
```ts
/**
 * return void when type check is pass
 * throw error when type check is failed
 */
type AssertFunction = (val: any, className: string, propNames: string[])=> void | never

Common issues

1. Experimental support for decorators is a feature that is subject to change in a future release.

In tsconfig.json

"emitDecoratorMetadata": true,
"experimentalDecorators": true,

2. How to validate a nested object

(1) ConstraintBuilder.Class

import { ValidaxSchema, ConstraintBuilder } from 'validax';

@ValidaxSchema()
class Foo {
  @ConstraintBuilder.String().Decorator()
  bar!: string;
  @ConstraintBuilder.Number().Decorator()
  bar2!: number;
}

@ValidaxSchema()
class Person {
  @ConstraintBuilder.Class(Foo).Decorator()
  foo!: Foo;
}

(2) CustomConstraint

import { ValidaxSchema, CustomConstraint } from 'validax';

@ValidaxSchema()
class Person {
  @new CustomConstraint((val) => {
    if (!val || typeof val !== 'object')
      throw new Error('foo is not an object');
    if (typeof val.bar !== 'string')
      throw new Error('foo.bar is not a string');
    if (typeof val.bar2 !== 'number')
      throw new Error('foo.bar2 is not a number');
  }).Decorator()
  foo!: {
    bar: string;
    bar2: number;
  };
}