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 +216 -81
- package/dist/main.cjs.js +1 -1
- package/package.json +14 -3
- package/src/js/dataValidate.js +70 -25
- package/src/main.js +2 -2
- package/src/types.js +13 -6
package/README.md
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
# check-rule-mate
|
|
2
|
-
|
|
2
|
+
Rule-based, extensible and async-friendly data validation engine for complex forms and business rules.
|
|
3
3
|
|
|
4
4
|
## Overview
|
|
5
5
|
|
|
6
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
|
42
|
-
- [1.
|
|
43
|
-
- [2.
|
|
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
|
-
|
|
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
|
|
102
|
+
### Basic Usage
|
|
69
103
|
|
|
70
|
-
Here’s an example of validating a set of fields:
|
|
71
104
|
```javascript
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
|
|
136
|
+
// This should return { ok: true }
|
|
137
|
+
console.log(result);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
runFormValidate();
|
|
101
141
|
```
|
|
102
142
|
|
|
103
|
-
|
|
143
|
+
### Validation Result
|
|
144
|
+
A validation result follows this structure:
|
|
104
145
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
- **dataErrorMessages**: Custom error messages returned upon validation failure.
|
|
146
|
+
When is **valid**:
|
|
147
|
+
```javascript
|
|
148
|
+
{ ok: true }
|
|
149
|
+
```
|
|
110
150
|
|
|
111
|
-
|
|
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
|
-
|
|
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": {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
"
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
175
|
-
|
|
176
|
-
- **
|
|
177
|
-
- **
|
|
178
|
-
- **
|
|
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
|
-
|
|
182
|
-
|
|
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
|
-
|
|
325
|
+
#### Helper Signature
|
|
326
|
+
```typescript
|
|
327
|
+
(value, rule, modifier?, data?) => Record<string, Function>
|
|
328
|
+
```
|
|
223
329
|
|
|
224
|
-
|
|
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": {
|
|
228
|
-
|
|
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
|
|
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.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./dist/main.cjs.js",
|
|
6
6
|
"type": "commonjs",
|
|
7
|
-
"keywords": [
|
|
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.
|
|
29
|
+
"esbuild": "^0.27.2",
|
|
19
30
|
"express": "^4.21.2",
|
|
20
31
|
"jest": "^29.7.0"
|
|
21
32
|
}
|
package/src/js/dataValidate.js
CHANGED
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Validate your data fields using your rules, data rules and validators.
|
|
3
|
-
* @param {[DataField]}
|
|
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
|
|
8
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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(
|
|
91
|
+
if(!Object.keys(schema).every((key) => data.hasOwnProperty(key))) {
|
|
51
92
|
return { error: true, errorMessage: "Missing properties"}
|
|
52
93
|
}
|
|
53
|
-
const dataValidators = await
|
|
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,
|
|
97
|
+
return { error: true, errors: errors };
|
|
57
98
|
}
|
|
58
99
|
|
|
59
|
-
const dataRuleArr = Object.keys(
|
|
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
|
|
108
|
+
return { error: true, errorMessage: "Missing fields for schema"}
|
|
68
109
|
}
|
|
69
110
|
return { ok: true };
|
|
70
111
|
}
|
|
71
112
|
|
|
72
|
-
|
|
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
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 {
|
|
17
|
-
* @property {Object}
|
|
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}
|
|
35
|
-
* @property {
|
|
41
|
+
* @typedef {Object} SchemaRule
|
|
42
|
+
* @property {SchemaRuleFiVeld} field - The field which will use the rule
|
|
36
43
|
*/
|
|
37
44
|
|
|
38
45
|
/**
|
|
39
|
-
* @typedef {Object}
|
|
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,
|
|
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
|
/**
|