1.2.0 • Published 5 months ago

en-yup-decorator v1.2.0

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

En Yup Decorators

Added TypeScript decorators support for yup

Table of Contents

  1. Preface
  2. Usage
    1. Class instantiation
  3. Example
  4. From yup-decorators

Preface

This library is a continuation of yup-decorators, enhanced with support for the latest versions of yup and TypeScript. I would like to thank the original creators of yup-decorators for their excellent work in providing a powerful and flexible way to work with yup schemas. This version aims to bring the same functionality while keeping up with updates to yup and modern TypeScript features, offering an improved and more seamless experience (diff).

Usage

  • Named schema
import { a, is, namedSchema, getNamedSchema } from 'yup-decorator';

@namedSchema('user')
class User {
  constructor({ email, age }) {
    this.email = email;
    this.age = age;
  }
  @is(a.string().email('Not a valid email'))
  email: string;

  @is(
    a
      .number()
      .lessThan(80)
      .moreThan(10)
  )
  age: number;
}

// you can get the yup schema with
const userSchema = getNamedSchema('user');
  • Unnamed schema
import { schema, getSchemaByType } from 'yup-decorator';

@schema()
class User {
	...
}

// you can get the yup schema with
const userSchema = getSchemaByType(User);
  • Nested validation
import { is, a, an, nested, schema } from 'yup-decorator';

@schema()
export class NestedChildModel {
  @is(a.string().uppercase())
  uppercase: string;
}

@schema()
export class NestedModel {
  @is(
    an
      .array()
      .of(a.number())
      .min(2)
      .max(3)
  )
  array: number[];

  @nested()
  child: NestedChildModel;
}
  • Validate:
import { validate } from 'yup-decorator';

const user = new User({ email: 'test', age: 27 });

validate({
  object: user,
  options: {
    strict: true,
    abortEarly: false,
  },
}).then(err => {
  // err.name; // => 'ValidationError'
  // err.errors; // => ['Not a valid email']
});

// you can also pass in the schema name as a string or a constructor
validate({ object: user, schemaName: 'user' });
validate({ object: user, schemaName: User });

The sync version is validateSync

  • Check if object is valid or not
import { isValid } from 'yup-decorator';
isValid({ object: user }).then(isValid => console.log(isValid));

The sync version is isValidSync

  • Validate property at path
import { validateAt } from 'yup-decorator';
validateAt({ object: user, path: 'email' }).then(e => console.error(e));

The sync version is validateSyncAt

  • Cast object.

This will coerce the property's value according to its type

import { cast } from 'yup-decorator';
const user = new User({ email: 'test', age: '27' });
const result = cast({ object: user });
result; // {email: 'test@gmail.com', age: 27 }

The sync version is isValidSync


Class instantiation

@schema({ useTargetClass: true })
class Job {
  constructor(args: { name: string }) {
    this.name = args.name;
  }

  @is(a.string().required())
  name: string;
}

@schema({ useTargetClass: true })
class User {
  constructor(args: { name: string; job: Job; birthday: Date }) {
    this.name = args.name;
    this.job = args.job;
    this.birthday = args.birthday;
  }

  @is(a.string().required())
  name: string;

  @is(a.date().required())
  birthday: Date;

  @nestedType(
    () => Job,
    s => s.required()
  )
  job: Job;
}

const user: User = await validate({
  object: {
    job: { name: 'Dev' },
    name: 'Mattia',
    birthday: new Date().toString(),
  },
  schemaName: User,
});

console.log(
  user instanceof User,
  user.birthday instanceof Date,
  user.job instanceof Job
); // true, true, true

Example

An example where each property uses one of the various provided APIs

@schema()
class Person {
  constructor(args: {}) {
    ...
  }

  @is(a.string().required('Name is required')) // `is` let you register a schema to the given property
  name: string

  @nestedObject(() => Person) // `nestedRecord` let you register an object where each value is of the given property
  contacts: Record<string,Person>

  @nestedArray(() => House) // `nestedArray` let you register an array of the given type
  houses: House[]

  @nested() // `nested` infer the type if known
  job: Job

  nestedType(() => Country) // `nestedType` let you register an object schema to the given property
  country: Country
}

From yup-decorators

The main differences from yup-decorators are that schemas (@schema, @namedSchema) creates instances of EnYupSchema, so it is no longer possible to annotate a class as an object directly (@namedSchema(a.object().required)). Instead, there is a callback to enrich the generated schema (@namedSchema((s) => s.required())). This change is due to the ability to convert objects into instances of the target class during validation (useTargetClass). Tests and an example are provided to demonstrate this functionality.

The dependencies have been updated, and a version of yup >= 1.0.0 is now required.

1.2.0

5 months ago

1.1.0

7 months ago

1.0.0

7 months ago