@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
package/dist/helpers.d.mts
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
import { ReportingInformation,
|
|
1
|
+
import { ReportingInformation, ValidatedPropertyType, ValidationParameters } from "./models/validation.model.mjs";
|
|
2
2
|
import { Schematic } from "./schematic.mjs";
|
|
3
3
|
import { ValueName } from "./models/misc.model.mjs";
|
|
4
4
|
import { Constructor } from "@oscarpalmer/atoms/models";
|
|
5
5
|
|
|
6
6
|
//#region src/helpers.d.ts
|
|
7
7
|
declare function getInvalidInputMessage(actual: unknown): string;
|
|
8
|
-
declare function getInvalidMissingMessage(
|
|
9
|
-
declare function getInvalidTypeMessage(
|
|
10
|
-
declare function getInvalidValidatorMessage(
|
|
11
|
-
declare function
|
|
12
|
-
reporting: ReportingInformation;
|
|
13
|
-
strict: boolean;
|
|
14
|
-
};
|
|
8
|
+
declare function getInvalidMissingMessage(key: string, types: ValidatedPropertyType[]): string;
|
|
9
|
+
declare function getInvalidTypeMessage(key: string, types: ValidatedPropertyType[], actual: unknown): string;
|
|
10
|
+
declare function getInvalidValidatorMessage(key: string, type: ValueName, index: number, length: number): string;
|
|
11
|
+
declare function getParameters(input?: unknown): ValidationParameters;
|
|
15
12
|
declare function getReporting(value: unknown): ReportingInformation;
|
|
16
13
|
declare function getUnknownKeysMessage(keys: string[]): string;
|
|
17
14
|
/**
|
|
@@ -28,4 +25,4 @@ declare function instanceOf<Instance>(constructor: Constructor<Instance>): (valu
|
|
|
28
25
|
*/
|
|
29
26
|
declare function isSchematic(value: unknown): value is Schematic<never>;
|
|
30
27
|
//#endregion
|
|
31
|
-
export { getInvalidInputMessage, getInvalidMissingMessage, getInvalidTypeMessage, getInvalidValidatorMessage,
|
|
28
|
+
export { getInvalidInputMessage, getInvalidMissingMessage, getInvalidTypeMessage, getInvalidValidatorMessage, getParameters, getReporting, getUnknownKeysMessage, instanceOf, isSchematic };
|
package/dist/helpers.mjs
CHANGED
|
@@ -4,34 +4,37 @@ import { isConstructor, isPlainObject } from "@oscarpalmer/atoms/is";
|
|
|
4
4
|
function getInvalidInputMessage(actual) {
|
|
5
5
|
return VALIDATION_MESSAGE_INVALID_INPUT.replace("<>", getValueType(actual));
|
|
6
6
|
}
|
|
7
|
-
function getInvalidMissingMessage(
|
|
8
|
-
let message = VALIDATION_MESSAGE_INVALID_REQUIRED.replace("<>", renderTypes(
|
|
9
|
-
message = message.replace("<>",
|
|
7
|
+
function getInvalidMissingMessage(key, types) {
|
|
8
|
+
let message = VALIDATION_MESSAGE_INVALID_REQUIRED.replace("<>", renderTypes(types));
|
|
9
|
+
message = message.replace("<>", key);
|
|
10
10
|
return message;
|
|
11
11
|
}
|
|
12
|
-
function getInvalidTypeMessage(
|
|
13
|
-
let message = VALIDATION_MESSAGE_INVALID_TYPE.replace("<>", renderTypes(
|
|
14
|
-
message = message.replace("<>",
|
|
12
|
+
function getInvalidTypeMessage(key, types, actual) {
|
|
13
|
+
let message = VALIDATION_MESSAGE_INVALID_TYPE.replace("<>", renderTypes(types));
|
|
14
|
+
message = message.replace("<>", key);
|
|
15
15
|
message = message.replace("<>", getValueType(actual));
|
|
16
16
|
return message;
|
|
17
17
|
}
|
|
18
|
-
function getInvalidValidatorMessage(
|
|
19
|
-
let message = VALIDATION_MESSAGE_INVALID_VALUE.replace("<>",
|
|
18
|
+
function getInvalidValidatorMessage(key, type, index, length) {
|
|
19
|
+
let message = VALIDATION_MESSAGE_INVALID_VALUE.replace("<>", key);
|
|
20
20
|
message = message.replace("<>", type);
|
|
21
21
|
if (length > 1) message += VALIDATION_MESSAGE_INVALID_VALUE_SUFFIX.replace("<>", String(index));
|
|
22
22
|
return message;
|
|
23
23
|
}
|
|
24
|
-
function
|
|
24
|
+
function getParameters(input) {
|
|
25
25
|
if (typeof input === "boolean") return {
|
|
26
|
+
output: {},
|
|
26
27
|
reporting: getReporting(REPORTING_NONE),
|
|
27
28
|
strict: input
|
|
28
29
|
};
|
|
29
30
|
if (REPORTING_TYPES.has(input)) return {
|
|
31
|
+
output: {},
|
|
30
32
|
reporting: getReporting(input),
|
|
31
33
|
strict: false
|
|
32
34
|
};
|
|
33
35
|
const options = isPlainObject(input) ? input : {};
|
|
34
36
|
return {
|
|
37
|
+
output: {},
|
|
35
38
|
reporting: getReporting(options.errors),
|
|
36
39
|
strict: typeof options.strict === "boolean" ? options.strict : false
|
|
37
40
|
};
|
|
@@ -113,4 +116,4 @@ function renderTypes(types) {
|
|
|
113
116
|
return renderParts(parts, CONJUNCTION_OR, CONJUNCTION_OR_COMMA);
|
|
114
117
|
}
|
|
115
118
|
//#endregion
|
|
116
|
-
export { getInvalidInputMessage, getInvalidMissingMessage, getInvalidTypeMessage, getInvalidValidatorMessage,
|
|
119
|
+
export { getInvalidInputMessage, getInvalidMissingMessage, getInvalidTypeMessage, getInvalidValidatorMessage, getParameters, getReporting, getUnknownKeysMessage, instanceOf, isSchematic };
|
package/dist/index.d.mts
CHANGED
|
@@ -214,7 +214,7 @@ type ValidatedProperty = {
|
|
|
214
214
|
/**
|
|
215
215
|
* The property name in the schema
|
|
216
216
|
*/
|
|
217
|
-
key:
|
|
217
|
+
key: string;
|
|
218
218
|
/**
|
|
219
219
|
* Whether the property is required
|
|
220
220
|
*/
|
|
@@ -228,15 +228,6 @@ type ValidatedProperty = {
|
|
|
228
228
|
*/
|
|
229
229
|
validators: ValidatedPropertyValidators;
|
|
230
230
|
};
|
|
231
|
-
/**
|
|
232
|
-
* The full and short forms of a property's key path
|
|
233
|
-
*
|
|
234
|
-
* For a nested property `address.street`: `full` is `'address.street'`, `short` is `'street'`
|
|
235
|
-
*/
|
|
236
|
-
type ValidatedPropertyKey = {
|
|
237
|
-
full: string;
|
|
238
|
-
short: string;
|
|
239
|
-
};
|
|
240
231
|
/**
|
|
241
232
|
* A union of valid types for a {@link ValidatedProperty}'s `types` array
|
|
242
233
|
*
|
|
@@ -266,9 +257,12 @@ type ValidationInformation = {
|
|
|
266
257
|
value: unknown;
|
|
267
258
|
};
|
|
268
259
|
/**
|
|
269
|
-
*
|
|
260
|
+
*
|
|
270
261
|
*/
|
|
271
|
-
type ValidationInformationKey =
|
|
262
|
+
type ValidationInformationKey = {
|
|
263
|
+
full: string;
|
|
264
|
+
short: string;
|
|
265
|
+
};
|
|
272
266
|
/**
|
|
273
267
|
* Options for validation
|
|
274
268
|
*/
|
|
@@ -291,10 +285,73 @@ declare class Schematic<Model> {
|
|
|
291
285
|
#private;
|
|
292
286
|
private readonly $schematic;
|
|
293
287
|
constructor(properties: ValidatedProperty[]);
|
|
288
|
+
/**
|
|
289
|
+
* Parse a value according to the schema
|
|
290
|
+
*
|
|
291
|
+
* Returns a deeply cloned version of the value or throws an error for the first property that fails validation
|
|
292
|
+
* @param value Value to parse
|
|
293
|
+
* @param options Validation options
|
|
294
|
+
* @returns Deeply cloned version of the value if it matches the schema, otherwise throws an error
|
|
295
|
+
*/
|
|
296
|
+
get(value: unknown, options: ValidationOptions<'throw'>): Model;
|
|
297
|
+
/**
|
|
298
|
+
* Parse a value according to the schema
|
|
299
|
+
*
|
|
300
|
+
* Returns a deeply cloned version of the value or throws an error for the first property that fails validation
|
|
301
|
+
* @param value Value to parse
|
|
302
|
+
* @param errors Reporting type
|
|
303
|
+
* @returns Deeply cloned version of the value if it matches the schema, otherwise throws an error
|
|
304
|
+
*/
|
|
305
|
+
get(value: unknown, errors: 'throw'): Model;
|
|
306
|
+
/**
|
|
307
|
+
* Parse a value according to the schema
|
|
308
|
+
*
|
|
309
|
+
* 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
|
|
310
|
+
* @param value Value to parse
|
|
311
|
+
* @param options Validation options
|
|
312
|
+
* @returns Result holding deeply cloned value or all validation information
|
|
313
|
+
*/
|
|
314
|
+
get(value: unknown, options: ValidationOptions<'all'>): Result<Model, ValidationInformation[]>;
|
|
315
|
+
/**
|
|
316
|
+
* Parse a value according to the schema
|
|
317
|
+
*
|
|
318
|
+
* 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
|
|
319
|
+
* @param value Value to parse
|
|
320
|
+
* @param errors Reporting type
|
|
321
|
+
* @returns Result holding deeply cloned value or all validation information
|
|
322
|
+
*/
|
|
323
|
+
get(value: unknown, errors: 'all'): Result<Model, ValidationInformation[]>;
|
|
324
|
+
/**
|
|
325
|
+
* Parse a value according to the schema
|
|
326
|
+
*
|
|
327
|
+
* Returns a deeply cloned version of the value or all validation information for the first failing property
|
|
328
|
+
* @param value Value to parse
|
|
329
|
+
* @param options Validation options
|
|
330
|
+
* @returns Result holding deeply cloned value or all validation information
|
|
331
|
+
*/
|
|
332
|
+
get(value: unknown, options: ValidationOptions<'first'>): Result<Model, ValidationInformation>;
|
|
333
|
+
/**
|
|
334
|
+
* Parse a value according to the schema
|
|
335
|
+
*
|
|
336
|
+
* Returns a deeply cloned version of the value or all validation information for the first failing property
|
|
337
|
+
* @param value Value to parse
|
|
338
|
+
* @param errors Reporting type
|
|
339
|
+
* @returns Result holding deeply cloned value or all validation information
|
|
340
|
+
*/
|
|
341
|
+
get(value: unknown, errors: 'first'): Result<Model, ValidationInformation>;
|
|
342
|
+
/**
|
|
343
|
+
* Parse a value according to the schema
|
|
344
|
+
*
|
|
345
|
+
* Returns a deeply cloned version of the value or `undefined` if the value does not match the schema
|
|
346
|
+
* @param value Value to parse
|
|
347
|
+
* @param strict Validate if unknown keys are present in the object? _(defaults to `false`)_
|
|
348
|
+
* @returns Deeply cloned value, or `undefined` if it's invalid
|
|
349
|
+
*/
|
|
350
|
+
get(value: unknown, strict?: true): Model | undefined;
|
|
294
351
|
/**
|
|
295
352
|
* Does the value match the schema?
|
|
296
353
|
*
|
|
297
|
-
* 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
|
|
354
|
+
* 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
|
|
298
355
|
* @param value Value to validate
|
|
299
356
|
* @param options Validation options
|
|
300
357
|
* @returns `true` if the value matches the schema, otherwise throws an error
|
|
@@ -303,7 +360,7 @@ declare class Schematic<Model> {
|
|
|
303
360
|
/**
|
|
304
361
|
* Does the value match the schema?
|
|
305
362
|
*
|
|
306
|
-
* 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
|
|
363
|
+
* 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
|
|
307
364
|
* @param value Value to validate
|
|
308
365
|
* @param errors Reporting type
|
|
309
366
|
* @returns `true` if the value matches the schema, otherwise throws an error
|
|
@@ -312,25 +369,25 @@ declare class Schematic<Model> {
|
|
|
312
369
|
/**
|
|
313
370
|
* Does the value match the schema?
|
|
314
371
|
*
|
|
315
|
-
* 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
|
|
372
|
+
* 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
|
|
316
373
|
* @param value Value to validate
|
|
317
374
|
* @param options Validation options
|
|
318
|
-
* @returns `true`
|
|
375
|
+
* @returns Result holding `true` or all validation information
|
|
319
376
|
*/
|
|
320
377
|
is(value: unknown, options: ValidationOptions<'all'>): Result<true, ValidationInformation[]>;
|
|
321
378
|
/**
|
|
322
379
|
* Does the value match the schema?
|
|
323
380
|
*
|
|
324
|
-
* 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
|
|
381
|
+
* 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
|
|
325
382
|
* @param value Value to validate
|
|
326
383
|
* @param errors Reporting type
|
|
327
|
-
* @returns `true`
|
|
384
|
+
* @returns Result holding `true` or all validation information
|
|
328
385
|
*/
|
|
329
386
|
is(value: unknown, errors: 'all'): Result<true, ValidationInformation[]>;
|
|
330
387
|
/**
|
|
331
388
|
* Does the value match the schema?
|
|
332
389
|
*
|
|
333
|
-
* Will validate that the value matches the schema and return a result of `true` or all validation information for the failing property
|
|
390
|
+
* Will validate that the value matches the schema and return a result of `true` or all validation information for the first failing property
|
|
334
391
|
* @param value Value to validate
|
|
335
392
|
* @param options Validation options
|
|
336
393
|
* @returns `true` if the value matches the schema, otherwise `false`
|
|
@@ -339,7 +396,7 @@ declare class Schematic<Model> {
|
|
|
339
396
|
/**
|
|
340
397
|
* Does the value match the schema?
|
|
341
398
|
*
|
|
342
|
-
* Will validate that the value matches the schema and return a result of `true` or all validation information for the failing property
|
|
399
|
+
* Will validate that the value matches the schema and return a result of `true` or all validation information for the first failing property
|
|
343
400
|
* @param value Value to validate
|
|
344
401
|
* @param errors Reporting type
|
|
345
402
|
* @returns `true` if the value matches the schema, otherwise `false`
|
|
@@ -348,7 +405,7 @@ declare class Schematic<Model> {
|
|
|
348
405
|
/**
|
|
349
406
|
* Does the value match the schema?
|
|
350
407
|
*
|
|
351
|
-
* Will validate that the value matches the schema and return `true` or `false`, without any validation information for validation failures
|
|
408
|
+
* Will validate that the value matches the schema and return `true` or `false`, without any validation information for validation failures
|
|
352
409
|
* @param value Value to validate
|
|
353
410
|
* @param strict Validate if unknown keys are present in the object? _(defaults to `false`)_
|
|
354
411
|
* @returns `true` if the value matches the schema, otherwise `false`
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isConstructor, isPlainObject } from "@oscarpalmer/atoms/is";
|
|
2
2
|
import { join } from "@oscarpalmer/atoms/string";
|
|
3
|
-
import { error } from "@oscarpalmer/atoms/result/misc";
|
|
3
|
+
import { error, ok } from "@oscarpalmer/atoms/result/misc";
|
|
4
|
+
import { clone } from "@oscarpalmer/atoms/value/clone";
|
|
4
5
|
//#region src/constants.ts
|
|
5
6
|
const CONJUNCTION_OR = " or ";
|
|
6
7
|
const CONJUNCTION_OR_COMMA = ", or ";
|
|
@@ -63,34 +64,37 @@ const TYPE_ALL = new Set([
|
|
|
63
64
|
function getInvalidInputMessage(actual) {
|
|
64
65
|
return VALIDATION_MESSAGE_INVALID_INPUT.replace("<>", getValueType(actual));
|
|
65
66
|
}
|
|
66
|
-
function getInvalidMissingMessage(
|
|
67
|
-
let message = VALIDATION_MESSAGE_INVALID_REQUIRED.replace("<>", renderTypes(
|
|
68
|
-
message = message.replace("<>",
|
|
67
|
+
function getInvalidMissingMessage(key, types) {
|
|
68
|
+
let message = VALIDATION_MESSAGE_INVALID_REQUIRED.replace("<>", renderTypes(types));
|
|
69
|
+
message = message.replace("<>", key);
|
|
69
70
|
return message;
|
|
70
71
|
}
|
|
71
|
-
function getInvalidTypeMessage(
|
|
72
|
-
let message = VALIDATION_MESSAGE_INVALID_TYPE.replace("<>", renderTypes(
|
|
73
|
-
message = message.replace("<>",
|
|
72
|
+
function getInvalidTypeMessage(key, types, actual) {
|
|
73
|
+
let message = VALIDATION_MESSAGE_INVALID_TYPE.replace("<>", renderTypes(types));
|
|
74
|
+
message = message.replace("<>", key);
|
|
74
75
|
message = message.replace("<>", getValueType(actual));
|
|
75
76
|
return message;
|
|
76
77
|
}
|
|
77
|
-
function getInvalidValidatorMessage(
|
|
78
|
-
let message = VALIDATION_MESSAGE_INVALID_VALUE.replace("<>",
|
|
78
|
+
function getInvalidValidatorMessage(key, type, index, length) {
|
|
79
|
+
let message = VALIDATION_MESSAGE_INVALID_VALUE.replace("<>", key);
|
|
79
80
|
message = message.replace("<>", type);
|
|
80
81
|
if (length > 1) message += VALIDATION_MESSAGE_INVALID_VALUE_SUFFIX.replace("<>", String(index));
|
|
81
82
|
return message;
|
|
82
83
|
}
|
|
83
|
-
function
|
|
84
|
+
function getParameters(input) {
|
|
84
85
|
if (typeof input === "boolean") return {
|
|
86
|
+
output: {},
|
|
85
87
|
reporting: getReporting(REPORTING_NONE),
|
|
86
88
|
strict: input
|
|
87
89
|
};
|
|
88
90
|
if (REPORTING_TYPES.has(input)) return {
|
|
91
|
+
output: {},
|
|
89
92
|
reporting: getReporting(input),
|
|
90
93
|
strict: false
|
|
91
94
|
};
|
|
92
95
|
const options = isPlainObject(input) ? input : {};
|
|
93
96
|
return {
|
|
97
|
+
output: {},
|
|
94
98
|
reporting: getReporting(options.errors),
|
|
95
99
|
strict: typeof options.strict === "boolean" ? options.strict : false
|
|
96
100
|
};
|
|
@@ -210,9 +214,8 @@ function getProperties(original, prefix, fromType) {
|
|
|
210
214
|
const properties = [];
|
|
211
215
|
for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
|
|
212
216
|
const key = keys[keyIndex];
|
|
213
|
-
const prefixed = join([prefix, key], ".");
|
|
214
217
|
const value = original[key];
|
|
215
|
-
if (value == null) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE.replace("<>",
|
|
218
|
+
if (value == null) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE.replace("<>", join([prefix, key], ".")));
|
|
216
219
|
const types = [];
|
|
217
220
|
let required = true;
|
|
218
221
|
let validators = {};
|
|
@@ -224,12 +227,9 @@ function getProperties(original, prefix, fromType) {
|
|
|
224
227
|
} else types.push(...getTypes(key, value, prefix));
|
|
225
228
|
if (!required && !types.includes("undefined")) types.push(TYPE_UNDEFINED);
|
|
226
229
|
properties.push({
|
|
230
|
+
key,
|
|
227
231
|
types,
|
|
228
232
|
validators,
|
|
229
|
-
key: {
|
|
230
|
-
full: prefixed,
|
|
231
|
-
short: key
|
|
232
|
-
},
|
|
233
233
|
required: required && !types.includes("undefined")
|
|
234
234
|
});
|
|
235
235
|
}
|
|
@@ -284,18 +284,21 @@ function getValidators(original) {
|
|
|
284
284
|
}
|
|
285
285
|
//#endregion
|
|
286
286
|
//#region src/validation/value.validation.ts
|
|
287
|
-
function validateNamed(
|
|
287
|
+
function validateNamed(name, value, parameters) {
|
|
288
288
|
if (!validators[name](value)) return false;
|
|
289
|
-
const propertyValidators =
|
|
289
|
+
const propertyValidators = parameters.origin.validators[name];
|
|
290
290
|
if (propertyValidators == null || propertyValidators.length === 0) return true;
|
|
291
291
|
const { length } = propertyValidators;
|
|
292
292
|
for (let index = 0; index < length; index += 1) {
|
|
293
293
|
const validator = propertyValidators[index];
|
|
294
294
|
if (!validator(value)) {
|
|
295
|
-
|
|
295
|
+
parameters.information.push({
|
|
296
296
|
value,
|
|
297
|
-
key: {
|
|
298
|
-
|
|
297
|
+
key: {
|
|
298
|
+
full: parameters.prefix,
|
|
299
|
+
short: parameters.origin.key
|
|
300
|
+
},
|
|
301
|
+
message: getInvalidValidatorMessage(parameters.prefix, name, index, length),
|
|
299
302
|
validator
|
|
300
303
|
});
|
|
301
304
|
return false;
|
|
@@ -303,103 +306,121 @@ function validateNamed(property, name, value, validation) {
|
|
|
303
306
|
}
|
|
304
307
|
return true;
|
|
305
308
|
}
|
|
306
|
-
function validateObject(obj, properties,
|
|
309
|
+
function validateObject(obj, properties, parameters, get) {
|
|
307
310
|
if (!isPlainObject(obj)) {
|
|
308
|
-
const key = origin == null ? {
|
|
311
|
+
const key = parameters?.origin == null ? {
|
|
309
312
|
full: "",
|
|
310
313
|
short: ""
|
|
311
|
-
} : {
|
|
314
|
+
} : {
|
|
315
|
+
full: parameters.prefix,
|
|
316
|
+
short: parameters.origin.key
|
|
317
|
+
};
|
|
312
318
|
const information = {
|
|
313
319
|
key,
|
|
314
|
-
message: origin == null ? getInvalidInputMessage(obj) : getInvalidTypeMessage(
|
|
315
|
-
...origin,
|
|
316
|
-
key
|
|
317
|
-
}, obj),
|
|
320
|
+
message: parameters?.origin == null ? getInvalidInputMessage(obj) : getInvalidTypeMessage(key.full, parameters.origin.types, obj),
|
|
318
321
|
value: obj
|
|
319
322
|
};
|
|
320
|
-
if (
|
|
321
|
-
|
|
322
|
-
return
|
|
323
|
+
if (parameters.reporting.throw) throw new ValidationError([information]);
|
|
324
|
+
parameters?.information?.push(information);
|
|
325
|
+
return parameters.reporting.none ? void 0 : [information];
|
|
323
326
|
}
|
|
324
|
-
if (
|
|
327
|
+
if (parameters.strict) {
|
|
325
328
|
const objKeys = Object.keys(obj);
|
|
326
|
-
const propertiesKeys = new Set(properties.map((property) => property.key
|
|
329
|
+
const propertiesKeys = new Set(properties.map((property) => property.key));
|
|
327
330
|
const unknownKeys = objKeys.filter((key) => !propertiesKeys.has(key));
|
|
328
331
|
if (unknownKeys.length > 0) {
|
|
329
332
|
const information = {
|
|
330
|
-
key: origin == null ? {
|
|
333
|
+
key: parameters?.origin == null ? {
|
|
331
334
|
full: "",
|
|
332
335
|
short: ""
|
|
333
|
-
} : {
|
|
334
|
-
|
|
336
|
+
} : {
|
|
337
|
+
full: join([parameters.prefix, parameters.origin?.key], "."),
|
|
338
|
+
short: parameters.origin.key
|
|
339
|
+
},
|
|
340
|
+
message: getUnknownKeysMessage(unknownKeys.map((key) => join([parameters?.prefix, key], "."))),
|
|
335
341
|
value: obj
|
|
336
342
|
};
|
|
337
|
-
if (
|
|
338
|
-
|
|
339
|
-
return
|
|
343
|
+
if (parameters.reporting.throw) throw new ValidationError([information]);
|
|
344
|
+
parameters?.information?.push(information);
|
|
345
|
+
return parameters.reporting.none ? void 0 : [information];
|
|
340
346
|
}
|
|
341
347
|
}
|
|
342
348
|
const allInformation = [];
|
|
349
|
+
const output = {};
|
|
343
350
|
const propertiesLength = properties.length;
|
|
344
351
|
outer: for (let propertyIndex = 0; propertyIndex < propertiesLength; propertyIndex += 1) {
|
|
345
|
-
|
|
346
|
-
property = {
|
|
347
|
-
...property,
|
|
348
|
-
key: {
|
|
349
|
-
full: join([origin?.key.full, property.key.short], "."),
|
|
350
|
-
short: property.key.short
|
|
351
|
-
}
|
|
352
|
-
};
|
|
352
|
+
const property = properties[propertyIndex];
|
|
353
353
|
const { key, required, types } = property;
|
|
354
|
-
const value = obj[key
|
|
354
|
+
const value = obj[key];
|
|
355
|
+
if (get && value === void 0 && !required) continue;
|
|
355
356
|
if (value === void 0 && required) {
|
|
357
|
+
const prefixedKey = join([parameters.prefix, key], ".");
|
|
356
358
|
const information = {
|
|
357
359
|
value,
|
|
358
|
-
key: {
|
|
359
|
-
|
|
360
|
+
key: {
|
|
361
|
+
full: prefixedKey,
|
|
362
|
+
short: key
|
|
363
|
+
},
|
|
364
|
+
message: getInvalidMissingMessage(prefixedKey, property.types)
|
|
360
365
|
};
|
|
361
|
-
if (
|
|
362
|
-
|
|
363
|
-
if (
|
|
366
|
+
if (parameters.reporting.throw) throw new ValidationError([information]);
|
|
367
|
+
parameters?.information?.push(information);
|
|
368
|
+
if (parameters.reporting.all) {
|
|
364
369
|
allInformation.push(information);
|
|
365
370
|
continue;
|
|
366
371
|
}
|
|
367
|
-
return
|
|
372
|
+
return parameters.reporting.none ? void 0 : [information];
|
|
368
373
|
}
|
|
374
|
+
const prefixedKey = join([parameters.prefix, key], ".");
|
|
369
375
|
const typesLength = types.length;
|
|
370
376
|
const information = [];
|
|
371
377
|
for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
|
|
372
378
|
const type = types[typeIndex];
|
|
373
|
-
if (validateValue(type,
|
|
379
|
+
if (validateValue(type, value, {
|
|
380
|
+
information,
|
|
381
|
+
output,
|
|
382
|
+
origin: property,
|
|
383
|
+
prefix: prefixedKey,
|
|
384
|
+
reporting: parameters.reporting,
|
|
385
|
+
strict: parameters.strict
|
|
386
|
+
}, get)) {
|
|
387
|
+
if (get) output[key] = clone(value);
|
|
388
|
+
continue outer;
|
|
389
|
+
}
|
|
374
390
|
}
|
|
375
391
|
if (information.length === 0) information.push({
|
|
376
392
|
value,
|
|
377
|
-
key: {
|
|
378
|
-
|
|
393
|
+
key: {
|
|
394
|
+
full: prefixedKey,
|
|
395
|
+
short: key
|
|
396
|
+
},
|
|
397
|
+
message: getInvalidTypeMessage(prefixedKey, property.types, value)
|
|
379
398
|
});
|
|
380
|
-
if (
|
|
381
|
-
|
|
382
|
-
if (
|
|
399
|
+
if (parameters.reporting.throw) throw new ValidationError(information);
|
|
400
|
+
parameters?.information?.push(...information);
|
|
401
|
+
if (parameters.reporting.all) {
|
|
383
402
|
allInformation.push(...information);
|
|
384
403
|
continue;
|
|
385
404
|
}
|
|
386
|
-
return
|
|
405
|
+
return parameters.reporting.none ? void 0 : information;
|
|
387
406
|
}
|
|
388
|
-
|
|
407
|
+
if (get) if (parameters.origin == null) parameters.output = output;
|
|
408
|
+
else parameters.output[parameters.origin.key] = output;
|
|
409
|
+
return parameters.reporting.none || allInformation.length === 0 ? parameters.output : allInformation;
|
|
389
410
|
}
|
|
390
|
-
function validateSchematic(
|
|
391
|
-
const result = validateObject(value, schematicProperties.get(schematic),
|
|
392
|
-
return
|
|
411
|
+
function validateSchematic(schematic, value, parameters, get) {
|
|
412
|
+
const result = validateObject(value, schematicProperties.get(schematic), parameters, get);
|
|
413
|
+
return result == null || Array.isArray(result) ? false : true;
|
|
393
414
|
}
|
|
394
|
-
function validateValue(type,
|
|
415
|
+
function validateValue(type, value, parameters, get) {
|
|
395
416
|
switch (true) {
|
|
396
417
|
case typeof type === "function": return type(value);
|
|
397
418
|
case Array.isArray(type): {
|
|
398
|
-
const
|
|
399
|
-
return
|
|
419
|
+
const result = validateObject(value, type, parameters, get);
|
|
420
|
+
return result == null || Array.isArray(result) ? false : true;
|
|
400
421
|
}
|
|
401
|
-
case isSchematic(type): return validateSchematic(
|
|
402
|
-
default: return validateNamed(
|
|
422
|
+
case isSchematic(type): return validateSchematic(type, value, parameters, get);
|
|
423
|
+
default: return validateNamed(type, value, parameters);
|
|
403
424
|
}
|
|
404
425
|
}
|
|
405
426
|
const validators = {
|
|
@@ -427,14 +448,19 @@ var Schematic = class {
|
|
|
427
448
|
this.#properties = properties;
|
|
428
449
|
schematicProperties.set(this, properties);
|
|
429
450
|
}
|
|
451
|
+
get(value, options) {
|
|
452
|
+
const parameters = getParameters(options);
|
|
453
|
+
const result = validateObject(value, this.#properties, parameters, true);
|
|
454
|
+
if (result == null) return;
|
|
455
|
+
if (!Array.isArray(result)) return parameters.reporting.none ? result : ok(result);
|
|
456
|
+
return error(parameters.reporting.all ? result : result[0]);
|
|
457
|
+
}
|
|
430
458
|
is(value, options) {
|
|
431
|
-
const
|
|
432
|
-
const result = validateObject(value, this.#properties,
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
if (typeof result === "boolean") return result;
|
|
437
|
-
return error(reporting.all ? result : result[0]);
|
|
459
|
+
const parameters = getParameters(options);
|
|
460
|
+
const result = validateObject(value, this.#properties, parameters, false);
|
|
461
|
+
if (result == null) return false;
|
|
462
|
+
if (!Array.isArray(result)) return parameters.reporting.none ? true : ok(true);
|
|
463
|
+
return error(parameters.reporting.all ? result : result[0]);
|
|
438
464
|
}
|
|
439
465
|
};
|
|
440
466
|
function schematic(schema) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Schematic } from "../schematic.mjs";
|
|
2
2
|
import { ValueName } from "./misc.model.mjs";
|
|
3
|
-
import { GenericCallback } from "@oscarpalmer/atoms/models";
|
|
3
|
+
import { GenericCallback, PlainObject } from "@oscarpalmer/atoms/models";
|
|
4
4
|
|
|
5
5
|
//#region src/models/validation.model.d.ts
|
|
6
6
|
/**
|
|
@@ -41,7 +41,7 @@ type ValidatedProperty = {
|
|
|
41
41
|
/**
|
|
42
42
|
* The property name in the schema
|
|
43
43
|
*/
|
|
44
|
-
key:
|
|
44
|
+
key: string;
|
|
45
45
|
/**
|
|
46
46
|
* Whether the property is required
|
|
47
47
|
*/
|
|
@@ -55,15 +55,6 @@ type ValidatedProperty = {
|
|
|
55
55
|
*/
|
|
56
56
|
validators: ValidatedPropertyValidators;
|
|
57
57
|
};
|
|
58
|
-
/**
|
|
59
|
-
* The full and short forms of a property's key path
|
|
60
|
-
*
|
|
61
|
-
* For a nested property `address.street`: `full` is `'address.street'`, `short` is `'street'`
|
|
62
|
-
*/
|
|
63
|
-
type ValidatedPropertyKey = {
|
|
64
|
-
full: string;
|
|
65
|
-
short: string;
|
|
66
|
-
};
|
|
67
58
|
/**
|
|
68
59
|
* A union of valid types for a {@link ValidatedProperty}'s `types` array
|
|
69
60
|
*
|
|
@@ -93,9 +84,12 @@ type ValidationInformation = {
|
|
|
93
84
|
value: unknown;
|
|
94
85
|
};
|
|
95
86
|
/**
|
|
96
|
-
*
|
|
87
|
+
*
|
|
97
88
|
*/
|
|
98
|
-
type ValidationInformationKey =
|
|
89
|
+
type ValidationInformationKey = {
|
|
90
|
+
full: string;
|
|
91
|
+
short: string;
|
|
92
|
+
};
|
|
99
93
|
/**
|
|
100
94
|
* Options for validation
|
|
101
95
|
*/
|
|
@@ -109,9 +103,13 @@ type ValidationOptions<Errors extends ReportingType> = {
|
|
|
109
103
|
*/
|
|
110
104
|
strict?: boolean;
|
|
111
105
|
};
|
|
112
|
-
type
|
|
106
|
+
type ValidationParameters = {
|
|
107
|
+
information?: ValidationInformation[];
|
|
108
|
+
origin?: ValidatedProperty;
|
|
109
|
+
output: PlainObject;
|
|
110
|
+
prefix?: string;
|
|
113
111
|
reporting: ReportingInformation;
|
|
114
112
|
strict: boolean;
|
|
115
113
|
};
|
|
116
114
|
//#endregion
|
|
117
|
-
export { ReportingInformation, ReportingType, SchematicError, ValidatedProperty,
|
|
115
|
+
export { ReportingInformation, ReportingType, SchematicError, ValidatedProperty, ValidatedPropertyType, ValidatedPropertyValidators, ValidationError, ValidationInformation, ValidationInformationKey, ValidationOptions, ValidationParameters };
|