@reformer/core 1.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +53 -0
- package/dist/behaviors.d.ts +2 -0
- package/dist/behaviors.js +230 -0
- package/dist/core/behavior/behavior-applicator.d.ts +71 -0
- package/dist/core/behavior/behavior-applicator.js +92 -0
- package/dist/core/behavior/behavior-context.d.ts +29 -0
- package/dist/core/behavior/behavior-context.js +38 -0
- package/dist/core/behavior/behavior-registry.d.ts +97 -0
- package/dist/core/behavior/behavior-registry.js +198 -0
- package/dist/core/behavior/behaviors/compute-from.d.ts +41 -0
- package/dist/core/behavior/behaviors/compute-from.js +84 -0
- package/dist/core/behavior/behaviors/copy-from.d.ts +31 -0
- package/dist/core/behavior/behaviors/copy-from.js +64 -0
- package/dist/core/behavior/behaviors/enable-when.d.ts +49 -0
- package/dist/core/behavior/behaviors/enable-when.js +81 -0
- package/dist/core/behavior/behaviors/index.d.ts +11 -0
- package/dist/core/behavior/behaviors/index.js +11 -0
- package/dist/core/behavior/behaviors/reset-when.d.ts +51 -0
- package/dist/core/behavior/behaviors/reset-when.js +63 -0
- package/dist/core/behavior/behaviors/revalidate-when.d.ts +30 -0
- package/dist/core/behavior/behaviors/revalidate-when.js +51 -0
- package/dist/core/behavior/behaviors/sync-fields.d.ts +28 -0
- package/dist/core/behavior/behaviors/sync-fields.js +66 -0
- package/dist/core/behavior/behaviors/transform-value.d.ts +120 -0
- package/dist/core/behavior/behaviors/transform-value.js +110 -0
- package/dist/core/behavior/behaviors/watch-field.d.ts +35 -0
- package/dist/core/behavior/behaviors/watch-field.js +56 -0
- package/dist/core/behavior/compose-behavior.d.ts +106 -0
- package/dist/core/behavior/compose-behavior.js +166 -0
- package/dist/core/behavior/create-field-path.d.ts +20 -0
- package/dist/core/behavior/create-field-path.js +69 -0
- package/dist/core/behavior/index.d.ts +12 -0
- package/dist/core/behavior/index.js +17 -0
- package/dist/core/behavior/types.d.ts +152 -0
- package/dist/core/behavior/types.js +7 -0
- package/dist/core/context/form-context-impl.d.ts +29 -0
- package/dist/core/context/form-context-impl.js +37 -0
- package/dist/core/factories/index.d.ts +6 -0
- package/dist/core/factories/index.js +6 -0
- package/dist/core/factories/node-factory.d.ts +209 -0
- package/dist/core/factories/node-factory.js +281 -0
- package/dist/core/nodes/array-node.d.ts +308 -0
- package/dist/core/nodes/array-node.js +534 -0
- package/dist/core/nodes/field-node.d.ts +269 -0
- package/dist/core/nodes/field-node.js +510 -0
- package/dist/core/nodes/form-node.d.ts +342 -0
- package/dist/core/nodes/form-node.js +343 -0
- package/dist/core/nodes/group-node/field-registry.d.ts +191 -0
- package/dist/core/nodes/group-node/field-registry.js +215 -0
- package/dist/core/nodes/group-node/index.d.ts +11 -0
- package/dist/core/nodes/group-node/index.js +11 -0
- package/dist/core/nodes/group-node/proxy-builder.d.ts +71 -0
- package/dist/core/nodes/group-node/proxy-builder.js +161 -0
- package/dist/core/nodes/group-node/state-manager.d.ts +184 -0
- package/dist/core/nodes/group-node/state-manager.js +265 -0
- package/dist/core/nodes/group-node.d.ts +494 -0
- package/dist/core/nodes/group-node.js +770 -0
- package/dist/core/types/deep-schema.d.ts +78 -0
- package/dist/core/types/deep-schema.js +11 -0
- package/dist/core/types/field-path.d.ts +42 -0
- package/dist/core/types/field-path.js +4 -0
- package/dist/core/types/form-context.d.ts +83 -0
- package/dist/core/types/form-context.js +25 -0
- package/dist/core/types/group-node-proxy.d.ts +135 -0
- package/dist/core/types/group-node-proxy.js +31 -0
- package/dist/core/types/index.d.ts +163 -0
- package/dist/core/types/index.js +4 -0
- package/dist/core/types/validation-schema.d.ts +104 -0
- package/dist/core/types/validation-schema.js +10 -0
- package/dist/core/utils/create-form.d.ts +61 -0
- package/dist/core/utils/create-form.js +24 -0
- package/dist/core/utils/debounce.d.ts +160 -0
- package/dist/core/utils/debounce.js +197 -0
- package/dist/core/utils/error-handler.d.ts +180 -0
- package/dist/core/utils/error-handler.js +226 -0
- package/dist/core/utils/field-path-navigator.d.ts +240 -0
- package/dist/core/utils/field-path-navigator.js +374 -0
- package/dist/core/utils/index.d.ts +14 -0
- package/dist/core/utils/index.js +14 -0
- package/dist/core/utils/registry-helpers.d.ts +50 -0
- package/dist/core/utils/registry-helpers.js +79 -0
- package/dist/core/utils/registry-stack.d.ts +69 -0
- package/dist/core/utils/registry-stack.js +86 -0
- package/dist/core/utils/resources.d.ts +41 -0
- package/dist/core/utils/resources.js +69 -0
- package/dist/core/utils/subscription-manager.d.ts +180 -0
- package/dist/core/utils/subscription-manager.js +214 -0
- package/dist/core/utils/type-guards.d.ts +116 -0
- package/dist/core/utils/type-guards.js +169 -0
- package/dist/core/validation/core/apply-when.d.ts +28 -0
- package/dist/core/validation/core/apply-when.js +41 -0
- package/dist/core/validation/core/apply.d.ts +63 -0
- package/dist/core/validation/core/apply.js +38 -0
- package/dist/core/validation/core/index.d.ts +8 -0
- package/dist/core/validation/core/index.js +8 -0
- package/dist/core/validation/core/validate-async.d.ts +42 -0
- package/dist/core/validation/core/validate-async.js +45 -0
- package/dist/core/validation/core/validate-tree.d.ts +35 -0
- package/dist/core/validation/core/validate-tree.js +37 -0
- package/dist/core/validation/core/validate.d.ts +32 -0
- package/dist/core/validation/core/validate.js +38 -0
- package/dist/core/validation/field-path.d.ts +43 -0
- package/dist/core/validation/field-path.js +147 -0
- package/dist/core/validation/index.d.ts +21 -0
- package/dist/core/validation/index.js +33 -0
- package/dist/core/validation/validate-form.d.ts +85 -0
- package/dist/core/validation/validate-form.js +152 -0
- package/dist/core/validation/validation-applicator.d.ts +89 -0
- package/dist/core/validation/validation-applicator.js +217 -0
- package/dist/core/validation/validation-context.d.ts +47 -0
- package/dist/core/validation/validation-context.js +75 -0
- package/dist/core/validation/validation-registry.d.ts +156 -0
- package/dist/core/validation/validation-registry.js +298 -0
- package/dist/core/validation/validators/array-validators.d.ts +63 -0
- package/dist/core/validation/validators/array-validators.js +86 -0
- package/dist/core/validation/validators/date.d.ts +38 -0
- package/dist/core/validation/validators/date.js +117 -0
- package/dist/core/validation/validators/email.d.ts +44 -0
- package/dist/core/validation/validators/email.js +60 -0
- package/dist/core/validation/validators/index.d.ts +14 -0
- package/dist/core/validation/validators/index.js +14 -0
- package/dist/core/validation/validators/max-length.d.ts +45 -0
- package/dist/core/validation/validators/max-length.js +60 -0
- package/dist/core/validation/validators/max.d.ts +45 -0
- package/dist/core/validation/validators/max.js +60 -0
- package/dist/core/validation/validators/min-length.d.ts +45 -0
- package/dist/core/validation/validators/min-length.js +60 -0
- package/dist/core/validation/validators/min.d.ts +45 -0
- package/dist/core/validation/validators/min.js +60 -0
- package/dist/core/validation/validators/number.d.ts +38 -0
- package/dist/core/validation/validators/number.js +90 -0
- package/dist/core/validation/validators/pattern.d.ts +47 -0
- package/dist/core/validation/validators/pattern.js +62 -0
- package/dist/core/validation/validators/phone.d.ts +34 -0
- package/dist/core/validation/validators/phone.js +58 -0
- package/dist/core/validation/validators/required.d.ts +48 -0
- package/dist/core/validation/validators/required.js +69 -0
- package/dist/core/validation/validators/url.d.ts +29 -0
- package/dist/core/validation/validators/url.js +55 -0
- package/dist/create-field-path-CdPF3lIK.js +704 -0
- package/dist/hooks/useFormControl.d.ts +48 -0
- package/dist/hooks/useFormControl.js +298 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +8 -0
- package/dist/node-factory-D7DOnSSN.js +3200 -0
- package/dist/validators.d.ts +2 -0
- package/dist/validators.js +298 -0
- package/llms.txt +847 -0
- package/package.json +86 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FormErrorHandler - централизованная обработка ошибок в формах
|
|
3
|
+
*
|
|
4
|
+
* Устраняет несогласованность обработки ошибок между:
|
|
5
|
+
* - field-node.ts (логирует и конвертирует в ValidationError)
|
|
6
|
+
* - behavior-applicator.ts (логирует и пробрасывает)
|
|
7
|
+
* - validation-applicator.ts (логирует и проглатывает)
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* try {
|
|
12
|
+
* await validator(value);
|
|
13
|
+
* } catch (error) {
|
|
14
|
+
* return FormErrorHandler.handle(error, 'AsyncValidator', ErrorStrategy.CONVERT);
|
|
15
|
+
* }
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Стратегия обработки ошибок
|
|
20
|
+
*
|
|
21
|
+
* Определяет, что делать с ошибкой после логирования
|
|
22
|
+
*/
|
|
23
|
+
export var ErrorStrategy;
|
|
24
|
+
(function (ErrorStrategy) {
|
|
25
|
+
/**
|
|
26
|
+
* Пробросить ошибку дальше (throw)
|
|
27
|
+
* Используется когда ошибка критична и должна остановить выполнение
|
|
28
|
+
*/
|
|
29
|
+
ErrorStrategy["THROW"] = "throw";
|
|
30
|
+
/**
|
|
31
|
+
* Залогировать и проглотить ошибку (продолжить выполнение)
|
|
32
|
+
* Используется когда ошибка не критична
|
|
33
|
+
*/
|
|
34
|
+
ErrorStrategy["LOG"] = "log";
|
|
35
|
+
/**
|
|
36
|
+
* Конвертировать ошибку в ValidationError
|
|
37
|
+
* Используется в async validators для отображения ошибки валидации пользователю
|
|
38
|
+
*/
|
|
39
|
+
ErrorStrategy["CONVERT"] = "convert";
|
|
40
|
+
})(ErrorStrategy || (ErrorStrategy = {}));
|
|
41
|
+
/**
|
|
42
|
+
* Централизованный обработчик ошибок для форм
|
|
43
|
+
*
|
|
44
|
+
* Обеспечивает:
|
|
45
|
+
* - Единообразное логирование ошибок в DEV режиме
|
|
46
|
+
* - Гибкие стратегии обработки (throw/log/convert)
|
|
47
|
+
* - Типобезопасное извлечение сообщений из Error/string/unknown
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* // В async validator (конвертировать в ValidationError)
|
|
52
|
+
* try {
|
|
53
|
+
* await validateEmail(value);
|
|
54
|
+
* } catch (error) {
|
|
55
|
+
* return FormErrorHandler.handle(error, 'EmailValidator', ErrorStrategy.CONVERT);
|
|
56
|
+
* }
|
|
57
|
+
*
|
|
58
|
+
* // В behavior applicator (пробросить критичную ошибку)
|
|
59
|
+
* try {
|
|
60
|
+
* applyBehavior(schema);
|
|
61
|
+
* } catch (error) {
|
|
62
|
+
* FormErrorHandler.handle(error, 'BehaviorApplicator', ErrorStrategy.THROW);
|
|
63
|
+
* }
|
|
64
|
+
*
|
|
65
|
+
* // В validator (залогировать и продолжить)
|
|
66
|
+
* try {
|
|
67
|
+
* validator(value);
|
|
68
|
+
* } catch (error) {
|
|
69
|
+
* FormErrorHandler.handle(error, 'Validator', ErrorStrategy.LOG);
|
|
70
|
+
* }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export class FormErrorHandler {
|
|
74
|
+
/**
|
|
75
|
+
* Обработать ошибку согласно заданной стратегии
|
|
76
|
+
*
|
|
77
|
+
* @param error Ошибка для обработки (Error | string | unknown)
|
|
78
|
+
* @param context Контекст ошибки для логирования (например, 'AsyncValidator', 'BehaviorRegistry')
|
|
79
|
+
* @param strategy Стратегия обработки (THROW | LOG | CONVERT)
|
|
80
|
+
* @returns ValidationError если strategy = CONVERT, undefined если strategy = LOG, никогда не возвращается если strategy = THROW
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```typescript
|
|
84
|
+
* // THROW - пробросить ошибку
|
|
85
|
+
* try {
|
|
86
|
+
* riskyOperation();
|
|
87
|
+
* } catch (error) {
|
|
88
|
+
* FormErrorHandler.handle(error, 'RiskyOperation', ErrorStrategy.THROW);
|
|
89
|
+
* // Этот код никогда не выполнится
|
|
90
|
+
* }
|
|
91
|
+
*
|
|
92
|
+
* // LOG - залогировать и продолжить
|
|
93
|
+
* try {
|
|
94
|
+
* nonCriticalOperation();
|
|
95
|
+
* } catch (error) {
|
|
96
|
+
* FormErrorHandler.handle(error, 'NonCritical', ErrorStrategy.LOG);
|
|
97
|
+
* // Продолжаем выполнение
|
|
98
|
+
* }
|
|
99
|
+
*
|
|
100
|
+
* // CONVERT - конвертировать в ValidationError
|
|
101
|
+
* try {
|
|
102
|
+
* await validator(value);
|
|
103
|
+
* } catch (error) {
|
|
104
|
+
* const validationError = FormErrorHandler.handle(
|
|
105
|
+
* error,
|
|
106
|
+
* 'AsyncValidator',
|
|
107
|
+
* ErrorStrategy.CONVERT
|
|
108
|
+
* );
|
|
109
|
+
* return validationError;
|
|
110
|
+
* }
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
static handle(error, context, strategy = ErrorStrategy.THROW) {
|
|
114
|
+
// Извлекаем сообщение из ошибки
|
|
115
|
+
const message = this.extractMessage(error);
|
|
116
|
+
// Логируем в DEV режиме
|
|
117
|
+
if (import.meta.env.DEV) {
|
|
118
|
+
console.error(`[${context}]`, error);
|
|
119
|
+
}
|
|
120
|
+
// Применяем стратегию
|
|
121
|
+
switch (strategy) {
|
|
122
|
+
case ErrorStrategy.THROW:
|
|
123
|
+
throw error;
|
|
124
|
+
case ErrorStrategy.LOG:
|
|
125
|
+
// Просто логируем, не возвращаем ничего
|
|
126
|
+
return;
|
|
127
|
+
case ErrorStrategy.CONVERT:
|
|
128
|
+
// Конвертируем в ValidationError
|
|
129
|
+
return {
|
|
130
|
+
code: 'validator_error',
|
|
131
|
+
message,
|
|
132
|
+
params: { field: context },
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Извлечь сообщение из ошибки
|
|
138
|
+
*
|
|
139
|
+
* Обрабатывает различные типы ошибок:
|
|
140
|
+
* - Error объекты → error.message
|
|
141
|
+
* - Строки → возвращает как есть
|
|
142
|
+
* - Объекты с message → извлекает message
|
|
143
|
+
* - Другое → String(error)
|
|
144
|
+
*
|
|
145
|
+
* @param error Ошибка для извлечения сообщения
|
|
146
|
+
* @returns Сообщение ошибки
|
|
147
|
+
* @private
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```typescript
|
|
151
|
+
* FormErrorHandler.extractMessage(new Error('Test'));
|
|
152
|
+
* // 'Test'
|
|
153
|
+
*
|
|
154
|
+
* FormErrorHandler.extractMessage('String error');
|
|
155
|
+
* // 'String error'
|
|
156
|
+
*
|
|
157
|
+
* FormErrorHandler.extractMessage({ message: 'Object error' });
|
|
158
|
+
* // 'Object error'
|
|
159
|
+
*
|
|
160
|
+
* FormErrorHandler.extractMessage(null);
|
|
161
|
+
* // 'null'
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
static extractMessage(error) {
|
|
165
|
+
if (error instanceof Error) {
|
|
166
|
+
return error.message;
|
|
167
|
+
}
|
|
168
|
+
if (typeof error === 'string') {
|
|
169
|
+
return error;
|
|
170
|
+
}
|
|
171
|
+
if (typeof error === 'object' && error !== null && 'message' in error) {
|
|
172
|
+
return String(error.message);
|
|
173
|
+
}
|
|
174
|
+
return String(error);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Создать ValidationError с заданными параметрами
|
|
178
|
+
*
|
|
179
|
+
* Утилитная функция для создания ValidationError объектов
|
|
180
|
+
*
|
|
181
|
+
* @param code Код ошибки
|
|
182
|
+
* @param message Сообщение ошибки
|
|
183
|
+
* @param field Поле (опционально)
|
|
184
|
+
* @returns ValidationError объект
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```typescript
|
|
188
|
+
* const error = FormErrorHandler.createValidationError(
|
|
189
|
+
* 'required',
|
|
190
|
+
* 'This field is required',
|
|
191
|
+
* 'email'
|
|
192
|
+
* );
|
|
193
|
+
* // { code: 'required', message: 'This field is required', field: 'email' }
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
static createValidationError(code, message, field) {
|
|
197
|
+
return {
|
|
198
|
+
code,
|
|
199
|
+
message,
|
|
200
|
+
params: field ? { field } : undefined,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Проверить, является ли объект ValidationError
|
|
205
|
+
*
|
|
206
|
+
* Type guard для ValidationError
|
|
207
|
+
*
|
|
208
|
+
* @param value Значение для проверки
|
|
209
|
+
* @returns true если value является ValidationError
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```typescript
|
|
213
|
+
* if (FormErrorHandler.isValidationError(result)) {
|
|
214
|
+
* console.log(result.code); // OK, типобезопасно
|
|
215
|
+
* }
|
|
216
|
+
* ```
|
|
217
|
+
*/
|
|
218
|
+
static isValidationError(value) {
|
|
219
|
+
return (typeof value === 'object' &&
|
|
220
|
+
value !== null &&
|
|
221
|
+
'code' in value &&
|
|
222
|
+
'message' in value &&
|
|
223
|
+
typeof value.code === 'string' &&
|
|
224
|
+
typeof value.message === 'string');
|
|
225
|
+
}
|
|
226
|
+
}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import type { UnknownRecord } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Сегмент пути к полю формы
|
|
4
|
+
*
|
|
5
|
+
* Представляет один сегмент в пути к полю, например:
|
|
6
|
+
* - `"email" → { key: 'email' }`
|
|
7
|
+
* - `"items[0]" → { key: 'items', index: 0 }`
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* // Путь "items[0].name" разбивается на:
|
|
14
|
+
* [
|
|
15
|
+
* { key: 'items', index: 0 },
|
|
16
|
+
* { key: 'name' }
|
|
17
|
+
* ]
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export interface PathSegment {
|
|
21
|
+
/**
|
|
22
|
+
* Ключ поля
|
|
23
|
+
*/
|
|
24
|
+
key: string;
|
|
25
|
+
/**
|
|
26
|
+
* Индекс в массиве (опционально)
|
|
27
|
+
* Присутствует только для сегментов вида "items[0]"
|
|
28
|
+
*/
|
|
29
|
+
index?: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Навигация по путям к полям формы
|
|
33
|
+
*
|
|
34
|
+
* Централизует логику парсинга и навигации по путям к полям формы.
|
|
35
|
+
* Используется в ValidationContext, BehaviorContext, GroupNode для единообразной
|
|
36
|
+
* обработки путей вида "address.city" или "items[0].name".
|
|
37
|
+
*
|
|
38
|
+
* Устраняет дублирование логики парсинга путей в 4 местах кодовой базы.
|
|
39
|
+
*
|
|
40
|
+
* @internal
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* const navigator = new FieldPathNavigator();
|
|
45
|
+
*
|
|
46
|
+
* // Парсинг пути
|
|
47
|
+
* const segments = navigator.parsePath('items[0].title');
|
|
48
|
+
* // [{ key: 'items', index: 0 }, { key: 'title' }]
|
|
49
|
+
*
|
|
50
|
+
* // Получение значения из объекта
|
|
51
|
+
* const obj = { items: [{ title: 'Item 1' }] };
|
|
52
|
+
* const value = navigator.getValueByPath(obj, 'items[0].title');
|
|
53
|
+
* // 'Item 1'
|
|
54
|
+
*
|
|
55
|
+
* // Получение узла формы
|
|
56
|
+
* const titleNode = navigator.getNodeByPath(form, 'items[0].title');
|
|
57
|
+
* titleNode?.setValue('New Title');
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare class FieldPathNavigator {
|
|
61
|
+
/**
|
|
62
|
+
* Парсит путь в массив сегментов
|
|
63
|
+
*
|
|
64
|
+
* Поддерживаемые форматы:
|
|
65
|
+
* - Простые пути: "name", "email"
|
|
66
|
+
* - Вложенные пути: "address.city", "user.profile.avatar"
|
|
67
|
+
* - Массивы: "items[0]", "items[0].name", "tags[1][0]"
|
|
68
|
+
* - Комбинации: "orders[0].items[1].price"
|
|
69
|
+
*
|
|
70
|
+
* @param path Путь к полю (строка с точками и квадратными скобками)
|
|
71
|
+
* @returns Массив сегментов пути
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* navigator.parsePath('email');
|
|
76
|
+
* // [{ key: 'email' }]
|
|
77
|
+
*
|
|
78
|
+
* navigator.parsePath('address.city');
|
|
79
|
+
* // [{ key: 'address' }, { key: 'city' }]
|
|
80
|
+
*
|
|
81
|
+
* navigator.parsePath('items[0].name');
|
|
82
|
+
* // [{ key: 'items', index: 0 }, { key: 'name' }]
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
parsePath(path: string): PathSegment[];
|
|
86
|
+
/**
|
|
87
|
+
* Добавляет сегмент в массив, обрабатывая массивы
|
|
88
|
+
* @private
|
|
89
|
+
*/
|
|
90
|
+
private addSegment;
|
|
91
|
+
/**
|
|
92
|
+
* Получает значение по пути из объекта
|
|
93
|
+
*
|
|
94
|
+
* Проходит по всем сегментам пути и возвращает конечное значение.
|
|
95
|
+
* Если путь не найден, возвращает undefined.
|
|
96
|
+
*
|
|
97
|
+
* @param obj Объект для навигации
|
|
98
|
+
* @param path Путь к значению
|
|
99
|
+
* @returns Значение или undefined, если путь не найден
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* const obj = {
|
|
104
|
+
* email: 'test@mail.com',
|
|
105
|
+
* address: { city: 'Moscow' },
|
|
106
|
+
* items: [{ title: 'Item 1' }]
|
|
107
|
+
* };
|
|
108
|
+
*
|
|
109
|
+
* navigator.getValueByPath(obj, 'email');
|
|
110
|
+
* // 'test@mail.com'
|
|
111
|
+
*
|
|
112
|
+
* navigator.getValueByPath(obj, 'address.city');
|
|
113
|
+
* // 'Moscow'
|
|
114
|
+
*
|
|
115
|
+
* navigator.getValueByPath(obj, 'items[0].title');
|
|
116
|
+
* // 'Item 1'
|
|
117
|
+
*
|
|
118
|
+
* navigator.getValueByPath(obj, 'invalid.path');
|
|
119
|
+
* // undefined
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
getValueByPath(obj: UnknownRecord, path: string): unknown;
|
|
123
|
+
/**
|
|
124
|
+
* Устанавливает значение по пути в объекте (мутирует объект)
|
|
125
|
+
*
|
|
126
|
+
* Создает промежуточные объекты, если они не существуют.
|
|
127
|
+
* Выбрасывает ошибку, если ожидается массив, но его нет.
|
|
128
|
+
*
|
|
129
|
+
* @param obj Объект для модификации
|
|
130
|
+
* @param path Путь к значению
|
|
131
|
+
* @param value Новое значение
|
|
132
|
+
*
|
|
133
|
+
* @throws {Error} Если ожидается массив по пути, но его нет
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```typescript
|
|
137
|
+
* const obj = { address: { city: '' } };
|
|
138
|
+
* navigator.setValueByPath(obj, 'address.city', 'Moscow');
|
|
139
|
+
* // obj.address.city === 'Moscow'
|
|
140
|
+
*
|
|
141
|
+
* const obj2: UnknownRecord = {};
|
|
142
|
+
* navigator.setValueByPath(obj2, 'address.city', 'Moscow');
|
|
143
|
+
* // Создаст { address: { city: 'Moscow' } }
|
|
144
|
+
*
|
|
145
|
+
* const obj3 = { items: [{ title: 'Old' }] };
|
|
146
|
+
* navigator.setValueByPath(obj3, 'items[0].title', 'New');
|
|
147
|
+
* // obj3.items[0].title === 'New'
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
setValueByPath(obj: UnknownRecord, path: string, value: unknown): void;
|
|
151
|
+
/**
|
|
152
|
+
* Получить значение из FormNode по пути
|
|
153
|
+
*
|
|
154
|
+
* Автоматически извлекает значение из FormNode (через .value.value).
|
|
155
|
+
* Используется в ValidationContext и BehaviorContext для единообразного
|
|
156
|
+
* доступа к значениям полей формы.
|
|
157
|
+
*
|
|
158
|
+
* @param form Корневой узел формы (обычно GroupNode)
|
|
159
|
+
* @param path Путь к полю
|
|
160
|
+
* @returns Значение поля или undefined, если путь не найден
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```typescript
|
|
164
|
+
* const form = new GroupNode({
|
|
165
|
+
* email: { value: 'test@mail.com', component: Input },
|
|
166
|
+
* address: {
|
|
167
|
+
* city: { value: 'Moscow', component: Input }
|
|
168
|
+
* },
|
|
169
|
+
* items: [{ title: { value: 'Item 1', component: Input } }]
|
|
170
|
+
* });
|
|
171
|
+
*
|
|
172
|
+
* navigator.getFormNodeValue(form, 'email');
|
|
173
|
+
* // 'test@mail.com'
|
|
174
|
+
*
|
|
175
|
+
* navigator.getFormNodeValue(form, 'address.city');
|
|
176
|
+
* // 'Moscow'
|
|
177
|
+
*
|
|
178
|
+
* navigator.getFormNodeValue(form, 'items[0].title');
|
|
179
|
+
* // 'Item 1'
|
|
180
|
+
*
|
|
181
|
+
* navigator.getFormNodeValue(form, 'invalid.path');
|
|
182
|
+
* // undefined
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
getFormNodeValue(form: unknown, path: string): unknown;
|
|
186
|
+
/**
|
|
187
|
+
* Type guard для проверки, является ли объект FormNode
|
|
188
|
+
*
|
|
189
|
+
* Проверяет наличие характерных свойств FormNode:
|
|
190
|
+
* - value (Signal)
|
|
191
|
+
* - value.value (значение Signal)
|
|
192
|
+
*
|
|
193
|
+
* @param obj Объект для проверки
|
|
194
|
+
* @returns true, если объект является FormNode
|
|
195
|
+
* @private
|
|
196
|
+
*/
|
|
197
|
+
private isFormNode;
|
|
198
|
+
/**
|
|
199
|
+
* Получает узел формы по пути
|
|
200
|
+
*
|
|
201
|
+
* Навигирует по структуре FormNode (GroupNode/FieldNode/ArrayNode)
|
|
202
|
+
* и возвращает узел по указанному пути.
|
|
203
|
+
*
|
|
204
|
+
* Поддерживает:
|
|
205
|
+
* - Доступ к полям GroupNode через fields Map
|
|
206
|
+
* - Доступ к элементам ArrayNode через индекс
|
|
207
|
+
* - Proxy-доступ к полям (для обратной совместимости)
|
|
208
|
+
*
|
|
209
|
+
* @param form Корневой узел формы (обычно GroupNode)
|
|
210
|
+
* @param path Путь к узлу
|
|
211
|
+
* @returns Узел формы или null, если путь не найден
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```typescript
|
|
215
|
+
* const form = new GroupNode({
|
|
216
|
+
* email: { value: '', component: Input },
|
|
217
|
+
* address: {
|
|
218
|
+
* city: { value: '', component: Input }
|
|
219
|
+
* },
|
|
220
|
+
* items: [{ title: { value: '', component: Input } }]
|
|
221
|
+
* });
|
|
222
|
+
*
|
|
223
|
+
* const emailNode = navigator.getNodeByPath(form, 'email');
|
|
224
|
+
* // FieldNode
|
|
225
|
+
*
|
|
226
|
+
* const cityNode = navigator.getNodeByPath(form, 'address.city');
|
|
227
|
+
* // FieldNode
|
|
228
|
+
*
|
|
229
|
+
* const itemNode = navigator.getNodeByPath(form, 'items[0]');
|
|
230
|
+
* // GroupNode
|
|
231
|
+
*
|
|
232
|
+
* const titleNode = navigator.getNodeByPath(form, 'items[0].title');
|
|
233
|
+
* // FieldNode
|
|
234
|
+
*
|
|
235
|
+
* const invalidNode = navigator.getNodeByPath(form, 'invalid.path');
|
|
236
|
+
* // null
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
getNodeByPath(form: unknown, path: string): unknown | null;
|
|
240
|
+
}
|