check-rule-mate 0.4.3 → 0.5.0

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 CHANGED
@@ -1,11 +1,18 @@
1
1
  # check-rule-mate
2
- Validate any type of data in JS using your own rules and validations.
2
+ Rule-based, extensible and async-friendly data validation engine for complex forms and business rules.
3
3
 
4
4
  ## Overview
5
5
 
6
- A lightweight and reusable JavaScript "library" for data validation. This library was designed 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
+ **check-rule-mate** is a lightweight **rule-driven validation engine** for JavaScript.
7
+ Instead of coupling validation logic directly to schemas or fields, check-rule-mate separates concerns into **rules**, **schemas**, **validators**, and **error messages**, allowing you to build **highly reusable**, **composable**, and **context-aware validations**.
7
8
 
8
- 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.
9
+ It is designed for scenarios where traditional schema-based validators start to feel limiting, especially when you need:
10
+
11
+ - Cross-field validation
12
+ - Contextual rules
13
+ - Async checks
14
+ - Reusable validation logic across multiple forms
15
+ - Full control over execution flow and error handling
9
16
 
10
17
 
11
18
  **Github repository:** [check-rule-mate repository](https://github.com/johnrock16/check-rule-mate)
@@ -15,49 +22,76 @@ The core goal is to provide a **reusable and easy-to-extend** for handling vario
15
22
  **Test the core functionalities here:** [check-rule-mate demo](https://johnrock16.github.io/check-rule-mate/)
16
23
  (Note: Creating or modifying custom validators is not supported in the demo, as it requires JavaScript implementation.)
17
24
 
25
+ ## Why check-rule-mate?
18
26
 
19
- ## Features
27
+ Use **check-rule-mate** if you:
28
+ - Need reusable validation logic across different forms and contexts
29
+ - Have complex or conditional validation rules
30
+ - Want full control over how validation runs
31
+ - Need async validations (API calls, database checks, etc.)
32
+ - Prefer rule-driven validation instead of tightly coupled schemas
33
+ - Want clean separation between rules, data, and messages
34
+
35
+
36
+ ## Core Concepts
20
37
 
21
- - **Custom Validation Rules**: Easily define custom rules for form fields.
22
- - **Modular Design**: Separation of rule definitions and error messages for easy management.
23
- - **Easy Integration**: Can be used in any JavaScript environment.
24
- - **Clear Error Handling**: Handles errors and displays messages.
25
- - **Extendable**: Create your custom validators and rules and extend as you want.
38
+ check-rule-mate is built around four main concepts:
26
39
 
27
- ## Advanced Features
40
+ 1. **Rules**: How data is validated
41
+ 2. **Schema**: What should be validated
42
+ 3. **Validation Helpers**: How rules are executed
43
+ 4. **Error Messages**: How errors are communicated
28
44
 
29
- - **Modifiers:** Extend rules for specific use cases (e.g., age validation in a date rule).
30
- - **Dynamic Parameters:** Use $variable to access field data within rules.
31
- - **Modular Rules and Validators:** Create multiple files for rules and helpers, organizing them by context or form.
32
- - **Async Validations:** You could create async functions to validate some data. Do You need to use a fetch or wait a promise to be resolved? No problems.
45
+ This separation makes the system flexible, scalable, and easy to maintain.
46
+
47
+ ## Features
48
+
49
+ - Rule-based validation engine
50
+ - Reusable validation rules
51
+ - Modifiers for contextual rule extensions
52
+ - Cross-field validation using dynamic parameters
53
+ - Async validation support
54
+ - Abort early or collect all errors
55
+ - Strict or loose schema matching
56
+ - i18n-ready error messages
57
+ - Framework-agnostic (frontend or backend)
33
58
 
34
59
  ## Table of Contents
35
60
 
36
61
  - [Getting Started](#Getting-Started)
37
- - [Installation](#Installation)
62
+ - [NPM - Installation](#Installation)
63
+ - [Repository - Installation](#Repository---Installation)
38
64
  - [Running Tests](#Running-Tests)
39
65
  - [How It Works](#How-It-Works)
40
66
  - [Basic Example](#Basic-Example)
41
- - [Defining Validation Components](#Defining-Validation-Components)
42
- - [1. Data Rules](#Data-Rules)
43
- - [2. General Rules](#General-Rules)
44
- - [3. Validation Helpers](#Validation-Helpers)
67
+ - [Defining Validation](#Defining-Validation)
68
+ - [1. Schema](#Defining-a-Schema-What-to-validate)
69
+ - [2. Rules](#Defining-Rules-How-to-validate)
70
+ - [3. Validation Helpers](#Validation-Helpers-Execution-Layer)
45
71
  - [4. Error Messages](#Error-Messages)
46
72
  - [5. Example Usage](#Example-Usage)
47
73
  - [Vanilla](#vanilla)
48
74
  - [Express](#express)
49
75
  - [Frontend](#frontend)
76
+ - [When NOT to use check-rule-mate](#When-NOT-to-use-check-rule-mate)
77
+ - [License](#License);
50
78
 
51
79
  ## Getting Started
80
+
52
81
  ### Installation
82
+ If you are in NPM use this:
83
+ ```bash
84
+ npm install check-rule-mate
85
+ ```
53
86
 
54
- To install and start the library, run:
87
+ ### Repository - Installation
88
+ If you downloaded the repository you can install using:
55
89
  ```bash
56
90
  npm install
57
91
  npm start
58
92
  ```
59
93
 
60
- ### Running Tests
94
+ ### Repository - Running Tests
61
95
 
62
96
  Execute the test suite with:
63
97
  ```bash
@@ -65,69 +99,102 @@ npm test
65
99
  ```
66
100
 
67
101
  ## How It Works
68
- ### Basic Example
102
+ ### Basic Usage
69
103
 
70
- Here’s an example of validating a set of fields:
71
104
  ```javascript
72
- const { myValidator } = require('./dataValidator/validators');
73
- const { dataValidate } = require('./dataValidator/dataValidate');
74
- const MY_RULES = require('./dataValidator/rules/validators/myValidatorRules.json');
75
- const CONTACT_US = require('./dataValidator/rules/data/contactUs.json');
76
- const MY_VALIDATION_ERROR_MESSAGES = require('./i18n/en_US/errors/myValidatorRules.json');
77
-
78
- async function runDataValidate() {
79
- const fields = {
80
- name: "John",
81
- lastName: "Doe",
82
- email: "email@email.com",
83
- emailConfirm: "email@email.com",
84
- phone: "",
85
- subject: "I need a coffee",
86
- message: "Give me coffee"
87
- };
88
-
89
- // This should return { ok: true }
90
- const result = await dataValidate(fields, {
91
- validationHelpers: myValidator,
92
- rules: MY_RULES,
93
- dataRule: CONTACT_US,
94
- dataErrorMessages: MY_VALIDATION_ERROR_MESSAGES,
95
- });
96
-
97
- console.log(result);
98
- }
105
+ import MY_RULES from './rules/myValidatorRules.json' with { type: 'json' };
106
+ import CONTACT_US from './schemas/contactUs.json' with { type: 'json' };
107
+ import ERROR_MESSAGES from './i18n/en_US/errors.json' with { type: 'json' };
108
+
109
+ import { createValidator } from 'check-rule-mate';
110
+ import { myValidator } from './validators/myValidator.js';
111
+
112
+ const fields = {
113
+ name: 'John',
114
+ lastName: 'Doe',
115
+ email: 'email@email.com',
116
+ emailConfirm: 'email@email.com',
117
+ phone: '',
118
+ subject: 'I need a coffee',
119
+ message: 'Give me coffee'
120
+ };
121
+
122
+ async function runFormValidate() {
123
+ const validator = createValidator(fields, {
124
+ validationHelpers: myValidator,
125
+ rules: MY_RULES,
126
+ schema: CONTACT_US,
127
+ errorMessages: ERROR_MESSAGES,
128
+ options: {
129
+ abortEarly: false,
130
+ propertiesMustMatch: true
131
+ }
132
+ });
133
+
134
+ const result = await validator.validate();
99
135
 
100
- runDataValidate();
136
+ // This should return { ok: true }
137
+ console.log(result);
138
+ }
139
+
140
+ runFormValidate();
101
141
  ```
102
142
 
103
- #### Parameters for dataValidate:
143
+ ### Validation Result
144
+ A validation result follows this structure:
104
145
 
105
- - **fields**: The object containing data to be validated.
106
- - **validationHelpers**: Functions to validate field data (see /dataValidator/validators).
107
- - **rules**: General validation rules for your application.
108
- - **dataRule**: Specific rules linking fields to validation logic.
109
- - **dataErrorMessages**: Custom error messages returned upon validation failure.
146
+ When is **valid**:
147
+ ```javascript
148
+ { ok: true }
149
+ ```
110
150
 
111
- ## Defining Validation Components
151
+ When is **invalid** and **has errors**:
152
+ ```javascript
153
+ {
154
+ error: true;
155
+ errors: {
156
+ [field: string]: {
157
+ type: string;
158
+ message: string;
159
+ }[];
160
+ };
161
+ }
162
+ ```
112
163
 
113
- ### Data Rules
114
164
 
115
- Define rules for specific datasets, such as forms. Example for a "Contact Us" form:
165
+ ## Defining Validation
166
+
167
+ ### Defining a Schema (What to validate)
168
+
169
+ Schemas map **data fields** to **rules**.
116
170
  ```json
117
171
  {
118
- "name": { "rule": "name", "required": true },
119
- "lastName": { "rule": "name", "required": true },
120
- "email": { "rule": "email", "required": true },
121
- "emailConfirm": { "rule": "email--confirm", "required": true },
122
- "phone": { "rule": "phone", "required": false },
123
- "subject": { "rule": "hasText", "required": true },
124
- "message": { "rule": "hasText", "required": true }
172
+ "name": {
173
+ "rule": "name",
174
+ "required": true
175
+ },
176
+ "email": {
177
+ "rule": "email",
178
+ "required": true
179
+ },
180
+ "emailConfirm": {
181
+ "rule": "email--confirm",
182
+ "required": true
183
+ },
184
+ "phone": {
185
+ "rule": "phone",
186
+ "required": false
187
+ }
125
188
  }
126
189
  ```
127
190
 
128
- ### General Rules
191
+ #### Schema Properties
192
+ - **rule**: Rule name (supports modifiers via `rule--modifier`)
193
+ - **required**: Whether the field must exist and not be empty
194
+
195
+ ### Defining Rules (How to validate)
129
196
 
130
- Define reusable validation logic. Example:
197
+ Rules define validation logic, independent of any specific form.
131
198
 
132
199
  ```json
133
200
  {
@@ -169,17 +236,53 @@ Define reusable validation logic. Example:
169
236
  }
170
237
  }
171
238
  ```
172
- #### Key Components:
173
239
 
174
- - **validate**: Array of functions to execute for validation.
175
- - **error**: Error messages for validation failures.
176
- - **regex**: Regular expression for validation.
177
- - **modifier**: Overrides specific rules with additional validations.
178
- - **params**: Parameters for validation functions (e.g., $email accesses email field data).
240
+ #### Rule Properties
241
+
242
+ - **validate**: Ordered list of validation functions
243
+ - **regex**: Optional regex used by the regex helper
244
+ - **error**: Error keys mapped to validation functions
245
+ - **modifier**: Contextual rule extensions
246
+ - **params**: Parameters passed to validation helpers
247
+
248
+ #### Modifiers (Contextual Rules)
249
+ Modifiers allow extending a rule **without duplicating logic**.
250
+
251
+ Example:
252
+ ```json
253
+ "email--confirm"
254
+ ```
255
+
256
+ Internally:
179
257
 
258
+ - Base rule: email
259
+ - Modifier: confirm
180
260
 
181
- ### Validation Helpers
182
- Helper functions perform actual validation. Example:
261
+ Modifiers can override:
262
+
263
+ - validate
264
+ - params
265
+ - regex
266
+ - error
267
+
268
+ This makes rules highly reusable and expressive.
269
+
270
+ #### Dynamic Parameters ($field)
271
+ Rules can reference other fields dynamically:
272
+
273
+ ```json
274
+ "params": {
275
+ "equals": ["$email"]
276
+ }
277
+ ```
278
+
279
+ At runtime:
280
+ - `$email` resolves to `data.email`
281
+ - Enables **cross-field validation**
282
+
283
+
284
+ ### Validation Helpers (Execution Layer)
285
+ Validation helpers are the **runtime implementation** of rules.
183
286
 
184
287
  ```javascript
185
288
  const myValidator = function (value, rule, modifier = null, data = null) {
@@ -219,13 +322,36 @@ const myValidator = function (value, rule, modifier = null, data = null) {
219
322
  };
220
323
  ```
221
324
 
222
- ### Error Messages
325
+ #### Helper Signature
326
+ ```typescript
327
+ (value, rule, modifier?, data?) => Record<string, Function>
328
+ ```
223
329
 
224
- Define custom error messages in a structured format:
330
+ Helpers:
331
+ - Can be **sync or async**
332
+ - Are **stateless**
333
+ - Do not know about schemas or error messages
334
+
335
+ ### Error Messages (i18n-ready)
336
+ Errors are resolved via keys, not hardcoded strings.
225
337
  ``` json
226
338
  {
227
- "common": { "hasText": "Please fill out this field." },
228
- "email": { "regex": "Enter a valid email address." }
339
+ "common": {
340
+ "hasText": "Please fill the field"
341
+ },
342
+ "email": {
343
+ "regex": "Please enter a valid email",
344
+ "equals": "Emails do not match"
345
+ }
346
+ }
347
+ ```
348
+ This makes localization and message customization straightforward.
349
+
350
+ ### Validation Options
351
+ ```typescript
352
+ options: {
353
+ abortEarly?: boolean; // Stop on first error
354
+ propertiesMustMatch?: boolean; // Schema vs data strictness
229
355
  }
230
356
  ```
231
357
 
@@ -270,3 +396,12 @@ npm run example:express
270
396
  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)
271
397
 
272
398
  **Frontend example:** [check-rule-mate demo.](https://johnrock16.github.io/check-rule-mate/)
399
+
400
+
401
+ ## When NOT to use check-rule-mate
402
+ - Simple one-off forms
403
+ - Basic required-only validation
404
+ - When schema-based validation is enough
405
+
406
+ ## License
407
+ - ISC
package/dist/main.cjs.js CHANGED
@@ -1 +1 @@
1
- var h=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var M=Object.prototype.hasOwnProperty;var O=(n,s)=>{for(var o in s)h(n,o,{get:s[o],enumerable:!0})},b=(n,s,o,i)=>{if(s&&typeof s=="object"||typeof s=="function")for(let u of R(s))!M.call(n,u)&&u!==o&&h(n,u,{get:()=>s[u],enumerable:!(i=w(s,u))||i.enumerable});return n};var q=n=>b(h({},"__esModule",{value:!0}),n);var P={};O(P,{dataValidate:()=>V});module.exports=q(P);function V(n,{validationHelpers:s={},rules:o,dataRule:i,dataErrorMessages:u={}}){let y={};function g(e,f){if(!e||typeof f!="string")return;let l=f.split("."),t=e;for(let c of l){if(t[c]===void 0)return;t=t[c]}return t}async function a(e,f=null){let{rule:l,required:t}=i[e.key];if((l&&t||!t&&e.value!="")&&l){let c=l.split("--")[0],r=l.split("--").length>1?l.split("--")[1]:"",m=E(e.value,o[c],r,s,f),{isValid:p,errorMessage:v,errorType:k}=await m.validate();return p||(y[e.key]={name:e.key,error:!0,errorMessage:g(u,v)||v,errorType:k}),p}return!0}async function d(){let e=Object.keys(n).map(f=>({key:f,value:n[f]}));if(e&&e.length>0){if(!Object.keys(i).every(r=>n.hasOwnProperty(r)))return{error:!0,errorMessage:"Missing properties"};if((await Promise.all([...e].map(async r=>await a(r,n)))).some(r=>!r))return{error:!0,dataErrors:y};let l=Object.keys(i).map(r=>({key:r,required:i[r].required})),t=e.map(r=>r.key);if(!l.filter(r=>r.required).map(r=>r.key).every(r=>t.includes(r)))return{error:!0}}else if(!e||e.length===0)return{error:!0,errorMessage:"Missing fields for dataRules"};return{ok:!0}}return d()}function E(n,s,o=null,i=null,u=null){async function y(a){let d,e;return{isValid:!(await Promise.all(a.validate.map(async t=>{let c=!0;if(a.params&&a.params[t]&&a.params[t].length>0){let r=a.params[t].map(p=>typeof p=="string"&&p[0]==="$"?p.substring(1,p.length):p);c=await this[t](...r)}else c=await this[t]();return!c&&!d&&(a!=null&&a.error[t])&&(d=a.error[t],e=t),c}))).some(t=>!t),errorMessage:d,errorType:e}}async function g(){if(i&&typeof i=="function"){let d=i(n,s,o,u);Object.keys(d).forEach(e=>{this[e]=d[e]})}return o?await y.call(this,s.modifier[o]):await y.call(this,s)}return{validate:g}}0&&(module.exports={dataValidate});
1
+ var k=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var P=Object.prototype.hasOwnProperty;var j=(u,n)=>{for(var c in n)k(u,c,{get:n[c],enumerable:!0})},I=(u,n,c,i)=>{if(n&&typeof n=="object"||typeof n=="function")for(let f of b(n))!P.call(u,f)&&f!==c&&k(u,f,{get:()=>n[f],enumerable:!(i=E(n,f))||i.enumerable});return u};var T=u=>I(k({},"__esModule",{value:!0}),u);var x={};j(x,{createValidator:()=>V});module.exports=T(x);function V(u,{validationHelpers:n={},rules:c,schema:i,errorMessages:f={},options:y={propertiesMustMatch:!0,abortEarly:!1}}){let p={},r=u,d={all:async e=>Promise.all([...e].map(async s=>await h(s,r))),first:async e=>{let s=[];for(let t of e){let l=await h(t,r);if(s.push(l),!l)return s}return s}};function g(e,s){if(!e||typeof s!="string")return;let t=s.split("."),l=e;for(let M of t){if(l[M]===void 0)return;l=l[M]}return l}async function h(e,s=null){if(i[e.key]){let{rule:t,required:l}=i[e.key];if((t&&l||!l&&e.value!="")&&t){let M=t.split("--")[0],a=t.split("--").length>1?t.split("--")[1]:"",O=U(e.value,c[M],a,n,s),{isValid:R,errorMessage:m,errorType:q}=await O.validate();return R||(p[e.key]={name:e.key,error:!0,errorMessage:g(f,m)||m,errorType:q}),R}}else if(y.propertiesMustMatch)return p[e.key]={name:e.key,error:!0,errorMessage:"Invalid property"},!1;return!0}async function w(e){return await h({key:e,value:r[e]},r)?{ok:!0}:{error:!0,errors:p[e]}}async function o(){p={};let e=Object.keys(r).map(s=>({key:s,value:r[s]}));if(e&&e.length>0){if(!Object.keys(i).every(a=>r.hasOwnProperty(a)))return{error:!0,errorMessage:"Missing properties"};if((y!=null&&y.abortEarly?await d.first(e):await d.all(e)).some(a=>!a))return{error:!0,errors:p};let t=Object.keys(i).map(a=>({key:a,required:i[a].required})),l=e.map(a=>a.key);if(!t.filter(a=>a.required).map(a=>a.key).every(a=>l.includes(a)))return{error:!0}}else if(!e||e.length===0)return{error:!0,errorMessage:"Missing fields for schema"};return{ok:!0}}function v(e){r=e}return{validate:o,validateField:w,setData:v}}function U(u,n,c=null,i=null,f=null){async function y(r){let d,g;return{isValid:!(await Promise.all(r.validate.map(async o=>{let v=!0;if(r.params&&r.params[o]&&r.params[o].length>0){let e=r.params[o].map(t=>typeof t=="string"&&t[0]==="$"?t.substring(1,t.length):t);v=await this[o](...e)}else v=await this[o]();return!v&&!d&&(r!=null&&r.error[o])&&(d=r.error[o],g=o),v}))).some(o=>!o),errorMessage:d,errorType:g}}async function p(){if(i&&typeof i=="function"){let d=i(u,n,c,f);Object.keys(d).forEach(g=>{this[g]=d[g]})}return c?await y.call(this,n.modifier[c]):await y.call(this,n)}return{validate:p}}0&&(module.exports={createValidator});
package/package.json CHANGED
@@ -1,10 +1,21 @@
1
1
  {
2
2
  "name": "check-rule-mate",
3
- "version": "0.4.3",
3
+ "version": "0.5.0",
4
4
  "description": "",
5
5
  "main": "./dist/main.cjs.js",
6
6
  "type": "commonjs",
7
- "keywords": ["data validation", "data validation js", "validator", "validate", "form validator", "form validator js", "form validate", "check-rule-mate", "check rule", "check rule mate"],
7
+ "keywords": [
8
+ "data validation",
9
+ "data validation js",
10
+ "validator",
11
+ "validate",
12
+ "form validator",
13
+ "form validator js",
14
+ "form validate",
15
+ "check-rule-mate",
16
+ "check rule",
17
+ "check rule mate"
18
+ ],
8
19
  "scripts": {
9
20
  "start": "node ./examples/vanilla/src/index.js",
10
21
  "build": "node build",
@@ -15,7 +26,7 @@
15
26
  "author": "João Rocha",
16
27
  "license": "ISC",
17
28
  "devDependencies": {
18
- "esbuild": "^0.24.0",
29
+ "esbuild": "^0.27.2",
19
30
  "express": "^4.21.2",
20
31
  "jest": "^29.7.0"
21
32
  }
@@ -1,11 +1,26 @@
1
1
  /**
2
2
  * Validate your data fields using your rules, data rules and validators.
3
- * @param {[DataField]} data - All the data fields to be validate
3
+ * @param {[DataField]} dataParameter - All the data fields to be validate
4
4
  * @param {DataValidatorConfigs} config - The configs which will be followed during validation
5
- * @returns {DataValidatorSuccessResponse | DataValidatorErrorResponse} - The response of your validation
6
5
  */
7
- export function dataValidate(data, {validationHelpers = {}, rules, dataRule, dataErrorMessages = {}}) {
8
- const dataErrors = {};
6
+ export function createValidator(dataParameter, {validationHelpers = {}, rules, schema, errorMessages = {}, options = { propertiesMustMatch: true, abortEarly: false}}) {
7
+ let errors = {};
8
+ let data = dataParameter;
9
+
10
+ const validateByStrategies = {
11
+ all: async (dataArr) => Promise.all([...dataArr].map(async (input) => await inputValidation(input, data))),
12
+ first: async (dataArr) => {
13
+ const results = []
14
+ for (const input of dataArr) {
15
+ const result = await inputValidation(input, data);
16
+ results.push(result);
17
+ if (!result) {
18
+ return results
19
+ }
20
+ }
21
+ return results;
22
+ }
23
+ };
9
24
 
10
25
  function getObjectValueByPath(obj, path) {
11
26
  if (!obj || typeof path !== 'string') return undefined;
@@ -22,41 +37,67 @@ export function dataValidate(data, {validationHelpers = {}, rules, dataRule, dat
22
37
  }
23
38
 
24
39
  async 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 } = await 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
40
+ if (schema[dataAttribute.key]) {
41
+ const { rule, required } = schema[dataAttribute.key];
42
+ if ((rule && required) || (!required && dataAttribute.value != '')) {
43
+ if (rule) {
44
+ const INPUT_RULE = rule.split('--')[0];
45
+ const RULE_MODIFIER = rule.split('--').length > 1 ? rule.split('--')[1] : '';
46
+ const dataAttributeValidation = dataAttributeValidator(dataAttribute.value, rules[INPUT_RULE], RULE_MODIFIER, validationHelpers, data);
47
+ const { isValid, errorMessage, errorType } = await dataAttributeValidation.validate();
48
+ if (!isValid) {
49
+ errors[dataAttribute.key] = {
50
+ name: dataAttribute.key,
51
+ error: true,
52
+ errorMessage: getObjectValueByPath(errorMessages, errorMessage) || errorMessage,
53
+ errorType: errorType
54
+ }
39
55
  }
56
+ return isValid;
40
57
  }
41
- return isValid;
42
58
  }
59
+ } else if (options.propertiesMustMatch) {
60
+ errors[dataAttribute.key] = {
61
+ name: dataAttribute.key,
62
+ error: true,
63
+ errorMessage: "Invalid property"
64
+ }
65
+ return false;
43
66
  }
44
67
  return true;
45
68
  }
46
69
 
70
+ /**
71
+ * Validate only a field using the attribute key
72
+ * @param {string} key - The field key name you want to validate
73
+ * @returns {DataValidatorSuccessResponse | DataValidatorErrorResponse} - The response of your validation
74
+ */
75
+ async function validateField(key) {
76
+ const result = await inputValidation({key: key, value: data[key]}, data);
77
+ if (!result) {
78
+ return { error: true, errors: errors[key]}
79
+ }
80
+ return { ok: true}
81
+ }
82
+
83
+ /**
84
+ * Validate the entire fields using the schema
85
+ * @returns {DataValidatorSuccessResponse | DataValidatorErrorResponse} - The response of your validation
86
+ */
47
87
  async function validate() {
88
+ errors = {};
48
89
  let dataArr = Object.keys(data).map((key) => ({ key, value: data[key] }));
49
90
  if (dataArr && dataArr.length > 0) {
50
- if(!Object.keys(dataRule).every((key) => data.hasOwnProperty(key))) {
91
+ if(!Object.keys(schema).every((key) => data.hasOwnProperty(key))) {
51
92
  return { error: true, errorMessage: "Missing properties"}
52
93
  }
53
- const dataValidators = await Promise.all([...dataArr].map(async (input) => await inputValidation(input, data)));
94
+ const dataValidators = options?.abortEarly ? await validateByStrategies.first(dataArr) : await validateByStrategies.all(dataArr);
54
95
 
55
96
  if (dataValidators.some((element) => !element)) {
56
- return { error: true, dataErrors: dataErrors };
97
+ return { error: true, errors: errors };
57
98
  }
58
99
 
59
- const dataRuleArr = Object.keys(dataRule).map((key) => ({ key, required: dataRule[key].required}));
100
+ const dataRuleArr = Object.keys(schema).map((key) => ({ key, required: schema[key].required}));
60
101
  const dataAttributesKey = dataArr.map((attribute) => attribute.key);
61
102
  const dataAttributesRequired = dataRuleArr.filter((rule) => rule.required).map((rule) => rule.key);
62
103
 
@@ -64,12 +105,16 @@ export function dataValidate(data, {validationHelpers = {}, rules, dataRule, dat
64
105
  return { error: true };
65
106
  }
66
107
  } else if (!dataArr || dataArr.length === 0) {
67
- return { error: true, errorMessage: "Missing fields for dataRules"}
108
+ return { error: true, errorMessage: "Missing fields for schema"}
68
109
  }
69
110
  return { ok: true };
70
111
  }
71
112
 
72
- return validate();
113
+ function setData(newData) {
114
+ data = newData;
115
+ }
116
+
117
+ return {validate, validateField, setData};
73
118
  }
74
119
 
75
120
  /**
package/src/main.js CHANGED
@@ -1,5 +1,5 @@
1
- import { dataValidate } from './js/dataValidate.js';
1
+ import { createValidator } from './js/dataValidate.js';
2
2
 
3
3
  export {
4
- dataValidate,
4
+ createValidator,
5
5
  }
package/src/types.js CHANGED
@@ -13,8 +13,15 @@
13
13
  * @typedef {Object} DataValidatorConfigs
14
14
  * @property {ValidationHelpers} validationHelpers - The validator functions to help your validations
15
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
16
+ * @property {SchemaRule} schema - The rules you want to use per field
17
+ * @property {Object} errorMessages - The error messages you want to show during errors
18
+ * @property {ValidatorOption} options - Options
19
+ */
20
+
21
+ /**
22
+ * @typedef {Object} ValidatorOption
23
+ * @property {boolean} propertiesMustMatch - If the form fields doesn't match with the expected structure will triggers an error
24
+ * @property {boolean} abortEarly - Stops when caughts the first error
18
25
  */
19
26
 
20
27
  /**
@@ -31,18 +38,18 @@
31
38
  */
32
39
 
33
40
  /**
34
- * @typedef {Object} DataRule
35
- * @property {dataRuleFiVeld} field - The field which will use the rule
41
+ * @typedef {Object} SchemaRule
42
+ * @property {SchemaRuleFiVeld} field - The field which will use the rule
36
43
  */
37
44
 
38
45
  /**
39
- * @typedef {Object} DataRuleField
46
+ * @typedef {Object} SchemaRuleField
40
47
  * @property {string} rule - The validation rule for the field (e.g., "name", "email", "phone", "hasText").
41
48
  * @property {boolean} required - Indicates whether the field is required.
42
49
  */
43
50
 
44
51
  /**
45
- * @typedef {Object.<string, DataRule>} DataRule - A dynamic object where the keys are field names and the values define the field rules.
52
+ * @typedef {Object.<string, SchemaRule>} SchemaRule - A dynamic object where the keys are field names and the values define the field rules.
46
53
  */
47
54
 
48
55
  /**