@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.
@@ -1,14 +1,14 @@
1
- import { ReportingInformation, ValidatedPropertyType, ValidationParameters } from "./models/validation.model.mjs";
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: ValidatedPropertyType[]): string;
9
- declare function getInvalidTypeMessage(key: string, types: ValidatedPropertyType[], actual: unknown): string;
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): ValidationParameters;
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 `'${TYPE_OBJECT}'`;
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'` returns a boolean _(default)_
189
- * - `'first'` returns the first failure as a `Result`
190
- * - `'all'` returns all failures as a `Result` _(from same level)_
191
- * - `'throw'` throws a {@link ValidationError} on failure
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(properties: ValidatedProperty[]);
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 = SchemaIndex;
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
- ...VALIDATABLE_TYPES,
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 `'${TYPE_OBJECT}'`;
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/property.validation.ts
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 getProperties(original, prefix, fromType) {
207
- if (Object.keys(original).length === 0) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_EMPTY);
208
- if (fromType ?? false) {
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 getTypes(key, original, prefix, fromType) {
244
- const array = Array.isArray(original) ? original : [original];
245
- const { length } = array;
246
- const types = [];
247
- for (let index = 0; index < length; index += 1) {
248
- const value = array[index];
249
- switch (true) {
250
- case typeof value === "function":
251
- types.push(isConstructor(value) ? instanceOf(value) : value);
252
- break;
253
- case isPlainObject(value):
254
- types.push(getProperties(value, join([prefix, key], "."), fromType));
255
- break;
256
- case isSchematic(value):
257
- types.push(value);
258
- break;
259
- case TYPE_ALL.has(value):
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
- if (types.length === 0) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE.replace("<>", join([prefix, key], ".")));
266
- return types;
229
+ return true;
230
+ };
267
231
  }
268
- function getValidators(original) {
269
- const validators = {};
270
- if (original == null) return validators;
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 (!VALIDATABLE_TYPES.has(key)) throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY.replace("<>", key));
240
+ if (!TYPE_ALL.has(key)) throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY.replace("<>", key));
277
241
  const value = original[key];
278
- validators[key] = (Array.isArray(value) ? value : [value]).map((item) => {
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 validators;
247
+ return handlers;
284
248
  }
285
- //#endregion
286
- //#region src/validation/value.validation.ts
287
- function validateNamed(name, value, parameters) {
288
- if (!validators[name](value)) return false;
289
- const propertyValidators = parameters.origin.validators[name];
290
- if (propertyValidators == null || propertyValidators.length === 0) return true;
291
- const { length } = propertyValidators;
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
- return true;
308
- }
309
- function validateObject(obj, properties, parameters, get) {
310
- if (!isPlainObject(obj)) {
311
- const key = parameters?.origin == null ? {
312
- full: "",
313
- short: ""
314
- } : {
315
- full: parameters.prefix,
316
- short: parameters.origin.key
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
- if (parameters.reporting.throw) throw new ValidationError([information]);
324
- parameters?.information?.push(information);
325
- return parameters.reporting.none ? void 0 : [information];
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
- if (parameters.strict) {
328
- const objKeys = Object.keys(obj);
329
- const propertiesKeys = new Set(properties.map((property) => property.key));
330
- const unknownKeys = objKeys.filter((key) => !propertiesKeys.has(key));
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: parameters?.origin == null ? {
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
- message: getUnknownKeysMessage(unknownKeys.map((key) => join([parameters?.prefix, key], "."))),
341
- value: obj
319
+ value: input,
320
+ message: getInvalidInputMessage(input)
342
321
  };
343
322
  if (parameters.reporting.throw) throw new ValidationError([information]);
344
- parameters?.information?.push(information);
345
- return parameters.reporting.none ? void 0 : [information];
323
+ parameters.information?.push(information);
324
+ return parameters.reporting.none ? false : [information];
346
325
  }
347
- }
348
- const allInformation = [];
349
- const output = {};
350
- const propertiesLength = properties.length;
351
- outer: for (let propertyIndex = 0; propertyIndex < propertiesLength; propertyIndex += 1) {
352
- const property = properties[propertyIndex];
353
- const { key, required, types } = property;
354
- const value = obj[key];
355
- if (get && value === void 0 && !required) continue;
356
- if (value === void 0 && required) {
357
- const prefixedKey = join([parameters.prefix, key], ".");
358
- const information = {
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
- key: {
361
- full: prefixedKey,
362
- short: key
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 parameters.reporting.none ? void 0 : [information];
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 (information.length === 0) information.push({
392
- value,
393
- key: {
394
- full: prefixedKey,
395
- short: key
396
- },
397
- message: getInvalidTypeMessage(prefixedKey, property.types, value)
398
- });
399
- if (parameters.reporting.throw) throw new ValidationError(information);
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 validateSchematic(schematic, value, parameters, get) {
412
- const result = validateObject(value, schematicProperties.get(schematic), parameters, get);
413
- return result == null || Array.isArray(result) ? false : true;
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 validateValue(type, value, parameters, get) {
416
- switch (true) {
417
- case typeof type === "function": return type(value);
418
- case Array.isArray(type): {
419
- const result = validateObject(value, type, parameters, get);
420
- return result == null || Array.isArray(result) ? false : true;
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
- case isSchematic(type): return validateSchematic(type, value, parameters, get);
423
- default: return validateNamed(type, value, parameters);
424
- }
421
+ return allInformation;
422
+ };
425
423
  }
426
- const validators = {
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
- #properties;
446
- constructor(properties) {
443
+ #validator;
444
+ constructor(validator) {
447
445
  Object.defineProperty(this, PROPERTY_SCHEMATIC, { value: true });
448
- this.#properties = properties;
449
- schematicProperties.set(this, properties);
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 = validateObject(value, this.#properties, parameters, true);
454
- if (result == null) return;
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 = validateObject(value, this.#properties, parameters, false);
461
- if (result == null) return false;
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(getProperties(schema));
465
+ return new Schematic(getObjectValidator(schema));
470
466
  }
471
- const schematicProperties = /* @__PURE__ */ new WeakMap();
467
+ const schematicValidator = /* @__PURE__ */ new WeakMap();
472
468
  //#endregion
473
469
  export { SchematicError, ValidationError, instanceOf, isSchematic, schematic };