{"id":13451995,"url":"https://github.com/oussamahamdaoui/forgJs","last_synced_at":"2025-03-23T19:33:29.237Z","repository":{"id":33633568,"uuid":"158855715","full_name":"oussamahamdaoui/forgJs","owner":"oussamahamdaoui","description":"ForgJs is a javascript lightweight object validator.","archived":false,"fork":false,"pushed_at":"2023-10-18T21:19:49.000Z","size":1577,"stargazers_count":1664,"open_issues_count":3,"forks_count":51,"subscribers_count":19,"default_branch":"master","last_synced_at":"2024-03-14T14:03:01.813Z","etag":null,"topics":["javascript","js","object","validation"],"latest_commit_sha":null,"homepage":"https://oussamahamdaoui.github.io/forgjs-examples/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oussamahamdaoui.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-11-23T16:28:06.000Z","updated_at":"2024-03-13T10:45:22.000Z","dependencies_parsed_at":"2024-01-13T22:58:45.617Z","dependency_job_id":"cc4c715f-774f-4932-b281-55ba094353c8","html_url":"https://github.com/oussamahamdaoui/forgJs","commit_stats":{"total_commits":156,"total_committers":17,"mean_commits":9.176470588235293,"dds":0.4935897435897436,"last_synced_commit":"4a413951fa2afde37b52e0fbdde0ff81b52cf8a3"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oussamahamdaoui%2FforgJs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oussamahamdaoui%2FforgJs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oussamahamdaoui%2FforgJs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oussamahamdaoui%2FforgJs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oussamahamdaoui","download_url":"https://codeload.github.com/oussamahamdaoui/forgJs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221900706,"owners_count":16898986,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","js","object","validation"],"created_at":"2024-07-31T07:01:09.513Z","updated_at":"2024-10-28T18:30:28.729Z","avatar_url":"https://github.com/oussamahamdaoui.png","language":"JavaScript","funding_links":[],"categories":["Repository","JavaScript"],"sub_categories":["Data Validation"],"readme":"# ![forgJs logo](./media/logo.png?raw=true)\n\nForgJs is a JavaScript lightweight object validator. Go check the Quick start section and start coding with love :heart:\n\n![email](./media/email.gif?raw=true)\n\n![password](./media/password.gif?raw=true)\n\n![number](./media/number.gif?raw=true)\n\n![url](./media/url.gif?raw=true)\n\nSee more live examples [here](https://oussamahamdaoui.github.io/forgjs-examples/)\n\n# Quick start\n\nInstall it via npm by running `npm i @cesium133/forgjs`\n\n## Your first validator\n\n```javascript\n  const { Validator, Rule } = require('@cesium133/forgjs');\n\nconst emailRule = new Rule({\n    type: 'email',\n    user: user =\u003e user === 'dedede',\n    domain: domain =\u003e ['outlook', 'gmail', 'yahoo'].indexOf(domain) !== -1,\n}, null);\n\nconst passwordRule = new Rule({\n    type: 'password',\n    minLength: 8,\n    uppercase: 1,\n    numbers: 1,\n    matchesOneOf: ['@', '_', '-', '.', '!'],\n}, null);\n\nconst vComplex = new Validator({\n    age: new Rule({ type: 'int', min: 18, max: 99 }),\n    dateOfBirth: new Rule({ type: 'date' }),\n    array: new Rule({ type: 'array', of: new Rule({ type: 'string' }) }),\n    email: emailRule,\n    password: passwordRule\n});\n\nvComplex.test({\n    age: 26,\n    dateOfBirth: new Date(1995, 10, 3),\n    array: ['1'],\n    email: 'dedede@yahoo.fr;',\n    password: 'ad1_A@@Axs',\n}); /// returns true\n  ```\n\n## Error handling\n\nYou can get custom error messages by doing this:\n\n```javascript\nconst vComplexe = new Validator({\n    age: new Rule({\n      type: 'int', min: 18, max: 99,\n    }, 'age must be integer and between 18 and 99'),\n    dateOfBirth: new Rule({ type: 'date' }, 'date must be a date'),\n  });\n\n  vComplexe.getErrors({\n    age: 16,\n    dateOfBirth: 123,\n  }); // ['age must be integer and between 18 and 99', 'date must be a date']\n\n```\n## Test over an array\n\nYou can test over multiple arrays using this method:\n\n```javascript\nconst vComplexe = new Validator({\n    age: new Rule({\n      type: 'int', min: 18, max: 99,\n    }),\n  });\n\n  vComplexe.testAll([{\n    age: 19,\n  }, {\n    age: 16,\n  }]);  // returns 1\n```\n\n# Rules\n\nA `Rule` object validates a single value, it can be used like this: \n\n```javascript\n  const { Validator, Rule } = require('@cesium133/forgjs');\n  const floatRule = new Rule({\n    type: 'float',\n    min: 100,\n  }, null);\n\n  floatRule.test(2.001); /// returns true;\n```\n\n**The only required value is `type`!**\n\n\u003e You can make a rule by simply passing a string if you only need to check the type : `new Rule('int');`\n\n## int\n\n* min (int)\n* max (int)\n* equal (int)\n\n## boolean\n\n* toBe (boolean)\n\n## string\n\n* minLength (int)\n* maxLength (int)\n* equal (string)\n* match: (regex)\n* notEmpty (bool)\n\n## email\n\n* minLength (int)\n* maxLength (int)\n* equal (string)\n* match: (regex)\n* notEmpty (bool)\n* user (`function(user)`)\n* domain (`function(domain)`)\n\n```javascript\n  const emailRule = new Rule({\n    type: 'email',\n    user: user =\u003e user === 'dedede',\n    domain: domain =\u003e ['outlook', 'gmail', 'yahoo'].indexOf(domain) !== -1,\n  }, null);\n\n  emailRule.test('dedede@gmail.fr'); // returns true\n```\n\n## password\n\n* minLength (int)\n* maxLength (int)\n* equal (string)\n* match: (regex)\n* notEmpty (bool)\n* uppercase (int)\n* number (int)\n* mathesOneOf (Array)\n* matchesAllOf (Array)\n\n```javascript\n  const passwordRule = new Rule({\n    type: 'password',\n    minLength: 8,\n    uppercase: 1,\n    numbers: 1,\n    matchesOneOf: ['@', '_', '-', '.', '!'],\n  }, null);\n\n  passwordRule.test('@_-bddcd6A'); // returns true\n```\n\n## url\n\n* minLength (int)\n* maxLength (int)\n* equal (string)\n* match: (regex)\n* notEmpty (bool)\n* protocol (`function(protocol)`)\n* domain (`function(domain)`)\n\n```javascript\n  const urlRule = new Rule({\n    type: 'url',\n    protocol: prot =\u003e prot === 'https',\n    domain: domain =\u003e domain === 'google.fr',\n  }, null);\n\n  urlRule.test('https://google.fr'); // returns true\n```\n\n## date\n\n* after (date)\n* before (date)\n* between (Array of dates like this [date, date])\n* equal (date)\n\n## float\n\n* min (Number)\n* max (Number)\n* equal (float)\n\n## array\n\n* of (Rule or Validator object)\n* notEmpty (bool)\n* length (int)\n\nThe `of` rule checks every element of the array against the rule.\n\n## function\n\n* result\n\nTo explain result, what's better than an example:\n\n```javascript\n  const { Validator, Rule } = require('@cesium133/forgjs');\n\n  function someFunctionThatReturnsAnInt(int) {\n    return int * 5;\n  }\n\n  const functionTest = new Rule({\n    type: 'function',\n    result: {\n      of: 5,\n      toBe: new Rule('int'),\n    },\n  }, null);\n\n  functionTest.test(someFunctionThatReturnsAnInt); /// returns true;\n\n  ```\n## string-int, string-float, string-date, string-boolean\n\nThese types 'inherit' from string, they have both the properties, here are some examples:\n\n### string-int\n\n```javascript\nconst stringInt = new Rule({\n  type: 'string-int',\n  minLength: 2,\n  min: 5,\n}, null);\n\nstringInt.test(2) // returns false 2 is not a string\nstringInt.test('2a') // returns false '2a' is not a int\nstringInt.test('2.1') // returns false '2.1' is not a int\nstringInt.test('5') // returns false length of '5' is smaller than 2\nstringInt.test('50') // returns true\n```\n### string-boolean\n\n```javascript\nconst stringBoolean = new Rule({\n  type: 'string-boolean',\n  toBe: true\n}, null);\n\nstringBoolean.test(true) // returns false true is not a boolean\nstringBoolean.test('false') // returns false 'false' is not true\nstringBoolean.test('true') // returns true\n\n```\n\n```javascript\nconst stringDate = new Rule({\n  type: 'string-date',\n  after: new Date(2019, 11, 1),\n}, null);\n\nstringDate.test(new Date(2018, 11, 1)) // returns false new Date(2018, 11, 1) is not a string\nstringDate.test('some string') // returns false 'some string' is not a valid date\nstringDate.test('2018-12-17') // returns false '2018-12-17' is not after new Date(2019, 11, 1)\nstringDate.test('2020-01-01') // returns true\n```\n\n**Forgjs tries to cast the value to the right type before passing it to the validation function please be careful!**\n\nHere is an example where Javascript behaviour makes the test wrong:\n\n```javascript\nconst stringDate = new Rule({\n  type: 'string-date',\n  equal: new Date(2019, 10, 1), // month in js strart at 0\n}, null);\n\nstringDate.test('2019-11-01') // returns false\nstringDate.test('2019-11-01T00:00') // returns true\n\n\n// this is because:\n\nnew Date(2019, 10, 1) - new Date('2019-11-01') // equals  3600000 thats exactly 1 hour\n\nnew Date(2019, 10, 1) - new Date('2019-11-01T00:00') // equals 0\n\n```\n\n## Multiple types\n\nYou can check for multiple types with `OR` or `AND` operators like this:\n\n```javascript\n  const intRule = new Rule({\n    type: 'int|float|number',\n  }, null);\n\n  intRule.test(2) // returns true\n```\n\nThis means the test should verify the `int`, `float` or `number` rule\n\n```javascript\n  const intRule = new Rule({\n    type: 'int\u0026number',\n  }, null);\n  intRule.test(2.1); // returns false\n```\n\nThe result doesn't match the `int` rule\n\n## Common properties\n\nEvery type has these properties:\n\n* optional\n* custom\n* oneOf\n\n### optional\n\nIf optional is set to `true` the element is optional and an `undefined` value is considered correct.\nExample:\n\n```javascript\nconst { Validator, Rule } = require('@cesium133/forgjs');\n\nconst intRule = new Rule({\n    type: 'int',\n    optional: true,\n  }, null);\nintRule.test(); // returns true\n```\n\n### custom\n\nCustom allows you to write your own rule, an example is better than a long explanation:\n\n```javascript\n  const { Validator, Rule } = require('@cesium133/forgjs');\n  \n  function isCorrectAge(age, object) {\n    if (age === Math.floor((new Date() - object.dateOfBirth) / 1000 / 60 / 60 / 24 / 30 / 12)) {\n      return true;\n    }\n    return false;\n  }\n  const vComplexe = new Validator({\n    age: new Rule({\n      type: 'int', min: 18, max: 99, custom: isCorrectAge,\n    }),\n    dateOfBirth: new Rule({ type: 'date' }),\n  });\n\n  vComplexe.test({\n    age: 23,\n    dateOfBirth: new Date(1995, 10, 3),\n    array: ['1'],\n  }); // returns true\n\n```\n### oneOf\n\nOne of checks if the element is in a array\n```javascript\n  const floatRule = new Rule({\n    type: 'float',\n    oneOf: [3.5, 100.1, 7.2, 0.1],\n  }, null);\n  floatRule.test(100.1); // returns true\n```\n\n# Make a new type\n\nCreating a new type is done using the Rule class like this:\n\n```javascript\n  const { Validator, Rule } = require('@cesium133/forgjs'); \n  \n  Rule.addCustom('customInteger', {\n    min: (val, min) =\u003e val - min \u003e 0,\n    max: (val, max) =\u003e val - max \u003c 0,\n    equal: (val, equal) =\u003e val === equal,\n    type: val =\u003e Number.isInteger(val) \u0026\u0026 val \u003e 0 \u0026\u0026 val \u003c 100,\n  });\n\n  const customInteger = new Rule({\n    type: 'customInteger',\n    min: 10,\n  }, null);\n\n  customInteger.test(11) // returns true\n\n  customInteger.test(200) // returns false\n\n```\n\n# How to contribute\n\nThank 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.\nRules:\n\n### 1 Please use this template which will help developers to test and better understand your request\n\n```javascript\nconst someRule= new Rule({\n    type: 'yourType',\n    prop1: val1,\n    prop2: val2, ...\n  }, null);\n\n  someRule.test(validValue) // returns true\n  someRule.test(invalidValue) // returns false\n```\n\n## 2 Please if you think a comment is a good feature to be added like the comment instead of creating a new one.\n\n## 3 Before submitting a new comment check if the same comment is not already present\n\n## 4 If you submit a PR (pull request) and you only change the Readme please add `[ci skip]` to your commit message\n\n## 5 If you have any questions ask them in the FAQ\n\n## 6 Please have fun, and if you feel like not following the rules then don't follow them\n\ncode with love ❤️\n\n# Left TO DO for next release\n\n# Contact\n\nFollow me on twitter at [@forg_js](https://twitter.com/forg_js \"@forg_js\")\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foussamahamdaoui%2FforgJs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foussamahamdaoui%2FforgJs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foussamahamdaoui%2FforgJs/lists"}