check-rule-mate 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +210 -0
- package/package.json +21 -0
- package/src/js/dataValidate.js +119 -0
- package/src/main.js +5 -0
- package/src/types.js +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# check-rule-mate
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
A lightweight and reusable JavaScript "library" for data validation. This library was esigned to simplify the process of validating form inputs using flexible rules and error handling. Validating your data by allowing you to define flexible rules, custom error messages, and reusable helper functions—all in a structured format.
|
|
6
|
+
|
|
7
|
+
The core goal is to provide a **reusable and easy-to-extend** for handling various form inputs, including fields like name, email, birthdate, phone number, and more.
|
|
8
|
+
|
|
9
|
+
Test the core functionalities here: [check-rule-mate Demo](https://johnrock16.github.io/check-rule-mate/)
|
|
10
|
+
(Note: Creating or modifying custom validators is not supported in the demo, as it requires JavaScript implementation.)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **Custom Validation Rules**: Easily define custom rules for form fields.
|
|
16
|
+
- **Modular Design**: Separation of rule definitions and error messages for easy management.
|
|
17
|
+
- **Easy Integration**: Can be used in any JavaScript environment.
|
|
18
|
+
- **Clear Error Handling**: Handles errors and displays messages.
|
|
19
|
+
- **Extendable**: Create your custom validators and rules and extend as you want.
|
|
20
|
+
|
|
21
|
+
## Advanced Features
|
|
22
|
+
|
|
23
|
+
- **Modifiers:** Extend rules for specific use cases (e.g., age validation in a date rule).
|
|
24
|
+
- **Dynamic Parameters:** Use $variable to access field data within rules.
|
|
25
|
+
- **Modular Rules and Validators:** Create multiple files for rules and helpers, organizing them by context or form.
|
|
26
|
+
|
|
27
|
+
## Table of Contents
|
|
28
|
+
|
|
29
|
+
- [Getting Started](#Getting-Started)
|
|
30
|
+
- [Installation](#Installation)
|
|
31
|
+
- [Running Tests](#Running-Tests)
|
|
32
|
+
- [How It Works](#How-It-Works)
|
|
33
|
+
- [Basic Example](#Basic-Example)
|
|
34
|
+
- [Defining Validation Components](#Defining-Validation-Components)
|
|
35
|
+
- [1. Data Rules](#Data-Rules)
|
|
36
|
+
- [2. General Rules](#General-Rules)
|
|
37
|
+
- [3. Validation Helpers](#Validation-Helpers)
|
|
38
|
+
- [4. Error Messages](#Error-Messages)
|
|
39
|
+
- [5. Example Usage](#Example-Usage)
|
|
40
|
+
- [Vanilla](#vanilla)
|
|
41
|
+
- [Express](#express)
|
|
42
|
+
- [Frontend](#frontend)
|
|
43
|
+
|
|
44
|
+
## Getting Started
|
|
45
|
+
### Installation
|
|
46
|
+
|
|
47
|
+
To install and start the library, run:
|
|
48
|
+
```bash
|
|
49
|
+
npm install
|
|
50
|
+
npm start
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Running Tests
|
|
54
|
+
|
|
55
|
+
Execute the test suite with:
|
|
56
|
+
```bash
|
|
57
|
+
npm test
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## How It Works
|
|
61
|
+
### Basic Example
|
|
62
|
+
|
|
63
|
+
Here’s an example of validating a set of fields:
|
|
64
|
+
```javascript
|
|
65
|
+
const { myValidator } = require('./dataValidator/validators');
|
|
66
|
+
const { dataValidate } = require('./dataValidator/dataValidate');
|
|
67
|
+
const MY_RULES = require('./dataValidator/rules/validators/myValidatorRules.json');
|
|
68
|
+
const CONTACT_US = require('./dataValidator/rules/data/contactUs.json');
|
|
69
|
+
const MY_VALIDATION_ERROR_MESSAGES = require('./i18n/en_US/errors/myValidatorRules.json');
|
|
70
|
+
|
|
71
|
+
const fields = {
|
|
72
|
+
name: "John",
|
|
73
|
+
lastName: "Doe",
|
|
74
|
+
email: "email@email.com",
|
|
75
|
+
emailConfirm: "email@email.com",
|
|
76
|
+
phone: "",
|
|
77
|
+
subject: "I need a coffee",
|
|
78
|
+
message: "Give me coffee"
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// This should return { ok: true }
|
|
82
|
+
const result = dataValidate(fields, {
|
|
83
|
+
validationHelpers: myValidator,
|
|
84
|
+
rules: MY_RULES,
|
|
85
|
+
dataRule: CONTACT_US,
|
|
86
|
+
dataErrorMessages: MY_VALIDATION_ERROR_MESSAGES,
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
#### Parameters for dataValidate:
|
|
91
|
+
|
|
92
|
+
- **fields**: The object containing data to be validated.
|
|
93
|
+
- **validationHelpers**: Functions to validate field data (see /dataValidator/validators).
|
|
94
|
+
- **rules**: General validation rules for your application.
|
|
95
|
+
- **dataRule**: Specific rules linking fields to validation logic.
|
|
96
|
+
- **dataErrorMessages**: Custom error messages returned upon validation failure.
|
|
97
|
+
|
|
98
|
+
## Defining Validation Components
|
|
99
|
+
|
|
100
|
+
### Data Rules
|
|
101
|
+
|
|
102
|
+
Define rules for specific datasets, such as forms. Example for a "Contact Us" form:
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"name": { "rule": "name", "required": true },
|
|
106
|
+
"lastName": { "rule": "name", "required": true },
|
|
107
|
+
"email": { "rule": "email", "required": true },
|
|
108
|
+
"emailConfirm": { "rule": "email--confirm", "required": true },
|
|
109
|
+
"phone": { "rule": "phone", "required": false },
|
|
110
|
+
"subject": { "rule": "hasText", "required": true },
|
|
111
|
+
"message": { "rule": "hasText", "required": true }
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### General Rules
|
|
116
|
+
|
|
117
|
+
Define reusable validation logic. Example:
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{
|
|
121
|
+
"name": {
|
|
122
|
+
"validate": ["hasText"],
|
|
123
|
+
"error": { "hasText": "common.hasText" }
|
|
124
|
+
},
|
|
125
|
+
"email": {
|
|
126
|
+
"regex": "/^[a-z0-9.]+@[a-z0-9]+\\.[a-z]+(\\.[a-z]+)?$/i",
|
|
127
|
+
"validate": ["regex"],
|
|
128
|
+
"error": { "regex": "email.regex" },
|
|
129
|
+
"modifier": {
|
|
130
|
+
"confirm": {
|
|
131
|
+
"validate": ["regex", "equals"],
|
|
132
|
+
"params": { "equals": ["$email"] },
|
|
133
|
+
"error": { "equals": "email.equals" }
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
"date": {
|
|
138
|
+
"regex": "/^\\d{4}[\/\\-](0?[1-9]|1[012])[\/\\-](0?[1-9]|[12][0-9]|3[01])$/",
|
|
139
|
+
"validate": ["regex", "validDate"],
|
|
140
|
+
"error": {
|
|
141
|
+
"regex": "common.dateFormat",
|
|
142
|
+
"validDate": "date.validDate"
|
|
143
|
+
},
|
|
144
|
+
"modifier": {
|
|
145
|
+
"age": {
|
|
146
|
+
"validate": ["regex", "validateAge"],
|
|
147
|
+
"params": {
|
|
148
|
+
"validateAge": [18, 130]
|
|
149
|
+
},
|
|
150
|
+
"error": {
|
|
151
|
+
"regex": "common.dateFormat",
|
|
152
|
+
"validateAge": "date.modifier.age.validateAge"
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
#### Key Components:
|
|
160
|
+
|
|
161
|
+
- **validate**: Array of functions to execute for validation.
|
|
162
|
+
- **error**: Error messages for validation failures.
|
|
163
|
+
- **regex**: Regular expression for validation.
|
|
164
|
+
- **modifier**: Overrides specific rules with additional validations.
|
|
165
|
+
- **params**: Parameters for validation functions (e.g., $email accesses email field data).
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
### Validation Helpers
|
|
169
|
+
Helper functions perform actual validation. Example:
|
|
170
|
+
|
|
171
|
+
```javascript
|
|
172
|
+
const myValidator = function (value, rule, modifier = null, data = null) {
|
|
173
|
+
function regex() {
|
|
174
|
+
const regexTemplate = rule.modifier?.[modifier]?.regex || rule.regex;
|
|
175
|
+
const regex = new RegExp(regexTemplate);
|
|
176
|
+
return regex.test(value);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function hasText() {
|
|
180
|
+
return value.trim().length > 0;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function equals(key) {
|
|
184
|
+
return value === data[key];
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return { regex, hasText, equals };
|
|
188
|
+
};
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Error Messages
|
|
192
|
+
|
|
193
|
+
Define custom error messages in a structured format:
|
|
194
|
+
``` json
|
|
195
|
+
{
|
|
196
|
+
"common": { "hasText": "Please fill out this field." },
|
|
197
|
+
"email": { "regex": "Enter a valid email address." }
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Example Usage
|
|
202
|
+
|
|
203
|
+
Explore examples in the examples folder folder.
|
|
204
|
+
|
|
205
|
+
#### Vanilla
|
|
206
|
+
Here you are free to test anything you want about form validation, also We have a lot of tests scenarios in __tests__ which could be a great start.
|
|
207
|
+
#### Express:
|
|
208
|
+
See how the check-rule-mate works in back-end using a middleware.
|
|
209
|
+
#### Frontend:
|
|
210
|
+
Here you can found the DEMO page and it's a type of "playground" to test how RULES works and validations works. (Here you can't create customized javascript so custom validatorHelpers are disabled by default)
|
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "check-rule-mate",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "./dist/main.cjs.js",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "node ./examples/vanilla/src/index.js",
|
|
9
|
+
"build": "node build",
|
|
10
|
+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
11
|
+
"example:vanilla": "node ./examples/vanilla/src/index.js",
|
|
12
|
+
"example:express": "node ./examples/express/src/main.js"
|
|
13
|
+
},
|
|
14
|
+
"author": "João Rocha",
|
|
15
|
+
"license": "ISC",
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"esbuild": "^0.24.0",
|
|
18
|
+
"express": "^4.21.2",
|
|
19
|
+
"jest": "^29.7.0"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate your data fields using your rules, data rules and validators.
|
|
3
|
+
* @param {[DataField]} data - All the data fields to be validate
|
|
4
|
+
* @param {DataValidatorConfigs} config - The configs which will be followed during validation
|
|
5
|
+
* @returns {DataValidatorSuccessResponse | DataValidatorErrorResponse} - The response of your validation
|
|
6
|
+
*/
|
|
7
|
+
export function dataValidate(data, {validationHelpers = {}, rules, dataRule, dataErrorMessages = {}}) {
|
|
8
|
+
const dataErrors = {};
|
|
9
|
+
|
|
10
|
+
function getObjectValueByPath(obj, path) {
|
|
11
|
+
if (!obj || typeof path !== 'string') return undefined;
|
|
12
|
+
|
|
13
|
+
const keys = path.split('.');
|
|
14
|
+
let current = obj;
|
|
15
|
+
|
|
16
|
+
for (const key of keys) {
|
|
17
|
+
if (current[key] === undefined) return undefined;
|
|
18
|
+
current = current[key];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return current;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function inputValidation(dataAttribute, data = null) {
|
|
25
|
+
const { rule, required } = dataRule[dataAttribute.key];
|
|
26
|
+
|
|
27
|
+
if ((rule && required) || (!required && dataAttribute.value != '')) {
|
|
28
|
+
if (rule) {
|
|
29
|
+
const INPUT_RULE = rule.split('--')[0];
|
|
30
|
+
const RULE_MODIFIER = rule.split('--').length > 1 ? rule.split('--')[1] : '';
|
|
31
|
+
const dataAttributeValidation = dataAttributeValidator(dataAttribute.value, rules[INPUT_RULE], RULE_MODIFIER, validationHelpers, data);
|
|
32
|
+
const { isValid, errorMessage, errorType } = dataAttributeValidation.validate();
|
|
33
|
+
if (!isValid) {
|
|
34
|
+
dataErrors[dataAttribute.key] = {
|
|
35
|
+
name: dataAttribute.key,
|
|
36
|
+
error: true,
|
|
37
|
+
errorMessage: getObjectValueByPath(dataErrorMessages, errorMessage) || errorMessage,
|
|
38
|
+
errorType: errorType
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return isValid;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function validate() {
|
|
48
|
+
let dataArr = Object.keys(data).map((key) => ({ key, value: data[key] }));
|
|
49
|
+
if (dataArr && dataArr.length > 0) {
|
|
50
|
+
if(!Object.keys(dataRule).every((key) => data.hasOwnProperty(key))) {
|
|
51
|
+
return { error: true, errorMessage: "Missing properties"}
|
|
52
|
+
}
|
|
53
|
+
const dataValidators = [...dataArr].map((input) => inputValidation(input, data));
|
|
54
|
+
|
|
55
|
+
if (dataValidators.some((element) => !element)) {
|
|
56
|
+
return { error: true, dataErrors: dataErrors };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const dataRuleArr = Object.keys(dataRule).map((key) => ({ key, required: dataRule[key].required}));
|
|
60
|
+
const dataAttributesKey = dataArr.map((attribute) => attribute.key);
|
|
61
|
+
const dataAttributesRequired = dataRuleArr.filter((rule) => rule.required).map((rule) => rule.key);
|
|
62
|
+
|
|
63
|
+
if (!dataAttributesRequired.every((fieldRequired) => dataAttributesKey.includes(fieldRequired))) {
|
|
64
|
+
return { error: true };
|
|
65
|
+
}
|
|
66
|
+
} else if (!dataArr || dataArr.length === 0) {
|
|
67
|
+
return { error: true, errorMessage: "Missing fields for dataRules"}
|
|
68
|
+
}
|
|
69
|
+
return { ok: true };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return validate();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* A function to validate each attribute from a object [dataField]
|
|
77
|
+
* @param {string} value - The value to be validated
|
|
78
|
+
* @param {string} rule - The rule to be used during validation
|
|
79
|
+
* @param {string} modifier - The modifier of the rule if have
|
|
80
|
+
* @param {Function} customValidation - The function which will validate the value
|
|
81
|
+
* @param {[DataField]} data - The entire data fields
|
|
82
|
+
* @returns {{validate: Function}} the built function to validate all this parameters
|
|
83
|
+
*/
|
|
84
|
+
function dataAttributeValidator (value, rule, modifier = null, customValidation = null, data = null) {
|
|
85
|
+
function validateRules(rule) {
|
|
86
|
+
let errorMessage;
|
|
87
|
+
let errorType;
|
|
88
|
+
const isValid = !rule.validate.some((validation) => {
|
|
89
|
+
let isInvalid = true;
|
|
90
|
+
if ((rule.params && rule.params[validation] && rule.params[validation].length > 0)) {
|
|
91
|
+
const params = rule.params[validation].map((param) => (typeof param === 'string' && param[0] === '$') ? param.substring(1, param.length) : param);
|
|
92
|
+
isInvalid = !this[validation](...params)
|
|
93
|
+
} else {
|
|
94
|
+
isInvalid = !this[validation]()
|
|
95
|
+
}
|
|
96
|
+
if (isInvalid && !errorMessage && rule?.error[validation]) {
|
|
97
|
+
errorMessage = rule.error[validation];
|
|
98
|
+
errorType = validation;
|
|
99
|
+
}
|
|
100
|
+
return isInvalid;
|
|
101
|
+
});
|
|
102
|
+
return {isValid, errorMessage, errorType}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function validate() {
|
|
106
|
+
if (customValidation && typeof customValidation === 'function') {
|
|
107
|
+
const validation = customValidation(value, rule, modifier, data);
|
|
108
|
+
Object.keys(validation).forEach((key) => {
|
|
109
|
+
this[key] = validation[key];
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return modifier ? validateRules.call(this, rule.modifier[modifier]) : validateRules.call(this, rule);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return({
|
|
117
|
+
validate
|
|
118
|
+
});
|
|
119
|
+
}
|
package/src/main.js
ADDED
package/src/types.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module typedefs
|
|
3
|
+
* This file contains all typedefs used in the project.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {Object} DataField
|
|
8
|
+
* @property {string} name - The name and key of the field
|
|
9
|
+
* @property {string} value - the value of the field
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {Object} DataValidatorConfigs
|
|
14
|
+
* @property {ValidationHelpers} validationHelpers - The validator functions to help your validations
|
|
15
|
+
* @property {Object} rules - The rules you want to use through validation
|
|
16
|
+
* @property {dataRule} dataRule - The rules you want to use per field
|
|
17
|
+
* @property {Object} dataErrorMessages - The error messages you want to show during errors
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {Function} ValidatorHelper
|
|
22
|
+
* @param {any} value - The value to be validate
|
|
23
|
+
* @param {string} rule - The rules to be followed during validation
|
|
24
|
+
* @param {string} modifier - If rule has a modifier applied
|
|
25
|
+
* @param {[DataField]} data - The data fields object
|
|
26
|
+
* @returns {boolean} The validation result of the value
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {Object.<string, ValidatorHelper>} ValidationHelpers
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @typedef {Object} DataRule
|
|
35
|
+
* @property {dataRuleFiVeld} field - The field which will use the rule
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @typedef {Object} DataRuleField
|
|
40
|
+
* @property {string} rule - The validation rule for the field (e.g., "name", "email", "phone", "hasText").
|
|
41
|
+
* @property {boolean} required - Indicates whether the field is required.
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @typedef {Object.<string, DataRule>} DataRule - A dynamic object where the keys are field names and the values define the field rules.
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Represents a successful response.
|
|
50
|
+
*
|
|
51
|
+
* @typedef {Object} DataValidatorSuccessResponse
|
|
52
|
+
* @property {boolean} ok - Indicates the operation was successful.
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Represents an error response.
|
|
57
|
+
*
|
|
58
|
+
* @typedef {Object} DataValidatorErrorResponse
|
|
59
|
+
* @property {boolean} error - Indicates an error occurred.
|
|
60
|
+
* @property {string} [errorMessage] - A message describing the error (optional).
|
|
61
|
+
* @property {Object} [dataErrors] - Additional error details (optional).
|
|
62
|
+
*/
|