hapi-joi-decorators

Class decorations based validations using JOI as a backend

Usage no npm install needed!

<script type="module">
  import hapiJoiDecorators from 'https://cdn.skypack.dev/hapi-joi-decorators';
</script>

README

hapi-joi-decorators

Thisrepository is elisvathi/hapi-joi-decorators joi upgrade to match last hapi joi version Allows to create validation schemas by using typescript decorators using joi as a backend

Status: Work in progress

Table of Contents

Installation

    npm install --save hapi-joi-decorators

General Decorators

Required Decorator

Invalidates the object if the field doesn't exist

Usage

    class Example {
        @Required()
        public field: string;
    }
    
    // Joi schema
    schema.required();

or...

    import {ClassValidator} from "hapi-joi-decorators";
    class Example extends ClassValidator{
        @Required()
        public field: string = 'default value';
    }
    
    const schema: Joi.Schema = Example.toObject();
    // Joi schema
    console.log('example schema', schema);

Optional Decorator

Turns off the required flag for the field

Usage

    class Example {
        @Optional()
        public field: string;
    }

    // Joi schema
    schema.optional();

Nullable Decorator

Allows the field to have null as a value

Usage

    class Example {
        @Nullable()
        public field: string;
    }
    
    // Joi schema
    schema.allow(null)

or...

    class Example {
        @Nullable()
        public field: string;
    }

    class Derived extends Example {
        /**
         * Use it with a boolean value if you need to disable the value on 
         * a derived class
         * */
        @Nullable(false)
        public field: string;
    }

ValidOptions Decorator

Allows only the values provided in the arguments

Usage

    class Example {
        @ValidOptions('name', 'age')
        public field: string;
    }

    // Joi schema
    schema.valid('name', 'age');

Number Decorators

Max Decorator

Specifies the max value for the field

Usage

    class Example {
        @Max(42)
        public field: number;
    }
    
    // Joi schema
    schema.max(42);

or...

    class Example {
        /**
         * Excludes the value from being accepted 
         * */
        @Max({value: 42, exclude: true})
        public field: number;
    }
    
    // Joi schema
    schema.max(42).invalid(42)

Min Decorator

Specifies the min value for the field

Usage

    class Example {
        @Min(42)
        public field: number;
    }
    
    // Joi schema
    schema.min(42);

or...

    class Example {
        /**
         * Excludes the value from being accepted 
         * */
        @Min({value: 42, exclude: true})
        public field: number;
    }
    
    // Joi schema
    schema.min(42)

Positive Decorator

Allows positive values only to the number field

Usage

    class Example {
        @Positive()
        public field: number;
    }

    // Joi schema
    schema.positive();

    class Derived extends Example {
        // Use the flags if you need to override it when you inherit
        @Positive(false)
        public field: number;
    }

Negative Decorator

Allows negative values only to the number field

Usage

    class Example {
        @Negative()
        public field: number;
    }

    // Joi schema
    schema.negative();

    class Derived extends Example {
        // Use the flags if you need to override it when you inherit
        @Negative(false)
        public field: number;
    }

String Decorators

MinLength Decorator

Sets a lower limit to the string length

Usage

    class Example {
        @MinLength(42)
        public field: string;
    }
    
    // Joi schema
    schema.min(42);

MaxLength Decorator

Sets an upper limit to the string length

Usage

    class Example {
        @MaxLength(42)
        public field: string;
    }
    
    // Joi schema
    schema.max(42);

NotEmpty Decorator

Sets the string lower limit to 1 character

Usage

    class Example {
        @NotEmpty()
        public field: string;
    }
    
    // Joi schema
    schema.min(1);
    
    class Derived extends Example {
        // Use the flag if you want to disable the NotEmpty check on a derived class
        @NotEmpty(false)
        public field: string;
    }

Email Decorator

String field should be a valid email

Usage

    class Example {
        @Email()
        public field: string;
    }
    
    // Joi schema
    schema.email();
    
    class Derived extends Example {
        // Use the flag if you want to disable the Email check on a derived class
        @Email(false)
        public field: string;
    }

DateString Decorator

Validates the string as a date using the specified format

Usage

    class Example {
        // Default is YYYY-MM-DD
        @Required()
        @Date('YY-MM-DD')
        public date: string;
    }
    
    // Joi schema
    schema.date('YY-MM-DD');
    

Array Decorators

ItemType Decorator

Is required to specify the array item type if the array items should be validated

Usage

    class Item {
        @Required()
        public id: number;
    }

    class Example {
        @ItemType(Item)
        public field: Item[];
    }
    
    // Joi schema
    schema.array().items(Joi.object().keys({
        id: Joi.number().required()
    }));

MinLength Decorator

Sets a lower limit to the array length

Usage

    class Example {
        @MinLength(42)
        public field: string[];
    }
    
    // Joi schema
    schema.array().min(42);

MaxLength Decorator

Sets an upper limit to the array length

Usage

    class Example {
        @MaxLength(42)
        public field: string[];
    }
    
    // Joi schema
    schema.array().max(42);

NotEmpty Decorator

Sets the array lower limit to 1 item

Usage

    class Example {
        @NotEmpty()
        public field: string[];
    }
    
    // Joi schema
    schema.array().min(1);
    
    class Derived extends Example {
        // Use the flag if you want to disable the NotEmpty check on a derived class
        @NotEmpty(false)
        public field: string[];
    }

Date Decorators

DateString format decorator

Specifies the format that the field should have as an input Uses joi-date-extensions Extension as a backend

Usage


    class Example {
        @Required()
        @DateString('YYYY-MM-DD')
        public date: Date;
    }

    // Joi schema
    Joi.date().format('YYYY-MM-DD').required();

Custom Validation Schema

CustomSchema Decorator

You can create a custom Joi schema for the field or append properties to existing one

Usage


    // Using a lambda function
    class Example {
        @Required()
        @CustomSchema((current: Joi.Schema)=>current.optional())
        public field: string;
    }

    // Creating a schema from scratch, overrides any pre-built schema from other decorators
    class SecondExample {
        @CustomSchema(Joi.string().optional())
        public date: Date;
    }

Nested Validations

Validates the child fields if their type is another class

Usage

    class ChildObject {
        @Optional()
        id: number;
    }

    class Example {
        @Required()
        public child: ChildObject;
    }
    
    // Joi schema
    schema.object().keys({
        child: Joi.object().keys({
            id: Joi.number().optional()
        }).required()
    });

Inheritance

Inherited classes inherit the validation metadata from the base class

Usage

    class BaseObject {
        @Optional()
        id: number;
    }

    class Inherited extends BaseObject {
        @Optional()
        name: string;
    }
    
    // Joi schema
    schema.object().keys({
        id: Joi.number().optional(),
        name: Join.string().optional()
    });

You can also override validation properties from the base class

    class BaseObject {
        @Required()
        @Email()
        primary: string;
    }

    class Inherited extends BaseObject {
        @Optional()
        name: string;
        @Optional()
        primary: string;
    }
    
    // Joi schema
    // Base Class

    schema.object().keys({
        primary: Joi.string().email().required(),
    });

    // Derived Class 
    schema.object().keys({
        primary: Joi.string().email().optional(),
        name: Join.string().optional()
    });

Getting the validation schema


    import {ClassValidator} from "hapi-joi-decorators";
    class Example extends ClassValidator{
        @Required()
        @Email()
        email: string;
    }

    const schema: Joi.Schema = Example.toObject();


Validating the object


    import { Validate } from 'hapi-joi-decorators'

    class Example {
        @Required()
        @Email()
        public email: string;
    }

    const value : Example = new Example();
    value.email = "john@example.com"

    Validate(value).catch(error=>{console.log(error.message)});

Example

    import { Validate } from 'hapi-joi-decorators'

    class UserData {

        @Optional()
        allowNotifications: boolean;

    }

    class Location {

        @Required()
        @NotEmpty()
        name: string;

        @Required()
        latitude: number;

        @Required()
        longitude: number;

    }

    class User {

        @Required()
        @Email()
        public email: string;

        @Required()
        @MaxLength(30)
        @MinLength(5)
        public username: string;

        @Required()
        @MaxLength(30)
        @MinLength(5)
        public password: string;

        @Optional()
        @Min({value: 18})
        @Max({value: 30, exclude: true})
        public age: number;

        @Required()
        public data: UserData;

        @Required()
        @ItemType(Location)
        @MaxLength(10)
        public locations: Location[];

    }

    async function fetchData(): Promise<User> {
        ...
    }

    fetchData().then((result: User)=>Validate(user));