@oscarpalmer/jhunal 0.18.0 → 0.20.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 -1
- package/dist/constants.mjs +7 -1
- package/dist/helpers.d.mts +6 -1
- package/dist/helpers.mjs +36 -10
- package/dist/index.d.mts +138 -94
- package/dist/index.mjs +128 -43
- package/dist/models/infer.model.d.mts +12 -12
- package/dist/models/misc.model.d.mts +20 -29
- package/dist/models/schema.plain.model.d.mts +4 -4
- package/dist/models/schema.typed.model.d.mts +5 -23
- package/dist/models/transform.model.d.mts +9 -13
- package/dist/models/validation.model.d.mts +49 -13
- package/dist/models/validation.model.mjs +4 -1
- package/dist/schematic.d.mts +52 -4
- package/dist/schematic.mjs +13 -4
- package/dist/validation/value.validation.d.mts +2 -2
- package/dist/validation/value.validation.mjs +78 -33
- package/package.json +1 -1
- package/src/constants.ts +16 -0
- package/src/helpers.ts +61 -15
- package/src/models/infer.model.ts +12 -12
- package/src/models/misc.model.ts +20 -29
- package/src/models/schema.plain.model.ts +4 -4
- package/src/models/schema.typed.model.ts +5 -23
- package/src/models/transform.model.ts +9 -13
- package/src/models/validation.model.ts +51 -9
- package/src/schematic.ts +79 -9
- package/src/validation/property.validation.ts +3 -4
- package/src/validation/value.validation.ts +120 -43
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
2
2
|
import type {GenericCallback} from '@oscarpalmer/atoms/models';
|
|
3
|
+
import {join} from '@oscarpalmer/atoms/string';
|
|
4
|
+
import {TYPE_OBJECT} from '../constants';
|
|
3
5
|
import {
|
|
4
6
|
getInvalidInputMessage,
|
|
5
7
|
getInvalidMissingMessage,
|
|
6
8
|
getInvalidTypeMessage,
|
|
7
9
|
getInvalidValidatorMessage,
|
|
10
|
+
getUnknownKeysMessage,
|
|
8
11
|
isSchematic,
|
|
9
12
|
} from '../helpers';
|
|
10
13
|
import type {ValueName} from '../models/misc.model';
|
|
11
14
|
import {
|
|
12
15
|
ValidationError,
|
|
13
|
-
type ReportingInformation,
|
|
14
16
|
type ValidatedProperty,
|
|
15
17
|
type ValidatedPropertyType,
|
|
16
18
|
type ValidationInformation,
|
|
19
|
+
type ValidationOptionsExtended,
|
|
17
20
|
} from '../models/validation.model';
|
|
21
|
+
import {schematicProperties, type Schematic} from '../schematic';
|
|
18
22
|
|
|
19
23
|
function validateNamed(
|
|
20
24
|
property: ValidatedProperty,
|
|
@@ -39,6 +43,7 @@ function validateNamed(
|
|
|
39
43
|
|
|
40
44
|
if (!validator(value)) {
|
|
41
45
|
validation.push({
|
|
46
|
+
value,
|
|
42
47
|
key: {...property.key},
|
|
43
48
|
message: getInvalidValidatorMessage(property, name, index, length),
|
|
44
49
|
validator: validator as GenericCallback,
|
|
@@ -54,26 +59,77 @@ function validateNamed(
|
|
|
54
59
|
export function validateObject(
|
|
55
60
|
obj: unknown,
|
|
56
61
|
properties: ValidatedProperty[],
|
|
57
|
-
|
|
62
|
+
options: ValidationOptionsExtended,
|
|
63
|
+
origin?: ValidatedProperty,
|
|
58
64
|
validation?: ValidationInformation[],
|
|
59
|
-
): boolean {
|
|
65
|
+
): boolean | ValidationInformation[] {
|
|
60
66
|
if (!isPlainObject(obj)) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
const key = origin == null ? {full: '', short: ''} : {...origin.key};
|
|
68
|
+
|
|
69
|
+
const information = {
|
|
70
|
+
key,
|
|
71
|
+
message:
|
|
72
|
+
origin == null
|
|
73
|
+
? getInvalidInputMessage(obj)
|
|
74
|
+
: getInvalidTypeMessage(
|
|
75
|
+
{
|
|
76
|
+
...origin,
|
|
77
|
+
key,
|
|
78
|
+
},
|
|
79
|
+
obj,
|
|
80
|
+
),
|
|
81
|
+
value: obj,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
if (options.reporting.throw) {
|
|
85
|
+
throw new ValidationError([information]);
|
|
68
86
|
}
|
|
69
87
|
|
|
70
|
-
|
|
88
|
+
validation?.push(information);
|
|
89
|
+
|
|
90
|
+
return options.reporting.none ? false : [information];
|
|
71
91
|
}
|
|
72
92
|
|
|
93
|
+
if (options.strict) {
|
|
94
|
+
const objKeys = Object.keys(obj);
|
|
95
|
+
|
|
96
|
+
const propertiesKeys = new Set(properties.map(property => property.key.short));
|
|
97
|
+
|
|
98
|
+
const unknownKeys = objKeys.filter(key => !propertiesKeys.has(key));
|
|
99
|
+
|
|
100
|
+
if (unknownKeys.length > 0) {
|
|
101
|
+
const key = origin == null ? {full: '', short: ''} : {...origin.key};
|
|
102
|
+
|
|
103
|
+
const information: ValidationInformation = {
|
|
104
|
+
key,
|
|
105
|
+
message: getUnknownKeysMessage(unknownKeys.map(key => join([origin?.key.full, key], '.'))),
|
|
106
|
+
value: obj,
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
if (options.reporting.throw) {
|
|
110
|
+
throw new ValidationError([information]);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
validation?.push(information);
|
|
114
|
+
|
|
115
|
+
return options.reporting.none ? false : [information];
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const allInformation: ValidationInformation[] = [];
|
|
120
|
+
|
|
73
121
|
const propertiesLength = properties.length;
|
|
74
122
|
|
|
75
123
|
outer: for (let propertyIndex = 0; propertyIndex < propertiesLength; propertyIndex += 1) {
|
|
76
|
-
|
|
124
|
+
let property = properties[propertyIndex];
|
|
125
|
+
|
|
126
|
+
property = {
|
|
127
|
+
...property,
|
|
128
|
+
key: {
|
|
129
|
+
full: join([origin?.key.full, property.key.short], '.'),
|
|
130
|
+
short: property.key.short,
|
|
131
|
+
},
|
|
132
|
+
};
|
|
77
133
|
|
|
78
134
|
const {key, required, types} = property;
|
|
79
135
|
|
|
@@ -81,11 +137,12 @@ export function validateObject(
|
|
|
81
137
|
|
|
82
138
|
if (value === undefined && required) {
|
|
83
139
|
const information: ValidationInformation = {
|
|
140
|
+
value,
|
|
84
141
|
key: {...key},
|
|
85
142
|
message: getInvalidMissingMessage(property),
|
|
86
143
|
};
|
|
87
144
|
|
|
88
|
-
if (reporting.throw && validation == null) {
|
|
145
|
+
if (options.reporting.throw && validation == null) {
|
|
89
146
|
throw new ValidationError([information]);
|
|
90
147
|
}
|
|
91
148
|
|
|
@@ -93,7 +150,13 @@ export function validateObject(
|
|
|
93
150
|
validation.push(information);
|
|
94
151
|
}
|
|
95
152
|
|
|
96
|
-
|
|
153
|
+
if (options.reporting.all) {
|
|
154
|
+
allInformation.push(information);
|
|
155
|
+
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return options.reporting.none ? false : [information];
|
|
97
160
|
}
|
|
98
161
|
|
|
99
162
|
const typesLength = types.length;
|
|
@@ -103,60 +166,74 @@ export function validateObject(
|
|
|
103
166
|
for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
|
|
104
167
|
const type = types[typeIndex];
|
|
105
168
|
|
|
106
|
-
if (validateValue(type, property, value,
|
|
169
|
+
if (validateValue(type, property, value, options, information)) {
|
|
107
170
|
continue outer;
|
|
108
171
|
}
|
|
109
172
|
}
|
|
110
173
|
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
);
|
|
174
|
+
if (information.length === 0) {
|
|
175
|
+
information.push({
|
|
176
|
+
value,
|
|
177
|
+
key: {...key},
|
|
178
|
+
message: getInvalidTypeMessage(property, value),
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (options.reporting.throw && validation == null) {
|
|
183
|
+
throw new ValidationError(information);
|
|
122
184
|
}
|
|
123
185
|
|
|
124
186
|
validation?.push(...information);
|
|
125
187
|
|
|
126
|
-
|
|
188
|
+
if (options.reporting.all) {
|
|
189
|
+
allInformation.push(...information);
|
|
190
|
+
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return options.reporting.none ? false : information;
|
|
127
195
|
}
|
|
128
196
|
|
|
129
|
-
return true;
|
|
197
|
+
return options.reporting.none || allInformation.length === 0 ? true : allInformation;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function validateSchematic(
|
|
201
|
+
property: ValidatedProperty,
|
|
202
|
+
schematic: Schematic<unknown>,
|
|
203
|
+
value: unknown,
|
|
204
|
+
options: ValidationOptionsExtended,
|
|
205
|
+
validation: ValidationInformation[],
|
|
206
|
+
): boolean {
|
|
207
|
+
const properties = schematicProperties.get(schematic)!;
|
|
208
|
+
|
|
209
|
+
const result = validateObject(value, properties, options, property, validation);
|
|
210
|
+
|
|
211
|
+
return typeof result === 'boolean' ? result : result.length === 0;
|
|
130
212
|
}
|
|
131
213
|
|
|
132
214
|
function validateValue(
|
|
133
215
|
type: ValidatedPropertyType,
|
|
134
216
|
property: ValidatedProperty,
|
|
135
217
|
value: unknown,
|
|
136
|
-
|
|
218
|
+
options: ValidationOptionsExtended,
|
|
137
219
|
validation: ValidationInformation[],
|
|
138
220
|
): boolean {
|
|
139
|
-
let result: boolean;
|
|
140
|
-
|
|
141
221
|
switch (true) {
|
|
142
222
|
case typeof type === 'function':
|
|
143
|
-
|
|
144
|
-
break;
|
|
223
|
+
return (type as GenericCallback)(value);
|
|
145
224
|
|
|
146
|
-
case Array.isArray(type):
|
|
147
|
-
|
|
148
|
-
|
|
225
|
+
case Array.isArray(type): {
|
|
226
|
+
const validated = validateObject(value, type, options, property, validation);
|
|
227
|
+
|
|
228
|
+
return typeof validated === 'boolean' ? validated : false;
|
|
229
|
+
}
|
|
149
230
|
|
|
150
231
|
case isSchematic(type):
|
|
151
|
-
|
|
152
|
-
break;
|
|
232
|
+
return validateSchematic(property, type, value, options, validation);
|
|
153
233
|
|
|
154
234
|
default:
|
|
155
|
-
|
|
156
|
-
break;
|
|
235
|
+
return validateNamed(property, type as ValueName, value, validation);
|
|
157
236
|
}
|
|
158
|
-
|
|
159
|
-
return result;
|
|
160
237
|
}
|
|
161
238
|
|
|
162
239
|
//
|
|
@@ -169,7 +246,7 @@ const validators: Record<ValueName, (value: unknown) => boolean> = {
|
|
|
169
246
|
function: value => typeof value === 'function',
|
|
170
247
|
null: value => value === null,
|
|
171
248
|
number: value => typeof value === 'number',
|
|
172
|
-
object: value => typeof value ===
|
|
249
|
+
object: value => typeof value === TYPE_OBJECT && value !== null,
|
|
173
250
|
string: value => typeof value === 'string',
|
|
174
251
|
symbol: value => typeof value === 'symbol',
|
|
175
252
|
undefined: value => value === undefined,
|