@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,10 @@
1
+ /**
2
+ * Типы для validation schema паттерна
3
+ *
4
+ * Основано на Angular Signal Forms подходе:
5
+ * - Валидация определяется отдельно от схемы полей
6
+ * - Поддержка условной валидации (applyWhen)
7
+ * - Cross-field валидация (validateTree)
8
+ * - Асинхронная валидация с контекстом
9
+ */
10
+ export {};
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Фабричная функция для создания формы с правильной типизацией
3
+ *
4
+ * Решает проблему с типизацией конструктора GroupNode, который возвращает
5
+ * Proxy (GroupNodeWithControls), но TypeScript не может это вывести автоматически.
6
+ *
7
+ * @group Utilities
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * // Вместо:
12
+ * const form: GroupNodeWithControls<MyForm> = new GroupNode<MyForm>(config);
13
+ *
14
+ * // Используйте:
15
+ * const form = createForm<MyForm>(config);
16
+ * ```
17
+ */
18
+ import type { GroupNodeWithControls, GroupNodeConfig, FormSchema } from '../types';
19
+ /**
20
+ * Создать форму с полной конфигурацией (form, behavior, validation)
21
+ *
22
+ * @group Utilities
23
+ *
24
+ * @param config - Конфигурация формы с полями, поведением и валидацией
25
+ * @returns Типизированная форма с Proxy-доступом к полям
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const form = createForm<UserForm>({
30
+ * form: {
31
+ * email: { value: '', component: Input },
32
+ * password: { value: '', component: Input },
33
+ * },
34
+ * validation: (path) => {
35
+ * required(path.email);
36
+ * email(path.email);
37
+ * required(path.password);
38
+ * minLength(path.password, 8);
39
+ * },
40
+ * });
41
+ *
42
+ * // TypeScript знает о полях:
43
+ * form.email.setValue('test@mail.com');
44
+ * ```
45
+ */
46
+ export declare function createForm<T>(config: GroupNodeConfig<T>): GroupNodeWithControls<T>;
47
+ /**
48
+ * Создать форму только со схемой полей (обратная совместимость)
49
+ *
50
+ * @param schema - Схема полей формы
51
+ * @returns Типизированная форма с Proxy-доступом к полям
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * const form = createForm<UserForm>({
56
+ * email: { value: '', component: Input },
57
+ * password: { value: '', component: Input },
58
+ * });
59
+ * ```
60
+ */
61
+ export declare function createForm<T>(schema: FormSchema<T>): GroupNodeWithControls<T>;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Фабричная функция для создания формы с правильной типизацией
3
+ *
4
+ * Решает проблему с типизацией конструктора GroupNode, который возвращает
5
+ * Proxy (GroupNodeWithControls), но TypeScript не может это вывести автоматически.
6
+ *
7
+ * @group Utilities
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * // Вместо:
12
+ * const form: GroupNodeWithControls<MyForm> = new GroupNode<MyForm>(config);
13
+ *
14
+ * // Используйте:
15
+ * const form = createForm<MyForm>(config);
16
+ * ```
17
+ */
18
+ import { GroupNode } from '../nodes/group-node';
19
+ /**
20
+ * Реализация фабричной функции
21
+ */
22
+ export function createForm(schemaOrConfig) {
23
+ return new GroupNode(schemaOrConfig);
24
+ }
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Debouncer - утилита для отложенного выполнения функций
3
+ *
4
+ * Устраняет дублирование debounce логики между field-node.ts и behavior-registry.ts
5
+ *
6
+ * @internal
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const debouncer = new Debouncer(300);
11
+ *
12
+ * // Отложить выполнение на 300мс
13
+ * await debouncer.debounce(async () => {
14
+ * await validateField();
15
+ * });
16
+ *
17
+ * // Отменить отложенное выполнение
18
+ * debouncer.cancel();
19
+ *
20
+ * // Выполнить немедленно, отменив отложенное
21
+ * await debouncer.flush(async () => {
22
+ * await validateField();
23
+ * });
24
+ * ```
25
+ */
26
+ /**
27
+ * Класс для debouncing (отложенного выполнения) функций
28
+ *
29
+ * @internal
30
+ *
31
+ * Откладывает выполнение функции на заданное время. Если функция вызывается
32
+ * повторно до истечения времени, предыдущий вызов отменяется.
33
+ *
34
+ * Полезно для:
35
+ * - Отложенной валидации при вводе (debounced validation)
36
+ * - Отложенного сохранения данных
37
+ * - Отложенной обработки событий behaviors
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * // В FieldNode
42
+ * class FieldNode {
43
+ * private validationDebouncer: Debouncer;
44
+ *
45
+ * constructor(config) {
46
+ * this.validationDebouncer = new Debouncer(config.debounce || 0);
47
+ * }
48
+ *
49
+ * async validate(): Promise<boolean> {
50
+ * return this.validationDebouncer.debounce(async () => {
51
+ * // Валидация выполнится через debounce мс
52
+ * return await this.runValidation();
53
+ * });
54
+ * }
55
+ * }
56
+ * ```
57
+ */
58
+ export declare class Debouncer {
59
+ private readonly delay;
60
+ /**
61
+ * Таймер для отложенного выполнения
62
+ * @private
63
+ */
64
+ private timer?;
65
+ /**
66
+ * Создать Debouncer с заданной задержкой
67
+ *
68
+ * @param delay Задержка в миллисекундах (0 = без задержки)
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * const debouncer = new Debouncer(300); // 300мс задержка
73
+ * const immediate = new Debouncer(0); // Без задержки
74
+ * ```
75
+ */
76
+ constructor(delay: number);
77
+ /**
78
+ * Отложить выполнение функции
79
+ *
80
+ * Если вызывается повторно до истечения delay, предыдущий вызов отменяется
81
+ * и таймер перезапускается.
82
+ *
83
+ * @param fn Функция для выполнения (может быть async)
84
+ * @returns Promise, который разрешается результатом функции
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * const debouncer = new Debouncer(300);
89
+ *
90
+ * // Первый вызов - запланирован через 300мс
91
+ * debouncer.debounce(async () => console.log('First'));
92
+ *
93
+ * // Второй вызов через 100мс - отменяет первый, запланирован через 300мс
94
+ * debouncer.debounce(async () => console.log('Second'));
95
+ *
96
+ * // Через 300мс выведет только: "Second"
97
+ * ```
98
+ */
99
+ debounce<T>(fn: () => T | Promise<T>): Promise<T>;
100
+ /**
101
+ * Отменить отложенное выполнение
102
+ *
103
+ * Если есть запланированный вызов, он будет отменен и не выполнится.
104
+ * Promise из debounce() никогда не разрешится.
105
+ *
106
+ * @example
107
+ * ```typescript
108
+ * const debouncer = new Debouncer(300);
109
+ *
110
+ * debouncer.debounce(async () => {
111
+ * console.log('This will not execute');
112
+ * });
113
+ *
114
+ * debouncer.cancel(); // Отменяем вызов
115
+ * ```
116
+ */
117
+ cancel(): void;
118
+ /**
119
+ * Выполнить функцию немедленно, отменив любой отложенный вызов
120
+ *
121
+ * Полезно когда нужно принудительно выполнить действие сейчас,
122
+ * игнорируя debounce.
123
+ *
124
+ * @param fn Функция для немедленного выполнения
125
+ * @returns Promise с результатом функции
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * const debouncer = new Debouncer(300);
130
+ *
131
+ * // Запланировано через 300мс
132
+ * debouncer.debounce(async () => console.log('Delayed'));
133
+ *
134
+ * // Отменяем отложенный и выполняем немедленно
135
+ * await debouncer.flush(async () => console.log('Immediate'));
136
+ * // Выведет: "Immediate" (сразу)
137
+ * // "Delayed" не выполнится (отменен)
138
+ * ```
139
+ */
140
+ flush<T>(fn: () => T | Promise<T>): Promise<T>;
141
+ /**
142
+ * Проверить, есть ли активный (запланированный) вызов
143
+ *
144
+ * @returns true если есть запланированный вызов
145
+ *
146
+ * @example
147
+ * ```typescript
148
+ * const debouncer = new Debouncer(300);
149
+ *
150
+ * console.log(debouncer.isPending()); // false
151
+ *
152
+ * debouncer.debounce(() => console.log('Test'));
153
+ * console.log(debouncer.isPending()); // true
154
+ *
155
+ * // Через 300мс
156
+ * console.log(debouncer.isPending()); // false
157
+ * ```
158
+ */
159
+ isPending(): boolean;
160
+ }
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Debouncer - утилита для отложенного выполнения функций
3
+ *
4
+ * Устраняет дублирование debounce логики между field-node.ts и behavior-registry.ts
5
+ *
6
+ * @internal
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const debouncer = new Debouncer(300);
11
+ *
12
+ * // Отложить выполнение на 300мс
13
+ * await debouncer.debounce(async () => {
14
+ * await validateField();
15
+ * });
16
+ *
17
+ * // Отменить отложенное выполнение
18
+ * debouncer.cancel();
19
+ *
20
+ * // Выполнить немедленно, отменив отложенное
21
+ * await debouncer.flush(async () => {
22
+ * await validateField();
23
+ * });
24
+ * ```
25
+ */
26
+ /**
27
+ * Класс для debouncing (отложенного выполнения) функций
28
+ *
29
+ * @internal
30
+ *
31
+ * Откладывает выполнение функции на заданное время. Если функция вызывается
32
+ * повторно до истечения времени, предыдущий вызов отменяется.
33
+ *
34
+ * Полезно для:
35
+ * - Отложенной валидации при вводе (debounced validation)
36
+ * - Отложенного сохранения данных
37
+ * - Отложенной обработки событий behaviors
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * // В FieldNode
42
+ * class FieldNode {
43
+ * private validationDebouncer: Debouncer;
44
+ *
45
+ * constructor(config) {
46
+ * this.validationDebouncer = new Debouncer(config.debounce || 0);
47
+ * }
48
+ *
49
+ * async validate(): Promise<boolean> {
50
+ * return this.validationDebouncer.debounce(async () => {
51
+ * // Валидация выполнится через debounce мс
52
+ * return await this.runValidation();
53
+ * });
54
+ * }
55
+ * }
56
+ * ```
57
+ */
58
+ export class Debouncer {
59
+ delay;
60
+ /**
61
+ * Таймер для отложенного выполнения
62
+ * @private
63
+ */
64
+ timer;
65
+ /**
66
+ * Создать Debouncer с заданной задержкой
67
+ *
68
+ * @param delay Задержка в миллисекундах (0 = без задержки)
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * const debouncer = new Debouncer(300); // 300мс задержка
73
+ * const immediate = new Debouncer(0); // Без задержки
74
+ * ```
75
+ */
76
+ constructor(delay) {
77
+ this.delay = delay;
78
+ }
79
+ /**
80
+ * Отложить выполнение функции
81
+ *
82
+ * Если вызывается повторно до истечения delay, предыдущий вызов отменяется
83
+ * и таймер перезапускается.
84
+ *
85
+ * @param fn Функция для выполнения (может быть async)
86
+ * @returns Promise, который разрешается результатом функции
87
+ *
88
+ * @example
89
+ * ```typescript
90
+ * const debouncer = new Debouncer(300);
91
+ *
92
+ * // Первый вызов - запланирован через 300мс
93
+ * debouncer.debounce(async () => console.log('First'));
94
+ *
95
+ * // Второй вызов через 100мс - отменяет первый, запланирован через 300мс
96
+ * debouncer.debounce(async () => console.log('Second'));
97
+ *
98
+ * // Через 300мс выведет только: "Second"
99
+ * ```
100
+ */
101
+ async debounce(fn) {
102
+ return new Promise((resolve, reject) => {
103
+ // Отменяем предыдущий таймер, если есть
104
+ if (this.timer) {
105
+ clearTimeout(this.timer);
106
+ }
107
+ // Если delay = 0, выполняем немедленно
108
+ if (this.delay === 0) {
109
+ Promise.resolve()
110
+ .then(() => fn())
111
+ .then(resolve)
112
+ .catch(reject);
113
+ return;
114
+ }
115
+ // Запускаем новый таймер
116
+ this.timer = setTimeout(async () => {
117
+ try {
118
+ const result = await fn();
119
+ resolve(result);
120
+ }
121
+ catch (error) {
122
+ reject(error);
123
+ }
124
+ }, this.delay);
125
+ });
126
+ }
127
+ /**
128
+ * Отменить отложенное выполнение
129
+ *
130
+ * Если есть запланированный вызов, он будет отменен и не выполнится.
131
+ * Promise из debounce() никогда не разрешится.
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * const debouncer = new Debouncer(300);
136
+ *
137
+ * debouncer.debounce(async () => {
138
+ * console.log('This will not execute');
139
+ * });
140
+ *
141
+ * debouncer.cancel(); // Отменяем вызов
142
+ * ```
143
+ */
144
+ cancel() {
145
+ if (this.timer) {
146
+ clearTimeout(this.timer);
147
+ this.timer = undefined;
148
+ }
149
+ }
150
+ /**
151
+ * Выполнить функцию немедленно, отменив любой отложенный вызов
152
+ *
153
+ * Полезно когда нужно принудительно выполнить действие сейчас,
154
+ * игнорируя debounce.
155
+ *
156
+ * @param fn Функция для немедленного выполнения
157
+ * @returns Promise с результатом функции
158
+ *
159
+ * @example
160
+ * ```typescript
161
+ * const debouncer = new Debouncer(300);
162
+ *
163
+ * // Запланировано через 300мс
164
+ * debouncer.debounce(async () => console.log('Delayed'));
165
+ *
166
+ * // Отменяем отложенный и выполняем немедленно
167
+ * await debouncer.flush(async () => console.log('Immediate'));
168
+ * // Выведет: "Immediate" (сразу)
169
+ * // "Delayed" не выполнится (отменен)
170
+ * ```
171
+ */
172
+ async flush(fn) {
173
+ this.cancel();
174
+ return await fn();
175
+ }
176
+ /**
177
+ * Проверить, есть ли активный (запланированный) вызов
178
+ *
179
+ * @returns true если есть запланированный вызов
180
+ *
181
+ * @example
182
+ * ```typescript
183
+ * const debouncer = new Debouncer(300);
184
+ *
185
+ * console.log(debouncer.isPending()); // false
186
+ *
187
+ * debouncer.debounce(() => console.log('Test'));
188
+ * console.log(debouncer.isPending()); // true
189
+ *
190
+ * // Через 300мс
191
+ * console.log(debouncer.isPending()); // false
192
+ * ```
193
+ */
194
+ isPending() {
195
+ return this.timer !== undefined;
196
+ }
197
+ }
@@ -0,0 +1,180 @@
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
+ import type { ValidationError } from '../types';
19
+ /**
20
+ * Стратегия обработки ошибок
21
+ *
22
+ * Определяет, что делать с ошибкой после логирования
23
+ */
24
+ export declare enum ErrorStrategy {
25
+ /**
26
+ * Пробросить ошибку дальше (throw)
27
+ * Используется когда ошибка критична и должна остановить выполнение
28
+ */
29
+ THROW = "throw",
30
+ /**
31
+ * Залогировать и проглотить ошибку (продолжить выполнение)
32
+ * Используется когда ошибка не критична
33
+ */
34
+ LOG = "log",
35
+ /**
36
+ * Конвертировать ошибку в ValidationError
37
+ * Используется в async validators для отображения ошибки валидации пользователю
38
+ */
39
+ CONVERT = "convert"
40
+ }
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 declare 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: unknown, context: string, strategy?: ErrorStrategy): ValidationError | never | void;
114
+ /**
115
+ * Извлечь сообщение из ошибки
116
+ *
117
+ * Обрабатывает различные типы ошибок:
118
+ * - Error объекты → error.message
119
+ * - Строки → возвращает как есть
120
+ * - Объекты с message → извлекает message
121
+ * - Другое → String(error)
122
+ *
123
+ * @param error Ошибка для извлечения сообщения
124
+ * @returns Сообщение ошибки
125
+ * @private
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * FormErrorHandler.extractMessage(new Error('Test'));
130
+ * // 'Test'
131
+ *
132
+ * FormErrorHandler.extractMessage('String error');
133
+ * // 'String error'
134
+ *
135
+ * FormErrorHandler.extractMessage({ message: 'Object error' });
136
+ * // 'Object error'
137
+ *
138
+ * FormErrorHandler.extractMessage(null);
139
+ * // 'null'
140
+ * ```
141
+ */
142
+ private static extractMessage;
143
+ /**
144
+ * Создать ValidationError с заданными параметрами
145
+ *
146
+ * Утилитная функция для создания ValidationError объектов
147
+ *
148
+ * @param code Код ошибки
149
+ * @param message Сообщение ошибки
150
+ * @param field Поле (опционально)
151
+ * @returns ValidationError объект
152
+ *
153
+ * @example
154
+ * ```typescript
155
+ * const error = FormErrorHandler.createValidationError(
156
+ * 'required',
157
+ * 'This field is required',
158
+ * 'email'
159
+ * );
160
+ * // { code: 'required', message: 'This field is required', field: 'email' }
161
+ * ```
162
+ */
163
+ static createValidationError(code: string, message: string, field?: string): ValidationError;
164
+ /**
165
+ * Проверить, является ли объект ValidationError
166
+ *
167
+ * Type guard для ValidationError
168
+ *
169
+ * @param value Значение для проверки
170
+ * @returns true если value является ValidationError
171
+ *
172
+ * @example
173
+ * ```typescript
174
+ * if (FormErrorHandler.isValidationError(result)) {
175
+ * console.log(result.code); // OK, типобезопасно
176
+ * }
177
+ * ```
178
+ */
179
+ static isValidationError(value: unknown): value is ValidationError;
180
+ }