@oscarpalmer/jhunal 0.19.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/constants.d.mts +7 -1
- package/dist/constants.mjs +7 -1
- package/dist/helpers.d.mts +7 -5
- package/dist/helpers.mjs +47 -18
- package/dist/index.d.mts +190 -109
- package/dist/index.mjs +161 -62
- 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 +55 -22
- package/dist/models/validation.model.mjs +4 -1
- package/dist/schematic.d.mts +103 -11
- package/dist/schematic.mjs +18 -8
- package/dist/validation/property.validation.mjs +2 -6
- package/dist/validation/value.validation.d.mts +3 -2
- package/dist/validation/value.validation.mjs +92 -34
- package/package.json +52 -52
- package/src/constants.ts +16 -0
- package/src/helpers.ts +81 -29
- 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 +57 -19
- package/src/schematic.ts +143 -17
- package/src/validation/property.validation.ts +8 -11
- package/src/validation/value.validation.ts +148 -44
|
@@ -1,33 +1,32 @@
|
|
|
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
|
+
import {join} from '@oscarpalmer/atoms/string';
|
|
4
|
+
import {clone} from '@oscarpalmer/atoms/value/clone';
|
|
3
5
|
import {TYPE_OBJECT} from '../constants';
|
|
4
6
|
import {
|
|
5
7
|
getInvalidInputMessage,
|
|
6
8
|
getInvalidMissingMessage,
|
|
7
9
|
getInvalidTypeMessage,
|
|
8
10
|
getInvalidValidatorMessage,
|
|
11
|
+
getUnknownKeysMessage,
|
|
9
12
|
isSchematic,
|
|
10
13
|
} from '../helpers';
|
|
11
14
|
import type {ValueName} from '../models/misc.model';
|
|
12
15
|
import {
|
|
13
16
|
ValidationError,
|
|
14
|
-
type ReportingInformation,
|
|
15
17
|
type ValidatedProperty,
|
|
16
18
|
type ValidatedPropertyType,
|
|
17
19
|
type ValidationInformation,
|
|
20
|
+
type ValidationParameters,
|
|
18
21
|
} from '../models/validation.model';
|
|
22
|
+
import {schematicProperties, type Schematic} from '../schematic';
|
|
19
23
|
|
|
20
|
-
function validateNamed(
|
|
21
|
-
property: ValidatedProperty,
|
|
22
|
-
name: ValueName,
|
|
23
|
-
value: unknown,
|
|
24
|
-
validation: ValidationInformation[],
|
|
25
|
-
): boolean {
|
|
24
|
+
function validateNamed(name: ValueName, value: unknown, parameters: ValidationParameters): boolean {
|
|
26
25
|
if (!validators[name](value)) {
|
|
27
26
|
return false;
|
|
28
27
|
}
|
|
29
28
|
|
|
30
|
-
const propertyValidators =
|
|
29
|
+
const propertyValidators = parameters.origin!.validators[name];
|
|
31
30
|
|
|
32
31
|
if (propertyValidators == null || propertyValidators.length === 0) {
|
|
33
32
|
return true;
|
|
@@ -39,10 +38,13 @@ function validateNamed(
|
|
|
39
38
|
const validator = propertyValidators[index];
|
|
40
39
|
|
|
41
40
|
if (!validator(value)) {
|
|
42
|
-
|
|
41
|
+
parameters.information!.push({
|
|
43
42
|
value,
|
|
44
|
-
key: {
|
|
45
|
-
|
|
43
|
+
key: {
|
|
44
|
+
full: parameters.prefix!,
|
|
45
|
+
short: parameters.origin!.key,
|
|
46
|
+
},
|
|
47
|
+
message: getInvalidValidatorMessage(parameters.prefix!, name, index, length),
|
|
46
48
|
validator: validator as GenericCallback,
|
|
47
49
|
});
|
|
48
50
|
|
|
@@ -56,27 +58,74 @@ function validateNamed(
|
|
|
56
58
|
export function validateObject(
|
|
57
59
|
obj: unknown,
|
|
58
60
|
properties: ValidatedProperty[],
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
): boolean | ValidationInformation[] {
|
|
61
|
+
parameters: ValidationParameters,
|
|
62
|
+
get: boolean,
|
|
63
|
+
): PlainObject | ValidationInformation[] | undefined {
|
|
63
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
|
+
|
|
64
73
|
const information = {
|
|
65
|
-
key
|
|
74
|
+
key,
|
|
66
75
|
message:
|
|
67
|
-
|
|
76
|
+
parameters?.origin == null
|
|
77
|
+
? getInvalidInputMessage(obj)
|
|
78
|
+
: getInvalidTypeMessage(key.full, parameters.origin.types, obj),
|
|
68
79
|
value: obj,
|
|
69
80
|
};
|
|
70
81
|
|
|
71
|
-
if (reporting.throw) {
|
|
82
|
+
if (parameters.reporting.throw) {
|
|
72
83
|
throw new ValidationError([information]);
|
|
73
84
|
}
|
|
74
85
|
|
|
75
|
-
|
|
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
|
+
}
|
|
76
123
|
}
|
|
77
124
|
|
|
78
125
|
const allInformation: ValidationInformation[] = [];
|
|
79
126
|
|
|
127
|
+
const output: PlainObject = {};
|
|
128
|
+
|
|
80
129
|
const propertiesLength = properties.length;
|
|
81
130
|
|
|
82
131
|
outer: for (let propertyIndex = 0; propertyIndex < propertiesLength; propertyIndex += 1) {
|
|
@@ -84,32 +133,43 @@ export function validateObject(
|
|
|
84
133
|
|
|
85
134
|
const {key, required, types} = property;
|
|
86
135
|
|
|
87
|
-
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
|
+
}
|
|
88
143
|
|
|
89
144
|
if (value === undefined && required) {
|
|
145
|
+
const prefixedKey = join([parameters.prefix, key], '.');
|
|
146
|
+
|
|
90
147
|
const information: ValidationInformation = {
|
|
91
148
|
value,
|
|
92
|
-
key: {
|
|
93
|
-
|
|
149
|
+
key: {
|
|
150
|
+
full: prefixedKey,
|
|
151
|
+
short: key,
|
|
152
|
+
},
|
|
153
|
+
message: getInvalidMissingMessage(prefixedKey, property.types),
|
|
94
154
|
};
|
|
95
155
|
|
|
96
|
-
if (reporting.throw
|
|
156
|
+
if (parameters.reporting.throw) {
|
|
97
157
|
throw new ValidationError([information]);
|
|
98
158
|
}
|
|
99
159
|
|
|
100
|
-
|
|
101
|
-
validation.push(information);
|
|
102
|
-
}
|
|
160
|
+
parameters?.information?.push(information);
|
|
103
161
|
|
|
104
|
-
if (reporting.all) {
|
|
162
|
+
if (parameters.reporting.all) {
|
|
105
163
|
allInformation.push(information);
|
|
106
164
|
|
|
107
165
|
continue;
|
|
108
166
|
}
|
|
109
167
|
|
|
110
|
-
return reporting.none ?
|
|
168
|
+
return parameters.reporting.none ? undefined : [information];
|
|
111
169
|
}
|
|
112
170
|
|
|
171
|
+
const prefixedKey = join([parameters.prefix, key], '.');
|
|
172
|
+
|
|
113
173
|
const typesLength = types.length;
|
|
114
174
|
|
|
115
175
|
const information: ValidationInformation[] = [];
|
|
@@ -117,7 +177,25 @@ export function validateObject(
|
|
|
117
177
|
for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
|
|
118
178
|
const type = types[typeIndex];
|
|
119
179
|
|
|
120
|
-
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
|
+
|
|
121
199
|
continue outer;
|
|
122
200
|
}
|
|
123
201
|
}
|
|
@@ -125,50 +203,76 @@ export function validateObject(
|
|
|
125
203
|
if (information.length === 0) {
|
|
126
204
|
information.push({
|
|
127
205
|
value,
|
|
128
|
-
key: {
|
|
129
|
-
|
|
206
|
+
key: {
|
|
207
|
+
full: prefixedKey,
|
|
208
|
+
short: key,
|
|
209
|
+
},
|
|
210
|
+
message: getInvalidTypeMessage(prefixedKey, property.types, value),
|
|
130
211
|
});
|
|
131
212
|
}
|
|
132
213
|
|
|
133
|
-
if (reporting.throw
|
|
214
|
+
if (parameters.reporting.throw) {
|
|
134
215
|
throw new ValidationError(information);
|
|
135
216
|
}
|
|
136
217
|
|
|
137
|
-
|
|
218
|
+
parameters?.information?.push(...information);
|
|
138
219
|
|
|
139
|
-
if (reporting.all) {
|
|
220
|
+
if (parameters.reporting.all) {
|
|
140
221
|
allInformation.push(...information);
|
|
141
222
|
|
|
142
223
|
continue;
|
|
143
224
|
}
|
|
144
225
|
|
|
145
|
-
return reporting.none ?
|
|
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
|
+
}
|
|
146
235
|
}
|
|
147
236
|
|
|
148
|
-
return reporting.none
|
|
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;
|
|
149
253
|
}
|
|
150
254
|
|
|
151
255
|
function validateValue(
|
|
152
256
|
type: ValidatedPropertyType,
|
|
153
|
-
property: ValidatedProperty,
|
|
154
257
|
value: unknown,
|
|
155
|
-
|
|
156
|
-
|
|
258
|
+
parameters: ValidationParameters,
|
|
259
|
+
get: boolean,
|
|
157
260
|
): boolean {
|
|
158
261
|
switch (true) {
|
|
159
262
|
case typeof type === 'function':
|
|
160
263
|
return (type as GenericCallback)(value);
|
|
161
264
|
|
|
162
265
|
case Array.isArray(type): {
|
|
163
|
-
const
|
|
164
|
-
|
|
266
|
+
const result = validateObject(value, type, parameters, get);
|
|
267
|
+
|
|
268
|
+
return result == null || Array.isArray(result) ? false : true;
|
|
165
269
|
}
|
|
166
270
|
|
|
167
271
|
case isSchematic(type):
|
|
168
|
-
return type
|
|
272
|
+
return validateSchematic(type, value, parameters, get);
|
|
169
273
|
|
|
170
274
|
default:
|
|
171
|
-
return validateNamed(
|
|
275
|
+
return validateNamed(type as ValueName, value, parameters);
|
|
172
276
|
}
|
|
173
277
|
}
|
|
174
278
|
|