@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
package/dist/helpers.d.mts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { ReportingInformation,
|
|
1
|
+
import { ReportingInformation, ValidatorParameters, ValidatorType } 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(key: string, types:
|
|
9
|
-
declare function getInvalidTypeMessage(key: string, types:
|
|
8
|
+
declare function getInvalidMissingMessage(key: string, types: ValidatorType[]): string;
|
|
9
|
+
declare function getInvalidTypeMessage(key: string, types: ValidatorType[], actual: unknown): string;
|
|
10
10
|
declare function getInvalidValidatorMessage(key: string, type: ValueName, index: number, length: number): string;
|
|
11
|
-
declare function getParameters(input?: unknown):
|
|
11
|
+
declare function getParameters(input?: unknown): ValidatorParameters;
|
|
12
12
|
declare function getReporting(value: unknown): ReportingInformation;
|
|
13
13
|
declare function getUnknownKeysMessage(keys: string[]): string;
|
|
14
14
|
/**
|
package/dist/helpers.mjs
CHANGED
|
@@ -41,7 +41,8 @@ function getParameters(input) {
|
|
|
41
41
|
}
|
|
42
42
|
function getPropertyType(original) {
|
|
43
43
|
if (typeof original === "function") return "a validated value";
|
|
44
|
-
if (Array.isArray(original)) return `'
|
|
44
|
+
if (Array.isArray(original)) return `'array'`;
|
|
45
|
+
if (isPlainObject(original)) return `'${TYPE_OBJECT}'`;
|
|
45
46
|
if (isSchematic(original)) return `a ${NAME_SCHEMATIC}`;
|
|
46
47
|
return `'${String(original)}'`;
|
|
47
48
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -182,13 +182,16 @@ type TypedSchemaRequired<Model extends PlainObject> = {
|
|
|
182
182
|
} & TypedSchema<Model>;
|
|
183
183
|
//#endregion
|
|
184
184
|
//#region src/models/validation.model.d.ts
|
|
185
|
+
type ReportingInformation = Record<ReportingType, boolean> & {
|
|
186
|
+
type: ReportingType;
|
|
187
|
+
};
|
|
185
188
|
/**
|
|
186
189
|
* Controls how validation failures are reported
|
|
187
190
|
*
|
|
188
|
-
* - `'none'
|
|
189
|
-
* - `'first'
|
|
190
|
-
* - `'all'
|
|
191
|
-
* - `'throw'
|
|
191
|
+
* - `'none'`, returns a boolean _(default)_
|
|
192
|
+
* - `'first'`, returns the first failure as a `Result`
|
|
193
|
+
* - `'all'`, returns all failures as a `Result` _(from same level)_
|
|
194
|
+
* - `'throw'`, throws a {@link ValidationError} on failure
|
|
192
195
|
*/
|
|
193
196
|
type ReportingType = 'all' | 'first' | 'none' | 'throw';
|
|
194
197
|
/**
|
|
@@ -197,49 +200,6 @@ type ReportingType = 'all' | 'first' | 'none' | 'throw';
|
|
|
197
200
|
declare class SchematicError extends Error {
|
|
198
201
|
constructor(message: string);
|
|
199
202
|
}
|
|
200
|
-
/**
|
|
201
|
-
* The runtime representation of a parsed schema property, used internally during validation
|
|
202
|
-
*
|
|
203
|
-
* @example
|
|
204
|
-
* ```ts
|
|
205
|
-
* const parsed: ValidatedProperty = {
|
|
206
|
-
* key: 'age',
|
|
207
|
-
* required: true,
|
|
208
|
-
* types: ['number'],
|
|
209
|
-
* validators: { number: [(v) => v > 0] },
|
|
210
|
-
* };
|
|
211
|
-
* ```
|
|
212
|
-
*/
|
|
213
|
-
type ValidatedProperty = {
|
|
214
|
-
/**
|
|
215
|
-
* The property name in the schema
|
|
216
|
-
*/
|
|
217
|
-
key: string;
|
|
218
|
-
/**
|
|
219
|
-
* Whether the property is required
|
|
220
|
-
*/
|
|
221
|
-
required: boolean;
|
|
222
|
-
/**
|
|
223
|
-
* The allowed types for this property
|
|
224
|
-
*/
|
|
225
|
-
types: ValidatedPropertyType[];
|
|
226
|
-
/**
|
|
227
|
-
* Custom validators grouped by {@link ValueName}
|
|
228
|
-
*/
|
|
229
|
-
validators: ValidatedPropertyValidators;
|
|
230
|
-
};
|
|
231
|
-
/**
|
|
232
|
-
* A union of valid types for a {@link ValidatedProperty}'s `types` array
|
|
233
|
-
*
|
|
234
|
-
* Can be a callback _(custom validator)_, a {@link Schematic}, a nested {@link ValidatedProperty}, or a {@link ValueName} string
|
|
235
|
-
*/
|
|
236
|
-
type ValidatedPropertyType = GenericCallback | ValidatedProperty[] | Schematic<unknown> | ValueName;
|
|
237
|
-
/**
|
|
238
|
-
* A map of validator functions keyed by {@link ValueName}, used at runtime in {@link ValidatedProperty}
|
|
239
|
-
*
|
|
240
|
-
* Each key holds an array of validator functions that receive an `unknown` value and return a `boolean`
|
|
241
|
-
*/
|
|
242
|
-
type ValidatedPropertyValidators = { [Key in ValueName]?: Array<(value: unknown) => boolean> };
|
|
243
203
|
/**
|
|
244
204
|
* Thrown in `'throw'` mode when one or more properties fail validation; `information` holds all failures
|
|
245
205
|
*/
|
|
@@ -276,6 +236,13 @@ type ValidationOptions<Errors extends ReportingType> = {
|
|
|
276
236
|
*/
|
|
277
237
|
strict?: boolean;
|
|
278
238
|
};
|
|
239
|
+
type Validator = (input: unknown, parameters: ValidatorParameters, get: boolean) => boolean | ValidationInformation[];
|
|
240
|
+
type ValidatorParameters = {
|
|
241
|
+
information?: ValidationInformation[];
|
|
242
|
+
output: PlainObject;
|
|
243
|
+
reporting: ReportingInformation;
|
|
244
|
+
strict: boolean;
|
|
245
|
+
};
|
|
279
246
|
//#endregion
|
|
280
247
|
//#region src/schematic.d.ts
|
|
281
248
|
/**
|
|
@@ -284,7 +251,7 @@ type ValidationOptions<Errors extends ReportingType> = {
|
|
|
284
251
|
declare class Schematic<Model> {
|
|
285
252
|
#private;
|
|
286
253
|
private readonly $schematic;
|
|
287
|
-
constructor(
|
|
254
|
+
constructor(validator: Validator);
|
|
288
255
|
/**
|
|
289
256
|
* Parse a value according to the schema
|
|
290
257
|
*
|
|
@@ -452,19 +419,13 @@ type PlainSchema = {
|
|
|
452
419
|
* };
|
|
453
420
|
* ```
|
|
454
421
|
*/
|
|
455
|
-
type Schema =
|
|
422
|
+
type Schema = PlainSchema;
|
|
456
423
|
/**
|
|
457
424
|
* A union of all valid types for a single schema entry
|
|
458
425
|
*
|
|
459
426
|
* Can be a {@link Constructor}, {@link PlainSchema}, {@link SchemaProperty}, {@link Schematic}, {@link ValueName} string, or a custom validator function
|
|
460
427
|
*/
|
|
461
428
|
type SchemaEntry = Constructor | PlainSchema | SchemaProperty | Schematic<unknown> | ValueName | ((value: unknown) => boolean);
|
|
462
|
-
/**
|
|
463
|
-
* Index signature interface backing {@link Schema}, allowing string-keyed entries of {@link PlainSchema}, {@link SchemaEntry}, or arrays of {@link SchemaEntry}
|
|
464
|
-
*/
|
|
465
|
-
interface SchemaIndex {
|
|
466
|
-
[key: string]: PlainSchema | SchemaEntry | SchemaEntry[];
|
|
467
|
-
}
|
|
468
429
|
/**
|
|
469
430
|
* A property definition with explicit type(s), an optional requirement flag, and optional validators
|
|
470
431
|
*
|
|
@@ -672,4 +633,4 @@ declare function instanceOf<Instance>(constructor: Constructor<Instance>): (valu
|
|
|
672
633
|
*/
|
|
673
634
|
declare function isSchematic(value: unknown): value is Schematic<never>;
|
|
674
635
|
//#endregion
|
|
675
|
-
export { type Schema, type Schematic, SchematicError, type TypedSchema, ValidationError, instanceOf, isSchematic, schematic };
|
|
636
|
+
export { type Schema, type Schematic, SchematicError, type TypedSchema, ValidationError, type ValidationInformation, type ValidationOptions, instanceOf, isSchematic, schematic };
|
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
3
|
import { error, ok } from "@oscarpalmer/atoms/result/misc";
|
|
4
|
+
import { join as join$1 } from "@oscarpalmer/atoms";
|
|
4
5
|
import { clone } from "@oscarpalmer/atoms/value/clone";
|
|
5
6
|
//#region src/constants.ts
|
|
6
7
|
const CONJUNCTION_OR = " or ";
|
|
@@ -43,19 +44,18 @@ const TYPE_ARRAY = "array";
|
|
|
43
44
|
const TYPE_NULL = "null";
|
|
44
45
|
const TYPE_OBJECT = "object";
|
|
45
46
|
const TYPE_UNDEFINED = "undefined";
|
|
46
|
-
const VALIDATABLE_TYPES = new Set([
|
|
47
|
-
"array",
|
|
48
|
-
"bigint",
|
|
49
|
-
"boolean",
|
|
50
|
-
"date",
|
|
51
|
-
"function",
|
|
52
|
-
"number",
|
|
53
|
-
"string",
|
|
54
|
-
"symbol",
|
|
55
|
-
TYPE_OBJECT
|
|
56
|
-
]);
|
|
57
47
|
const TYPE_ALL = new Set([
|
|
58
|
-
...
|
|
48
|
+
...new Set([
|
|
49
|
+
"array",
|
|
50
|
+
"bigint",
|
|
51
|
+
"boolean",
|
|
52
|
+
"date",
|
|
53
|
+
"function",
|
|
54
|
+
"number",
|
|
55
|
+
"string",
|
|
56
|
+
"symbol",
|
|
57
|
+
TYPE_OBJECT
|
|
58
|
+
]),
|
|
59
59
|
"null",
|
|
60
60
|
TYPE_UNDEFINED
|
|
61
61
|
]);
|
|
@@ -101,7 +101,8 @@ function getParameters(input) {
|
|
|
101
101
|
}
|
|
102
102
|
function getPropertyType(original) {
|
|
103
103
|
if (typeof original === "function") return "a validated value";
|
|
104
|
-
if (Array.isArray(original)) return `'
|
|
104
|
+
if (Array.isArray(original)) return `'array'`;
|
|
105
|
+
if (isPlainObject(original)) return `'${TYPE_OBJECT}'`;
|
|
105
106
|
if (isSchematic(original)) return `a ${NAME_SCHEMATIC}`;
|
|
106
107
|
return `'${String(original)}'`;
|
|
107
108
|
}
|
|
@@ -197,233 +198,230 @@ var ValidationError = class extends Error {
|
|
|
197
198
|
}
|
|
198
199
|
};
|
|
199
200
|
//#endregion
|
|
200
|
-
//#region src/validation
|
|
201
|
+
//#region src/validation.ts
|
|
201
202
|
function getDisallowedProperty(obj) {
|
|
202
203
|
if ("$required" in obj) return PROPERTY_REQUIRED;
|
|
203
204
|
if ("$type" in obj) return PROPERTY_TYPE;
|
|
204
205
|
if ("$validators" in obj) return PROPERTY_VALIDATORS;
|
|
205
206
|
}
|
|
206
|
-
function
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
const property = getDisallowedProperty(original);
|
|
210
|
-
if (property != null) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED.replace("<>", prefix).replace("<>", property));
|
|
211
|
-
}
|
|
212
|
-
const keys = Object.keys(original);
|
|
213
|
-
const keysLength = keys.length;
|
|
214
|
-
const properties = [];
|
|
215
|
-
for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
|
|
216
|
-
const key = keys[keyIndex];
|
|
217
|
-
const value = original[key];
|
|
218
|
-
if (value == null) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE.replace("<>", join([prefix, key], ".")));
|
|
219
|
-
const types = [];
|
|
220
|
-
let required = true;
|
|
221
|
-
let validators = {};
|
|
222
|
-
if (isPlainObject(value)) {
|
|
223
|
-
required = getRequired(key, value) ?? required;
|
|
224
|
-
validators = getValidators(value[PROPERTY_VALIDATORS]);
|
|
225
|
-
const hasType = PROPERTY_TYPE in value;
|
|
226
|
-
types.push(...getTypes(key, hasType ? value[PROPERTY_TYPE] : value, prefix, hasType));
|
|
227
|
-
} else types.push(...getTypes(key, value, prefix));
|
|
228
|
-
if (!required && !types.includes("undefined")) types.push(TYPE_UNDEFINED);
|
|
229
|
-
properties.push({
|
|
230
|
-
key,
|
|
231
|
-
types,
|
|
232
|
-
validators,
|
|
233
|
-
required: required && !types.includes("undefined")
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
return properties;
|
|
237
|
-
}
|
|
238
|
-
function getRequired(key, obj) {
|
|
239
|
-
if (!("$required" in obj)) return;
|
|
240
|
-
if (typeof obj["$required"] !== "boolean") throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_REQUIRED.replace("<>", key));
|
|
241
|
-
return obj[PROPERTY_REQUIRED];
|
|
207
|
+
function getFunctionValidator(fn) {
|
|
208
|
+
const validator = isConstructor(fn) ? instanceOf(fn) : fn;
|
|
209
|
+
return (input) => validator(input) === true;
|
|
242
210
|
}
|
|
243
|
-
function
|
|
244
|
-
const
|
|
245
|
-
const
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
types.push(value);
|
|
261
|
-
break;
|
|
262
|
-
default: throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE.replace("<>", join([prefix, key], ".")));
|
|
211
|
+
function getNamedValidator(key, name, handlers) {
|
|
212
|
+
const validator = namedValidators[name];
|
|
213
|
+
const named = handlers[name] ?? [];
|
|
214
|
+
const { length } = named;
|
|
215
|
+
return (input, parameters) => {
|
|
216
|
+
if (!validator(input)) return false;
|
|
217
|
+
for (let index = 0; index < length; index += 1) {
|
|
218
|
+
const handler = named[index];
|
|
219
|
+
if (handler(input) === true) continue;
|
|
220
|
+
const information = {
|
|
221
|
+
key,
|
|
222
|
+
validator,
|
|
223
|
+
message: getInvalidValidatorMessage(key.full, name, index, length),
|
|
224
|
+
value: input
|
|
225
|
+
};
|
|
226
|
+
parameters.information?.push(information);
|
|
227
|
+
return parameters.reporting.none ? false : [information];
|
|
263
228
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
return types;
|
|
229
|
+
return true;
|
|
230
|
+
};
|
|
267
231
|
}
|
|
268
|
-
function
|
|
269
|
-
const
|
|
270
|
-
if (original == null) return
|
|
232
|
+
function getNamedHandlers(original, prefix) {
|
|
233
|
+
const handlers = {};
|
|
234
|
+
if (original == null) return handlers;
|
|
271
235
|
if (!isPlainObject(original)) throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE);
|
|
272
236
|
const keys = Object.keys(original);
|
|
273
237
|
const { length } = keys;
|
|
274
238
|
for (let index = 0; index < length; index += 1) {
|
|
275
239
|
const key = keys[index];
|
|
276
|
-
if (!
|
|
240
|
+
if (!TYPE_ALL.has(key)) throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY.replace("<>", key));
|
|
277
241
|
const value = original[key];
|
|
278
|
-
|
|
279
|
-
if (typeof item !== "function") throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE.replace("<>", key));
|
|
242
|
+
handlers[key] = (Array.isArray(value) ? value : [value]).map((item) => {
|
|
243
|
+
if (typeof item !== "function") throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE.replace("<>", key).replace("<>", prefix));
|
|
280
244
|
return item;
|
|
281
245
|
});
|
|
282
246
|
}
|
|
283
|
-
return
|
|
247
|
+
return handlers;
|
|
284
248
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
if (
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
for (let index = 0; index < length; index += 1) {
|
|
293
|
-
const validator = propertyValidators[index];
|
|
294
|
-
if (!validator(value)) {
|
|
295
|
-
parameters.information.push({
|
|
296
|
-
value,
|
|
297
|
-
key: {
|
|
298
|
-
full: parameters.prefix,
|
|
299
|
-
short: parameters.origin.key
|
|
300
|
-
},
|
|
301
|
-
message: getInvalidValidatorMessage(parameters.prefix, name, index, length),
|
|
302
|
-
validator
|
|
303
|
-
});
|
|
304
|
-
return false;
|
|
305
|
-
}
|
|
249
|
+
function getObjectValidator(original, origin, fromType) {
|
|
250
|
+
const keys = Object.keys(original);
|
|
251
|
+
const keysLength = keys.length;
|
|
252
|
+
if (keysLength === 0) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_EMPTY);
|
|
253
|
+
if (fromType ?? false) {
|
|
254
|
+
const property = getDisallowedProperty(original);
|
|
255
|
+
if (property != null) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED.replace("<>", origin.full).replace("<>", property));
|
|
306
256
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
full:
|
|
316
|
-
short:
|
|
317
|
-
};
|
|
318
|
-
const information = {
|
|
319
|
-
key,
|
|
320
|
-
message: parameters?.origin == null ? getInvalidInputMessage(obj) : getInvalidTypeMessage(key.full, parameters.origin.types, obj),
|
|
321
|
-
value: obj
|
|
257
|
+
const set = /* @__PURE__ */ new Set();
|
|
258
|
+
const items = [];
|
|
259
|
+
for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
|
|
260
|
+
const key = keys[keyIndex];
|
|
261
|
+
const value = original[key];
|
|
262
|
+
if (value == null) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE.replace("<>", join$1([origin?.full, key], ".")));
|
|
263
|
+
const prefixedKey = origin == null ? key : join$1([origin.full, key], ".");
|
|
264
|
+
const fullKey = {
|
|
265
|
+
full: prefixedKey,
|
|
266
|
+
short: key
|
|
322
267
|
};
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
268
|
+
let handlers = {};
|
|
269
|
+
let required = true;
|
|
270
|
+
let typed = false;
|
|
271
|
+
let types;
|
|
272
|
+
const validators = [];
|
|
273
|
+
if (isPlainObject(value)) {
|
|
274
|
+
typed = PROPERTY_TYPE in value;
|
|
275
|
+
const type = typed ? value[PROPERTY_TYPE] : value;
|
|
276
|
+
handlers = getNamedHandlers(value[PROPERTY_VALIDATORS], prefixedKey);
|
|
277
|
+
required = getRequired(key, value) ?? required;
|
|
278
|
+
types = Array.isArray(type) ? type : [type];
|
|
279
|
+
} else types = Array.isArray(value) ? value : [value];
|
|
280
|
+
if (types.length === 0) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE.replace("<>", prefixedKey).replace("<>", String(value)));
|
|
281
|
+
const typesLength = types.length;
|
|
282
|
+
for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
|
|
283
|
+
const type = types[typeIndex];
|
|
284
|
+
let validator;
|
|
285
|
+
switch (true) {
|
|
286
|
+
case typeof type === "function":
|
|
287
|
+
validator = getFunctionValidator(type);
|
|
288
|
+
break;
|
|
289
|
+
case isPlainObject(type):
|
|
290
|
+
validator = getObjectValidator(type, fullKey, typed);
|
|
291
|
+
break;
|
|
292
|
+
case isSchematic(type):
|
|
293
|
+
validator = getSchematicValidator(type);
|
|
294
|
+
break;
|
|
295
|
+
case TYPE_ALL.has(type):
|
|
296
|
+
validator = getNamedValidator(fullKey, type, handlers);
|
|
297
|
+
break;
|
|
298
|
+
default: throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE.replace("<>", prefixedKey).replace("<>", String(type)));
|
|
299
|
+
}
|
|
300
|
+
validators.push(validator);
|
|
301
|
+
}
|
|
302
|
+
set.add(key);
|
|
303
|
+
items.push({
|
|
304
|
+
types,
|
|
305
|
+
key: fullKey,
|
|
306
|
+
required: required && !types.includes("undefined"),
|
|
307
|
+
validator: getValidator(validators)
|
|
308
|
+
});
|
|
326
309
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
if (unknownKeys.length > 0) {
|
|
310
|
+
const validatorsLength = items.length;
|
|
311
|
+
return (input, parameters, get) => {
|
|
312
|
+
if (!isPlainObject(input)) {
|
|
313
|
+
if (origin != null) return false;
|
|
332
314
|
const information = {
|
|
333
|
-
key:
|
|
315
|
+
key: {
|
|
334
316
|
full: "",
|
|
335
317
|
short: ""
|
|
336
|
-
} : {
|
|
337
|
-
full: join([parameters.prefix, parameters.origin?.key], "."),
|
|
338
|
-
short: parameters.origin.key
|
|
339
318
|
},
|
|
340
|
-
|
|
341
|
-
|
|
319
|
+
value: input,
|
|
320
|
+
message: getInvalidInputMessage(input)
|
|
342
321
|
};
|
|
343
322
|
if (parameters.reporting.throw) throw new ValidationError([information]);
|
|
344
|
-
parameters
|
|
345
|
-
return parameters.reporting.none ?
|
|
323
|
+
parameters.information?.push(information);
|
|
324
|
+
return parameters.reporting.none ? false : [information];
|
|
346
325
|
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
326
|
+
if (parameters.strict) {
|
|
327
|
+
const unknownKeys = Object.keys(input).filter((key) => !set.has(key));
|
|
328
|
+
if (unknownKeys.length > 0) {
|
|
329
|
+
const information = {
|
|
330
|
+
key: origin ?? {
|
|
331
|
+
full: "",
|
|
332
|
+
short: ""
|
|
333
|
+
},
|
|
334
|
+
message: getUnknownKeysMessage(unknownKeys),
|
|
335
|
+
value: input
|
|
336
|
+
};
|
|
337
|
+
if (parameters.reporting.throw) throw new ValidationError([information]);
|
|
338
|
+
parameters.information?.push(information);
|
|
339
|
+
return parameters.reporting.none ? false : [information];
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
const allInformation = [];
|
|
343
|
+
const output = {};
|
|
344
|
+
for (let validatorIndex = 0; validatorIndex < validatorsLength; validatorIndex += 1) {
|
|
345
|
+
const { key, required, types, validator } = items[validatorIndex];
|
|
346
|
+
const value = input[key.short];
|
|
347
|
+
if (value === void 0) {
|
|
348
|
+
if (required) {
|
|
349
|
+
if (parameters.reporting.none) return false;
|
|
350
|
+
const information = {
|
|
351
|
+
key,
|
|
352
|
+
value,
|
|
353
|
+
message: getInvalidMissingMessage(key.full, types)
|
|
354
|
+
};
|
|
355
|
+
if (parameters.reporting.throw) throw new ValidationError([information]);
|
|
356
|
+
parameters.information?.push(information);
|
|
357
|
+
if (parameters.reporting.all) {
|
|
358
|
+
allInformation.push(information);
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
return [information];
|
|
362
|
+
}
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
const previousOutput = parameters.output;
|
|
366
|
+
parameters.output = output;
|
|
367
|
+
const result = validator(value, parameters, get);
|
|
368
|
+
parameters.output = previousOutput;
|
|
369
|
+
if (result === false) continue;
|
|
370
|
+
if (result === true) {
|
|
371
|
+
if (get) output[key.short] = clone(value);
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
if (parameters.reporting.none) return false;
|
|
375
|
+
const information = typeof result !== "boolean" && result.length > 0 ? result : [{
|
|
376
|
+
key,
|
|
359
377
|
value,
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
},
|
|
364
|
-
message: getInvalidMissingMessage(prefixedKey, property.types)
|
|
365
|
-
};
|
|
366
|
-
if (parameters.reporting.throw) throw new ValidationError([information]);
|
|
367
|
-
parameters?.information?.push(information);
|
|
378
|
+
message: getInvalidTypeMessage(key.full, types, value)
|
|
379
|
+
}];
|
|
380
|
+
if (parameters.reporting.throw) throw new ValidationError(information);
|
|
368
381
|
if (parameters.reporting.all) {
|
|
369
|
-
allInformation.push(information);
|
|
382
|
+
allInformation.push(...information);
|
|
370
383
|
continue;
|
|
371
384
|
}
|
|
372
|
-
return
|
|
373
|
-
}
|
|
374
|
-
const prefixedKey = join([parameters.prefix, key], ".");
|
|
375
|
-
const typesLength = types.length;
|
|
376
|
-
const information = [];
|
|
377
|
-
for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
|
|
378
|
-
const type = types[typeIndex];
|
|
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
|
-
}
|
|
385
|
+
return information;
|
|
390
386
|
}
|
|
391
|
-
if (
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
parameters?.information?.push(...information);
|
|
401
|
-
if (parameters.reporting.all) {
|
|
402
|
-
allInformation.push(...information);
|
|
403
|
-
continue;
|
|
404
|
-
}
|
|
405
|
-
return parameters.reporting.none ? void 0 : information;
|
|
406
|
-
}
|
|
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;
|
|
387
|
+
if (get) if (origin == null) parameters.output = output;
|
|
388
|
+
else parameters.output[origin.short] = output;
|
|
389
|
+
return parameters.reporting.none || allInformation.length === 0 ? true : allInformation;
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
function getRequired(key, obj) {
|
|
393
|
+
if (!("$required" in obj)) return;
|
|
394
|
+
if (typeof obj["$required"] !== "boolean") throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_REQUIRED.replace("<>", key));
|
|
395
|
+
return obj[PROPERTY_REQUIRED];
|
|
410
396
|
}
|
|
411
|
-
function
|
|
412
|
-
const
|
|
413
|
-
return
|
|
397
|
+
function getSchematicValidator(schematic) {
|
|
398
|
+
const validator = schematicValidator.get(schematic);
|
|
399
|
+
return (input, parameters, get) => {
|
|
400
|
+
let result = false;
|
|
401
|
+
if (isPlainObject(input)) result = validator(input, parameters, get);
|
|
402
|
+
if (typeof result === "boolean") return result;
|
|
403
|
+
parameters.information?.push(...result);
|
|
404
|
+
return result.length === 0 ? true : result;
|
|
405
|
+
};
|
|
414
406
|
}
|
|
415
|
-
function
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
407
|
+
function getValidator(validators) {
|
|
408
|
+
const { length } = validators;
|
|
409
|
+
return (input, parameters, get) => {
|
|
410
|
+
const allInformation = [];
|
|
411
|
+
for (let index = 0; index < length; index += 1) {
|
|
412
|
+
const previousInformation = parameters.information;
|
|
413
|
+
parameters.information = [];
|
|
414
|
+
const result = validators[index](input, parameters, get);
|
|
415
|
+
parameters.information = previousInformation;
|
|
416
|
+
if (result === false) continue;
|
|
417
|
+
if (result === true) return true;
|
|
418
|
+
parameters.information?.push(...result);
|
|
419
|
+
allInformation.push(...result);
|
|
421
420
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
}
|
|
421
|
+
return allInformation;
|
|
422
|
+
};
|
|
425
423
|
}
|
|
426
|
-
const
|
|
424
|
+
const namedValidators = {
|
|
427
425
|
array: Array.isArray,
|
|
428
426
|
bigint: (value) => typeof value === "bigint",
|
|
429
427
|
boolean: (value) => typeof value === "boolean",
|
|
@@ -442,32 +440,30 @@ const validators = {
|
|
|
442
440
|
* A schematic for validating objects
|
|
443
441
|
*/
|
|
444
442
|
var Schematic = class {
|
|
445
|
-
#
|
|
446
|
-
constructor(
|
|
443
|
+
#validator;
|
|
444
|
+
constructor(validator) {
|
|
447
445
|
Object.defineProperty(this, PROPERTY_SCHEMATIC, { value: true });
|
|
448
|
-
this.#
|
|
449
|
-
|
|
446
|
+
this.#validator = validator;
|
|
447
|
+
schematicValidator.set(this, validator);
|
|
450
448
|
}
|
|
451
449
|
get(value, options) {
|
|
452
450
|
const parameters = getParameters(options);
|
|
453
|
-
const result =
|
|
454
|
-
if (result
|
|
455
|
-
if (!Array.isArray(result)) return parameters.reporting.none ? result : ok(result);
|
|
451
|
+
const result = this.#validator(value, parameters, true);
|
|
452
|
+
if (typeof result === "boolean") return parameters.reporting.none ? result ? parameters.output : void 0 : ok(parameters.output);
|
|
456
453
|
return error(parameters.reporting.all ? result : result[0]);
|
|
457
454
|
}
|
|
458
455
|
is(value, options) {
|
|
459
456
|
const parameters = getParameters(options);
|
|
460
|
-
const result =
|
|
461
|
-
if (result
|
|
462
|
-
if (!Array.isArray(result)) return parameters.reporting.none ? true : ok(true);
|
|
457
|
+
const result = this.#validator(value, parameters, false);
|
|
458
|
+
if (typeof result === "boolean") return parameters.reporting.none ? result : ok(result);
|
|
463
459
|
return error(parameters.reporting.all ? result : result[0]);
|
|
464
460
|
}
|
|
465
461
|
};
|
|
466
462
|
function schematic(schema) {
|
|
467
463
|
if (isSchematic(schema)) return schema;
|
|
468
464
|
if (!isPlainObject(schema)) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_TYPE);
|
|
469
|
-
return new Schematic(
|
|
465
|
+
return new Schematic(getObjectValidator(schema));
|
|
470
466
|
}
|
|
471
|
-
const
|
|
467
|
+
const schematicValidator = /* @__PURE__ */ new WeakMap();
|
|
472
468
|
//#endregion
|
|
473
469
|
export { SchematicError, ValidationError, instanceOf, isSchematic, schematic };
|