qantra-pineapple

1.1.5 • Public • Published

pineapple

advanced json object validator specially designed to validate user json input and return readable error messages

alt text

Install

npm install qantra-pineapple

Change Log

  • Starting from version 1.0.9, validators can return true, false or value. if value is returned it will override the real object value in the same exact path when the trim/format function is called. this feature has been tested on none array values and is yet to be implemented for array values

Simple Usuage

let Pineapple = require('../index.js');
let pine = new Pineapple();

const run = async ()=>{
    let schema = [
        /** will fail in length */
        {
          path: 'user.firstname',
          label: 'First Name',
          length: { min:3 , max: 8 },
        },
        /** will fail in regex*/
        {
            path: 'user.email',
            label: 'Email',
            regex: '^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$',
        },
        /** will fail in type */
        {
            path: 'user.age',
            label: 'Age',
            type: 'Number',
        },
        /** will fail in option */
        {
            path: 'user.gender',
            oneOf: ['male','female'],
            required: true,
        },
        /** will fail in reqiured */
        {
            path: 'user.licenseId',
            label: 'license Id',
            required: true,
        }
      ]
      
      let payload = {
        user: {
            firstname: 'bahi hussein abdel baset',
            email: 'jumbo@mumbo@shit',
            age: 'twelve',
            gender: 'monkey',
        }
      }
      
      let error = await pine.validate(payload, schema);
      if(error){
        console.log(error);

        /*** OUTPUT
          [
            {
                label: 'First Name',
                path: 'user.firstname',
                message: 'First Name has invalid length',
                log: '_length',
                errors: []
            },
            {
                label: 'Age',
                path: 'user.age',
                message: 'Age invalid type',
                log: '_type',
                errors: []
            },
            {
                label: 'user.gender',
                path: 'user.gender',
                message: 'user.gender invalid option',
                log: '_oneOf',
                errors: []
            },
            {
                label: 'license Id',
                path: 'user.licenseId',
                message: 'license Id is required',
                log: '_required',
                errors: []
            }
            ]
         */
      }
}


run();

Using validation models to avoid repetition

validation models can be used to define validation object that can be used in multiple schemes

const models = {
  id: {
    type: 'string'
    regex: '^[a-f\d]{24}$'
  }
}

pine = Pine({models});

let schema1 = [
  {
    path: 'user.id',
    model: 'id'
  },
]

let schema2 = [
  {
    path: 'product.id',
    model: 'id'
  }
]

pine.validate(obj1, schema1);
pine.validate(obj2, schema2);

this will simply compine {...model, ...schemaObject}

Validation Props

  • label: label is useful for returning a user readable message
  • type: can be 'string', 'number', 'array', 'object', 'boolean', 'date'
  • required: true or false
  • length: can be a number or object length: 5 , length: {min: 10, max: 100}
  • regex: takes a regex expression to match
  • oneOf: array of string from which the user value must be included ['male','female']
  • canParse: takes a string 'int' , 'date' , 'float' check if a value can be parsed.
  • items: validates array items and takes an a validation model reference object if validating array of strings of validation models reference array if validating array of objects

Advanced Example


//validation schema
let validationModels = [
  {
    model: 'name',
    label: 'Username',
    regex: /^([a-zA-Z0-9\s]{3,50})$/
  },
  {
    model: 'mobile',
    required: false,
  },
  {
    model: 'age',
    label: 'Age',
    type: 'Number',
  },
  {
    model: 'skills',
    label: 'User Skills',
    type: 'Array',
    length: {max:5},
    items: {
      type: 'String',
      length: { min: 3, max: 50}
    }
  },
  {
    model: 'gender',
    label: 'Gender',
    type: 'String',
    oneOf: ['male', 'female'],
  },
  {
    model: 'books',
    label: 'User Books',
    type: 'Array',
    items: [

      {
        label: 'Book Title',
        path: 'title',
        type: 'String',
        required: true,
      },
      {
        label: 'Prints',
        path: 'prints',
        type: 'Array',
        items: [
          {
            label: 'Country',
            path: 'country',
            type: 'String',
            required: true,
          },
          {
            label: 'Release Date',
            path: 'release.date',
            canParse: 'date'
          }
        ]
      }

    ]
  }


]

// user object
let userInput = {
  user: {
    name: 'bahi hussein',
    age: '19',
    skills: ['coding','drawing', 'ts'],
    games: [
      {title: 'outlast', score: 80},
      {title: 'red alert', score: 100},
    ],
    gender: 'ninja',
    books: [
      {
        title: 'bezzels',
        prints: [
          {
            country: 'egypt',
            release:{
              date: 1586193356622
            },
          },
          {
            country: 'uk',
            release:{
              date: 'king toot'
            },
          }
        ]
      }
    ],

    adult: true,

  }
}


//model reference
let modelReference = [
  { model: 'name', path: 'user.name', label: 'Writer Name'},
  { model: 'mobile', path: 'user.mobile', required: true,},
  { model: 'age', path: 'user.age' },
  { model: 'skills', path: 'user.skills' },
  { model: 'gender', path: 'user.gender' },
  { model: 'books',  path: 'user.books' },
]

let pineapple = new Pineapple({models: validationModels});

let result = pineapple.validate(userInput, modelReference);

console.log(JSON.stringify(result))

[
   {
      "label":"user.mobile",
      "path":"user.mobile",
      "message":"user.mobile is required",
      "log":"_required",
      "errors":[

      ]
   },
   {
      "label":"Age",
      "path":"user.age",
      "message":"Age invalid type",
      "log":"_type",
      "errors":[

      ]
   },
   {
      "label":"User Skills",
      "path":"user.skills",
      "message":"one of the User Skills items is invalid",
      "log":"_length @index(2)",
      "errors":[

      ]
   },
   {
      "label":"Gender",
      "path":"user.gender",
      "message":"Gender invalid option",
      "log":"_oneOf",
      "errors":[

      ]
   },
   {
      "label":"User Books",
      "path":"user.books",
      "message":"one of the User Books items is invalid",
      "log":"_items @index(0)",
      "errors":[
         {
            "label":"Prints",
            "path":"prints",
            "message":"one of the Prints items is invalid",
            "log":"_items @index(1)",
            "errors":[
               {
                  "label":"Release Date",
                  "path":"release.date",
                  "message":"Release Date invalid parsing",
                  "log":"_canParse",
                  "errors":[

                  ]
               }
            ]
         }
      ]
   }
]

Methods

  • validate(payload, schema) validates object against schema
  • trim(payload, schema) trim's the object to match schema requirments

custom validator

const blockPine = new Pineapple({
    models,
    customValidators: {
    'switch': (data)=>{
        let switchKeys = Object.keys(data);
        let valid = true;
        for(let i=0; i<switchKeys.length; i++){
            if(typeof data[switchKeys[i]] !== "boolean"){
                valid = false;
                break;
            }
        }
        return valid;
    },
    counter: (data)=>{
        let counterKeys = Object.keys(data);
        let valid = true;
        for(let i=0; i<counterKeys.length; i++){
            if(!_.isNumber(data[counterKeys[i]])){
                valid = false;
                break;
            }
        }
        return valid;
    }
}});

it can be used in the schema with prop custom:

Dependents (2)

Package Sidebar

Install

npm i qantra-pineapple

Weekly Downloads

51

Version

1.1.5

License

ISC

Unpacked Size

102 kB

Total Files

7

Last publish

Collaborators

  • rahmasabry
  • qantra
  • 3adly