@reformer/core 1.0.0-beta.1 → 1.0.0-beta.2

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 (79) hide show
  1. package/dist/behaviors/compute-from.js +3 -3
  2. package/dist/behaviors/enable-when.js +5 -5
  3. package/dist/behaviors/reset-when.js +1 -1
  4. package/dist/behaviors/revalidate-when.js +1 -1
  5. package/dist/behaviors/sync-fields.js +5 -5
  6. package/dist/behaviors/watch-field.js +3 -3
  7. package/dist/behaviors.js +2 -2
  8. package/dist/core/types/field-path.d.ts +2 -2
  9. package/dist/core/types/index.d.ts +1 -1
  10. package/dist/core/types/validation-schema.d.ts +21 -50
  11. package/dist/core/validation/core/index.d.ts +0 -1
  12. package/dist/core/validation/core/validate-async.d.ts +9 -15
  13. package/dist/core/validation/core/validate.d.ts +15 -15
  14. package/dist/core/validation/index.d.ts +5 -3
  15. package/dist/core/validation/validation-applicator.d.ts +2 -56
  16. package/dist/core/validation/validation-registry.d.ts +18 -16
  17. package/dist/core/validation/validators/array-validators.d.ts +6 -31
  18. package/dist/core/validation/validators/email.d.ts +5 -29
  19. package/dist/core/validation/validators/future-date.d.ts +6 -28
  20. package/dist/core/validation/validators/index.d.ts +12 -4
  21. package/dist/core/validation/validators/integer.d.ts +13 -0
  22. package/dist/core/validation/validators/is-date.d.ts +5 -28
  23. package/dist/core/validation/validators/is-number.d.ts +14 -0
  24. package/dist/core/validation/validators/max-age.d.ts +6 -29
  25. package/dist/core/validation/validators/max-date.d.ts +6 -29
  26. package/dist/core/validation/validators/max-length.d.ts +5 -30
  27. package/dist/core/validation/validators/max.d.ts +7 -29
  28. package/dist/core/validation/validators/min-age.d.ts +6 -29
  29. package/dist/core/validation/validators/min-date.d.ts +6 -29
  30. package/dist/core/validation/validators/min-length.d.ts +5 -30
  31. package/dist/core/validation/validators/min.d.ts +7 -29
  32. package/dist/core/validation/validators/multiple-of.d.ts +13 -0
  33. package/dist/core/validation/validators/non-negative.d.ts +13 -0
  34. package/dist/core/validation/validators/non-zero.d.ts +13 -0
  35. package/dist/core/validation/validators/past-date.d.ts +5 -28
  36. package/dist/core/validation/validators/pattern.d.ts +5 -32
  37. package/dist/core/validation/validators/phone.d.ts +9 -19
  38. package/dist/core/validation/validators/required.d.ts +10 -31
  39. package/dist/core/validation/validators/url.d.ts +13 -15
  40. package/dist/{index-D25LsbRm.js → index-DLh_Ryb2.js} +1 -1
  41. package/dist/index.js +465 -397
  42. package/dist/{registry-helpers-Bv_BJ1s-.js → registry-helpers-CLPXad2B.js} +152 -292
  43. package/dist/validators/email.js +7 -9
  44. package/dist/validators/future-date.js +11 -12
  45. package/dist/validators/integer.d.ts +2 -0
  46. package/dist/validators/integer.js +10 -0
  47. package/dist/validators/is-date.js +6 -7
  48. package/dist/validators/is-number.d.ts +2 -0
  49. package/dist/validators/is-number.js +10 -0
  50. package/dist/validators/max-age.js +11 -12
  51. package/dist/validators/max-date.js +11 -12
  52. package/dist/validators/max-length.js +12 -8
  53. package/dist/validators/max.js +5 -6
  54. package/dist/validators/min-age.js +10 -11
  55. package/dist/validators/min-date.js +12 -13
  56. package/dist/validators/min-length.js +12 -8
  57. package/dist/validators/min.js +6 -7
  58. package/dist/validators/multiple-of.d.ts +2 -0
  59. package/dist/validators/multiple-of.js +10 -0
  60. package/dist/validators/non-negative.d.ts +2 -0
  61. package/dist/validators/non-negative.js +10 -0
  62. package/dist/validators/non-zero.d.ts +2 -0
  63. package/dist/validators/non-zero.js +10 -0
  64. package/dist/validators/past-date.js +11 -12
  65. package/dist/validators/pattern.js +6 -7
  66. package/dist/validators/phone.js +14 -32
  67. package/dist/validators/required.js +9 -10
  68. package/dist/validators/url.js +19 -16
  69. package/dist/validators-xJyP-jLZ.js +169 -0
  70. package/dist/validators.js +54 -50
  71. package/llms.txt +505 -790
  72. package/package.json +20 -4
  73. package/dist/core/validation/core/validate-tree.d.ts +0 -35
  74. package/dist/core/validation/validation-context.d.ts +0 -86
  75. package/dist/core/validation/validators/number.d.ts +0 -31
  76. package/dist/validate-C3XiA_zf.js +0 -10
  77. package/dist/validators/number.d.ts +0 -2
  78. package/dist/validators/number.js +0 -35
  79. package/dist/validators-BGsNOgT1.js +0 -207
@@ -1,7 +1,7 @@
1
1
  import { effect as _ } from "@preact/signals-core";
2
- import { b as v } from "../registry-helpers-Bv_BJ1s-.js";
2
+ import { g as v } from "../registry-helpers-CLPXad2B.js";
3
3
  import { r as V } from "../safe-effect-Dh8uw81c.js";
4
- function N(n, i, s, f) {
4
+ function b(n, i, s, f) {
5
5
  const { debounce: p, condition: u } = f || {}, h = (r, E, m) => {
6
6
  const a = r.getFieldByPath(i.__path);
7
7
  if (!a) return null;
@@ -27,5 +27,5 @@ function N(n, i, s, f) {
27
27
  v().register(h, { debounce: p });
28
28
  }
29
29
  export {
30
- N as computeFrom
30
+ b as computeFrom
31
31
  };
@@ -1,20 +1,20 @@
1
1
  import { effect as c } from "@preact/signals-core";
2
- import { b } from "../registry-helpers-Bv_BJ1s-.js";
3
- import { r as d } from "../safe-effect-Dh8uw81c.js";
2
+ import { g as d } from "../registry-helpers-CLPXad2B.js";
3
+ import { r as b } from "../safe-effect-Dh8uw81c.js";
4
4
  function h(t, n, r) {
5
- const { debounce: o, resetOnDisable: a = !1 } = r || {}, i = (s, m, l) => {
5
+ const { debounce: o, resetOnDisable: a = !1 } = r || {}, i = (s, g, l) => {
6
6
  const e = s.getFieldByPath(t.__path);
7
7
  return e ? c(() => {
8
8
  const f = s.value.value;
9
9
  l(() => {
10
10
  const u = n(f);
11
- d(() => {
11
+ b(() => {
12
12
  u ? e.enable() : (e.disable(), a && e.reset());
13
13
  });
14
14
  });
15
15
  }) : null;
16
16
  };
17
- b().register(i, { debounce: o });
17
+ d().register(i, { debounce: o });
18
18
  }
19
19
  function _(t, n, r) {
20
20
  h(t, (o) => !n(o), r);
@@ -1,5 +1,5 @@
1
1
  import { effect as c } from "@preact/signals-core";
2
- import { b as d } from "../registry-helpers-Bv_BJ1s-.js";
2
+ import { g as d } from "../registry-helpers-CLPXad2B.js";
3
3
  import { r as h } from "../safe-effect-Dh8uw81c.js";
4
4
  function R(r, n, o) {
5
5
  const { debounce: s, resetValue: u = null, onlyIfDirty: a = !1 } = o || {}, i = (t, m, l) => {
@@ -1,5 +1,5 @@
1
1
  import { effect as d } from "@preact/signals-core";
2
- import { b as h } from "../registry-helpers-Bv_BJ1s-.js";
2
+ import { g as h } from "../registry-helpers-CLPXad2B.js";
3
3
  function p(o, a, i) {
4
4
  const { debounce: l } = i || {}, u = (t, s, c) => {
5
5
  const r = t.getFieldByPath(o.__path);
@@ -1,12 +1,12 @@
1
1
  import { effect as o } from "@preact/signals-core";
2
- import { b as v } from "../registry-helpers-Bv_BJ1s-.js";
2
+ import { g as v } from "../registry-helpers-CLPXad2B.js";
3
3
  import { r as i } from "../safe-effect-Dh8uw81c.js";
4
4
  function E(u, f, c) {
5
- const { debounce: d, transform: a } = c || {}, p = (n, h, l) => {
5
+ const { debounce: d, transform: a } = c || {}, g = (n, h, l) => {
6
6
  const r = n.getFieldByPath(u.__path), s = n.getFieldByPath(f.__path);
7
7
  if (!r || !s) return null;
8
8
  let e = !1;
9
- const g = o(() => {
9
+ const p = o(() => {
10
10
  const t = r.value.value;
11
11
  e || l(() => {
12
12
  e = !0, i(() => {
@@ -31,10 +31,10 @@ function E(u, f, c) {
31
31
  });
32
32
  });
33
33
  return () => {
34
- g(), m();
34
+ p(), m();
35
35
  };
36
36
  };
37
- v().register(p, { debounce: d });
37
+ v().register(g, { debounce: d });
38
38
  }
39
39
  export {
40
40
  E as syncFields
@@ -1,7 +1,7 @@
1
1
  import { effect as c } from "@preact/signals-core";
2
- import { b as d } from "../registry-helpers-Bv_BJ1s-.js";
2
+ import { g as d } from "../registry-helpers-CLPXad2B.js";
3
3
  import { r as i } from "../safe-effect-Dh8uw81c.js";
4
- function g(n, r, u) {
4
+ function p(n, r, u) {
5
5
  const { debounce: a, immediate: f = !1 } = u || {}, s = (l, o, m) => {
6
6
  const e = l.getFieldByPath(n.__path);
7
7
  return e ? (f && i(() => {
@@ -17,5 +17,5 @@ function g(n, r, u) {
17
17
  d().register(s, { debounce: a });
18
18
  }
19
19
  export {
20
- g as watchField
20
+ p as watchField
21
21
  };
package/dist/behaviors.js CHANGED
@@ -1,5 +1,5 @@
1
- import { a as o, b as a, i as t, t as m } from "./index-D25LsbRm.js";
2
- import { a as s, B as f } from "./registry-helpers-Bv_BJ1s-.js";
1
+ import { a as o, b as a, i as t, t as m } from "./index-DLh_Ryb2.js";
2
+ import { a as s, B as f } from "./registry-helpers-CLPXad2B.js";
3
3
  import { copyFrom as n } from "./behaviors/copy-from.js";
4
4
  import { disableWhen as h, enableWhen as i } from "./behaviors/enable-when.js";
5
5
  import { computeFrom as c } from "./behaviors/compute-from.js";
@@ -23,9 +23,9 @@ import { AnyFunction } from './index';
23
23
  * };
24
24
  * ```
25
25
  */
26
- export type FieldPath<T> = {
26
+ export type FieldPath<T> = NonNullable<T> extends object ? NonNullable<T> extends Array<unknown> | Date | File | Blob | AnyFunction ? FieldPathNode<unknown, T> : {
27
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
- };
28
+ } : FieldPathNode<unknown, T>;
29
29
  /**
30
30
  * Узел в пути поля
31
31
  * Содержит метаинформацию о поле для валидации
@@ -99,7 +99,7 @@ export interface ErrorFilterOptions {
99
99
  export type FieldStatus = 'valid' | 'invalid' | 'pending' | 'disabled';
100
100
  export type { FieldConfig } from './deep-schema';
101
101
  export type { FieldPath, FieldPathNode } from '../types/field-path';
102
- export type { ContextualValidatorFn, ContextualAsyncValidatorFn, TreeValidatorFn, ConditionFn, ValidateOptions, ValidateAsyncOptions, ValidateTreeOptions, ValidationSchemaFn, ValidatorRegistration, } from './validation-schema';
102
+ export type { Validator, AsyncValidator, ConditionFn, ValidateOptions, ValidateAsyncOptions, ValidationSchemaFn, ValidatorRegistration, } from './validation-schema';
103
103
  export type { FormSchema, ArrayConfig } from './deep-schema';
104
104
  export type { FormContext } from './form-context';
105
105
  export type { FormControlsProxy, FormProxy, FormArrayProxy } from './form-proxy';
@@ -1,57 +1,34 @@
1
1
  import { FormFields, ValidationError } from './index';
2
2
  import { FieldPath } from './field-path';
3
- import { FormContext } from './form-context';
3
+ import { FormProxy } from './form-proxy';
4
4
  /**
5
- * Функция валидации поля с контекстом
5
+ * Чистый синхронный валидатор поля.
6
6
  *
7
- * Новый паттерн: (value, ctx: FormContext) => ValidationError | null
7
+ * Принимает значение поля, прокси текущего поля (control) и прокси корня формы (root).
8
+ * Возвращает ValidationError либо null. Не знает про реестр валидации.
8
9
  *
9
10
  * @example
10
11
  * ```typescript
11
- * validate(path.email, (value, ctx) => {
12
- * if (!value) return { code: 'required', message: 'Email required' };
13
- * const confirm = ctx.form.confirmEmail.value.value;
14
- * if (value !== confirm) return { code: 'mismatch', message: 'Must match' };
12
+ * const isAdult: Validator<MyForm, number> = (value, control, root) => {
13
+ * if (value < 18) return { code: 'tooYoung', message: '18+' };
15
14
  * return null;
16
- * });
15
+ * };
16
+ * validate(path.age, isAdult);
17
17
  * ```
18
18
  */
19
- export type ContextualValidatorFn<TForm, TField> = (value: TField, ctx: FormContext<TForm>) => ValidationError | null;
19
+ export type Validator<TForm, TField> = (value: TField, control: FormProxy<TField>, root: FormProxy<TForm>) => ValidationError | null;
20
20
  /**
21
- * Асинхронная функция валидации поля с контекстом
21
+ * Чистый асинхронный валидатор поля.
22
22
  *
23
- * @example
24
- * ```typescript
25
- * validateAsync(path.email, async (value, ctx) => {
26
- * const exists = await checkEmailExists(value);
27
- * if (exists) return { code: 'exists', message: 'Email already taken' };
28
- * return null;
29
- * });
30
- * ```
31
- */
32
- export type ContextualAsyncValidatorFn<TForm, TField> = (value: TField, ctx: FormContext<TForm>) => Promise<ValidationError | null>;
33
- /**
34
- * Функция cross-field валидации
35
- *
36
- * @example
37
- * ```typescript
38
- * validateTree((ctx) => {
39
- * const password = ctx.form.password.value.value;
40
- * const confirm = ctx.form.confirmPassword.value.value;
41
- * if (password !== confirm) {
42
- * return { code: 'mismatch', message: 'Passwords must match' };
43
- * }
44
- * return null;
45
- * });
46
- * ```
23
+ * Регистрируется через `validateAsync(path, validator, { debounce })`.
47
24
  */
48
- export type TreeValidatorFn<TForm> = (ctx: FormContext<TForm>) => ValidationError | null;
25
+ export type AsyncValidator<TForm, TField> = (value: TField, control: FormProxy<TField>, root: FormProxy<TForm>) => Promise<ValidationError | null>;
49
26
  /**
50
- * Функция условия для applyWhen
27
+ * Функция условия для applyWhen.
51
28
  */
52
29
  export type ConditionFn<T> = (value: T) => boolean;
53
30
  /**
54
- * Опции для функции validate
31
+ * Опции для функции validate.
55
32
  */
56
33
  export interface ValidateOptions {
57
34
  /** Сообщение об ошибке */
@@ -60,23 +37,16 @@ export interface ValidateOptions {
60
37
  params?: FormFields;
61
38
  }
62
39
  /**
63
- * Опции для функции validateAsync
40
+ * Опции для функции validateAsync.
64
41
  */
65
42
  export interface ValidateAsyncOptions extends ValidateOptions {
66
43
  /** Задержка перед выполнением валидации (в мс) */
67
44
  debounce?: number;
68
45
  }
69
46
  /**
70
- * Опции для функции validateTree
71
- */
72
- export interface ValidateTreeOptions {
73
- /** Поле, к которому привязать ошибку */
74
- targetField?: string;
75
- }
76
- /**
77
- * Функция validation schema
47
+ * Функция validation schema.
78
48
  *
79
- * Принимает FieldPath и определяет все правила валидации для формы
49
+ * Принимает FieldPath и определяет все правила валидации для формы.
80
50
  */
81
51
  export type ValidationSchemaFn<T> = (path: FieldPath<T>) => void;
82
52
  /**
@@ -85,9 +55,10 @@ export type ValidationSchemaFn<T> = (path: FieldPath<T>) => void;
85
55
  */
86
56
  export interface ValidatorRegistration {
87
57
  fieldPath: string;
88
- type: 'sync' | 'async' | 'tree';
89
- validator: ContextualValidatorFn<unknown, unknown> | ContextualAsyncValidatorFn<unknown, unknown> | TreeValidatorFn<unknown>;
90
- options?: ValidateOptions | ValidateAsyncOptions | ValidateTreeOptions;
58
+ type: 'sync' | 'async' | 'array-items';
59
+ validator: Validator<unknown, unknown> | AsyncValidator<unknown, unknown>;
60
+ options?: ValidateOptions | ValidateAsyncOptions;
61
+ /** Для условной валидации (applyWhen). */
91
62
  condition?: {
92
63
  fieldPath: string;
93
64
  conditionFn: ConditionFn<unknown>;
@@ -3,6 +3,5 @@
3
3
  */
4
4
  export { validate } from './validate';
5
5
  export { validateAsync } from './validate-async';
6
- export { validateTree } from './validate-tree';
7
6
  export { applyWhen } from './apply-when';
8
7
  export { apply } from './apply';
@@ -1,7 +1,8 @@
1
- import { ContextualAsyncValidatorFn, ValidateAsyncOptions } from '../../types/validation-schema';
2
- import { FieldPathNode } from '../../types';
1
+ import { AsyncValidator, FieldPathNode, ValidateAsyncOptions } from '../../types';
3
2
  /**
4
- * Зарегистрировать асинхронный валидатор для поля
3
+ * Зарегистрировать асинхронный валидатор для поля.
4
+ *
5
+ * Принимает чистую async-функцию `(value, control, root) => Promise<error | null>`.
5
6
  *
6
7
  * @group Validation
7
8
  * @category Core Functions
@@ -10,27 +11,20 @@ import { FieldPathNode } from '../../types';
10
11
  * ```typescript
11
12
  * validateAsync(
12
13
  * path.inn,
13
- * async (ctx: ValidationContext<TForm, TField>) => {
14
- * const inn = ctx.value();
15
- * if (!inn) return null;
16
- *
14
+ * async (value, _control, _root) => {
15
+ * if (!value) return null;
17
16
  * const response = await fetch('/api/validate-inn', {
18
17
  * method: 'POST',
19
- * body: JSON.stringify({ inn }),
18
+ * body: JSON.stringify({ inn: value }),
20
19
  * });
21
- *
22
20
  * const data = await response.json();
23
21
  * if (!data.valid) {
24
- * return {
25
- * code: 'invalidInn',
26
- * message: 'ИНН не найден в базе данных ФНС',
27
- * };
22
+ * return { code: 'invalidInn', message: 'ИНН не найден в базе ФНС' };
28
23
  * }
29
- *
30
24
  * return null;
31
25
  * },
32
26
  * { debounce: 1000 }
33
27
  * );
34
28
  * ```
35
29
  */
36
- export declare function validateAsync<TForm, TField>(fieldPath: FieldPathNode<TForm, TField>, validatorFn: ContextualAsyncValidatorFn<TForm, TField>, options?: ValidateAsyncOptions): void;
30
+ export declare function validateAsync<TForm, TField>(fieldPath: FieldPathNode<TForm, TField>, validator: AsyncValidator<TForm, TField>, options?: ValidateAsyncOptions): void;
@@ -1,26 +1,26 @@
1
- import { ContextualValidatorFn, FieldPathNode, ValidateOptions } from '../../types';
1
+ import { Validator, FieldPathNode, ValidateOptions } from '../../types';
2
2
  /**
3
- * Зарегистрировать кастомный синхронный валидатор для поля
4
- * Поддерживает опциональные поля
3
+ * Зарегистрировать синхронный валидатор для поля.
4
+ *
5
+ * Принимает чистую функцию-валидатор `(value, control, root) => error | null`,
6
+ * либо фабрику из `@reformer/core/validators` (например, `required()`).
5
7
  *
6
8
  * @group Validation
7
9
  * @category Core Functions
8
10
  *
9
11
  * @example
10
12
  * ```typescript
11
- * validate(path.birthDate, (ctx: ValidationContext<TForm, TField>) => {
12
- * const birthDate = new Date(ctx.value());
13
- * const age = calculateAge(birthDate);
14
- *
15
- * if (age < 18) {
16
- * return {
17
- * code: 'tooYoung',
18
- * message: 'Заемщику должно быть не менее 18 лет',
19
- * };
20
- * }
21
- *
13
+ * // Кастомный валидатор
14
+ * validate(path.birthDate, (value, _control, root) => {
15
+ * const age = calculateAge(new Date(value));
16
+ * if (age < 18) return { code: 'tooYoung', message: 'Только 18+' };
22
17
  * return null;
23
18
  * });
19
+ *
20
+ * // Фабрика из @reformer/core/validators
21
+ * import { required, min } from '@reformer/core/validators';
22
+ * validate(path.loanAmount, required());
23
+ * validate(path.loanAmount, min(50000, { message: 'Min 50 000' }));
24
24
  * ```
25
25
  */
26
- export declare function validate<TForm, TField>(fieldPath: FieldPathNode<TForm, TField> | undefined, validatorFn: ContextualValidatorFn<TForm, TField>, options?: ValidateOptions): void;
26
+ export declare function validate<TForm, TField>(fieldPath: FieldPathNode<TForm, TField> | undefined, validator: Validator<TForm, TField>, options?: ValidateOptions): void;
@@ -1,6 +1,5 @@
1
1
  export { validate } from './core/validate';
2
2
  export { validateAsync } from './core/validate-async';
3
- export { validateTree } from './core/validate-tree';
4
3
  export { apply } from './core/apply';
5
4
  export { applyWhen } from './core/apply-when';
6
5
  export { required } from './validators/required';
@@ -12,7 +11,11 @@ export { email } from './validators/email';
12
11
  export { pattern } from './validators/pattern';
13
12
  export { url } from './validators/url';
14
13
  export { phone, type PhoneFormat } from './validators/phone';
15
- export { number } from './validators/number';
14
+ export { isNumber } from './validators/is-number';
15
+ export { integer } from './validators/integer';
16
+ export { multipleOf } from './validators/multiple-of';
17
+ export { nonNegative } from './validators/non-negative';
18
+ export { nonZero } from './validators/non-zero';
16
19
  export { isDate } from './validators/is-date';
17
20
  export { minDate } from './validators/min-date';
18
21
  export { maxDate } from './validators/max-date';
@@ -24,4 +27,3 @@ export { notEmpty, validateItems } from './validators/array-validators';
24
27
  export { createFieldPath, extractPath, extractKey, toFieldPath } from '../utils/field-path';
25
28
  export { validateForm } from './validate-form';
26
29
  export { ValidationRegistry } from './validation-registry';
27
- export { ValidationContextImpl, TreeValidationContextImpl } from './validation-context';
@@ -1,70 +1,16 @@
1
1
  import { GroupNode } from '../nodes/group-node';
2
2
  import { ValidatorRegistration } from '../types';
3
- /**
4
- * Класс для применения валидаторов к форме
5
- *
6
- * Выполняет:
7
- * - Группировку валидаторов по полям
8
- * - Фильтрацию по условиям (condition)
9
- * - Применение sync/async валидаторов к FieldNode
10
- * - Применение tree валидаторов (кросс-полевая валидация)
11
- *
12
- * @template T Тип формы (объект)
13
- */
14
3
  export declare class ValidationApplicator<T> {
15
4
  private readonly form;
16
5
  constructor(form: GroupNode<T>);
17
6
  /**
18
- * Применить валидаторы к полям формы
19
- *
20
- * Этапы применения:
21
- * 1. Разделение валидаторов на field и tree
22
- * 2. Применение field валидаторов (sync/async)
23
- * 3. Применение tree валидаторов (кросс-полевая валидация)
24
- *
25
- * @param validators Зарегистрированные валидаторы
7
+ * Применить валидаторы к полям формы.
26
8
  */
27
9
  apply(validators: ValidatorRegistration[]): Promise<void>;
28
- /**
29
- * Группировка валидаторов по типам
30
- *
31
- * Разделяет валидаторы на:
32
- * - Field validators (sync/async) - группируются по fieldPath
33
- * - Tree validators - применяются ко всей форме
34
- *
35
- * @param validators Все зарегистрированные валидаторы
36
- * @returns Сгруппированные валидаторы
37
- */
38
10
  private groupValidators;
39
11
  /**
40
- * Применение field валидаторов к полям
41
- *
42
- * Для каждого поля:
43
- * 1. Найти FieldNode по пути
44
- * 2. Проверить условия (condition)
45
- * 3. Выполнить sync/async валидаторы
46
- * 4. Установить ошибки на поле
47
- *
48
- * @param validatorsByField Валидаторы, сгруппированные по полям
12
+ * Применение sync/async валидаторов к полям.
49
13
  */
50
14
  private applyFieldValidators;
51
- /**
52
- * Применение tree валидаторов (кросс-полевая валидация)
53
- *
54
- * Tree валидаторы имеют доступ ко всей форме через TreeValidationContext.
55
- * Ошибки устанавливаются на targetField (если указано).
56
- *
57
- * @param treeValidators Список tree валидаторов
58
- */
59
- private applyTreeValidators;
60
- /**
61
- * Проверка условия (condition) для валидатора
62
- *
63
- * Условие определяет, должен ли валидатор выполняться.
64
- * Использует getFieldByPath для поддержки вложенных путей.
65
- *
66
- * @param condition Условие валидатора
67
- * @returns true, если условие выполнено
68
- */
69
15
  private checkCondition;
70
16
  }
@@ -1,10 +1,8 @@
1
1
  import { GroupNode } from '../nodes/group-node';
2
2
  import { FormFields } from '../types';
3
- import { AbstractRegistry } from '../utils/abstract-registry';
4
- import { ValidatorRegistration, ContextualValidatorFn, ContextualAsyncValidatorFn, TreeValidatorFn, ConditionFn, ValidateOptions, ValidateAsyncOptions, ValidateTreeOptions } from '../types/validation-schema';
3
+ import { ValidatorRegistration, Validator, AsyncValidator, ConditionFn, ValidateOptions, ValidateAsyncOptions } from '../types/validation-schema';
5
4
  /**
6
5
  * Контекст регистрации валидаторов
7
- * Управляет condition stack для условных валидаторов
8
6
  */
9
7
  declare class RegistrationContext {
10
8
  private validators;
@@ -32,9 +30,10 @@ declare class RegistrationContext {
32
30
  * Каждый экземпляр GroupNode создает собственный реестр (композиция).
33
31
  * Устраняет race conditions и изолирует формы друг от друга.
34
32
  *
35
- * Наследует AbstractRegistry для унификации:
36
- * - Управления global stack
37
- * - Template methods begin/end registration
33
+ * Context stack используется для tracking текущего активного реестра:
34
+ * - beginRegistration() помещает this в global stack
35
+ * - endRegistration() извлекает из global stack
36
+ * - getCurrent() возвращает текущий активный реестр
38
37
  *
39
38
  * @example
40
39
  * ```typescript
@@ -49,10 +48,13 @@ declare class RegistrationContext {
49
48
  * }
50
49
  * ```
51
50
  */
52
- export declare class ValidationRegistry extends AbstractRegistry<ValidatorRegistration> {
53
- /** Внутренний стек контекстов для управления condition blocks */
51
+ export declare class ValidationRegistry {
52
+ /**
53
+ * Global stack активных реестров
54
+ * Используется для изоляции форм друг от друга
55
+ */
56
+ private static registryStack;
54
57
  private contextStack;
55
- /** Финальные валидаторы после завершения регистрации */
56
58
  private validators;
57
59
  /**
58
60
  * Получить текущий активный реестр из global stack
@@ -75,7 +77,6 @@ export declare class ValidationRegistry extends AbstractRegistry<ValidatorRegist
75
77
  * Начать регистрацию валидаторов для формы
76
78
  *
77
79
  * Помещает this в global stack для изоляции форм
78
- * Создает новый RegistrationContext для condition management
79
80
  */
80
81
  beginRegistration(): RegistrationContext;
81
82
  /**
@@ -100,15 +101,11 @@ export declare class ValidationRegistry extends AbstractRegistry<ValidatorRegist
100
101
  /**
101
102
  * Зарегистрировать синхронный валидатор
102
103
  */
103
- registerSync<TForm = unknown, TField = unknown>(fieldPath: string, validator: ContextualValidatorFn<TForm, TField>, options?: ValidateOptions): void;
104
+ registerSync<TForm = unknown, TField = unknown>(fieldPath: string, validator: Validator<TForm, TField>, options?: ValidateOptions): void;
104
105
  /**
105
106
  * Зарегистрировать асинхронный валидатор
106
107
  */
107
- registerAsync<TForm = unknown, TField = unknown>(fieldPath: string, validator: ContextualAsyncValidatorFn<TForm, TField>, options?: ValidateAsyncOptions): void;
108
- /**
109
- * Зарегистрировать tree валидатор
110
- */
111
- registerTree<TForm = unknown>(validator: TreeValidatorFn<TForm>, options?: ValidateTreeOptions): void;
108
+ registerAsync<TForm = unknown, TField = unknown>(fieldPath: string, validator: AsyncValidator<TForm, TField>, options?: ValidateAsyncOptions): void;
112
109
  /**
113
110
  * Войти в условный блок
114
111
  */
@@ -133,6 +130,11 @@ export declare class ValidationRegistry extends AbstractRegistry<ValidatorRegist
133
130
  * Возвращает локальный массив валидаторов (без аргумента form).
134
131
  */
135
132
  getValidators(): ValidatorRegistration[];
133
+ /**
134
+ * Применить зарегистрированные валидаторы к GroupNode
135
+ * @private
136
+ */
137
+ private applyValidators;
136
138
  /**
137
139
  * Применить array-items validators к ArrayNode элементам
138
140
  * @private
@@ -1,51 +1,26 @@
1
- import { ValidateOptions, ValidationSchemaFn } from '../../types/validation-schema';
1
+ import { Validator, ValidateOptions, ValidationSchemaFn } from '../../types/validation-schema';
2
2
  import { FieldPathNode } from '../../types';
3
3
  /**
4
- * Проверить что массив содержит хотя бы один элемент
5
- *
6
- * Это удобный алиас для `minLength(field, 1)`, оптимизированный для массивов.
7
- *
8
- * @group Validation
9
- * @category Validators
10
- *
11
- * @param fieldPath - Поле-массив для валидации
12
- * @param options - Опции валидации (message, params и т.д.)
4
+ * Фабрика валидатора, проверяющего что массив (или строка) не пустой.
13
5
  *
14
6
  * @example
15
7
  * ```typescript
16
- * // Простая проверка
17
- * notEmpty(path.properties, { message: 'Добавьте хотя бы один объект имущества' });
18
- *
19
- * // С дополнительными параметрами
20
- * notEmpty(path.coBorrowers, {
21
- * message: 'Требуется хотя бы один созаемщик',
22
- * params: { minItems: 1 }
23
- * });
8
+ * validate(path.properties, notEmpty({ message: 'Добавьте хотя бы один элемент' }));
24
9
  * ```
25
10
  */
26
- export declare function notEmpty<TForm, TItem>(fieldPath: FieldPathNode<TForm, TItem[] | undefined> | undefined, options?: ValidateOptions): void;
11
+ export declare function notEmpty<TForm = unknown, TField = unknown>(options?: ValidateOptions): Validator<TForm, TField>;
27
12
  /**
28
- * Применить validation schema к каждому элементу массива
13
+ * Применить validation schema к каждому элементу массива.
29
14
  *
30
15
  * Регистрирует схему валидации, которая будет автоматически применяться
31
16
  * к каждому элементу ArrayNode (как существующим, так и новым).
32
17
  *
33
- * @group Validation
34
- * @category Validators
35
- *
36
- * @param fieldPath - Поле-массив для валидации элементов
37
- * @param itemSchemaFn - Validation schema для одного элемента
38
- *
39
18
  * @example
40
19
  * ```typescript
41
20
  * import { propertyValidation } from './property-validation';
42
21
  *
43
- * // В additionalValidation
44
22
  * applyWhen(path.hasProperty, (value) => value === true, (path) => {
45
- * // Проверка что массив не пустой
46
- * notEmpty(path.properties, { message: 'Добавьте хотя бы один объект имущества' });
47
- *
48
- * // Валидация каждого элемента
23
+ * validate(path.properties, notEmpty({ message: 'Добавьте хотя бы один объект' }));
49
24
  * validateItems(path.properties, propertyValidation);
50
25
  * });
51
26
  * ```
@@ -1,37 +1,13 @@
1
- import { ValidateOptions } from '../../types/validation-schema';
2
- import { FieldPathNode } from '../../types';
1
+ import { Validator, ValidateOptions } from '../../types/validation-schema';
3
2
  /**
4
- * Валидатор формата email
3
+ * Фабрика валидатора формата email.
5
4
  *
6
- * Проверяет, что значение соответствует формату email адреса.
7
5
  * Пустые значения пропускаются (используйте `required` для обязательности).
8
6
  *
9
- * @group Validation
10
- * @category Validators
11
- *
12
- * @param fieldPath - Путь к полю для валидации
13
- * @param options - Опции валидации (message, params)
14
- *
15
- * @example
16
- * ```typescript
17
- * // Базовое использование
18
- * validationSchema: (path) => [
19
- * required(path.email),
20
- * email(path.email),
21
- * ]
22
- *
23
- * // С кастомным сообщением
24
- * email(path.email, { message: 'Введите корректный email адрес' })
25
- * ```
26
- *
27
7
  * @example
28
8
  * ```typescript
29
- * // Ошибка валидации
30
- * {
31
- * code: 'email',
32
- * message: 'Неверный формат email',
33
- * params: {}
34
- * }
9
+ * validate(path.email, email());
10
+ * validate(path.email, email({ message: 'Введите корректный email' }));
35
11
  * ```
36
12
  */
37
- export declare function email<TForm, TField extends string | null | undefined = string>(fieldPath: FieldPathNode<TForm, TField> | undefined, options?: ValidateOptions): void;
13
+ export declare function email<TForm = unknown, TField extends string | undefined = string>(options?: ValidateOptions): Validator<TForm, TField>;