@astral/validations 4.7.0 → 4.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1364,6 +1364,26 @@ validate({
1364
1364
  });
1365
1365
  ```
1366
1366
 
1367
+ Позволяет делать optional вложенные правила:
1368
+
1369
+ ```ts
1370
+ type Values = { name: string | number; isAgree: boolean };
1371
+
1372
+ const validate = object<Values>({
1373
+ name: optional(
1374
+ when({
1375
+ is: (_, ctx) => Boolean(ctx.values?.isAgree),
1376
+ then: string(),
1377
+ otherwise: number(),
1378
+ })
1379
+ ),
1380
+ isAgree: optional(boolean()),
1381
+ });
1382
+
1383
+ // undefined
1384
+ validate({ isAgree: false, name: undefined });
1385
+ ```
1386
+
1367
1387
  ---
1368
1388
 
1369
1389
  ## when. Условная валидация
@@ -1,8 +1,19 @@
1
+ import { DeepPartial } from 'utility-types';
1
2
  import { ValidationContext } from '../types';
2
3
  import { ValidationTypes } from '../../types';
4
+ type Params<TLastSchemaValues extends Record<string, unknown>> = {
5
+ /**
6
+ * Value последнего валидируемого объекта
7
+ */
8
+ lastSchemaValue?: DeepPartial<TLastSchemaValues>;
9
+ /**
10
+ * Позволяет создать ctx, в котором будет соответсвующий isOptional
11
+ */
12
+ isOptional?: boolean;
13
+ };
3
14
  /**
4
15
  * @description Создает context валидации. Используется внутри фабрик guard и rule
5
16
  * @default по-дефолту сбрасывает все флаги в false
6
17
  */
7
- export declare function createContext<TValue extends ValidationTypes>(prevCtx: ValidationContext<{}, TValue> | undefined, value: TValue): ValidationContext<{}, TValue>;
8
- export declare function createContext<TValue extends ValidationTypes, TLastSchemaValues extends Record<string, unknown>>(prevCtx: ValidationContext<{}> | undefined, value: TValue, lastSchemaValue: TLastSchemaValues): ValidationContext<TLastSchemaValues, TValue>;
18
+ export declare function createContext<TValue extends ValidationTypes, TLastSchemaValues extends Record<string, unknown> = {}>(prevCtx: ValidationContext<Record<string, unknown>> | undefined, value: TValue, { lastSchemaValue, isOptional }?: Params<TLastSchemaValues>): ValidationContext<TLastSchemaValues>;
19
+ export {};
@@ -1,20 +1,21 @@
1
1
  import { createSimpleError } from '../../errors';
2
- export function createContext(prevCtx, value, lastSchemaValue) {
3
- if (prevCtx && !lastSchemaValue) {
4
- return prevCtx;
5
- }
6
- const currentLastSchemaValue = lastSchemaValue ? lastSchemaValue : undefined;
2
+ /**
3
+ * @description Создает context валидации. Используется внутри фабрик guard и rule
4
+ * @default по-дефолту сбрасывает все флаги в false
5
+ */
6
+ export function createContext(prevCtx, value, { lastSchemaValue, isOptional } = {}) {
7
7
  if (prevCtx) {
8
- return Object.assign(Object.assign({}, prevCtx), { values: currentLastSchemaValue });
8
+ return Object.assign(Object.assign({}, prevCtx), { isOptional: isOptional !== null && isOptional !== void 0 ? isOptional : prevCtx.isOptional, values: lastSchemaValue || prevCtx.values });
9
9
  }
10
10
  return {
11
- values: currentLastSchemaValue,
11
+ values: lastSchemaValue,
12
12
  global: {
13
13
  values: value,
14
14
  overrides: {
15
15
  objectIsPartial: false,
16
16
  },
17
17
  },
18
+ isOptional: isOptional !== null && isOptional !== void 0 ? isOptional : false,
18
19
  createError: createSimpleError,
19
20
  };
20
21
  }
@@ -11,7 +11,7 @@ export type ValidationContext<TLastSchemaValues extends Record<string, unknown>
11
11
  /**
12
12
  * @description Глобальные значения, идущие от самого верхнего правила к самому нижнему
13
13
  */
14
- global: {
14
+ global: DeepReadonly<{
15
15
  /**
16
16
  * @description Значения, которые валидируется guard самого высоко порядка
17
17
  */
@@ -25,9 +25,13 @@ export type ValidationContext<TLastSchemaValues extends Record<string, unknown>
25
25
  */
26
26
  objectIsPartial: boolean;
27
27
  };
28
- };
28
+ }>;
29
29
  /**
30
30
  * @description Фабрика ошибок. Возвращает новую ошибку валидации
31
31
  */
32
32
  createError: typeof createSimpleError;
33
+ /**
34
+ * @description Флаг, позволяющий отключать в guard'ах required правило. Первый guard, который примет isOptional===true сбросит его
35
+ */
36
+ isOptional: boolean;
33
37
  }>;
@@ -1,6 +1,23 @@
1
1
  import { ValidationResult } from '../../types';
2
2
  import { ValidationContext } from '../../context';
3
- import { GuardDefOptions, GuardValue } from '../types';
3
+ export type GuardDefOptions<AddDefOptions extends Record<string, unknown>> = Partial<AddDefOptions> & {
4
+ /**
5
+ * @description Переопределяет дефолтное сообщения ошибки для required
6
+ * @example string.define({ requiredMessage: 'ИНН не может быть пустым' })(inn())
7
+ */
8
+ requiredErrorMessage?: string;
9
+ /**
10
+ * @description Переопределяет сообщение об ошибке типа
11
+ * @example string.define({ typeErrorMessage: 'ИНН не может быть числом' })(inn())
12
+ */
13
+ typeErrorMessage?: string;
14
+ /**
15
+ * @description Позволяет выключать проверку на required
16
+ * @default false
17
+ */
18
+ isOptional?: boolean;
19
+ };
20
+ export type GuardValue = unknown;
4
21
  /**
5
22
  * @description Интерфейс функции guard, которая в прототипе содержит метод define
6
23
  */
@@ -28,11 +45,11 @@ export interface AsyncGuard<TLastSchemaValues extends Record<string, unknown> =
28
45
  /**
29
46
  * @description Функция, которая позволяет определять частную логику для guard
30
47
  */
31
- type GuardExecutor<AddDefOptions extends Record<string, unknown>> = (value: unknown, ctx: ValidationContext<Record<string, unknown>>, defOptions: GuardDefOptions<AddDefOptions>) => ValidationResult;
48
+ type GuardExecutor<TLastSchemaValues extends Record<string, unknown>, AddDefOptions extends Record<string, unknown>> = (value: unknown, ctx: ValidationContext<TLastSchemaValues>, defOptions: GuardDefOptions<AddDefOptions>) => ValidationResult;
32
49
  /**
33
50
  * @description Функция, которая позволяет определять частную логику для guard
34
51
  */
35
- type AsyncGuardExecutor<AddDefOptions extends Record<string, unknown>> = (value: unknown, ctx: ValidationContext<Record<string, unknown>>, defOptions: GuardDefOptions<AddDefOptions>) => Promise<ValidationResult>;
52
+ type AsyncGuardExecutor<TLastSchemaValues extends Record<string, unknown>, AddDefOptions extends Record<string, unknown>> = (value: unknown, ctx: ValidationContext<TLastSchemaValues>, defOptions: GuardDefOptions<AddDefOptions>) => Promise<ValidationResult>;
36
53
  /**
37
54
  * @description Создает guard. Guard - функция, проверяющая тип значения
38
55
  * По-дефолту проверяет value на required. Для выключения required необходимо использовать optional().
@@ -49,6 +66,6 @@ type AsyncGuardExecutor<AddDefOptions extends Record<string, unknown>> = (value:
49
66
  * });
50
67
  * ```
51
68
  */
52
- export declare function createGuard<TLastSchemaValues extends Record<string, unknown>, AddDefOptions extends Record<string, unknown> = {}>(executor: GuardExecutor<AddDefOptions>): Guard<TLastSchemaValues, AddDefOptions>;
53
- export declare function createGuard<TLastSchemaValues extends Record<string, unknown>, AddDefOptions extends Record<string, unknown> = {}>(executor: AsyncGuardExecutor<AddDefOptions>): AsyncGuard<TLastSchemaValues, AddDefOptions>;
69
+ export declare function createGuard<TLastSchemaValues extends Record<string, unknown>, AddDefOptions extends Record<string, unknown> = {}>(executor: GuardExecutor<TLastSchemaValues, AddDefOptions>): Guard<TLastSchemaValues, AddDefOptions>;
70
+ export declare function createGuard<TLastSchemaValues extends Record<string, unknown>, AddDefOptions extends Record<string, unknown> = {}>(executor: AsyncGuardExecutor<TLastSchemaValues, AddDefOptions>): AsyncGuard<TLastSchemaValues, AddDefOptions>;
54
71
  export {};
@@ -4,16 +4,20 @@ export function createGuard(executor) {
4
4
  // выделено в отдельную именованную функцию для того, чтобы ее можно было рекурсивно вызывать в define
5
5
  const createInnerGuard = (defOptions = {}) => {
6
6
  const guard = (value, prevCtx) => {
7
+ const actualDefOptions = Object.assign(Object.assign({}, defOptions), { isOptional: (prevCtx === null || prevCtx === void 0 ? void 0 : prevCtx.isOptional) || defOptions.isOptional });
7
8
  const ctx = createContext(prevCtx,
8
9
  // при создании контекста сейчас не имеет значение какого типа будет ctx.values
9
- value);
10
+ value, {
11
+ lastSchemaValue: value,
12
+ isOptional: false,
13
+ });
10
14
  const requiredResult = required({
11
- message: defOptions === null || defOptions === void 0 ? void 0 : defOptions.requiredErrorMessage,
15
+ message: actualDefOptions === null || actualDefOptions === void 0 ? void 0 : actualDefOptions.requiredErrorMessage,
12
16
  })(value, ctx);
13
- if ((defOptions === null || defOptions === void 0 ? void 0 : defOptions.isOptional) && requiredResult) {
17
+ if ((actualDefOptions === null || actualDefOptions === void 0 ? void 0 : actualDefOptions.isOptional) && requiredResult) {
14
18
  return undefined;
15
19
  }
16
- return requiredResult || executor(value, ctx, defOptions);
20
+ return requiredResult || executor(value, ctx, actualDefOptions);
17
21
  };
18
22
  guard.define = (overridesDefOptions) => createInnerGuard(overridesDefOptions);
19
23
  return guard;
package/object/object.js CHANGED
@@ -27,7 +27,9 @@ import { OBJECT_TYPE_ERROR_INFO } from './constants';
27
27
  * ```
28
28
  */
29
29
  export const object = (schema) => createGuard((value, ctx, { typeErrorMessage, isPartial }) => {
30
- const context = createContext(ctx, value, value);
30
+ const context = createContext(ctx, value, {
31
+ lastSchemaValue: value,
32
+ });
31
33
  if (!isPlainObject(value)) {
32
34
  return context.createError(Object.assign(Object.assign({}, OBJECT_TYPE_ERROR_INFO), { message: typeErrorMessage || OBJECT_TYPE_ERROR_INFO.message }));
33
35
  }
@@ -45,7 +45,9 @@ import { OBJECT_TYPE_ERROR_INFO } from '../constants';
45
45
  * ```
46
46
  */
47
47
  export const objectAsync = (schema) => createGuard((value, ctx, { typeErrorMessage, isPartial }) => __awaiter(void 0, void 0, void 0, function* () {
48
- const context = createContext(ctx, value, value);
48
+ const context = createContext(ctx, value, {
49
+ lastSchemaValue: value,
50
+ });
49
51
  if (!isPlainObject(value)) {
50
52
  return context.createError(Object.assign(Object.assign({}, OBJECT_TYPE_ERROR_INFO), { message: typeErrorMessage || OBJECT_TYPE_ERROR_INFO.message }));
51
53
  }
@@ -1,7 +1,6 @@
1
- import { Guard } from '../core';
1
+ import { IndependentValidationRule, ValidationRule } from '../core';
2
2
  /**
3
3
  * @description Выключает проверку на required в guard
4
- * @param guard - правило, проверяющее тип значения
5
4
  * @example object({ name: optional(string(min(22))) })
6
5
  */
7
- export declare const optional: <TLastSchemaValues extends Record<string, unknown>>(guard: Guard<TLastSchemaValues, {}>) => Guard<TLastSchemaValues, {}>;
6
+ export declare const optional: <TLastSchemaValues extends Record<string, unknown>>(rule: ValidationRule<unknown, TLastSchemaValues>) => IndependentValidationRule<unknown, TLastSchemaValues>;
@@ -1,6 +1,6 @@
1
+ import { callRule, createContext, } from '../core';
1
2
  /**
2
3
  * @description Выключает проверку на required в guard
3
- * @param guard - правило, проверяющее тип значения
4
4
  * @example object({ name: optional(string(min(22))) })
5
5
  */
6
- export const optional = (guard) => guard.define({ isOptional: true });
6
+ export const optional = (rule) => (value, ctx) => callRule(rule, value, createContext(ctx, value, { isOptional: true }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astral/validations",
3
- "version": "4.7.0",
3
+ "version": "4.8.0",
4
4
  "browser": "./index.js",
5
5
  "main": "./index.js",
6
6
  "dependencies": {
@@ -1,18 +0,0 @@
1
- export type GuardDefOptions<AddDefOptions extends Record<string, unknown>> = Partial<AddDefOptions> & {
2
- /**
3
- * @description Переопределяет дефолтное сообщения ошибки для required
4
- * @example string.define({ requiredMessage: 'ИНН не может быть пустым' })(inn())
5
- */
6
- requiredErrorMessage?: string;
7
- /**
8
- * @description Переопределяет сообщение об ошибке типа
9
- * @example string.define({ typeErrorMessage: 'ИНН не может быть числом' })(inn())
10
- */
11
- typeErrorMessage?: string;
12
- /**
13
- * @description Позволяет выключать проверку на required
14
- * @default false
15
- */
16
- isOptional?: boolean;
17
- };
18
- export type GuardValue = unknown;
@@ -1 +0,0 @@
1
- export {};