@oscarpalmer/jhunal 0.20.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 +6 -9
- package/dist/helpers.mjs +15 -11
- package/dist/index.d.mts +94 -76
- package/dist/index.mjs +233 -211
- package/dist/models/schema.plain.model.d.mts +2 -8
- package/dist/models/validation.model.d.mts +18 -64
- package/dist/schematic.d.mts +76 -13
- package/dist/schematic.mjs +20 -18
- package/dist/validation.d.mts +7 -0
- package/dist/validation.mjs +245 -0
- package/package.json +52 -52
- package/src/helpers.ts +29 -20
- package/src/index.ts +6 -1
- package/src/models/schema.plain.model.ts +1 -8
- package/src/models/validation.model.ts +44 -82
- package/src/schematic.ts +109 -24
- package/src/validation.ts +498 -0
- package/dist/validation/property.validation.d.mts +0 -7
- package/dist/validation/property.validation.mjs +0 -96
- package/dist/validation/value.validation.d.mts +0 -6
- package/dist/validation/value.validation.mjs +0 -140
- package/src/validation/property.validation.ts +0 -219
- package/src/validation/value.validation.ts +0 -253
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
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 { join as join$1 } from "@oscarpalmer/atoms";
|
|
5
|
+
import { clone } from "@oscarpalmer/atoms/value/clone";
|
|
4
6
|
//#region src/constants.ts
|
|
5
7
|
const CONJUNCTION_OR = " or ";
|
|
6
8
|
const CONJUNCTION_OR_COMMA = ", or ";
|
|
@@ -42,19 +44,18 @@ const TYPE_ARRAY = "array";
|
|
|
42
44
|
const TYPE_NULL = "null";
|
|
43
45
|
const TYPE_OBJECT = "object";
|
|
44
46
|
const TYPE_UNDEFINED = "undefined";
|
|
45
|
-
const VALIDATABLE_TYPES = new Set([
|
|
46
|
-
"array",
|
|
47
|
-
"bigint",
|
|
48
|
-
"boolean",
|
|
49
|
-
"date",
|
|
50
|
-
"function",
|
|
51
|
-
"number",
|
|
52
|
-
"string",
|
|
53
|
-
"symbol",
|
|
54
|
-
TYPE_OBJECT
|
|
55
|
-
]);
|
|
56
47
|
const TYPE_ALL = new Set([
|
|
57
|
-
...
|
|
48
|
+
...new Set([
|
|
49
|
+
"array",
|
|
50
|
+
"bigint",
|
|
51
|
+
"boolean",
|
|
52
|
+
"date",
|
|
53
|
+
"function",
|
|
54
|
+
"number",
|
|
55
|
+
"string",
|
|
56
|
+
"symbol",
|
|
57
|
+
TYPE_OBJECT
|
|
58
|
+
]),
|
|
58
59
|
"null",
|
|
59
60
|
TYPE_UNDEFINED
|
|
60
61
|
]);
|
|
@@ -63,41 +64,45 @@ 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
|
};
|
|
97
101
|
}
|
|
98
102
|
function getPropertyType(original) {
|
|
99
103
|
if (typeof original === "function") return "a validated value";
|
|
100
|
-
if (Array.isArray(original)) return `'
|
|
104
|
+
if (Array.isArray(original)) return `'array'`;
|
|
105
|
+
if (isPlainObject(original)) return `'${TYPE_OBJECT}'`;
|
|
101
106
|
if (isSchematic(original)) return `a ${NAME_SCHEMATIC}`;
|
|
102
107
|
return `'${String(original)}'`;
|
|
103
108
|
}
|
|
@@ -193,216 +198,230 @@ var ValidationError = class extends Error {
|
|
|
193
198
|
}
|
|
194
199
|
};
|
|
195
200
|
//#endregion
|
|
196
|
-
//#region src/validation
|
|
201
|
+
//#region src/validation.ts
|
|
197
202
|
function getDisallowedProperty(obj) {
|
|
198
203
|
if ("$required" in obj) return PROPERTY_REQUIRED;
|
|
199
204
|
if ("$type" in obj) return PROPERTY_TYPE;
|
|
200
205
|
if ("$validators" in obj) return PROPERTY_VALIDATORS;
|
|
201
206
|
}
|
|
202
|
-
function
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
const property = getDisallowedProperty(original);
|
|
206
|
-
if (property != null) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED.replace("<>", prefix).replace("<>", property));
|
|
207
|
-
}
|
|
208
|
-
const keys = Object.keys(original);
|
|
209
|
-
const keysLength = keys.length;
|
|
210
|
-
const properties = [];
|
|
211
|
-
for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
|
|
212
|
-
const key = keys[keyIndex];
|
|
213
|
-
const prefixed = join([prefix, key], ".");
|
|
214
|
-
const value = original[key];
|
|
215
|
-
if (value == null) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE.replace("<>", prefixed));
|
|
216
|
-
const types = [];
|
|
217
|
-
let required = true;
|
|
218
|
-
let validators = {};
|
|
219
|
-
if (isPlainObject(value)) {
|
|
220
|
-
required = getRequired(key, value) ?? required;
|
|
221
|
-
validators = getValidators(value[PROPERTY_VALIDATORS]);
|
|
222
|
-
const hasType = PROPERTY_TYPE in value;
|
|
223
|
-
types.push(...getTypes(key, hasType ? value[PROPERTY_TYPE] : value, prefix, hasType));
|
|
224
|
-
} else types.push(...getTypes(key, value, prefix));
|
|
225
|
-
if (!required && !types.includes("undefined")) types.push(TYPE_UNDEFINED);
|
|
226
|
-
properties.push({
|
|
227
|
-
types,
|
|
228
|
-
validators,
|
|
229
|
-
key: {
|
|
230
|
-
full: prefixed,
|
|
231
|
-
short: key
|
|
232
|
-
},
|
|
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
|
-
validation.push({
|
|
296
|
-
value,
|
|
297
|
-
key: { ...property.key },
|
|
298
|
-
message: getInvalidValidatorMessage(property, name, index, length),
|
|
299
|
-
validator
|
|
300
|
-
});
|
|
301
|
-
return false;
|
|
302
|
-
}
|
|
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));
|
|
303
256
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
key
|
|
314
|
-
message: origin == null ? getInvalidInputMessage(obj) : getInvalidTypeMessage({
|
|
315
|
-
...origin,
|
|
316
|
-
key
|
|
317
|
-
}, obj),
|
|
318
|
-
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
|
|
319
267
|
};
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
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
|
+
});
|
|
323
309
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
if (unknownKeys.length > 0) {
|
|
310
|
+
const validatorsLength = items.length;
|
|
311
|
+
return (input, parameters, get) => {
|
|
312
|
+
if (!isPlainObject(input)) {
|
|
313
|
+
if (origin != null) return false;
|
|
329
314
|
const information = {
|
|
330
|
-
key:
|
|
315
|
+
key: {
|
|
331
316
|
full: "",
|
|
332
317
|
short: ""
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
|
|
318
|
+
},
|
|
319
|
+
value: input,
|
|
320
|
+
message: getInvalidInputMessage(input)
|
|
336
321
|
};
|
|
337
|
-
if (
|
|
338
|
-
|
|
339
|
-
return
|
|
322
|
+
if (parameters.reporting.throw) throw new ValidationError([information]);
|
|
323
|
+
parameters.information?.push(information);
|
|
324
|
+
return parameters.reporting.none ? false : [information];
|
|
340
325
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
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];
|
|
351
340
|
}
|
|
352
|
-
}
|
|
353
|
-
const
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
const
|
|
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,
|
|
357
377
|
value,
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
if (
|
|
362
|
-
|
|
363
|
-
if (options.reporting.all) {
|
|
364
|
-
allInformation.push(information);
|
|
378
|
+
message: getInvalidTypeMessage(key.full, types, value)
|
|
379
|
+
}];
|
|
380
|
+
if (parameters.reporting.throw) throw new ValidationError(information);
|
|
381
|
+
if (parameters.reporting.all) {
|
|
382
|
+
allInformation.push(...information);
|
|
365
383
|
continue;
|
|
366
384
|
}
|
|
367
|
-
return
|
|
368
|
-
}
|
|
369
|
-
const typesLength = types.length;
|
|
370
|
-
const information = [];
|
|
371
|
-
for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
|
|
372
|
-
const type = types[typeIndex];
|
|
373
|
-
if (validateValue(type, property, value, options, information)) continue outer;
|
|
385
|
+
return information;
|
|
374
386
|
}
|
|
375
|
-
if (
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
});
|
|
380
|
-
if (options.reporting.throw && validation == null) throw new ValidationError(information);
|
|
381
|
-
validation?.push(...information);
|
|
382
|
-
if (options.reporting.all) {
|
|
383
|
-
allInformation.push(...information);
|
|
384
|
-
continue;
|
|
385
|
-
}
|
|
386
|
-
return options.reporting.none ? false : information;
|
|
387
|
-
}
|
|
388
|
-
return options.reporting.none || allInformation.length === 0 ? true : 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
|
+
};
|
|
389
391
|
}
|
|
390
|
-
function
|
|
391
|
-
|
|
392
|
-
|
|
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];
|
|
393
396
|
}
|
|
394
|
-
function
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
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
|
+
};
|
|
406
|
+
}
|
|
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);
|
|
400
420
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
}
|
|
421
|
+
return allInformation;
|
|
422
|
+
};
|
|
404
423
|
}
|
|
405
|
-
const
|
|
424
|
+
const namedValidators = {
|
|
406
425
|
array: Array.isArray,
|
|
407
426
|
bigint: (value) => typeof value === "bigint",
|
|
408
427
|
boolean: (value) => typeof value === "boolean",
|
|
@@ -421,27 +440,30 @@ const validators = {
|
|
|
421
440
|
* A schematic for validating objects
|
|
422
441
|
*/
|
|
423
442
|
var Schematic = class {
|
|
424
|
-
#
|
|
425
|
-
constructor(
|
|
443
|
+
#validator;
|
|
444
|
+
constructor(validator) {
|
|
426
445
|
Object.defineProperty(this, PROPERTY_SCHEMATIC, { value: true });
|
|
427
|
-
this.#
|
|
428
|
-
|
|
446
|
+
this.#validator = validator;
|
|
447
|
+
schematicValidator.set(this, validator);
|
|
448
|
+
}
|
|
449
|
+
get(value, options) {
|
|
450
|
+
const parameters = getParameters(options);
|
|
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);
|
|
453
|
+
return error(parameters.reporting.all ? result : result[0]);
|
|
429
454
|
}
|
|
430
455
|
is(value, options) {
|
|
431
|
-
const
|
|
432
|
-
const result =
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
});
|
|
436
|
-
if (typeof result === "boolean") return result;
|
|
437
|
-
return error(reporting.all ? result : result[0]);
|
|
456
|
+
const parameters = getParameters(options);
|
|
457
|
+
const result = this.#validator(value, parameters, false);
|
|
458
|
+
if (typeof result === "boolean") return parameters.reporting.none ? result : ok(result);
|
|
459
|
+
return error(parameters.reporting.all ? result : result[0]);
|
|
438
460
|
}
|
|
439
461
|
};
|
|
440
462
|
function schematic(schema) {
|
|
441
463
|
if (isSchematic(schema)) return schema;
|
|
442
464
|
if (!isPlainObject(schema)) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_TYPE);
|
|
443
|
-
return new Schematic(
|
|
465
|
+
return new Schematic(getObjectValidator(schema));
|
|
444
466
|
}
|
|
445
|
-
const
|
|
467
|
+
const schematicValidator = /* @__PURE__ */ new WeakMap();
|
|
446
468
|
//#endregion
|
|
447
469
|
export { SchematicError, ValidationError, instanceOf, isSchematic, schematic };
|
|
@@ -25,19 +25,13 @@ type PlainSchema = {
|
|
|
25
25
|
* };
|
|
26
26
|
* ```
|
|
27
27
|
*/
|
|
28
|
-
type Schema =
|
|
28
|
+
type Schema = PlainSchema;
|
|
29
29
|
/**
|
|
30
30
|
* A union of all valid types for a single schema entry
|
|
31
31
|
*
|
|
32
32
|
* Can be a {@link Constructor}, {@link PlainSchema}, {@link SchemaProperty}, {@link Schematic}, {@link ValueName} string, or a custom validator function
|
|
33
33
|
*/
|
|
34
34
|
type SchemaEntry = Constructor | PlainSchema | SchemaProperty | Schematic<unknown> | ValueName | ((value: unknown) => boolean);
|
|
35
|
-
/**
|
|
36
|
-
* Index signature interface backing {@link Schema}, allowing string-keyed entries of {@link PlainSchema}, {@link SchemaEntry}, or arrays of {@link SchemaEntry}
|
|
37
|
-
*/
|
|
38
|
-
interface SchemaIndex {
|
|
39
|
-
[key: string]: PlainSchema | SchemaEntry | SchemaEntry[];
|
|
40
|
-
}
|
|
41
35
|
/**
|
|
42
36
|
* A property definition with explicit type(s), an optional requirement flag, and optional validators
|
|
43
37
|
*
|
|
@@ -89,4 +83,4 @@ type SchemaPropertyType = Constructor | PlainSchema | Schematic<unknown> | Value
|
|
|
89
83
|
*/
|
|
90
84
|
type PropertyValidators<Value> = { [Key in ExtractValueNames<Value>]?: ((value: Values[Key]) => boolean) | Array<(value: Values[Key]) => boolean> };
|
|
91
85
|
//#endregion
|
|
92
|
-
export { PlainSchema, PropertyValidators, Schema, SchemaEntry,
|
|
86
|
+
export { PlainSchema, PropertyValidators, Schema, SchemaEntry, SchemaProperty, SchemaPropertyType };
|