@oscarpalmer/jhunal 0.21.0 → 0.22.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 +4 -4
- package/dist/helpers.mjs +2 -1
- package/dist/index.d.mts +17 -56
- package/dist/index.mjs +211 -215
- package/dist/models/schema.plain.model.d.mts +2 -8
- package/dist/models/validation.model.d.mts +10 -54
- package/dist/schematic.d.mts +4 -4
- package/dist/schematic.mjs +12 -15
- package/dist/validation.d.mts +7 -0
- package/dist/validation.mjs +245 -0
- package/package.json +1 -1
- package/src/helpers.ts +11 -8
- package/src/index.ts +6 -1
- package/src/models/schema.plain.model.ts +1 -8
- package/src/models/validation.model.ts +37 -72
- package/src/schematic.ts +18 -23
- package/src/validation.ts +498 -0
- package/dist/validation/property.validation.d.mts +0 -7
- package/dist/validation/property.validation.mjs +0 -92
- package/dist/validation/value.validation.d.mts +0 -7
- package/dist/validation/value.validation.mjs +0 -162
- package/src/validation/property.validation.ts +0 -217
- package/src/validation/value.validation.ts +0 -293
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import "../constants.mjs";
|
|
2
|
-
import { getInvalidInputMessage, getInvalidMissingMessage, getInvalidTypeMessage, getInvalidValidatorMessage, getUnknownKeysMessage, isSchematic } from "../helpers.mjs";
|
|
3
|
-
import { ValidationError } from "../models/validation.model.mjs";
|
|
4
|
-
import { schematicProperties } from "../schematic.mjs";
|
|
5
|
-
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
6
|
-
import { join } from "@oscarpalmer/atoms/string";
|
|
7
|
-
import { clone } from "@oscarpalmer/atoms/value/clone";
|
|
8
|
-
//#region src/validation/value.validation.ts
|
|
9
|
-
function validateNamed(name, value, parameters) {
|
|
10
|
-
if (!validators[name](value)) return false;
|
|
11
|
-
const propertyValidators = parameters.origin.validators[name];
|
|
12
|
-
if (propertyValidators == null || propertyValidators.length === 0) return true;
|
|
13
|
-
const { length } = propertyValidators;
|
|
14
|
-
for (let index = 0; index < length; index += 1) {
|
|
15
|
-
const validator = propertyValidators[index];
|
|
16
|
-
if (!validator(value)) {
|
|
17
|
-
parameters.information.push({
|
|
18
|
-
value,
|
|
19
|
-
key: {
|
|
20
|
-
full: parameters.prefix,
|
|
21
|
-
short: parameters.origin.key
|
|
22
|
-
},
|
|
23
|
-
message: getInvalidValidatorMessage(parameters.prefix, name, index, length),
|
|
24
|
-
validator
|
|
25
|
-
});
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return true;
|
|
30
|
-
}
|
|
31
|
-
function validateObject(obj, properties, parameters, get) {
|
|
32
|
-
if (!isPlainObject(obj)) {
|
|
33
|
-
const key = parameters?.origin == null ? {
|
|
34
|
-
full: "",
|
|
35
|
-
short: ""
|
|
36
|
-
} : {
|
|
37
|
-
full: parameters.prefix,
|
|
38
|
-
short: parameters.origin.key
|
|
39
|
-
};
|
|
40
|
-
const information = {
|
|
41
|
-
key,
|
|
42
|
-
message: parameters?.origin == null ? getInvalidInputMessage(obj) : getInvalidTypeMessage(key.full, parameters.origin.types, obj),
|
|
43
|
-
value: obj
|
|
44
|
-
};
|
|
45
|
-
if (parameters.reporting.throw) throw new ValidationError([information]);
|
|
46
|
-
parameters?.information?.push(information);
|
|
47
|
-
return parameters.reporting.none ? void 0 : [information];
|
|
48
|
-
}
|
|
49
|
-
if (parameters.strict) {
|
|
50
|
-
const objKeys = Object.keys(obj);
|
|
51
|
-
const propertiesKeys = new Set(properties.map((property) => property.key));
|
|
52
|
-
const unknownKeys = objKeys.filter((key) => !propertiesKeys.has(key));
|
|
53
|
-
if (unknownKeys.length > 0) {
|
|
54
|
-
const information = {
|
|
55
|
-
key: parameters?.origin == null ? {
|
|
56
|
-
full: "",
|
|
57
|
-
short: ""
|
|
58
|
-
} : {
|
|
59
|
-
full: join([parameters.prefix, parameters.origin?.key], "."),
|
|
60
|
-
short: parameters.origin.key
|
|
61
|
-
},
|
|
62
|
-
message: getUnknownKeysMessage(unknownKeys.map((key) => join([parameters?.prefix, key], "."))),
|
|
63
|
-
value: obj
|
|
64
|
-
};
|
|
65
|
-
if (parameters.reporting.throw) throw new ValidationError([information]);
|
|
66
|
-
parameters?.information?.push(information);
|
|
67
|
-
return parameters.reporting.none ? void 0 : [information];
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
const allInformation = [];
|
|
71
|
-
const output = {};
|
|
72
|
-
const propertiesLength = properties.length;
|
|
73
|
-
outer: for (let propertyIndex = 0; propertyIndex < propertiesLength; propertyIndex += 1) {
|
|
74
|
-
const property = properties[propertyIndex];
|
|
75
|
-
const { key, required, types } = property;
|
|
76
|
-
const value = obj[key];
|
|
77
|
-
if (get && value === void 0 && !required) continue;
|
|
78
|
-
if (value === void 0 && required) {
|
|
79
|
-
const prefixedKey = join([parameters.prefix, key], ".");
|
|
80
|
-
const information = {
|
|
81
|
-
value,
|
|
82
|
-
key: {
|
|
83
|
-
full: prefixedKey,
|
|
84
|
-
short: key
|
|
85
|
-
},
|
|
86
|
-
message: getInvalidMissingMessage(prefixedKey, property.types)
|
|
87
|
-
};
|
|
88
|
-
if (parameters.reporting.throw) throw new ValidationError([information]);
|
|
89
|
-
parameters?.information?.push(information);
|
|
90
|
-
if (parameters.reporting.all) {
|
|
91
|
-
allInformation.push(information);
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
return parameters.reporting.none ? void 0 : [information];
|
|
95
|
-
}
|
|
96
|
-
const prefixedKey = join([parameters.prefix, key], ".");
|
|
97
|
-
const typesLength = types.length;
|
|
98
|
-
const information = [];
|
|
99
|
-
for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
|
|
100
|
-
const type = types[typeIndex];
|
|
101
|
-
if (validateValue(type, value, {
|
|
102
|
-
information,
|
|
103
|
-
output,
|
|
104
|
-
origin: property,
|
|
105
|
-
prefix: prefixedKey,
|
|
106
|
-
reporting: parameters.reporting,
|
|
107
|
-
strict: parameters.strict
|
|
108
|
-
}, get)) {
|
|
109
|
-
if (get) output[key] = clone(value);
|
|
110
|
-
continue outer;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
if (information.length === 0) information.push({
|
|
114
|
-
value,
|
|
115
|
-
key: {
|
|
116
|
-
full: prefixedKey,
|
|
117
|
-
short: key
|
|
118
|
-
},
|
|
119
|
-
message: getInvalidTypeMessage(prefixedKey, property.types, value)
|
|
120
|
-
});
|
|
121
|
-
if (parameters.reporting.throw) throw new ValidationError(information);
|
|
122
|
-
parameters?.information?.push(...information);
|
|
123
|
-
if (parameters.reporting.all) {
|
|
124
|
-
allInformation.push(...information);
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
return parameters.reporting.none ? void 0 : information;
|
|
128
|
-
}
|
|
129
|
-
if (get) if (parameters.origin == null) parameters.output = output;
|
|
130
|
-
else parameters.output[parameters.origin.key] = output;
|
|
131
|
-
return parameters.reporting.none || allInformation.length === 0 ? parameters.output : allInformation;
|
|
132
|
-
}
|
|
133
|
-
function validateSchematic(schematic, value, parameters, get) {
|
|
134
|
-
const result = validateObject(value, schematicProperties.get(schematic), parameters, get);
|
|
135
|
-
return result == null || Array.isArray(result) ? false : true;
|
|
136
|
-
}
|
|
137
|
-
function validateValue(type, value, parameters, get) {
|
|
138
|
-
switch (true) {
|
|
139
|
-
case typeof type === "function": return type(value);
|
|
140
|
-
case Array.isArray(type): {
|
|
141
|
-
const result = validateObject(value, type, parameters, get);
|
|
142
|
-
return result == null || Array.isArray(result) ? false : true;
|
|
143
|
-
}
|
|
144
|
-
case isSchematic(type): return validateSchematic(type, value, parameters, get);
|
|
145
|
-
default: return validateNamed(type, value, parameters);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
const validators = {
|
|
149
|
-
array: Array.isArray,
|
|
150
|
-
bigint: (value) => typeof value === "bigint",
|
|
151
|
-
boolean: (value) => typeof value === "boolean",
|
|
152
|
-
date: (value) => value instanceof Date,
|
|
153
|
-
function: (value) => typeof value === "function",
|
|
154
|
-
null: (value) => value === null,
|
|
155
|
-
number: (value) => typeof value === "number",
|
|
156
|
-
object: (value) => typeof value === "object" && value !== null,
|
|
157
|
-
string: (value) => typeof value === "string",
|
|
158
|
-
symbol: (value) => typeof value === "symbol",
|
|
159
|
-
undefined: (value) => value === void 0
|
|
160
|
-
};
|
|
161
|
-
//#endregion
|
|
162
|
-
export { validateObject };
|
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
import {isConstructor, isPlainObject} from '@oscarpalmer/atoms/is';
|
|
2
|
-
import type {PlainObject} from '@oscarpalmer/atoms/models';
|
|
3
|
-
import {join} from '@oscarpalmer/atoms/string';
|
|
4
|
-
import {
|
|
5
|
-
PROPERTY_REQUIRED,
|
|
6
|
-
PROPERTY_TYPE,
|
|
7
|
-
PROPERTY_VALIDATORS,
|
|
8
|
-
SCHEMATIC_MESSAGE_SCHEMA_INVALID_EMPTY,
|
|
9
|
-
SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED,
|
|
10
|
-
SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE,
|
|
11
|
-
SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_REQUIRED,
|
|
12
|
-
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
|
-
TEMPLATE_PATTERN,
|
|
17
|
-
TYPE_ALL,
|
|
18
|
-
TYPE_UNDEFINED,
|
|
19
|
-
VALIDATABLE_TYPES,
|
|
20
|
-
} from '../constants';
|
|
21
|
-
import {instanceOf, isSchematic} from '../helpers';
|
|
22
|
-
import type {ValueName} from '../models/misc.model';
|
|
23
|
-
import {
|
|
24
|
-
SchematicError,
|
|
25
|
-
type ValidatedProperty,
|
|
26
|
-
type ValidatedPropertyType,
|
|
27
|
-
type ValidatedPropertyValidators,
|
|
28
|
-
} from '../models/validation.model';
|
|
29
|
-
|
|
30
|
-
function getDisallowedProperty(obj: PlainObject): string | undefined {
|
|
31
|
-
if (PROPERTY_REQUIRED in obj) {
|
|
32
|
-
return PROPERTY_REQUIRED;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (PROPERTY_TYPE in obj) {
|
|
36
|
-
return PROPERTY_TYPE;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (PROPERTY_VALIDATORS in obj) {
|
|
40
|
-
return PROPERTY_VALIDATORS;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function getProperties(
|
|
45
|
-
original: PlainObject,
|
|
46
|
-
prefix?: string,
|
|
47
|
-
fromType?: boolean,
|
|
48
|
-
): ValidatedProperty[] {
|
|
49
|
-
if (Object.keys(original).length === 0) {
|
|
50
|
-
throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_EMPTY);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (fromType ?? false) {
|
|
54
|
-
const property = getDisallowedProperty(original);
|
|
55
|
-
|
|
56
|
-
if (property != null) {
|
|
57
|
-
throw new SchematicError(
|
|
58
|
-
SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED.replace(
|
|
59
|
-
TEMPLATE_PATTERN,
|
|
60
|
-
prefix!,
|
|
61
|
-
).replace(TEMPLATE_PATTERN, property),
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const keys = Object.keys(original);
|
|
67
|
-
const keysLength = keys.length;
|
|
68
|
-
|
|
69
|
-
const properties: ValidatedProperty[] = [];
|
|
70
|
-
|
|
71
|
-
for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
|
|
72
|
-
const key = keys[keyIndex];
|
|
73
|
-
const value = original[key];
|
|
74
|
-
|
|
75
|
-
if (value == null) {
|
|
76
|
-
throw new SchematicError(
|
|
77
|
-
SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE.replace(
|
|
78
|
-
TEMPLATE_PATTERN,
|
|
79
|
-
join([prefix, key], '.'),
|
|
80
|
-
),
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const types: ValidatedPropertyType[] = [];
|
|
85
|
-
|
|
86
|
-
let required = true;
|
|
87
|
-
let validators: ValidatedPropertyValidators = {};
|
|
88
|
-
|
|
89
|
-
if (isPlainObject(value)) {
|
|
90
|
-
required = getRequired(key, value) ?? required;
|
|
91
|
-
validators = getValidators(value[PROPERTY_VALIDATORS]);
|
|
92
|
-
|
|
93
|
-
const hasType = PROPERTY_TYPE in value;
|
|
94
|
-
|
|
95
|
-
types.push(...getTypes(key, hasType ? value[PROPERTY_TYPE] : value, prefix, hasType));
|
|
96
|
-
} else {
|
|
97
|
-
types.push(...getTypes(key, value, prefix));
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (!required && !types.includes(TYPE_UNDEFINED)) {
|
|
101
|
-
types.push(TYPE_UNDEFINED);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
properties.push({
|
|
105
|
-
key,
|
|
106
|
-
types,
|
|
107
|
-
validators,
|
|
108
|
-
required: required && !types.includes(TYPE_UNDEFINED),
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return properties;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function getRequired(key: string, obj: PlainObject): boolean | undefined {
|
|
116
|
-
if (!(PROPERTY_REQUIRED in obj)) {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (typeof obj[PROPERTY_REQUIRED] !== 'boolean') {
|
|
121
|
-
throw new SchematicError(
|
|
122
|
-
SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_REQUIRED.replace(TEMPLATE_PATTERN, key),
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return obj[PROPERTY_REQUIRED];
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function getTypes(
|
|
130
|
-
key: string,
|
|
131
|
-
original: unknown,
|
|
132
|
-
prefix?: string,
|
|
133
|
-
fromType?: boolean,
|
|
134
|
-
): ValidatedPropertyType[] {
|
|
135
|
-
const array = Array.isArray(original) ? original : [original];
|
|
136
|
-
const {length} = array;
|
|
137
|
-
|
|
138
|
-
const types: ValidatedPropertyType[] = [];
|
|
139
|
-
|
|
140
|
-
for (let index = 0; index < length; index += 1) {
|
|
141
|
-
const value = array[index];
|
|
142
|
-
|
|
143
|
-
switch (true) {
|
|
144
|
-
case typeof value === 'function':
|
|
145
|
-
types.push(isConstructor(value) ? instanceOf(value) : value);
|
|
146
|
-
break;
|
|
147
|
-
|
|
148
|
-
case isPlainObject(value):
|
|
149
|
-
types.push(getProperties(value, join([prefix, key], '.'), fromType));
|
|
150
|
-
break;
|
|
151
|
-
|
|
152
|
-
case isSchematic(value):
|
|
153
|
-
types.push(value);
|
|
154
|
-
break;
|
|
155
|
-
|
|
156
|
-
case TYPE_ALL.has(value as never):
|
|
157
|
-
types.push(value as never);
|
|
158
|
-
break;
|
|
159
|
-
|
|
160
|
-
default:
|
|
161
|
-
throw new SchematicError(
|
|
162
|
-
SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE.replace(
|
|
163
|
-
TEMPLATE_PATTERN,
|
|
164
|
-
join([prefix, key], '.'),
|
|
165
|
-
),
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (types.length === 0) {
|
|
171
|
-
throw new SchematicError(
|
|
172
|
-
SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE.replace(
|
|
173
|
-
TEMPLATE_PATTERN,
|
|
174
|
-
join([prefix, key], '.'),
|
|
175
|
-
),
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
return types;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
function getValidators(original: unknown): ValidatedPropertyValidators {
|
|
183
|
-
const validators: ValidatedPropertyValidators = {};
|
|
184
|
-
|
|
185
|
-
if (original == null) {
|
|
186
|
-
return validators;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (!isPlainObject(original)) {
|
|
190
|
-
throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const keys = Object.keys(original);
|
|
194
|
-
const {length} = keys;
|
|
195
|
-
|
|
196
|
-
for (let index = 0; index < length; index += 1) {
|
|
197
|
-
const key = keys[index];
|
|
198
|
-
|
|
199
|
-
if (!VALIDATABLE_TYPES.has(key as never)) {
|
|
200
|
-
throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY.replace(TEMPLATE_PATTERN, key));
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const value = (original as PlainObject)[key];
|
|
204
|
-
|
|
205
|
-
validators[key as ValueName] = (Array.isArray(value) ? value : [value]).map(item => {
|
|
206
|
-
if (typeof item !== 'function') {
|
|
207
|
-
throw new TypeError(
|
|
208
|
-
SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE.replace(TEMPLATE_PATTERN, key),
|
|
209
|
-
);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
return item;
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
return validators;
|
|
217
|
-
}
|
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
2
|
-
import type {GenericCallback, PlainObject} from '@oscarpalmer/atoms/models';
|
|
3
|
-
import {join} from '@oscarpalmer/atoms/string';
|
|
4
|
-
import {clone} from '@oscarpalmer/atoms/value/clone';
|
|
5
|
-
import {TYPE_OBJECT} from '../constants';
|
|
6
|
-
import {
|
|
7
|
-
getInvalidInputMessage,
|
|
8
|
-
getInvalidMissingMessage,
|
|
9
|
-
getInvalidTypeMessage,
|
|
10
|
-
getInvalidValidatorMessage,
|
|
11
|
-
getUnknownKeysMessage,
|
|
12
|
-
isSchematic,
|
|
13
|
-
} from '../helpers';
|
|
14
|
-
import type {ValueName} from '../models/misc.model';
|
|
15
|
-
import {
|
|
16
|
-
ValidationError,
|
|
17
|
-
type ValidatedProperty,
|
|
18
|
-
type ValidatedPropertyType,
|
|
19
|
-
type ValidationInformation,
|
|
20
|
-
type ValidationParameters,
|
|
21
|
-
} from '../models/validation.model';
|
|
22
|
-
import {schematicProperties, type Schematic} from '../schematic';
|
|
23
|
-
|
|
24
|
-
function validateNamed(name: ValueName, value: unknown, parameters: ValidationParameters): boolean {
|
|
25
|
-
if (!validators[name](value)) {
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const propertyValidators = parameters.origin!.validators[name];
|
|
30
|
-
|
|
31
|
-
if (propertyValidators == null || propertyValidators.length === 0) {
|
|
32
|
-
return true;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const {length} = propertyValidators;
|
|
36
|
-
|
|
37
|
-
for (let index = 0; index < length; index += 1) {
|
|
38
|
-
const validator = propertyValidators[index];
|
|
39
|
-
|
|
40
|
-
if (!validator(value)) {
|
|
41
|
-
parameters.information!.push({
|
|
42
|
-
value,
|
|
43
|
-
key: {
|
|
44
|
-
full: parameters.prefix!,
|
|
45
|
-
short: parameters.origin!.key,
|
|
46
|
-
},
|
|
47
|
-
message: getInvalidValidatorMessage(parameters.prefix!, name, index, length),
|
|
48
|
-
validator: validator as GenericCallback,
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return true;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function validateObject(
|
|
59
|
-
obj: unknown,
|
|
60
|
-
properties: ValidatedProperty[],
|
|
61
|
-
parameters: ValidationParameters,
|
|
62
|
-
get: boolean,
|
|
63
|
-
): PlainObject | ValidationInformation[] | undefined {
|
|
64
|
-
if (!isPlainObject(obj)) {
|
|
65
|
-
const key =
|
|
66
|
-
parameters?.origin == null
|
|
67
|
-
? {full: '', short: ''}
|
|
68
|
-
: {
|
|
69
|
-
full: parameters.prefix!,
|
|
70
|
-
short: parameters.origin.key,
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const information = {
|
|
74
|
-
key,
|
|
75
|
-
message:
|
|
76
|
-
parameters?.origin == null
|
|
77
|
-
? getInvalidInputMessage(obj)
|
|
78
|
-
: getInvalidTypeMessage(key.full, parameters.origin.types, obj),
|
|
79
|
-
value: obj,
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
if (parameters.reporting.throw) {
|
|
83
|
-
throw new ValidationError([information]);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
parameters?.information?.push(information);
|
|
87
|
-
|
|
88
|
-
return parameters.reporting.none ? undefined : [information];
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (parameters.strict) {
|
|
92
|
-
const objKeys = Object.keys(obj);
|
|
93
|
-
|
|
94
|
-
const propertiesKeys = new Set(properties.map(property => property.key));
|
|
95
|
-
|
|
96
|
-
const unknownKeys = objKeys.filter(key => !propertiesKeys.has(key));
|
|
97
|
-
|
|
98
|
-
if (unknownKeys.length > 0) {
|
|
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
|
-
};
|
|
106
|
-
|
|
107
|
-
const information: ValidationInformation = {
|
|
108
|
-
key,
|
|
109
|
-
message: getUnknownKeysMessage(
|
|
110
|
-
unknownKeys.map(key => join([parameters?.prefix, key], '.')),
|
|
111
|
-
),
|
|
112
|
-
value: obj,
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
if (parameters.reporting.throw) {
|
|
116
|
-
throw new ValidationError([information]);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
parameters?.information?.push(information);
|
|
120
|
-
|
|
121
|
-
return parameters.reporting.none ? undefined : [information];
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const allInformation: ValidationInformation[] = [];
|
|
126
|
-
|
|
127
|
-
const output: PlainObject = {};
|
|
128
|
-
|
|
129
|
-
const propertiesLength = properties.length;
|
|
130
|
-
|
|
131
|
-
outer: for (let propertyIndex = 0; propertyIndex < propertiesLength; propertyIndex += 1) {
|
|
132
|
-
const property = properties[propertyIndex];
|
|
133
|
-
|
|
134
|
-
const {key, required, types} = property;
|
|
135
|
-
|
|
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
|
-
}
|
|
143
|
-
|
|
144
|
-
if (value === undefined && required) {
|
|
145
|
-
const prefixedKey = join([parameters.prefix, key], '.');
|
|
146
|
-
|
|
147
|
-
const information: ValidationInformation = {
|
|
148
|
-
value,
|
|
149
|
-
key: {
|
|
150
|
-
full: prefixedKey,
|
|
151
|
-
short: key,
|
|
152
|
-
},
|
|
153
|
-
message: getInvalidMissingMessage(prefixedKey, property.types),
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
if (parameters.reporting.throw) {
|
|
157
|
-
throw new ValidationError([information]);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
parameters?.information?.push(information);
|
|
161
|
-
|
|
162
|
-
if (parameters.reporting.all) {
|
|
163
|
-
allInformation.push(information);
|
|
164
|
-
|
|
165
|
-
continue;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return parameters.reporting.none ? undefined : [information];
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const prefixedKey = join([parameters.prefix, key], '.');
|
|
172
|
-
|
|
173
|
-
const typesLength = types.length;
|
|
174
|
-
|
|
175
|
-
const information: ValidationInformation[] = [];
|
|
176
|
-
|
|
177
|
-
for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
|
|
178
|
-
const type = types[typeIndex];
|
|
179
|
-
|
|
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
|
-
|
|
199
|
-
continue outer;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (information.length === 0) {
|
|
204
|
-
information.push({
|
|
205
|
-
value,
|
|
206
|
-
key: {
|
|
207
|
-
full: prefixedKey,
|
|
208
|
-
short: key,
|
|
209
|
-
},
|
|
210
|
-
message: getInvalidTypeMessage(prefixedKey, property.types, value),
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
if (parameters.reporting.throw) {
|
|
215
|
-
throw new ValidationError(information);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
parameters?.information?.push(...information);
|
|
219
|
-
|
|
220
|
-
if (parameters.reporting.all) {
|
|
221
|
-
allInformation.push(...information);
|
|
222
|
-
|
|
223
|
-
continue;
|
|
224
|
-
}
|
|
225
|
-
|
|
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
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
return parameters.reporting.none || allInformation.length === 0
|
|
238
|
-
? parameters.output
|
|
239
|
-
: allInformation;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function validateSchematic(
|
|
243
|
-
schematic: Schematic<unknown>,
|
|
244
|
-
value: unknown,
|
|
245
|
-
parameters: ValidationParameters,
|
|
246
|
-
get: boolean,
|
|
247
|
-
): boolean {
|
|
248
|
-
const properties = schematicProperties.get(schematic)!;
|
|
249
|
-
|
|
250
|
-
const result = validateObject(value, properties, parameters, get);
|
|
251
|
-
|
|
252
|
-
return result == null || Array.isArray(result) ? false : true;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
function validateValue(
|
|
256
|
-
type: ValidatedPropertyType,
|
|
257
|
-
value: unknown,
|
|
258
|
-
parameters: ValidationParameters,
|
|
259
|
-
get: boolean,
|
|
260
|
-
): boolean {
|
|
261
|
-
switch (true) {
|
|
262
|
-
case typeof type === 'function':
|
|
263
|
-
return (type as GenericCallback)(value);
|
|
264
|
-
|
|
265
|
-
case Array.isArray(type): {
|
|
266
|
-
const result = validateObject(value, type, parameters, get);
|
|
267
|
-
|
|
268
|
-
return result == null || Array.isArray(result) ? false : true;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
case isSchematic(type):
|
|
272
|
-
return validateSchematic(type, value, parameters, get);
|
|
273
|
-
|
|
274
|
-
default:
|
|
275
|
-
return validateNamed(type as ValueName, value, parameters);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
//
|
|
280
|
-
|
|
281
|
-
const validators: Record<ValueName, (value: unknown) => boolean> = {
|
|
282
|
-
array: Array.isArray,
|
|
283
|
-
bigint: value => typeof value === 'bigint',
|
|
284
|
-
boolean: value => typeof value === 'boolean',
|
|
285
|
-
date: value => value instanceof Date,
|
|
286
|
-
function: value => typeof value === 'function',
|
|
287
|
-
null: value => value === null,
|
|
288
|
-
number: value => typeof value === 'number',
|
|
289
|
-
object: value => typeof value === TYPE_OBJECT && value !== null,
|
|
290
|
-
string: value => typeof value === 'string',
|
|
291
|
-
symbol: value => typeof value === 'symbol',
|
|
292
|
-
undefined: value => value === undefined,
|
|
293
|
-
};
|