@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.
Files changed (150) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +53 -0
  3. package/dist/behaviors.d.ts +2 -0
  4. package/dist/behaviors.js +230 -0
  5. package/dist/core/behavior/behavior-applicator.d.ts +71 -0
  6. package/dist/core/behavior/behavior-applicator.js +92 -0
  7. package/dist/core/behavior/behavior-context.d.ts +29 -0
  8. package/dist/core/behavior/behavior-context.js +38 -0
  9. package/dist/core/behavior/behavior-registry.d.ts +97 -0
  10. package/dist/core/behavior/behavior-registry.js +198 -0
  11. package/dist/core/behavior/behaviors/compute-from.d.ts +41 -0
  12. package/dist/core/behavior/behaviors/compute-from.js +84 -0
  13. package/dist/core/behavior/behaviors/copy-from.d.ts +31 -0
  14. package/dist/core/behavior/behaviors/copy-from.js +64 -0
  15. package/dist/core/behavior/behaviors/enable-when.d.ts +49 -0
  16. package/dist/core/behavior/behaviors/enable-when.js +81 -0
  17. package/dist/core/behavior/behaviors/index.d.ts +11 -0
  18. package/dist/core/behavior/behaviors/index.js +11 -0
  19. package/dist/core/behavior/behaviors/reset-when.d.ts +51 -0
  20. package/dist/core/behavior/behaviors/reset-when.js +63 -0
  21. package/dist/core/behavior/behaviors/revalidate-when.d.ts +30 -0
  22. package/dist/core/behavior/behaviors/revalidate-when.js +51 -0
  23. package/dist/core/behavior/behaviors/sync-fields.d.ts +28 -0
  24. package/dist/core/behavior/behaviors/sync-fields.js +66 -0
  25. package/dist/core/behavior/behaviors/transform-value.d.ts +120 -0
  26. package/dist/core/behavior/behaviors/transform-value.js +110 -0
  27. package/dist/core/behavior/behaviors/watch-field.d.ts +35 -0
  28. package/dist/core/behavior/behaviors/watch-field.js +56 -0
  29. package/dist/core/behavior/compose-behavior.d.ts +106 -0
  30. package/dist/core/behavior/compose-behavior.js +166 -0
  31. package/dist/core/behavior/create-field-path.d.ts +20 -0
  32. package/dist/core/behavior/create-field-path.js +69 -0
  33. package/dist/core/behavior/index.d.ts +12 -0
  34. package/dist/core/behavior/index.js +17 -0
  35. package/dist/core/behavior/types.d.ts +152 -0
  36. package/dist/core/behavior/types.js +7 -0
  37. package/dist/core/context/form-context-impl.d.ts +29 -0
  38. package/dist/core/context/form-context-impl.js +37 -0
  39. package/dist/core/factories/index.d.ts +6 -0
  40. package/dist/core/factories/index.js +6 -0
  41. package/dist/core/factories/node-factory.d.ts +209 -0
  42. package/dist/core/factories/node-factory.js +281 -0
  43. package/dist/core/nodes/array-node.d.ts +308 -0
  44. package/dist/core/nodes/array-node.js +534 -0
  45. package/dist/core/nodes/field-node.d.ts +269 -0
  46. package/dist/core/nodes/field-node.js +510 -0
  47. package/dist/core/nodes/form-node.d.ts +342 -0
  48. package/dist/core/nodes/form-node.js +343 -0
  49. package/dist/core/nodes/group-node/field-registry.d.ts +191 -0
  50. package/dist/core/nodes/group-node/field-registry.js +215 -0
  51. package/dist/core/nodes/group-node/index.d.ts +11 -0
  52. package/dist/core/nodes/group-node/index.js +11 -0
  53. package/dist/core/nodes/group-node/proxy-builder.d.ts +71 -0
  54. package/dist/core/nodes/group-node/proxy-builder.js +161 -0
  55. package/dist/core/nodes/group-node/state-manager.d.ts +184 -0
  56. package/dist/core/nodes/group-node/state-manager.js +265 -0
  57. package/dist/core/nodes/group-node.d.ts +494 -0
  58. package/dist/core/nodes/group-node.js +770 -0
  59. package/dist/core/types/deep-schema.d.ts +78 -0
  60. package/dist/core/types/deep-schema.js +11 -0
  61. package/dist/core/types/field-path.d.ts +42 -0
  62. package/dist/core/types/field-path.js +4 -0
  63. package/dist/core/types/form-context.d.ts +83 -0
  64. package/dist/core/types/form-context.js +25 -0
  65. package/dist/core/types/group-node-proxy.d.ts +135 -0
  66. package/dist/core/types/group-node-proxy.js +31 -0
  67. package/dist/core/types/index.d.ts +163 -0
  68. package/dist/core/types/index.js +4 -0
  69. package/dist/core/types/validation-schema.d.ts +104 -0
  70. package/dist/core/types/validation-schema.js +10 -0
  71. package/dist/core/utils/create-form.d.ts +61 -0
  72. package/dist/core/utils/create-form.js +24 -0
  73. package/dist/core/utils/debounce.d.ts +160 -0
  74. package/dist/core/utils/debounce.js +197 -0
  75. package/dist/core/utils/error-handler.d.ts +180 -0
  76. package/dist/core/utils/error-handler.js +226 -0
  77. package/dist/core/utils/field-path-navigator.d.ts +240 -0
  78. package/dist/core/utils/field-path-navigator.js +374 -0
  79. package/dist/core/utils/index.d.ts +14 -0
  80. package/dist/core/utils/index.js +14 -0
  81. package/dist/core/utils/registry-helpers.d.ts +50 -0
  82. package/dist/core/utils/registry-helpers.js +79 -0
  83. package/dist/core/utils/registry-stack.d.ts +69 -0
  84. package/dist/core/utils/registry-stack.js +86 -0
  85. package/dist/core/utils/resources.d.ts +41 -0
  86. package/dist/core/utils/resources.js +69 -0
  87. package/dist/core/utils/subscription-manager.d.ts +180 -0
  88. package/dist/core/utils/subscription-manager.js +214 -0
  89. package/dist/core/utils/type-guards.d.ts +116 -0
  90. package/dist/core/utils/type-guards.js +169 -0
  91. package/dist/core/validation/core/apply-when.d.ts +28 -0
  92. package/dist/core/validation/core/apply-when.js +41 -0
  93. package/dist/core/validation/core/apply.d.ts +63 -0
  94. package/dist/core/validation/core/apply.js +38 -0
  95. package/dist/core/validation/core/index.d.ts +8 -0
  96. package/dist/core/validation/core/index.js +8 -0
  97. package/dist/core/validation/core/validate-async.d.ts +42 -0
  98. package/dist/core/validation/core/validate-async.js +45 -0
  99. package/dist/core/validation/core/validate-tree.d.ts +35 -0
  100. package/dist/core/validation/core/validate-tree.js +37 -0
  101. package/dist/core/validation/core/validate.d.ts +32 -0
  102. package/dist/core/validation/core/validate.js +38 -0
  103. package/dist/core/validation/field-path.d.ts +43 -0
  104. package/dist/core/validation/field-path.js +147 -0
  105. package/dist/core/validation/index.d.ts +21 -0
  106. package/dist/core/validation/index.js +33 -0
  107. package/dist/core/validation/validate-form.d.ts +85 -0
  108. package/dist/core/validation/validate-form.js +152 -0
  109. package/dist/core/validation/validation-applicator.d.ts +89 -0
  110. package/dist/core/validation/validation-applicator.js +217 -0
  111. package/dist/core/validation/validation-context.d.ts +47 -0
  112. package/dist/core/validation/validation-context.js +75 -0
  113. package/dist/core/validation/validation-registry.d.ts +156 -0
  114. package/dist/core/validation/validation-registry.js +298 -0
  115. package/dist/core/validation/validators/array-validators.d.ts +63 -0
  116. package/dist/core/validation/validators/array-validators.js +86 -0
  117. package/dist/core/validation/validators/date.d.ts +38 -0
  118. package/dist/core/validation/validators/date.js +117 -0
  119. package/dist/core/validation/validators/email.d.ts +44 -0
  120. package/dist/core/validation/validators/email.js +60 -0
  121. package/dist/core/validation/validators/index.d.ts +14 -0
  122. package/dist/core/validation/validators/index.js +14 -0
  123. package/dist/core/validation/validators/max-length.d.ts +45 -0
  124. package/dist/core/validation/validators/max-length.js +60 -0
  125. package/dist/core/validation/validators/max.d.ts +45 -0
  126. package/dist/core/validation/validators/max.js +60 -0
  127. package/dist/core/validation/validators/min-length.d.ts +45 -0
  128. package/dist/core/validation/validators/min-length.js +60 -0
  129. package/dist/core/validation/validators/min.d.ts +45 -0
  130. package/dist/core/validation/validators/min.js +60 -0
  131. package/dist/core/validation/validators/number.d.ts +38 -0
  132. package/dist/core/validation/validators/number.js +90 -0
  133. package/dist/core/validation/validators/pattern.d.ts +47 -0
  134. package/dist/core/validation/validators/pattern.js +62 -0
  135. package/dist/core/validation/validators/phone.d.ts +34 -0
  136. package/dist/core/validation/validators/phone.js +58 -0
  137. package/dist/core/validation/validators/required.d.ts +48 -0
  138. package/dist/core/validation/validators/required.js +69 -0
  139. package/dist/core/validation/validators/url.d.ts +29 -0
  140. package/dist/core/validation/validators/url.js +55 -0
  141. package/dist/create-field-path-CdPF3lIK.js +704 -0
  142. package/dist/hooks/useFormControl.d.ts +48 -0
  143. package/dist/hooks/useFormControl.js +298 -0
  144. package/dist/index.d.ts +10 -0
  145. package/dist/index.js +8 -0
  146. package/dist/node-factory-D7DOnSSN.js +3200 -0
  147. package/dist/validators.d.ts +2 -0
  148. package/dist/validators.js +298 -0
  149. package/llms.txt +847 -0
  150. package/package.json +86 -0
@@ -0,0 +1,209 @@
1
+ /**
2
+ * NodeFactory - фабрика для создания узлов формы
3
+ *
4
+ * Инкапсулирует логику определения типа конфига и создания соответствующего узла.
5
+ * Используется в GroupNode и ArrayNode для создания дочерних узлов.
6
+ *
7
+ * Паттерн Factory Method упрощает создание узлов и делает код более читаемым:
8
+ * - Вместо if-else в GroupNode/ArrayNode
9
+ * - Единая точка для создания узлов
10
+ * - Легко добавлять новые типы узлов
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const factory = new NodeFactory();
15
+ *
16
+ * // Создание FieldNode
17
+ * const field = factory.createNode({ value: '', component: Input });
18
+ *
19
+ * // Создание GroupNode
20
+ * const group = factory.createNode({
21
+ * email: { value: '', component: Input },
22
+ * password: { value: '', component: Input }
23
+ * });
24
+ *
25
+ * // Создание ArrayNode
26
+ * const array = factory.createNode({
27
+ * schema: { title: { value: '', component: Input } },
28
+ * initialItems: []
29
+ * });
30
+ * ```
31
+ */
32
+ import type { FormNode } from '../nodes/form-node';
33
+ /**
34
+ * Фабрика для создания узлов формы
35
+ *
36
+ * Определяет тип конфига и создает соответствующий узел (FieldNode, GroupNode, ArrayNode)
37
+ */
38
+ export declare class NodeFactory {
39
+ /**
40
+ * Создает узел формы на основе конфигурации
41
+ *
42
+ * ✅ ОБНОВЛЕНО: Теперь поддерживает массивы напрямую
43
+ *
44
+ * Автоматически определяет тип узла:
45
+ * - FieldNode: имеет value и component
46
+ * - ArrayNode: массив [schema, ...items] или { schema, initialItems }
47
+ * - GroupNode: объект без value, component, schema
48
+ *
49
+ * @param config Конфигурация узла
50
+ * @returns Экземпляр FieldNode, GroupNode или ArrayNode
51
+ * @throws Error если конфиг не соответствует ни одному типу
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * const factory = new NodeFactory();
56
+ *
57
+ * // FieldNode
58
+ * const field = factory.createNode({
59
+ * value: 'test@mail.com',
60
+ * component: Input,
61
+ * validators: [required, email]
62
+ * });
63
+ *
64
+ * // GroupNode
65
+ * const group = factory.createNode({
66
+ * email: { value: '', component: Input },
67
+ * password: { value: '', component: Input }
68
+ * });
69
+ *
70
+ * // ArrayNode (объект)
71
+ * const array = factory.createNode({
72
+ * schema: { title: { value: '', component: Input } },
73
+ * initialItems: [{ title: 'Item 1' }]
74
+ * });
75
+ *
76
+ * // ArrayNode (массив) - новый формат
77
+ * const array2 = factory.createNode([
78
+ * { title: { value: '', component: Input } }, // schema
79
+ * { title: 'Item 1' }, // initial item 1
80
+ * { title: 'Item 2' } // initial item 2
81
+ * ]);
82
+ * ```
83
+ */
84
+ createNode<T>(config: unknown): FormNode<T>;
85
+ /**
86
+ * Создать ArrayNode из массива [schema, ...initialItems]
87
+ *
88
+ * ✅ НОВОЕ: Извлечено из GroupNode для централизации логики
89
+ *
90
+ * Формат: [itemSchema, ...initialItems]
91
+ * - Первый элемент - схема элемента массива
92
+ * - Остальные элементы - начальные значения
93
+ *
94
+ * @param config Массив с схемой и начальными элементами
95
+ * @returns ArrayNode
96
+ *
97
+ * @example
98
+ * ```typescript
99
+ * const factory = new NodeFactory();
100
+ *
101
+ * // Массив с начальными элементами
102
+ * const array = factory.createArrayNodeFromArray([
103
+ * { title: { value: '', component: Input } }, // schema
104
+ * { title: 'Item 1' }, // initial value
105
+ * { title: 'Item 2' } // initial value
106
+ * ]);
107
+ * ```
108
+ * @private
109
+ */
110
+ private createArrayNodeFromArray;
111
+ /**
112
+ * Извлечь значения из схемы (рекурсивно)
113
+ *
114
+ * ✅ НОВОЕ: Извлечено из GroupNode для централизации логики
115
+ *
116
+ * Преобразует схему формы в объект со значениями:
117
+ * - `{ name: { value: 'John', component: Input } } → { name: 'John' }`
118
+ * - Поддерживает вложенные группы
119
+ * - Поддерживает массивы
120
+ *
121
+ * @param schema Схема формы
122
+ * @returns Объект со значениями полей
123
+ *
124
+ * @example
125
+ * ```typescript
126
+ * const factory = new NodeFactory();
127
+ *
128
+ * const schema = {
129
+ * name: { value: 'John', component: Input },
130
+ * age: { value: 30, component: Input },
131
+ * address: {
132
+ * city: { value: 'Moscow', component: Input }
133
+ * }
134
+ * };
135
+ *
136
+ * factory.extractValues(schema);
137
+ * // { name: 'John', age: 30, address: { city: 'Moscow' } }
138
+ * ```
139
+ */
140
+ extractValues(schema: unknown): unknown;
141
+ /**
142
+ * Проверяет, является ли конфиг конфигурацией поля (FieldConfig)
143
+ *
144
+ * FieldConfig имеет обязательные свойства:
145
+ * - value: начальное значение поля
146
+ * - component: React-компонент для отображения
147
+ *
148
+ * @param config Проверяемая конфигурация
149
+ * @returns true если config является FieldConfig
150
+ *
151
+ * @example
152
+ * ```typescript
153
+ * const factory = new NodeFactory();
154
+ *
155
+ * factory.isFieldConfig({ value: '', component: Input }); // true
156
+ * factory.isFieldConfig({ email: { value: '' } }); // false
157
+ * factory.isFieldConfig(null); // false
158
+ * ```
159
+ */
160
+ isFieldConfig(config: unknown): boolean;
161
+ /**
162
+ * Проверяет, является ли конфиг конфигурацией массива (ArrayConfig)
163
+ *
164
+ * ArrayConfig имеет обязательное свойство:
165
+ * - schema: схема для элементов массива
166
+ *
167
+ * И НЕ имеет:
168
+ * - value (отличие от FieldConfig)
169
+ *
170
+ * @param config Проверяемая конфигурация
171
+ * @returns true если config является ArrayConfig
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * const factory = new NodeFactory();
176
+ *
177
+ * factory.isArrayConfig({ schema: {}, initialItems: [] }); // true
178
+ * factory.isArrayConfig({ value: '', component: Input }); // false
179
+ * factory.isArrayConfig({ email: { value: '' } }); // false
180
+ * ```
181
+ */
182
+ isArrayConfig(config: unknown): boolean;
183
+ /**
184
+ * Проверяет, является ли конфиг конфигурацией группы (GroupConfig)
185
+ *
186
+ * GroupConfig - это объект, который:
187
+ * - НЕ является FieldConfig (нет value/component)
188
+ * - НЕ является ArrayConfig (нет schema)
189
+ * - Содержит вложенные конфиги полей/групп/массивов
190
+ *
191
+ * @param config Проверяемая конфигурация
192
+ * @returns true если config является GroupConfig
193
+ *
194
+ * @example
195
+ * ```typescript
196
+ * const factory = new NodeFactory();
197
+ *
198
+ * factory.isGroupConfig({
199
+ * email: { value: '', component: Input },
200
+ * password: { value: '', component: Input }
201
+ * }); // true
202
+ *
203
+ * factory.isGroupConfig({ value: '', component: Input }); // false
204
+ * factory.isGroupConfig({ schema: {} }); // false
205
+ * factory.isGroupConfig(null); // false
206
+ * ```
207
+ */
208
+ isGroupConfig(config: unknown): boolean;
209
+ }
@@ -0,0 +1,281 @@
1
+ /**
2
+ * NodeFactory - фабрика для создания узлов формы
3
+ *
4
+ * Инкапсулирует логику определения типа конфига и создания соответствующего узла.
5
+ * Используется в GroupNode и ArrayNode для создания дочерних узлов.
6
+ *
7
+ * Паттерн Factory Method упрощает создание узлов и делает код более читаемым:
8
+ * - Вместо if-else в GroupNode/ArrayNode
9
+ * - Единая точка для создания узлов
10
+ * - Легко добавлять новые типы узлов
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const factory = new NodeFactory();
15
+ *
16
+ * // Создание FieldNode
17
+ * const field = factory.createNode({ value: '', component: Input });
18
+ *
19
+ * // Создание GroupNode
20
+ * const group = factory.createNode({
21
+ * email: { value: '', component: Input },
22
+ * password: { value: '', component: Input }
23
+ * });
24
+ *
25
+ * // Создание ArrayNode
26
+ * const array = factory.createNode({
27
+ * schema: { title: { value: '', component: Input } },
28
+ * initialItems: []
29
+ * });
30
+ * ```
31
+ */
32
+ import { FieldNode } from '../nodes/field-node';
33
+ import { GroupNode } from '../nodes/group-node';
34
+ import { ArrayNode } from '../nodes/array-node';
35
+ /**
36
+ * Фабрика для создания узлов формы
37
+ *
38
+ * Определяет тип конфига и создает соответствующий узел (FieldNode, GroupNode, ArrayNode)
39
+ */
40
+ export class NodeFactory {
41
+ /**
42
+ * Создает узел формы на основе конфигурации
43
+ *
44
+ * ✅ ОБНОВЛЕНО: Теперь поддерживает массивы напрямую
45
+ *
46
+ * Автоматически определяет тип узла:
47
+ * - FieldNode: имеет value и component
48
+ * - ArrayNode: массив [schema, ...items] или { schema, initialItems }
49
+ * - GroupNode: объект без value, component, schema
50
+ *
51
+ * @param config Конфигурация узла
52
+ * @returns Экземпляр FieldNode, GroupNode или ArrayNode
53
+ * @throws Error если конфиг не соответствует ни одному типу
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * const factory = new NodeFactory();
58
+ *
59
+ * // FieldNode
60
+ * const field = factory.createNode({
61
+ * value: 'test@mail.com',
62
+ * component: Input,
63
+ * validators: [required, email]
64
+ * });
65
+ *
66
+ * // GroupNode
67
+ * const group = factory.createNode({
68
+ * email: { value: '', component: Input },
69
+ * password: { value: '', component: Input }
70
+ * });
71
+ *
72
+ * // ArrayNode (объект)
73
+ * const array = factory.createNode({
74
+ * schema: { title: { value: '', component: Input } },
75
+ * initialItems: [{ title: 'Item 1' }]
76
+ * });
77
+ *
78
+ * // ArrayNode (массив) - новый формат
79
+ * const array2 = factory.createNode([
80
+ * { title: { value: '', component: Input } }, // schema
81
+ * { title: 'Item 1' }, // initial item 1
82
+ * { title: 'Item 2' } // initial item 2
83
+ * ]);
84
+ * ```
85
+ */
86
+ createNode(config) {
87
+ // 0. ✅ НОВОЕ: Проверка массива (приоритет: специфический формат)
88
+ if (Array.isArray(config) && config.length >= 1) {
89
+ return this.createArrayNodeFromArray(config);
90
+ }
91
+ // 1. Проверка FieldConfig (приоритет: самый специфичный тип)
92
+ if (this.isFieldConfig(config)) {
93
+ return new FieldNode(config);
94
+ }
95
+ // 2. Проверка ArrayConfig
96
+ if (this.isArrayConfig(config)) {
97
+ const arrayConfig = config;
98
+ return new ArrayNode(arrayConfig.schema, arrayConfig.initialItems);
99
+ }
100
+ // 3. Проверка GroupConfig (самый общий тип)
101
+ if (this.isGroupConfig(config)) {
102
+ return new GroupNode(config);
103
+ }
104
+ // Неизвестный конфиг
105
+ throw new Error(`NodeFactory: Unknown node config. Expected FieldConfig, GroupConfig, or ArrayConfig, but got: ${JSON.stringify(config)}`);
106
+ }
107
+ /**
108
+ * Создать ArrayNode из массива [schema, ...initialItems]
109
+ *
110
+ * ✅ НОВОЕ: Извлечено из GroupNode для централизации логики
111
+ *
112
+ * Формат: [itemSchema, ...initialItems]
113
+ * - Первый элемент - схема элемента массива
114
+ * - Остальные элементы - начальные значения
115
+ *
116
+ * @param config Массив с схемой и начальными элементами
117
+ * @returns ArrayNode
118
+ *
119
+ * @example
120
+ * ```typescript
121
+ * const factory = new NodeFactory();
122
+ *
123
+ * // Массив с начальными элементами
124
+ * const array = factory.createArrayNodeFromArray([
125
+ * { title: { value: '', component: Input } }, // schema
126
+ * { title: 'Item 1' }, // initial value
127
+ * { title: 'Item 2' } // initial value
128
+ * ]);
129
+ * ```
130
+ * @private
131
+ */
132
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
133
+ createArrayNodeFromArray(config) {
134
+ const [itemSchema, ...restItems] = config;
135
+ // Обработка начальных элементов:
136
+ // Если элемент - схема группы, извлечь значения
137
+ const initialItems = [];
138
+ // ИСПРАВЛЕНИЕ: Первый элемент является и схемой, и первым элементом данных
139
+ // Если первый элемент имеет значения (GroupConfig с value), добавляем его как первый item
140
+ if (this.isGroupConfig(itemSchema)) {
141
+ initialItems.push(this.extractValues(itemSchema));
142
+ }
143
+ // Добавляем остальные элементы
144
+ for (const item of restItems) {
145
+ if (this.isGroupConfig(item)) {
146
+ initialItems.push(this.extractValues(item));
147
+ }
148
+ else {
149
+ initialItems.push(item);
150
+ }
151
+ }
152
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
153
+ return new ArrayNode(itemSchema, initialItems);
154
+ }
155
+ /**
156
+ * Извлечь значения из схемы (рекурсивно)
157
+ *
158
+ * ✅ НОВОЕ: Извлечено из GroupNode для централизации логики
159
+ *
160
+ * Преобразует схему формы в объект со значениями:
161
+ * - `{ name: { value: 'John', component: Input } } → { name: 'John' }`
162
+ * - Поддерживает вложенные группы
163
+ * - Поддерживает массивы
164
+ *
165
+ * @param schema Схема формы
166
+ * @returns Объект со значениями полей
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * const factory = new NodeFactory();
171
+ *
172
+ * const schema = {
173
+ * name: { value: 'John', component: Input },
174
+ * age: { value: 30, component: Input },
175
+ * address: {
176
+ * city: { value: 'Moscow', component: Input }
177
+ * }
178
+ * };
179
+ *
180
+ * factory.extractValues(schema);
181
+ * // { name: 'John', age: 30, address: { city: 'Moscow' } }
182
+ * ```
183
+ */
184
+ extractValues(schema) {
185
+ // 1. FieldConfig - вернуть value
186
+ if (this.isFieldConfig(schema)) {
187
+ return schema.value;
188
+ }
189
+ // 2. Массив - рекурсивно обработать элементы
190
+ if (Array.isArray(schema)) {
191
+ return schema.map((item) => this.extractValues(item));
192
+ }
193
+ // 3. GroupConfig - рекурсивно извлечь значения всех полей
194
+ if (this.isGroupConfig(schema)) {
195
+ const result = {};
196
+ for (const [key, config] of Object.entries(schema)) {
197
+ result[key] = this.extractValues(config);
198
+ }
199
+ return result;
200
+ }
201
+ // 4. Примитивное значение - вернуть как есть
202
+ return schema;
203
+ }
204
+ /**
205
+ * Проверяет, является ли конфиг конфигурацией поля (FieldConfig)
206
+ *
207
+ * FieldConfig имеет обязательные свойства:
208
+ * - value: начальное значение поля
209
+ * - component: React-компонент для отображения
210
+ *
211
+ * @param config Проверяемая конфигурация
212
+ * @returns true если config является FieldConfig
213
+ *
214
+ * @example
215
+ * ```typescript
216
+ * const factory = new NodeFactory();
217
+ *
218
+ * factory.isFieldConfig({ value: '', component: Input }); // true
219
+ * factory.isFieldConfig({ email: { value: '' } }); // false
220
+ * factory.isFieldConfig(null); // false
221
+ * ```
222
+ */
223
+ isFieldConfig(config) {
224
+ return (config != null && typeof config === 'object' && 'value' in config && 'component' in config);
225
+ }
226
+ /**
227
+ * Проверяет, является ли конфиг конфигурацией массива (ArrayConfig)
228
+ *
229
+ * ArrayConfig имеет обязательное свойство:
230
+ * - schema: схема для элементов массива
231
+ *
232
+ * И НЕ имеет:
233
+ * - value (отличие от FieldConfig)
234
+ *
235
+ * @param config Проверяемая конфигурация
236
+ * @returns true если config является ArrayConfig
237
+ *
238
+ * @example
239
+ * ```typescript
240
+ * const factory = new NodeFactory();
241
+ *
242
+ * factory.isArrayConfig({ schema: {}, initialItems: [] }); // true
243
+ * factory.isArrayConfig({ value: '', component: Input }); // false
244
+ * factory.isArrayConfig({ email: { value: '' } }); // false
245
+ * ```
246
+ */
247
+ isArrayConfig(config) {
248
+ return (config != null && typeof config === 'object' && 'schema' in config && !('value' in config));
249
+ }
250
+ /**
251
+ * Проверяет, является ли конфиг конфигурацией группы (GroupConfig)
252
+ *
253
+ * GroupConfig - это объект, который:
254
+ * - НЕ является FieldConfig (нет value/component)
255
+ * - НЕ является ArrayConfig (нет schema)
256
+ * - Содержит вложенные конфиги полей/групп/массивов
257
+ *
258
+ * @param config Проверяемая конфигурация
259
+ * @returns true если config является GroupConfig
260
+ *
261
+ * @example
262
+ * ```typescript
263
+ * const factory = new NodeFactory();
264
+ *
265
+ * factory.isGroupConfig({
266
+ * email: { value: '', component: Input },
267
+ * password: { value: '', component: Input }
268
+ * }); // true
269
+ *
270
+ * factory.isGroupConfig({ value: '', component: Input }); // false
271
+ * factory.isGroupConfig({ schema: {} }); // false
272
+ * factory.isGroupConfig(null); // false
273
+ * ```
274
+ */
275
+ isGroupConfig(config) {
276
+ return (config != null &&
277
+ typeof config === 'object' &&
278
+ !this.isFieldConfig(config) &&
279
+ !this.isArrayConfig(config));
280
+ }
281
+ }