@oscarpalmer/jhunal 0.22.0 → 0.23.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/dist/constants.d.mts +7 -3
- package/dist/constants.mjs +34 -12
- package/dist/helpers/message.helper.d.mts +11 -0
- package/dist/helpers/message.helper.mjs +70 -0
- package/dist/helpers/misc.helper.d.mts +22 -0
- package/dist/helpers/misc.helper.mjs +56 -0
- package/dist/index.d.mts +304 -275
- package/dist/index.mjs +187 -154
- package/dist/models/validation.model.d.mts +18 -7
- package/dist/schematic.d.mts +25 -7
- package/dist/schematic.mjs +6 -4
- package/dist/validator/base.validator.d.mts +6 -0
- package/dist/validator/base.validator.mjs +19 -0
- package/dist/validator/function.validator.d.mts +6 -0
- package/dist/validator/function.validator.mjs +9 -0
- package/dist/validator/named.handler.d.mts +6 -0
- package/dist/validator/named.handler.mjs +22 -0
- package/dist/validator/named.validator.d.mts +7 -0
- package/dist/validator/named.validator.mjs +39 -0
- package/dist/validator/object.validator.d.mts +7 -0
- package/dist/{validation.mjs → validator/object.validator.mjs} +20 -98
- package/dist/validator/schematic.validator.d.mts +7 -0
- package/dist/validator/schematic.validator.mjs +16 -0
- package/package.json +1 -1
- package/src/constants.ts +42 -10
- package/src/helpers/message.helper.ts +152 -0
- package/src/helpers/misc.helper.ts +93 -0
- package/src/index.ts +3 -3
- package/src/models/validation.model.ts +19 -6
- package/src/schematic.ts +43 -16
- package/src/validator/base.validator.ts +31 -0
- package/src/validator/function.validator.ts +9 -0
- package/src/validator/named.handler.ts +50 -0
- package/src/validator/named.validator.ts +62 -0
- package/src/{validation.ts → validator/object.validator.ts} +23 -181
- package/src/validator/schematic.validator.ts +25 -0
- package/dist/helpers.d.mts +0 -28
- package/dist/helpers.mjs +0 -120
- package/dist/validation.d.mts +0 -7
- package/src/helpers.ts +0 -249
package/src/index.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export {instanceOf, isSchematic} from './helpers';
|
|
1
|
+
export {instanceOf, isSchematic} from './helpers/misc.helper';
|
|
2
2
|
export type {Schema} from './models/schema.plain.model';
|
|
3
3
|
export type {TypedSchema} from './models/schema.typed.model';
|
|
4
4
|
export {
|
|
5
5
|
SchematicError,
|
|
6
6
|
ValidationError,
|
|
7
|
-
type
|
|
8
|
-
type
|
|
7
|
+
type GetOptions,
|
|
8
|
+
type IsOptions,
|
|
9
9
|
} from './models/validation.model';
|
|
10
10
|
export {schematic, type Schematic} from './schematic';
|
|
@@ -91,20 +91,32 @@ export type ValidationInformationKey = {
|
|
|
91
91
|
|
|
92
92
|
// #region Options
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
* Options for validation
|
|
96
|
-
*/
|
|
97
|
-
export type ValidationOptions<Errors extends ReportingType> = {
|
|
94
|
+
type BaseOptions<Errors extends ReportingType> = {
|
|
98
95
|
/**
|
|
99
96
|
* How should validation failures be reported; see {@link ReportingType} _(defaults to `'none'`)_
|
|
100
97
|
*/
|
|
101
|
-
errors
|
|
98
|
+
errors: Errors;
|
|
102
99
|
/**
|
|
103
100
|
* Validate if unknown keys are present in the object? _(defaults to `false`)_
|
|
104
101
|
*/
|
|
105
102
|
strict?: boolean;
|
|
106
103
|
};
|
|
107
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Options for validating and getting a value from an input
|
|
107
|
+
*/
|
|
108
|
+
export type GetOptions<Errors extends ReportingType> = BaseOptions<Errors> & {
|
|
109
|
+
/**
|
|
110
|
+
* Get a deeply cloned version of the input? _(defaults to `true`)_
|
|
111
|
+
*/
|
|
112
|
+
clone?: boolean;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Options for validation an input value
|
|
117
|
+
*/
|
|
118
|
+
export type IsOptions<Errors extends ReportingType> = BaseOptions<Errors>;
|
|
119
|
+
|
|
108
120
|
// #endregion
|
|
109
121
|
|
|
110
122
|
// #region Validator
|
|
@@ -113,9 +125,10 @@ export type Validator = (
|
|
|
113
125
|
input: unknown,
|
|
114
126
|
parameters: ValidatorParameters,
|
|
115
127
|
get: boolean,
|
|
116
|
-
) =>
|
|
128
|
+
) => true | ValidationInformation[];
|
|
117
129
|
|
|
118
130
|
export type ValidatorParameters = {
|
|
131
|
+
clone: boolean;
|
|
119
132
|
information?: ValidationInformation[];
|
|
120
133
|
output: PlainObject;
|
|
121
134
|
reporting: ReportingInformation;
|
package/src/schematic.ts
CHANGED
|
@@ -3,17 +3,18 @@ import type {PlainObject} from '@oscarpalmer/atoms/models';
|
|
|
3
3
|
import {error, ok} from '@oscarpalmer/atoms/result/misc';
|
|
4
4
|
import type {Result} from '@oscarpalmer/atoms/result/models';
|
|
5
5
|
import {PROPERTY_SCHEMATIC, SCHEMATIC_MESSAGE_SCHEMA_INVALID_TYPE} from './constants';
|
|
6
|
-
import {getParameters, isSchematic} from './helpers';
|
|
6
|
+
import {getParameters, isSchematic} from './helpers/misc.helper';
|
|
7
7
|
import type {Infer} from './models/infer.model';
|
|
8
8
|
import type {Schema} from './models/schema.plain.model';
|
|
9
9
|
import type {TypedSchema} from './models/schema.typed.model';
|
|
10
10
|
import {
|
|
11
11
|
SchematicError,
|
|
12
|
+
type GetOptions,
|
|
13
|
+
type IsOptions,
|
|
12
14
|
type ValidationInformation,
|
|
13
|
-
type ValidationOptions,
|
|
14
15
|
type Validator,
|
|
15
16
|
} from './models/validation.model';
|
|
16
|
-
import {getObjectValidator} from './
|
|
17
|
+
import {getObjectValidator} from './validator/object.validator';
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* A schematic for validating objects
|
|
@@ -41,7 +42,7 @@ export class Schematic<Model> {
|
|
|
41
42
|
* @param options Validation options
|
|
42
43
|
* @returns Deeply cloned version of the value if it matches the schema, otherwise throws an error
|
|
43
44
|
*/
|
|
44
|
-
get(value: unknown, options:
|
|
45
|
+
get(value: unknown, options: GetOptions<'throw'>): Model;
|
|
45
46
|
|
|
46
47
|
/**
|
|
47
48
|
* Parse a value according to the schema
|
|
@@ -61,7 +62,7 @@ export class Schematic<Model> {
|
|
|
61
62
|
* @param options Validation options
|
|
62
63
|
* @returns Result holding deeply cloned value or all validation information
|
|
63
64
|
*/
|
|
64
|
-
get(value: unknown, options:
|
|
65
|
+
get(value: unknown, options: GetOptions<'all'>): Result<Model, ValidationInformation[]>;
|
|
65
66
|
|
|
66
67
|
/**
|
|
67
68
|
* Parse a value according to the schema
|
|
@@ -81,7 +82,7 @@ export class Schematic<Model> {
|
|
|
81
82
|
* @param options Validation options
|
|
82
83
|
* @returns Result holding deeply cloned value or all validation information
|
|
83
84
|
*/
|
|
84
|
-
get(value: unknown, options:
|
|
85
|
+
get(value: unknown, options: GetOptions<'first'>): Result<Model, ValidationInformation>;
|
|
85
86
|
|
|
86
87
|
/**
|
|
87
88
|
* Parse a value according to the schema
|
|
@@ -93,6 +94,16 @@ export class Schematic<Model> {
|
|
|
93
94
|
*/
|
|
94
95
|
get(value: unknown, errors: 'first'): Result<Model, ValidationInformation>;
|
|
95
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Parse a value according to the schema
|
|
99
|
+
*
|
|
100
|
+
* Returns a deeply cloned version of the value or `undefined` if the value does not match the schema
|
|
101
|
+
* @param value Value to parse
|
|
102
|
+
* @param options Validation options
|
|
103
|
+
* @returns Deeply cloned value, or `undefined` if it's invalid
|
|
104
|
+
*/
|
|
105
|
+
get(value: unknown, options: GetOptions<'none'>): Model | undefined;
|
|
106
|
+
|
|
96
107
|
/**
|
|
97
108
|
* Parse a value according to the schema
|
|
98
109
|
*
|
|
@@ -108,14 +119,16 @@ export class Schematic<Model> {
|
|
|
108
119
|
|
|
109
120
|
const result = this.#validator(value, parameters, true);
|
|
110
121
|
|
|
111
|
-
if (
|
|
112
|
-
return parameters.reporting.none
|
|
113
|
-
?
|
|
114
|
-
? parameters.output
|
|
115
|
-
: undefined
|
|
122
|
+
if (result === true) {
|
|
123
|
+
return parameters.reporting.none || parameters.reporting.throw
|
|
124
|
+
? parameters.output
|
|
116
125
|
: ok(parameters.output);
|
|
117
126
|
}
|
|
118
127
|
|
|
128
|
+
if (parameters.reporting.none) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
119
132
|
return error(parameters.reporting.all ? result : result[0]);
|
|
120
133
|
}
|
|
121
134
|
|
|
@@ -127,7 +140,7 @@ export class Schematic<Model> {
|
|
|
127
140
|
* @param options Validation options
|
|
128
141
|
* @returns `true` if the value matches the schema, otherwise throws an error
|
|
129
142
|
*/
|
|
130
|
-
is(value: unknown, options:
|
|
143
|
+
is(value: unknown, options: IsOptions<'throw'>): asserts value is Model;
|
|
131
144
|
|
|
132
145
|
/**
|
|
133
146
|
* Does the value match the schema?
|
|
@@ -147,7 +160,7 @@ export class Schematic<Model> {
|
|
|
147
160
|
* @param options Validation options
|
|
148
161
|
* @returns Result holding `true` or all validation information
|
|
149
162
|
*/
|
|
150
|
-
is(value: unknown, options:
|
|
163
|
+
is(value: unknown, options: IsOptions<'all'>): Result<true, ValidationInformation[]>;
|
|
151
164
|
|
|
152
165
|
/**
|
|
153
166
|
* Does the value match the schema?
|
|
@@ -167,7 +180,7 @@ export class Schematic<Model> {
|
|
|
167
180
|
* @param options Validation options
|
|
168
181
|
* @returns `true` if the value matches the schema, otherwise `false`
|
|
169
182
|
*/
|
|
170
|
-
is(value: unknown, options:
|
|
183
|
+
is(value: unknown, options: IsOptions<'first'>): Result<true, ValidationInformation>;
|
|
171
184
|
|
|
172
185
|
/**
|
|
173
186
|
* Does the value match the schema?
|
|
@@ -179,6 +192,16 @@ export class Schematic<Model> {
|
|
|
179
192
|
*/
|
|
180
193
|
is(value: unknown, errors: 'first'): Result<true, ValidationInformation>;
|
|
181
194
|
|
|
195
|
+
/**
|
|
196
|
+
* Does the value match the schema?
|
|
197
|
+
*
|
|
198
|
+
* Will validate that the value matches the schema and return `true` or `false`, without any validation information for validation failures
|
|
199
|
+
* @param value Value to validate
|
|
200
|
+
* @param options Validation options
|
|
201
|
+
* @returns `true` if the value matches the schema, otherwise `false`
|
|
202
|
+
*/
|
|
203
|
+
is(value: unknown, options: IsOptions<'none'>): value is Model;
|
|
204
|
+
|
|
182
205
|
/**
|
|
183
206
|
* Does the value match the schema?
|
|
184
207
|
*
|
|
@@ -194,8 +217,12 @@ export class Schematic<Model> {
|
|
|
194
217
|
|
|
195
218
|
const result = this.#validator(value, parameters, false);
|
|
196
219
|
|
|
197
|
-
if (
|
|
198
|
-
return parameters.reporting.none ? result : ok(result);
|
|
220
|
+
if (result === true) {
|
|
221
|
+
return parameters.reporting.none || parameters.reporting.throw ? result : ok(result);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (parameters.reporting.none) {
|
|
225
|
+
return false;
|
|
199
226
|
}
|
|
200
227
|
|
|
201
228
|
return error(parameters.reporting.all ? result : result[0]);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type {ValidationInformation, Validator} from '../models/validation.model';
|
|
2
|
+
|
|
3
|
+
export function getBaseValidator(validators: Validator[]): Validator {
|
|
4
|
+
const {length} = validators;
|
|
5
|
+
|
|
6
|
+
return (input, parameters, get) => {
|
|
7
|
+
const allInformation: ValidationInformation[] = [];
|
|
8
|
+
|
|
9
|
+
for (let index = 0; index < length; index += 1) {
|
|
10
|
+
const previousInformation = parameters.information;
|
|
11
|
+
|
|
12
|
+
const nextInformation: ValidationInformation[] = [];
|
|
13
|
+
|
|
14
|
+
parameters.information = nextInformation;
|
|
15
|
+
|
|
16
|
+
const result = validators[index](input, parameters, get);
|
|
17
|
+
|
|
18
|
+
parameters.information = previousInformation;
|
|
19
|
+
|
|
20
|
+
if (result === true) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
parameters.information?.push(...result);
|
|
25
|
+
|
|
26
|
+
allInformation.push(...result);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return allInformation;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import {isConstructor} from '@oscarpalmer/atoms/is';
|
|
2
|
+
import {instanceOf} from '../helpers/misc.helper';
|
|
3
|
+
import type {Validator} from '../models/validation.model';
|
|
4
|
+
|
|
5
|
+
export function getFunctionValidator(fn: Function): Validator {
|
|
6
|
+
const validator = isConstructor(fn) ? instanceOf(fn) : fn;
|
|
7
|
+
|
|
8
|
+
return input => (validator(input) ? true : []);
|
|
9
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
2
|
+
import {
|
|
3
|
+
SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY,
|
|
4
|
+
SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE,
|
|
5
|
+
SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE,
|
|
6
|
+
TEMPLATE_PATTERN,
|
|
7
|
+
TYPE_ALL,
|
|
8
|
+
} from '../constants';
|
|
9
|
+
import type {ValueName} from '../models/misc.model';
|
|
10
|
+
import type {NamedValidatorHandlers} from '../models/validation.model';
|
|
11
|
+
|
|
12
|
+
export function getNamedHandlers(original: unknown, prefix: string): NamedValidatorHandlers {
|
|
13
|
+
const handlers: NamedValidatorHandlers = {};
|
|
14
|
+
|
|
15
|
+
if (original == null) {
|
|
16
|
+
return handlers;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (!isPlainObject(original)) {
|
|
20
|
+
throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const keys = Object.keys(original);
|
|
24
|
+
const {length} = keys;
|
|
25
|
+
|
|
26
|
+
for (let index = 0; index < length; index += 1) {
|
|
27
|
+
const key = keys[index];
|
|
28
|
+
|
|
29
|
+
if (!TYPE_ALL.has(key as never)) {
|
|
30
|
+
throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY.replace(TEMPLATE_PATTERN, key));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const value = original[key];
|
|
34
|
+
|
|
35
|
+
handlers[key as ValueName] = (Array.isArray(value) ? value : [value]).map(item => {
|
|
36
|
+
if (typeof item !== 'function') {
|
|
37
|
+
throw new TypeError(
|
|
38
|
+
SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE.replace(TEMPLATE_PATTERN, key).replace(
|
|
39
|
+
TEMPLATE_PATTERN,
|
|
40
|
+
prefix,
|
|
41
|
+
),
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return item;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return handlers;
|
|
50
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {TYPE_OBJECT} from '../constants';
|
|
2
|
+
import {getInvalidValidatorMessage} from '../helpers/message.helper';
|
|
3
|
+
import type {ValueName} from '../models/misc.model';
|
|
4
|
+
import type {
|
|
5
|
+
NamedValidatorHandlers,
|
|
6
|
+
NamedValidators,
|
|
7
|
+
ValidationInformation,
|
|
8
|
+
ValidationInformationKey,
|
|
9
|
+
Validator,
|
|
10
|
+
} from '../models/validation.model';
|
|
11
|
+
|
|
12
|
+
export function getNamedValidator(
|
|
13
|
+
key: ValidationInformationKey,
|
|
14
|
+
name: ValueName,
|
|
15
|
+
handlers: NamedValidatorHandlers,
|
|
16
|
+
): Validator {
|
|
17
|
+
const validator = namedValidators[name];
|
|
18
|
+
|
|
19
|
+
const named = handlers[name] ?? [];
|
|
20
|
+
const {length} = named;
|
|
21
|
+
|
|
22
|
+
return (input, parameters) => {
|
|
23
|
+
if (!validator(input)) {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
for (let index = 0; index < length; index += 1) {
|
|
28
|
+
const handler = named[index];
|
|
29
|
+
|
|
30
|
+
if (handler(input) === true) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const information: ValidationInformation = {
|
|
35
|
+
key,
|
|
36
|
+
validator,
|
|
37
|
+
message: getInvalidValidatorMessage(key.full, name, index, length),
|
|
38
|
+
value: input,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
parameters.information?.push(information);
|
|
42
|
+
|
|
43
|
+
return parameters.reporting.none ? [] : [information];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return true;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const namedValidators: NamedValidators = {
|
|
51
|
+
array: Array.isArray,
|
|
52
|
+
bigint: value => typeof value === 'bigint',
|
|
53
|
+
boolean: value => typeof value === 'boolean',
|
|
54
|
+
date: value => value instanceof Date,
|
|
55
|
+
function: value => typeof value === 'function',
|
|
56
|
+
null: value => value === null,
|
|
57
|
+
number: value => typeof value === 'number',
|
|
58
|
+
object: value => typeof value === TYPE_OBJECT && value !== null,
|
|
59
|
+
string: value => typeof value === 'string',
|
|
60
|
+
symbol: value => typeof value === 'symbol',
|
|
61
|
+
undefined: value => value === undefined,
|
|
62
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
2
|
+
import type {PlainObject} from '@oscarpalmer/atoms/models';
|
|
3
|
+
import {join} from '@oscarpalmer/atoms/string';
|
|
3
4
|
import {clone} from '@oscarpalmer/atoms/value/clone';
|
|
4
5
|
import {
|
|
5
6
|
PROPERTY_REQUIRED,
|
|
@@ -10,35 +11,32 @@ import {
|
|
|
10
11
|
SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE,
|
|
11
12
|
SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_REQUIRED,
|
|
12
13
|
SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE,
|
|
13
|
-
SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY,
|
|
14
|
-
SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE,
|
|
15
|
-
SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE,
|
|
16
14
|
TEMPLATE_PATTERN,
|
|
17
15
|
TYPE_ALL,
|
|
18
|
-
TYPE_OBJECT,
|
|
19
16
|
TYPE_UNDEFINED,
|
|
20
|
-
} from '
|
|
17
|
+
} from '../constants';
|
|
21
18
|
import {
|
|
22
19
|
getInvalidInputMessage,
|
|
23
20
|
getInvalidMissingMessage,
|
|
24
21
|
getInvalidTypeMessage,
|
|
25
|
-
getInvalidValidatorMessage,
|
|
26
22
|
getUnknownKeysMessage,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
} from '
|
|
30
|
-
import type {ValueName} from './models/misc.model';
|
|
23
|
+
} from '../helpers/message.helper';
|
|
24
|
+
import {isSchematic} from '../helpers/misc.helper';
|
|
25
|
+
import type {ValueName} from '../models/misc.model';
|
|
31
26
|
import {
|
|
27
|
+
type NamedValidatorHandlers,
|
|
32
28
|
SchematicError,
|
|
33
29
|
ValidationError,
|
|
34
|
-
type NamedValidatorHandlers,
|
|
35
|
-
type NamedValidators,
|
|
36
30
|
type ValidationInformation,
|
|
37
31
|
type ValidationInformationKey,
|
|
38
32
|
type Validator,
|
|
39
33
|
type ValidatorType,
|
|
40
|
-
} from '
|
|
41
|
-
import {
|
|
34
|
+
} from '../models/validation.model';
|
|
35
|
+
import {getBaseValidator} from './base.validator';
|
|
36
|
+
import {getFunctionValidator} from './function.validator';
|
|
37
|
+
import {getNamedHandlers} from './named.handler';
|
|
38
|
+
import {getNamedValidator} from './named.validator';
|
|
39
|
+
import {getSchematicValidator} from './schematic.validator';
|
|
42
40
|
|
|
43
41
|
function getDisallowedProperty(obj: PlainObject): string | undefined {
|
|
44
42
|
if (PROPERTY_REQUIRED in obj) {
|
|
@@ -54,90 +52,6 @@ function getDisallowedProperty(obj: PlainObject): string | undefined {
|
|
|
54
52
|
}
|
|
55
53
|
}
|
|
56
54
|
|
|
57
|
-
function getFunctionValidator(fn: Function): Validator {
|
|
58
|
-
const validator = isConstructor(fn) ? instanceOf(fn) : fn;
|
|
59
|
-
|
|
60
|
-
return input => validator(input) === true;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function getNamedValidator(
|
|
64
|
-
key: ValidationInformationKey,
|
|
65
|
-
name: ValueName,
|
|
66
|
-
handlers: NamedValidatorHandlers,
|
|
67
|
-
): Validator {
|
|
68
|
-
const validator = namedValidators[name];
|
|
69
|
-
|
|
70
|
-
const named = handlers[name] ?? [];
|
|
71
|
-
const {length} = named;
|
|
72
|
-
|
|
73
|
-
return (input, parameters) => {
|
|
74
|
-
if (!validator(input)) {
|
|
75
|
-
return false;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
for (let index = 0; index < length; index += 1) {
|
|
79
|
-
const handler = named[index];
|
|
80
|
-
|
|
81
|
-
if (handler(input) === true) {
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const information: ValidationInformation = {
|
|
86
|
-
key,
|
|
87
|
-
validator,
|
|
88
|
-
message: getInvalidValidatorMessage(key.full, name, index, length),
|
|
89
|
-
value: input,
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
parameters.information?.push(information);
|
|
93
|
-
|
|
94
|
-
return parameters.reporting.none ? false : [information];
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return true;
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function getNamedHandlers(original: unknown, prefix: string): NamedValidatorHandlers {
|
|
102
|
-
const handlers: NamedValidatorHandlers = {};
|
|
103
|
-
|
|
104
|
-
if (original == null) {
|
|
105
|
-
return handlers;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
if (!isPlainObject(original)) {
|
|
109
|
-
throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const keys = Object.keys(original);
|
|
113
|
-
const {length} = keys;
|
|
114
|
-
|
|
115
|
-
for (let index = 0; index < length; index += 1) {
|
|
116
|
-
const key = keys[index];
|
|
117
|
-
|
|
118
|
-
if (!TYPE_ALL.has(key as never)) {
|
|
119
|
-
throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY.replace(TEMPLATE_PATTERN, key));
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const value = (original as PlainObject)[key];
|
|
123
|
-
|
|
124
|
-
handlers[key as ValueName] = (Array.isArray(value) ? value : [value]).map(item => {
|
|
125
|
-
if (typeof item !== 'function') {
|
|
126
|
-
throw new TypeError(
|
|
127
|
-
SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE.replace(TEMPLATE_PATTERN, key).replace(
|
|
128
|
-
TEMPLATE_PATTERN,
|
|
129
|
-
prefix,
|
|
130
|
-
),
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return item;
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return handlers;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
55
|
export function getObjectValidator(
|
|
142
56
|
original: PlainObject,
|
|
143
57
|
origin?: ValidationInformationKey,
|
|
@@ -263,7 +177,7 @@ export function getObjectValidator(
|
|
|
263
177
|
types,
|
|
264
178
|
key: fullKey,
|
|
265
179
|
required: required && !types.includes(TYPE_UNDEFINED),
|
|
266
|
-
validator:
|
|
180
|
+
validator: getBaseValidator(validators),
|
|
267
181
|
});
|
|
268
182
|
}
|
|
269
183
|
|
|
@@ -272,7 +186,7 @@ export function getObjectValidator(
|
|
|
272
186
|
return (input, parameters, get) => {
|
|
273
187
|
if (!isPlainObject(input)) {
|
|
274
188
|
if (origin != null) {
|
|
275
|
-
return
|
|
189
|
+
return [];
|
|
276
190
|
}
|
|
277
191
|
|
|
278
192
|
const information: ValidationInformation = {
|
|
@@ -290,7 +204,7 @@ export function getObjectValidator(
|
|
|
290
204
|
|
|
291
205
|
parameters.information?.push(information);
|
|
292
206
|
|
|
293
|
-
return
|
|
207
|
+
return [information];
|
|
294
208
|
}
|
|
295
209
|
|
|
296
210
|
if (parameters.strict) {
|
|
@@ -313,7 +227,7 @@ export function getObjectValidator(
|
|
|
313
227
|
|
|
314
228
|
parameters.information?.push(information);
|
|
315
229
|
|
|
316
|
-
return
|
|
230
|
+
return [information];
|
|
317
231
|
}
|
|
318
232
|
}
|
|
319
233
|
|
|
@@ -328,7 +242,7 @@ export function getObjectValidator(
|
|
|
328
242
|
if (value === undefined) {
|
|
329
243
|
if (required) {
|
|
330
244
|
if (parameters.reporting.none) {
|
|
331
|
-
return
|
|
245
|
+
return [];
|
|
332
246
|
}
|
|
333
247
|
|
|
334
248
|
const information: ValidationInformation = {
|
|
@@ -363,20 +277,16 @@ export function getObjectValidator(
|
|
|
363
277
|
|
|
364
278
|
parameters.output = previousOutput;
|
|
365
279
|
|
|
366
|
-
if (result === false) {
|
|
367
|
-
continue;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
280
|
if (result === true) {
|
|
371
|
-
if (get) {
|
|
372
|
-
output[key.short] = clone(value);
|
|
281
|
+
if (get && !isPlainObject(value)) {
|
|
282
|
+
output[key.short] = parameters.clone ? clone(value) : value;
|
|
373
283
|
}
|
|
374
284
|
|
|
375
285
|
continue;
|
|
376
286
|
}
|
|
377
287
|
|
|
378
288
|
if (parameters.reporting.none) {
|
|
379
|
-
return
|
|
289
|
+
return [];
|
|
380
290
|
}
|
|
381
291
|
|
|
382
292
|
const information: ValidationInformation[] =
|
|
@@ -411,7 +321,7 @@ export function getObjectValidator(
|
|
|
411
321
|
}
|
|
412
322
|
}
|
|
413
323
|
|
|
414
|
-
return
|
|
324
|
+
return allInformation.length === 0 ? true : allInformation;
|
|
415
325
|
};
|
|
416
326
|
}
|
|
417
327
|
|
|
@@ -428,71 +338,3 @@ function getRequired(key: string, obj: PlainObject): boolean | undefined {
|
|
|
428
338
|
|
|
429
339
|
return obj[PROPERTY_REQUIRED];
|
|
430
340
|
}
|
|
431
|
-
|
|
432
|
-
function getSchematicValidator(schematic: Schematic<unknown>): Validator {
|
|
433
|
-
const validator = schematicValidator.get(schematic)!;
|
|
434
|
-
|
|
435
|
-
return (input, parameters, get) => {
|
|
436
|
-
let result: ReturnType<Validator> = false;
|
|
437
|
-
|
|
438
|
-
if (isPlainObject(input)) {
|
|
439
|
-
result = validator(input, parameters, get);
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
if (typeof result === 'boolean') {
|
|
443
|
-
return result;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
parameters.information?.push(...result);
|
|
447
|
-
|
|
448
|
-
return result.length === 0 ? true : result;
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
function getValidator(validators: Validator[]): Validator {
|
|
453
|
-
const {length} = validators;
|
|
454
|
-
|
|
455
|
-
return (input, parameters, get) => {
|
|
456
|
-
const allInformation: ValidationInformation[] = [];
|
|
457
|
-
|
|
458
|
-
for (let index = 0; index < length; index += 1) {
|
|
459
|
-
const previousInformation = parameters.information;
|
|
460
|
-
|
|
461
|
-
const nextInformation: ValidationInformation[] = [];
|
|
462
|
-
|
|
463
|
-
parameters.information = nextInformation;
|
|
464
|
-
|
|
465
|
-
const result = validators[index](input, parameters, get);
|
|
466
|
-
|
|
467
|
-
parameters.information = previousInformation;
|
|
468
|
-
|
|
469
|
-
if (result === false) {
|
|
470
|
-
continue;
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
if (result === true) {
|
|
474
|
-
return true;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
parameters.information?.push(...result);
|
|
478
|
-
|
|
479
|
-
allInformation.push(...result);
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
return allInformation;
|
|
483
|
-
};
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
const namedValidators: NamedValidators = {
|
|
487
|
-
array: Array.isArray,
|
|
488
|
-
bigint: value => typeof value === 'bigint',
|
|
489
|
-
boolean: value => typeof value === 'boolean',
|
|
490
|
-
date: value => value instanceof Date,
|
|
491
|
-
function: value => typeof value === 'function',
|
|
492
|
-
null: value => value === null,
|
|
493
|
-
number: value => typeof value === 'number',
|
|
494
|
-
object: value => typeof value === TYPE_OBJECT && value !== null,
|
|
495
|
-
string: value => typeof value === 'string',
|
|
496
|
-
symbol: value => typeof value === 'symbol',
|
|
497
|
-
undefined: value => value === undefined,
|
|
498
|
-
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
2
|
+
import type {Validator} from '../models/validation.model';
|
|
3
|
+
import {Schematic, schematicValidator} from '../schematic';
|
|
4
|
+
|
|
5
|
+
export function getSchematicValidator(schematic: Schematic<unknown>): Validator {
|
|
6
|
+
const validator = schematicValidator.get(schematic)!;
|
|
7
|
+
|
|
8
|
+
return (input, parameters, get) => {
|
|
9
|
+
let result: ReturnType<Validator>;
|
|
10
|
+
|
|
11
|
+
if (isPlainObject(input)) {
|
|
12
|
+
result = validator(input, parameters, get);
|
|
13
|
+
} else {
|
|
14
|
+
result = [];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (result === true) {
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
parameters.information?.push(...result);
|
|
22
|
+
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
}
|