@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,78 @@
1
+ /**
2
+ * Типы для схемы формы (Deep Schema)
3
+ *
4
+ * Автоматическое определение типов схемы на основе структуры данных:
5
+ * - `[{...}]` → массив форм
6
+ * - `{...}` → вложенная группа
7
+ * - `{value, component}` → конфигурация поля
8
+ *
9
+ * @group Types
10
+ */
11
+ import type { ComponentType } from 'react';
12
+ import type { ValidatorFn, AsyncValidatorFn, FormFields, AnyFunction } from './index';
13
+ /**
14
+ * Конфигурация поля
15
+ * @group Types
16
+ * @category Configuration Types
17
+ */
18
+ export interface FieldConfig<T> {
19
+ value: T | null;
20
+ component: ComponentType<any>;
21
+ componentProps?: any;
22
+ validators?: ValidatorFn<T>[];
23
+ asyncValidators?: AsyncValidatorFn<T>[];
24
+ disabled?: boolean;
25
+ updateOn?: 'change' | 'blur' | 'submit';
26
+ /** Задержка (в мс) перед запуском асинхронной валидации */
27
+ debounce?: number;
28
+ }
29
+ /**
30
+ * Конфигурация массива
31
+ * @group Types
32
+ * @category Configuration Types
33
+ */
34
+ export interface ArrayConfig<T extends FormFields> {
35
+ itemSchema: FormSchema<T>;
36
+ initial?: Partial<T>[];
37
+ }
38
+ /**
39
+ * Автоматически определяет тип схемы на основе TypeScript типа:
40
+ * - `T[] -> [FormSchema<T>]` (массив с одним элементом)
41
+ * - `object -> FormSchema<T>` (группа)
42
+ * - `primitive -> FieldConfig<T>` (поле)
43
+ *
44
+ * Использует NonNullable для корректной обработки опциональных полей
45
+ *
46
+ * @group Types
47
+ * @category Configuration Types
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * interface Form {
52
+ * name: string; // → FieldConfig<string>
53
+ * address: { // → FormSchema<Address>
54
+ * city: string;
55
+ * street: string;
56
+ * };
57
+ * items?: Array<{ // → [FormSchema<Item>] (опциональный)
58
+ * title: string;
59
+ * price: number;
60
+ * }>;
61
+ * }
62
+ *
63
+ * const schema: FormSchema<Form> = {
64
+ * name: { value: '', component: Input },
65
+ * address: {
66
+ * city: { value: '', component: Input },
67
+ * street: { value: '', component: Input },
68
+ * },
69
+ * items: [{
70
+ * title: { value: '', component: Input },
71
+ * price: { value: 0, component: Input },
72
+ * }],
73
+ * };
74
+ * ```
75
+ */
76
+ export type FormSchema<T> = {
77
+ [K in keyof T]: NonNullable<T[K]> extends string | number | boolean ? FieldConfig<T[K]> : NonNullable<T[K]> extends Array<infer U> ? U extends string | number | boolean ? FieldConfig<T[K]> : U extends Date | File | Blob | AnyFunction ? FieldConfig<T[K]> : [FormSchema<U>] : NonNullable<T[K]> extends Date | File | Blob | AnyFunction ? FieldConfig<T[K]> : FormSchema<NonNullable<T[K]>>;
78
+ };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Типы для схемы формы (Deep Schema)
3
+ *
4
+ * Автоматическое определение типов схемы на основе структуры данных:
5
+ * - `[{...}]` → массив форм
6
+ * - `{...}` → вложенная группа
7
+ * - `{value, component}` → конфигурация поля
8
+ *
9
+ * @group Types
10
+ */
11
+ export {};
@@ -0,0 +1,42 @@
1
+ import type { AnyFunction } from './index';
2
+ /**
3
+ * FieldPath предоставляет типобезопасный доступ к путям полей формы
4
+ *
5
+ * Рекурсивно обрабатывает вложенные объекты для поддержки вложенных форм.
6
+ *
7
+ * Использование:
8
+ * ```typescript
9
+ * const validation = (path: FieldPath<MyForm>) => {
10
+ * required(path.email, { message: 'Email обязателен' });
11
+ *
12
+ * // Вложенные объекты
13
+ * required(path.registrationAddress.city);
14
+ * minLength(path.registrationAddress.street, 3);
15
+ *
16
+ * applyWhen(
17
+ * path.loanType,
18
+ * (type) => type === 'mortgage',
19
+ * (path) => {
20
+ * required(path.propertyValue, { message: 'Укажите стоимость' });
21
+ * }
22
+ * );
23
+ * };
24
+ * ```
25
+ */
26
+ export type FieldPath<T> = {
27
+ [K in keyof T]: NonNullable<T[K]> extends Array<unknown> ? FieldPathNode<T, T[K], K> : NonNullable<T[K]> extends Date | File | Blob | AnyFunction ? FieldPathNode<T, T[K], K> : NonNullable<T[K]> extends object ? FieldPathNode<T, T[K], K> & FieldPath<NonNullable<T[K]>> : FieldPathNode<T, T[K], K>;
28
+ };
29
+ /**
30
+ * Узел в пути поля
31
+ * Содержит метаинформацию о поле для валидации
32
+ */
33
+ export interface FieldPathNode<TForm, TField, TKey = unknown> {
34
+ /** Ключ поля */
35
+ readonly __key: TKey;
36
+ /** Путь к полю (для вложенных объектов) */
37
+ readonly __path: string;
38
+ /** Тип формы */
39
+ readonly __formType?: TForm;
40
+ /** Тип поля */
41
+ readonly __fieldType?: TField;
42
+ }
@@ -0,0 +1,4 @@
1
+ // ============================================================================
2
+ // FieldPath - proxy для доступа к путям полей
3
+ // ============================================================================
4
+ export {};
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Единый контекст для работы с формой
3
+ *
4
+ * Используется в:
5
+ * - Behavior схемах (watchField, copyFrom, transformValue, etc.)
6
+ * - Validation схемах (validate, validateAsync, validateTree)
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * // Behavior
11
+ * watchField(path.country, (country, ctx) => {
12
+ * ctx.form.city.updateComponentProps({ options: cities });
13
+ * ctx.setFieldValue('city', null);
14
+ * });
15
+ *
16
+ * // Validation
17
+ * validate(path.email, (value, ctx) => {
18
+ * if (!value) return { code: 'required', message: 'Required' };
19
+ * const confirm = ctx.form.confirmEmail.value.value;
20
+ * if (value !== confirm) return { code: 'mismatch', message: 'Emails must match' };
21
+ * return null;
22
+ * });
23
+ * ```
24
+ */
25
+ import type { GroupNodeWithControls } from './group-node-proxy';
26
+ /**
27
+ * Единый контекст для работы с формой
28
+ *
29
+ * Предоставляет:
30
+ * - `form` - типизированный Proxy-доступ к полям формы
31
+ * - `setFieldValue` - безопасная установка значения (emitEvent: false)
32
+ */
33
+ export interface FormContext<TForm> {
34
+ /**
35
+ * Форма с типизированным Proxy-доступом к полям
36
+ *
37
+ * Позволяет обращаться к полям напрямую через точечную нотацию:
38
+ * - `ctx.form.email` → FieldNode
39
+ * - `ctx.form.address.city` → FieldNode (вложенный)
40
+ * - `ctx.form.items` → ArrayNode
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * // Получить значение
45
+ * ctx.form.email.value.value
46
+ *
47
+ * // Установить значение (⚠️ может вызвать цикл в behavior!)
48
+ * ctx.form.email.setValue('new@mail.com')
49
+ *
50
+ * // Безопасно установить значение
51
+ * ctx.form.email.setValue('new@mail.com', { emitEvent: false })
52
+ *
53
+ * // Обновить пропсы компонента
54
+ * ctx.form.city.updateComponentProps({ options: cities })
55
+ *
56
+ * // Валидация поля
57
+ * await ctx.form.email.validate()
58
+ *
59
+ * // Работа с массивами
60
+ * ctx.form.items.push({ title: 'New' })
61
+ * ctx.form.items.clear()
62
+ * ```
63
+ */
64
+ readonly form: GroupNodeWithControls<TForm>;
65
+ /**
66
+ * Безопасно установить значение поля по строковому пути
67
+ *
68
+ * Автоматически использует `emitEvent: false` для предотвращения
69
+ * бесконечных циклов в behavior схемах.
70
+ *
71
+ * @param path - Путь к полю (например, "address.city", "items[0].name")
72
+ * @param value - Новое значение
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * // Сброс города при смене страны
77
+ * watchField(path.country, (country, ctx) => {
78
+ * ctx.setFieldValue('city', null);
79
+ * });
80
+ * ```
81
+ */
82
+ setFieldValue(path: string, value: unknown): void;
83
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Единый контекст для работы с формой
3
+ *
4
+ * Используется в:
5
+ * - Behavior схемах (watchField, copyFrom, transformValue, etc.)
6
+ * - Validation схемах (validate, validateAsync, validateTree)
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * // Behavior
11
+ * watchField(path.country, (country, ctx) => {
12
+ * ctx.form.city.updateComponentProps({ options: cities });
13
+ * ctx.setFieldValue('city', null);
14
+ * });
15
+ *
16
+ * // Validation
17
+ * validate(path.email, (value, ctx) => {
18
+ * if (!value) return { code: 'required', message: 'Required' };
19
+ * const confirm = ctx.form.confirmEmail.value.value;
20
+ * if (value !== confirm) return { code: 'mismatch', message: 'Emails must match' };
21
+ * return null;
22
+ * });
23
+ * ```
24
+ */
25
+ export {};
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Типы для Proxy-доступа к полям GroupNode
3
+ *
4
+ * Решает проблему типизации, когда GroupNode<T> использует Proxy для прямого доступа к полям.
5
+ * TypeScript не может автоматически определить правильные типы для вложенных форм и массивов.
6
+ *
7
+ * @group Types
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * interface MyForm {
12
+ * name: string;
13
+ * address: {
14
+ * city: string;
15
+ * };
16
+ * items: Array<{ title: string }>;
17
+ * }
18
+ *
19
+ * const form: GroupNodeWithControls<MyForm> = new GroupNode(schema);
20
+ *
21
+ * // TypeScript знает, что это FieldNode<string>
22
+ * form.name.setValue('John');
23
+ *
24
+ * // TypeScript знает, что это GroupNode<{city: string}>
25
+ * form.address.city.setValue('Moscow');
26
+ *
27
+ * // TypeScript знает, что это ArrayNode<{title: string}>
28
+ * form.items.push({ title: 'New Item' });
29
+ * ```
30
+ */
31
+ import type { FormFields } from './index';
32
+ type FieldNode<_T> = any;
33
+ type GroupNode<_T> = any;
34
+ type ArrayNode<_T> = any;
35
+ /**
36
+ * Мапит тип модели данных T на правильные типы узлов формы
37
+ *
38
+ * Рекурсивно определяет типы узлов на основе структуры данных:
39
+ * - `T[K] extends Array<infer U>` где U - объект → `ArrayNodeWithControls<U>`
40
+ * - `T[K] extends Array<infer U>` где U - примитив → `FieldNode<T[K]>` (массив как обычное поле)
41
+ * - `T[K] extends object` → `GroupNodeWithControls<T[K]>` (вложенная форма с типизацией)
42
+ * - `T[K]` примитив → `FieldNode<T[K]>` (простое поле)
43
+ *
44
+ * Использует NonNullable для правильной обработки опциональных полей
45
+ *
46
+ * @group Types
47
+ * @category Proxy Types
48
+ *
49
+ * @template T - Тип модели данных формы
50
+ */
51
+ export type FormNodeControls<T> = {
52
+ [K in keyof T]: NonNullable<T[K]> extends Array<infer U> ? U extends FormFields ? ArrayNodeWithControls<U> : FieldNode<T[K]> : NonNullable<T[K]> extends FormFields ? NonNullable<T[K]> extends Date | File | Blob ? FieldNode<T[K]> : GroupNodeWithControls<NonNullable<T[K]>> : FieldNode<T[K]>;
53
+ };
54
+ /**
55
+ * Комбинированный тип для GroupNode с Proxy доступом к полям
56
+ *
57
+ * Объединяет методы и свойства GroupNode с типизированными полями формы.
58
+ * Это позволяет использовать как API GroupNode, так и прямой доступ к полям.
59
+ *
60
+ * @group Types
61
+ * @category Proxy Types
62
+ *
63
+ * @template T - Тип модели данных формы
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * interface UserForm {
68
+ * email: string;
69
+ * profile: {
70
+ * name: string;
71
+ * age: number;
72
+ * };
73
+ * }
74
+ *
75
+ * const form: GroupNodeWithControls<UserForm> = new GroupNode(schema);
76
+ *
77
+ * // Доступ к методам GroupNode
78
+ * await form.validate();
79
+ * const values = form.getValue();
80
+ * console.log(form.valid.value);
81
+ *
82
+ * // Прямой доступ к полям (через Proxy)
83
+ * form.email.setValue('test@mail.com');
84
+ * form.profile.name.setValue('John');
85
+ * ```
86
+ */
87
+ export type GroupNodeWithControls<T> = GroupNode<T> & FormNodeControls<T>;
88
+ /**
89
+ * Комбинированный тип для ArrayNode с Proxy доступом к элементам
90
+ *
91
+ * Объединяет методы и свойства ArrayNode с типизированным доступом к элементам массива.
92
+ *
93
+ * @group Types
94
+ * @category Proxy Types
95
+ *
96
+ * @template T - Тип модели данных элемента массива
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * interface TodoItem {
101
+ * title: string;
102
+ * completed: boolean;
103
+ * }
104
+ *
105
+ * const todos: ArrayNodeWithControls<TodoItem> = new ArrayNode(schema);
106
+ *
107
+ * // Доступ к методам ArrayNode
108
+ * todos.push({ title: 'New todo', completed: false });
109
+ * todos.removeAt(0);
110
+ *
111
+ * // Доступ к элементам (через Proxy)
112
+ * todos.at(0)?.title.setValue('Updated title');
113
+ *
114
+ * // Итерация
115
+ * todos.forEach((item, i) => {
116
+ * console.log(item.title.value.value);
117
+ * });
118
+ * ```
119
+ */
120
+ export type ArrayNodeWithControls<T extends FormFields> = ArrayNode<T> & {
121
+ /**
122
+ * Безопасный доступ к элементу массива по индексу
123
+ * Возвращает GroupNode с типизированными полями или undefined
124
+ */
125
+ at(index: number): GroupNodeWithControls<T> | undefined;
126
+ /**
127
+ * Итерация по элементам массива с типизированными элементами
128
+ */
129
+ forEach(callback: (item: GroupNodeWithControls<T>, index: number) => void): void;
130
+ /**
131
+ * Маппинг элементов массива с типизированными элементами
132
+ */
133
+ map<R>(callback: (item: GroupNodeWithControls<T>, index: number) => R): R[];
134
+ };
135
+ export {};
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Типы для Proxy-доступа к полям GroupNode
3
+ *
4
+ * Решает проблему типизации, когда GroupNode<T> использует Proxy для прямого доступа к полям.
5
+ * TypeScript не может автоматически определить правильные типы для вложенных форм и массивов.
6
+ *
7
+ * @group Types
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * interface MyForm {
12
+ * name: string;
13
+ * address: {
14
+ * city: string;
15
+ * };
16
+ * items: Array<{ title: string }>;
17
+ * }
18
+ *
19
+ * const form: GroupNodeWithControls<MyForm> = new GroupNode(schema);
20
+ *
21
+ * // TypeScript знает, что это FieldNode<string>
22
+ * form.name.setValue('John');
23
+ *
24
+ * // TypeScript знает, что это GroupNode<{city: string}>
25
+ * form.address.city.setValue('Moscow');
26
+ *
27
+ * // TypeScript знает, что это ArrayNode<{title: string}>
28
+ * form.items.push({ title: 'New Item' });
29
+ * ```
30
+ */
31
+ export {};
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Represents any valid form value type
3
+ * Use this instead of 'any' for form values to maintain type safety
4
+ *
5
+ * @group Types
6
+ * @category Core Types
7
+ */
8
+ export type FormValue = string | number | boolean | null | undefined | Date | File | FormValue[] | {
9
+ [key: string]: FormValue;
10
+ };
11
+ /**
12
+ * Type-safe alternative to 'any' for unknown form values
13
+ * Requires explicit type checking before use
14
+ * @internal
15
+ */
16
+ export type UnknownFormValue = unknown;
17
+ /**
18
+ * Синхронная функция валидации
19
+ * @group Types
20
+ * @category Validation Types
21
+ */
22
+ export type ValidatorFn<T = FormValue> = (value: T) => ValidationError | null;
23
+ /**
24
+ * Асинхронная функция валидации
25
+ * @group Types
26
+ * @category Validation Types
27
+ */
28
+ export type AsyncValidatorFn<T = FormValue> = (value: T) => Promise<ValidationError | null>;
29
+ /**
30
+ * Ошибка валидации
31
+ * @group Types
32
+ * @category Validation Types
33
+ */
34
+ export interface ValidationError {
35
+ code: string;
36
+ message: string;
37
+ params?: FormFields;
38
+ /** Severity level: 'error' (default) blocks submission, 'warning' shows message but allows submission */
39
+ severity?: 'error' | 'warning';
40
+ }
41
+ /**
42
+ * Опции для фильтрации ошибок в методе getErrors()
43
+ * @group Types
44
+ * @category Validation Types
45
+ */
46
+ export interface ErrorFilterOptions {
47
+ /** Фильтр по коду ошибки */
48
+ code?: string | string[];
49
+ /** Фильтр по сообщению (поддерживает частичное совпадение) */
50
+ message?: string;
51
+ /** Фильтр по параметрам ошибки */
52
+ params?: FormFields;
53
+ /** Кастомный предикат для фильтрации */
54
+ predicate?: (error: ValidationError) => boolean;
55
+ }
56
+ /**
57
+ * Статус поля формы
58
+ * @group Types
59
+ * @category Core Types
60
+ */
61
+ export type FieldStatus = 'valid' | 'invalid' | 'pending' | 'disabled';
62
+ export type { FieldConfig } from './deep-schema';
63
+ export type { FieldPath, FieldPathNode } from '../types/field-path';
64
+ export type { ContextualValidatorFn, ContextualAsyncValidatorFn, TreeValidatorFn, ConditionFn, ValidateOptions, ValidateAsyncOptions, ValidateTreeOptions, ValidationSchemaFn, ValidatorRegistration, } from './validation-schema';
65
+ export type { FormSchema, ArrayConfig } from './deep-schema';
66
+ export type { FormContext } from './form-context';
67
+ export type { FormNodeControls, GroupNodeWithControls, ArrayNodeWithControls, } from './group-node-proxy';
68
+ import type { BehaviorSchemaFn } from '../behavior/types';
69
+ import type { FormSchema } from './deep-schema';
70
+ import type { ValidationSchemaFn } from './validation-schema';
71
+ /**
72
+ * Конфигурация GroupNode с поддержкой схем
73
+ * Используется для создания форм с автоматическим применением behavior и validation схем
74
+ *
75
+ * @group Types
76
+ * @category Configuration Types
77
+ */
78
+ export interface GroupNodeConfig<T> {
79
+ /** Схема структуры формы (поля и их конфигурация) */
80
+ form: FormSchema<T>;
81
+ /** Схема реактивного поведения (copyFrom, enableWhen, computeFrom и т.д.) */
82
+ behavior?: BehaviorSchemaFn<T>;
83
+ /** Схема валидации (required, email, minLength и т.д.) */
84
+ validation?: ValidationSchemaFn<T>;
85
+ }
86
+ /**
87
+ * Тип для Record с unknown значениями
88
+ * Используется вместо инлайнового `Record<string, unknown>`
89
+ * @internal
90
+ */
91
+ export type UnknownRecord = Record<string, any>;
92
+ /**
93
+ * Интерфейс для узлов с методом applyValidationSchema
94
+ * @internal
95
+ */
96
+ export interface WithValidationSchema {
97
+ applyValidationSchema(schemaFn: unknown): void;
98
+ }
99
+ /**
100
+ * Интерфейс для узлов с методом applyBehaviorSchema
101
+ * @internal
102
+ */
103
+ export interface WithBehaviorSchema {
104
+ applyBehaviorSchema(schemaFn: unknown): void;
105
+ }
106
+ /**
107
+ * Интерфейс для узлов, похожих на ArrayNode (с методом at)
108
+ * Используется для duck typing при обходе путей
109
+ * @internal
110
+ */
111
+ export interface ArrayNodeLike {
112
+ at(index: number): FormNode<unknown> | undefined;
113
+ length: unknown;
114
+ }
115
+ import type { FormNode } from '../nodes/form-node';
116
+ /**
117
+ * Конфиг с полем schema (для ArrayConfig)
118
+ * @internal
119
+ */
120
+ export interface ConfigWithSchema {
121
+ schema: unknown;
122
+ initialItems?: unknown[];
123
+ }
124
+ /**
125
+ * Конфиг с полем value (для извлечения значений)
126
+ * @internal
127
+ */
128
+ export interface ConfigWithValue {
129
+ value: unknown;
130
+ }
131
+ /**
132
+ * Тип для конфига с полями (FormSchema generic constraint)
133
+ * Используется вместо `Record<string, any>` для схем форм
134
+ * @deprecated
135
+ * @internal
136
+ */
137
+ export type FormFields = Record<string, FormValue>;
138
+ /**
139
+ * Тип для путей к полям (field paths)
140
+ * Используется в навигации по полям вместо any
141
+ * @internal
142
+ */
143
+ export type FieldPathSegment = {
144
+ key: string;
145
+ index?: number;
146
+ };
147
+ /**
148
+ * Тип для коллбэков и обработчиков событий
149
+ * Используется вместо (...args: any[]) => any
150
+ * @internal
151
+ */
152
+ export type UnknownCallback = (...args: unknown[]) => unknown;
153
+ /**
154
+ * Тип для проверки на функцию в conditional types
155
+ * Используется вместо Function для type narrowing
156
+ * @internal
157
+ */
158
+ export type AnyFunction = (...args: never[]) => unknown;
159
+ /**
160
+ * Тип для результатов загрузки ресурсов
161
+ * @internal
162
+ */
163
+ export type ResourceLoadResult = unknown;
@@ -0,0 +1,4 @@
1
+ // ============================================================================
2
+ // Form Value Types
3
+ // ============================================================================
4
+ export {};
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Типы для validation schema паттерна
3
+ *
4
+ * Основано на Angular Signal Forms подходе:
5
+ * - Валидация определяется отдельно от схемы полей
6
+ * - Поддержка условной валидации (applyWhen)
7
+ * - Cross-field валидация (validateTree)
8
+ * - Асинхронная валидация с контекстом
9
+ */
10
+ import type { FormFields, ValidationError } from './index';
11
+ import type { FieldPath } from './field-path';
12
+ import type { FormContext } from './form-context';
13
+ /**
14
+ * Функция валидации поля с контекстом
15
+ *
16
+ * Новый паттерн: (value, ctx: FormContext) => ValidationError | null
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * validate(path.email, (value, ctx) => {
21
+ * if (!value) return { code: 'required', message: 'Email required' };
22
+ * const confirm = ctx.form.confirmEmail.value.value;
23
+ * if (value !== confirm) return { code: 'mismatch', message: 'Must match' };
24
+ * return null;
25
+ * });
26
+ * ```
27
+ */
28
+ export type ContextualValidatorFn<TForm, TField> = (value: TField, ctx: FormContext<TForm>) => ValidationError | null;
29
+ /**
30
+ * Асинхронная функция валидации поля с контекстом
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * validateAsync(path.email, async (value, ctx) => {
35
+ * const exists = await checkEmailExists(value);
36
+ * if (exists) return { code: 'exists', message: 'Email already taken' };
37
+ * return null;
38
+ * });
39
+ * ```
40
+ */
41
+ export type ContextualAsyncValidatorFn<TForm, TField> = (value: TField, ctx: FormContext<TForm>) => Promise<ValidationError | null>;
42
+ /**
43
+ * Функция cross-field валидации
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * validateTree((ctx) => {
48
+ * const password = ctx.form.password.value.value;
49
+ * const confirm = ctx.form.confirmPassword.value.value;
50
+ * if (password !== confirm) {
51
+ * return { code: 'mismatch', message: 'Passwords must match' };
52
+ * }
53
+ * return null;
54
+ * });
55
+ * ```
56
+ */
57
+ export type TreeValidatorFn<TForm> = (ctx: FormContext<TForm>) => ValidationError | null;
58
+ /**
59
+ * Функция условия для applyWhen
60
+ */
61
+ export type ConditionFn<T> = (value: T) => boolean;
62
+ /**
63
+ * Опции для функции validate
64
+ */
65
+ export interface ValidateOptions {
66
+ /** Сообщение об ошибке */
67
+ message?: string;
68
+ /** Параметры ошибки */
69
+ params?: FormFields;
70
+ }
71
+ /**
72
+ * Опции для функции validateAsync
73
+ */
74
+ export interface ValidateAsyncOptions extends ValidateOptions {
75
+ /** Задержка перед выполнением валидации (в мс) */
76
+ debounce?: number;
77
+ }
78
+ /**
79
+ * Опции для функции validateTree
80
+ */
81
+ export interface ValidateTreeOptions {
82
+ /** Поле, к которому привязать ошибку */
83
+ targetField?: string;
84
+ }
85
+ /**
86
+ * Функция validation schema
87
+ *
88
+ * Принимает FieldPath и определяет все правила валидации для формы
89
+ */
90
+ export type ValidationSchemaFn<T> = (path: FieldPath<T>) => void;
91
+ /**
92
+ * Регистрация валидатора в системе
93
+ * @internal
94
+ */
95
+ export interface ValidatorRegistration {
96
+ fieldPath: string;
97
+ type: 'sync' | 'async' | 'tree';
98
+ validator: ContextualValidatorFn<unknown, unknown> | ContextualAsyncValidatorFn<unknown, unknown> | TreeValidatorFn<unknown>;
99
+ options?: ValidateOptions | ValidateAsyncOptions | ValidateTreeOptions;
100
+ condition?: {
101
+ fieldPath: string;
102
+ conditionFn: ConditionFn<unknown>;
103
+ };
104
+ }