@astral/validations 4.7.0 → 4.8.1
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 +34 -1
- package/core/context/createContext/createContext.d.ts +13 -2
- package/core/context/createContext/createContext.js +8 -7
- package/core/context/types.d.ts +6 -2
- package/core/guard/createGuard/createGuard.d.ts +22 -5
- package/core/guard/createGuard/createGuard.js +8 -4
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/object/object.js +3 -1
- package/object/objectAsync/objectAsync.js +3 -1
- package/optional/index.d.ts +1 -0
- package/optional/index.js +1 -0
- package/optional/optional.d.ts +2 -3
- package/optional/optional.js +2 -2
- package/optional/optionalAsync/index.d.ts +1 -0
- package/optional/optionalAsync/index.js +1 -0
- package/optional/optionalAsync/optionalAsync.d.ts +6 -0
- package/optional/optionalAsync/optionalAsync.js +18 -0
- package/package.json +1 -1
- package/core/guard/types.d.ts +0 -18
- package/core/guard/types.js +0 -1
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. Условная валидация
|
@@ -1471,6 +1491,7 @@ validate(new Date())
|
|
1471
1491
|
Guard, поддерживающие асинхронную валидацию имеют постфиксы ```async```:
|
1472
1492
|
- ```objectAsync```
|
1473
1493
|
- ```stringAsync```
|
1494
|
+
- ```optionalAsync```
|
1474
1495
|
|
1475
1496
|
Пример:
|
1476
1497
|
|
@@ -1494,9 +1515,21 @@ const validate = objectAsync<Values>({
|
|
1494
1515
|
message: 'Nickname занят',
|
1495
1516
|
});
|
1496
1517
|
}),
|
1518
|
+
fullName: optionalAsync(stringAsync(async (value, ctx) => {
|
1519
|
+
const nicknameIsAvailable = await checkNickname(value);
|
1520
|
+
|
1521
|
+
if (nicknameIsAvailable) {
|
1522
|
+
return undefined;
|
1523
|
+
}
|
1524
|
+
|
1525
|
+
return ctx.createError({
|
1526
|
+
code: 'nickname-available',
|
1527
|
+
message: 'Nickname занят',
|
1528
|
+
});
|
1529
|
+
})),
|
1497
1530
|
});
|
1498
1531
|
|
1499
|
-
const result = await validate({ phone: '79308999999', nickname: 'Vasya' });
|
1532
|
+
const result = await validate({ phone: '79308999999', nickname: 'Vasya', fullName: '' });
|
1500
1533
|
|
1501
1534
|
// { nickname: 'Nickname занят' }
|
1502
1535
|
toPrettyError(result);
|
@@ -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<
|
8
|
-
export
|
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
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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:
|
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:
|
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
|
}
|
package/core/context/types.d.ts
CHANGED
@@ -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
|
-
|
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<
|
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<
|
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:
|
15
|
+
message: actualDefOptions === null || actualDefOptions === void 0 ? void 0 : actualDefOptions.requiredErrorMessage,
|
12
16
|
})(value, ctx);
|
13
|
-
if ((
|
17
|
+
if ((actualDefOptions === null || actualDefOptions === void 0 ? void 0 : actualDefOptions.isOptional) && requiredResult) {
|
14
18
|
return undefined;
|
15
19
|
}
|
16
|
-
return requiredResult || executor(value, ctx,
|
20
|
+
return requiredResult || executor(value, ctx, actualDefOptions);
|
17
21
|
};
|
18
22
|
guard.define = (overridesDefOptions) => createInnerGuard(overridesDefOptions);
|
19
23
|
return guard;
|
package/index.d.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
export { object, objectAsync, OBJECT_TYPE_ERROR_INFO, type Schema, type SchemaValue, type ObjectGuard, type ObjectAsyncGuard, } from './object';
|
2
|
-
export { optional } from './optional';
|
2
|
+
export { optional, optionalAsync } from './optional';
|
3
3
|
export { string, STRING_TYPE_ERROR_INFO, stringAsync } from './string';
|
4
4
|
export { date, INVALID_DATE_ERROR_INFO, DATE_TYPE_ERROR_INFO } from './date';
|
5
5
|
export { number, NAN_NUMBER_ERROR_INFO, NUMBER_TYPE_ERROR_INFO, INFINITY_NUMBER_ERROR_INFO, } from './number';
|
package/index.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
export { object, objectAsync, OBJECT_TYPE_ERROR_INFO, } from './object';
|
2
|
-
export { optional } from './optional';
|
2
|
+
export { optional, optionalAsync } from './optional';
|
3
3
|
export { string, STRING_TYPE_ERROR_INFO, stringAsync } from './string';
|
4
4
|
export { date, INVALID_DATE_ERROR_INFO, DATE_TYPE_ERROR_INFO } from './date';
|
5
5
|
export { number, NAN_NUMBER_ERROR_INFO, NUMBER_TYPE_ERROR_INFO, INFINITY_NUMBER_ERROR_INFO, } from './number';
|
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,
|
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,
|
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
|
}
|
package/optional/index.d.ts
CHANGED
package/optional/index.js
CHANGED
package/optional/optional.d.ts
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
import {
|
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>>(
|
6
|
+
export declare const optional: <TLastSchemaValues extends Record<string, unknown>>(rule: ValidationRule<unknown, TLastSchemaValues>) => IndependentValidationRule<unknown, TLastSchemaValues>;
|
package/optional/optional.js
CHANGED
@@ -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 = (
|
6
|
+
export const optional = (rule) => (value, ctx) => callRule(rule, value, createContext(ctx, value, { isOptional: true }));
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from './optionalAsync';
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from './optionalAsync';
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { AsyncIndependentValidationRule, AsyncValidationRule } from '../../core';
|
2
|
+
/**
|
3
|
+
* @description Выключает проверку на required в guard. Предназначен для асинхронных правил.
|
4
|
+
* @example object({ name: optionalAsync(stringAsync(min(22))) })
|
5
|
+
*/
|
6
|
+
export declare const optionalAsync: <TLastSchemaValues extends Record<string, unknown>>(rule: AsyncValidationRule<unknown, TLastSchemaValues>) => AsyncIndependentValidationRule<unknown, TLastSchemaValues>;
|
@@ -0,0 +1,18 @@
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
8
|
+
});
|
9
|
+
};
|
10
|
+
import { callAsyncRule, createContext, } from '../../core';
|
11
|
+
// TODO: необходимо добавить возможность использовать вложенные guards
|
12
|
+
/**
|
13
|
+
* @description Выключает проверку на required в guard. Предназначен для асинхронных правил.
|
14
|
+
* @example object({ name: optionalAsync(stringAsync(min(22))) })
|
15
|
+
*/
|
16
|
+
export const optionalAsync = (rule) => (value, ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
17
|
+
return callAsyncRule(rule, value, createContext(ctx, value, { isOptional: true }));
|
18
|
+
});
|
package/package.json
CHANGED
package/core/guard/types.d.ts
DELETED
@@ -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;
|
package/core/guard/types.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export {};
|