check-rule-mate 0.5.1 → 0.5.3
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 +131 -0
- package/bin/generate-docs.js +434 -0
- package/dist/main.cjs.js +1 -1
- package/package.json +4 -1
- package/src/index.d.ts +101 -1
- package/src/js/dataValidate.js +36 -7
- package/src/types.js +72 -1
package/README.md
CHANGED
|
@@ -13,6 +13,7 @@ It is designed for scenarios where traditional schema-based validators start to
|
|
|
13
13
|
- Async checks
|
|
14
14
|
- Reusable validation logic across multiple forms
|
|
15
15
|
- Full control over execution flow and error handling
|
|
16
|
+
- Lifecycle Hooks
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
**Github repository:** [check-rule-mate repository](https://github.com/johnrock16/check-rule-mate)
|
|
@@ -31,6 +32,7 @@ Use **check-rule-mate** if you:
|
|
|
31
32
|
- Need async validations (API calls, database checks, etc.)
|
|
32
33
|
- Prefer rule-driven validation instead of tightly coupled schemas
|
|
33
34
|
- Want clean separation between rules, data, and messages
|
|
35
|
+
- You want to have auto documentation of your forms
|
|
34
36
|
|
|
35
37
|
|
|
36
38
|
## Core Concepts
|
|
@@ -55,6 +57,7 @@ This separation makes the system flexible, scalable, and easy to maintain.
|
|
|
55
57
|
- Strict or loose schema matching
|
|
56
58
|
- i18n-ready error messages
|
|
57
59
|
- Framework-agnostic (frontend or backend)
|
|
60
|
+
- Auto documentation (automatic generated by a CLI command)
|
|
58
61
|
|
|
59
62
|
## Table of Contents
|
|
60
63
|
|
|
@@ -64,6 +67,8 @@ This separation makes the system flexible, scalable, and easy to maintain.
|
|
|
64
67
|
- [Running Tests](#Repository---Running-Tests)
|
|
65
68
|
- [How It Works](#How-It-Works)
|
|
66
69
|
- [Basic Usage](#Basic-Usage)
|
|
70
|
+
- [Lifecycle Hooks](#Lifecycle-Hooks)
|
|
71
|
+
- [Auto documentation](#Auto-Documentation)
|
|
67
72
|
- [Defining Validation](#Defining-Validation)
|
|
68
73
|
- [1. Schema](#Defining-a-Schema-What-to-validate)
|
|
69
74
|
- [2. Rules](#Defining-Rules-How-to-validate)
|
|
@@ -164,6 +169,132 @@ When is **invalid** and **has errors**:
|
|
|
164
169
|
}
|
|
165
170
|
```
|
|
166
171
|
|
|
172
|
+
### Lifecycle Hooks
|
|
173
|
+
The **check-rule-mate** lifecycle hooks allow you to observe, extend and react to the validation process without coupling logic to rules or helpers.
|
|
174
|
+
|
|
175
|
+
Hooks are especially useful for:
|
|
176
|
+
|
|
177
|
+
- Logging and debugging
|
|
178
|
+
- Analytics and metrics
|
|
179
|
+
- Custom side-effects
|
|
180
|
+
- Integrating validation with UI or external systems
|
|
181
|
+
- Advanced error handling and reporting
|
|
182
|
+
- They provide fine-grained control over the validation lifecycle.
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
hooks?: {
|
|
186
|
+
onValidateStart?: (payload) => void;
|
|
187
|
+
onValidateFieldStart?: (payload) => void;
|
|
188
|
+
onValidateFieldError?: (payload) => void;
|
|
189
|
+
onValidateFieldSuccess?: (payload) => void;
|
|
190
|
+
onValidateEnd?: (payload) => void;
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
#### Hook Payloads
|
|
195
|
+
|
|
196
|
+
##### `onValidateStart`
|
|
197
|
+
Triggered once before validation begins.
|
|
198
|
+
```typescript
|
|
199
|
+
onValidateStart: ({ data }) => void
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Payload:**
|
|
203
|
+
- `data`: Full form data object being validated
|
|
204
|
+
|
|
205
|
+
##### `onValidateFieldStart`
|
|
206
|
+
Triggered before validating each field.
|
|
207
|
+
```typescript
|
|
208
|
+
onValidateFieldStart: ({ field, value, schemaField }) => void
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Payload:**
|
|
212
|
+
- `field`: Field name
|
|
213
|
+
- `value`: Field value
|
|
214
|
+
- `schemaField`: Schema configuration for the field (or `null` if missing)
|
|
215
|
+
|
|
216
|
+
##### `onValidateFieldError`
|
|
217
|
+
Triggered when a field fails validation.
|
|
218
|
+
```typescript
|
|
219
|
+
onValidateFieldError: ({ field, value, schemaField, error }) => void
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Payload:**
|
|
223
|
+
- `field`: Field name
|
|
224
|
+
- `value`: Field value
|
|
225
|
+
- `schemaField`: Schema configuration for the field (or `null` if missing)
|
|
226
|
+
- `error`: Validation error object
|
|
227
|
+
|
|
228
|
+
##### `onValidateFieldSuccess`
|
|
229
|
+
Triggered when a field is successfully validated.
|
|
230
|
+
```typescript
|
|
231
|
+
onValidateFieldSuccess: ({ field, value, schemaField }) => void
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**Payload:**
|
|
235
|
+
- `field`: Field name
|
|
236
|
+
- `value`: Field value
|
|
237
|
+
- `schemaField`: Schema configuration for the field (or `null` if missing)
|
|
238
|
+
|
|
239
|
+
##### `onValidateEnd`
|
|
240
|
+
Triggered once after validation finishes.
|
|
241
|
+
```typescript
|
|
242
|
+
onValidateEnd: ({ data, errors }) => void
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Payload:**
|
|
246
|
+
- `data`: Full form data object being validated
|
|
247
|
+
- `errors`: Validation errors (if any)
|
|
248
|
+
If no errors occurred, `errors` may be `undefined`.
|
|
249
|
+
|
|
250
|
+
#### Hooks - Example Usage
|
|
251
|
+
```javascript
|
|
252
|
+
const validator = createValidator(fields, {
|
|
253
|
+
validationHelpers: myValidator,
|
|
254
|
+
rules: MY_RULES,
|
|
255
|
+
schema: CONTACT_US,
|
|
256
|
+
errorMessages: ERROR_MESSAGES,
|
|
257
|
+
hooks: {
|
|
258
|
+
onValidateStart: ({ data }) => {
|
|
259
|
+
console.log('Validation started', data);
|
|
260
|
+
},
|
|
261
|
+
|
|
262
|
+
onValidateFieldStart: ({ field, value }) => {
|
|
263
|
+
console.log(`Validating ${field}`, value);
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
onValidateFieldError: ({ field, error }) => {
|
|
267
|
+
console.error(`Error on ${field}`, error);
|
|
268
|
+
},
|
|
269
|
+
|
|
270
|
+
onValidateFieldSuccess: ({ field }) => {
|
|
271
|
+
console.log(`${field} validated successfully`);
|
|
272
|
+
},
|
|
273
|
+
|
|
274
|
+
onValidateEnd: ({ data, errors }) => {
|
|
275
|
+
if (errors) {
|
|
276
|
+
console.log('Validation finished with errors', errors);
|
|
277
|
+
} else {
|
|
278
|
+
console.log('Validation finished successfully');
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
await validator.validate();
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Auto Documentation
|
|
288
|
+
|
|
289
|
+
**check-rule-mate** contains a script to generate **automatic documentation** based in your rules, schemas and error messages.
|
|
290
|
+
|
|
291
|
+
To use that it is simple, you only need to run this command:
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
npx check-rule-mate-auto-docs --rules rules-path --schemas schemas-path --errors errors-path --out file.html
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
This will generate a HTML file containing the rules, schemas and errors.
|
|
167
298
|
|
|
168
299
|
## Defining Validation
|
|
169
300
|
|
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* check-rule-mate — Auto Documentation Generator
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// import fs from "fs";
|
|
7
|
+
// import path from "path";
|
|
8
|
+
// import process from "process";
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const process = require('process');
|
|
13
|
+
|
|
14
|
+
/* ---------------------------------------
|
|
15
|
+
* CLI ARGS
|
|
16
|
+
* -------------------------------------*/
|
|
17
|
+
const args = process.argv.slice(2);
|
|
18
|
+
const getArg = (flag) => {
|
|
19
|
+
const index = args.indexOf(flag);
|
|
20
|
+
return index !== -1 ? args[index + 1] : null;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const RULES_DIR = getArg('--rules');
|
|
24
|
+
const SCHEMAS_DIR = getArg('--schemas');
|
|
25
|
+
const ERRORS_DIR = getArg('--errors')
|
|
26
|
+
const OUTPUT = getArg('--out') || "check-rule-mate-docs.html";
|
|
27
|
+
|
|
28
|
+
if (!RULES_DIR || !SCHEMAS_DIR) {
|
|
29
|
+
console.error(`
|
|
30
|
+
Usage:
|
|
31
|
+
npx check-rule-mate-auto-docs --rules ./rules --schemas ./schemas --errors ./errors --out docs.html
|
|
32
|
+
`);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* ---------------------------------------
|
|
37
|
+
* HELPERS
|
|
38
|
+
* -------------------------------------*/
|
|
39
|
+
const readJSONFiles = (dir) => {
|
|
40
|
+
return fs.readdirSync(dir)
|
|
41
|
+
.filter(f => f.endsWith(".json"))
|
|
42
|
+
.map(file => ({
|
|
43
|
+
name: file.replace(".json", ""),
|
|
44
|
+
content: JSON.parse(fs.readFileSync(path.join(dir, file), "utf-8"))
|
|
45
|
+
}));
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const rulesFiles = readJSONFiles(RULES_DIR);
|
|
49
|
+
const schemasFiles = readJSONFiles(SCHEMAS_DIR);
|
|
50
|
+
const errorsFiles = readJSONFiles(ERRORS_DIR);
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
/* ---------------------------------------
|
|
54
|
+
* INDEX RELATIONSHIPS
|
|
55
|
+
* -------------------------------------*/
|
|
56
|
+
const ruleUsageMap = {};
|
|
57
|
+
const errorUsageMap = {}
|
|
58
|
+
|
|
59
|
+
schemasFiles.forEach(schemaFile => {
|
|
60
|
+
Object.entries(schemaFile.content).forEach(([field, config]) => {
|
|
61
|
+
const ruleName = config.rule.split("--")[0];
|
|
62
|
+
if (!ruleUsageMap[ruleName]) ruleUsageMap[ruleName] = [];
|
|
63
|
+
ruleUsageMap[ruleName].push({
|
|
64
|
+
schema: schemaFile.name,
|
|
65
|
+
field,
|
|
66
|
+
rule: config.rule
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
rulesFiles.forEach(rulesFile => {
|
|
72
|
+
Object.entries(rulesFile.content).forEach(([field, config]) => {
|
|
73
|
+
Object.entries(config.error).forEach(([key, value]) => {
|
|
74
|
+
const errorName = value;
|
|
75
|
+
if (!errorUsageMap[errorName]) errorUsageMap[errorName] = [];
|
|
76
|
+
errorUsageMap[errorName].push({
|
|
77
|
+
file: rulesFile.name,
|
|
78
|
+
field,
|
|
79
|
+
error: value
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
if (config?.modifier) {
|
|
83
|
+
Object.entries(config.modifier).forEach(([modifierKey, modifier]) => {
|
|
84
|
+
if (modifier?.error) {
|
|
85
|
+
Object.entries(modifier.error).forEach(([key, value]) => {
|
|
86
|
+
const errorName = value;
|
|
87
|
+
if (!errorUsageMap[errorName]) errorUsageMap[errorName] = [];
|
|
88
|
+
errorUsageMap[errorName].push({
|
|
89
|
+
file: rulesFile.name,
|
|
90
|
+
field,
|
|
91
|
+
error: value
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
/* ---------------------------------------
|
|
102
|
+
* HTML GENERATION
|
|
103
|
+
* -------------------------------------*/
|
|
104
|
+
const html = `
|
|
105
|
+
<!DOCTYPE html>
|
|
106
|
+
<html lang="en">
|
|
107
|
+
<head>
|
|
108
|
+
<meta charset="UTF-8" />
|
|
109
|
+
<title>check-rule-mate — Documentation</title>
|
|
110
|
+
<style>
|
|
111
|
+
${generateCSS()}
|
|
112
|
+
</style>
|
|
113
|
+
</head>
|
|
114
|
+
<body>
|
|
115
|
+
|
|
116
|
+
<aside class="sidebar">
|
|
117
|
+
<input id="search" placeholder="Search..." />
|
|
118
|
+
|
|
119
|
+
<h3>Schemas</h3>
|
|
120
|
+
${schemasFiles.map(s => `
|
|
121
|
+
<a href="#schema-${s.name}">${s.name}</a>
|
|
122
|
+
`).join("")}
|
|
123
|
+
|
|
124
|
+
<h3>Rules</h3>
|
|
125
|
+
${rulesFiles.map(rf =>
|
|
126
|
+
Object.keys(rf.content).map(rule => `
|
|
127
|
+
<a href="#rule-${rule}">${rf.name} - ${rule}</a>
|
|
128
|
+
`).join("")
|
|
129
|
+
).join("")}
|
|
130
|
+
|
|
131
|
+
<h3>Errors</h3>
|
|
132
|
+
${errorsFiles.map(errorFile =>
|
|
133
|
+
Object.keys(errorFile.content).map(error => `
|
|
134
|
+
<a href="#error-${error}">${errorFile.name} - ${error}</a>
|
|
135
|
+
`).join("")
|
|
136
|
+
).join("")}
|
|
137
|
+
</aside>
|
|
138
|
+
|
|
139
|
+
<main>
|
|
140
|
+
<section>
|
|
141
|
+
<h1>check-rule-mate</h1>
|
|
142
|
+
<p class="muted">
|
|
143
|
+
Visual documentation of validation rules and schemas.
|
|
144
|
+
</p>
|
|
145
|
+
</section>
|
|
146
|
+
|
|
147
|
+
${renderSchemas(schemasFiles)}
|
|
148
|
+
${renderRules(rulesFiles, ruleUsageMap)}
|
|
149
|
+
${renderErrors(errorsFiles, errorUsageMap)}
|
|
150
|
+
</main>
|
|
151
|
+
|
|
152
|
+
<script>
|
|
153
|
+
${generateClientJS()}
|
|
154
|
+
</script>
|
|
155
|
+
|
|
156
|
+
</body>
|
|
157
|
+
</html>
|
|
158
|
+
`;
|
|
159
|
+
|
|
160
|
+
fs.writeFileSync(OUTPUT, html);
|
|
161
|
+
console.log(`✔ Documentation generated at ${OUTPUT}`);
|
|
162
|
+
|
|
163
|
+
/* ---------------------------------------
|
|
164
|
+
* RENDERERS
|
|
165
|
+
* -------------------------------------*/
|
|
166
|
+
function renderSchemas(schemas) {
|
|
167
|
+
return schemas.map(schema => `
|
|
168
|
+
<section id="schema-${schema.name}" class="card">
|
|
169
|
+
<h2>Schema: ${schema.name}</h2>
|
|
170
|
+
|
|
171
|
+
<table>
|
|
172
|
+
<thead>
|
|
173
|
+
<tr>
|
|
174
|
+
<th>Field</th>
|
|
175
|
+
<th>Rule</th>
|
|
176
|
+
<th class="text-center">Required</th>
|
|
177
|
+
<th class="text-center">Cache</th>
|
|
178
|
+
</tr>
|
|
179
|
+
</thead>
|
|
180
|
+
<tbody>
|
|
181
|
+
${Object.entries(schema.content).map(([field, cfg]) => `
|
|
182
|
+
<tr>
|
|
183
|
+
<td>${field}</td>
|
|
184
|
+
<td>
|
|
185
|
+
<a href="#rule-${cfg.rule.split("--")[0]}">
|
|
186
|
+
${cfg.rule}
|
|
187
|
+
</a>
|
|
188
|
+
</td>
|
|
189
|
+
<td class="text-center">${cfg.required ? "✔" : "optional"}</td>
|
|
190
|
+
<td class="text-center">${cfg.cache === false ? "off" : "✔"}</td>
|
|
191
|
+
</tr>
|
|
192
|
+
`).join("")}
|
|
193
|
+
</tbody>
|
|
194
|
+
</table>
|
|
195
|
+
</section>
|
|
196
|
+
`).join("");
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function renderRules(rulesFiles, usageMap) {
|
|
200
|
+
return rulesFiles.map(file =>
|
|
201
|
+
Object.entries(file.content).map(([ruleName, rule]) => `
|
|
202
|
+
<section id="rule-${ruleName}" class="card">
|
|
203
|
+
<h2>Rule: ${ruleName} (${file.name})</h2>
|
|
204
|
+
${rule?.docs?.description ?
|
|
205
|
+
`<p>${rule.docs.description}</p>`
|
|
206
|
+
: ''}
|
|
207
|
+
|
|
208
|
+
<h3>Validation Flow</h3>
|
|
209
|
+
<div class="flow">
|
|
210
|
+
${rule.validate.map(v => `
|
|
211
|
+
<div class="flow-step">${v}</div>
|
|
212
|
+
<div class="flow-arrow">→</div>
|
|
213
|
+
`).join("")}
|
|
214
|
+
<div class="flow-step success">valid</div>
|
|
215
|
+
</div>
|
|
216
|
+
|
|
217
|
+
<h3>Error Codes</h3>
|
|
218
|
+
${renderRulesErrors(rule.error)}
|
|
219
|
+
|
|
220
|
+
${rule.modifier ? `
|
|
221
|
+
<h3>Modifiers</h3>
|
|
222
|
+
${Object.entries(rule.modifier).map(([mod, modRule]) => `
|
|
223
|
+
<div class="modifier">
|
|
224
|
+
<span class="tag modifier">${mod}</span>
|
|
225
|
+
${modRule?.docs?.description ? `<p>${modRule.docs.description}</p>` : ''}
|
|
226
|
+
|
|
227
|
+
<div class="flow">
|
|
228
|
+
${modRule.validate.map(v => `
|
|
229
|
+
<div class="flow-step">${v}</div>
|
|
230
|
+
<div class="flow-arrow">→</div>
|
|
231
|
+
`).join("")}
|
|
232
|
+
<div class="flow-step success">valid</div>
|
|
233
|
+
</div>
|
|
234
|
+
|
|
235
|
+
<h4>Error Codes</h4>
|
|
236
|
+
${renderRulesErrors(modRule.error)}
|
|
237
|
+
</div>
|
|
238
|
+
`).join("")}
|
|
239
|
+
` : ""}
|
|
240
|
+
|
|
241
|
+
<h3>Used by Schemas</h3>
|
|
242
|
+
<ul>
|
|
243
|
+
${(usageMap[ruleName] || []).map(u =>
|
|
244
|
+
`<li>${u.schema} → <strong>${u.field}</strong> (${u.rule})</li>`
|
|
245
|
+
).join("") || "<li>Not used</li>"}
|
|
246
|
+
</ul>
|
|
247
|
+
|
|
248
|
+
${rule?.docs?.notes ?
|
|
249
|
+
`
|
|
250
|
+
<h3>Notes</h3>
|
|
251
|
+
<div class="rule-notes">${rule?.docs?.notes}</div>
|
|
252
|
+
`
|
|
253
|
+
: ''}
|
|
254
|
+
</section>
|
|
255
|
+
`).join("")
|
|
256
|
+
).join("");
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function renderRulesErrors(errors = {}) {
|
|
260
|
+
return `
|
|
261
|
+
<ul>
|
|
262
|
+
${Object.entries(errors).map(([k, v]) =>
|
|
263
|
+
`<li><a href="#error-${v.split('.')[0]}" class="tag error">${k}</a> ${v}</li>`
|
|
264
|
+
).join("")}
|
|
265
|
+
</ul>
|
|
266
|
+
`;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function renderErrors(errorFiles, usageMap) {
|
|
270
|
+
return errorFiles.map(file =>
|
|
271
|
+
Object.entries(file.content).map(([errorName, errors]) => `
|
|
272
|
+
<section id="error-${errorName}" class="card">
|
|
273
|
+
<h2>Error: ${errorName} (${file.name})</h2>
|
|
274
|
+
<ul>
|
|
275
|
+
${Object.entries(errors).map(([key, value]) => `
|
|
276
|
+
<li><span class="tag error">${key}</span> ${value} </li>
|
|
277
|
+
`).join('')}
|
|
278
|
+
</ul>
|
|
279
|
+
|
|
280
|
+
<h3>Used by Rules</h3>
|
|
281
|
+
<ul>
|
|
282
|
+
${Object.entries(errors).map(([key, value]) => `
|
|
283
|
+
${(usageMap[`${errorName}.${key}`] || []).map(u =>
|
|
284
|
+
`<li>${u.file} → <strong>${u.field}</strong> (${u.error})</li>`
|
|
285
|
+
).join("") || "<li>Not used</li>"}
|
|
286
|
+
`).join('')}
|
|
287
|
+
</ul>
|
|
288
|
+
</section>
|
|
289
|
+
`).join('')).join('');
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/* ---------------------------------------
|
|
293
|
+
* CSS
|
|
294
|
+
* -------------------------------------*/
|
|
295
|
+
function generateCSS() {
|
|
296
|
+
return `
|
|
297
|
+
body {
|
|
298
|
+
margin: 0;
|
|
299
|
+
font-family: Inter, system-ui, sans-serif;
|
|
300
|
+
display: grid;
|
|
301
|
+
grid-template-columns: 280px 1fr;
|
|
302
|
+
background: #0f172a;
|
|
303
|
+
color: #e5e7eb;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.sidebar {
|
|
307
|
+
padding: 16px;
|
|
308
|
+
background: #020617;
|
|
309
|
+
overflow-y: auto;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.sidebar input {
|
|
313
|
+
width: 100%;
|
|
314
|
+
padding: 8px;
|
|
315
|
+
border-radius: 6px;
|
|
316
|
+
border: none;
|
|
317
|
+
margin-bottom: 16px;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.sidebar a {
|
|
321
|
+
display: block;
|
|
322
|
+
padding: 6px 10px;
|
|
323
|
+
color: #e5e7eb;
|
|
324
|
+
text-decoration: none;
|
|
325
|
+
border-radius: 6px;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.sidebar a:hover {
|
|
329
|
+
background: rgba(56,189,248,0.2);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
a {
|
|
333
|
+
color: #e5e7eb;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
main {
|
|
337
|
+
padding: 32px;
|
|
338
|
+
overflow-y: auto;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.card {
|
|
342
|
+
background: #020617;
|
|
343
|
+
border-radius: 12px;
|
|
344
|
+
padding: 24px;
|
|
345
|
+
margin-bottom: 32px;
|
|
346
|
+
border: 1px solid rgba(255,255,255,0.05);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.flow {
|
|
350
|
+
display: flex;
|
|
351
|
+
align-items: center;
|
|
352
|
+
gap: 12px;
|
|
353
|
+
flex-wrap: wrap;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
.flow-step {
|
|
357
|
+
padding: 10px 14px;
|
|
358
|
+
border-radius: 8px;
|
|
359
|
+
background: rgba(56,189,248,0.15);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.flow-arrow {
|
|
363
|
+
opacity: 0.5;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
.success {
|
|
367
|
+
background: rgba(34,197,94,0.2);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.tag {
|
|
371
|
+
padding: 4px 8px;
|
|
372
|
+
border-radius: 999px;
|
|
373
|
+
font-size: 14px;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.tag.error {
|
|
377
|
+
display: inline-block;
|
|
378
|
+
margin-bottom: 8px;
|
|
379
|
+
background: rgba(239,68,68,0.2);
|
|
380
|
+
text-decoration: none;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
.tag.modifier {
|
|
384
|
+
display: inline-block;
|
|
385
|
+
font-size: 16px;
|
|
386
|
+
margin-bottom: 8px;
|
|
387
|
+
font-weight: 600;
|
|
388
|
+
background: rgba(167,139,250,0.2);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
table {
|
|
392
|
+
width: 100%;
|
|
393
|
+
border-collapse: collapse;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
td, th {
|
|
397
|
+
padding: 8px;
|
|
398
|
+
border-bottom: 1px solid rgba(255,255,255,0.05);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
th {
|
|
402
|
+
text-align: left;
|
|
403
|
+
border-bottom: 1px solid #f4f4f4;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
.rule-notes {
|
|
407
|
+
padding: 16px;
|
|
408
|
+
color: black;
|
|
409
|
+
background: #f4f4f4;
|
|
410
|
+
border-radius: 12px;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.text-center {
|
|
414
|
+
text-align: center;
|
|
415
|
+
}
|
|
416
|
+
`;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/* ---------------------------------------
|
|
420
|
+
* CLIENT JS
|
|
421
|
+
* -------------------------------------*/
|
|
422
|
+
function generateClientJS() {
|
|
423
|
+
return `
|
|
424
|
+
const search = document.getElementById("search");
|
|
425
|
+
search.addEventListener("input", e => {
|
|
426
|
+
const value = e.target.value.toLowerCase();
|
|
427
|
+
document.querySelectorAll("section.card").forEach(card => {
|
|
428
|
+
card.style.display = card.innerText.toLowerCase().includes(value)
|
|
429
|
+
? ""
|
|
430
|
+
: "none";
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
`;
|
|
434
|
+
}
|
package/dist/main.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var M=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var L=(r,a)=>{for(var u in a)M(r,u,{get:a[u],enumerable:!0})},_=(r,a,u,l)=>{if(a&&typeof a=="object"||typeof a=="function")for(let d of D(a))!U.call(r,d)&&d!==u&&M(r,d,{get:()=>a[d],enumerable:!(l=j(a,d))||l.enumerable});return r};var x=r=>_(M({},"__esModule",{value:!0}),r);var K={};L(K,{createValidator:()=>q});module.exports=x(K);var O={propertiesMustMatch:!0,abortEarly:!1,cache:!0};function q(r,{validationHelpers:a={},rules:u,schema:l,errorMessages:d={},hooks:g={},options:p=O}){p={...O,...p},r=r;let i={},y={},v={all:async e=>Promise.all([...e].map(async n=>await m(n,r))),first:async e=>{let n=[];for(let V of e){let t=await m(V,r);if(n.push(t),!t)return n}return n}};function w(e,n){if(!e||typeof n!="string")return;let V=n.split("."),t=e;for(let f of V){if(t[f]===void 0)return;t=t[f]}return t}async function m(e,n=null){var V,t;if(o("onValidateFieldStart",{field:e.key,value:e.value,schemaField:l[e.key]||null}),l[e.key]){let{rule:f,required:s}=l[e.key];if((((V=l[e.key])==null?void 0:V.cache)!==void 0?l[e.key].cache:p.cache)&&n[e.key]===((t=y[e.key])==null?void 0:t.value))return y[e.key].isValid;if((f&&s||!s&&e.value!="")&&f){let P=f.split("--")[0],S=f.split("--").length>1?f.split("--")[1]:"",I=B(e.value,u[P],S,a,n),{isValid:E,errorMessage:F,errorType:T}=await I.validate();if(E)o("onValidateFieldSuccess",{field:e.key,value:e.value,schemaField:l[e.key]});else{let R={name:e.key,field:e.key,code:F,type:T,message:w(d,F)||""};i[e.key]=R,o("onValidateFieldError",{field:e.key,value:e.value,schemaField:l[e.key],error:R})}return y[e.key]={isValid:E,value:n[e.key]},E}}else if(p.propertiesMustMatch){let f={name:e.key,field:e.key,message:"Invalid property",internal:!0};return i[e.key]=f,o("onValidateFieldError",{field:e.key,value:e.value,error:f}),!1}return o("onValidateFieldSuccess",{field:e.key,value:e.value}),!0}async function c(e){return await m({key:e,value:r[e]},r)?{ok:!0}:{error:!0,errors:i[e]}}async function k(){o("onValidateStart",{data:r}),i={};let e=Object.keys(r).map(n=>({key:n,value:r[n]}));if(e&&e.length>0){if(!Object.keys(l).every(s=>r.hasOwnProperty(s)))return o("onValidateEnd",{data:r,errors:[{name:"internal: schema - missing properties",message:"Missing properties",internal:!0}]}),{error:!0,errorMessage:"Missing properties"};if((p!=null&&p.abortEarly?await v.first(e):await v.all(e)).some(s=>!s))return o("onValidateEnd",{data:r,errors:i}),{error:!0,errors:i};let V=Object.keys(l).map(s=>({key:s,required:l[s].required})),t=e.map(s=>s.key);if(!V.filter(s=>s.required).map(s=>s.key).every(s=>t.includes(s))){let s={error:!0};return o("onValidateEnd",{data:r,errors:[{name:"internal: fields - required",message:"",internal:!0}]}),s}}else if(!e||e.length===0){let n={error:!0,errorMessage:"Missing fields for schema"};return o("onValidateEnd",{data:r,errors:[{name:"internal: schema - missing fields",message:n.errorMessage,internal:!0}]}),n}return o("onValidateEnd",{data:r}),{ok:!0}}function o(e,n){g!=null&&g[e]&&typeof g[e]=="function"&&g[e]({...n})}function h(e){r=e}return{validate:k,validateField:c,setData:h}}function B(r,a,u=null,l=null,d=null){async function g(i){let y,v;return{isValid:!(await Promise.all(i.validate.map(async c=>{let k=!0;if(i.params&&i.params[c]&&i.params[c].length>0){let o=i.params[c].map(e=>typeof e=="string"&&e[0]==="$"?e.substring(1,e.length):e);k=await this[c](...o)}else k=await this[c]();return!k&&!y&&(i!=null&&i.error[c])&&(y=i.error[c],v=c),k}))).some(c=>!c),errorMessage:y,errorType:v}}async function p(){if(l&&typeof l=="function"){let y=l(r,a,u,d);Object.keys(y).forEach(v=>{this[v]=y[v]})}return u?await g.call(this,a.modifier[u]):await g.call(this,a)}return{validate:p}}0&&(module.exports={createValidator});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "check-rule-mate",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./dist/main.cjs.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -17,6 +17,9 @@
|
|
|
17
17
|
"check rule",
|
|
18
18
|
"check rule mate"
|
|
19
19
|
],
|
|
20
|
+
"bin": {
|
|
21
|
+
"check-rule-mate-auto-docs": "./bin/generate-docs.js"
|
|
22
|
+
},
|
|
20
23
|
"scripts": {
|
|
21
24
|
"start": "node ./examples/vanilla/src/index.js",
|
|
22
25
|
"build": "node build",
|
package/src/index.d.ts
CHANGED
|
@@ -86,6 +86,9 @@ export interface DataValidatorConfigs {
|
|
|
86
86
|
|
|
87
87
|
/** Validator options */
|
|
88
88
|
options: ValidatorOptions
|
|
89
|
+
|
|
90
|
+
/** Validator hooks */
|
|
91
|
+
hooks: ValidatorHooks
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
/**
|
|
@@ -100,9 +103,12 @@ export interface DataValidatorSuccessResponse {
|
|
|
100
103
|
* Error object.
|
|
101
104
|
*/
|
|
102
105
|
export interface CheckError {
|
|
103
|
-
/**
|
|
106
|
+
/** Error name */
|
|
104
107
|
name: string
|
|
105
108
|
|
|
109
|
+
/** Field name */
|
|
110
|
+
field?: string
|
|
111
|
+
|
|
106
112
|
/** Error path */
|
|
107
113
|
code?: string
|
|
108
114
|
|
|
@@ -111,6 +117,9 @@ export interface CheckError {
|
|
|
111
117
|
|
|
112
118
|
/** Error message */
|
|
113
119
|
message?: string
|
|
120
|
+
|
|
121
|
+
/** Internal error flag */
|
|
122
|
+
internal?: boolean
|
|
114
123
|
}
|
|
115
124
|
|
|
116
125
|
/**
|
|
@@ -126,3 +135,94 @@ export interface DataValidatorErrorResponse {
|
|
|
126
135
|
/** Additional error details */
|
|
127
136
|
errors?: Record<string, CheckError>
|
|
128
137
|
}
|
|
138
|
+
|
|
139
|
+
export interface ValidatorHooks {
|
|
140
|
+
/** Executed before validation runs */
|
|
141
|
+
onValidateStart?: onValidateStart
|
|
142
|
+
|
|
143
|
+
/** Executed before validation runs for each field */
|
|
144
|
+
onValidateFieldStart?: onValidateFieldStart
|
|
145
|
+
|
|
146
|
+
/** Executed when validation fails for some field */
|
|
147
|
+
onValidateFieldError?: onValidateFieldError
|
|
148
|
+
|
|
149
|
+
/** Executed when validation has success for some field */
|
|
150
|
+
onValidateFieldSuccess?: onValidateFieldSuccess
|
|
151
|
+
|
|
152
|
+
/** Executed after validation runs */
|
|
153
|
+
onValidateEnd?: onValidateEnd
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface onValidateStart {
|
|
157
|
+
/** Returns the payload of hook */
|
|
158
|
+
payload: onValidateStartPayload
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export interface onValidateFieldStart {
|
|
162
|
+
/** Returns the payload of hook */
|
|
163
|
+
payload: onValidateFieldStartPayload
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export interface onValidateFieldError {
|
|
167
|
+
/** Returns the payload of hook */
|
|
168
|
+
payload: onValidateFieldErrorPayload
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export interface onValidateFieldSuccess {
|
|
172
|
+
/** Returns the payload of hook */
|
|
173
|
+
payload: onValidateFieldSuccessPayload
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export interface onValidateEnd {
|
|
177
|
+
/** Returns the payload of hook */
|
|
178
|
+
payload: onValidateEndPayload
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export interface onValidateStartPayload {
|
|
182
|
+
/** Form data object */
|
|
183
|
+
data: Object
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export interface onValidateFieldStart {
|
|
187
|
+
/** Field name */
|
|
188
|
+
field: string
|
|
189
|
+
|
|
190
|
+
/** Field value */
|
|
191
|
+
value: any
|
|
192
|
+
|
|
193
|
+
/** Schema field */
|
|
194
|
+
schemaField: SchemaRuleField
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export interface onValidateFieldError {
|
|
198
|
+
/** Field name */
|
|
199
|
+
field: string
|
|
200
|
+
|
|
201
|
+
/** Field value */
|
|
202
|
+
value: any
|
|
203
|
+
|
|
204
|
+
/** Schema field */
|
|
205
|
+
schemaField: SchemaRuleField
|
|
206
|
+
|
|
207
|
+
/** Field error */
|
|
208
|
+
error: CheckError
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export interface onValidateFieldSuccess {
|
|
212
|
+
/** Field name */
|
|
213
|
+
field: string
|
|
214
|
+
|
|
215
|
+
/** Field value */
|
|
216
|
+
value: any
|
|
217
|
+
|
|
218
|
+
/** Schema field */
|
|
219
|
+
schemaField: SchemaRuleField
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export interface onValidateEndPayload {
|
|
223
|
+
/** Form data object */
|
|
224
|
+
data: Object
|
|
225
|
+
|
|
226
|
+
/** Form errors */
|
|
227
|
+
errors?: Record<string, CheckError>
|
|
228
|
+
}
|
package/src/js/dataValidate.js
CHANGED
|
@@ -5,7 +5,7 @@ const DEFAUL_OPTIONS = { propertiesMustMatch: true, abortEarly: false, cache: tr
|
|
|
5
5
|
* @param {[DataField]} data - All the data fields to be validate
|
|
6
6
|
* @param {DataValidatorConfigs} config - The configs which will be followed during validation
|
|
7
7
|
*/
|
|
8
|
-
export function createValidator(data, {validationHelpers = {}, rules, schema, errorMessages = {}, options = DEFAUL_OPTIONS}) {
|
|
8
|
+
export function createValidator(data, {validationHelpers = {}, rules, schema, errorMessages = {}, hooks = {}, options = DEFAUL_OPTIONS}) {
|
|
9
9
|
options = { ...DEFAUL_OPTIONS, ...options};
|
|
10
10
|
data = data;
|
|
11
11
|
let errors = {};
|
|
@@ -41,6 +41,7 @@ export function createValidator(data, {validationHelpers = {}, rules, schema, er
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
async function inputValidation(dataAttribute, data = null) {
|
|
44
|
+
hookTrigger('onValidateFieldStart', { field: dataAttribute.key, value: dataAttribute.value, schemaField: schema[dataAttribute.key] || null });
|
|
44
45
|
if (schema[dataAttribute.key]) {
|
|
45
46
|
const { rule, required } = schema[dataAttribute.key];
|
|
46
47
|
const cacheEnabled = schema[dataAttribute.key]?.cache !== undefined ? schema[dataAttribute.key].cache : options.cache;
|
|
@@ -56,24 +57,36 @@ export function createValidator(data, {validationHelpers = {}, rules, schema, er
|
|
|
56
57
|
const dataAttributeValidation = dataAttributeValidator(dataAttribute.value, rules[INPUT_RULE], RULE_MODIFIER, validationHelpers, data);
|
|
57
58
|
const { isValid, errorMessage, errorType } = await dataAttributeValidation.validate();
|
|
58
59
|
if (!isValid) {
|
|
59
|
-
|
|
60
|
+
const error = {
|
|
60
61
|
name: dataAttribute.key,
|
|
62
|
+
field: dataAttribute.key,
|
|
61
63
|
code: errorMessage,
|
|
62
64
|
type: errorType,
|
|
63
65
|
message: getObjectValueByPath(errorMessages, errorMessage) || ''
|
|
64
|
-
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
errors[dataAttribute.key] = error;
|
|
69
|
+
hookTrigger('onValidateFieldError', { field: dataAttribute.key, value: dataAttribute.value, schemaField: schema[dataAttribute.key] , error: error });
|
|
70
|
+
} else {
|
|
71
|
+
hookTrigger('onValidateFieldSuccess', { field: dataAttribute.key, value: dataAttribute.value, schemaField: schema[dataAttribute.key] });
|
|
65
72
|
}
|
|
66
73
|
oldData[dataAttribute.key] = {isValid: isValid, value: data[dataAttribute.key]};
|
|
67
74
|
return isValid;
|
|
68
75
|
}
|
|
69
76
|
}
|
|
70
77
|
} else if (options.propertiesMustMatch) {
|
|
71
|
-
|
|
78
|
+
const error = {
|
|
72
79
|
name: dataAttribute.key,
|
|
73
|
-
|
|
80
|
+
field: dataAttribute.key,
|
|
81
|
+
message: "Invalid property",
|
|
82
|
+
internal: true
|
|
74
83
|
}
|
|
84
|
+
|
|
85
|
+
errors[dataAttribute.key] = error;
|
|
86
|
+
hookTrigger('onValidateFieldError', { field: dataAttribute.key, value: dataAttribute.value, error: error });
|
|
75
87
|
return false;
|
|
76
88
|
}
|
|
89
|
+
hookTrigger('onValidateFieldSuccess', { field: dataAttribute.key, value: dataAttribute.value });
|
|
77
90
|
return true;
|
|
78
91
|
}
|
|
79
92
|
|
|
@@ -95,15 +108,18 @@ export function createValidator(data, {validationHelpers = {}, rules, schema, er
|
|
|
95
108
|
* @returns {DataValidatorSuccessResponse | DataValidatorErrorResponse} - The response of your validation
|
|
96
109
|
*/
|
|
97
110
|
async function validate() {
|
|
111
|
+
hookTrigger('onValidateStart', { data });
|
|
98
112
|
errors = {};
|
|
99
113
|
let dataArr = Object.keys(data).map((key) => ({ key, value: data[key] }));
|
|
100
114
|
if (dataArr && dataArr.length > 0) {
|
|
101
115
|
if(!Object.keys(schema).every((key) => data.hasOwnProperty(key))) {
|
|
116
|
+
hookTrigger('onValidateEnd', { data, errors: [{name: 'internal: schema - missing properties' , message: 'Missing properties', internal: true}] });
|
|
102
117
|
return { error: true, errorMessage: "Missing properties"}
|
|
103
118
|
}
|
|
104
119
|
const dataValidators = options?.abortEarly ? await validateByStrategies.first(dataArr) : await validateByStrategies.all(dataArr);
|
|
105
120
|
|
|
106
121
|
if (dataValidators.some((element) => !element)) {
|
|
122
|
+
hookTrigger('onValidateEnd', { data, errors: errors });
|
|
107
123
|
return { error: true, errors: errors };
|
|
108
124
|
}
|
|
109
125
|
|
|
@@ -112,14 +128,27 @@ export function createValidator(data, {validationHelpers = {}, rules, schema, er
|
|
|
112
128
|
const dataAttributesRequired = dataRuleArr.filter((rule) => rule.required).map((rule) => rule.key);
|
|
113
129
|
|
|
114
130
|
if (!dataAttributesRequired.every((fieldRequired) => dataAttributesKey.includes(fieldRequired))) {
|
|
115
|
-
|
|
131
|
+
const error = { error: true };
|
|
132
|
+
|
|
133
|
+
hookTrigger('onValidateEnd', { data, errors: [{name: 'internal: fields - required' , message: '', internal: true}] });
|
|
134
|
+
return error;
|
|
116
135
|
}
|
|
117
136
|
} else if (!dataArr || dataArr.length === 0) {
|
|
118
|
-
|
|
137
|
+
const error = { error: true, errorMessage: "Missing fields for schema"};
|
|
138
|
+
|
|
139
|
+
hookTrigger('onValidateEnd', { data, errors: [{name: 'internal: schema - missing fields' , message: error.errorMessage, internal: true}] });
|
|
140
|
+
return error;
|
|
119
141
|
}
|
|
142
|
+
hookTrigger('onValidateEnd', { data });
|
|
120
143
|
return { ok: true };
|
|
121
144
|
}
|
|
122
145
|
|
|
146
|
+
function hookTrigger(hookName, parameters) {
|
|
147
|
+
if (hooks?.[hookName] && typeof hooks[hookName] === 'function') {
|
|
148
|
+
hooks[hookName]({...parameters});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
123
152
|
function setData(newData) {
|
|
124
153
|
data = newData;
|
|
125
154
|
}
|
package/src/types.js
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* @property {SchemaRule} schema - The rules you want to use per field
|
|
17
17
|
* @property {Object} errorMessages - The error messages you want to show during errors
|
|
18
18
|
* @property {ValidatorOptions} options - Options
|
|
19
|
+
* @property {ValidatorHooks} hooks - The hooks you want to execute in some specific phase of validation
|
|
19
20
|
*/
|
|
20
21
|
|
|
21
22
|
/**
|
|
@@ -74,8 +75,78 @@
|
|
|
74
75
|
* Error Object
|
|
75
76
|
*
|
|
76
77
|
* @typedef {Object} CheckError
|
|
77
|
-
* @property {string} name -
|
|
78
|
+
* @property {string} name - Error name
|
|
79
|
+
* @property {string} field - Field name (optional)
|
|
78
80
|
* @property {string} code - Error path (optional)
|
|
79
81
|
* @property {string} type - Error type (optional)
|
|
80
82
|
* @property {string} message - Error message (optional)
|
|
83
|
+
* @property {boolean} internal - Flag to know if it is a internal error (optional)
|
|
84
|
+
*/
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @typedef {Object} ValidatorHooks
|
|
89
|
+
* @property {onValidateStart} onValidateStart - Executed before validation runs
|
|
90
|
+
* @property {onValidateFieldStart} onValidateFieldStart - Executed before validation runs for each field
|
|
91
|
+
* @property {onValidateFieldError} onValidateFieldError - Executed when validation fails for some field
|
|
92
|
+
* @property {onValidateFieldSuccess} onValidateFieldSuccess - Executed when validation has success for some field
|
|
93
|
+
* @property {onValidateEnd} onValidateEnd - Executed after validation runs
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @typedef {Function} onValidateStart
|
|
98
|
+
* @property {onValidateStartPayload} payload - Returns the payload of validate form hook
|
|
99
|
+
*/
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @typedef {Object} onValidateStartPayload
|
|
103
|
+
* @property {Object} data - Returns the form data
|
|
104
|
+
*/
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @typedef {Function} onValidateFieldStart
|
|
108
|
+
* @property {onValidateFieldStartPayload} payload - Returns the payload of validate field hook
|
|
109
|
+
*/
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @typedef {Object} onValidateFieldStartPayload
|
|
113
|
+
* @property {string} field - Returns the field name
|
|
114
|
+
* @property {any} value - Returns the value of field
|
|
115
|
+
* @property {SchemaRuleField} schemaField - Returns the schema field
|
|
116
|
+
*/
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @typedef {Function} onValidateFieldError
|
|
120
|
+
* @property {onValidateFieldErrorPayload} payload - Returns the payload of validate field error hook
|
|
121
|
+
*/
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @typedef {Object} onValidateFieldErrorPayload
|
|
125
|
+
* @property {string} field - Returns the field name
|
|
126
|
+
* @property {string} value - Returns the value of field
|
|
127
|
+
* @property {SchemaRuleField} schemaField - Returns the schema field
|
|
128
|
+
* @property {CheckError} error - Returns the error data
|
|
129
|
+
*/
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @typedef {Function} onValidateFieldSuccess
|
|
133
|
+
* @property {onValidateFieldSuccessPayload} payload - Returns the payload of validate field success hook
|
|
134
|
+
*/
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* @typedef {Object} onValidateFieldSuccessPayload
|
|
138
|
+
* @property {string} field - Returns the field name
|
|
139
|
+
* @property {string} value - Returns the value of field
|
|
140
|
+
* @property {SchemaRuleField} schemaField - Returns the schema field
|
|
141
|
+
*/
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* @typedef {Function} onValidateEnd
|
|
145
|
+
* @property {onValidateEndPayload} payload - Returns the payload of validate form hook
|
|
146
|
+
*/
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @typedef {Object} onValidateEndPayload
|
|
150
|
+
* @property {Object} data - Returns the form data
|
|
151
|
+
* @property {DataValidatorErrorResponse} errors - Returns the errors of validation if had
|
|
81
152
|
*/
|