@reformer/core 11.0.0-beta.8 → 11.0.0-beta.9
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 +91 -73
- package/dist/behaviors-value-HA_Q03hc.js +108 -0
- package/dist/behaviors.js +370 -242
- package/dist/{create-model-BBRHhHwK.js → create-model-BvcbNPgL.js} +6 -6
- package/dist/date-utils-90-qZbse.js +43 -0
- package/dist/{en-CjAqn7h0.js → en-HP8XEych.js} +6 -3
- package/dist/form/aggregate-signals.d.ts +21 -63
- package/dist/form/behaviors/collections.d.ts +28 -7
- package/dist/form/behaviors/context.d.ts +19 -2
- package/dist/form/behaviors/index.d.ts +3 -3
- package/dist/form/behaviors/internals.d.ts +9 -2
- package/dist/form/behaviors/node.d.ts +25 -2
- package/dist/form/behaviors/operators.d.ts +17 -9
- package/dist/form/behaviors/schema-operators.d.ts +6 -4
- package/dist/form/behaviors/types.d.ts +12 -4
- package/dist/form/create-form.d.ts +47 -35
- package/dist/form/flow/flow.d.ts +87 -0
- package/dist/form/form-bundle.d.ts +45 -28
- package/dist/form/form-config-base.d.ts +46 -0
- package/dist/form/form-level.d.ts +121 -0
- package/dist/form/form-proxy-builder.d.ts +6 -22
- package/dist/form/index.d.ts +16 -21
- package/dist/form/nodes/form-array-node.d.ts +100 -0
- package/dist/form/nodes/form-control-node.d.ts +73 -0
- package/dist/form/nodes/form-group-node.d.ts +66 -0
- package/dist/form/nodes/node-kind.d.ts +29 -0
- package/dist/form/nodes/state/availability.d.ts +6 -0
- package/dist/form/nodes/state/component.d.ts +6 -0
- package/dist/form/nodes/state/index.d.ts +12 -0
- package/dist/form/nodes/state/interaction.d.ts +13 -0
- package/dist/form/nodes/state/issues.d.ts +9 -0
- package/dist/form/nodes/state/pending.d.ts +6 -0
- package/dist/form/schema/compile.d.ts +59 -0
- package/dist/form/schema/compiled.d.ts +143 -0
- package/dist/form/schema/row-key.d.ts +11 -0
- package/dist/form/schema-controller.d.ts +30 -14
- package/dist/form/signal-node-registry.d.ts +6 -7
- package/dist/form/submission.d.ts +93 -0
- package/dist/form/type-guards.d.ts +14 -73
- package/dist/form/types/contracts.d.ts +19 -92
- package/dist/form/types/field-config.d.ts +27 -0
- package/dist/form/types/index.d.ts +5 -57
- package/dist/form/types/nodes.d.ts +159 -0
- package/dist/form/types/schema-node.d.ts +139 -63
- package/dist/form/types/validation-schema.d.ts +23 -27
- package/dist/form/validation/context.d.ts +42 -7
- package/dist/form/validation/index.d.ts +9 -8
- package/dist/form/validation/operators.d.ts +22 -30
- package/dist/form/validation/run.d.ts +93 -18
- package/dist/form/validation/strategy.d.ts +41 -13
- package/dist/form/validation/types.d.ts +74 -20
- package/dist/form/validators/date-utils.d.ts +13 -1
- package/dist/form/validators/email.d.ts +8 -7
- package/dist/form/validators/file-type.d.ts +8 -7
- package/dist/form/validators/file-utils.d.ts +2 -1
- package/dist/form/validators/future-date.d.ts +8 -7
- package/dist/form/validators/index.d.ts +1 -1
- package/dist/form/validators/integer.d.ts +8 -7
- package/dist/form/validators/is-date.d.ts +11 -9
- package/dist/form/validators/is-number.d.ts +11 -9
- package/dist/form/validators/max-age.d.ts +13 -9
- package/dist/form/validators/max-date.d.ts +8 -7
- package/dist/form/validators/max-file-size.d.ts +8 -7
- package/dist/form/validators/max-files.d.ts +8 -7
- package/dist/form/validators/max-length.d.ts +14 -7
- package/dist/form/validators/max-total-file-size.d.ts +8 -7
- package/dist/form/validators/max.d.ts +10 -8
- package/dist/form/validators/min-age.d.ts +12 -9
- package/dist/form/validators/min-date.d.ts +8 -7
- package/dist/form/validators/min-file-size.d.ts +8 -7
- package/dist/form/validators/min-files.d.ts +11 -9
- package/dist/form/validators/min-length.d.ts +14 -7
- package/dist/form/validators/min.d.ts +10 -8
- package/dist/form/validators/multiple-of.d.ts +10 -8
- package/dist/form/validators/non-negative.d.ts +8 -7
- package/dist/form/validators/non-zero.d.ts +8 -7
- package/dist/form/validators/past-date.d.ts +8 -7
- package/dist/form/validators/pattern.d.ts +9 -8
- package/dist/form/validators/phone.d.ts +8 -7
- package/dist/form/validators/required.d.ts +11 -9
- package/dist/form/validators/url.d.ts +20 -13
- package/dist/form/validators/validation-issue.d.ts +8 -0
- package/dist/i18n/descriptor.d.ts +1 -1
- package/dist/i18n/en.json.d.ts +5 -1
- package/dist/i18n/locale-store.d.ts +7 -0
- package/dist/i18n/message-format.d.ts +24 -4
- package/dist/i18n/ru.json.d.ts +5 -1
- package/dist/i18n/translator.d.ts +11 -0
- package/dist/i18n/validation-message.d.ts +42 -7
- package/dist/i18n.d.ts +7 -12
- package/dist/i18n.js +66 -283
- package/dist/index.d.ts +16 -7
- package/dist/index.js +924 -2855
- package/dist/loader-BWkigpVe.js +52 -0
- package/dist/locale/en.js +1 -1
- package/dist/locale/en.json +4 -1
- package/dist/locale/ru.js +4 -1
- package/dist/locale/ru.json +4 -1
- package/dist/locale-CG54AU2Q.js +219 -0
- package/dist/locale.js +1 -1
- package/dist/model/behaviors-value.d.ts +24 -6
- package/dist/model/create-model.d.ts +2 -2
- package/dist/model/derived-registry.d.ts +1 -1
- package/dist/model/index.d.ts +11 -5
- package/dist/model/model-nodes.d.ts +79 -12
- package/dist/model/model-signals-proxy.d.ts +5 -6
- package/dist/model/model-value-proxy.d.ts +20 -15
- package/dist/model/safe-effect.d.ts +33 -1
- package/dist/model/types.d.ts +63 -13
- package/dist/model.js +20 -18
- package/dist/node-kind-C-r6ZMdo.js +15 -0
- package/dist/platforms/react/field-binding/field-adapter.d.ts +1 -1
- package/dist/platforms/react/field-binding/field-handle.d.ts +5 -2
- package/dist/platforms/react/form-bundle-context.d.ts +2 -2
- package/dist/platforms/react/hooks/types.d.ts +57 -38
- package/dist/platforms/react/hooks/use-form-bundle.d.ts +19 -4
- package/dist/platforms/react/hooks/use-form-flow.d.ts +40 -0
- package/dist/platforms/react/hooks/use-form-validation.d.ts +12 -6
- package/dist/platforms/react/hooks/useArrayLength.d.ts +6 -6
- package/dist/platforms/react/hooks/useFormControl.d.ts +7 -9
- package/dist/platforms/react/hooks/useFormControlValue.d.ts +18 -19
- package/dist/platforms/react/hooks/useSignalSubscription.d.ts +9 -1
- package/dist/platforms/react/i18n/context.d.ts +6 -1
- package/dist/platforms/react/i18n/hooks.d.ts +16 -10
- package/dist/platforms/react/i18n/provider.d.ts +9 -2
- package/dist/platforms/react/index.d.ts +6 -4
- package/dist/react.d.ts +22 -0
- package/dist/react.js +505 -0
- package/dist/runtime-token.d.ts +1 -2
- package/dist/safe-effect-BbtX3KuN.js +643 -0
- package/dist/schema-controller-CpiO2JoK.js +143 -0
- package/dist/signals.d.ts +15 -9
- package/dist/signals.js +11 -6
- package/dist/strategy-CoFSemuP.js +375 -0
- package/dist/type-guards-D-N_5Ddh.js +19 -0
- package/dist/validation-issue-B9mjI8jz.js +7 -0
- package/dist/validation-message-Ced9MGxs.js +194 -0
- package/dist/validation.js +9 -9
- package/dist/validators/email.js +5 -5
- package/dist/validators/future-date.js +8 -8
- package/dist/validators/integer.js +3 -3
- package/dist/validators/is-date.js +4 -4
- package/dist/validators/is-number.js +4 -4
- package/dist/validators/max-age.js +8 -9
- package/dist/validators/max-date.js +8 -8
- package/dist/validators/max-length.js +7 -7
- package/dist/validators/max.js +4 -4
- package/dist/validators/min-age.js +10 -8
- package/dist/validators/min-date.js +3 -3
- package/dist/validators/min-length.js +5 -5
- package/dist/validators/min.js +4 -4
- package/dist/validators/multiple-of.js +11 -7
- package/dist/validators/non-negative.js +3 -3
- package/dist/validators/non-zero.js +3 -3
- package/dist/validators/past-date.js +8 -8
- package/dist/validators/pattern.js +5 -5
- package/dist/validators/phone.js +11 -9
- package/dist/validators/required.js +2 -2
- package/dist/validators/url.js +48 -12
- package/dist/validators.js +17 -17
- package/docs/llms/01-api-reference.md +60 -34
- package/docs/llms/02-quick-start.md +111 -80
- package/docs/llms/03-api-signatures.md +368 -153
- package/docs/llms/04-common-patterns.md +58 -56
- package/docs/llms/05-common-mistakes.md +69 -44
- package/docs/llms/06-troubleshooting.md +14 -9
- package/docs/llms/07-complete-import.md +74 -43
- package/docs/llms/08-form-types.md +11 -4
- package/docs/llms/09-formschema.md +129 -81
- package/docs/llms/10-arrays.md +106 -75
- package/docs/llms/11-async-watchfield.md +2 -2
- package/docs/llms/13-multi-step.md +134 -63
- package/docs/llms/14-extended-mistakes.md +20 -17
- package/docs/llms/15-project-structure.md +221 -74
- package/docs/llms/16-ui-components.md +55 -42
- package/docs/llms/17-nonexistent-api.md +199 -32
- package/docs/llms/18-conditional-fields.md +66 -32
- package/docs/llms/19-reading-values.md +15 -3
- package/docs/llms/20-compute-vs-watch.md +16 -10
- package/docs/llms/21-array-operations.md +51 -27
- package/docs/llms/22-cycle-detection.md +1 -1
- package/docs/llms/23-copy-from.md +2 -2
- package/docs/llms/24-sync-fields.md +6 -5
- package/docs/llms/25-reset-when.md +14 -7
- package/docs/llms/26-transform-value.md +4 -4
- package/docs/llms/27-revalidate-when.md +16 -15
- package/docs/llms/28-submit-and-reset.md +276 -128
- package/docs/llms/29-async-preload.md +39 -29
- package/docs/llms/30-type-safety-recipes.md +105 -51
- package/docs/llms/31-async-validator-debounce.md +96 -53
- package/docs/llms/33-validation-strategy.md +177 -65
- package/docs/llms/34-i18n.md +69 -43
- package/docs/llms/35-unified-contract.md +100 -39
- package/docs/llms/36-issue-messages.md +284 -0
- package/docs/llms/37-compiled-schema.md +332 -0
- package/docs/llms/38-form-flow.md +397 -0
- package/llms-index.json +1 -1
- package/llms.txt +6084 -3420
- package/package.json +23 -4
- package/dist/behaviors-value-C7dSEhCc.js +0 -134
- package/dist/date-utils-dTT_x_Be.js +0 -31
- package/dist/form/create-core-form.d.ts +0 -72
- package/dist/form/factories/index.d.ts +0 -6
- package/dist/form/factories/node-factory.d.ts +0 -189
- package/dist/form/form-submitter.d.ts +0 -121
- package/dist/form/nodes/array-node.d.ts +0 -276
- package/dist/form/nodes/field-node.d.ts +0 -297
- package/dist/form/nodes/form-node.d.ts +0 -326
- package/dist/form/nodes/group-node.d.ts +0 -284
- package/dist/form/nodes/model-array-node.d.ts +0 -126
- package/dist/form/nodes/subscription-manager.d.ts +0 -180
- package/dist/form/status-machine.d.ts +0 -115
- package/dist/form/types/deep-schema.d.ts +0 -107
- package/dist/form/types/form-proxy.d.ts +0 -141
- package/dist/form/unique-id.d.ts +0 -45
- package/dist/form/validation/config.d.ts +0 -73
- package/dist/form/validation/error-handler.d.ts +0 -166
- package/dist/form/validators/validation-error.d.ts +0 -8
- package/dist/index-BrNkQj1y.js +0 -105
- package/dist/loader-Dv_Hl7JC.js +0 -216
- package/dist/model-value-proxy-caTmAiUd.js +0 -419
- package/dist/node-BeV_lV5i.js +0 -100
- package/dist/strategy-DgzELWno.js +0 -204
- package/dist/validation-error-B-U3RsV0.js +0 -11
|
@@ -1,33 +1,108 @@
|
|
|
1
|
-
import { FormModel } from '../../
|
|
2
|
-
import {
|
|
1
|
+
import { FormModel } from '../../model/types';
|
|
2
|
+
import { ValidationResult, ValidationDefinition } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Тонкая identity-обёртка для типизации/discoverability (как `defineFormBehavior`). Возвращает схему как есть.
|
|
5
5
|
*
|
|
6
6
|
* @example
|
|
7
7
|
* ```ts
|
|
8
|
-
* export const step1 =
|
|
8
|
+
* export const step1 = defineValidation<LoanForm>(({ model }) => {
|
|
9
9
|
* validate(model.$.loanAmount, [required(), min(50000)]);
|
|
10
10
|
* });
|
|
11
11
|
* ```
|
|
12
12
|
*/
|
|
13
|
-
export declare function
|
|
13
|
+
export declare function defineValidation<T>(schema: ValidationDefinition<T>): ValidationDefinition<T>;
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* Отменить идущий прогон пары (model, schema): его `AbortSignal` срабатывает, ожидание async-правил
|
|
16
|
+
* размыкается, результат получает статус `cancelled` и по нодам не разносится. Контроллер живой
|
|
17
|
+
* проверки зовёт это при снятии — иначе ответ правила лёг бы на ноды уже снятой формы.
|
|
18
18
|
*
|
|
19
|
-
*
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
export declare function cancelRun(model: object, schema: object): void;
|
|
22
|
+
/**
|
|
23
|
+
* Какие поля пометить тронутыми при разносе: `false` — никакие, `true` — проверенные правилами,
|
|
24
|
+
* `'all'` — проверенные, а при отказе (`invalid`, `error`) ещё и всю форму.
|
|
25
|
+
*
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
export type ValidationTouch = boolean | 'all';
|
|
29
|
+
/** Идёт ли сейчас касание полей от имени проверки ({@link touchByValidation}). @internal */
|
|
30
|
+
export declare const isTouchByValidation: () => boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Собрать результат проверки модели схемой — без формы и без побочных эффектов на нодах.
|
|
33
|
+
*
|
|
34
|
+
* Открывает ambient-окно на время синхронного прогона `schema`, дожидается async-правил и
|
|
35
|
+
* возвращает {@link ValidationResult}. Нод формы не трогает: ошибки по ним разносит
|
|
36
|
+
* {@link applyValidationResult}. Подходит для проверки данных без UI (сервер, тест, предпросмотр).
|
|
37
|
+
*
|
|
38
|
+
* Статус результата:
|
|
39
|
+
* - `cancelled` — прогон устарел: пока он шёл, для той же пары (model, schema) запущен следующий;
|
|
40
|
+
* - `error` — хотя бы одно async-правило не вернуло результат (сеть, исключение) — см. `failures`;
|
|
41
|
+
* - `invalid` — есть блокирующие ошибки (`severity: 'warning'` не блокирует);
|
|
42
|
+
* - `valid` — блокирующих ошибок нет.
|
|
43
|
+
*
|
|
44
|
+
* ⚠️ `schema` должна быть СТАБИЛЬНОЙ ссылкой: отмена устаревших прогонов ключится по идентичности
|
|
45
|
+
* `schema`. Держите схемы в `const` / `defineValidation`.
|
|
46
|
+
*
|
|
47
|
+
* @param model - Модель данных формы.
|
|
48
|
+
* @param schema - Схема валидации (стабильная ссылка).
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* const result = await runValidation(model, formRules);
|
|
53
|
+
* if (result.status === 'error') showToast('Не удалось проверить форму, повторите попытку');
|
|
54
|
+
* else if (result.status !== 'cancelled') applyValidationResult(result, { touch: true });
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function runValidation<T>(model: FormModel<T>, schema: ValidationDefinition<T>): Promise<ValidationResult>;
|
|
58
|
+
/**
|
|
59
|
+
* Разнести собранный результат по нодам формы: поставить ошибки проверенным полям и погасить поля,
|
|
60
|
+
* которые были с ошибкой в прошлом разнесённом прогоне той же пары (model, schema), а теперь не
|
|
61
|
+
* проверялись (удалённая строка массива, выключенная ветка).
|
|
62
|
+
*
|
|
63
|
+
* Отменённый результат (`status: 'cancelled'`) не разносится: его async-часть оборвана.
|
|
64
|
+
*
|
|
65
|
+
* `options.touch`: пометить `touched` ИМЕННО поля, которые схема проверяла (не всё поддерево):
|
|
66
|
+
* поля выключенной ветки `validateWhen` и, в проверке уровня формы, выключенные поля не метятся —
|
|
67
|
+
* пользователь их не видел, и после включения их ошибка не должна быть видна с первой проверки.
|
|
68
|
+
* Замечания становятся видимыми (`shouldShowIssues`: есть замечания и `touched || dirty`) без
|
|
69
|
+
* ручного `form.markAsTouched()`; при пошаговой валидации следующий шаг не показывается
|
|
70
|
+
* «тронутым».
|
|
71
|
+
*
|
|
72
|
+
* @param result - Результат {@link runValidation}.
|
|
73
|
+
* @param options - `{ touch }` — пометить проверенные поля `touched` для показа ошибок.
|
|
74
|
+
*/
|
|
75
|
+
export declare function applyValidationResult(result: ValidationResult, options?: {
|
|
76
|
+
touch?: boolean;
|
|
77
|
+
}): void;
|
|
78
|
+
/**
|
|
79
|
+
* Прогон с разносом и полным результатом — общий движок {@link validateModel}, контроллера
|
|
80
|
+
* стратегии и прогонов шага. На время async-правил держит ноды их полей в `pending`.
|
|
81
|
+
* `skipDisabled` — проверка уровня формы: поля выключенных нод не учитываются.
|
|
82
|
+
*
|
|
83
|
+
* `touch`: `true` — пометить тронутыми проверенные поля; `'all'` — то же, а при отказе (`invalid`,
|
|
84
|
+
* `error`) ещё и всю форму: так попытка отправки раскрывает замечания полей, которых правила не
|
|
85
|
+
* касались. Отменённый результат не разносится и ничего не трогает.
|
|
86
|
+
*
|
|
87
|
+
* @internal
|
|
88
|
+
*/
|
|
89
|
+
export declare function runAndApply<T>(model: FormModel<T>, schema: ValidationDefinition<T>, options?: {
|
|
90
|
+
touch?: ValidationTouch;
|
|
91
|
+
skipDisabled?: boolean;
|
|
92
|
+
}): Promise<ValidationResult>;
|
|
93
|
+
/**
|
|
94
|
+
* Провалидировать модель ЛЮБОЙ схемой (шаг или вся форма): собрать результат и разнести ошибки по
|
|
95
|
+
* нодам формы. Возвращает `true` только для статуса `valid`: ошибки, сбой правила и отмена дают
|
|
96
|
+
* `false` (**fail-closed**). Чтобы различить их, берите {@link runValidation} либо
|
|
97
|
+
* `bundle.validate()` / `bundle.validateStep(id)` сборки формы.
|
|
22
98
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
99
|
+
* Гашение — на пару (model, schema): `validateModel(model, step2)` и `validateModel(model, form)`
|
|
100
|
+
* не мешают друг другу. Устаревший прогон (быстрый повторный вызов той же (model, schema))
|
|
101
|
+
* отменяется через `AbortSignal`.
|
|
26
102
|
*
|
|
27
|
-
* `
|
|
28
|
-
* (
|
|
29
|
-
* без
|
|
30
|
-
* «тронутым» до ввода. Валидные проверенные поля тоже метятся — это безвредно (ошибка не покажется).
|
|
103
|
+
* ⚠️ `schema` должна быть СТАБИЛЬНОЙ ссылкой: отмена устаревших прогонов ключится по идентичности
|
|
104
|
+
* `schema`. Инлайн-стрелка (`validateModel(model, ({ model }) => …)`) каждый раз создаёт НОВЫЙ
|
|
105
|
+
* прогон без дедупликации — держите схемы в `const` / `defineValidation`.
|
|
31
106
|
*
|
|
32
107
|
* @param model - Модель данных формы.
|
|
33
108
|
* @param schema - Схема валидации (стабильная ссылка).
|
|
@@ -40,6 +115,6 @@ export declare function defineValidationSchema<T>(schema: ValidationSchema<T>):
|
|
|
40
115
|
* const stepOk = await validateModel(model, step2Validation, { touch: true }); // + показать ошибки шага
|
|
41
116
|
* ```
|
|
42
117
|
*/
|
|
43
|
-
export declare function validateModel<T>(model: FormModel<T>, schema:
|
|
118
|
+
export declare function validateModel<T>(model: FormModel<T>, schema: ValidationDefinition<T>, options?: {
|
|
44
119
|
touch?: boolean;
|
|
45
120
|
}): Promise<boolean>;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { ReadonlySignal } from '@preact/signals-core';
|
|
2
|
-
import { FormModel } from '../../
|
|
3
|
-
import {
|
|
2
|
+
import { FormModel } from '../../model/types';
|
|
3
|
+
import { ValidationResult, ValidationDefinition } from './types';
|
|
4
4
|
/**
|
|
5
5
|
* Когда запускается schema-валидация:
|
|
6
|
-
* - `submit` (по умолчанию) — только явным
|
|
7
|
-
* - `blur` — при потере фокуса поля (
|
|
6
|
+
* - `submit` (по умолчанию) — только явным прогоном (`validate()`, отправка);
|
|
7
|
+
* - `blur` — при потере фокуса поля (каждый уход из любого листа, и повторный тоже);
|
|
8
8
|
* - `change` — на каждый ввод (с опц. `debounce`);
|
|
9
|
-
* - `afterFirstSubmit` — тихо до
|
|
9
|
+
* - `afterFirstSubmit` — тихо до первой попытки отправки (`run({ submit: true })`), затем live
|
|
10
|
+
* (см. `liveAfterSubmit`). Проверка без отправки (`validate()`) фазу не переключает.
|
|
10
11
|
*/
|
|
11
12
|
export type ValidationStrategyKind = 'submit' | 'blur' | 'change' | 'afterFirstSubmit';
|
|
12
13
|
export interface ValidationStrategyOptions {
|
|
@@ -17,12 +18,35 @@ export interface ValidationStrategyOptions {
|
|
|
17
18
|
/** Режим live-фазы для `afterFirstSubmit`. Default `'change'`. */
|
|
18
19
|
liveAfterSubmit?: 'change' | 'blur';
|
|
19
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Опции полного прогона {@link FormValidationController.run}.
|
|
23
|
+
*/
|
|
24
|
+
export interface FormValidationRunOptions {
|
|
25
|
+
/**
|
|
26
|
+
* Какие поля пометить тронутыми: `true` (по умолчанию) — проверенные правилами; `'all'` — они же,
|
|
27
|
+
* а при отказе (`invalid`, `error`) ещё и вся форма.
|
|
28
|
+
*/
|
|
29
|
+
touch?: true | 'all';
|
|
30
|
+
/**
|
|
31
|
+
* Прогон — попытка отправки: переводит `afterFirstSubmit` в живую фазу. Проверка без отправки
|
|
32
|
+
* (`validate()`, кнопка «Проверить») фазу не трогает.
|
|
33
|
+
*/
|
|
34
|
+
submit?: boolean;
|
|
35
|
+
}
|
|
20
36
|
export interface FormValidationController {
|
|
21
37
|
/**
|
|
22
|
-
* Полный прогон схемы с раскрытием
|
|
23
|
-
* `afterFirstSubmit` в
|
|
38
|
+
* Полный прогон схемы с раскрытием замечаний проверенных полей (`touch: true`). Попыткой
|
|
39
|
+
* отправки не считается: `afterFirstSubmit` остаётся в тихой фазе. Возвращает `true` только для
|
|
40
|
+
* статуса `valid`: ошибки, сбой правила и отмена дают `false`.
|
|
24
41
|
*/
|
|
25
42
|
validate(): Promise<boolean>;
|
|
43
|
+
/**
|
|
44
|
+
* Полный прогон с полным результатом: по статусу отличают ошибки (`invalid`) от сбоя правила
|
|
45
|
+
* (`error`) и отмены (`cancelled`). Без опций — тот же прогон, что
|
|
46
|
+
* {@link FormValidationController.validate}; `{ submit: true }` — попытка отправки,
|
|
47
|
+
* `{ touch: 'all' }` — при отказе раскрыть всю форму.
|
|
48
|
+
*/
|
|
49
|
+
run(options?: FormValidationRunOptions): Promise<ValidationResult>;
|
|
26
50
|
/**
|
|
27
51
|
* Армировать реактивные подписки стратегии. Идемпотентно. Возвращает `dispose`. НЕ звать при SSR.
|
|
28
52
|
*
|
|
@@ -31,7 +55,10 @@ export interface FormValidationController {
|
|
|
31
55
|
* после такого цикла молча оставался бы без живой валидации.
|
|
32
56
|
*/
|
|
33
57
|
start(): () => void;
|
|
34
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Снять подписки и таймеры, отменить идущий прогон (его `validate()` или `run()` получит
|
|
60
|
+
* `cancelled`). Идемпотентно; после него `start()` снова армирует стратегию.
|
|
61
|
+
*/
|
|
35
62
|
dispose(): void;
|
|
36
63
|
/** Идёт ли прогон (submit или live) — снапшот. */
|
|
37
64
|
readonly isValidating: boolean;
|
|
@@ -39,23 +66,24 @@ export interface FormValidationController {
|
|
|
39
66
|
readonly validating: ReadonlySignal<boolean>;
|
|
40
67
|
}
|
|
41
68
|
/**
|
|
42
|
-
* Собрать контроллер валидации формы с выбранной стратегией запуска.
|
|
43
|
-
*
|
|
69
|
+
* Собрать контроллер валидации формы с выбранной стратегией запуска. Движок прогона — тот же, что у
|
|
70
|
+
* `validateModel`.
|
|
44
71
|
*
|
|
45
72
|
* Фабрика ЧИСТАЯ до `start()` (никаких подписок) — безопасна для SSR/headless. Реактивные триггеры
|
|
46
73
|
* арминуются только в `start()` (в React — из `useEffect`).
|
|
47
74
|
*
|
|
48
75
|
* @typeParam T - Форма данных модели.
|
|
49
76
|
* @param model - Модель данных.
|
|
50
|
-
* @param schema - Схема валидации. **Стабильная ссылка** (иначе
|
|
77
|
+
* @param schema - Схема валидации. **Стабильная ссылка** (иначе устаревший прогон не отменится).
|
|
51
78
|
* @param options - {@link ValidationStrategyOptions}.
|
|
52
79
|
*
|
|
53
80
|
* @example
|
|
54
81
|
* ```ts
|
|
55
82
|
* const ctrl = createFormValidation(model, schema, { strategy: 'afterFirstSubmit', debounce: 300 });
|
|
56
83
|
* const dispose = ctrl.start(); // на клиенте
|
|
57
|
-
* const ok = await ctrl.validate(); //
|
|
84
|
+
* const ok = await ctrl.validate(); // проверка: замечания проверенных полей
|
|
85
|
+
* const sent = await ctrl.run({ touch: 'all', submit: true }); // попытка отправки: живая фаза
|
|
58
86
|
* dispose();
|
|
59
87
|
* ```
|
|
60
88
|
*/
|
|
61
|
-
export declare function createFormValidation<T>(model: FormModel<T>, schema:
|
|
89
|
+
export declare function createFormValidation<T>(model: FormModel<T>, schema: ValidationDefinition<T>, options?: ValidationStrategyOptions): FormValidationController;
|
|
@@ -1,29 +1,83 @@
|
|
|
1
|
-
import { FormModel,
|
|
1
|
+
import { FormModel, PathAwareSignal } from '../../model/types';
|
|
2
|
+
import { ValidationIssue } from '../types/contracts';
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
+
* Синхронное правило поля типа `TField`: получает значение, возвращает ошибку или `null`.
|
|
4
5
|
*
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*
|
|
6
|
+
* Правило, написанное для более широкого типа, подходит полю с более узким: `min()` принимает
|
|
7
|
+
* `number | null | undefined` и годится и полю `number`, и полю `number | null`; `required()`
|
|
8
|
+
* принимает любое значение. Обратное — ошибка компиляции: `validate(model.$.age, [email()])`
|
|
9
|
+
* подсветится, потому что `email` ждёт строку, а поле числовое.
|
|
10
|
+
*
|
|
11
|
+
* Правило над несколькими полями — оператор `cross` области схемы: он получает снимок модели.
|
|
10
12
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* const AMOUNT_RULES: Rule<number | null>[] = [required(), min(50000)];
|
|
16
|
+
* const notReserved: Rule<string> = (value) =>
|
|
17
|
+
* value === 'admin' ? { code: 'reserved' } : null;
|
|
18
|
+
* ```
|
|
17
19
|
*/
|
|
18
|
-
export type Rule<TField> = (value: TField
|
|
20
|
+
export type Rule<TField> = (value: TField) => ValidationIssue | null;
|
|
19
21
|
/**
|
|
20
22
|
* Асинхронное правило поля. Получает `AbortSignal` для отмены устаревших ответов (быстрый повторный
|
|
21
|
-
* прогон той же схемы отменяет предыдущий).
|
|
23
|
+
* прогон той же схемы отменяет предыдущий).
|
|
24
|
+
*
|
|
25
|
+
* Отклонённое правило (сеть, исключение) — это сбой проверки, а не «ошибок нет»: прогон получает
|
|
26
|
+
* статус `error`, поле — блокирующую ошибку `ruleFailed`. Если недоступность сервиса не должна
|
|
27
|
+
* мешать отправке, ловите ошибку в правиле и возвращайте `null` — это решение автора правила.
|
|
22
28
|
*/
|
|
23
29
|
export type AsyncRule<TField> = (value: TField, ctx: {
|
|
24
30
|
signal: AbortSignal;
|
|
25
|
-
}) => Promise<
|
|
26
|
-
/**
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
}) => Promise<ValidationIssue | null>;
|
|
32
|
+
/**
|
|
33
|
+
* Область схемы валидации — то, что схема получает аргументом.
|
|
34
|
+
*
|
|
35
|
+
* В корне прогона область — вся форма; в схеме, подключённой через `apply` / `applyEach`, —
|
|
36
|
+
* под-модель группы или строки массива. Поэтому правила подформы пишутся один раз и не знают, где
|
|
37
|
+
* она стоит.
|
|
38
|
+
*/
|
|
39
|
+
export interface ValidationScope<T> {
|
|
40
|
+
/** Модель области. Привязки правил — через её `$`: `validate(model.$.email, [...])`. */
|
|
41
|
+
readonly model: FormModel<T>;
|
|
42
|
+
/**
|
|
43
|
+
* Правило над несколькими полями: `check` получает снимок модели области (`model.get()`) и
|
|
44
|
+
* вешает ошибку на поле `handle`. Тип снимка выведен из схемы — приводить его не нужно.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* defineValidation<Loan>(({ model, cross }) => {
|
|
49
|
+
* cross(model.$.initialPayment, (loan) =>
|
|
50
|
+
* loan.initialPayment > loan.propertyValue ? tooHigh : null
|
|
51
|
+
* );
|
|
52
|
+
* });
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
cross(handle: PathAwareSignal<unknown>, check: (snapshot: T) => ValidationIssue | null): void;
|
|
56
|
+
}
|
|
57
|
+
/** Схема валидации — обычная функция над областью. First-class значение (можно `apply`/тестировать/переиспользовать). */
|
|
58
|
+
export type ValidationDefinition<T> = (scope: ValidationScope<T>) => void;
|
|
59
|
+
/**
|
|
60
|
+
* Чем закончился прогон схемы:
|
|
61
|
+
* - `valid` — блокирующих ошибок нет (`severity: 'warning'` не блокирует);
|
|
62
|
+
* - `invalid` — есть блокирующие ошибки;
|
|
63
|
+
* - `error` — хотя бы одно async-правило не вернуло результат (сеть, исключение);
|
|
64
|
+
* - `cancelled` — прогон устарел: для той же пары (model, schema) запущен следующий.
|
|
65
|
+
*
|
|
66
|
+
* Приоритет при нескольких причинах: `cancelled` → `error` → `invalid` → `valid`.
|
|
67
|
+
*/
|
|
68
|
+
export type ValidationStatus = 'valid' | 'invalid' | 'cancelled' | 'error';
|
|
69
|
+
/** Правило, которое не вернуло результат. */
|
|
70
|
+
export interface ValidationFailure {
|
|
71
|
+
/** Ручка поля `model.$.…`, чьё правило отклонилось. */
|
|
72
|
+
readonly handle: PathAwareSignal<unknown>;
|
|
73
|
+
/** То, чем правило отклонилось (ошибка сети, исключение). */
|
|
74
|
+
readonly error: unknown;
|
|
75
|
+
}
|
|
76
|
+
/** Результат прогона схемы валидации — см. `runValidation`. */
|
|
77
|
+
export interface ValidationResult {
|
|
78
|
+
readonly status: ValidationStatus;
|
|
79
|
+
/** Ошибки по ручке поля `model.$.…`; путь — метаданные ручки (`handle.__path`). */
|
|
80
|
+
readonly issues: ReadonlyMap<PathAwareSignal<unknown>, readonly ValidationIssue[]>;
|
|
81
|
+
/** Правила, которые не вернули результат (сеть, исключение). */
|
|
82
|
+
readonly failures: readonly ValidationFailure[];
|
|
83
|
+
}
|
|
@@ -6,7 +6,14 @@
|
|
|
6
6
|
* @module form/validators/date-utils
|
|
7
7
|
*/
|
|
8
8
|
/**
|
|
9
|
-
* Парсит значение в объект Date
|
|
9
|
+
* Парсит значение в объект Date. Строгий формат: `Date` либо строка `YYYY-MM-DD` (значение
|
|
10
|
+
* `<input type="date">`); любая другая строка — не дата. Разбор движка (`new Date(строка)`) не
|
|
11
|
+
* используется: он угадывает дату по обрывкам (`'hello 1'`, `'March 7'`), и результат зависит от
|
|
12
|
+
* движка.
|
|
13
|
+
*
|
|
14
|
+
* Строка `YYYY-MM-DD` — локальная полночь этого дня: `new Date('2024-01-01')` дал бы полночь UTC,
|
|
15
|
+
* и западнее UTC правила дат сравнивали бы предыдущий день. Несуществующая дата (`2023-02-29`)
|
|
16
|
+
* не разбирается — движок перенёс бы её на 1 марта.
|
|
10
17
|
*
|
|
11
18
|
* @param value - Значение для парсинга (Date, string или undefined)
|
|
12
19
|
* @returns Date объект или null если парсинг не удался
|
|
@@ -20,11 +27,16 @@ export declare function getToday(): Date;
|
|
|
20
27
|
* Нормализует дату, обнуляя время
|
|
21
28
|
*/
|
|
22
29
|
export declare function normalizeDate(date: Date): Date;
|
|
30
|
+
/** Дата рождения позже сегодняшнего дня. */
|
|
31
|
+
export declare function isFutureBirth(birthDate: Date): boolean;
|
|
23
32
|
/**
|
|
24
33
|
* Вычисляет полный возраст (в годах) по календарным полям.
|
|
25
34
|
*
|
|
26
35
|
* Считаем по годам/месяцам/дням, а не делением миллисекунд на усреднённый год (365.25 дн): усреднение
|
|
27
36
|
* даёт off-by-one на границе — в день N-летия накопленных реальных дней меньше `N * 365.25`, и `floor`
|
|
28
37
|
* роняет возраст до `N - 1` (т.е. `minAge(18)` ошибочно отклонял 18-летнего в его день рождения).
|
|
38
|
+
*
|
|
39
|
+
* Родившийся 29 февраля в невисокосный год становится на год старше 28 февраля: срок, исчисляемый
|
|
40
|
+
* годами, истекает в последний день месяца, если соответствующего числа в нём нет (ГК РФ, ст. 192).
|
|
29
41
|
*/
|
|
30
42
|
export declare function calculateAge(birthDate: Date): number;
|
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RuleOptions } from '../types/validation-schema';
|
|
2
|
+
import { Rule } from '../validation/types';
|
|
2
3
|
/**
|
|
3
4
|
* Фабрика валидатора формата email.
|
|
4
5
|
*
|
|
5
6
|
* Проверяет по упрощённому regex `^[^\s@]+@[^\s@]+\.[^\s@]+$`. Пустые значения
|
|
6
7
|
* (`''`/`null`/`undefined`) пропускаются (используйте {@link required} для обязательности).
|
|
7
8
|
*
|
|
8
|
-
* @param options - Опции валидатора ({@link
|
|
9
|
-
* @returns
|
|
9
|
+
* @param options - Опции валидатора ({@link RuleOptions}): `code`, `params`
|
|
10
|
+
* @returns Правило {@link Rule} для строкового поля
|
|
10
11
|
*
|
|
11
12
|
* @example Проверка формата email
|
|
12
13
|
* ```typescript
|
|
13
|
-
* import {
|
|
14
|
+
* import { defineValidation, validate } from '@reformer/core/validation';
|
|
14
15
|
* import { required, email } from '@reformer/core/validators';
|
|
15
16
|
*
|
|
16
17
|
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
17
|
-
* const validation =
|
|
18
|
-
* validate(model.$.email, [required(), email({
|
|
18
|
+
* const validation = defineValidation<MyForm>(({ model }) => {
|
|
19
|
+
* validate(model.$.email, [required(), email({ code: 'email.email' })]);
|
|
19
20
|
* });
|
|
20
21
|
* ```
|
|
21
22
|
*/
|
|
22
|
-
export declare function email
|
|
23
|
+
export declare function email(options?: RuleOptions): Rule<string | null | undefined>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RuleOptions } from '../types/validation-schema';
|
|
2
|
+
import { Rule } from '../validation/types';
|
|
2
3
|
/**
|
|
3
4
|
* Фабрика валидатора типа файла.
|
|
4
5
|
*
|
|
@@ -12,19 +13,19 @@ import { Validator, ValidateOptions } from '../types/validation-schema';
|
|
|
12
13
|
* пропускаются (используйте {@link required} для обязательности).
|
|
13
14
|
*
|
|
14
15
|
* @param accept - Accept-строка допустимых типов, например `'image/*,.pdf'`
|
|
15
|
-
* @param options - Опции валидатора ({@link
|
|
16
|
+
* @param options - Опции валидатора ({@link RuleOptions}). В `params` ошибки автоматически
|
|
16
17
|
* попадают `accept` и `fileName` (первый нарушивший файл).
|
|
17
|
-
* @returns
|
|
18
|
+
* @returns Правило {@link Rule} для файла или массива файлов
|
|
18
19
|
*
|
|
19
20
|
* @example Только изображения и PDF
|
|
20
21
|
* ```typescript
|
|
21
|
-
* import {
|
|
22
|
+
* import { defineValidation, validate } from '@reformer/core/validation';
|
|
22
23
|
* import { fileType } from '@reformer/core/validators';
|
|
23
24
|
*
|
|
24
25
|
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
25
|
-
* const validation =
|
|
26
|
-
* validate(model.$.documents, [fileType('image/*,.pdf', {
|
|
26
|
+
* const validation = defineValidation<MyForm>(({ model }) => {
|
|
27
|
+
* validate(model.$.documents, [fileType('image/*,.pdf', { code: 'documents.fileType' })]);
|
|
27
28
|
* });
|
|
28
29
|
* ```
|
|
29
30
|
*/
|
|
30
|
-
export declare function fileType
|
|
31
|
+
export declare function fileType(accept: string, options?: RuleOptions): Rule<unknown>;
|
|
@@ -39,7 +39,8 @@ export declare function toFileArray(value: unknown): FileLike[] | null;
|
|
|
39
39
|
/**
|
|
40
40
|
* Проверяет файл против accept-паттерна в синтаксисе нативного атрибута
|
|
41
41
|
* `<input type="file" accept>`: список через запятую из расширений (`.pdf`),
|
|
42
|
-
* точных MIME (`image/png`) и wildcard-категорий (`image/*`)
|
|
42
|
+
* точных MIME (`image/png`) и wildcard-категорий (`image/*`); шаблон «любой тип» (звёздочка,
|
|
43
|
+
* слэш, звёздочка) пропускает любой файл. Регистронезависимо.
|
|
43
44
|
*
|
|
44
45
|
* Нужен собственный матчер, потому что `accept` у нативного input — только подсказка
|
|
45
46
|
* пикеру: на drag-and-drop и на программное значение он не действует.
|
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RuleOptions } from '../types/validation-schema';
|
|
2
|
+
import { Rule } from '../validation/types';
|
|
2
3
|
/**
|
|
3
4
|
* Фабрика валидатора, проверяющего что дата не в прошлом.
|
|
4
5
|
*
|
|
5
6
|
* Дата не должна быть раньше сегодняшнего дня (сравнение по нормализованным датам).
|
|
6
7
|
* Пустые и невалидные даты пропускаются (используйте {@link required} и {@link isDate}).
|
|
7
8
|
*
|
|
8
|
-
* @param options - Опции валидатора ({@link
|
|
9
|
-
* @returns
|
|
9
|
+
* @param options - Опции валидатора ({@link RuleOptions}): `code`, `params`
|
|
10
|
+
* @returns Правило {@link Rule} для поля даты (`string | Date`)
|
|
10
11
|
*
|
|
11
12
|
* @example Дата не в прошлом
|
|
12
13
|
* ```typescript
|
|
13
|
-
* import {
|
|
14
|
+
* import { defineValidation, validate } from '@reformer/core/validation';
|
|
14
15
|
* import { required, futureDate } from '@reformer/core/validators';
|
|
15
16
|
*
|
|
16
17
|
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
17
|
-
* const validation =
|
|
18
|
-
* validate(model.$.appointmentDate, [required(), futureDate({
|
|
18
|
+
* const validation = defineValidation<MyForm>(({ model }) => {
|
|
19
|
+
* validate(model.$.appointmentDate, [required(), futureDate({ code: 'appointmentDate.futureDate' })]);
|
|
19
20
|
* });
|
|
20
21
|
* ```
|
|
21
22
|
*/
|
|
22
|
-
export declare function futureDate
|
|
23
|
+
export declare function futureDate(options?: RuleOptions): Rule<string | Date | null | undefined>;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Все примитивы — фабрики, возвращающие чистый `Validator<TForm, TField>`; передаются вторым
|
|
5
5
|
* аргументом оператора `validate` внутри схемы валидации: `validate(model.$.age, [required(), min(18)])`.
|
|
6
|
-
* В layout-схему формы правила НЕ кладутся — поля `validators` у узла
|
|
6
|
+
* В layout-схему формы правила НЕ кладутся — поля `validators` у узла нет.
|
|
7
7
|
*
|
|
8
8
|
* Гранулярные сабпаты (`@reformer/core/validators/required` и ещё 20) собираются отдельными
|
|
9
9
|
* entry для tree-shaking; этот модуль отдаёт полный набор для случаев, когда правил много.
|
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RuleOptions } from '../types/validation-schema';
|
|
2
|
+
import { Rule } from '../validation/types';
|
|
2
3
|
/**
|
|
3
4
|
* Фабрика валидатора, проверяющего что число — целое.
|
|
4
5
|
*
|
|
5
6
|
* Пустые значения и не-числа пропускаются (используйте {@link required} и {@link isNumber}).
|
|
6
7
|
*
|
|
7
|
-
* @param options - Опции валидатора ({@link
|
|
8
|
-
* @returns
|
|
8
|
+
* @param options - Опции валидатора ({@link RuleOptions}): `code`, `params`
|
|
9
|
+
* @returns Правило {@link Rule} для числового поля
|
|
9
10
|
*
|
|
10
11
|
* @example Проверка целого числа
|
|
11
12
|
* ```typescript
|
|
12
|
-
* import {
|
|
13
|
+
* import { defineValidation, validate } from '@reformer/core/validation';
|
|
13
14
|
* import { required, integer } from '@reformer/core/validators';
|
|
14
15
|
*
|
|
15
16
|
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
16
|
-
* const validation =
|
|
17
|
-
* validate(model.$.count, [required(), integer({
|
|
17
|
+
* const validation = defineValidation<MyForm>(({ model }) => {
|
|
18
|
+
* validate(model.$.count, [required(), integer({ code: 'count.integer' })]);
|
|
18
19
|
* });
|
|
19
20
|
* ```
|
|
20
21
|
*/
|
|
21
|
-
export declare function integer
|
|
22
|
+
export declare function integer(options?: RuleOptions): Rule<number | null | undefined>;
|
|
@@ -1,22 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RuleOptions } from '../types/validation-schema';
|
|
2
|
+
import { Rule } from '../validation/types';
|
|
2
3
|
/**
|
|
3
4
|
* Фабрика валидатора, проверяющего что значение — валидная дата.
|
|
4
5
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
6
|
+
* Строгий формат: `Date` либо строка `YYYY-MM-DD` с существующим днём календаря. Строки в иных
|
|
7
|
+
* форматах (`'31.12.2024'`, `'March 7'`, дата со временем) — `date_invalid`. Пустые значения
|
|
8
|
+
* (`''`/`null`/`undefined`) пропускаются (используйте {@link required} для обязательности).
|
|
7
9
|
*
|
|
8
|
-
* @param options - Опции валидатора ({@link
|
|
9
|
-
* @returns
|
|
10
|
+
* @param options - Опции валидатора ({@link RuleOptions}): `code`, `params`
|
|
11
|
+
* @returns Правило {@link Rule} для поля даты (`string | Date`)
|
|
10
12
|
*
|
|
11
13
|
* @example Проверка валидности даты
|
|
12
14
|
* ```typescript
|
|
13
|
-
* import {
|
|
15
|
+
* import { defineValidation, validate } from '@reformer/core/validation';
|
|
14
16
|
* import { required, isDate } from '@reformer/core/validators';
|
|
15
17
|
*
|
|
16
18
|
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
17
|
-
* const validation =
|
|
18
|
-
* validate(model.$.eventDate, [required(), isDate({
|
|
19
|
+
* const validation = defineValidation<MyForm>(({ model }) => {
|
|
20
|
+
* validate(model.$.eventDate, [required(), isDate({ code: 'eventDate.isDate' })]);
|
|
19
21
|
* });
|
|
20
22
|
* ```
|
|
21
23
|
*/
|
|
22
|
-
export declare function isDate
|
|
24
|
+
export declare function isDate(options?: RuleOptions): Rule<string | Date | null | undefined>;
|
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RuleOptions } from '../types/validation-schema';
|
|
2
|
+
import { Rule } from '../validation/types';
|
|
2
3
|
/**
|
|
3
|
-
* Фабрика валидатора, проверяющего что значение — конечное число (не NaN
|
|
4
|
+
* Фабрика валидатора, проверяющего что значение — конечное число (не `NaN`, не `±Infinity`,
|
|
5
|
+
* не строка).
|
|
4
6
|
*
|
|
5
|
-
* Пустые значения (`null`/`undefined`) пропускаются (используйте {@link required} для
|
|
7
|
+
* Пустые значения (`''`/`null`/`undefined`) пропускаются (используйте {@link required} для
|
|
6
8
|
* обязательности). В отличие от других number-валидаторов, **не** пропускает не-числа
|
|
7
9
|
* и `NaN` — это его задача.
|
|
8
10
|
*
|
|
9
|
-
* @param options - Опции валидатора ({@link
|
|
10
|
-
* @returns
|
|
11
|
+
* @param options - Опции валидатора ({@link RuleOptions}): `code`, `params`
|
|
12
|
+
* @returns Правило {@link Rule} для числового поля
|
|
11
13
|
*
|
|
12
14
|
* @example Проверка, что значение — число
|
|
13
15
|
* ```typescript
|
|
14
|
-
* import {
|
|
16
|
+
* import { defineValidation, validate } from '@reformer/core/validation';
|
|
15
17
|
* import { required, isNumber } from '@reformer/core/validators';
|
|
16
18
|
*
|
|
17
19
|
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
18
|
-
* const validation =
|
|
19
|
-
* validate(model.$.amount, [required(), isNumber({
|
|
20
|
+
* const validation = defineValidation<MyForm>(({ model }) => {
|
|
21
|
+
* validate(model.$.amount, [required(), isNumber({ code: 'amount.isNumber' })]);
|
|
20
22
|
* });
|
|
21
23
|
* ```
|
|
22
24
|
*/
|
|
23
|
-
export declare function isNumber
|
|
25
|
+
export declare function isNumber(options?: RuleOptions): Rule<number | null | undefined>;
|