GithubHelp home page GithubHelp logo

michallytek / class-transformer-validator Goto Github PK

View Code? Open in Web Editor NEW
199.0 5.0 19.0 298 KB

A simple plugin for class-transformer and class-validator which combines them in a nice and programmer-friendly API.

License: MIT License

TypeScript 100.00%
typescript javascript validation validator

class-transformer-validator's Introduction

class-transformer-validator

npm version Dependency Status devDependency Status peerDependency Status

A simple plugin for class-transformer and class-validator which combines them in a nice and programmer-friendly API.

Installation

Module installation

npm install class-transformer-validator --save

(or the short way):

npm i -S class-transformer-validator

Peer dependencies

This package is only a simple plugin/wrapper, so you have to install the required modules too because it can't work without them. See detailed installation instruction for the modules installation:

Usage

The usage of this module is very simple.

import { IsEmail } from "class-validator";
import { transformAndValidate } from "class-transformer-validator";

// declare the class using class-validator decorators
class User {
  @IsEmail()
  public email: string;

  public hello(): string {
    return "World!";
  }
}

// then load the JSON string from any part of your app
const userJson: string = loadJsonFromSomething();

// transform the JSON to class instance and validate it correctness
transformAndValidate(User, userJson)
  .then((userObject: User) => {
    // now you can access all your class prototype method
    console.log(`Hello ${userObject.hello()}`); // prints "Hello World!" on console
  })
  .catch(err => {
    // here you can handle error on transformation (invalid JSON)
    // or validation error (e.g. invalid email property)
    console.error(err);
  });

You can also transform and validate plain JS object (e.g. from express req.body). Using ES7 async/await syntax:

async (req, res) => {
  try {
    // transform and validate request body
    const userObject = await transformAndValidate(User, req.body);
    // infered type of userObject is User, you can access all class prototype properties and methods
  } catch (err) {
    // your error handling
    console.error(err);
  }
};

And since release 0.3.0 you can also pass array of objects - all of them will be validated using given class validation constraints:

async (req, res) => {
  try {
    // transform and validate request body - array of User objects
    const userObjects = await transformAndValidate(User, req.body);
    userObjects.forEach(user => console.log(`Hello ${user.hello()}`));
  } catch (err) {
    // your error handling
  }
};

API reference

Function signatures

There is available the transformAndValidate function with three overloads:

function transformAndValidate<T extends object>(
  classType: ClassType<T>,
  jsonString: string,
  options?: TransformValidationOptions,
): Promise<T | T[]>;
function transformAndValidate<T extends object>(
  classType: ClassType<T>,
  object: object,
  options?: TransformValidationOptions,
): Promise<T>;
function transformAndValidate<T extends object>(
  classType: ClassType<T>,
  array: object[],
  options?: TransformValidationOptions,
): Promise<T[]>;

Be aware that if you validate json string, the return type is a Promise of T or T[] so you need to assert the returned type if you know the shape of json:

const users = (await transformAndValidate(
  User,
  JSON.stringify([{ email: "[email protected]" }]),
)) as User[];

Or you can just check the type in runtime using Array.isArray method.

Synchronous transformation and validation

If you need sync validation, use transformAndValidateSync function instead (available since v0.4.0). It will synchronously return T or T[], not a Promise.

Parameters and types

  • classType - an class symbol, a constructor function which can be called with new
type ClassType<T> = {
  new (...args: any[]): T;
};
  • jsonString - a normal string containing JSON

  • object - plain JS object of type object (introduced in TypeScript 2.2), you will have compile-time error while trying to pass number, boolean, null or undefined but unfortunately run-time error when passing a function

  • array - array of plain JS objects like described above

  • options - optional options object, it has two optional properties

interface TransformValidationOptions {
  validator?: ValidatorOptions;
  transformer?: ClassTransformOptions;
}

You can use it to pass options for class-validator (more info) and for class-transformer (more info).

More info

The class-transformer and class-validator are more powerful than it was showed in the simple usage sample, so go to their github page and check out they capabilities!

Release notes

0.9.1

  • widen class-transformer peer dependency version range to >=0.2.3
  • updated all dev dependencies

0.9.0

  • bump class-validator peer dependency to version >=0.12.0
  • updated TypeScript dependency to version ^3.9.5
  • updated all dev dependencies

0.8.0

  • updated class-transformer dependency to version ^0.2.3
  • updated class-validator dependency to version ^0.10.1
  • updated TypeScript dependency to version ^3.6.3
  • built code is now emitted as ES2015 (dropped es5 support)
  • updated all dev dependencies

0.7.1

  • updated class-transformer dependency to version ^0.2.0

0.6.0

  • updated class-validator dependency to version ^0.9.1

0.5.0

  • remove deprecated TransformValdiationOptions interface (typo)
  • updated class-validator dependency to version ^0.8.1 and class-transformer to ^0.1.9

0.4.1

  • fix TransformValdiationOptions interface name typo (deprecate in favour of TransformValidationOptions)

0.4.0

  • added transformAndValidateSync function for synchronous validation
  • changed return type for JSON's transform and validation to Promise of T or T[]
  • updated class-validator dependency to version ^0.7.2 and class-transformer to ^0.1.7

0.3.0

  • added support for transform and validate array of objects given class
  • updated class-validator dependency to version ^0.7.1

0.2.0

  • changed object parameter type declaration to object (introduced in TS 2.2)
  • throwing error when passed array, undefined or null

0.1.1

0.1.0

  • initial version with transformAndValidate function

class-transformer-validator's People

Contributors

michallytek avatar quezak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

class-transformer-validator's Issues

Give an option to combine class-validator's decorators with class-transformer's "excludeExtraneousValues" ?

Since this package uses both class-validator and class-transformer, and many users complain on applying @expose() on all fields in order to remove extraneous values, wouldn't it be possible to give an option to levarage the validation decorators?

Something like "excludeUnvalidatedFields"?

Or, perhaps, we could have something like @IsStringExpose(), that wraps both @IsString() and @expose() ? I created this Gist as reference: https://gist.github.com/pauloendoh/f7d3194bae2ff121e78ce45589bd4ab2

Cannot validate array elements

I can validate nested objects, and I can make sure that certain property is an array. However, the validator does not care if the elements in the array are valid or not. What am I forgetting here?

export class Album {
  @IsString()
  @Expose()
  @IsDefined()
  name!: string;
}

export class Photo {
  @IsNumber()
  @Expose()
  @IsDefined()
  id!: number;

  @Expose()
  @IsDefined()
  @IsArray()
  @Type(() => Album)
  albums!: Album[];
}

const object = {
  name: "Juan Ramon Riquelme",
  albums: [{
    noName: "Felipe"
  }]
}

// This line succeeds, but it should fail!
transformAndValidate(Photo, object, {
    transformer: { excludeExtraneousValues: true },
    validator: { forbidUnknownValues: true }
  }).then(console.log).catch(console.error);

I have written a complete reproducer and pushed it here: https://gitlab.com/albertodiazdorado/class-transform-validator-issue
To reproduce:

git clone https://gitlab.com/albertodiazdorado/class-transform-validator-issue.git
pushd class-transform-validator-issue
yarn install # or npm install
yarn start   # or npm start

A typo in README.md

console.err(error)

Property 'err' does not exist on type 'console'.
Replace it with 'error':
console.error(something)

Simplified usage for type guards

I'm currently using this package with a helper to create type guards:

/** Create a type guard function for a class decorated with validators. */
export function isValidFactory<T extends object>(classType: ClassType<T>): (instance: object) => instance is T {
  return (instance: object): instance is T => {
    try {
      transformAndValidateSync(classType, instance)
      return true
    } catch (err) {
      return false
    }
  }
}

Would you be interested in a PR that adds this helper?

Error when validate nested Object

Hello,

I have this code :

import 'reflect-metadata'

import { IsDate, ValidateNested, validate } from 'class-validator'
import { Type, plainToClass } from 'class-transformer'
import { transformAndValidate } from 'class-transformer-validator'

export class User {
  @Type(() => Date)
  @IsDate()
  availabilityDate?: Date
}

export class Parent {
  @ValidateNested()
  @Type(() => User)
  user?: User
}

const body = {
  user: {
    availabilityDate: new Date().toISOString(),
  },
}
const classTransformer = plainToClass(Parent, body) as any

console.log(
  'Typeof',
  Object.prototype.toString.call(classTransformer.user.availabilityDate) === '[object Date]'
) // true

validate(classTransformer).then((errors) => {
  console.log(errors) // []
})

transformAndValidate(User, body)
  .then((resultValidator: any) => {
    // Don't pass here
    console.log(
      Object.prototype.toString.call(resultValidator.user.availabilityDate) === '[object Date]'
    ) // Should be true
  })
  .catch((err) => {
    console.log(err) // -> constraints: { isDate: 'availabilityDate must be a Date instance' }
  })

As you can see, validate don't returns errors but transformAndValidate do. Did I miss something ?

Thanks

transformer or validator always keep getting removed

when i install class-validator, class-transformer get removed, and when i install class-transformer again, class validator gets removed.

yarn version : 1.3.2
npm version : 5.5.1
node version: 8.9.1
angular/cli: 1.6.4
angular-devkit/build-optimizer: 0.0.38
angular-devkit/core: 0.0.25
angular-devkit/schematics: 0.0.48
ngtools/json-schema: 1.1.0
ngtools/webpack: 1.9.4
schematics/angular: 0.1.13
schematics/schematics: 0.0.13
typescript: 2.2.2
webpack: 3.10.0

Make it work with optionals?

How do I make it work with optional attributes? The validator is checking it regardless of the attribute being optional.

export class CreateEventDto {
  @IsString()
  @Length(5, 255)
  title: string;

  @IsString()
  @Length(5, 255)
  location: string;

  @IsString()
  @IsNotEmpty()
  @Length(5, 255)
  description: string;

  @IsUrl()
  url?: string;

  @IsString({ each: true })
  images: string[];

  @IsDateString()
  startDate: Date;

  @IsDateString()
  endDate: Date;
}

export class UpdateEventDto implements Partial<CreateEventDto> {}

Error when I run try to validate UpdateEventDto body:

{
            "target": {
                "name": "AuraEd workshop on web automation with python"
            },
            "property": "title",
            "children": [],
            "constraints": {
                "length": "title must be longer than or equal to 5 characters",
                "isString": "title must be a string"
            }
        },
        {
            "target": {
                "name": "AuraEd workshop on web automation with python"
            },
            "property": "location",
            "children": [],
            "constraints": {
                "length": "location must be longer than or equal to 5 characters",
                "isString": "location must be a string"
            }
        },
        {
            "target": {
                "name": "AuraEd workshop on web automation with python"
            },
            "property": "description",
            "children": [],
            "constraints": {
                "length": "description must be longer than or equal to 5 characters",
                "isNotEmpty": "description should not be empty",
                "isString": "description must be a string"
            }
        },
        {
            "target": {
                "name": "AuraEd workshop on web automation with python"
            },
            "property": "url",
            "children": [],
            "constraints": {
                "isUrl": "url must be an URL address"
            }
        },
        {
            "target": {
                "name": "AuraEd workshop on web automation with python"
            },
            "property": "startDate",
            "children": [],
            "constraints": {
                "isDateString": "startDate must be a ISOString"
            }
        },
        {
            "target": {
                "name": "AuraEd workshop on web automation with python"
            },
            "property": "endDate",
            "children": [],
            "constraints": {
                "isDateString": "endDate must be a ISOString"
            }
        }

The API Input:

{
    "name": "AuraEd workshop on web automation with python"
}

Update deps to class-transformer 0.2.0

I recently updated to class-transformer 0.2.0, becuase I wanted to use the discriminator feature that they introduced. From my brief tests it looks like it still works with this package, but my use cases are not too complicated, so I can't say everything's ok :) Anyway, it may be worth releasing with updated deps, probably as v0.7 since it's theoretically a breaking change for class-transformer.

Common decorators

How about extending this project with some new decorators that would make use of the fact that both libraries are available?

For example: instead of using @Type(() => Foo) and @IsInstance(Foo, {each: true}) and @IsArray() one could use a single decorator like @IsArrayOf(Foo) which would configure both class-transformer and class-validator with less code.

Adding support for arrays

There should be done support for array transforming and validation

  • create tests for array case
  • detect if param is array
  • call validate foreach

Add support for json array

Currently transformAndValidate(classType, jsonString) returns Promise<classType> even if jsonString is a JSON array string. This feature need new type definition (Promise<classType|Array<classType>>) which will require type assertion from lib consumers.

Typing for `transformAndValidate` with array is not correct

The types for transformAndValidate is declared as:
export declare function transformAndValidate<T extends object>(classType: ClassType<T>, object: object, options?: TransformValidationOptions): Promise<T>;

Where the return is typed as <T>

However, if the return of transformAndValidate is an array of transformed instances then you need t do something like this to get the typing correct:

as unknown as InstanceClass[]

class-transformer 0.2.2 breaks transformAndValidate

It should relate to this issue in class-transformer after they released 0.2.2 yesterday

import { transformAndValidate } from 'class-transformer-validator';

class User {
  @IsEmail()
  identifier!: string;

  @IsString()
  password!: string;
}

const user: User = {
  identifier: '[email protected]',
  password: 'password123',
};

const userJson: string = JSON.stringify(user);

await transformAndValidate(User, userJson)
  .then(async (): Promise<void> => Promise.resolve())
  .catch(async (err: Error): Promise<never> => Promise.reject(err));

Throw error
TypeError: Reflect.getMetadata is not a function

Which was working fine before(before they upgrade to 0.2.2)

By adding

import 'reflect-metadata';

at the top solved this issue.

Cannot find name 'object'

Could you change 'object' to 'Object' in index.d.ts please?

I have got 10 errors in index.d.ts file like this:

class-transformer-validator/index.d.ts:19:56
Cannot find name 'object'.

args.value.length not reflecting the true length of the input

Hi,
I have the following:

export class Onset {
  @IsNotEmpty( { message: 'Input required' } )
  @MinLength( 6, { message: minLength6Fn } )
  mode: string
}

export function minLength6Fn( args: ValidationArguments ) {
  switch ( args.value.length ) {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
      return `Too short, minimum length is ${args.constraints[ 0 ]} characters, but actual is ${args.value.length}`
  }
}

Validation is done as shown below:

 onset = new Onset()
onset.model = 'Sudden'

          transformAndValidate( Onset, currentValue )
                  .then( ( onset: Onset ) => {
        
                  } )
                  .catch( errors => {
                    console.log( `onset errors | ${JSON.stringify( errors ) }` )
                    console.log( errors )
        
                    let propError = findPropertyValidationErrors( errors, 'mode' )
                    console.log( propError )
                  } )

The validation error printed to console is '["Too short, minimum length is 6 characters, but actual is 5"]

The ${args.value.length} in return Too short, minimum length is ${args.constraints[ 0 ]} characters, but actual is ${args.value.length} is NOT reflecting the true length of the input.

Is this a bug?

Class Validator Peer Dependency Error

This is my package.json dependencies:

"class-transformer-validator": "^0.8.0",
"class-validator": "^0.11.0",

and I'm getting yarn error:
"class-transformer-validator#class-validator@^0.10.1" doesn't satisfy found match of "[email protected]"

Simple custom validators

I don't understand why creating custom validators need require so much boilerplate with class creation etc. Surely there should be a simple way to create custom validators that take messages? E.g.

@IsString
@IsNotEmpty
@ValidIf(o.section === "SomeSectionName", { message: "Wrong section" })
myProperty!: string

Am I missing a simple way of doing this without creating a constraint class and then registering a decorator or using the @Validate(MyConstraint, { message: "Wrong section" }) form?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.