GithubHelp home page GithubHelp logo

oussamahamdaoui / forgjs Goto Github PK

View Code? Open in Web Editor NEW
1.7K 19.0 51.0 1.54 MB

ForgJs is a javascript lightweight object validator.

Home Page: https://oussamahamdaoui.github.io/forgjs-examples/

License: MIT License

JavaScript 100.00%
javascript object validation js

forgjs's Introduction

forgJs logo

ForgJs is a JavaScript lightweight object validator. Go check the Quick start section and start coding with love ❤️

email

password

number

url

See more live examples here

Quick start

Install it via npm by running npm i @cesium133/forgjs

Your first validator

  const { Validator, Rule } = require('@cesium133/forgjs');

const emailRule = new Rule({
    type: 'email',
    user: user => user === 'dedede',
    domain: domain => ['outlook', 'gmail', 'yahoo'].indexOf(domain) !== -1,
}, null);

const passwordRule = new Rule({
    type: 'password',
    minLength: 8,
    uppercase: 1,
    numbers: 1,
    matchesOneOf: ['@', '_', '-', '.', '!'],
}, null);

const vComplex = new Validator({
    age: new Rule({ type: 'int', min: 18, max: 99 }),
    dateOfBirth: new Rule({ type: 'date' }),
    array: new Rule({ type: 'array', of: new Rule({ type: 'string' }) }),
    email: emailRule,
    password: passwordRule
});

vComplex.test({
    age: 26,
    dateOfBirth: new Date(1995, 10, 3),
    array: ['1'],
    email: '[email protected];',
    password: 'ad1_A@@Axs',
}); /// returns true

Error handling

You can get custom error messages by doing this:

const vComplexe = new Validator({
    age: new Rule({
      type: 'int', min: 18, max: 99,
    }, 'age must be integer and between 18 and 99'),
    dateOfBirth: new Rule({ type: 'date' }, 'date must be a date'),
  });

  vComplexe.getErrors({
    age: 16,
    dateOfBirth: 123,
  }); // ['age must be integer and between 18 and 99', 'date must be a date']

Test over an array

You can test over multiple arrays using this method:

const vComplexe = new Validator({
    age: new Rule({
      type: 'int', min: 18, max: 99,
    }),
  });

  vComplexe.testAll([{
    age: 19,
  }, {
    age: 16,
  }]);  // returns 1

Rules

A Rule object validates a single value, it can be used like this:

  const { Validator, Rule } = require('@cesium133/forgjs');
  const floatRule = new Rule({
    type: 'float',
    min: 100,
  }, null);

  floatRule.test(2.001); /// returns true;

The only required value is type!

You can make a rule by simply passing a string if you only need to check the type : new Rule('int');

int

  • min (int)
  • max (int)
  • equal (int)

boolean

  • toBe (boolean)

string

  • minLength (int)
  • maxLength (int)
  • equal (string)
  • match: (regex)
  • notEmpty (bool)

email

  • minLength (int)
  • maxLength (int)
  • equal (string)
  • match: (regex)
  • notEmpty (bool)
  • user (function(user))
  • domain (function(domain))
  const emailRule = new Rule({
    type: 'email',
    user: user => user === 'dedede',
    domain: domain => ['outlook', 'gmail', 'yahoo'].indexOf(domain) !== -1,
  }, null);

  emailRule.test('[email protected]'); // returns true

password

  • minLength (int)
  • maxLength (int)
  • equal (string)
  • match: (regex)
  • notEmpty (bool)
  • uppercase (int)
  • number (int)
  • mathesOneOf (Array)
  • matchesAllOf (Array)
  const passwordRule = new Rule({
    type: 'password',
    minLength: 8,
    uppercase: 1,
    numbers: 1,
    matchesOneOf: ['@', '_', '-', '.', '!'],
  }, null);

  passwordRule.test('@_-bddcd6A'); // returns true

url

  • minLength (int)
  • maxLength (int)
  • equal (string)
  • match: (regex)
  • notEmpty (bool)
  • protocol (function(protocol))
  • domain (function(domain))
  const urlRule = new Rule({
    type: 'url',
    protocol: prot => prot === 'https',
    domain: domain => domain === 'google.fr',
  }, null);

  urlRule.test('https://google.fr'); // returns true

date

  • after (date)
  • before (date)
  • between (Array of dates like this [date, date])
  • equal (date)

float

  • min (Number)
  • max (Number)
  • equal (float)

array

  • of (Rule or Validator object)
  • notEmpty (bool)
  • length (int)

The of rule checks every element of the array against the rule.

function

  • result

To explain result, what's better than an example:

  const { Validator, Rule } = require('@cesium133/forgjs');

  function someFunctionThatReturnsAnInt(int) {
    return int * 5;
  }

  const functionTest = new Rule({
    type: 'function',
    result: {
      of: 5,
      toBe: new Rule('int'),
    },
  }, null);

  functionTest.test(someFunctionThatReturnsAnInt); /// returns true;

string-int, string-float, string-date, string-boolean

These types 'inherit' from string, they have both the properties, here are some examples:

string-int

const stringInt = new Rule({
  type: 'string-int',
  minLength: 2,
  min: 5,
}, null);

stringInt.test(2) // returns false 2 is not a string
stringInt.test('2a') // returns false '2a' is not a int
stringInt.test('2.1') // returns false '2.1' is not a int
stringInt.test('5') // returns false length of '5' is smaller than 2
stringInt.test('50') // returns true

string-boolean

const stringBoolean = new Rule({
  type: 'string-boolean',
  toBe: true
}, null);

stringBoolean.test(true) // returns false true is not a boolean
stringBoolean.test('false') // returns false 'false' is not true
stringBoolean.test('true') // returns true
const stringDate = new Rule({
  type: 'string-date',
  after: new Date(2019, 11, 1),
}, null);

stringDate.test(new Date(2018, 11, 1)) // returns false new Date(2018, 11, 1) is not a string
stringDate.test('some string') // returns false 'some string' is not a valid date
stringDate.test('2018-12-17') // returns false '2018-12-17' is not after new Date(2019, 11, 1)
stringDate.test('2020-01-01') // returns true

Forgjs tries to cast the value to the right type before passing it to the validation function please be careful!

Here is an example where Javascript behaviour makes the test wrong:

const stringDate = new Rule({
  type: 'string-date',
  equal: new Date(2019, 10, 1), // month in js strart at 0
}, null);

stringDate.test('2019-11-01') // returns false
stringDate.test('2019-11-01T00:00') // returns true


// this is because:

new Date(2019, 10, 1) - new Date('2019-11-01') // equals  3600000 thats exactly 1 hour

new Date(2019, 10, 1) - new Date('2019-11-01T00:00') // equals 0

Multiple types

You can check for multiple types with OR or AND operators like this:

  const intRule = new Rule({
    type: 'int|float|number',
  }, null);

  intRule.test(2) // returns true

This means the test should verify the int, float or number rule

  const intRule = new Rule({
    type: 'int&number',
  }, null);
  intRule.test(2.1); // returns false

The result doesn't match the int rule

Common properties

Every type has these properties:

  • optional
  • custom
  • oneOf

optional

If optional is set to true the element is optional and an undefined value is considered correct. Example:

const { Validator, Rule } = require('@cesium133/forgjs');

const intRule = new Rule({
    type: 'int',
    optional: true,
  }, null);
intRule.test(); // returns true

custom

Custom allows you to write your own rule, an example is better than a long explanation:

  const { Validator, Rule } = require('@cesium133/forgjs');
  
  function isCorrectAge(age, object) {
    if (age === Math.floor((new Date() - object.dateOfBirth) / 1000 / 60 / 60 / 24 / 30 / 12)) {
      return true;
    }
    return false;
  }
  const vComplexe = new Validator({
    age: new Rule({
      type: 'int', min: 18, max: 99, custom: isCorrectAge,
    }),
    dateOfBirth: new Rule({ type: 'date' }),
  });

  vComplexe.test({
    age: 23,
    dateOfBirth: new Date(1995, 10, 3),
    array: ['1'],
  }); // returns true

oneOf

One of checks if the element is in a array

  const floatRule = new Rule({
    type: 'float',
    oneOf: [3.5, 100.1, 7.2, 0.1],
  }, null);
  floatRule.test(100.1); // returns true

Make a new type

Creating a new type is done using the Rule class like this:

  const { Validator, Rule } = require('@cesium133/forgjs'); 
  
  Rule.addCustom('customInteger', {
    min: (val, min) => val - min > 0,
    max: (val, max) => val - max < 0,
    equal: (val, equal) => val === equal,
    type: val => Number.isInteger(val) && val > 0 && val < 100,
  });

  const customInteger = new Rule({
    type: 'customInteger',
    min: 10,
  }, null);

  customInteger.test(11) // returns true

  customInteger.test(200) // returns false

How to contribute

Thank you everyone for contributing to make this code better, if you have suggestions or ideas to improve the code please feel free to leave a comment here #29. Rules:

1 Please use this template which will help developers to test and better understand your request

const someRule= new Rule({
    type: 'yourType',
    prop1: val1,
    prop2: val2, ...
  }, null);

  someRule.test(validValue) // returns true
  someRule.test(invalidValue) // returns false

2 Please if you think a comment is a good feature to be added like the comment instead of creating a new one.

3 Before submitting a new comment check if the same comment is not already present

4 If you submit a PR (pull request) and you only change the Readme please add [ci skip] to your commit message

5 If you have any questions ask them in the FAQ

6 Please have fun, and if you feel like not following the rules then don't follow them

code with love ❤️

Left TO DO for next release

Contact

Follow me on twitter at @forg_js

forgjs's People

Contributors

benjaminvanryseghem avatar dependabot[bot] avatar jason-cooke avatar jayjamesjay avatar l1wulf avatar lucianbuzzo avatar mecm1993 avatar morpheus7cs avatar muturgan avatar netshade avatar nevoss avatar oussamahamdaoui avatar robpethick avatar xx-nf-xx avatar yoda6 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

forgjs's Issues

Validating an undefined property will cause an error

Validating an undefined property will cause an error, e.g.:

const { Validator, Rule } = require('@cesium133/forgjs');


let validator = new Validator({
    name: new Rule({ type: 'string', optional: false, notEmpty: true, minLength: 1 }),
});

// this will works
validator.test({ name: 'ok' }); // return true


// this will throw an exception
validator.test({ name: null }); // this throw an Error

(I'm using @cesium133/forgjs version "1.1.9)

changing the order of the rule properties causes an error

const { Validator, Rule } = require('@cesium133/forgjs');


// test: use type at the start -- this will works
let validator = new Validator({
    name: new Rule({ type: 'string', optional: false, notEmpty: true, minLength: 1 }),
    description: new Rule({ type: 'string', optional: true }),
    done: new Rule({ type: 'boolean', optional: true })
});
validator.test({ description: 'Just with description.' }); // return false


// test: use type at the end -- this will throw an Error
validator = new Validator({
    name: new Rule({ optional: false, notEmpty: true, minLength: 1, type: 'string' }),
    description: new Rule({ type: 'string', optional: true }),
    done: new Rule({ type: 'boolean', optional: true })
});

validator.test({ description: 'Just with description.' }); // this throw an Error

Error message as fucntions

Hey, I did a quick scan for the repo and I like what I see, I have written a Form library and I was seeking for some package like this one to fill out the validation part (didn't find something that I like so I write some light validation class inside my library). so I thinking about using this library,

some feature that I think will be great is to set the error message as a function for example:

const createMinIntRule = (num) => {
 return new Rule(
   { type: 'integer', min: num }, 
   (key, value) => `${key} must be greater then ${num}, ${value} is not enough` 
  )
}

and then you can create more reusability in your rules, let me know what do you think about it, I will love to make a pull request with implementation,

of course there that the option of a string as an error message will be still working.

Incorrect error message returned on nested array rules

Example

    const validator = new Validator({
        users: new Rule({
            type: "array",
            of: new Rule({type: "int", oneOf: [2, 3, 4, 5]}, "User ID does not exist")
        }, "Users' ID not provided"),
    });


validator.getErrors([2,4,7,10])  // returns Users' ID not provided

create-react-app + forgJS

Hi there,
I'm trying to use forgJS with create-react-app but unfortunately it raise the error:

1!] Error: 'Rule' is not exported by node_modules/@cesium133/forgjs/index.js

this is how I used:

import * as React from 'react';
import { Rule } from '@cesium133/forgjs';
import styles from './styles.css';

const ExampleComponent = ({ text }: any) => {
  const floatRule = new Rule(
    {
      type: 'float',
      min: 100,
    },
    null
  );
  const result = floatRule.test(200.3);
  console.log(result);

  return <div className={styles.test}>Example Component: {text}</div>;
};

export default ExampleComponent;

To have a working example is enough to do:
npx create-react-library
and then install the package forgJs.

Can someone help me on that please?

errorMessages is empty array when validation fails due to unexpected field

Example:

const event = new Validator({
  employeeId: new Rule({ type: 'string' }),
  duration: new Rule({ type: 'int' })
})

event.test({
	employeeId: '123',
	duration: 10,
	shouldNotBeHere: true
})

// returns false, this is OK

events.getErrors({
	employeeId: '123',
	duration: 10,
	shouldNotBeHere: true
})

// returns [], this is not OK I think, should return at least [undefined] or even better: ['Unknown property found: "shouldNotBeThere"']

Validator.getErrors()

Validator.getErrors() methods returns a function definition for me and not a string.

Duplicate error messages when check for multiple types.

Example:

const { Validator, Rule } = require('@cesium133/forgjs');

const validator = new Validator({
  value: new Rule(
    {
      type: 'int|float',
      min: 1
    },
    'Error message'
  ),
});

validator.getErrors({
  value: 0,
});  // [ 'Error message', 'Error message' ]

One rule, one custom error message, but multiple errors in array.

I was trying to fix it and send a PR, but it seems like you have unfinished or undocumented work there.

Validating a null property will cause an error

Validating a null property will cause an error, e.g.:

const { Validator, Rule } = require('@cesium133/forgjs');


let validator = new Validator({
    name: new Rule({ type: 'string', optional: false, notEmpty: true, minLength: 1 }),
});

// this will works
validator.test({ name: 'ok' }); // return true


// this will throw an exception
validator.test({ name: null }); // this throw an Error

allowed fields

this package is awesome. thnk you!

suggestion for the functionality extands.

it will be very usefull to check required and allowed keys in anobject

Type boolean?

This might be a stupid question, but how can I add a boolean rule in a validator?

in other words, if I have an object {a:1, b:true} I can test for a to be an integer, but how do I test for b to be a boolean?

Suggestions

Hey every one, If you have suggestions or ideas to improuve the code please feel free to let a comment here.
Rulles:

1 Please use this template wich will help developers to test and better understend your request:

const someRule= new Rule({
    type: 'yourType',
    prop1: val1,
    prop2: val2, ...
  }, null);

  someRule.test(validValue) // returns true
  someRule.test(invalidValue) // returns false

2 Please if you think a comment is a good feature to be added like the coment insted of creating a new one.

3 Before submitting a new comment check if the same comment is not allready present

4 If you submit a PR (pull request) and you only change the Readme plese add [ci skip] to your commit message

5 If you have any questions ask them in the FAQ

6 Please have fun, and if you feel like not following the rulles then don't follow them

code with love ❤️

example in README fails due to typos

Hello
there are a few mistakes in the example on README, I found the following - please see below the corrected code.

  1. the object passed to the Validator included 'pasword' instead of 'password'
  2. the email was set to 'my-email' not 'dedede' which made the test fail

Corrected code:

const { Validator, Rule } = require('@cesium133/forgjs');

const emailRule = new Rule({
    type: 'email',
    user: user => user === 'dedede',
    domain: domain => ['outlook', 'gmail', 'yahoo'].indexOf(domain) !== -1,
}, null);

const passwordRule = new Rule({
    type: 'password',
    minLength: 8,
    uppercase: 1,
    numbers: 1,
    matchesOneOf: ['@', '_', '-', '.', '!'],
}, null);

const vComplexe = new Validator({
    age: new Rule({ type: 'int', min: 18, max: 99 }),
    dateOfBirth: new Rule({ type: 'date' }),
    array: new Rule({ type: 'array', of: new Rule({ type: 'string' }) }),
    email: emailRule,
    password: passwordRule
});

vComplexe.test({
    age: 26,
    dateOfBirth: new Date(1995, 10, 3),
    array: ['1'],
    email: '[email protected];',
    password: 'ad1_A@@Axs',
}); /// returns true

Repo Improvements

Hi, I saw a reddit post asking for improvement suggestions in this repo. Here goes:

  1. Use Rultor for automating merge/deploy/release operations.
  2. Use Puzzle Driven Development and 0pdd for task management.

If it sounds interesting and want more details, feel free to ask, I'll be glad to help.

Have fun!

The equal value of rule

The doc says type string has a equal check, which value should be int. But the code actually checks if the string value is exactly equal to the parameter.
screen shot 2018-12-16 at 11 07 02 am

Optional property to support "empty" values

Hi! I have the following example:

// value is one of "", "ABCD1234"
const discountCode = new Rule({
  type: 'string',
  match: /^[A-Z0-9]$/,
  optional: true,
  minLength: 8,
  maxLength: 8
}).test(value)

Setting the optional property does not work here right now, because it requires the value to be either undefined or something that matches the Rule. I was curious if there is a possibility to state somewhere that "" should be also acceptable? I could do either value = "" || ... or

Rule({
  type: 'string',
  match: /^$|^[A-Z0-9]{8}$/
})

, just curious if there is a cleaner way?

Typos in readme

Error handeling -> Error handling

Left TO DO for next relese -> Left TO DO for next release

throw errors

imagine
I want to validate any data, and show any message to user on error
so I must to do somethink like:

const result = prettyValidator.test(data);

if (!result) {
   const errors = prettyValidator.getErrors(data);
   procassErrors(errors); // in my case -> res.status(422).send(errors);
   return;
}

go on...

so I must to go through this cycle twice on error. and my data can contains lot of fields.

well, i can do this:

const errors= prettyValidator.getErrors(data);

if (errors.length > 0) {
   res.status(422).send(errors);
   return;
}

go on...

these performance is better, but the syntax is not semantic - looks like I expect an error.
and the result is not semantic - I expect an empty array on success

I recommend you to generate the errorArray in the test method too, but return true on success and throw errorArray on error.

this will allow to use try/catch and write more clean code

Support for validating Nested Objects

Hey there. Loved the repo! I had a question though. How do you support nested Objects. Just for an example, if we have a object like

{ name: { first_name: 'John', last_name: 'Doe' }, address: { city: 'Mumbai', country: 'India' } }

How do we go about validating this?

Validator.getErrors() throws an error on undefined fields

Example:

const validator = new Validator({
  str: new Rule(
    { type: 'string' },
    'Error message'
  )
});

validator.getErrors({
  str: undefined,
}); // Error thrown: Cannot read property 'constructor' of undefined

Expected behavior: [ 'Error message' ]

P.S. null and undefined have no constructor in JS

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.