@reformer/core 1.0.0-beta.1 → 1.0.0-beta.2
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/dist/behaviors/compute-from.js +3 -3
- package/dist/behaviors/enable-when.js +5 -5
- package/dist/behaviors/reset-when.js +1 -1
- package/dist/behaviors/revalidate-when.js +1 -1
- package/dist/behaviors/sync-fields.js +5 -5
- package/dist/behaviors/watch-field.js +3 -3
- package/dist/behaviors.js +2 -2
- package/dist/core/types/field-path.d.ts +2 -2
- package/dist/core/types/index.d.ts +1 -1
- package/dist/core/types/validation-schema.d.ts +21 -50
- package/dist/core/validation/core/index.d.ts +0 -1
- package/dist/core/validation/core/validate-async.d.ts +9 -15
- package/dist/core/validation/core/validate.d.ts +15 -15
- package/dist/core/validation/index.d.ts +5 -3
- package/dist/core/validation/validation-applicator.d.ts +2 -56
- package/dist/core/validation/validation-registry.d.ts +18 -16
- package/dist/core/validation/validators/array-validators.d.ts +6 -31
- package/dist/core/validation/validators/email.d.ts +5 -29
- package/dist/core/validation/validators/future-date.d.ts +6 -28
- package/dist/core/validation/validators/index.d.ts +12 -4
- package/dist/core/validation/validators/integer.d.ts +13 -0
- package/dist/core/validation/validators/is-date.d.ts +5 -28
- package/dist/core/validation/validators/is-number.d.ts +14 -0
- package/dist/core/validation/validators/max-age.d.ts +6 -29
- package/dist/core/validation/validators/max-date.d.ts +6 -29
- package/dist/core/validation/validators/max-length.d.ts +5 -30
- package/dist/core/validation/validators/max.d.ts +7 -29
- package/dist/core/validation/validators/min-age.d.ts +6 -29
- package/dist/core/validation/validators/min-date.d.ts +6 -29
- package/dist/core/validation/validators/min-length.d.ts +5 -30
- package/dist/core/validation/validators/min.d.ts +7 -29
- package/dist/core/validation/validators/multiple-of.d.ts +13 -0
- package/dist/core/validation/validators/non-negative.d.ts +13 -0
- package/dist/core/validation/validators/non-zero.d.ts +13 -0
- package/dist/core/validation/validators/past-date.d.ts +5 -28
- package/dist/core/validation/validators/pattern.d.ts +5 -32
- package/dist/core/validation/validators/phone.d.ts +9 -19
- package/dist/core/validation/validators/required.d.ts +10 -31
- package/dist/core/validation/validators/url.d.ts +13 -15
- package/dist/{index-D25LsbRm.js → index-DLh_Ryb2.js} +1 -1
- package/dist/index.js +465 -397
- package/dist/{registry-helpers-Bv_BJ1s-.js → registry-helpers-CLPXad2B.js} +152 -292
- package/dist/validators/email.js +7 -9
- package/dist/validators/future-date.js +11 -12
- package/dist/validators/integer.d.ts +2 -0
- package/dist/validators/integer.js +10 -0
- package/dist/validators/is-date.js +6 -7
- package/dist/validators/is-number.d.ts +2 -0
- package/dist/validators/is-number.js +10 -0
- package/dist/validators/max-age.js +11 -12
- package/dist/validators/max-date.js +11 -12
- package/dist/validators/max-length.js +12 -8
- package/dist/validators/max.js +5 -6
- package/dist/validators/min-age.js +10 -11
- package/dist/validators/min-date.js +12 -13
- package/dist/validators/min-length.js +12 -8
- package/dist/validators/min.js +6 -7
- package/dist/validators/multiple-of.d.ts +2 -0
- package/dist/validators/multiple-of.js +10 -0
- package/dist/validators/non-negative.d.ts +2 -0
- package/dist/validators/non-negative.js +10 -0
- package/dist/validators/non-zero.d.ts +2 -0
- package/dist/validators/non-zero.js +10 -0
- package/dist/validators/past-date.js +11 -12
- package/dist/validators/pattern.js +6 -7
- package/dist/validators/phone.js +14 -32
- package/dist/validators/required.js +9 -10
- package/dist/validators/url.js +19 -16
- package/dist/validators-xJyP-jLZ.js +169 -0
- package/dist/validators.js +54 -50
- package/llms.txt +505 -790
- package/package.json +20 -4
- package/dist/core/validation/core/validate-tree.d.ts +0 -35
- package/dist/core/validation/validation-context.d.ts +0 -86
- package/dist/core/validation/validators/number.d.ts +0 -31
- package/dist/validate-C3XiA_zf.js +0 -10
- package/dist/validators/number.d.ts +0 -2
- package/dist/validators/number.js +0 -35
- package/dist/validators-BGsNOgT1.js +0 -207
package/llms.txt
CHANGED
|
@@ -42,18 +42,18 @@
|
|
|
42
42
|
|
|
43
43
|
### Imports (CRITICALLY IMPORTANT)
|
|
44
44
|
|
|
45
|
-
| What
|
|
46
|
-
|
|
|
47
|
-
| `createForm`, `useFormControl`, `useFormControlValue`, `validateForm`
|
|
45
|
+
| What | Where |
|
|
46
|
+
| ------------------------------------------------------------------------------------------- | --------------------------- |
|
|
47
|
+
| `createForm`, `useFormControl`, `useFormControlValue`, `validateForm` | `@reformer/core` |
|
|
48
48
|
| `ValidationSchemaFn`, `BehaviorSchemaFn`, `FieldPath`, `FormProxy`, `FieldNode` | `@reformer/core` |
|
|
49
|
-
| `FormSchema`, `FieldConfig`, `ArrayNode`
|
|
50
|
-
| `required`, `min`, `max`, `minLength`, `maxLength`, `email`
|
|
51
|
-
| `pattern`, `url`, `phone`, `
|
|
52
|
-
| `validate`, `validateAsync`, `
|
|
53
|
-
| `notEmpty`, `validateItems`
|
|
54
|
-
| `computeFrom`, `enableWhen`, `disableWhen`, `watchField`, `copyFrom`
|
|
55
|
-
| `resetWhen`, `revalidateWhen`, `syncFields`
|
|
56
|
-
| `transformValue`, `transformers`
|
|
49
|
+
| `FormSchema`, `FieldConfig`, `ArrayNode` | `@reformer/core` |
|
|
50
|
+
| `required`, `min`, `max`, `minLength`, `maxLength`, `email` | `@reformer/core/validators` |
|
|
51
|
+
| `pattern`, `url`, `phone`, `isNumber`, `integer`, `multipleOf`, `nonNegative`, `nonZero` | `@reformer/core/validators` |
|
|
52
|
+
| `validate`, `validateAsync`, `applyWhen`, `apply` | `@reformer/core/validators` |
|
|
53
|
+
| `notEmpty`, `validateItems` | `@reformer/core/validators` |
|
|
54
|
+
| `computeFrom`, `enableWhen`, `disableWhen`, `watchField`, `copyFrom` | `@reformer/core/behaviors` |
|
|
55
|
+
| `resetWhen`, `revalidateWhen`, `syncFields` | `@reformer/core/behaviors` |
|
|
56
|
+
| `transformValue`, `transformers` | `@reformer/core/behaviors` |
|
|
57
57
|
|
|
58
58
|
### Type Values
|
|
59
59
|
|
|
@@ -63,10 +63,10 @@
|
|
|
63
63
|
|
|
64
64
|
### React Hooks Comparison (CRITICALLY IMPORTANT)
|
|
65
65
|
|
|
66
|
-
| Hook
|
|
67
|
-
|
|
68
|
-
| `useFormControl(field)`
|
|
69
|
-
| `useFormControlValue(field)` | `T` (value directly)
|
|
66
|
+
| Hook | Return Type | Subscribes To | Use Case |
|
|
67
|
+
|------|-------------|---------------|----------|
|
|
68
|
+
| `useFormControl(field)` | `{ value, errors, disabled, touched, ... }` | All signals | Full field state, form inputs |
|
|
69
|
+
| `useFormControlValue(field)` | `T` (value directly) | Only value signal | Conditional rendering |
|
|
70
70
|
|
|
71
71
|
**CRITICAL**: Do NOT destructure `useFormControlValue`! It returns `T` directly, NOT `{ value: T }`.
|
|
72
72
|
|
|
@@ -188,26 +188,39 @@ const schema: FormSchema<{ properties: PropertyItem[] }> = {
|
|
|
188
188
|
|
|
189
189
|
### Validators
|
|
190
190
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
number
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
191
|
+
Operators register validators in the schema. Validator factories return pure
|
|
192
|
+
`Validator<TForm, TField>` functions of shape `(value, control, root) => ValidationError | null`.
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
// Operators (register validators in schema)
|
|
196
|
+
validate(path, validator: Validator<TForm, TField>, options?: { message?: string })
|
|
197
|
+
validateAsync(path, validator: AsyncValidator<TForm, TField>, options?: { message?: string; debounce?: number })
|
|
198
|
+
|
|
199
|
+
// Validator factories (return Validator). Pass to validate().
|
|
200
|
+
required(options?: { message?: string })
|
|
201
|
+
min(value: number, options?: { message?: string })
|
|
202
|
+
max(value: number, options?: { message?: string })
|
|
203
|
+
minLength(length: number, options?: { message?: string })
|
|
204
|
+
maxLength(length: number, options?: { message?: string })
|
|
205
|
+
email(options?: { message?: string })
|
|
206
|
+
pattern(regex: RegExp, options?: { message?: string })
|
|
207
|
+
url(options?: { message?: string; requireProtocol?: boolean })
|
|
208
|
+
phone(options?: { message?: string; format?: PhoneFormat })
|
|
209
|
+
// Number validator factories (atomic — compose via several validate() calls)
|
|
210
|
+
isNumber(options?: { message?: string })
|
|
211
|
+
integer(options?: { message?: string })
|
|
212
|
+
multipleOf(divisor: number, options?: { message?: string })
|
|
213
|
+
nonNegative(options?: { message?: string }) // value >= 0
|
|
214
|
+
nonZero(options?: { message?: string }) // value !== 0
|
|
215
|
+
date(options?: { message?: string; minAge?: number; maxAge?: number; noFuture?: boolean; noPast?: boolean })
|
|
216
|
+
notEmpty(options?: { message?: string })
|
|
217
|
+
|
|
218
|
+
// Usage: pass a factory result to validate()
|
|
219
|
+
validate(path.email, required());
|
|
220
|
+
validate(path.age, min(18));
|
|
221
|
+
validate(path.amount, integer());
|
|
222
|
+
validate(path.amount, min(0));
|
|
223
|
+
validate(path.amount, max(1000));
|
|
211
224
|
|
|
212
225
|
// Conditional validation (3 arguments!)
|
|
213
226
|
applyWhen(fieldPath, condition: (fieldValue) => boolean, validatorsFn: (path) => void)
|
|
@@ -220,8 +233,8 @@ applyWhen(
|
|
|
220
233
|
path.loanType, // 1st: field to watch
|
|
221
234
|
(type) => type === 'mortgage', // 2nd: condition on field value
|
|
222
235
|
(p) => { // 3rd: validators to apply
|
|
223
|
-
|
|
224
|
-
|
|
236
|
+
validate(p.propertyValue, required());
|
|
237
|
+
validate(p.propertyValue, min(100000));
|
|
225
238
|
}
|
|
226
239
|
);
|
|
227
240
|
|
|
@@ -230,8 +243,8 @@ applyWhen(
|
|
|
230
243
|
path.address.country,
|
|
231
244
|
(country) => country === 'US',
|
|
232
245
|
(p) => {
|
|
233
|
-
|
|
234
|
-
|
|
246
|
+
validate(p.address.state, required());
|
|
247
|
+
validate(p.address.zip, pattern(/^\d{5}(-\d{4})?$/));
|
|
235
248
|
}
|
|
236
249
|
);
|
|
237
250
|
|
|
@@ -240,19 +253,18 @@ applyWhen(
|
|
|
240
253
|
path.hasInsurance,
|
|
241
254
|
(has) => has === true,
|
|
242
255
|
(p) => {
|
|
243
|
-
|
|
244
|
-
|
|
256
|
+
validate(p.insuranceCompany, required());
|
|
257
|
+
validate(p.policyNumber, required());
|
|
245
258
|
}
|
|
246
259
|
);
|
|
247
260
|
|
|
248
261
|
// WRONG - only 2 arguments (React Hook Form pattern)
|
|
249
262
|
applyWhen(
|
|
250
263
|
(form) => form.loanType === 'mortgage', // WRONG!
|
|
251
|
-
() => {
|
|
264
|
+
() => { validate(path.propertyValue, required()); }
|
|
252
265
|
);
|
|
253
266
|
|
|
254
|
-
// Array
|
|
255
|
-
notEmpty(path, options?: { message?: string })
|
|
267
|
+
// Array item schema operator
|
|
256
268
|
validateItems(arrayPath, itemValidatorsFn: (itemPath) => void)
|
|
257
269
|
```
|
|
258
270
|
|
|
@@ -426,26 +438,29 @@ const { value } = useFormControl(form.field as FieldNode<ExpectedType>);
|
|
|
426
438
|
|
|
427
439
|
### Validation Priority (IMPORTANT)
|
|
428
440
|
|
|
429
|
-
**
|
|
441
|
+
**Operators register validators; built-in factories return validators. Pass factories to `validate()`.**
|
|
442
|
+
|
|
443
|
+
Operators: `validate`, `validateAsync`, `applyWhen`, `apply`, `validateItems`.
|
|
444
|
+
Factories (return `Validator<TForm, TField>`): `required`, `email`, `min`, `max`, `minLength`, `maxLength`,
|
|
445
|
+
`pattern`, `url`, `phone`, `number`, `date`, `notEmpty`.
|
|
430
446
|
|
|
431
447
|
```typescript
|
|
432
|
-
// 1. BEST:
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
448
|
+
// 1. BEST: Pass built-in factories to validate()
|
|
449
|
+
validate(path.email, required());
|
|
450
|
+
validate(path.email, email());
|
|
451
|
+
validate(path.age, min(18));
|
|
452
|
+
validate(path.password, minLength(8));
|
|
453
|
+
validate(path.phone, pattern(/^\+7\d{10}$/));
|
|
438
454
|
|
|
439
|
-
// 2. GOOD:
|
|
440
|
-
validate(path.customField, (value,
|
|
441
|
-
// Custom logic that can't be expressed with built-in validators
|
|
455
|
+
// 2. GOOD: Custom validator when no factory fits. Signature: (value, control, root).
|
|
456
|
+
validate(path.customField, (value, control, root) => {
|
|
442
457
|
if (customCondition(value)) {
|
|
443
458
|
return { code: 'custom', message: 'Custom error' };
|
|
444
459
|
}
|
|
445
460
|
return null;
|
|
446
461
|
});
|
|
447
462
|
|
|
448
|
-
// 3. WRONG: Don't recreate built-in validators
|
|
463
|
+
// 3. WRONG: Don't recreate built-in validators inline
|
|
449
464
|
validate(path.email, (value) => {
|
|
450
465
|
if (!value) return { code: 'required', message: 'Required' }; // Use required() instead!
|
|
451
466
|
if (!value.includes('@')) return { code: 'email', message: 'Invalid' }; // Use email() instead!
|
|
@@ -532,6 +547,68 @@ const behavior: BehaviorSchemaFn<LoanForm> = (path) => {
|
|
|
532
547
|
|
|
533
548
|
Reference patterns: `complex-multy-step-form/schemas/credit-application-behavior.ts`.
|
|
534
549
|
|
|
550
|
+
### Extracting Nested Rules
|
|
551
|
+
|
|
552
|
+
When the body of `applyWhen` / `validate` grows beyond a few lines,
|
|
553
|
+
extract it to a **named top-level function** typed with one of the public types from
|
|
554
|
+
`@reformer/core`:
|
|
555
|
+
|
|
556
|
+
- `ValidationSchemaFn<TForm>` — sub-schema passed to `applyWhen` or `apply`.
|
|
557
|
+
- `Validator<TForm, TField>` / `AsyncValidator<TForm, TField>` — field validator passed to `validate` / `validateAsync`. Cross-field правила пишутся в той же сигнатуре — `(value, control, root) => …` — и навешиваются на конкретное поле-носитель ошибки.
|
|
558
|
+
|
|
559
|
+
This keeps the schema body flat (reads like a table of contents) and surfaces the
|
|
560
|
+
**intent** of each rule via a meaningful name.
|
|
561
|
+
|
|
562
|
+
```typescript
|
|
563
|
+
import type { ValidationSchemaFn, Validator } from '@reformer/core';
|
|
564
|
+
|
|
565
|
+
// 1. Cross-field rule — extracted Validator (reads other fields via `root`)
|
|
566
|
+
const initialPaymentVsPropertyValue: Validator<CreditApplicationForm, unknown> = (
|
|
567
|
+
_value,
|
|
568
|
+
_control,
|
|
569
|
+
root
|
|
570
|
+
) => {
|
|
571
|
+
const form = root.getValue();
|
|
572
|
+
if (form.initialPayment && form.propertyValue && form.initialPayment > form.propertyValue) {
|
|
573
|
+
return { code: 'initialPaymentTooHigh', message: 'Взнос не может превышать стоимость' };
|
|
574
|
+
}
|
|
575
|
+
return null;
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
// 2. Custom field validator — extracted Validator
|
|
579
|
+
const validateAdultAge: Validator<CreditApplicationForm, string | undefined> = (value) => {
|
|
580
|
+
if (!value) return null;
|
|
581
|
+
const age = new Date().getFullYear() - new Date(value).getFullYear();
|
|
582
|
+
if (age < 18) return { code: 'tooYoung', message: 'Минимум 18 лет' };
|
|
583
|
+
return null;
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
// 3. Nested schema for applyWhen — extracted ValidationSchemaFn
|
|
587
|
+
const mortgageFieldsRules: ValidationSchemaFn<CreditApplicationForm> = (path) => {
|
|
588
|
+
validate(path.propertyValue, required());
|
|
589
|
+
validate(path.propertyValue, min(1000000));
|
|
590
|
+
validate(path.initialPayment, required());
|
|
591
|
+
validate(path.initialPayment, initialPaymentVsPropertyValue);
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
// 4. Main schema — flat, reads as a table of contents
|
|
595
|
+
export const basicInfoValidation: ValidationSchemaFn<CreditApplicationForm> = (path) => {
|
|
596
|
+
validate(path.loanType, required());
|
|
597
|
+
validate(path.personalData.birthDate, validateAdultAge);
|
|
598
|
+
applyWhen(path.loanType, (type) => type === 'mortgage', mortgageFieldsRules);
|
|
599
|
+
};
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
**Naming convention** (camelCase, semantic — not echoing the operator name):
|
|
603
|
+
|
|
604
|
+
- `applyWhen` sub-schema → describes the conditional branch: `mortgageFieldsRules`, `employedFieldsRules`.
|
|
605
|
+
- Cross-field `Validator` → describes the invariant: `initialPaymentVsPropertyValue`, `paymentToIncomeUnderHalf`.
|
|
606
|
+
- Field-level `Validator` → describes the check: `validateAdultAge`, `validatePasswordsMatch`.
|
|
607
|
+
|
|
608
|
+
**When to extract.** Inline lambdas are fine for short one-liners
|
|
609
|
+
(`applyWhen(path.x, (v) => v === 'mortgage', mortgageFieldsRules)` — the condition stays inline).
|
|
610
|
+
Extract whenever the body spans more than ~3 lines or contains nested rules.
|
|
611
|
+
|
|
535
612
|
## 6. 4. COMMON MISTAKES
|
|
536
613
|
|
|
537
614
|
### TSC overload-resolution error: `'form' does not exist in FormSchema<T>`
|
|
@@ -1274,19 +1351,32 @@ enableWhen(path.vehicle.vin, (form) => form.insuranceType === 'casco', { resetOn
|
|
|
1274
1351
|
|
|
1275
1352
|
See `22-cycle-detection.md` for complete pattern.
|
|
1276
1353
|
|
|
1277
|
-
###
|
|
1354
|
+
### Cross-field валидация — через `validate` + `root`
|
|
1278
1355
|
|
|
1279
1356
|
```typescript
|
|
1280
|
-
//
|
|
1281
|
-
|
|
1357
|
+
// Validator signature: (value, control, root) => ValidationError | null
|
|
1358
|
+
// Cross-field правило вешается на ПОЛЕ-НОСИТЕЛЬ ошибки. Соседние поля читаются через `root`.
|
|
1282
1359
|
|
|
1283
|
-
// CORRECT
|
|
1284
|
-
|
|
1285
|
-
|
|
1360
|
+
// CORRECT — ошибка ложится на path.field1
|
|
1361
|
+
validate(path.field1, (_value, _control, root) => {
|
|
1362
|
+
const form = root.getValue(); // typed as TForm
|
|
1363
|
+
if (form.field1 > form.field2) {
|
|
1286
1364
|
return { code: 'error', message: 'Invalid' };
|
|
1287
1365
|
}
|
|
1288
1366
|
return null;
|
|
1289
1367
|
});
|
|
1368
|
+
|
|
1369
|
+
// CORRECT — те же поля через reactive-доступ
|
|
1370
|
+
validate(path.address.city, (value, _control, root) => {
|
|
1371
|
+
if (!value && root.address.region.value.value) {
|
|
1372
|
+
return { code: 'cityRequired', message: 'City required when region is set' };
|
|
1373
|
+
}
|
|
1374
|
+
return null;
|
|
1375
|
+
});
|
|
1376
|
+
|
|
1377
|
+
// WRONG - old API removed
|
|
1378
|
+
validateGroup(scopePath, (scope, root) => { ... }); // validateGroup убран
|
|
1379
|
+
validateTree((ctx) => { ... }); // validateTree no longer exists
|
|
1290
1380
|
```
|
|
1291
1381
|
|
|
1292
1382
|
## 16. 14. PROJECT STRUCTURE (COLOCATION)
|
|
@@ -1787,18 +1877,18 @@ The "one watcher per trigger" cycle-prevention rule means **never register two w
|
|
|
1787
1877
|
|
|
1788
1878
|
```typescript
|
|
1789
1879
|
// WRONG - bracket notation does NOT work!
|
|
1790
|
-
const first = form.items[0];
|
|
1791
|
-
const second = form.items[1];
|
|
1880
|
+
const first = form.items[0]; // undefined or error
|
|
1881
|
+
const second = form.items[1]; // undefined or error
|
|
1792
1882
|
|
|
1793
1883
|
// CORRECT - use .at() method
|
|
1794
|
-
const first = form.items.at(0);
|
|
1795
|
-
const second = form.items.at(1);
|
|
1884
|
+
const first = form.items.at(0); // FormProxy<ItemType> | undefined
|
|
1885
|
+
const second = form.items.at(1); // FormProxy<ItemType> | undefined
|
|
1796
1886
|
|
|
1797
1887
|
// CORRECT - iterate with map (most common pattern)
|
|
1798
1888
|
form.items.map((item, index) => {
|
|
1799
1889
|
// item is fully typed GroupNode
|
|
1800
1890
|
item.name.setValue('New Name');
|
|
1801
|
-
item.price.value.value;
|
|
1891
|
+
item.price.value.value; // read value
|
|
1802
1892
|
});
|
|
1803
1893
|
```
|
|
1804
1894
|
|
|
@@ -1841,7 +1931,9 @@ function ItemsList({ form }: { form: FormProxy<MyForm> }) {
|
|
|
1841
1931
|
|
|
1842
1932
|
{length === 0 && <p>No items yet</p>}
|
|
1843
1933
|
|
|
1844
|
-
<button onClick={() => form.items.push({ name: '', price: 0 })}>
|
|
1934
|
+
<button onClick={() => form.items.push({ name: '', price: 0 })}>
|
|
1935
|
+
Add Item
|
|
1936
|
+
</button>
|
|
1845
1937
|
</div>
|
|
1846
1938
|
);
|
|
1847
1939
|
}
|
|
@@ -1849,35 +1941,35 @@ function ItemsList({ form }: { form: FormProxy<MyForm> }) {
|
|
|
1849
1941
|
|
|
1850
1942
|
### Array Cross-Validation
|
|
1851
1943
|
|
|
1944
|
+
Cross-field правила по массиву пишутся как обычный `Validator`, вешаются на сам массив
|
|
1945
|
+
(или на любое поле-носитель ошибки), а данные читаются через `root`.
|
|
1946
|
+
|
|
1852
1947
|
```typescript
|
|
1853
1948
|
// Validate uniqueness across array items
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
},
|
|
1865
|
-
{ targetField: 'items' }
|
|
1866
|
-
);
|
|
1949
|
+
validate(path.items, (_value, _control, root) => {
|
|
1950
|
+
const items = root.items;
|
|
1951
|
+
const names = items.map((item) => item.name.value.value);
|
|
1952
|
+
const uniqueNames = new Set(names);
|
|
1953
|
+
|
|
1954
|
+
if (names.length !== uniqueNames.size) {
|
|
1955
|
+
return { code: 'duplicate', message: 'Item names must be unique' };
|
|
1956
|
+
}
|
|
1957
|
+
return null;
|
|
1958
|
+
});
|
|
1867
1959
|
|
|
1868
1960
|
// Validate sum of percentages
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1961
|
+
validate(path.items, (_value, _control, root) => {
|
|
1962
|
+
const items = root.items;
|
|
1963
|
+
const totalPercent = items.reduce(
|
|
1964
|
+
(sum, item) => sum + (item.percentage.value.value || 0),
|
|
1965
|
+
0
|
|
1966
|
+
);
|
|
1873
1967
|
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
{ targetField: 'items' }
|
|
1880
|
-
);
|
|
1968
|
+
if (Math.abs(totalPercent - 100) > 0.01) {
|
|
1969
|
+
return { code: 'invalid_total', message: 'Percentages must sum to 100%' };
|
|
1970
|
+
}
|
|
1971
|
+
return null;
|
|
1972
|
+
});
|
|
1881
1973
|
```
|
|
1882
1974
|
|
|
1883
1975
|
## 22. Cycle Detection Prevention Checklist
|
|
@@ -4265,6 +4357,25 @@ export interface ArrayNodeLike {
|
|
|
4265
4357
|
|
|
4266
4358
|
_Source: src/core/types/index.ts_
|
|
4267
4359
|
|
|
4360
|
+
### AsyncValidator
|
|
4361
|
+
|
|
4362
|
+
**Kind:** `type`
|
|
4363
|
+
|
|
4364
|
+
Чистый асинхронный валидатор поля.
|
|
4365
|
+
|
|
4366
|
+
Регистрируется через `validateAsync(path, validator, { debounce })`.
|
|
4367
|
+
|
|
4368
|
+
**Signature:**
|
|
4369
|
+
```typescript
|
|
4370
|
+
export type AsyncValidator<TForm, TField> = (
|
|
4371
|
+
value: TField,
|
|
4372
|
+
control: FormProxy<TField>,
|
|
4373
|
+
root: FormProxy<TForm>
|
|
4374
|
+
) => Promise<ValidationError | null>;
|
|
4375
|
+
```
|
|
4376
|
+
|
|
4377
|
+
_Source: src/core/types/validation-schema.ts_
|
|
4378
|
+
|
|
4268
4379
|
### AsyncValidatorFn
|
|
4269
4380
|
|
|
4270
4381
|
**Kind:** `type`
|
|
@@ -4611,7 +4722,7 @@ _Source: src/core/behavior/types.ts_
|
|
|
4611
4722
|
|
|
4612
4723
|
**Kind:** `type`
|
|
4613
4724
|
|
|
4614
|
-
Функция условия для applyWhen
|
|
4725
|
+
Функция условия для applyWhen.
|
|
4615
4726
|
|
|
4616
4727
|
**Signature:**
|
|
4617
4728
|
```typescript
|
|
@@ -4651,61 +4762,6 @@ export interface ConfigWithValue {
|
|
|
4651
4762
|
|
|
4652
4763
|
_Source: src/core/types/index.ts_
|
|
4653
4764
|
|
|
4654
|
-
### ContextualAsyncValidatorFn
|
|
4655
|
-
|
|
4656
|
-
**Kind:** `type`
|
|
4657
|
-
|
|
4658
|
-
Асинхронная функция валидации поля с контекстом
|
|
4659
|
-
|
|
4660
|
-
**Signature:**
|
|
4661
|
-
```typescript
|
|
4662
|
-
export type ContextualAsyncValidatorFn<TForm, TField> = (
|
|
4663
|
-
value: TField,
|
|
4664
|
-
ctx: FormContext<TForm>
|
|
4665
|
-
) => Promise<ValidationError | null>;
|
|
4666
|
-
```
|
|
4667
|
-
|
|
4668
|
-
**Examples:**
|
|
4669
|
-
|
|
4670
|
-
```typescript
|
|
4671
|
-
validateAsync(path.email, async (value, ctx) => {
|
|
4672
|
-
const exists = await checkEmailExists(value);
|
|
4673
|
-
if (exists) return { code: 'exists', message: 'Email already taken' };
|
|
4674
|
-
return null;
|
|
4675
|
-
});
|
|
4676
|
-
```
|
|
4677
|
-
|
|
4678
|
-
_Source: src/core/types/validation-schema.ts_
|
|
4679
|
-
|
|
4680
|
-
### ContextualValidatorFn
|
|
4681
|
-
|
|
4682
|
-
**Kind:** `type`
|
|
4683
|
-
|
|
4684
|
-
Функция валидации поля с контекстом
|
|
4685
|
-
|
|
4686
|
-
Новый паттерн: (value, ctx: FormContext) => ValidationError | null
|
|
4687
|
-
|
|
4688
|
-
**Signature:**
|
|
4689
|
-
```typescript
|
|
4690
|
-
export type ContextualValidatorFn<TForm, TField> = (
|
|
4691
|
-
value: TField,
|
|
4692
|
-
ctx: FormContext<TForm>
|
|
4693
|
-
) => ValidationError | null;
|
|
4694
|
-
```
|
|
4695
|
-
|
|
4696
|
-
**Examples:**
|
|
4697
|
-
|
|
4698
|
-
```typescript
|
|
4699
|
-
validate(path.email, (value, ctx) => {
|
|
4700
|
-
if (!value) return { code: 'required', message: 'Email required' };
|
|
4701
|
-
const confirm = ctx.form.confirmEmail.value.value;
|
|
4702
|
-
if (value !== confirm) return { code: 'mismatch', message: 'Must match' };
|
|
4703
|
-
return null;
|
|
4704
|
-
});
|
|
4705
|
-
```
|
|
4706
|
-
|
|
4707
|
-
_Source: src/core/types/validation-schema.ts_
|
|
4708
|
-
|
|
4709
4765
|
### copyFrom
|
|
4710
4766
|
|
|
4711
4767
|
**Kind:** `function`
|
|
@@ -4978,43 +5034,22 @@ _Source: src/core/behavior/behaviors/enable-when.ts_
|
|
|
4978
5034
|
|
|
4979
5035
|
**Kind:** `function`
|
|
4980
5036
|
|
|
4981
|
-
|
|
5037
|
+
Фабрика валидатора формата email.
|
|
4982
5038
|
|
|
4983
|
-
Проверяет, что значение соответствует формату email адреса.
|
|
4984
5039
|
Пустые значения пропускаются (используйте `required` для обязательности).
|
|
4985
5040
|
|
|
4986
5041
|
**Signature:**
|
|
4987
5042
|
```typescript
|
|
4988
|
-
export function email<TForm, TField extends string |
|
|
4989
|
-
fieldPath: FieldPathNode<TForm, TField> | undefined,
|
|
5043
|
+
export function email<TForm = unknown, TField extends string | undefined = string>(
|
|
4990
5044
|
options?: ValidateOptions
|
|
4991
|
-
):
|
|
5045
|
+
): Validator<TForm, TField>
|
|
4992
5046
|
```
|
|
4993
5047
|
|
|
4994
|
-
**Parameters:**
|
|
4995
|
-
- `fieldPath` — - Путь к полю для валидации
|
|
4996
|
-
- `options` — - Опции валидации (message, params)
|
|
4997
|
-
|
|
4998
5048
|
**Examples:**
|
|
4999
5049
|
|
|
5000
5050
|
```typescript
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
required(path.email),
|
|
5004
|
-
email(path.email),
|
|
5005
|
-
]
|
|
5006
|
-
|
|
5007
|
-
// С кастомным сообщением
|
|
5008
|
-
email(path.email, { message: 'Введите корректный email адрес' })
|
|
5009
|
-
```
|
|
5010
|
-
|
|
5011
|
-
```typescript
|
|
5012
|
-
// Ошибка валидации
|
|
5013
|
-
{
|
|
5014
|
-
code: 'email',
|
|
5015
|
-
message: 'Неверный формат email',
|
|
5016
|
-
params: {}
|
|
5017
|
-
}
|
|
5051
|
+
validate(path.email, email());
|
|
5052
|
+
validate(path.email, email({ message: 'Введите корректный email' }));
|
|
5018
5053
|
```
|
|
5019
5054
|
|
|
5020
5055
|
_Source: src/core/validation/validators/email.ts_
|
|
@@ -5529,15 +5564,20 @@ const validation = (path: FieldPath<MyForm>) => {
|
|
|
5529
5564
|
|
|
5530
5565
|
**Signature:**
|
|
5531
5566
|
```typescript
|
|
5532
|
-
export type FieldPath<T> =
|
|
5533
|
-
|
|
5534
|
-
?
|
|
5535
|
-
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5567
|
+
export type FieldPath<T> =
|
|
5568
|
+
NonNullable<T> extends object
|
|
5569
|
+
? NonNullable<T> extends Array<unknown> | Date | File | Blob | AnyFunction
|
|
5570
|
+
? FieldPathNode<unknown, T> // Опаковые объекты — не разворачиваем в mapped type
|
|
5571
|
+
: {
|
|
5572
|
+
[K in keyof T]: NonNullable<T[K]> extends Array<unknown>
|
|
5573
|
+
? FieldPathNode<T, T[K], K> // Массивы - не рекурсим (обрабатываются отдельно)
|
|
5574
|
+
: NonNullable<T[K]> extends Date | File | Blob | AnyFunction
|
|
5575
|
+
? FieldPathNode<T, T[K], K> // Специальные объекты - не рекурсим
|
|
5576
|
+
: NonNullable<T[K]> extends object
|
|
5577
|
+
? FieldPathNode<T, T[K], K> & FieldPath<NonNullable<T[K]>> // Обычные объекты - рекурсия!
|
|
5578
|
+
: FieldPathNode<T, T[K], K>; // Примитивы
|
|
5579
|
+
}
|
|
5580
|
+
: FieldPathNode<unknown, T>;
|
|
5541
5581
|
```
|
|
5542
5582
|
|
|
5543
5583
|
_Source: src/core/types/field-path.ts_
|
|
@@ -6276,41 +6316,23 @@ _Source: src/core/types/index.ts_
|
|
|
6276
6316
|
|
|
6277
6317
|
**Kind:** `function`
|
|
6278
6318
|
|
|
6279
|
-
|
|
6319
|
+
Фабрика валидатора, проверяющего что дата не в прошлом.
|
|
6280
6320
|
|
|
6281
|
-
Пустые
|
|
6321
|
+
Пустые и невалидные даты пропускаются.
|
|
6282
6322
|
|
|
6283
6323
|
**Signature:**
|
|
6284
6324
|
```typescript
|
|
6285
|
-
export function futureDate<
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
):
|
|
6325
|
+
export function futureDate<
|
|
6326
|
+
TForm = unknown,
|
|
6327
|
+
TField extends string | Date | undefined = string | Date,
|
|
6328
|
+
>(options?: ValidateOptions): Validator<TForm, TField>
|
|
6289
6329
|
```
|
|
6290
6330
|
|
|
6291
|
-
**Parameters:**
|
|
6292
|
-
- `fieldPath` — - Путь к полю для валидации
|
|
6293
|
-
- `options` — - Опции валидации (message, params)
|
|
6294
|
-
|
|
6295
6331
|
**Examples:**
|
|
6296
6332
|
|
|
6297
6333
|
```typescript
|
|
6298
|
-
|
|
6299
|
-
|
|
6300
|
-
futureDate(path.eventDate),
|
|
6301
|
-
]
|
|
6302
|
-
|
|
6303
|
-
// С кастомным сообщением
|
|
6304
|
-
futureDate(path.appointmentDate, { message: 'Дата записи должна быть в будущем' })
|
|
6305
|
-
```
|
|
6306
|
-
|
|
6307
|
-
```typescript
|
|
6308
|
-
// Ошибка валидации
|
|
6309
|
-
{
|
|
6310
|
-
code: 'date_past',
|
|
6311
|
-
message: 'Дата не может быть в прошлом',
|
|
6312
|
-
params: {}
|
|
6313
|
-
}
|
|
6334
|
+
validate(path.eventDate, futureDate());
|
|
6335
|
+
validate(path.appointmentDate, futureDate({ message: 'Дата записи должна быть в будущем' }));
|
|
6314
6336
|
```
|
|
6315
6337
|
|
|
6316
6338
|
_Source: src/core/validation/validators/future-date.ts_
|
|
@@ -6485,6 +6507,30 @@ export interface GroupNodeConfig<T> {
|
|
|
6485
6507
|
|
|
6486
6508
|
_Source: src/core/types/index.ts_
|
|
6487
6509
|
|
|
6510
|
+
### integer
|
|
6511
|
+
|
|
6512
|
+
**Kind:** `function`
|
|
6513
|
+
|
|
6514
|
+
Фабрика валидатора, проверяющего что число — целое.
|
|
6515
|
+
|
|
6516
|
+
Пустые значения и не-числа пропускаются (используйте `required` и `isNumber`).
|
|
6517
|
+
|
|
6518
|
+
**Signature:**
|
|
6519
|
+
```typescript
|
|
6520
|
+
export function integer<TForm = unknown, TField extends number | undefined = number>(
|
|
6521
|
+
options?: ValidateOptions
|
|
6522
|
+
): Validator<TForm, TField>
|
|
6523
|
+
```
|
|
6524
|
+
|
|
6525
|
+
**Examples:**
|
|
6526
|
+
|
|
6527
|
+
```typescript
|
|
6528
|
+
validate(path.age, integer());
|
|
6529
|
+
validate(path.count, integer({ message: 'Должно быть целым числом' }));
|
|
6530
|
+
```
|
|
6531
|
+
|
|
6532
|
+
_Source: src/core/validation/validators/integer.ts_
|
|
6533
|
+
|
|
6488
6534
|
### isArrayNode
|
|
6489
6535
|
|
|
6490
6536
|
**Kind:** `function`
|
|
@@ -6520,42 +6566,22 @@ _Source: src/core/utils/type-guards.ts_
|
|
|
6520
6566
|
|
|
6521
6567
|
**Kind:** `function`
|
|
6522
6568
|
|
|
6523
|
-
|
|
6569
|
+
Фабрика валидатора, проверяющего что значение — валидная дата.
|
|
6524
6570
|
|
|
6525
6571
|
Пустые значения пропускаются (используйте `required` для обязательности).
|
|
6526
6572
|
|
|
6527
6573
|
**Signature:**
|
|
6528
6574
|
```typescript
|
|
6529
|
-
export function isDate<TForm, TField extends string | Date | undefined = string | Date>(
|
|
6530
|
-
fieldPath: FieldPathNode<TForm, TField> | undefined,
|
|
6575
|
+
export function isDate<TForm = unknown, TField extends string | Date | undefined = string | Date>(
|
|
6531
6576
|
options?: ValidateOptions
|
|
6532
|
-
):
|
|
6577
|
+
): Validator<TForm, TField>
|
|
6533
6578
|
```
|
|
6534
6579
|
|
|
6535
|
-
**Parameters:**
|
|
6536
|
-
- `fieldPath` — - Путь к полю для валидации
|
|
6537
|
-
- `options` — - Опции валидации (message, params)
|
|
6538
|
-
|
|
6539
6580
|
**Examples:**
|
|
6540
6581
|
|
|
6541
6582
|
```typescript
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
isDate(path.birthDate),
|
|
6545
|
-
isDate(path.eventDate),
|
|
6546
|
-
]
|
|
6547
|
-
|
|
6548
|
-
// С кастомным сообщением
|
|
6549
|
-
isDate(path.birthDate, { message: 'Введите корректную дату' })
|
|
6550
|
-
```
|
|
6551
|
-
|
|
6552
|
-
```typescript
|
|
6553
|
-
// Ошибка валидации
|
|
6554
|
-
{
|
|
6555
|
-
code: 'date_invalid',
|
|
6556
|
-
message: 'Неверный формат даты',
|
|
6557
|
-
params: {}
|
|
6558
|
-
}
|
|
6583
|
+
validate(path.birthDate, isDate());
|
|
6584
|
+
validate(path.eventDate, isDate({ message: 'Введите корректную дату' }));
|
|
6559
6585
|
```
|
|
6560
6586
|
|
|
6561
6587
|
_Source: src/core/validation/validators/is-date.ts_
|
|
@@ -6650,49 +6676,55 @@ if (isGroupNode(node)) {
|
|
|
6650
6676
|
|
|
6651
6677
|
_Source: src/core/utils/type-guards.ts_
|
|
6652
6678
|
|
|
6653
|
-
###
|
|
6679
|
+
### isNumber
|
|
6654
6680
|
|
|
6655
6681
|
**Kind:** `function`
|
|
6656
6682
|
|
|
6657
|
-
|
|
6683
|
+
Фабрика валидатора, проверяющего что значение — конечное число (не NaN, не строка).
|
|
6658
6684
|
|
|
6659
|
-
|
|
6660
|
-
|
|
6685
|
+
Пустые значения (`null`/`undefined`) пропускаются (используйте `required` для обязательности).
|
|
6686
|
+
В отличие от других number-валидаторов, **не** пропускает не-числа — это его задача.
|
|
6661
6687
|
|
|
6662
6688
|
**Signature:**
|
|
6663
6689
|
```typescript
|
|
6664
|
-
export function
|
|
6665
|
-
fieldPath: FieldPathNode<TForm, TField> | undefined,
|
|
6666
|
-
maxValue: number,
|
|
6690
|
+
export function isNumber<TForm = unknown, TField extends number | undefined = number>(
|
|
6667
6691
|
options?: ValidateOptions
|
|
6668
|
-
):
|
|
6692
|
+
): Validator<TForm, TField>
|
|
6669
6693
|
```
|
|
6670
6694
|
|
|
6671
|
-
**Parameters:**
|
|
6672
|
-
- `fieldPath` — - Путь к полю для валидации
|
|
6673
|
-
- `maxValue` — - Максимально допустимое значение
|
|
6674
|
-
- `options` — - Опции валидации (message, params)
|
|
6675
|
-
|
|
6676
6695
|
**Examples:**
|
|
6677
6696
|
|
|
6678
6697
|
```typescript
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6698
|
+
validate(path.amount, isNumber());
|
|
6699
|
+
validate(path.amount, isNumber({ message: 'Введите число' }));
|
|
6700
|
+
```
|
|
6701
|
+
|
|
6702
|
+
_Source: src/core/validation/validators/is-number.ts_
|
|
6684
6703
|
|
|
6685
|
-
|
|
6686
|
-
|
|
6704
|
+
### max
|
|
6705
|
+
|
|
6706
|
+
**Kind:** `function`
|
|
6707
|
+
|
|
6708
|
+
Фабрика валидатора максимального числового значения.
|
|
6709
|
+
|
|
6710
|
+
Пустые значения пропускаются (используйте `required` для обязательности).
|
|
6711
|
+
|
|
6712
|
+
**Signature:**
|
|
6713
|
+
```typescript
|
|
6714
|
+
export function max<TForm = unknown, TField extends number | undefined = number>(
|
|
6715
|
+
maxValue: number,
|
|
6716
|
+
options?: ValidateOptions
|
|
6717
|
+
): Validator<TForm, TField>
|
|
6687
6718
|
```
|
|
6688
6719
|
|
|
6720
|
+
**Examples:**
|
|
6721
|
+
|
|
6689
6722
|
```typescript
|
|
6690
|
-
|
|
6691
|
-
{
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
}
|
|
6723
|
+
import { validate } from '@reformer/core';
|
|
6724
|
+
import { max } from '@reformer/core/validators';
|
|
6725
|
+
|
|
6726
|
+
validate(path.quantity, max(100));
|
|
6727
|
+
validate(path.discount, max(50, { message: 'Не более 50%' }));
|
|
6696
6728
|
```
|
|
6697
6729
|
|
|
6698
6730
|
_Source: src/core/validation/validators/max.ts_
|
|
@@ -6701,43 +6733,23 @@ _Source: src/core/validation/validators/max.ts_
|
|
|
6701
6733
|
|
|
6702
6734
|
**Kind:** `function`
|
|
6703
6735
|
|
|
6704
|
-
|
|
6736
|
+
Фабрика валидатора максимального возраста (по дате рождения).
|
|
6705
6737
|
|
|
6706
|
-
Пустые
|
|
6738
|
+
Пустые и невалидные даты пропускаются.
|
|
6707
6739
|
|
|
6708
6740
|
**Signature:**
|
|
6709
6741
|
```typescript
|
|
6710
|
-
export function maxAge<
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
): void
|
|
6742
|
+
export function maxAge<
|
|
6743
|
+
TForm = unknown,
|
|
6744
|
+
TField extends string | Date | null | undefined = string | Date,
|
|
6745
|
+
>(maxAgeValue: number, options?: ValidateOptions): Validator<TForm, TField>
|
|
6715
6746
|
```
|
|
6716
6747
|
|
|
6717
|
-
**Parameters:**
|
|
6718
|
-
- `fieldPath` — - Путь к полю для валидации (дата рождения)
|
|
6719
|
-
- `maxAgeValue` — - Максимально допустимый возраст в годах
|
|
6720
|
-
- `options` — - Опции валидации (message, params)
|
|
6721
|
-
|
|
6722
6748
|
**Examples:**
|
|
6723
6749
|
|
|
6724
6750
|
```typescript
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
maxAge(path.birthDate, 65),
|
|
6728
|
-
]
|
|
6729
|
-
|
|
6730
|
-
// С кастомным сообщением
|
|
6731
|
-
maxAge(path.birthDate, 100, { message: 'Проверьте правильность даты рождения' })
|
|
6732
|
-
```
|
|
6733
|
-
|
|
6734
|
-
```typescript
|
|
6735
|
-
// Ошибка валидации
|
|
6736
|
-
{
|
|
6737
|
-
code: 'date_max_age',
|
|
6738
|
-
message: 'Максимальный возраст: 65 лет',
|
|
6739
|
-
params: { maxAge: 65, currentAge: 70 }
|
|
6740
|
-
}
|
|
6751
|
+
validate(path.birthDate, maxAge(65));
|
|
6752
|
+
validate(path.birthDate, maxAge(100, { message: 'Проверьте дату рождения' }));
|
|
6741
6753
|
```
|
|
6742
6754
|
|
|
6743
6755
|
_Source: src/core/validation/validators/max-age.ts_
|
|
@@ -6746,43 +6758,23 @@ _Source: src/core/validation/validators/max-age.ts_
|
|
|
6746
6758
|
|
|
6747
6759
|
**Kind:** `function`
|
|
6748
6760
|
|
|
6749
|
-
|
|
6761
|
+
Фабрика валидатора максимальной даты (включительно).
|
|
6750
6762
|
|
|
6751
|
-
Пустые
|
|
6763
|
+
Пустые и невалидные даты пропускаются.
|
|
6752
6764
|
|
|
6753
6765
|
**Signature:**
|
|
6754
6766
|
```typescript
|
|
6755
|
-
export function maxDate<
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
): void
|
|
6767
|
+
export function maxDate<
|
|
6768
|
+
TForm = unknown,
|
|
6769
|
+
TField extends string | Date | null | undefined = string | Date,
|
|
6770
|
+
>(maxDateValue: Date, options?: ValidateOptions): Validator<TForm, TField>
|
|
6760
6771
|
```
|
|
6761
6772
|
|
|
6762
|
-
**Parameters:**
|
|
6763
|
-
- `fieldPath` — - Путь к полю для валидации
|
|
6764
|
-
- `maxDateValue` — - Максимально допустимая дата (включительно)
|
|
6765
|
-
- `options` — - Опции валидации (message, params)
|
|
6766
|
-
|
|
6767
6773
|
**Examples:**
|
|
6768
6774
|
|
|
6769
6775
|
```typescript
|
|
6770
|
-
//
|
|
6771
|
-
|
|
6772
|
-
maxDate(path.birthDate, new Date()), // Не позже сегодня
|
|
6773
|
-
]
|
|
6774
|
-
|
|
6775
|
-
// С кастомным сообщением
|
|
6776
|
-
maxDate(path.endDate, new Date('2025-12-31'), { message: 'Дата не может быть позже конца года' })
|
|
6777
|
-
```
|
|
6778
|
-
|
|
6779
|
-
```typescript
|
|
6780
|
-
// Ошибка валидации
|
|
6781
|
-
{
|
|
6782
|
-
code: 'date_max',
|
|
6783
|
-
message: 'Дата должна быть не позднее 31.12.2025',
|
|
6784
|
-
params: { maxDate: Date }
|
|
6785
|
-
}
|
|
6776
|
+
validate(path.birthDate, maxDate(new Date())); // не позже сегодня
|
|
6777
|
+
validate(path.endDate, maxDate(new Date('2025-12-31')));
|
|
6786
6778
|
```
|
|
6787
6779
|
|
|
6788
6780
|
_Source: src/core/validation/validators/max-date.ts_
|
|
@@ -6791,45 +6783,23 @@ _Source: src/core/validation/validators/max-date.ts_
|
|
|
6791
6783
|
|
|
6792
6784
|
**Kind:** `function`
|
|
6793
6785
|
|
|
6794
|
-
|
|
6786
|
+
Фабрика валидатора максимальной длины строки или массива.
|
|
6795
6787
|
|
|
6796
|
-
Проверяет, что длина строки не превышает указанный максимум.
|
|
6797
6788
|
Пустые значения пропускаются (используйте `required` для обязательности).
|
|
6798
6789
|
|
|
6799
6790
|
**Signature:**
|
|
6800
6791
|
```typescript
|
|
6801
|
-
export function maxLength<TForm, TField
|
|
6802
|
-
fieldPath: FieldPathNode<TForm, TField> | undefined,
|
|
6792
|
+
export function maxLength<TForm = unknown, TField = unknown>(
|
|
6803
6793
|
maxLen: number,
|
|
6804
6794
|
options?: ValidateOptions
|
|
6805
|
-
):
|
|
6795
|
+
): Validator<TForm, TField>
|
|
6806
6796
|
```
|
|
6807
6797
|
|
|
6808
|
-
**Parameters:**
|
|
6809
|
-
- `fieldPath` — - Путь к полю для валидации
|
|
6810
|
-
- `maxLen` — - Максимальная допустимая длина строки
|
|
6811
|
-
- `options` — - Опции валидации (message, params)
|
|
6812
|
-
|
|
6813
6798
|
**Examples:**
|
|
6814
6799
|
|
|
6815
6800
|
```typescript
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
maxLength(path.name, 50),
|
|
6819
|
-
maxLength(path.bio, 500),
|
|
6820
|
-
]
|
|
6821
|
-
|
|
6822
|
-
// С кастомным сообщением
|
|
6823
|
-
maxLength(path.bio, 500, { message: 'Максимум 500 символов' })
|
|
6824
|
-
```
|
|
6825
|
-
|
|
6826
|
-
```typescript
|
|
6827
|
-
// Ошибка валидации
|
|
6828
|
-
{
|
|
6829
|
-
code: 'maxLength',
|
|
6830
|
-
message: 'Максимальная длина: 500 символов',
|
|
6831
|
-
params: { maxLength: 500, actualLength: 512 }
|
|
6832
|
-
}
|
|
6801
|
+
validate(path.name, maxLength(50));
|
|
6802
|
+
validate(path.bio, maxLength(500, { message: 'Max 500 символов' }));
|
|
6833
6803
|
```
|
|
6834
6804
|
|
|
6835
6805
|
_Source: src/core/validation/validators/max-length.ts_
|
|
@@ -6838,45 +6808,26 @@ _Source: src/core/validation/validators/max-length.ts_
|
|
|
6838
6808
|
|
|
6839
6809
|
**Kind:** `function`
|
|
6840
6810
|
|
|
6841
|
-
|
|
6811
|
+
Фабрика валидатора минимального числового значения.
|
|
6842
6812
|
|
|
6843
|
-
Проверяет, что числовое значение не меньше указанного минимума.
|
|
6844
6813
|
Пустые значения пропускаются (используйте `required` для обязательности).
|
|
6845
6814
|
|
|
6846
6815
|
**Signature:**
|
|
6847
6816
|
```typescript
|
|
6848
|
-
export function min<TForm, TField extends number |
|
|
6849
|
-
fieldPath: FieldPathNode<TForm, TField> | undefined,
|
|
6817
|
+
export function min<TForm = unknown, TField extends number | undefined = number>(
|
|
6850
6818
|
minValue: number,
|
|
6851
6819
|
options?: ValidateOptions
|
|
6852
|
-
):
|
|
6820
|
+
): Validator<TForm, TField>
|
|
6853
6821
|
```
|
|
6854
6822
|
|
|
6855
|
-
**Parameters:**
|
|
6856
|
-
- `fieldPath` — - Путь к полю для валидации
|
|
6857
|
-
- `minValue` — - Минимально допустимое значение
|
|
6858
|
-
- `options` — - Опции валидации (message, params)
|
|
6859
|
-
|
|
6860
6823
|
**Examples:**
|
|
6861
6824
|
|
|
6862
6825
|
```typescript
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
min(path.age, 18),
|
|
6866
|
-
min(path.quantity, 1),
|
|
6867
|
-
]
|
|
6826
|
+
import { validate } from '@reformer/core';
|
|
6827
|
+
import { min } from '@reformer/core/validators';
|
|
6868
6828
|
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
```
|
|
6872
|
-
|
|
6873
|
-
```typescript
|
|
6874
|
-
// Ошибка валидации
|
|
6875
|
-
{
|
|
6876
|
-
code: 'min',
|
|
6877
|
-
message: 'Минимальное значение: 18',
|
|
6878
|
-
params: { min: 18, actual: 16 }
|
|
6879
|
-
}
|
|
6829
|
+
validate(path.age, min(18));
|
|
6830
|
+
validate(path.quantity, min(1, { message: 'Минимум 1' }));
|
|
6880
6831
|
```
|
|
6881
6832
|
|
|
6882
6833
|
_Source: src/core/validation/validators/min.ts_
|
|
@@ -6885,43 +6836,23 @@ _Source: src/core/validation/validators/min.ts_
|
|
|
6885
6836
|
|
|
6886
6837
|
**Kind:** `function`
|
|
6887
6838
|
|
|
6888
|
-
|
|
6839
|
+
Фабрика валидатора минимального возраста (по дате рождения).
|
|
6889
6840
|
|
|
6890
|
-
Пустые
|
|
6841
|
+
Пустые и невалидные даты пропускаются.
|
|
6891
6842
|
|
|
6892
6843
|
**Signature:**
|
|
6893
6844
|
```typescript
|
|
6894
|
-
export function minAge<
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
): void
|
|
6845
|
+
export function minAge<
|
|
6846
|
+
TForm = unknown,
|
|
6847
|
+
TField extends string | Date | null | undefined = string | Date,
|
|
6848
|
+
>(minAgeValue: number, options?: ValidateOptions): Validator<TForm, TField>
|
|
6899
6849
|
```
|
|
6900
6850
|
|
|
6901
|
-
**Parameters:**
|
|
6902
|
-
- `fieldPath` — - Путь к полю для валидации (дата рождения)
|
|
6903
|
-
- `minAgeValue` — - Минимально допустимый возраст в годах
|
|
6904
|
-
- `options` — - Опции валидации (message, params)
|
|
6905
|
-
|
|
6906
6851
|
**Examples:**
|
|
6907
6852
|
|
|
6908
6853
|
```typescript
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
minAge(path.birthDate, 18),
|
|
6912
|
-
]
|
|
6913
|
-
|
|
6914
|
-
// С кастомным сообщением
|
|
6915
|
-
minAge(path.birthDate, 21, { message: 'Вам должно быть не менее 21 года' })
|
|
6916
|
-
```
|
|
6917
|
-
|
|
6918
|
-
```typescript
|
|
6919
|
-
// Ошибка валидации
|
|
6920
|
-
{
|
|
6921
|
-
code: 'date_min_age',
|
|
6922
|
-
message: 'Минимальный возраст: 18 лет',
|
|
6923
|
-
params: { minAge: 18, currentAge: 16 }
|
|
6924
|
-
}
|
|
6854
|
+
validate(path.birthDate, minAge(18));
|
|
6855
|
+
validate(path.birthDate, minAge(21, { message: 'Вам должно быть не менее 21 года' }));
|
|
6925
6856
|
```
|
|
6926
6857
|
|
|
6927
6858
|
_Source: src/core/validation/validators/min-age.ts_
|
|
@@ -6930,43 +6861,23 @@ _Source: src/core/validation/validators/min-age.ts_
|
|
|
6930
6861
|
|
|
6931
6862
|
**Kind:** `function`
|
|
6932
6863
|
|
|
6933
|
-
|
|
6864
|
+
Фабрика валидатора минимальной даты (включительно).
|
|
6934
6865
|
|
|
6935
|
-
Пустые
|
|
6866
|
+
Пустые и невалидные даты пропускаются (используйте `required` и `isDate`).
|
|
6936
6867
|
|
|
6937
6868
|
**Signature:**
|
|
6938
6869
|
```typescript
|
|
6939
|
-
export function minDate<
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
): void
|
|
6870
|
+
export function minDate<
|
|
6871
|
+
TForm = unknown,
|
|
6872
|
+
TField extends string | Date | null | undefined = string | Date,
|
|
6873
|
+
>(minDateValue: Date, options?: ValidateOptions): Validator<TForm, TField>
|
|
6944
6874
|
```
|
|
6945
6875
|
|
|
6946
|
-
**Parameters:**
|
|
6947
|
-
- `fieldPath` — - Путь к полю для валидации
|
|
6948
|
-
- `minDateValue` — - Минимально допустимая дата (включительно)
|
|
6949
|
-
- `options` — - Опции валидации (message, params)
|
|
6950
|
-
|
|
6951
6876
|
**Examples:**
|
|
6952
6877
|
|
|
6953
6878
|
```typescript
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
minDate(path.eventDate, new Date('2024-01-01')),
|
|
6957
|
-
]
|
|
6958
|
-
|
|
6959
|
-
// С кастомным сообщением
|
|
6960
|
-
minDate(path.startDate, new Date(), { message: 'Дата должна быть не раньше сегодня' })
|
|
6961
|
-
```
|
|
6962
|
-
|
|
6963
|
-
```typescript
|
|
6964
|
-
// Ошибка валидации
|
|
6965
|
-
{
|
|
6966
|
-
code: 'date_min',
|
|
6967
|
-
message: 'Дата должна быть не ранее 01.01.2024',
|
|
6968
|
-
params: { minDate: Date }
|
|
6969
|
-
}
|
|
6879
|
+
validate(path.eventDate, minDate(new Date('2024-01-01')));
|
|
6880
|
+
validate(path.startDate, minDate(new Date(), { message: 'Дата должна быть не раньше сегодня' }));
|
|
6970
6881
|
```
|
|
6971
6882
|
|
|
6972
6883
|
_Source: src/core/validation/validators/min-date.ts_
|
|
@@ -6975,48 +6886,51 @@ _Source: src/core/validation/validators/min-date.ts_
|
|
|
6975
6886
|
|
|
6976
6887
|
**Kind:** `function`
|
|
6977
6888
|
|
|
6978
|
-
|
|
6889
|
+
Фабрика валидатора минимальной длины строки или массива.
|
|
6979
6890
|
|
|
6980
|
-
Проверяет, что длина строки не меньше указанного минимума.
|
|
6981
6891
|
Пустые значения пропускаются (используйте `required` для обязательности).
|
|
6982
6892
|
|
|
6983
6893
|
**Signature:**
|
|
6984
6894
|
```typescript
|
|
6985
|
-
export function minLength<TForm, TField
|
|
6986
|
-
fieldPath: FieldPathNode<TForm, TField> | undefined,
|
|
6895
|
+
export function minLength<TForm = unknown, TField = unknown>(
|
|
6987
6896
|
minLen: number,
|
|
6988
6897
|
options?: ValidateOptions
|
|
6989
|
-
):
|
|
6898
|
+
): Validator<TForm, TField>
|
|
6990
6899
|
```
|
|
6991
6900
|
|
|
6992
|
-
**Parameters:**
|
|
6993
|
-
- `fieldPath` — - Путь к полю для валидации
|
|
6994
|
-
- `minLen` — - Минимальная допустимая длина строки
|
|
6995
|
-
- `options` — - Опции валидации (message, params)
|
|
6996
|
-
|
|
6997
6901
|
**Examples:**
|
|
6998
6902
|
|
|
6999
6903
|
```typescript
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
6904
|
+
validate(path.name, minLength(2));
|
|
6905
|
+
validate(path.password, minLength(8, { message: 'Min 8 символов' }));
|
|
6906
|
+
```
|
|
6907
|
+
|
|
6908
|
+
_Source: src/core/validation/validators/min-length.ts_
|
|
6909
|
+
|
|
6910
|
+
### multipleOf
|
|
7005
6911
|
|
|
7006
|
-
|
|
7007
|
-
|
|
6912
|
+
**Kind:** `function`
|
|
6913
|
+
|
|
6914
|
+
Фабрика валидатора, проверяющего что число кратно заданному.
|
|
6915
|
+
|
|
6916
|
+
Пустые значения и не-числа пропускаются (используйте `required` и `isNumber`).
|
|
6917
|
+
|
|
6918
|
+
**Signature:**
|
|
6919
|
+
```typescript
|
|
6920
|
+
export function multipleOf<TForm = unknown, TField extends number | undefined = number>(
|
|
6921
|
+
divisor: number,
|
|
6922
|
+
options?: ValidateOptions
|
|
6923
|
+
): Validator<TForm, TField>
|
|
7008
6924
|
```
|
|
7009
6925
|
|
|
6926
|
+
**Examples:**
|
|
6927
|
+
|
|
7010
6928
|
```typescript
|
|
7011
|
-
|
|
7012
|
-
{
|
|
7013
|
-
code: 'minLength',
|
|
7014
|
-
message: 'Минимальная длина: 8 символов',
|
|
7015
|
-
params: { minLength: 8, actualLength: 3 }
|
|
7016
|
-
}
|
|
6929
|
+
validate(path.price, multipleOf(0.01));
|
|
6930
|
+
validate(path.rating, multipleOf(0.5, { message: 'Только шаг 0.5' }));
|
|
7017
6931
|
```
|
|
7018
6932
|
|
|
7019
|
-
_Source: src/core/validation/validators/
|
|
6933
|
+
_Source: src/core/validation/validators/multiple-of.ts_
|
|
7020
6934
|
|
|
7021
6935
|
### NodeFactory
|
|
7022
6936
|
|
|
@@ -7087,79 +7001,74 @@ const node = NodeFactory.create({ value: '' }); // → FieldNode<string>
|
|
|
7087
7001
|
|
|
7088
7002
|
_Source: src/core/factories/node-factory.ts_
|
|
7089
7003
|
|
|
7090
|
-
###
|
|
7004
|
+
### nonNegative
|
|
7091
7005
|
|
|
7092
7006
|
**Kind:** `function`
|
|
7093
7007
|
|
|
7094
|
-
|
|
7008
|
+
Фабрика валидатора, проверяющего что число неотрицательное (`≥ 0`).
|
|
7095
7009
|
|
|
7096
|
-
|
|
7010
|
+
Пустые значения и не-числа пропускаются (используйте `required` и `isNumber`).
|
|
7097
7011
|
|
|
7098
7012
|
**Signature:**
|
|
7099
7013
|
```typescript
|
|
7100
|
-
export function
|
|
7101
|
-
fieldPath: FieldPathNode<TForm, TItem[] | undefined> | undefined,
|
|
7014
|
+
export function nonNegative<TForm = unknown, TField extends number | undefined = number>(
|
|
7102
7015
|
options?: ValidateOptions
|
|
7103
|
-
):
|
|
7016
|
+
): Validator<TForm, TField>
|
|
7104
7017
|
```
|
|
7105
7018
|
|
|
7106
|
-
**Parameters:**
|
|
7107
|
-
- `fieldPath` — - Поле-массив для валидации
|
|
7108
|
-
- `options` — - Опции валидации (message, params и т.д.)
|
|
7109
|
-
|
|
7110
7019
|
**Examples:**
|
|
7111
7020
|
|
|
7112
7021
|
```typescript
|
|
7113
|
-
|
|
7114
|
-
|
|
7022
|
+
validate(path.quantity, nonNegative());
|
|
7023
|
+
validate(path.balance, nonNegative({ message: 'Баланс не может быть отрицательным' }));
|
|
7024
|
+
```
|
|
7115
7025
|
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7026
|
+
_Source: src/core/validation/validators/non-negative.ts_
|
|
7027
|
+
|
|
7028
|
+
### nonZero
|
|
7029
|
+
|
|
7030
|
+
**Kind:** `function`
|
|
7031
|
+
|
|
7032
|
+
Фабрика валидатора, проверяющего что число не равно нулю.
|
|
7033
|
+
|
|
7034
|
+
Пустые значения и не-числа пропускаются (используйте `required` и `isNumber`).
|
|
7035
|
+
|
|
7036
|
+
**Signature:**
|
|
7037
|
+
```typescript
|
|
7038
|
+
export function nonZero<TForm = unknown, TField extends number | undefined = number>(
|
|
7039
|
+
options?: ValidateOptions
|
|
7040
|
+
): Validator<TForm, TField>
|
|
7121
7041
|
```
|
|
7122
7042
|
|
|
7123
|
-
|
|
7043
|
+
**Examples:**
|
|
7044
|
+
|
|
7045
|
+
```typescript
|
|
7046
|
+
validate(path.quantity, nonZero());
|
|
7047
|
+
validate(path.divisor, nonZero({ message: 'Не может быть нулём' }));
|
|
7048
|
+
```
|
|
7124
7049
|
|
|
7125
|
-
|
|
7050
|
+
_Source: src/core/validation/validators/non-zero.ts_
|
|
7051
|
+
|
|
7052
|
+
### notEmpty
|
|
7126
7053
|
|
|
7127
7054
|
**Kind:** `function`
|
|
7128
7055
|
|
|
7129
|
-
|
|
7130
|
-
Проверяет, что значение является числом и соответствует заданным ограничениям
|
|
7056
|
+
Фабрика валидатора, проверяющего что массив (или строка) не пустой.
|
|
7131
7057
|
|
|
7132
7058
|
**Signature:**
|
|
7133
7059
|
```typescript
|
|
7134
|
-
export function
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
/** Минимальное значение (включительно) */
|
|
7138
|
-
min?: number;
|
|
7139
|
-
/** Максимальное значение (включительно) */
|
|
7140
|
-
max?: number;
|
|
7141
|
-
/** Требовать целое число */
|
|
7142
|
-
integer?: boolean;
|
|
7143
|
-
/** Значение должно быть кратно этому числу */
|
|
7144
|
-
multipleOf?: number;
|
|
7145
|
-
/** Разрешить отрицательные числа (по умолчанию true) */
|
|
7146
|
-
allowNegative?: boolean;
|
|
7147
|
-
/** Разрешить ноль (по умолчанию true) */
|
|
7148
|
-
allowZero?: boolean;
|
|
7149
|
-
}
|
|
7150
|
-
): void
|
|
7060
|
+
export function notEmpty<TForm = unknown, TField = unknown>(
|
|
7061
|
+
options?: ValidateOptions
|
|
7062
|
+
): Validator<TForm, TField>
|
|
7151
7063
|
```
|
|
7152
7064
|
|
|
7153
7065
|
**Examples:**
|
|
7154
7066
|
|
|
7155
7067
|
```typescript
|
|
7156
|
-
|
|
7157
|
-
number(path.price, { min: 0, max: 1000000 });
|
|
7158
|
-
number(path.percentage, { min: 0, max: 100, integer: true });
|
|
7159
|
-
number(path.rating, { min: 0, max: 5, multipleOf: 0.5 });
|
|
7068
|
+
validate(path.properties, notEmpty({ message: 'Добавьте хотя бы один элемент' }));
|
|
7160
7069
|
```
|
|
7161
7070
|
|
|
7162
|
-
_Source: src/core/validation/validators/
|
|
7071
|
+
_Source: src/core/validation/validators/array-validators.ts_
|
|
7163
7072
|
|
|
7164
7073
|
### ObservableForm
|
|
7165
7074
|
|
|
@@ -7204,41 +7113,21 @@ _Source: src/core/utils/form-observer.ts_
|
|
|
7204
7113
|
|
|
7205
7114
|
**Kind:** `function`
|
|
7206
7115
|
|
|
7207
|
-
|
|
7116
|
+
Фабрика валидатора, проверяющего что дата не в будущем.
|
|
7208
7117
|
|
|
7209
|
-
Пустые
|
|
7118
|
+
Пустые и невалидные даты пропускаются.
|
|
7210
7119
|
|
|
7211
7120
|
**Signature:**
|
|
7212
7121
|
```typescript
|
|
7213
|
-
export function pastDate<TForm, TField extends string | Date | undefined = string | Date>(
|
|
7214
|
-
fieldPath: FieldPathNode<TForm, TField> | undefined,
|
|
7122
|
+
export function pastDate<TForm = unknown, TField extends string | Date | undefined = string | Date>(
|
|
7215
7123
|
options?: ValidateOptions
|
|
7216
|
-
):
|
|
7124
|
+
): Validator<TForm, TField>
|
|
7217
7125
|
```
|
|
7218
7126
|
|
|
7219
|
-
**Parameters:**
|
|
7220
|
-
- `fieldPath` — - Путь к полю для валидации
|
|
7221
|
-
- `options` — - Опции валидации (message, params)
|
|
7222
|
-
|
|
7223
7127
|
**Examples:**
|
|
7224
7128
|
|
|
7225
7129
|
```typescript
|
|
7226
|
-
|
|
7227
|
-
validationSchema: (path) => [
|
|
7228
|
-
pastDate(path.birthDate),
|
|
7229
|
-
]
|
|
7230
|
-
|
|
7231
|
-
// С кастомным сообщением
|
|
7232
|
-
pastDate(path.birthDate, { message: 'Дата рождения не может быть в будущем' })
|
|
7233
|
-
```
|
|
7234
|
-
|
|
7235
|
-
```typescript
|
|
7236
|
-
// Ошибка валидации
|
|
7237
|
-
{
|
|
7238
|
-
code: 'date_future',
|
|
7239
|
-
message: 'Дата не может быть в будущем',
|
|
7240
|
-
params: {}
|
|
7241
|
-
}
|
|
7130
|
+
validate(path.birthDate, pastDate({ message: 'Дата рождения не может быть в будущем' }));
|
|
7242
7131
|
```
|
|
7243
7132
|
|
|
7244
7133
|
_Source: src/core/validation/validators/past-date.ts_
|
|
@@ -7285,47 +7174,23 @@ _Source: src/core/utils/field-path-navigator.ts_
|
|
|
7285
7174
|
|
|
7286
7175
|
**Kind:** `function`
|
|
7287
7176
|
|
|
7288
|
-
|
|
7177
|
+
Фабрика валидатора регулярного выражения.
|
|
7289
7178
|
|
|
7290
|
-
Проверяет, что значение соответствует указанному регулярному выражению.
|
|
7291
7179
|
Пустые значения пропускаются (используйте `required` для обязательности).
|
|
7292
7180
|
|
|
7293
7181
|
**Signature:**
|
|
7294
7182
|
```typescript
|
|
7295
|
-
export function pattern<TForm, TField extends string |
|
|
7296
|
-
fieldPath: FieldPathNode<TForm, TField> | undefined,
|
|
7183
|
+
export function pattern<TForm = unknown, TField extends string | undefined = string>(
|
|
7297
7184
|
regex: RegExp,
|
|
7298
7185
|
options?: ValidateOptions
|
|
7299
|
-
):
|
|
7186
|
+
): Validator<TForm, TField>
|
|
7300
7187
|
```
|
|
7301
7188
|
|
|
7302
|
-
**Parameters:**
|
|
7303
|
-
- `fieldPath` — - Путь к полю для валидации
|
|
7304
|
-
- `regex` — - Регулярное выражение для проверки
|
|
7305
|
-
- `options` — - Опции валидации (message, params)
|
|
7306
|
-
|
|
7307
7189
|
**Examples:**
|
|
7308
7190
|
|
|
7309
7191
|
```typescript
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
// Только цифры
|
|
7314
|
-
pattern(path.code, /^\d+$/)
|
|
7315
|
-
|
|
7316
|
-
// С кастомным сообщением
|
|
7317
|
-
pattern(path.username, /^[a-z0-9_]+$/i, {
|
|
7318
|
-
message: 'Только латинские буквы, цифры и подчёркивание'
|
|
7319
|
-
})
|
|
7320
|
-
```
|
|
7321
|
-
|
|
7322
|
-
```typescript
|
|
7323
|
-
// Ошибка валидации
|
|
7324
|
-
{
|
|
7325
|
-
code: 'pattern',
|
|
7326
|
-
message: 'Значение не соответствует требуемому формату',
|
|
7327
|
-
params: { pattern: '^[a-z]+$' }
|
|
7328
|
-
}
|
|
7192
|
+
validate(path.name, pattern(/^[а-яА-Яa-zA-Z]+$/));
|
|
7193
|
+
validate(path.code, pattern(/^\d+$/, { message: 'Только цифры' }));
|
|
7329
7194
|
```
|
|
7330
7195
|
|
|
7331
7196
|
_Source: src/core/validation/validators/pattern.ts_
|
|
@@ -7334,26 +7199,22 @@ _Source: src/core/validation/validators/pattern.ts_
|
|
|
7334
7199
|
|
|
7335
7200
|
**Kind:** `function`
|
|
7336
7201
|
|
|
7337
|
-
|
|
7338
|
-
|
|
7202
|
+
Фабрика валидатора номера телефона.
|
|
7203
|
+
|
|
7204
|
+
Пустые значения пропускаются (используйте `required` для обязательности).
|
|
7339
7205
|
|
|
7340
7206
|
**Signature:**
|
|
7341
7207
|
```typescript
|
|
7342
|
-
export function phone<TForm, TField extends string |
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
/** Формат телефона */
|
|
7346
|
-
format?: PhoneFormat;
|
|
7347
|
-
}
|
|
7348
|
-
): void
|
|
7208
|
+
export function phone<TForm = unknown, TField extends string | undefined = string>(
|
|
7209
|
+
options?: PhoneValidatorOptions
|
|
7210
|
+
): Validator<TForm, TField>
|
|
7349
7211
|
```
|
|
7350
7212
|
|
|
7351
7213
|
**Examples:**
|
|
7352
7214
|
|
|
7353
7215
|
```typescript
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
phone(path.phoneNumber, { format: 'international', message: 'Неверный формат телефона' });
|
|
7216
|
+
validate(path.phone, phone());
|
|
7217
|
+
validate(path.phone, phone({ format: 'ru' }));
|
|
7357
7218
|
```
|
|
7358
7219
|
|
|
7359
7220
|
_Source: src/core/validation/validators/phone.ts_
|
|
@@ -7362,8 +7223,6 @@ _Source: src/core/validation/validators/phone.ts_
|
|
|
7362
7223
|
|
|
7363
7224
|
**Kind:** `type`
|
|
7364
7225
|
|
|
7365
|
-
Формат телефона для валидации
|
|
7366
|
-
|
|
7367
7226
|
**Signature:**
|
|
7368
7227
|
```typescript
|
|
7369
7228
|
export type PhoneFormat = 'international' | 'ru' | 'us' | 'any';
|
|
@@ -7411,47 +7270,29 @@ _Source: src/core/utils/registry-stack.ts_
|
|
|
7411
7270
|
|
|
7412
7271
|
**Kind:** `function`
|
|
7413
7272
|
|
|
7414
|
-
|
|
7273
|
+
Фабрика валидатора обязательного поля.
|
|
7274
|
+
|
|
7275
|
+
Возвращает чистую функцию-валидатор `(value, control, root)`. Передаётся в `validate()`.
|
|
7415
7276
|
|
|
7416
|
-
Проверяет, что поле имеет непустое значение.
|
|
7417
7277
|
Пустыми считаются: `null`, `undefined`, `''` (пустая строка).
|
|
7418
7278
|
Для boolean полей требуется значение `true`.
|
|
7419
7279
|
|
|
7420
7280
|
**Signature:**
|
|
7421
7281
|
```typescript
|
|
7422
|
-
export function required<TForm, TField>(
|
|
7423
|
-
fieldPath: FieldPathNode<TForm, TField> | undefined,
|
|
7282
|
+
export function required<TForm = unknown, TField = unknown>(
|
|
7424
7283
|
options?: ValidateOptions
|
|
7425
|
-
):
|
|
7284
|
+
): Validator<TForm, TField>
|
|
7426
7285
|
```
|
|
7427
7286
|
|
|
7428
|
-
**Parameters:**
|
|
7429
|
-
- `fieldPath` — - Путь к полю для валидации
|
|
7430
|
-
- `options` — - Опции валидации (message, params)
|
|
7431
|
-
|
|
7432
7287
|
**Examples:**
|
|
7433
7288
|
|
|
7434
7289
|
```typescript
|
|
7435
|
-
|
|
7436
|
-
|
|
7437
|
-
required(path.name),
|
|
7438
|
-
required(path.email),
|
|
7439
|
-
]
|
|
7440
|
-
|
|
7441
|
-
// С кастомным сообщением
|
|
7442
|
-
required(path.phone, { message: 'Укажите номер телефона' })
|
|
7443
|
-
|
|
7444
|
-
// Для checkbox (требует true)
|
|
7445
|
-
required(path.agreeToTerms, { message: 'Необходимо принять условия' })
|
|
7446
|
-
```
|
|
7290
|
+
import { validate } from '@reformer/core';
|
|
7291
|
+
import { required } from '@reformer/core/validators';
|
|
7447
7292
|
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
{
|
|
7451
|
-
code: 'required',
|
|
7452
|
-
message: 'Поле обязательно для заполнения',
|
|
7453
|
-
params: {}
|
|
7454
|
-
}
|
|
7293
|
+
validate(path.email, required());
|
|
7294
|
+
validate(path.phone, required({ message: 'Укажите номер телефона' }));
|
|
7295
|
+
validate(path.agreeToTerms, required({ message: 'Необходимо принять условия' }));
|
|
7455
7296
|
```
|
|
7456
7297
|
|
|
7457
7298
|
_Source: src/core/validation/validators/required.ts_
|
|
@@ -8166,60 +8007,6 @@ export interface TransformValueOptions {
|
|
|
8166
8007
|
|
|
8167
8008
|
_Source: src/core/behavior/behaviors/transform-value.ts_
|
|
8168
8009
|
|
|
8169
|
-
### TreeValidationContextImpl
|
|
8170
|
-
|
|
8171
|
-
**Kind:** `class`
|
|
8172
|
-
|
|
8173
|
-
Контекст cross-field валидации. Передаётся в `validateTree`/`validateForm`
|
|
8174
|
-
callback'и — напрямую инстанцировать не нужно.
|
|
8175
|
-
|
|
8176
|
-
**Signature:**
|
|
8177
|
-
```typescript
|
|
8178
|
-
export class TreeValidationContextImpl<TForm> extends BaseValidationContext<TForm> { /* … */ }
|
|
8179
|
-
```
|
|
8180
|
-
|
|
8181
|
-
**Examples:**
|
|
8182
|
-
|
|
8183
|
-
```typescript
|
|
8184
|
-
import { validateForm } from '@reformer/core';
|
|
8185
|
-
|
|
8186
|
-
validateForm(form, (ctx) => {
|
|
8187
|
-
// ctx — экземпляр TreeValidationContextImpl
|
|
8188
|
-
if (ctx.form.startDate.value > ctx.form.endDate.value) {
|
|
8189
|
-
return [{ code: 'date-range', message: 'Дата начала позже даты окончания' }];
|
|
8190
|
-
}
|
|
8191
|
-
return [];
|
|
8192
|
-
});
|
|
8193
|
-
```
|
|
8194
|
-
|
|
8195
|
-
_Source: src/core/validation/validation-context.ts_
|
|
8196
|
-
|
|
8197
|
-
### TreeValidatorFn
|
|
8198
|
-
|
|
8199
|
-
**Kind:** `type`
|
|
8200
|
-
|
|
8201
|
-
Функция cross-field валидации
|
|
8202
|
-
|
|
8203
|
-
**Signature:**
|
|
8204
|
-
```typescript
|
|
8205
|
-
export type TreeValidatorFn<TForm> = (ctx: FormContext<TForm>) => ValidationError | null;
|
|
8206
|
-
```
|
|
8207
|
-
|
|
8208
|
-
**Examples:**
|
|
8209
|
-
|
|
8210
|
-
```typescript
|
|
8211
|
-
validateTree((ctx) => {
|
|
8212
|
-
const password = ctx.form.password.value.value;
|
|
8213
|
-
const confirm = ctx.form.confirmPassword.value.value;
|
|
8214
|
-
if (password !== confirm) {
|
|
8215
|
-
return { code: 'mismatch', message: 'Passwords must match' };
|
|
8216
|
-
}
|
|
8217
|
-
return null;
|
|
8218
|
-
});
|
|
8219
|
-
```
|
|
8220
|
-
|
|
8221
|
-
_Source: src/core/types/validation-schema.ts_
|
|
8222
|
-
|
|
8223
8010
|
### uniqueId
|
|
8224
8011
|
|
|
8225
8012
|
**Kind:** `function`
|
|
@@ -8293,28 +8080,23 @@ _Source: src/core/types/index.ts_
|
|
|
8293
8080
|
|
|
8294
8081
|
**Kind:** `function`
|
|
8295
8082
|
|
|
8296
|
-
|
|
8297
|
-
|
|
8083
|
+
Фабрика валидатора URL.
|
|
8084
|
+
|
|
8085
|
+
Пустые значения пропускаются (используйте `required` для обязательности).
|
|
8298
8086
|
|
|
8299
8087
|
**Signature:**
|
|
8300
8088
|
```typescript
|
|
8301
|
-
export function url<TForm, TField extends string |
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
/** Требовать наличие протокола (http:// или https://) */
|
|
8305
|
-
requireProtocol?: boolean;
|
|
8306
|
-
/** Разрешенные протоколы */
|
|
8307
|
-
allowedProtocols?: string[];
|
|
8308
|
-
}
|
|
8309
|
-
): void
|
|
8089
|
+
export function url<TForm = unknown, TField extends string | undefined = string>(
|
|
8090
|
+
options?: UrlValidatorOptions
|
|
8091
|
+
): Validator<TForm, TField>
|
|
8310
8092
|
```
|
|
8311
8093
|
|
|
8312
8094
|
**Examples:**
|
|
8313
8095
|
|
|
8314
8096
|
```typescript
|
|
8315
|
-
|
|
8316
|
-
|
|
8317
|
-
|
|
8097
|
+
validate(path.website, url());
|
|
8098
|
+
validate(path.website, url({ requireProtocol: true }));
|
|
8099
|
+
validate(path.website, url({ allowedProtocols: ['https'] }));
|
|
8318
8100
|
```
|
|
8319
8101
|
|
|
8320
8102
|
_Source: src/core/validation/validators/url.ts_
|
|
@@ -8809,14 +8591,16 @@ _Source: src/hooks/useHiddenCondition.ts_
|
|
|
8809
8591
|
|
|
8810
8592
|
**Kind:** `function`
|
|
8811
8593
|
|
|
8812
|
-
Зарегистрировать
|
|
8813
|
-
|
|
8594
|
+
Зарегистрировать синхронный валидатор для поля.
|
|
8595
|
+
|
|
8596
|
+
Принимает чистую функцию-валидатор `(value, control, root) => error | null`,
|
|
8597
|
+
либо фабрику из `@reformer/core/validators` (например, `required()`).
|
|
8814
8598
|
|
|
8815
8599
|
**Signature:**
|
|
8816
8600
|
```typescript
|
|
8817
8601
|
export function validate<TForm, TField>(
|
|
8818
8602
|
fieldPath: FieldPathNode<TForm, TField> | undefined,
|
|
8819
|
-
|
|
8603
|
+
validator: Validator<TForm, TField>,
|
|
8820
8604
|
options?: ValidateOptions
|
|
8821
8605
|
): void
|
|
8822
8606
|
```
|
|
@@ -8824,20 +8608,14 @@ export function validate<TForm, TField>(
|
|
|
8824
8608
|
**Examples:**
|
|
8825
8609
|
|
|
8826
8610
|
```typescript
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
const age = calculateAge(
|
|
8830
|
-
|
|
8831
|
-
if (age < 18) {
|
|
8832
|
-
return {
|
|
8833
|
-
code: 'tooYoung',
|
|
8834
|
-
message: 'Заемщику должно быть не менее 18 лет',
|
|
8835
|
-
};
|
|
8836
|
-
}
|
|
8837
|
-
|
|
8611
|
+
// Кастомный валидатор
|
|
8612
|
+
validate(path.birthDate, (value, _control, root) => {
|
|
8613
|
+
const age = calculateAge(new Date(value));
|
|
8614
|
+
if (age < 18) return { code: 'tooYoung', message: 'Только 18+' };
|
|
8838
8615
|
return null;
|
|
8839
8616
|
});
|
|
8840
|
-
|
|
8617
|
+
|
|
8618
|
+
// Фабрика из
|
|
8841
8619
|
|
|
8842
8620
|
_Source: src/core/validation/core/validate.ts_
|
|
8843
8621
|
|
|
@@ -8845,13 +8623,15 @@ _Source: src/core/validation/core/validate.ts_
|
|
|
8845
8623
|
|
|
8846
8624
|
**Kind:** `function`
|
|
8847
8625
|
|
|
8848
|
-
Зарегистрировать асинхронный валидатор для
|
|
8626
|
+
Зарегистрировать асинхронный валидатор для поля.
|
|
8627
|
+
|
|
8628
|
+
Принимает чистую async-функцию `(value, control, root) => Promise<error | null>`.
|
|
8849
8629
|
|
|
8850
8630
|
**Signature:**
|
|
8851
8631
|
```typescript
|
|
8852
8632
|
export function validateAsync<TForm, TField>(
|
|
8853
8633
|
fieldPath: FieldPathNode<TForm, TField>,
|
|
8854
|
-
|
|
8634
|
+
validator: AsyncValidator<TForm, TField>,
|
|
8855
8635
|
options?: ValidateAsyncOptions
|
|
8856
8636
|
): void
|
|
8857
8637
|
```
|
|
@@ -8861,23 +8641,16 @@ export function validateAsync<TForm, TField>(
|
|
|
8861
8641
|
```typescript
|
|
8862
8642
|
validateAsync(
|
|
8863
8643
|
path.inn,
|
|
8864
|
-
async (
|
|
8865
|
-
|
|
8866
|
-
if (!inn) return null;
|
|
8867
|
-
|
|
8644
|
+
async (value, _control, _root) => {
|
|
8645
|
+
if (!value) return null;
|
|
8868
8646
|
const response = await fetch('/api/validate-inn', {
|
|
8869
8647
|
method: 'POST',
|
|
8870
|
-
body: JSON.stringify({ inn }),
|
|
8648
|
+
body: JSON.stringify({ inn: value }),
|
|
8871
8649
|
});
|
|
8872
|
-
|
|
8873
8650
|
const data = await response.json();
|
|
8874
8651
|
if (!data.valid) {
|
|
8875
|
-
return {
|
|
8876
|
-
code: 'invalidInn',
|
|
8877
|
-
message: 'ИНН не найден в базе данных ФНС',
|
|
8878
|
-
};
|
|
8652
|
+
return { code: 'invalidInn', message: 'ИНН не найден в базе ФНС' };
|
|
8879
8653
|
}
|
|
8880
|
-
|
|
8881
8654
|
return null;
|
|
8882
8655
|
},
|
|
8883
8656
|
{ debounce: 1000 }
|
|
@@ -8890,7 +8663,7 @@ _Source: src/core/validation/core/validate-async.ts_
|
|
|
8890
8663
|
|
|
8891
8664
|
**Kind:** `interface`
|
|
8892
8665
|
|
|
8893
|
-
Опции для функции validateAsync
|
|
8666
|
+
Опции для функции validateAsync.
|
|
8894
8667
|
|
|
8895
8668
|
**Signature:**
|
|
8896
8669
|
```typescript
|
|
@@ -8968,7 +8741,7 @@ _Source: src/core/validation/validate-form.ts_
|
|
|
8968
8741
|
|
|
8969
8742
|
**Kind:** `function`
|
|
8970
8743
|
|
|
8971
|
-
Применить validation schema к каждому элементу
|
|
8744
|
+
Применить validation schema к каждому элементу массива.
|
|
8972
8745
|
|
|
8973
8746
|
Регистрирует схему валидации, которая будет автоматически применяться
|
|
8974
8747
|
к каждому элементу ArrayNode (как существующим, так и новым).
|
|
@@ -8981,21 +8754,13 @@ export function validateItems<TForm, TItem>(
|
|
|
8981
8754
|
): void
|
|
8982
8755
|
```
|
|
8983
8756
|
|
|
8984
|
-
**Parameters:**
|
|
8985
|
-
- `fieldPath` — - Поле-массив для валидации элементов
|
|
8986
|
-
- `itemSchemaFn` — - Validation schema для одного элемента
|
|
8987
|
-
|
|
8988
8757
|
**Examples:**
|
|
8989
8758
|
|
|
8990
8759
|
```typescript
|
|
8991
8760
|
import { propertyValidation } from './property-validation';
|
|
8992
8761
|
|
|
8993
|
-
// В additionalValidation
|
|
8994
8762
|
applyWhen(path.hasProperty, (value) => value === true, (path) => {
|
|
8995
|
-
|
|
8996
|
-
notEmpty(path.properties, { message: 'Добавьте хотя бы один объект имущества' });
|
|
8997
|
-
|
|
8998
|
-
// Валидация каждого элемента
|
|
8763
|
+
validate(path.properties, notEmpty({ message: 'Добавьте хотя бы один объект' }));
|
|
8999
8764
|
validateItems(path.properties, propertyValidation);
|
|
9000
8765
|
});
|
|
9001
8766
|
```
|
|
@@ -9006,7 +8771,7 @@ _Source: src/core/validation/validators/array-validators.ts_
|
|
|
9006
8771
|
|
|
9007
8772
|
**Kind:** `interface`
|
|
9008
8773
|
|
|
9009
|
-
Опции для функции validate
|
|
8774
|
+
Опции для функции validate.
|
|
9010
8775
|
|
|
9011
8776
|
**Signature:**
|
|
9012
8777
|
```typescript
|
|
@@ -9020,88 +8785,6 @@ export interface ValidateOptions {
|
|
|
9020
8785
|
|
|
9021
8786
|
_Source: src/core/types/validation-schema.ts_
|
|
9022
8787
|
|
|
9023
|
-
### validateTree
|
|
9024
|
-
|
|
9025
|
-
**Kind:** `function`
|
|
9026
|
-
|
|
9027
|
-
Зарегистрировать cross-field валидатор
|
|
9028
|
-
|
|
9029
|
-
Используется для валидации, которая зависит от нескольких полей
|
|
9030
|
-
|
|
9031
|
-
**Signature:**
|
|
9032
|
-
```typescript
|
|
9033
|
-
export function validateTree<TForm>(
|
|
9034
|
-
validatorFn: TreeValidatorFn<TForm>,
|
|
9035
|
-
options?: ValidateTreeOptions
|
|
9036
|
-
): void
|
|
9037
|
-
```
|
|
9038
|
-
|
|
9039
|
-
**Examples:**
|
|
9040
|
-
|
|
9041
|
-
```typescript
|
|
9042
|
-
// Явная типизация ctx для избежания implicit any
|
|
9043
|
-
validateTree(
|
|
9044
|
-
(ctx: { form: MyForm }) => {
|
|
9045
|
-
if (ctx.form.initialPayment && ctx.form.propertyValue) {
|
|
9046
|
-
if (ctx.form.initialPayment > ctx.form.propertyValue) {
|
|
9047
|
-
return {
|
|
9048
|
-
code: 'initialPaymentTooHigh',
|
|
9049
|
-
message: 'Первоначальный взнос не может превышать стоимость',
|
|
9050
|
-
};
|
|
9051
|
-
}
|
|
9052
|
-
}
|
|
9053
|
-
return null;
|
|
9054
|
-
},
|
|
9055
|
-
{ targetField: 'initialPayment' }
|
|
9056
|
-
);
|
|
9057
|
-
```
|
|
9058
|
-
|
|
9059
|
-
_Source: src/core/validation/core/validate-tree.ts_
|
|
9060
|
-
|
|
9061
|
-
### ValidateTreeOptions
|
|
9062
|
-
|
|
9063
|
-
**Kind:** `interface`
|
|
9064
|
-
|
|
9065
|
-
Опции для функции validateTree
|
|
9066
|
-
|
|
9067
|
-
**Signature:**
|
|
9068
|
-
```typescript
|
|
9069
|
-
export interface ValidateTreeOptions {
|
|
9070
|
-
/** Поле, к которому привязать ошибку */
|
|
9071
|
-
targetField?: string;
|
|
9072
|
-
}
|
|
9073
|
-
```
|
|
9074
|
-
|
|
9075
|
-
_Source: src/core/types/validation-schema.ts_
|
|
9076
|
-
|
|
9077
|
-
### ValidationContextImpl
|
|
9078
|
-
|
|
9079
|
-
**Kind:** `class`
|
|
9080
|
-
|
|
9081
|
-
Контекст валидации одного поля. Создаётся фреймворком и передаётся в валидаторы
|
|
9082
|
-
(`required`, `validate`, …) — напрямую инстанцировать не нужно.
|
|
9083
|
-
|
|
9084
|
-
**Signature:**
|
|
9085
|
-
```typescript
|
|
9086
|
-
export class ValidationContextImpl<TForm, TField> extends BaseValidationContext<TForm> { /* … */ }
|
|
9087
|
-
```
|
|
9088
|
-
|
|
9089
|
-
**Examples:**
|
|
9090
|
-
|
|
9091
|
-
```typescript
|
|
9092
|
-
import { validate } from '@reformer/core/validators';
|
|
9093
|
-
|
|
9094
|
-
validate(path.password, (value, ctx) => {
|
|
9095
|
-
// ctx — экземпляр ValidationContextImpl, доступ к ctx.form для cross-field логики
|
|
9096
|
-
if (value !== ctx.form.confirmPassword.value) {
|
|
9097
|
-
return { code: 'mismatch', message: 'Пароли не совпадают' };
|
|
9098
|
-
}
|
|
9099
|
-
return null;
|
|
9100
|
-
});
|
|
9101
|
-
```
|
|
9102
|
-
|
|
9103
|
-
_Source: src/core/validation/validation-context.ts_
|
|
9104
|
-
|
|
9105
8788
|
### ValidationError
|
|
9106
8789
|
|
|
9107
8790
|
**Kind:** `interface`
|
|
@@ -9130,14 +8813,18 @@ _Source: src/core/types/index.ts_
|
|
|
9130
8813
|
Каждый экземпляр GroupNode создает собственный реестр (композиция).
|
|
9131
8814
|
Устраняет race conditions и изолирует формы друг от друга.
|
|
9132
8815
|
|
|
9133
|
-
|
|
9134
|
-
-
|
|
9135
|
-
-
|
|
8816
|
+
Context stack используется для tracking текущего активного реестра:
|
|
8817
|
+
- beginRegistration() помещает this в global stack
|
|
8818
|
+
- endRegistration() извлекает из global stack
|
|
8819
|
+
- getCurrent() возвращает текущий активный реестр
|
|
9136
8820
|
|
|
9137
8821
|
**Signature:**
|
|
9138
8822
|
```typescript
|
|
9139
|
-
export class ValidationRegistry
|
|
9140
|
-
/**
|
|
8823
|
+
export class ValidationRegistry {
|
|
8824
|
+
/**
|
|
8825
|
+
* Global stack активных реестров
|
|
8826
|
+
* Используется для изоляции форм друг от друга
|
|
8827
|
+
*/ /* … */ }
|
|
9141
8828
|
```
|
|
9142
8829
|
|
|
9143
8830
|
**Examples:**
|
|
@@ -9160,9 +8847,9 @@ _Source: src/core/validation/validation-registry.ts_
|
|
|
9160
8847
|
|
|
9161
8848
|
**Kind:** `type`
|
|
9162
8849
|
|
|
9163
|
-
Функция validation schema
|
|
8850
|
+
Функция validation schema.
|
|
9164
8851
|
|
|
9165
|
-
Принимает FieldPath и определяет все правила валидации для
|
|
8852
|
+
Принимает FieldPath и определяет все правила валидации для формы.
|
|
9166
8853
|
|
|
9167
8854
|
**Signature:**
|
|
9168
8855
|
```typescript
|
|
@@ -9171,6 +8858,36 @@ export type ValidationSchemaFn<T> = (path: FieldPath<T>) => void;
|
|
|
9171
8858
|
|
|
9172
8859
|
_Source: src/core/types/validation-schema.ts_
|
|
9173
8860
|
|
|
8861
|
+
### Validator
|
|
8862
|
+
|
|
8863
|
+
**Kind:** `type`
|
|
8864
|
+
|
|
8865
|
+
Чистый синхронный валидатор поля.
|
|
8866
|
+
|
|
8867
|
+
Принимает значение поля, прокси текущего поля (control) и прокси корня формы (root).
|
|
8868
|
+
Возвращает ValidationError либо null. Не знает про реестр валидации.
|
|
8869
|
+
|
|
8870
|
+
**Signature:**
|
|
8871
|
+
```typescript
|
|
8872
|
+
export type Validator<TForm, TField> = (
|
|
8873
|
+
value: TField,
|
|
8874
|
+
control: FormProxy<TField>,
|
|
8875
|
+
root: FormProxy<TForm>
|
|
8876
|
+
) => ValidationError | null;
|
|
8877
|
+
```
|
|
8878
|
+
|
|
8879
|
+
**Examples:**
|
|
8880
|
+
|
|
8881
|
+
```typescript
|
|
8882
|
+
const isAdult: Validator<MyForm, number> = (value, control, root) => {
|
|
8883
|
+
if (value < 18) return { code: 'tooYoung', message: '18+' };
|
|
8884
|
+
return null;
|
|
8885
|
+
};
|
|
8886
|
+
validate(path.age, isAdult);
|
|
8887
|
+
```
|
|
8888
|
+
|
|
8889
|
+
_Source: src/core/types/validation-schema.ts_
|
|
8890
|
+
|
|
9174
8891
|
### ValidatorFn
|
|
9175
8892
|
|
|
9176
8893
|
**Kind:** `type`
|
|
@@ -9194,12 +8911,10 @@ _Source: src/core/types/index.ts_
|
|
|
9194
8911
|
```typescript
|
|
9195
8912
|
export interface ValidatorRegistration {
|
|
9196
8913
|
fieldPath: string;
|
|
9197
|
-
type: 'sync' | 'async' | '
|
|
9198
|
-
validator:
|
|
9199
|
-
|
|
9200
|
-
|
|
9201
|
-
| TreeValidatorFn<unknown>;
|
|
9202
|
-
options?: ValidateOptions | ValidateAsyncOptions | ValidateTreeOptions;
|
|
8914
|
+
type: 'sync' | 'async' | 'array-items';
|
|
8915
|
+
validator: Validator<unknown, unknown> | AsyncValidator<unknown, unknown>;
|
|
8916
|
+
options?: ValidateOptions | ValidateAsyncOptions;
|
|
8917
|
+
/** Для условной валидации (applyWhen). */
|
|
9203
8918
|
condition?: {
|
|
9204
8919
|
fieldPath: string;
|
|
9205
8920
|
conditionFn: ConditionFn<unknown>;
|