@reformer/core 2.0.0-beta.7 → 2.0.0-beta.8
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.d.ts +2 -0
- package/dist/behaviors/compute-from.js +31 -0
- package/dist/behaviors/copy-from.d.ts +2 -0
- package/dist/behaviors/copy-from.js +29 -0
- package/dist/behaviors/enable-when.d.ts +2 -0
- package/dist/behaviors/enable-when.js +25 -0
- package/dist/behaviors/reset-when.d.ts +2 -0
- package/dist/behaviors/reset-when.js +24 -0
- package/dist/behaviors/revalidate-when.d.ts +2 -0
- package/dist/behaviors/revalidate-when.js +18 -0
- package/dist/behaviors/sync-fields.d.ts +2 -0
- package/dist/behaviors/sync-fields.js +41 -0
- package/dist/behaviors/transform-value.d.ts +2 -0
- package/dist/behaviors/transform-value.js +45 -0
- package/dist/behaviors/watch-field.d.ts +2 -0
- package/dist/behaviors/watch-field.js +21 -0
- package/dist/behaviors.js +26 -19
- package/dist/core/behavior/behavior-context.d.ts +26 -12
- package/dist/core/behavior/behavior-registry.d.ts +15 -27
- package/dist/core/behavior/behaviors/compute-from.d.ts +50 -21
- package/dist/core/behavior/behaviors/copy-from.d.ts +39 -14
- package/dist/core/behavior/behaviors/enable-when.d.ts +88 -19
- package/dist/core/behavior/behaviors/reset-when.d.ts +31 -18
- package/dist/core/behavior/behaviors/revalidate-when.d.ts +40 -17
- package/dist/core/behavior/behaviors/sync-fields.d.ts +34 -14
- package/dist/core/behavior/behaviors/transform-value.d.ts +116 -44
- package/dist/core/behavior/behaviors/watch-field.d.ts +66 -21
- package/dist/core/behavior/compose-behavior.d.ts +2 -12
- package/dist/core/behavior/index.d.ts +0 -1
- package/dist/core/behavior/types.d.ts +2 -8
- package/dist/core/factories/node-factory.d.ts +6 -29
- package/dist/core/nodes/array-node.d.ts +11 -15
- package/dist/core/nodes/field-node.d.ts +43 -24
- package/dist/core/nodes/form-node.d.ts +18 -20
- package/dist/core/nodes/group-node.d.ts +25 -21
- package/dist/core/types/deep-schema.d.ts +2 -12
- package/dist/core/types/field-path.d.ts +1 -1
- package/dist/core/types/form-context.d.ts +26 -26
- package/dist/core/types/form-proxy.d.ts +1 -31
- package/dist/core/types/index.d.ts +16 -4
- package/dist/core/types/validation-schema.d.ts +3 -12
- package/dist/core/utils/abstract-registry.d.ts +74 -0
- package/dist/core/utils/aggregate-signals.d.ts +71 -0
- package/dist/core/utils/create-form.d.ts +1 -20
- package/dist/core/utils/error-handler.d.ts +1 -18
- package/dist/core/utils/field-path-navigator.d.ts +1 -1
- package/dist/core/utils/field-path.d.ts +23 -11
- package/dist/core/utils/form-observer.d.ts +176 -0
- package/dist/core/utils/form-proxy-builder.d.ts +25 -0
- package/dist/core/utils/form-submitter.d.ts +121 -0
- package/dist/core/utils/index.d.ts +8 -2
- package/dist/core/utils/registry-helpers.d.ts +0 -7
- package/dist/core/utils/safe-effect.d.ts +73 -0
- package/dist/core/utils/status-machine.d.ts +153 -0
- package/dist/core/utils/type-guards.d.ts +5 -23
- package/dist/core/utils/unique-id.d.ts +34 -7
- package/dist/core/validation/core/apply-when.d.ts +3 -9
- package/dist/core/validation/core/apply.d.ts +2 -13
- package/dist/core/validation/core/validate-async.d.ts +2 -8
- package/dist/core/validation/core/validate-tree.d.ts +0 -6
- package/dist/core/validation/core/validate.d.ts +1 -7
- package/dist/core/validation/index.d.ts +8 -2
- package/dist/core/validation/validate-form.d.ts +1 -38
- package/dist/core/validation/validation-applicator.d.ts +2 -21
- package/dist/core/validation/validation-context.d.ts +38 -14
- package/dist/core/validation/validation-registry.d.ts +11 -20
- package/dist/core/validation/validators/array-validators.d.ts +2 -12
- package/dist/core/validation/validators/date-utils.d.ts +26 -0
- package/dist/core/validation/validators/email.d.ts +2 -9
- package/dist/core/validation/validators/future-date.d.ts +35 -0
- package/dist/core/validation/validators/index.d.ts +7 -1
- package/dist/core/validation/validators/is-date.d.ts +36 -0
- package/dist/core/validation/validators/max-age.d.ts +36 -0
- package/dist/core/validation/validators/max-date.d.ts +36 -0
- package/dist/core/validation/validators/max-length.d.ts +3 -10
- package/dist/core/validation/validators/max.d.ts +3 -10
- package/dist/core/validation/validators/min-age.d.ts +36 -0
- package/dist/core/validation/validators/min-date.d.ts +36 -0
- package/dist/core/validation/validators/min-length.d.ts +3 -10
- package/dist/core/validation/validators/min.d.ts +3 -10
- package/dist/core/validation/validators/number.d.ts +2 -9
- package/dist/core/validation/validators/past-date.d.ts +35 -0
- package/dist/core/validation/validators/pattern.d.ts +2 -9
- package/dist/core/validation/validators/phone.d.ts +2 -9
- package/dist/core/validation/validators/required.d.ts +2 -9
- package/dist/core/validation/validators/url.d.ts +2 -9
- package/dist/date-utils-xUWFslTj.js +29 -0
- package/dist/field-path-DuKdGcIE.js +66 -0
- package/dist/hooks/types.d.ts +1 -1
- package/dist/hooks/useArrayLength.d.ts +31 -0
- package/dist/hooks/useFormControl.d.ts +4 -4
- package/dist/hooks/useFormControlValue.d.ts +2 -2
- package/dist/hooks/useHiddenCondition.d.ts +25 -0
- package/dist/hooks/useSignalSubscription.d.ts +1 -1
- package/dist/index-D25LsbRm.js +73 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1031 -714
- package/dist/registry-helpers-Bv_BJ1s-.js +615 -0
- package/dist/safe-effect-Dh8uw81c.js +20 -0
- package/dist/validate-C3XiA_zf.js +10 -0
- package/dist/validators/email.d.ts +2 -0
- package/dist/validators/email.js +13 -0
- package/dist/validators/future-date.d.ts +2 -0
- package/dist/validators/future-date.js +20 -0
- package/dist/validators/is-date.d.ts +2 -0
- package/dist/validators/is-date.js +12 -0
- package/dist/validators/max-age.d.ts +2 -0
- package/dist/validators/max-age.js +20 -0
- package/dist/validators/max-date.d.ts +2 -0
- package/dist/validators/max-date.js +20 -0
- package/dist/validators/max-length.d.ts +2 -0
- package/dist/validators/max-length.js +11 -0
- package/dist/validators/max.d.ts +2 -0
- package/dist/validators/max.js +11 -0
- package/dist/validators/min-age.d.ts +2 -0
- package/dist/validators/min-age.js +20 -0
- package/dist/validators/min-date.d.ts +2 -0
- package/dist/validators/min-date.js +20 -0
- package/dist/validators/min-length.d.ts +2 -0
- package/dist/validators/min-length.js +11 -0
- package/dist/validators/min.d.ts +2 -0
- package/dist/validators/min.js +11 -0
- package/dist/validators/number.d.ts +2 -0
- package/dist/validators/number.js +35 -0
- package/dist/validators/past-date.d.ts +2 -0
- package/dist/validators/past-date.js +20 -0
- package/dist/validators/pattern.d.ts +2 -0
- package/dist/validators/pattern.js +11 -0
- package/dist/validators/phone.d.ts +2 -0
- package/dist/validators/phone.js +35 -0
- package/dist/validators/required.d.ts +2 -0
- package/dist/validators/required.js +15 -0
- package/dist/validators/url.d.ts +2 -0
- package/dist/validators/url.js +19 -0
- package/dist/validators-BGsNOgT1.js +207 -0
- package/dist/validators.js +54 -29
- package/llms.txt +7878 -311
- package/package.json +83 -9
- package/dist/behaviors-DyPzh2-X.js +0 -508
- package/dist/core/behavior/create-field-path.d.ts +0 -7
- package/dist/core/context/form-context-impl.d.ts +0 -29
- package/dist/core/utils/debounce.d.ts +0 -160
- package/dist/core/utils/resources.d.ts +0 -41
- package/dist/core/validation/field-path.d.ts +0 -7
- package/dist/core/validation/validators/date.d.ts +0 -38
- package/dist/registry-helpers--8-OogF8.js +0 -477
- package/dist/validators-CWdzevnC.js +0 -397
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { ReadonlySignal } from '@preact/signals-core';
|
|
2
|
+
import { FieldStatus } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* События для State Machine
|
|
5
|
+
*/
|
|
6
|
+
export type StatusEvent = {
|
|
7
|
+
type: 'START_VALIDATION';
|
|
8
|
+
} | {
|
|
9
|
+
type: 'VALIDATION_SUCCESS';
|
|
10
|
+
} | {
|
|
11
|
+
type: 'VALIDATION_FAILURE';
|
|
12
|
+
} | {
|
|
13
|
+
type: 'DISABLE';
|
|
14
|
+
} | {
|
|
15
|
+
type: 'ENABLE';
|
|
16
|
+
hasErrors?: boolean;
|
|
17
|
+
} | {
|
|
18
|
+
type: 'SET_ERRORS';
|
|
19
|
+
hasErrors: boolean;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* FormStatusMachine - управляет состоянием поля формы
|
|
23
|
+
*
|
|
24
|
+
* Предоставляет:
|
|
25
|
+
* - Единый источник истины для статуса
|
|
26
|
+
* - Computed signals для derived состояний (valid, invalid, pending, disabled)
|
|
27
|
+
* - Валидацию переходов между состояниями
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const statusMachine = new FormStatusMachine('valid');
|
|
32
|
+
*
|
|
33
|
+
* // Начало валидации
|
|
34
|
+
* statusMachine.startValidation();
|
|
35
|
+
* console.log(statusMachine.pending.value); // true
|
|
36
|
+
*
|
|
37
|
+
* // Завершение валидации с ошибками
|
|
38
|
+
* statusMachine.completeValidation(true);
|
|
39
|
+
* console.log(statusMachine.invalid.value); // true
|
|
40
|
+
*
|
|
41
|
+
* // Отключение поля
|
|
42
|
+
* statusMachine.disable();
|
|
43
|
+
* console.log(statusMachine.disabled.value); // true
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare class FormStatusMachine {
|
|
47
|
+
/** Внутренний сигнал статуса */
|
|
48
|
+
private readonly _status;
|
|
49
|
+
/** Публичный read-only сигнал статуса */
|
|
50
|
+
readonly status: ReadonlySignal<FieldStatus>;
|
|
51
|
+
/** Поле валидно */
|
|
52
|
+
readonly valid: ReadonlySignal<boolean>;
|
|
53
|
+
/** Поле невалидно */
|
|
54
|
+
readonly invalid: ReadonlySignal<boolean>;
|
|
55
|
+
/** Идет валидация */
|
|
56
|
+
readonly pending: ReadonlySignal<boolean>;
|
|
57
|
+
/** Поле отключено */
|
|
58
|
+
readonly disabled: ReadonlySignal<boolean>;
|
|
59
|
+
/**
|
|
60
|
+
* @param initial - Начальный статус (по умолчанию 'valid')
|
|
61
|
+
*/
|
|
62
|
+
constructor(initial?: FieldStatus);
|
|
63
|
+
/**
|
|
64
|
+
* Начать валидацию
|
|
65
|
+
*
|
|
66
|
+
* Переводит статус в 'pending' если поле не отключено
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* statusMachine.startValidation();
|
|
71
|
+
* // status: 'pending'
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
startValidation(): void;
|
|
75
|
+
/**
|
|
76
|
+
* Завершить валидацию
|
|
77
|
+
*
|
|
78
|
+
* @param hasErrors - Есть ли ошибки валидации
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* // Валидация успешна
|
|
83
|
+
* statusMachine.completeValidation(false);
|
|
84
|
+
* // status: 'valid'
|
|
85
|
+
*
|
|
86
|
+
* // Есть ошибки
|
|
87
|
+
* statusMachine.completeValidation(true);
|
|
88
|
+
* // status: 'invalid'
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
completeValidation(hasErrors: boolean): void;
|
|
92
|
+
/**
|
|
93
|
+
* Установить ошибки напрямую (без перехода через pending)
|
|
94
|
+
*
|
|
95
|
+
* Используется для синхронной валидации или установки ошибок извне
|
|
96
|
+
*
|
|
97
|
+
* @param hasErrors - Есть ли ошибки
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* statusMachine.setErrors(true);
|
|
102
|
+
* // status: 'invalid'
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
setErrors(hasErrors: boolean): void;
|
|
106
|
+
/**
|
|
107
|
+
* Отключить поле
|
|
108
|
+
*
|
|
109
|
+
* Переводит статус в 'disabled'
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```typescript
|
|
113
|
+
* statusMachine.disable();
|
|
114
|
+
* // status: 'disabled'
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
disable(): void;
|
|
118
|
+
/**
|
|
119
|
+
* Включить поле
|
|
120
|
+
*
|
|
121
|
+
* @param hasErrors - Есть ли ошибки (определяет valid/invalid)
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```typescript
|
|
125
|
+
* statusMachine.enable(false);
|
|
126
|
+
* // status: 'valid'
|
|
127
|
+
*
|
|
128
|
+
* statusMachine.enable(true);
|
|
129
|
+
* // status: 'invalid'
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
enable(hasErrors?: boolean): void;
|
|
133
|
+
/**
|
|
134
|
+
* Обработать событие (альтернативный API)
|
|
135
|
+
*
|
|
136
|
+
* @param event - Событие для обработки
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* statusMachine.dispatch({ type: 'START_VALIDATION' });
|
|
141
|
+
* statusMachine.dispatch({ type: 'VALIDATION_FAILURE' });
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
dispatch(event: StatusEvent): void;
|
|
145
|
+
/**
|
|
146
|
+
* Получить текущий статус
|
|
147
|
+
*/
|
|
148
|
+
getStatus(): FieldStatus;
|
|
149
|
+
/**
|
|
150
|
+
* Проверить, можно ли начать валидацию
|
|
151
|
+
*/
|
|
152
|
+
canValidate(): boolean;
|
|
153
|
+
}
|
|
@@ -1,26 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* @group Utilities
|
|
7
|
-
* @category Type Guards
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```typescript
|
|
11
|
-
* import { isFieldNode, isGroupNode } from '@/core/utils/type-guards';
|
|
12
|
-
*
|
|
13
|
-
* if (isFieldNode(node)) {
|
|
14
|
-
* // TypeScript знает, что node это FieldNode
|
|
15
|
-
* node.validators;
|
|
16
|
-
* }
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
import type { FormNode } from '../nodes/form-node';
|
|
20
|
-
import type { FieldNode } from '../nodes/field-node';
|
|
21
|
-
import type { GroupNode } from '../nodes/group-node';
|
|
22
|
-
import type { ArrayNode } from '../nodes/array-node';
|
|
23
|
-
import type { FormFields, FormValue } from '../types';
|
|
1
|
+
import { FormNode } from '../nodes/form-node';
|
|
2
|
+
import { FieldNode } from '../nodes/field-node';
|
|
3
|
+
import { GroupNode } from '../nodes/group-node';
|
|
4
|
+
import { ArrayNode } from '../nodes/array-node';
|
|
5
|
+
import { FormFields, FormValue } from '../types';
|
|
24
6
|
/**
|
|
25
7
|
* Проверить, является ли значение любым FormNode
|
|
26
8
|
*
|
|
@@ -7,18 +7,45 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
9
9
|
* ```typescript
|
|
10
|
-
* const key1 = uniqueId(
|
|
11
|
-
* const key2 = uniqueId(
|
|
12
|
-
* const key3 = uniqueId(
|
|
10
|
+
* const key1 = uniqueId(SubscriptionKey.Watch); // "watch-1"
|
|
11
|
+
* const key2 = uniqueId(SubscriptionKey.Watch); // "watch-2"
|
|
12
|
+
* const key3 = uniqueId(SubscriptionKey.ComputeFrom); // "computeFrom-3"
|
|
13
13
|
* ```
|
|
14
14
|
*/
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* Типобезопасные ключи для подписок
|
|
17
|
+
* Используются с uniqueId() для генерации уникальных идентификаторов
|
|
18
|
+
*/
|
|
19
|
+
export declare const SubscriptionKey: {
|
|
20
|
+
/** FieldNode.watch() */
|
|
21
|
+
readonly Watch: "watch";
|
|
22
|
+
/** FieldNode.computeFrom() */
|
|
23
|
+
readonly ComputeFrom: "computeFrom";
|
|
24
|
+
/** GroupNode.linkFields() */
|
|
25
|
+
readonly LinkFields: "linkFields";
|
|
26
|
+
/** GroupNode.watchField() */
|
|
27
|
+
readonly WatchField: "watchField";
|
|
28
|
+
/** ArrayNode.watchItems() */
|
|
29
|
+
readonly WatchItems: "watchItems";
|
|
30
|
+
/** ArrayNode.watchLength() */
|
|
31
|
+
readonly WatchLength: "watchLength";
|
|
32
|
+
};
|
|
33
|
+
export type SubscriptionKeyType = (typeof SubscriptionKey)[keyof typeof SubscriptionKey];
|
|
34
|
+
/**
|
|
35
|
+
* Генерирует уникальный идентификатор с указанным префиксом.
|
|
17
36
|
*
|
|
18
|
-
* @param prefix - Префикс для идентификатора
|
|
19
|
-
* @returns Уникальный идентификатор в формате `${prefix}-${counter}
|
|
37
|
+
* @param prefix - Префикс для идентификатора (используйте {@link SubscriptionKey}).
|
|
38
|
+
* @returns Уникальный идентификатор в формате `${prefix}-${counter}`.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* import { uniqueId, SubscriptionKey } from '@reformer/core';
|
|
43
|
+
*
|
|
44
|
+
* uniqueId(SubscriptionKey.WatchField); // → 'watchField-1'
|
|
45
|
+
* uniqueId(SubscriptionKey.WatchField); // → 'watchField-2'
|
|
46
|
+
* ```
|
|
20
47
|
*/
|
|
21
|
-
export declare function uniqueId(prefix:
|
|
48
|
+
export declare function uniqueId(prefix: SubscriptionKeyType): string;
|
|
22
49
|
/**
|
|
23
50
|
* Сбросить счётчик (только для тестов)
|
|
24
51
|
* @internal
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* @group Validation
|
|
5
|
-
* @category Core Functions
|
|
6
|
-
*/
|
|
7
|
-
import type { FieldPath } from '../../types/field-path';
|
|
8
|
-
import type { ConditionFn } from '../../types/validation-schema';
|
|
9
|
-
import type { FieldPathNode } from '../../types';
|
|
1
|
+
import { FieldPath } from '../../types/field-path';
|
|
2
|
+
import { ConditionFn } from '../../types/validation-schema';
|
|
3
|
+
import { FieldPathNode } from '../../types';
|
|
10
4
|
/**
|
|
11
5
|
* Применить валидацию только при выполнении условия
|
|
12
6
|
*
|
|
@@ -1,16 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Предоставляет функции для переиспользования validation схем:
|
|
5
|
-
* - apply: применение схемы к полям (новый API)
|
|
6
|
-
*
|
|
7
|
-
* Дополняет существующий toFieldPath и applyWhen.
|
|
8
|
-
*
|
|
9
|
-
* @group Validation
|
|
10
|
-
* @category Core Functions
|
|
11
|
-
*/
|
|
12
|
-
import type { FieldPathNode, FieldPath } from '../../types';
|
|
13
|
-
import type { ValidationSchemaFn } from '../../types/validation-schema';
|
|
1
|
+
import { FieldPathNode, FieldPath } from '../../types';
|
|
2
|
+
import { ValidationSchemaFn } from '../../types/validation-schema';
|
|
14
3
|
/**
|
|
15
4
|
* Применить validation схему к корневому path формы
|
|
16
5
|
*
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* @group Validation
|
|
5
|
-
* @category Core Functions
|
|
6
|
-
*/
|
|
7
|
-
import type { ContextualAsyncValidatorFn, ValidateAsyncOptions } from '../../types/validation-schema';
|
|
8
|
-
import type { FieldPathNode } from '../../types';
|
|
1
|
+
import { ContextualAsyncValidatorFn, ValidateAsyncOptions } from '../../types/validation-schema';
|
|
2
|
+
import { FieldPathNode } from '../../types';
|
|
9
3
|
/**
|
|
10
4
|
* Зарегистрировать асинхронный валидатор для поля
|
|
11
5
|
*
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Кастомная синхронная валидация поля
|
|
3
|
-
*
|
|
4
|
-
* @group Validation
|
|
5
|
-
* @category Core Functions
|
|
6
|
-
*/
|
|
7
|
-
import type { ContextualValidatorFn, FieldPathNode, ValidateOptions } from '../../types';
|
|
1
|
+
import { ContextualValidatorFn, FieldPathNode, ValidateOptions } from '../../types';
|
|
8
2
|
/**
|
|
9
3
|
* Зарегистрировать кастомный синхронный валидатор для поля
|
|
10
4
|
* Поддерживает опциональные поля
|
|
@@ -13,9 +13,15 @@ export { pattern } from './validators/pattern';
|
|
|
13
13
|
export { url } from './validators/url';
|
|
14
14
|
export { phone, type PhoneFormat } from './validators/phone';
|
|
15
15
|
export { number } from './validators/number';
|
|
16
|
-
export {
|
|
16
|
+
export { isDate } from './validators/is-date';
|
|
17
|
+
export { minDate } from './validators/min-date';
|
|
18
|
+
export { maxDate } from './validators/max-date';
|
|
19
|
+
export { pastDate } from './validators/past-date';
|
|
20
|
+
export { futureDate } from './validators/future-date';
|
|
21
|
+
export { minAge } from './validators/min-age';
|
|
22
|
+
export { maxAge } from './validators/max-age';
|
|
17
23
|
export { notEmpty, validateItems } from './validators/array-validators';
|
|
18
|
-
export { createFieldPath, extractPath, extractKey, toFieldPath } from '
|
|
24
|
+
export { createFieldPath, extractPath, extractKey, toFieldPath } from '../utils/field-path';
|
|
19
25
|
export { validateForm } from './validate-form';
|
|
20
26
|
export { ValidationRegistry } from './validation-registry';
|
|
21
27
|
export { ValidationContextImpl, TreeValidationContextImpl } from './validation-context';
|
|
@@ -1,42 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* validateForm - утилита для валидации формы в соответствии со схемой
|
|
3
|
-
*
|
|
4
|
-
* Позволяет применить validation schema к форме без изменения
|
|
5
|
-
* зарегистрированной схемы в ValidationRegistry.
|
|
6
|
-
*
|
|
7
|
-
* ## Использование
|
|
8
|
-
*
|
|
9
|
-
* - **Multi-step формы**: валидация только полей текущего шага
|
|
10
|
-
* - **Условная валидация**: применение разных схем в зависимости от состояния
|
|
11
|
-
* - **Временная валидация**: проверка без сохранения в реестр
|
|
12
|
-
*
|
|
13
|
-
* ## Как это работает
|
|
14
|
-
*
|
|
15
|
-
* 1. Создаётся временный ValidationRegistry для схемы
|
|
16
|
-
* 2. Валидируются все FieldNode (field-level валидаторы из FieldConfig)
|
|
17
|
-
* 3. Применяются ТОЛЬКО contextual validators из переданной схемы
|
|
18
|
-
* 4. Временный реестр отменяется (не сохраняется в форму)
|
|
19
|
-
*
|
|
20
|
-
* ## Важно для multi-step форм
|
|
21
|
-
*
|
|
22
|
-
* Форма может быть создана С полной схемой валидации:
|
|
23
|
-
* ```typescript
|
|
24
|
-
* createForm({
|
|
25
|
-
* form: schema,
|
|
26
|
-
* validation: fullValidation, // Полная схема
|
|
27
|
-
* });
|
|
28
|
-
* ```
|
|
29
|
-
*
|
|
30
|
-
* При этом `validateForm(form, stepSchema)` будет применять
|
|
31
|
-
* только валидаторы из `stepSchema`, игнорируя валидаторы
|
|
32
|
-
* из других шагов.
|
|
33
|
-
*
|
|
34
|
-
* @see docs/multi-step-validation.md для подробной документации
|
|
35
|
-
*
|
|
36
|
-
* @module validation
|
|
37
|
-
*/
|
|
38
1
|
import { GroupNode } from '../nodes/group-node';
|
|
39
|
-
import
|
|
2
|
+
import { ValidationSchemaFn, FormFields } from '../types';
|
|
40
3
|
/**
|
|
41
4
|
* Валидировать форму в соответствии с указанной схемой
|
|
42
5
|
*
|
|
@@ -1,24 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Извлечено из GroupNode для соблюдения SRP (Single Responsibility Principle).
|
|
5
|
-
* Отвечает только за логику применения валидаторов к полям формы.
|
|
6
|
-
*
|
|
7
|
-
* @template T Тип формы
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```typescript
|
|
11
|
-
* class GroupNode {
|
|
12
|
-
* private readonly validationApplicator = new ValidationApplicator(this);
|
|
13
|
-
*
|
|
14
|
-
* async applyContextualValidators(validators: ValidatorRegistration[]) {
|
|
15
|
-
* await this.validationApplicator.apply(validators);
|
|
16
|
-
* }
|
|
17
|
-
* }
|
|
18
|
-
* ```
|
|
19
|
-
*/
|
|
20
|
-
import type { GroupNode } from '../nodes/group-node';
|
|
21
|
-
import type { ValidatorRegistration } from '../types';
|
|
1
|
+
import { GroupNode } from '../nodes/group-node';
|
|
2
|
+
import { ValidatorRegistration } from '../types';
|
|
22
3
|
/**
|
|
23
4
|
* Класс для применения валидаторов к форме
|
|
24
5
|
*
|
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* между различными типами контекстов валидации.
|
|
6
|
-
*/
|
|
7
|
-
import type { GroupNode } from '../nodes/group-node';
|
|
8
|
-
import type { FieldNode } from '../nodes/field-node';
|
|
9
|
-
import type { FormProxy } from '../types/form-proxy';
|
|
10
|
-
import type { FormContext } from '../types/form-context';
|
|
1
|
+
import { GroupNode } from '../nodes/group-node';
|
|
2
|
+
import { FieldNode } from '../nodes/field-node';
|
|
3
|
+
import { FormProxy } from '../types/form-proxy';
|
|
4
|
+
import { FormContext } from '../types/form-context';
|
|
11
5
|
/**
|
|
12
6
|
* Базовый класс контекста валидации
|
|
13
7
|
* Содержит общую логику для всех типов контекстов
|
|
@@ -25,10 +19,27 @@ declare abstract class BaseValidationContext<TForm> implements FormContext<TForm
|
|
|
25
19
|
* Автоматически использует emitEvent: false для предотвращения циклов
|
|
26
20
|
*/
|
|
27
21
|
setFieldValue(path: string, value: unknown): void;
|
|
22
|
+
/**
|
|
23
|
+
* Получить поле формы по строковому пути
|
|
24
|
+
*/
|
|
25
|
+
getFieldByPath(path: string): import('../..').FormNode<import('../types').FormValue> | undefined;
|
|
28
26
|
}
|
|
29
27
|
/**
|
|
30
|
-
* Контекст валидации
|
|
31
|
-
*
|
|
28
|
+
* Контекст валидации одного поля. Создаётся фреймворком и передаётся в валидаторы
|
|
29
|
+
* (`required`, `validate`, …) — напрямую инстанцировать не нужно.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* import { validate } from '@reformer/core/validators';
|
|
34
|
+
*
|
|
35
|
+
* validate(path.password, (value, ctx) => {
|
|
36
|
+
* // ctx — экземпляр ValidationContextImpl, доступ к ctx.form для cross-field логики
|
|
37
|
+
* if (value !== ctx.form.confirmPassword.value) {
|
|
38
|
+
* return { code: 'mismatch', message: 'Пароли не совпадают' };
|
|
39
|
+
* }
|
|
40
|
+
* return null;
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
32
43
|
*/
|
|
33
44
|
export declare class ValidationContextImpl<TForm, TField> extends BaseValidationContext<TForm> {
|
|
34
45
|
private control;
|
|
@@ -40,8 +51,21 @@ export declare class ValidationContextImpl<TForm, TField> extends BaseValidation
|
|
|
40
51
|
value(): TField;
|
|
41
52
|
}
|
|
42
53
|
/**
|
|
43
|
-
* Контекст
|
|
44
|
-
*
|
|
54
|
+
* Контекст cross-field валидации. Передаётся в `validateTree`/`validateForm`
|
|
55
|
+
* callback'и — напрямую инстанцировать не нужно.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* import { validateForm } from '@reformer/core';
|
|
60
|
+
*
|
|
61
|
+
* validateForm(form, (ctx) => {
|
|
62
|
+
* // ctx — экземпляр TreeValidationContextImpl
|
|
63
|
+
* if (ctx.form.startDate.value > ctx.form.endDate.value) {
|
|
64
|
+
* return [{ code: 'date-range', message: 'Дата начала позже даты окончания' }];
|
|
65
|
+
* }
|
|
66
|
+
* return [];
|
|
67
|
+
* });
|
|
68
|
+
* ```
|
|
45
69
|
*/
|
|
46
70
|
export declare class TreeValidationContextImpl<TForm> extends BaseValidationContext<TForm> {
|
|
47
71
|
constructor(form: GroupNode<TForm>);
|
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
* ValidationRegistry - система регистрации и применения валидаторов
|
|
3
|
-
*
|
|
4
|
-
* Работает как стек контекстов:
|
|
5
|
-
* 1. При вызове validation schema функции создается новый контекст
|
|
6
|
-
* 2. Все вызовы validate(), applyWhen() и т.д. регистрируют валидаторы в текущем контексте
|
|
7
|
-
* 3. После завершения схемы валидаторы применяются к GroupNode
|
|
8
|
-
*/
|
|
9
|
-
import type { GroupNode } from '../nodes/group-node';
|
|
1
|
+
import { GroupNode } from '../nodes/group-node';
|
|
10
2
|
import { FormFields } from '../types';
|
|
11
|
-
import
|
|
3
|
+
import { AbstractRegistry } from '../utils/abstract-registry';
|
|
4
|
+
import { ValidatorRegistration, ContextualValidatorFn, ContextualAsyncValidatorFn, TreeValidatorFn, ConditionFn, ValidateOptions, ValidateAsyncOptions, ValidateTreeOptions } from '../types/validation-schema';
|
|
12
5
|
/**
|
|
13
6
|
* Контекст регистрации валидаторов
|
|
7
|
+
* Управляет condition stack для условных валидаторов
|
|
14
8
|
*/
|
|
15
9
|
declare class RegistrationContext {
|
|
16
10
|
private validators;
|
|
@@ -38,10 +32,9 @@ declare class RegistrationContext {
|
|
|
38
32
|
* Каждый экземпляр GroupNode создает собственный реестр (композиция).
|
|
39
33
|
* Устраняет race conditions и изолирует формы друг от друга.
|
|
40
34
|
*
|
|
41
|
-
*
|
|
42
|
-
* -
|
|
43
|
-
* -
|
|
44
|
-
* - getCurrent() возвращает текущий активный реестр
|
|
35
|
+
* Наследует AbstractRegistry для унификации:
|
|
36
|
+
* - Управления global stack
|
|
37
|
+
* - Template methods begin/end registration
|
|
45
38
|
*
|
|
46
39
|
* @example
|
|
47
40
|
* ```typescript
|
|
@@ -56,13 +49,10 @@ declare class RegistrationContext {
|
|
|
56
49
|
* }
|
|
57
50
|
* ```
|
|
58
51
|
*/
|
|
59
|
-
export declare class ValidationRegistry {
|
|
60
|
-
/**
|
|
61
|
-
* Global stack активных реестров
|
|
62
|
-
* Используется для изоляции форм друг от друга
|
|
63
|
-
*/
|
|
64
|
-
private static registryStack;
|
|
52
|
+
export declare class ValidationRegistry extends AbstractRegistry<ValidatorRegistration> {
|
|
53
|
+
/** Внутренний стек контекстов для управления condition blocks */
|
|
65
54
|
private contextStack;
|
|
55
|
+
/** Финальные валидаторы после завершения регистрации */
|
|
66
56
|
private validators;
|
|
67
57
|
/**
|
|
68
58
|
* Получить текущий активный реестр из global stack
|
|
@@ -85,6 +75,7 @@ export declare class ValidationRegistry {
|
|
|
85
75
|
* Начать регистрацию валидаторов для формы
|
|
86
76
|
*
|
|
87
77
|
* Помещает this в global stack для изоляции форм
|
|
78
|
+
* Создает новый RegistrationContext для condition management
|
|
88
79
|
*/
|
|
89
80
|
beginRegistration(): RegistrationContext;
|
|
90
81
|
/**
|
|
@@ -1,15 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Предоставляет специализированные функции для валидации ArrayNode:
|
|
5
|
-
* - notEmpty: проверка что массив не пустой
|
|
6
|
-
* - validateItems: применение validation schema к каждому элементу
|
|
7
|
-
*
|
|
8
|
-
* @group Validation
|
|
9
|
-
* @category Validators
|
|
10
|
-
*/
|
|
11
|
-
import type { ValidateOptions, ValidationSchemaFn } from '../../types/validation-schema';
|
|
12
|
-
import type { FieldPathNode } from '../../types';
|
|
1
|
+
import { ValidateOptions, ValidationSchemaFn } from '../../types/validation-schema';
|
|
2
|
+
import { FieldPathNode } from '../../types';
|
|
13
3
|
/**
|
|
14
4
|
* Проверить что массив содержит хотя бы один элемент
|
|
15
5
|
*
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Утилиты для работы с датами в валидаторах
|
|
3
|
+
*
|
|
4
|
+
* @group Validation
|
|
5
|
+
* @category Validators
|
|
6
|
+
* @module validators/date-utils
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Парсит значение в объект Date
|
|
10
|
+
*
|
|
11
|
+
* @param value - Значение для парсинга (Date, string или undefined)
|
|
12
|
+
* @returns Date объект или null если парсинг не удался
|
|
13
|
+
*/
|
|
14
|
+
export declare function parseDate(value: string | Date | null | undefined): Date | null;
|
|
15
|
+
/**
|
|
16
|
+
* Возвращает сегодняшнюю дату с обнулённым временем
|
|
17
|
+
*/
|
|
18
|
+
export declare function getToday(): Date;
|
|
19
|
+
/**
|
|
20
|
+
* Нормализует дату, обнуляя время
|
|
21
|
+
*/
|
|
22
|
+
export declare function normalizeDate(date: Date): Date;
|
|
23
|
+
/**
|
|
24
|
+
* Вычисляет возраст на основе даты рождения
|
|
25
|
+
*/
|
|
26
|
+
export declare function calculateAge(birthDate: Date): number;
|
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* @group Validation
|
|
5
|
-
* @category Validators
|
|
6
|
-
* @module validators/email
|
|
7
|
-
*/
|
|
8
|
-
import type { ValidateOptions } from '../../types/validation-schema';
|
|
9
|
-
import type { FieldPathNode } from '../../types';
|
|
1
|
+
import { ValidateOptions } from '../../types/validation-schema';
|
|
2
|
+
import { FieldPathNode } from '../../types';
|
|
10
3
|
/**
|
|
11
4
|
* Валидатор формата email
|
|
12
5
|
*
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ValidateOptions } from '../../types/validation-schema';
|
|
2
|
+
import { FieldPathNode } from '../../types';
|
|
3
|
+
/**
|
|
4
|
+
* Проверяет, что дата находится в будущем (не в прошлом)
|
|
5
|
+
*
|
|
6
|
+
* Пустые значения и невалидные даты пропускаются (используйте `required` и `isDate`).
|
|
7
|
+
*
|
|
8
|
+
* @group Validation
|
|
9
|
+
* @category Validators
|
|
10
|
+
*
|
|
11
|
+
* @param fieldPath - Путь к полю для валидации
|
|
12
|
+
* @param options - Опции валидации (message, params)
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* // Базовое использование - дата события должна быть в будущем
|
|
17
|
+
* validationSchema: (path) => [
|
|
18
|
+
* futureDate(path.eventDate),
|
|
19
|
+
* ]
|
|
20
|
+
*
|
|
21
|
+
* // С кастомным сообщением
|
|
22
|
+
* futureDate(path.appointmentDate, { message: 'Дата записи должна быть в будущем' })
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* // Ошибка валидации
|
|
28
|
+
* {
|
|
29
|
+
* code: 'date_past',
|
|
30
|
+
* message: 'Дата не может быть в прошлом',
|
|
31
|
+
* params: {}
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function futureDate<TForm, TField extends string | Date | undefined = string | Date>(fieldPath: FieldPathNode<TForm, TField> | undefined, options?: ValidateOptions): void;
|
|
@@ -11,4 +11,10 @@ export { pattern } from './pattern';
|
|
|
11
11
|
export { url } from './url';
|
|
12
12
|
export { phone, type PhoneFormat } from './phone';
|
|
13
13
|
export { number } from './number';
|
|
14
|
-
export {
|
|
14
|
+
export { isDate } from './is-date';
|
|
15
|
+
export { minDate } from './min-date';
|
|
16
|
+
export { maxDate } from './max-date';
|
|
17
|
+
export { pastDate } from './past-date';
|
|
18
|
+
export { futureDate } from './future-date';
|
|
19
|
+
export { minAge } from './min-age';
|
|
20
|
+
export { maxAge } from './max-age';
|