@oscarpalmer/jhunal 0.20.0 → 0.21.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/helpers.d.mts +6 -9
- package/dist/helpers.mjs +13 -10
- package/dist/index.d.mts +78 -21
- package/dist/index.mjs +103 -77
- package/dist/models/validation.model.d.mts +13 -15
- package/dist/schematic.d.mts +72 -9
- package/dist/schematic.mjs +14 -9
- package/dist/validation/property.validation.mjs +2 -6
- package/dist/validation/value.validation.d.mts +3 -2
- package/dist/validation/value.validation.mjs +76 -54
- package/package.json +52 -52
- package/src/helpers.ts +22 -16
- package/src/models/validation.model.ts +12 -15
- package/src/schematic.ts +106 -16
- package/src/validation/property.validation.ts +5 -7
- package/src/validation/value.validation.ts +113 -73
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {GenericCallback} from '@oscarpalmer/atoms/models';
|
|
1
|
+
import type {GenericCallback, PlainObject} from '@oscarpalmer/atoms/models';
|
|
2
2
|
import {join} from '@oscarpalmer/atoms/string';
|
|
3
3
|
import {NAME_ERROR_SCHEMATIC, NAME_ERROR_VALIDATION} from '../constants';
|
|
4
4
|
import type {Schematic} from '../schematic';
|
|
@@ -59,7 +59,7 @@ export type ValidatedProperty = {
|
|
|
59
59
|
/**
|
|
60
60
|
* The property name in the schema
|
|
61
61
|
*/
|
|
62
|
-
key:
|
|
62
|
+
key: string;
|
|
63
63
|
/**
|
|
64
64
|
* Whether the property is required
|
|
65
65
|
*/
|
|
@@ -74,16 +74,6 @@ export type ValidatedProperty = {
|
|
|
74
74
|
validators: ValidatedPropertyValidators;
|
|
75
75
|
};
|
|
76
76
|
|
|
77
|
-
/**
|
|
78
|
-
* The full and short forms of a property's key path
|
|
79
|
-
*
|
|
80
|
-
* For a nested property `address.street`: `full` is `'address.street'`, `short` is `'street'`
|
|
81
|
-
*/
|
|
82
|
-
export type ValidatedPropertyKey = {
|
|
83
|
-
full: string;
|
|
84
|
-
short: string;
|
|
85
|
-
};
|
|
86
|
-
|
|
87
77
|
/**
|
|
88
78
|
* A union of valid types for a {@link ValidatedProperty}'s `types` array
|
|
89
79
|
*
|
|
@@ -139,9 +129,12 @@ export type ValidationInformation = {
|
|
|
139
129
|
};
|
|
140
130
|
|
|
141
131
|
/**
|
|
142
|
-
*
|
|
132
|
+
*
|
|
143
133
|
*/
|
|
144
|
-
export type ValidationInformationKey =
|
|
134
|
+
export type ValidationInformationKey = {
|
|
135
|
+
full: string;
|
|
136
|
+
short: string;
|
|
137
|
+
};
|
|
145
138
|
|
|
146
139
|
/**
|
|
147
140
|
* Options for validation
|
|
@@ -157,7 +150,11 @@ export type ValidationOptions<Errors extends ReportingType> = {
|
|
|
157
150
|
strict?: boolean;
|
|
158
151
|
};
|
|
159
152
|
|
|
160
|
-
export type
|
|
153
|
+
export type ValidationParameters = {
|
|
154
|
+
information?: ValidationInformation[];
|
|
155
|
+
origin?: ValidatedProperty;
|
|
156
|
+
output: PlainObject;
|
|
157
|
+
prefix?: string;
|
|
161
158
|
reporting: ReportingInformation;
|
|
162
159
|
strict: boolean;
|
|
163
160
|
};
|
package/src/schematic.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
2
2
|
import type {PlainObject} from '@oscarpalmer/atoms/models';
|
|
3
|
-
import {error} from '@oscarpalmer/atoms/result/misc';
|
|
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 {
|
|
6
|
+
import {getParameters, isSchematic} from './helpers';
|
|
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';
|
|
@@ -34,10 +34,96 @@ export class Schematic<Model> {
|
|
|
34
34
|
schematicProperties.set(this, properties);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Parse a value according to the schema
|
|
39
|
+
*
|
|
40
|
+
* Returns a deeply cloned version of the value or throws an error for the first property that fails validation
|
|
41
|
+
* @param value Value to parse
|
|
42
|
+
* @param options Validation options
|
|
43
|
+
* @returns Deeply cloned version of the value if it matches the schema, otherwise throws an error
|
|
44
|
+
*/
|
|
45
|
+
get(value: unknown, options: ValidationOptions<'throw'>): Model;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Parse a value according to the schema
|
|
49
|
+
*
|
|
50
|
+
* Returns a deeply cloned version of the value or throws an error for the first property that fails validation
|
|
51
|
+
* @param value Value to parse
|
|
52
|
+
* @param errors Reporting type
|
|
53
|
+
* @returns Deeply cloned version of the value if it matches the schema, otherwise throws an error
|
|
54
|
+
*/
|
|
55
|
+
get(value: unknown, errors: 'throw'): Model;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Parse a value according to the schema
|
|
59
|
+
*
|
|
60
|
+
* Returns a result of a deeply cloned version of the value or all validation information for validation failures from the same depth in the value
|
|
61
|
+
* @param value Value to parse
|
|
62
|
+
* @param options Validation options
|
|
63
|
+
* @returns Result holding deeply cloned value or all validation information
|
|
64
|
+
*/
|
|
65
|
+
get(value: unknown, options: ValidationOptions<'all'>): Result<Model, ValidationInformation[]>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Parse a value according to the schema
|
|
69
|
+
*
|
|
70
|
+
* Returns a result of a deeply cloned version of the value or all validation information for validation failures from the same depth in the value
|
|
71
|
+
* @param value Value to parse
|
|
72
|
+
* @param errors Reporting type
|
|
73
|
+
* @returns Result holding deeply cloned value or all validation information
|
|
74
|
+
*/
|
|
75
|
+
get(value: unknown, errors: 'all'): Result<Model, ValidationInformation[]>;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Parse a value according to the schema
|
|
79
|
+
*
|
|
80
|
+
* Returns a deeply cloned version of the value or all validation information for the first failing property
|
|
81
|
+
* @param value Value to parse
|
|
82
|
+
* @param options Validation options
|
|
83
|
+
* @returns Result holding deeply cloned value or all validation information
|
|
84
|
+
*/
|
|
85
|
+
get(value: unknown, options: ValidationOptions<'first'>): Result<Model, ValidationInformation>;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Parse a value according to the schema
|
|
89
|
+
*
|
|
90
|
+
* Returns a deeply cloned version of the value or all validation information for the first failing property
|
|
91
|
+
* @param value Value to parse
|
|
92
|
+
* @param errors Reporting type
|
|
93
|
+
* @returns Result holding deeply cloned value or all validation information
|
|
94
|
+
*/
|
|
95
|
+
get(value: unknown, errors: 'first'): Result<Model, ValidationInformation>;
|
|
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 strict Validate if unknown keys are present in the object? _(defaults to `false`)_
|
|
103
|
+
* @returns Deeply cloned value, or `undefined` if it's invalid
|
|
104
|
+
*/
|
|
105
|
+
get(value: unknown, strict?: true): Model | undefined;
|
|
106
|
+
|
|
107
|
+
get(value: unknown, options?: unknown): unknown {
|
|
108
|
+
const parameters = getParameters(options);
|
|
109
|
+
|
|
110
|
+
const result = validateObject(value, this.#properties, parameters, true);
|
|
111
|
+
|
|
112
|
+
if (result == null) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (!Array.isArray(result)) {
|
|
117
|
+
return parameters.reporting.none ? result : ok(result);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return error(parameters.reporting.all ? result : result[0]);
|
|
121
|
+
}
|
|
122
|
+
|
|
37
123
|
/**
|
|
38
124
|
* Does the value match the schema?
|
|
39
125
|
*
|
|
40
|
-
* Will assert that the values matches the schema and throw an error if it does not. The error will contain all validation information for the first property that fails validation
|
|
126
|
+
* Will assert that the values matches the schema and throw an error if it does not. The error will contain all validation information for the first property that fails validation
|
|
41
127
|
* @param value Value to validate
|
|
42
128
|
* @param options Validation options
|
|
43
129
|
* @returns `true` if the value matches the schema, otherwise throws an error
|
|
@@ -47,7 +133,7 @@ export class Schematic<Model> {
|
|
|
47
133
|
/**
|
|
48
134
|
* Does the value match the schema?
|
|
49
135
|
*
|
|
50
|
-
* Will assert that the values matches the schema and throw an error if it does not. The error will contain all validation information for the first property that fails validation
|
|
136
|
+
* Will assert that the values matches the schema and throw an error if it does not. The error will contain all validation information for the first property that fails validation
|
|
51
137
|
* @param value Value to validate
|
|
52
138
|
* @param errors Reporting type
|
|
53
139
|
* @returns `true` if the value matches the schema, otherwise throws an error
|
|
@@ -57,27 +143,27 @@ export class Schematic<Model> {
|
|
|
57
143
|
/**
|
|
58
144
|
* Does the value match the schema?
|
|
59
145
|
*
|
|
60
|
-
* Will validate that the value matches the schema and return a result of `true` or all validation information for validation failures from the same depth in the
|
|
146
|
+
* Will validate that the value matches the schema and return a result of `true` or all validation information for validation failures from the same depth in the value
|
|
61
147
|
* @param value Value to validate
|
|
62
148
|
* @param options Validation options
|
|
63
|
-
* @returns `true`
|
|
149
|
+
* @returns Result holding `true` or all validation information
|
|
64
150
|
*/
|
|
65
151
|
is(value: unknown, options: ValidationOptions<'all'>): Result<true, ValidationInformation[]>;
|
|
66
152
|
|
|
67
153
|
/**
|
|
68
154
|
* Does the value match the schema?
|
|
69
155
|
*
|
|
70
|
-
* Will validate that the value matches the schema and return a result of `true` or all validation information for validation failures from the same depth in the
|
|
156
|
+
* Will validate that the value matches the schema and return a result of `true` or all validation information for validation failures from the same depth in the value
|
|
71
157
|
* @param value Value to validate
|
|
72
158
|
* @param errors Reporting type
|
|
73
|
-
* @returns `true`
|
|
159
|
+
* @returns Result holding `true` or all validation information
|
|
74
160
|
*/
|
|
75
161
|
is(value: unknown, errors: 'all'): Result<true, ValidationInformation[]>;
|
|
76
162
|
|
|
77
163
|
/**
|
|
78
164
|
* Does the value match the schema?
|
|
79
165
|
*
|
|
80
|
-
* Will validate that the value matches the schema and return a result of `true` or all validation information for the failing property
|
|
166
|
+
* Will validate that the value matches the schema and return a result of `true` or all validation information for the first failing property
|
|
81
167
|
* @param value Value to validate
|
|
82
168
|
* @param options Validation options
|
|
83
169
|
* @returns `true` if the value matches the schema, otherwise `false`
|
|
@@ -87,7 +173,7 @@ export class Schematic<Model> {
|
|
|
87
173
|
/**
|
|
88
174
|
* Does the value match the schema?
|
|
89
175
|
*
|
|
90
|
-
* Will validate that the value matches the schema and return a result of `true` or all validation information for the failing property
|
|
176
|
+
* Will validate that the value matches the schema and return a result of `true` or all validation information for the first failing property
|
|
91
177
|
* @param value Value to validate
|
|
92
178
|
* @param errors Reporting type
|
|
93
179
|
* @returns `true` if the value matches the schema, otherwise `false`
|
|
@@ -97,7 +183,7 @@ export class Schematic<Model> {
|
|
|
97
183
|
/**
|
|
98
184
|
* Does the value match the schema?
|
|
99
185
|
*
|
|
100
|
-
* Will validate that the value matches the schema and return `true` or `false`, without any validation information for validation failures
|
|
186
|
+
* Will validate that the value matches the schema and return `true` or `false`, without any validation information for validation failures
|
|
101
187
|
* @param value Value to validate
|
|
102
188
|
* @param strict Validate if unknown keys are present in the object? _(defaults to `false`)_
|
|
103
189
|
* @returns `true` if the value matches the schema, otherwise `false`
|
|
@@ -105,15 +191,19 @@ export class Schematic<Model> {
|
|
|
105
191
|
is(value: unknown, strict?: true): value is Model;
|
|
106
192
|
|
|
107
193
|
is(value: unknown, options?: unknown): unknown {
|
|
108
|
-
const
|
|
194
|
+
const parameters = getParameters(options);
|
|
109
195
|
|
|
110
|
-
const result = validateObject(value, this.#properties,
|
|
196
|
+
const result = validateObject(value, this.#properties, parameters, false);
|
|
197
|
+
|
|
198
|
+
if (result == null) {
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
111
201
|
|
|
112
|
-
if (
|
|
113
|
-
return
|
|
202
|
+
if (!Array.isArray(result)) {
|
|
203
|
+
return parameters.reporting.none ? true : ok(true);
|
|
114
204
|
}
|
|
115
205
|
|
|
116
|
-
return error(reporting.all ? result : result[0]);
|
|
206
|
+
return error(parameters.reporting.all ? result : result[0]);
|
|
117
207
|
}
|
|
118
208
|
}
|
|
119
209
|
|
|
@@ -70,13 +70,14 @@ export function getProperties(
|
|
|
70
70
|
|
|
71
71
|
for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
|
|
72
72
|
const key = keys[keyIndex];
|
|
73
|
-
|
|
74
|
-
const prefixed = join([prefix, key], '.');
|
|
75
73
|
const value = original[key];
|
|
76
74
|
|
|
77
75
|
if (value == null) {
|
|
78
76
|
throw new SchematicError(
|
|
79
|
-
SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE.replace(
|
|
77
|
+
SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE.replace(
|
|
78
|
+
TEMPLATE_PATTERN,
|
|
79
|
+
join([prefix, key], '.'),
|
|
80
|
+
),
|
|
80
81
|
);
|
|
81
82
|
}
|
|
82
83
|
|
|
@@ -101,12 +102,9 @@ export function getProperties(
|
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
properties.push({
|
|
105
|
+
key,
|
|
104
106
|
types,
|
|
105
107
|
validators,
|
|
106
|
-
key: {
|
|
107
|
-
full: prefixed,
|
|
108
|
-
short: key,
|
|
109
|
-
},
|
|
110
108
|
required: required && !types.includes(TYPE_UNDEFINED),
|
|
111
109
|
});
|
|
112
110
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
2
|
-
import type {GenericCallback} from '@oscarpalmer/atoms/models';
|
|
2
|
+
import type {GenericCallback, PlainObject} from '@oscarpalmer/atoms/models';
|
|
3
3
|
import {join} from '@oscarpalmer/atoms/string';
|
|
4
|
+
import {clone} from '@oscarpalmer/atoms/value/clone';
|
|
4
5
|
import {TYPE_OBJECT} from '../constants';
|
|
5
6
|
import {
|
|
6
7
|
getInvalidInputMessage,
|
|
@@ -16,21 +17,16 @@ import {
|
|
|
16
17
|
type ValidatedProperty,
|
|
17
18
|
type ValidatedPropertyType,
|
|
18
19
|
type ValidationInformation,
|
|
19
|
-
type
|
|
20
|
+
type ValidationParameters,
|
|
20
21
|
} from '../models/validation.model';
|
|
21
22
|
import {schematicProperties, type Schematic} from '../schematic';
|
|
22
23
|
|
|
23
|
-
function validateNamed(
|
|
24
|
-
property: ValidatedProperty,
|
|
25
|
-
name: ValueName,
|
|
26
|
-
value: unknown,
|
|
27
|
-
validation: ValidationInformation[],
|
|
28
|
-
): boolean {
|
|
24
|
+
function validateNamed(name: ValueName, value: unknown, parameters: ValidationParameters): boolean {
|
|
29
25
|
if (!validators[name](value)) {
|
|
30
26
|
return false;
|
|
31
27
|
}
|
|
32
28
|
|
|
33
|
-
const propertyValidators =
|
|
29
|
+
const propertyValidators = parameters.origin!.validators[name];
|
|
34
30
|
|
|
35
31
|
if (propertyValidators == null || propertyValidators.length === 0) {
|
|
36
32
|
return true;
|
|
@@ -42,10 +38,13 @@ function validateNamed(
|
|
|
42
38
|
const validator = propertyValidators[index];
|
|
43
39
|
|
|
44
40
|
if (!validator(value)) {
|
|
45
|
-
|
|
41
|
+
parameters.information!.push({
|
|
46
42
|
value,
|
|
47
|
-
key: {
|
|
48
|
-
|
|
43
|
+
key: {
|
|
44
|
+
full: parameters.prefix!,
|
|
45
|
+
short: parameters.origin!.key,
|
|
46
|
+
},
|
|
47
|
+
message: getInvalidValidatorMessage(parameters.prefix!, name, index, length),
|
|
49
48
|
validator: validator as GenericCallback,
|
|
50
49
|
});
|
|
51
50
|
|
|
@@ -59,106 +58,118 @@ function validateNamed(
|
|
|
59
58
|
export function validateObject(
|
|
60
59
|
obj: unknown,
|
|
61
60
|
properties: ValidatedProperty[],
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
): boolean | ValidationInformation[] {
|
|
61
|
+
parameters: ValidationParameters,
|
|
62
|
+
get: boolean,
|
|
63
|
+
): PlainObject | ValidationInformation[] | undefined {
|
|
66
64
|
if (!isPlainObject(obj)) {
|
|
67
|
-
const key =
|
|
65
|
+
const key =
|
|
66
|
+
parameters?.origin == null
|
|
67
|
+
? {full: '', short: ''}
|
|
68
|
+
: {
|
|
69
|
+
full: parameters.prefix!,
|
|
70
|
+
short: parameters.origin.key,
|
|
71
|
+
};
|
|
68
72
|
|
|
69
73
|
const information = {
|
|
70
74
|
key,
|
|
71
75
|
message:
|
|
72
|
-
origin == null
|
|
76
|
+
parameters?.origin == null
|
|
73
77
|
? getInvalidInputMessage(obj)
|
|
74
|
-
: getInvalidTypeMessage(
|
|
75
|
-
{
|
|
76
|
-
...origin,
|
|
77
|
-
key,
|
|
78
|
-
},
|
|
79
|
-
obj,
|
|
80
|
-
),
|
|
78
|
+
: getInvalidTypeMessage(key.full, parameters.origin.types, obj),
|
|
81
79
|
value: obj,
|
|
82
80
|
};
|
|
83
81
|
|
|
84
|
-
if (
|
|
82
|
+
if (parameters.reporting.throw) {
|
|
85
83
|
throw new ValidationError([information]);
|
|
86
84
|
}
|
|
87
85
|
|
|
88
|
-
|
|
86
|
+
parameters?.information?.push(information);
|
|
89
87
|
|
|
90
|
-
return
|
|
88
|
+
return parameters.reporting.none ? undefined : [information];
|
|
91
89
|
}
|
|
92
90
|
|
|
93
|
-
if (
|
|
91
|
+
if (parameters.strict) {
|
|
94
92
|
const objKeys = Object.keys(obj);
|
|
95
93
|
|
|
96
|
-
const propertiesKeys = new Set(properties.map(property => property.key
|
|
94
|
+
const propertiesKeys = new Set(properties.map(property => property.key));
|
|
97
95
|
|
|
98
96
|
const unknownKeys = objKeys.filter(key => !propertiesKeys.has(key));
|
|
99
97
|
|
|
100
98
|
if (unknownKeys.length > 0) {
|
|
101
|
-
const key =
|
|
99
|
+
const key =
|
|
100
|
+
parameters?.origin == null
|
|
101
|
+
? {full: '', short: ''}
|
|
102
|
+
: {
|
|
103
|
+
full: join([parameters.prefix, parameters.origin?.key], '.'),
|
|
104
|
+
short: parameters.origin.key,
|
|
105
|
+
};
|
|
102
106
|
|
|
103
107
|
const information: ValidationInformation = {
|
|
104
108
|
key,
|
|
105
|
-
message: getUnknownKeysMessage(
|
|
109
|
+
message: getUnknownKeysMessage(
|
|
110
|
+
unknownKeys.map(key => join([parameters?.prefix, key], '.')),
|
|
111
|
+
),
|
|
106
112
|
value: obj,
|
|
107
113
|
};
|
|
108
114
|
|
|
109
|
-
if (
|
|
115
|
+
if (parameters.reporting.throw) {
|
|
110
116
|
throw new ValidationError([information]);
|
|
111
117
|
}
|
|
112
118
|
|
|
113
|
-
|
|
119
|
+
parameters?.information?.push(information);
|
|
114
120
|
|
|
115
|
-
return
|
|
121
|
+
return parameters.reporting.none ? undefined : [information];
|
|
116
122
|
}
|
|
117
123
|
}
|
|
118
124
|
|
|
119
125
|
const allInformation: ValidationInformation[] = [];
|
|
120
126
|
|
|
127
|
+
const output: PlainObject = {};
|
|
128
|
+
|
|
121
129
|
const propertiesLength = properties.length;
|
|
122
130
|
|
|
123
131
|
outer: for (let propertyIndex = 0; propertyIndex < propertiesLength; propertyIndex += 1) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
property = {
|
|
127
|
-
...property,
|
|
128
|
-
key: {
|
|
129
|
-
full: join([origin?.key.full, property.key.short], '.'),
|
|
130
|
-
short: property.key.short,
|
|
131
|
-
},
|
|
132
|
-
};
|
|
132
|
+
const property = properties[propertyIndex];
|
|
133
133
|
|
|
134
134
|
const {key, required, types} = property;
|
|
135
135
|
|
|
136
|
-
const value = obj[key
|
|
136
|
+
const value = obj[key];
|
|
137
|
+
|
|
138
|
+
if (get && value === undefined && !required) {
|
|
139
|
+
// TODO: during get, respect a default value for the property
|
|
140
|
+
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
137
143
|
|
|
138
144
|
if (value === undefined && required) {
|
|
145
|
+
const prefixedKey = join([parameters.prefix, key], '.');
|
|
146
|
+
|
|
139
147
|
const information: ValidationInformation = {
|
|
140
148
|
value,
|
|
141
|
-
key: {
|
|
142
|
-
|
|
149
|
+
key: {
|
|
150
|
+
full: prefixedKey,
|
|
151
|
+
short: key,
|
|
152
|
+
},
|
|
153
|
+
message: getInvalidMissingMessage(prefixedKey, property.types),
|
|
143
154
|
};
|
|
144
155
|
|
|
145
|
-
if (
|
|
156
|
+
if (parameters.reporting.throw) {
|
|
146
157
|
throw new ValidationError([information]);
|
|
147
158
|
}
|
|
148
159
|
|
|
149
|
-
|
|
150
|
-
validation.push(information);
|
|
151
|
-
}
|
|
160
|
+
parameters?.information?.push(information);
|
|
152
161
|
|
|
153
|
-
if (
|
|
162
|
+
if (parameters.reporting.all) {
|
|
154
163
|
allInformation.push(information);
|
|
155
164
|
|
|
156
165
|
continue;
|
|
157
166
|
}
|
|
158
167
|
|
|
159
|
-
return
|
|
168
|
+
return parameters.reporting.none ? undefined : [information];
|
|
160
169
|
}
|
|
161
170
|
|
|
171
|
+
const prefixedKey = join([parameters.prefix, key], '.');
|
|
172
|
+
|
|
162
173
|
const typesLength = types.length;
|
|
163
174
|
|
|
164
175
|
const information: ValidationInformation[] = [];
|
|
@@ -166,7 +177,25 @@ export function validateObject(
|
|
|
166
177
|
for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
|
|
167
178
|
const type = types[typeIndex];
|
|
168
179
|
|
|
169
|
-
if (
|
|
180
|
+
if (
|
|
181
|
+
validateValue(
|
|
182
|
+
type,
|
|
183
|
+
value,
|
|
184
|
+
{
|
|
185
|
+
information,
|
|
186
|
+
output,
|
|
187
|
+
origin: property,
|
|
188
|
+
prefix: prefixedKey,
|
|
189
|
+
reporting: parameters.reporting,
|
|
190
|
+
strict: parameters.strict,
|
|
191
|
+
},
|
|
192
|
+
get,
|
|
193
|
+
)
|
|
194
|
+
) {
|
|
195
|
+
if (get) {
|
|
196
|
+
output[key] = clone(value);
|
|
197
|
+
}
|
|
198
|
+
|
|
170
199
|
continue outer;
|
|
171
200
|
}
|
|
172
201
|
}
|
|
@@ -174,65 +203,76 @@ export function validateObject(
|
|
|
174
203
|
if (information.length === 0) {
|
|
175
204
|
information.push({
|
|
176
205
|
value,
|
|
177
|
-
key: {
|
|
178
|
-
|
|
206
|
+
key: {
|
|
207
|
+
full: prefixedKey,
|
|
208
|
+
short: key,
|
|
209
|
+
},
|
|
210
|
+
message: getInvalidTypeMessage(prefixedKey, property.types, value),
|
|
179
211
|
});
|
|
180
212
|
}
|
|
181
213
|
|
|
182
|
-
if (
|
|
214
|
+
if (parameters.reporting.throw) {
|
|
183
215
|
throw new ValidationError(information);
|
|
184
216
|
}
|
|
185
217
|
|
|
186
|
-
|
|
218
|
+
parameters?.information?.push(...information);
|
|
187
219
|
|
|
188
|
-
if (
|
|
220
|
+
if (parameters.reporting.all) {
|
|
189
221
|
allInformation.push(...information);
|
|
190
222
|
|
|
191
223
|
continue;
|
|
192
224
|
}
|
|
193
225
|
|
|
194
|
-
return
|
|
226
|
+
return parameters.reporting.none ? undefined : information;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (get) {
|
|
230
|
+
if (parameters.origin == null) {
|
|
231
|
+
parameters.output = output;
|
|
232
|
+
} else {
|
|
233
|
+
parameters.output[parameters.origin.key] = output;
|
|
234
|
+
}
|
|
195
235
|
}
|
|
196
236
|
|
|
197
|
-
return
|
|
237
|
+
return parameters.reporting.none || allInformation.length === 0
|
|
238
|
+
? parameters.output
|
|
239
|
+
: allInformation;
|
|
198
240
|
}
|
|
199
241
|
|
|
200
242
|
function validateSchematic(
|
|
201
|
-
property: ValidatedProperty,
|
|
202
243
|
schematic: Schematic<unknown>,
|
|
203
244
|
value: unknown,
|
|
204
|
-
|
|
205
|
-
|
|
245
|
+
parameters: ValidationParameters,
|
|
246
|
+
get: boolean,
|
|
206
247
|
): boolean {
|
|
207
248
|
const properties = schematicProperties.get(schematic)!;
|
|
208
249
|
|
|
209
|
-
const result = validateObject(value, properties,
|
|
250
|
+
const result = validateObject(value, properties, parameters, get);
|
|
210
251
|
|
|
211
|
-
return
|
|
252
|
+
return result == null || Array.isArray(result) ? false : true;
|
|
212
253
|
}
|
|
213
254
|
|
|
214
255
|
function validateValue(
|
|
215
256
|
type: ValidatedPropertyType,
|
|
216
|
-
property: ValidatedProperty,
|
|
217
257
|
value: unknown,
|
|
218
|
-
|
|
219
|
-
|
|
258
|
+
parameters: ValidationParameters,
|
|
259
|
+
get: boolean,
|
|
220
260
|
): boolean {
|
|
221
261
|
switch (true) {
|
|
222
262
|
case typeof type === 'function':
|
|
223
263
|
return (type as GenericCallback)(value);
|
|
224
264
|
|
|
225
265
|
case Array.isArray(type): {
|
|
226
|
-
const
|
|
266
|
+
const result = validateObject(value, type, parameters, get);
|
|
227
267
|
|
|
228
|
-
return
|
|
268
|
+
return result == null || Array.isArray(result) ? false : true;
|
|
229
269
|
}
|
|
230
270
|
|
|
231
271
|
case isSchematic(type):
|
|
232
|
-
return validateSchematic(
|
|
272
|
+
return validateSchematic(type, value, parameters, get);
|
|
233
273
|
|
|
234
274
|
default:
|
|
235
|
-
return validateNamed(
|
|
275
|
+
return validateNamed(type as ValueName, value, parameters);
|
|
236
276
|
}
|
|
237
277
|
}
|
|
238
278
|
|