Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/oussamahamdaoui/forgJs

ForgJs is a javascript lightweight object validator.
https://github.com/oussamahamdaoui/forgJs

javascript js object validation

Last synced: about 2 months ago
JSON representation

ForgJs is a javascript lightweight object validator.

Awesome Lists containing this project

README

        

# ![forgJs logo](./media/logo.png?raw=true)

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

![email](./media/email.gif?raw=true)

![password](./media/password.gif?raw=true)

![number](./media/number.gif?raw=true)

![url](./media/url.gif?raw=true)

See more live examples [here](https://oussamahamdaoui.github.io/forgjs-examples/)

# Quick start

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

## Your first validator

```javascript
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:

```javascript
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:

```javascript
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:

```javascript
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)`)

```javascript
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)

```javascript
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)`)

```javascript
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:

```javascript
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

```javascript
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

```javascript
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

```

```javascript
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:

```javascript
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:

```javascript
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

```javascript
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:

```javascript
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:

```javascript
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
```javascript
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:

```javascript
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

```javascript
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](https://twitter.com/forg_js "@forg_js")