check-rule-mate 0.4.2 → 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 -80
- package/dist/main.cjs.js +1 -1
- package/package.json +14 -2
- package/src/js/dataValidate.js +70 -25
- package/src/main.js +2 -2
- package/src/types.js +13 -6
package/README.md
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
# check-rule-mate
|
|
2
|
+
Rule-based, extensible and async-friendly data validation engine for complex forms and business rules.
|
|
2
3
|
|
|
3
4
|
## Overview
|
|
4
5
|
|
|
5
|
-
|
|
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**.
|
|
6
8
|
|
|
7
|
-
|
|
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
|
|
8
16
|
|
|
9
17
|
|
|
10
18
|
**Github repository:** [check-rule-mate repository](https://github.com/johnrock16/check-rule-mate)
|
|
@@ -14,49 +22,76 @@ The core goal is to provide a **reusable and easy-to-extend** for handling vario
|
|
|
14
22
|
**Test the core functionalities here:** [check-rule-mate demo](https://johnrock16.github.io/check-rule-mate/)
|
|
15
23
|
(Note: Creating or modifying custom validators is not supported in the demo, as it requires JavaScript implementation.)
|
|
16
24
|
|
|
25
|
+
## Why check-rule-mate?
|
|
17
26
|
|
|
18
|
-
|
|
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
|
|
19
37
|
|
|
20
|
-
-
|
|
21
|
-
- **Modular Design**: Separation of rule definitions and error messages for easy management.
|
|
22
|
-
- **Easy Integration**: Can be used in any JavaScript environment.
|
|
23
|
-
- **Clear Error Handling**: Handles errors and displays messages.
|
|
24
|
-
- **Extendable**: Create your custom validators and rules and extend as you want.
|
|
38
|
+
check-rule-mate is built around four main concepts:
|
|
25
39
|
|
|
26
|
-
|
|
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
|
|
27
44
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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)
|
|
32
58
|
|
|
33
59
|
## Table of Contents
|
|
34
60
|
|
|
35
61
|
- [Getting Started](#Getting-Started)
|
|
36
|
-
- [Installation](#Installation)
|
|
62
|
+
- [NPM - Installation](#Installation)
|
|
63
|
+
- [Repository - Installation](#Repository---Installation)
|
|
37
64
|
- [Running Tests](#Running-Tests)
|
|
38
65
|
- [How It Works](#How-It-Works)
|
|
39
66
|
- [Basic Example](#Basic-Example)
|
|
40
|
-
- [Defining Validation
|
|
41
|
-
- [1.
|
|
42
|
-
- [2.
|
|
43
|
-
- [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)
|
|
44
71
|
- [4. Error Messages](#Error-Messages)
|
|
45
72
|
- [5. Example Usage](#Example-Usage)
|
|
46
73
|
- [Vanilla](#vanilla)
|
|
47
74
|
- [Express](#express)
|
|
48
75
|
- [Frontend](#frontend)
|
|
76
|
+
- [When NOT to use check-rule-mate](#When-NOT-to-use-check-rule-mate)
|
|
77
|
+
- [License](#License);
|
|
49
78
|
|
|
50
79
|
## Getting Started
|
|
80
|
+
|
|
51
81
|
### Installation
|
|
82
|
+
If you are in NPM use this:
|
|
83
|
+
```bash
|
|
84
|
+
npm install check-rule-mate
|
|
85
|
+
```
|
|
52
86
|
|
|
53
|
-
|
|
87
|
+
### Repository - Installation
|
|
88
|
+
If you downloaded the repository you can install using:
|
|
54
89
|
```bash
|
|
55
90
|
npm install
|
|
56
91
|
npm start
|
|
57
92
|
```
|
|
58
93
|
|
|
59
|
-
### Running Tests
|
|
94
|
+
### Repository - Running Tests
|
|
60
95
|
|
|
61
96
|
Execute the test suite with:
|
|
62
97
|
```bash
|
|
@@ -64,69 +99,102 @@ npm test
|
|
|
64
99
|
```
|
|
65
100
|
|
|
66
101
|
## How It Works
|
|
67
|
-
### Basic
|
|
102
|
+
### Basic Usage
|
|
68
103
|
|
|
69
|
-
Here’s an example of validating a set of fields:
|
|
70
104
|
```javascript
|
|
71
|
-
|
|
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
|
-
|
|
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();
|
|
98
135
|
|
|
99
|
-
|
|
136
|
+
// This should return { ok: true }
|
|
137
|
+
console.log(result);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
runFormValidate();
|
|
100
141
|
```
|
|
101
142
|
|
|
102
|
-
|
|
143
|
+
### Validation Result
|
|
144
|
+
A validation result follows this structure:
|
|
103
145
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
- **dataErrorMessages**: Custom error messages returned upon validation failure.
|
|
146
|
+
When is **valid**:
|
|
147
|
+
```javascript
|
|
148
|
+
{ ok: true }
|
|
149
|
+
```
|
|
109
150
|
|
|
110
|
-
|
|
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
|
+
```
|
|
111
163
|
|
|
112
|
-
### Data Rules
|
|
113
164
|
|
|
114
|
-
|
|
165
|
+
## Defining Validation
|
|
166
|
+
|
|
167
|
+
### Defining a Schema (What to validate)
|
|
168
|
+
|
|
169
|
+
Schemas map **data fields** to **rules**.
|
|
115
170
|
```json
|
|
116
171
|
{
|
|
117
|
-
"name": {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
"
|
|
122
|
-
|
|
123
|
-
|
|
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
|
+
}
|
|
124
188
|
}
|
|
125
189
|
```
|
|
126
190
|
|
|
127
|
-
|
|
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)
|
|
128
196
|
|
|
129
|
-
|
|
197
|
+
Rules define validation logic, independent of any specific form.
|
|
130
198
|
|
|
131
199
|
```json
|
|
132
200
|
{
|
|
@@ -168,17 +236,53 @@ Define reusable validation logic. Example:
|
|
|
168
236
|
}
|
|
169
237
|
}
|
|
170
238
|
```
|
|
171
|
-
#### Key Components:
|
|
172
239
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
- **
|
|
176
|
-
- **
|
|
177
|
-
- **
|
|
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:
|
|
178
257
|
|
|
258
|
+
- Base rule: email
|
|
259
|
+
- Modifier: confirm
|
|
179
260
|
|
|
180
|
-
|
|
181
|
-
|
|
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.
|
|
182
286
|
|
|
183
287
|
```javascript
|
|
184
288
|
const myValidator = function (value, rule, modifier = null, data = null) {
|
|
@@ -218,13 +322,36 @@ const myValidator = function (value, rule, modifier = null, data = null) {
|
|
|
218
322
|
};
|
|
219
323
|
```
|
|
220
324
|
|
|
221
|
-
|
|
325
|
+
#### Helper Signature
|
|
326
|
+
```typescript
|
|
327
|
+
(value, rule, modifier?, data?) => Record<string, Function>
|
|
328
|
+
```
|
|
222
329
|
|
|
223
|
-
|
|
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.
|
|
224
337
|
``` json
|
|
225
338
|
{
|
|
226
|
-
"common": {
|
|
227
|
-
|
|
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
|
|
228
355
|
}
|
|
229
356
|
```
|
|
230
357
|
|
|
@@ -269,3 +396,12 @@ npm run example:express
|
|
|
269
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)
|
|
270
397
|
|
|
271
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,9 +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": [
|
|
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
|
+
],
|
|
7
19
|
"scripts": {
|
|
8
20
|
"start": "node ./examples/vanilla/src/index.js",
|
|
9
21
|
"build": "node build",
|
|
@@ -14,7 +26,7 @@
|
|
|
14
26
|
"author": "João Rocha",
|
|
15
27
|
"license": "ISC",
|
|
16
28
|
"devDependencies": {
|
|
17
|
-
"esbuild": "^0.
|
|
29
|
+
"esbuild": "^0.27.2",
|
|
18
30
|
"express": "^4.21.2",
|
|
19
31
|
"jest": "^29.7.0"
|
|
20
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
|
/**
|