@oscarpalmer/jhunal 0.19.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,37 +7,33 @@ import { PlainObject } from "@oscarpalmer/atoms/models";
7
7
  /**
8
8
  * Maps each element of a tuple through {@link ToValueType}
9
9
  *
10
- * @template Value - Tuple of types to map
10
+ * @template Value Tuple of types to map
11
11
  */
12
12
  type MapToValueTypes<Value extends unknown[]> = Value extends [infer Head, ...infer Tail] ? [ToValueType<Head>, ...MapToValueTypes<Tail>] : [];
13
13
  /**
14
14
  * Maps each element of a tuple through {@link ToSchemaPropertyTypeEach}
15
15
  *
16
- * @template Value - Tuple of types to map
16
+ * @template Value Tuple of types to map
17
17
  */
18
18
  type MapToSchemaPropertyTypes<Value extends unknown[]> = Value extends [infer Head, ...infer Tail] ? [ToSchemaPropertyTypeEach<Head>, ...MapToSchemaPropertyTypes<Tail>] : [];
19
19
  /**
20
- * Converts a type into its corresponding {@link SchemaPropertyType}-representation
20
+ * Converts a TypeScript type to its {@link SchemaPropertyType} representation, suitable for use in a typed schema
21
21
  *
22
- * Deduplicates and unwraps single-element tuples via {@link UnwrapSingle}
23
- *
24
- * @template Value - type to convert
22
+ * @template Value Type to convert
25
23
  */
26
24
  type ToSchemaPropertyType<Value> = UnwrapSingle<DeduplicateTuple<MapToSchemaPropertyTypes<UnionToTuple<Value>>>>;
27
25
  /**
28
26
  * Converts a single type to its schema property equivalent
29
27
  *
30
- * {@link NestedSchema} values have `$required` stripped, plain objects become {@link TypedSchema}, and primitives go through {@link ToValueType}
28
+ * Plain objects become {@link TypedSchema}; primitives go through {@link ToValueType}
31
29
  *
32
- * @template Value - type to convert
30
+ * @template Value Type to convert
33
31
  */
34
32
  type ToSchemaPropertyTypeEach<Value> = Value extends PlainObject ? TypedSchema<Value> : ToValueType<Value>;
35
33
  /**
36
- * Converts a type into its corresponding {@link ValueName}-representation
37
- *
38
- * Deduplicates and unwraps single-element tuples via {@link UnwrapSingle}
34
+ * Converts a TypeScript type to its {@link ValueName} representation, suitable for use as a top-level schema entry
39
35
  *
40
- * @template Value - type to convert
36
+ * @template Value Type to convert
41
37
  */
42
38
  type ToSchemaType<Value> = UnwrapSingle<DeduplicateTuple<MapToValueTypes<UnionToTuple<Value>>>>;
43
39
  /**
@@ -45,7 +41,7 @@ type ToSchemaType<Value> = UnwrapSingle<DeduplicateTuple<MapToValueTypes<UnionTo
45
41
  *
46
42
  * Resolves {@link Schematic} types as-is, then performs a reverse-lookup against {@link Values} _(excluding `'object'`)_ to find a matching key. If no match is found, `object` types resolve to `'object'` or a type-guard function, and all other unrecognised types resolve to a type-guard function
47
43
  *
48
- * @template Value - type to map
44
+ * @template Value Type to map
49
45
  *
50
46
  * @example
51
47
  * ```ts
@@ -1,12 +1,25 @@
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
- type ReportingInformation = Record<ReportingType, boolean>;
6
+ /**
7
+ * Maps each {@link ReportingType} to a boolean flag
8
+ */
9
+ type ReportingInformation = Record<ReportingType, boolean> & {
10
+ type: ReportingType;
11
+ };
12
+ /**
13
+ * Controls how validation failures are reported
14
+ *
15
+ * - `'none'` — returns a boolean _(default)_
16
+ * - `'first'` — returns the first failure as a `Result`
17
+ * - `'all'` — returns all failures as a `Result` _(from same level)_
18
+ * - `'throw'` — throws a {@link ValidationError} on failure
19
+ */
7
20
  type ReportingType = 'all' | 'first' | 'none' | 'throw';
8
21
  /**
9
- * A custom error class for schematic validation failures
22
+ * Thrown when a schema definition is invalid
10
23
  */
11
24
  declare class SchematicError extends Error {
12
25
  constructor(message: string);
@@ -28,7 +41,7 @@ type ValidatedProperty = {
28
41
  /**
29
42
  * The property name in the schema
30
43
  */
31
- key: ValidatedPropertyKey;
44
+ key: string;
32
45
  /**
33
46
  * Whether the property is required
34
47
  */
@@ -42,19 +55,6 @@ type ValidatedProperty = {
42
55
  */
43
56
  validators: ValidatedPropertyValidators;
44
57
  };
45
- /**
46
- * Property name in schema
47
- */
48
- type ValidatedPropertyKey = {
49
- /**
50
- * Full property key, including parent keys for nested properties _(e.g., `address.street`)_
51
- */
52
- full: string;
53
- /**
54
- * The last segment of the property key _(e.g., `street` for `address.street`)_
55
- */
56
- short: string;
57
- };
58
58
  /**
59
59
  * A union of valid types for a {@link ValidatedProperty}'s `types` array
60
60
  *
@@ -67,16 +67,49 @@ type ValidatedPropertyType = GenericCallback | ValidatedProperty[] | Schematic<u
67
67
  * Each key holds an array of validator functions that receive an `unknown` value and return a `boolean`
68
68
  */
69
69
  type ValidatedPropertyValidators = { [Key in ValueName]?: Array<(value: unknown) => boolean> };
70
+ /**
71
+ * Thrown in `'throw'` mode when one or more properties fail validation; `information` holds all failures
72
+ */
70
73
  declare class ValidationError extends Error {
71
74
  readonly information: ValidationInformation[];
72
75
  constructor(information: ValidationInformation[]);
73
76
  }
77
+ /**
78
+ * Describes a single validation failure
79
+ */
74
80
  type ValidationInformation = {
75
- key: ValidationInformationKey;
76
- message: string;
77
- validator?: GenericCallback;
81
+ /** The key path of the property that failed */key: ValidationInformationKey; /** Human-readable description of the failure */
82
+ message: string; /** The validator function that failed, if the failure was from a `$validators` entry */
83
+ validator?: GenericCallback; /** The value that was provided */
78
84
  value: unknown;
79
85
  };
80
- type ValidationInformationKey = ValidatedPropertyKey;
86
+ /**
87
+ *
88
+ */
89
+ type ValidationInformationKey = {
90
+ full: string;
91
+ short: string;
92
+ };
93
+ /**
94
+ * Options for validation
95
+ */
96
+ type ValidationOptions<Errors extends ReportingType> = {
97
+ /**
98
+ * How should validation failures be reported; see {@link ReportingType} _(defaults to `'none'`)_
99
+ */
100
+ errors?: Errors;
101
+ /**
102
+ * Validate if unknown keys are present in the object? _(defaults to `false`)_
103
+ */
104
+ strict?: boolean;
105
+ };
106
+ type ValidationParameters = {
107
+ information?: ValidationInformation[];
108
+ origin?: ValidatedProperty;
109
+ output: PlainObject;
110
+ prefix?: string;
111
+ reporting: ReportingInformation;
112
+ strict: boolean;
113
+ };
81
114
  //#endregion
82
- export { ReportingInformation, ReportingType, SchematicError, ValidatedProperty, ValidatedPropertyKey, ValidatedPropertyType, ValidatedPropertyValidators, ValidationError, ValidationInformation, ValidationInformationKey };
115
+ export { ReportingInformation, ReportingType, SchematicError, ValidatedProperty, ValidatedPropertyType, ValidatedPropertyValidators, ValidationError, ValidationInformation, ValidationInformationKey, ValidationOptions, ValidationParameters };
@@ -2,7 +2,7 @@ import { NAME_ERROR_SCHEMATIC, NAME_ERROR_VALIDATION } from "../constants.mjs";
2
2
  import { join } from "@oscarpalmer/atoms/string";
3
3
  //#region src/models/validation.model.ts
4
4
  /**
5
- * A custom error class for schematic validation failures
5
+ * Thrown when a schema definition is invalid
6
6
  */
7
7
  var SchematicError = class extends Error {
8
8
  constructor(message) {
@@ -10,6 +10,9 @@ var SchematicError = class extends Error {
10
10
  this.name = NAME_ERROR_SCHEMATIC;
11
11
  }
12
12
  };
13
+ /**
14
+ * Thrown in `'throw'` mode when one or more properties fail validation; `information` holds all failures
15
+ */
13
16
  var ValidationError = class extends Error {
14
17
  constructor(information) {
15
18
  super(join(information.map((item) => item.message), "; "));
@@ -1,6 +1,6 @@
1
1
  import { Infer } from "./models/infer.model.mjs";
2
2
  import { TypedSchema } from "./models/schema.typed.model.mjs";
3
- import { ValidatedProperty, ValidationInformation } from "./models/validation.model.mjs";
3
+ import { ValidatedProperty, ValidationInformation, ValidationOptions } from "./models/validation.model.mjs";
4
4
  import { Schema } from "./models/schema.plain.model.mjs";
5
5
  import { PlainObject } from "@oscarpalmer/atoms/models";
6
6
  import { Result } from "@oscarpalmer/atoms/result/models";
@@ -13,41 +13,132 @@ declare class Schematic<Model> {
13
13
  #private;
14
14
  private readonly $schematic;
15
15
  constructor(properties: ValidatedProperty[]);
16
+ /**
17
+ * Parse a value according to the schema
18
+ *
19
+ * Returns a deeply cloned version of the value or throws an error for the first property that fails validation
20
+ * @param value Value to parse
21
+ * @param options Validation options
22
+ * @returns Deeply cloned version of the value if it matches the schema, otherwise throws an error
23
+ */
24
+ get(value: unknown, options: ValidationOptions<'throw'>): Model;
25
+ /**
26
+ * Parse a value according to the schema
27
+ *
28
+ * Returns a deeply cloned version of the value or throws an error for the first property that fails validation
29
+ * @param value Value to parse
30
+ * @param errors Reporting type
31
+ * @returns Deeply cloned version of the value if it matches the schema, otherwise throws an error
32
+ */
33
+ get(value: unknown, errors: 'throw'): Model;
34
+ /**
35
+ * Parse a value according to the schema
36
+ *
37
+ * 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
38
+ * @param value Value to parse
39
+ * @param options Validation options
40
+ * @returns Result holding deeply cloned value or all validation information
41
+ */
42
+ get(value: unknown, options: ValidationOptions<'all'>): Result<Model, ValidationInformation[]>;
43
+ /**
44
+ * Parse a value according to the schema
45
+ *
46
+ * 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
47
+ * @param value Value to parse
48
+ * @param errors Reporting type
49
+ * @returns Result holding deeply cloned value or all validation information
50
+ */
51
+ get(value: unknown, errors: 'all'): Result<Model, ValidationInformation[]>;
52
+ /**
53
+ * Parse a value according to the schema
54
+ *
55
+ * Returns a deeply cloned version of the value or all validation information for the first failing property
56
+ * @param value Value to parse
57
+ * @param options Validation options
58
+ * @returns Result holding deeply cloned value or all validation information
59
+ */
60
+ get(value: unknown, options: ValidationOptions<'first'>): Result<Model, ValidationInformation>;
61
+ /**
62
+ * Parse a value according to the schema
63
+ *
64
+ * Returns a deeply cloned version of the value or all validation information for the first failing property
65
+ * @param value Value to parse
66
+ * @param errors Reporting type
67
+ * @returns Result holding deeply cloned value or all validation information
68
+ */
69
+ get(value: unknown, errors: 'first'): Result<Model, ValidationInformation>;
70
+ /**
71
+ * Parse a value according to the schema
72
+ *
73
+ * Returns a deeply cloned version of the value or `undefined` if the value does not match the schema
74
+ * @param value Value to parse
75
+ * @param strict Validate if unknown keys are present in the object? _(defaults to `false`)_
76
+ * @returns Deeply cloned value, or `undefined` if it's invalid
77
+ */
78
+ get(value: unknown, strict?: true): Model | undefined;
79
+ /**
80
+ * Does the value match the schema?
81
+ *
82
+ * 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
83
+ * @param value Value to validate
84
+ * @param options Validation options
85
+ * @returns `true` if the value matches the schema, otherwise throws an error
86
+ */
87
+ is(value: unknown, options: ValidationOptions<'throw'>): asserts value is Model;
16
88
  /**
17
89
  * Does the value match the schema?
18
90
  *
19
- * 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.
91
+ * 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
20
92
  * @param value Value to validate
21
- * @param errors Throws an error for the first validation failure
93
+ * @param errors Reporting type
22
94
  * @returns `true` if the value matches the schema, otherwise throws an error
23
95
  */
24
96
  is(value: unknown, errors: 'throw'): asserts value is Model;
25
97
  /**
26
98
  * Does the value match the schema?
27
99
  *
28
- * 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 object.
100
+ * 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
29
101
  * @param value Value to validate
30
- * @param errors All
31
- * @returns `true` if the value matches the schema, otherwise `false`
102
+ * @param options Validation options
103
+ * @returns Result holding `true` or all validation information
104
+ */
105
+ is(value: unknown, options: ValidationOptions<'all'>): Result<true, ValidationInformation[]>;
106
+ /**
107
+ * Does the value match the schema?
108
+ *
109
+ * 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
110
+ * @param value Value to validate
111
+ * @param errors Reporting type
112
+ * @returns Result holding `true` or all validation information
32
113
  */
33
114
  is(value: unknown, errors: 'all'): Result<true, ValidationInformation[]>;
34
115
  /**
35
116
  * Does the value match the schema?
36
117
  *
37
- * Will validate that the value matches the schema and return a result of `true` or all validation information for the failing property.
118
+ * Will validate that the value matches the schema and return a result of `true` or all validation information for the first failing property
119
+ * @param value Value to validate
120
+ * @param options Validation options
121
+ * @returns `true` if the value matches the schema, otherwise `false`
122
+ */
123
+ is(value: unknown, options: ValidationOptions<'first'>): Result<true, ValidationInformation>;
124
+ /**
125
+ * Does the value match the schema?
126
+ *
127
+ * Will validate that the value matches the schema and return a result of `true` or all validation information for the first failing property
38
128
  * @param value Value to validate
39
- * @param errors First
129
+ * @param errors Reporting type
40
130
  * @returns `true` if the value matches the schema, otherwise `false`
41
131
  */
42
132
  is(value: unknown, errors: 'first'): Result<true, ValidationInformation>;
43
133
  /**
44
134
  * Does the value match the schema?
45
135
  *
46
- * Will validate that the value matches the schema and return `true` or `false`, without any validation information for validation failures.
136
+ * Will validate that the value matches the schema and return `true` or `false`, without any validation information for validation failures
47
137
  * @param value Value to validate
138
+ * @param strict Validate if unknown keys are present in the object? _(defaults to `false`)_
48
139
  * @returns `true` if the value matches the schema, otherwise `false`
49
140
  */
50
- is(value: unknown): value is Model;
141
+ is(value: unknown, strict?: true): value is Model;
51
142
  }
52
143
  /**
53
144
  * Create a schematic from a schema
@@ -65,5 +156,6 @@ declare function schematic<Model extends Schema>(schema: Model): Schematic<Infer
65
156
  * @returns A schematic for the given typed schema
66
157
  */
67
158
  declare function schematic<Model extends PlainObject>(schema: TypedSchema<Model>): Schematic<Model>;
159
+ declare const schematicProperties: WeakMap<Schematic<unknown>, ValidatedProperty[]>;
68
160
  //#endregion
69
- export { Schematic, schematic };
161
+ export { Schematic, schematic, schematicProperties };
@@ -1,10 +1,10 @@
1
1
  import { PROPERTY_SCHEMATIC, SCHEMATIC_MESSAGE_SCHEMA_INVALID_TYPE } from "./constants.mjs";
2
- import { getReporting, isSchematic } from "./helpers.mjs";
2
+ import { getParameters, isSchematic } from "./helpers.mjs";
3
3
  import { SchematicError } from "./models/validation.model.mjs";
4
4
  import { getProperties } from "./validation/property.validation.mjs";
5
5
  import { validateObject } from "./validation/value.validation.mjs";
6
6
  import { isPlainObject } from "@oscarpalmer/atoms/is";
7
- import { error } from "@oscarpalmer/atoms/result/misc";
7
+ import { error, ok } from "@oscarpalmer/atoms/result/misc";
8
8
  //#region src/schematic.ts
9
9
  /**
10
10
  * A schematic for validating objects
@@ -14,12 +14,21 @@ var Schematic = class {
14
14
  constructor(properties) {
15
15
  Object.defineProperty(this, PROPERTY_SCHEMATIC, { value: true });
16
16
  this.#properties = properties;
17
+ schematicProperties.set(this, properties);
17
18
  }
18
- is(value, errors) {
19
- const reporting = getReporting(errors);
20
- const result = validateObject(value, this.#properties, reporting);
21
- if (typeof result === "boolean") return result;
22
- return error(reporting.all ? result : result[0]);
19
+ get(value, options) {
20
+ const parameters = getParameters(options);
21
+ const result = validateObject(value, this.#properties, parameters, true);
22
+ if (result == null) return;
23
+ if (!Array.isArray(result)) return parameters.reporting.none ? result : ok(result);
24
+ return error(parameters.reporting.all ? result : result[0]);
25
+ }
26
+ is(value, options) {
27
+ const parameters = getParameters(options);
28
+ const result = validateObject(value, this.#properties, parameters, false);
29
+ if (result == null) return false;
30
+ if (!Array.isArray(result)) return parameters.reporting.none ? true : ok(true);
31
+ return error(parameters.reporting.all ? result : result[0]);
23
32
  }
24
33
  };
25
34
  function schematic(schema) {
@@ -27,5 +36,6 @@ function schematic(schema) {
27
36
  if (!isPlainObject(schema)) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_TYPE);
28
37
  return new Schematic(getProperties(schema));
29
38
  }
39
+ const schematicProperties = /* @__PURE__ */ new WeakMap();
30
40
  //#endregion
31
- export { Schematic, schematic };
41
+ export { Schematic, schematic, schematicProperties };
@@ -20,9 +20,8 @@ function getProperties(original, prefix, fromType) {
20
20
  const properties = [];
21
21
  for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
22
22
  const key = keys[keyIndex];
23
- const prefixed = join([prefix, key], ".");
24
23
  const value = original[key];
25
- if (value == null) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE.replace("<>", prefixed));
24
+ if (value == null) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE.replace("<>", join([prefix, key], ".")));
26
25
  const types = [];
27
26
  let required = true;
28
27
  let validators = {};
@@ -34,12 +33,9 @@ function getProperties(original, prefix, fromType) {
34
33
  } else types.push(...getTypes(key, value, prefix));
35
34
  if (!required && !types.includes("undefined")) types.push(TYPE_UNDEFINED);
36
35
  properties.push({
36
+ key,
37
37
  types,
38
38
  validators,
39
- key: {
40
- full: prefixed,
41
- short: key
42
- },
43
39
  required: required && !types.includes("undefined")
44
40
  });
45
41
  }
@@ -1,6 +1,7 @@
1
- import { ReportingInformation, ValidatedProperty, ValidationInformation } from "../models/validation.model.mjs";
1
+ import { ValidatedProperty, ValidationInformation, ValidationParameters } from "../models/validation.model.mjs";
2
+ import { PlainObject } from "@oscarpalmer/atoms/models";
2
3
 
3
4
  //#region src/validation/value.validation.d.ts
4
- declare function validateObject(obj: unknown, properties: ValidatedProperty[], reporting: ReportingInformation, property?: ValidatedProperty, validation?: ValidationInformation[]): boolean | ValidationInformation[];
5
+ declare function validateObject(obj: unknown, properties: ValidatedProperty[], parameters: ValidationParameters, get: boolean): PlainObject | ValidationInformation[] | undefined;
5
6
  //#endregion
6
7
  export { validateObject };
@@ -1,20 +1,26 @@
1
1
  import "../constants.mjs";
2
- import { getInvalidInputMessage, getInvalidMissingMessage, getInvalidTypeMessage, getInvalidValidatorMessage, isSchematic } from "../helpers.mjs";
2
+ import { getInvalidInputMessage, getInvalidMissingMessage, getInvalidTypeMessage, getInvalidValidatorMessage, getUnknownKeysMessage, isSchematic } from "../helpers.mjs";
3
3
  import { ValidationError } from "../models/validation.model.mjs";
4
+ import { schematicProperties } from "../schematic.mjs";
4
5
  import { isPlainObject } from "@oscarpalmer/atoms/is";
6
+ import { join } from "@oscarpalmer/atoms/string";
7
+ import { clone } from "@oscarpalmer/atoms/value/clone";
5
8
  //#region src/validation/value.validation.ts
6
- function validateNamed(property, name, value, validation) {
9
+ function validateNamed(name, value, parameters) {
7
10
  if (!validators[name](value)) return false;
8
- const propertyValidators = property.validators[name];
11
+ const propertyValidators = parameters.origin.validators[name];
9
12
  if (propertyValidators == null || propertyValidators.length === 0) return true;
10
13
  const { length } = propertyValidators;
11
14
  for (let index = 0; index < length; index += 1) {
12
15
  const validator = propertyValidators[index];
13
16
  if (!validator(value)) {
14
- validation.push({
17
+ parameters.information.push({
15
18
  value,
16
- key: { ...property.key },
17
- message: getInvalidValidatorMessage(property, name, index, length),
19
+ key: {
20
+ full: parameters.prefix,
21
+ short: parameters.origin.key
22
+ },
23
+ message: getInvalidValidatorMessage(parameters.prefix, name, index, length),
18
24
  validator
19
25
  });
20
26
  return false;
@@ -22,69 +28,121 @@ function validateNamed(property, name, value, validation) {
22
28
  }
23
29
  return true;
24
30
  }
25
- function validateObject(obj, properties, reporting, property, validation) {
31
+ function validateObject(obj, properties, parameters, get) {
26
32
  if (!isPlainObject(obj)) {
33
+ const key = parameters?.origin == null ? {
34
+ full: "",
35
+ short: ""
36
+ } : {
37
+ full: parameters.prefix,
38
+ short: parameters.origin.key
39
+ };
27
40
  const information = {
28
- key: {
29
- full: "",
30
- short: ""
31
- },
32
- message: property == null ? getInvalidInputMessage(obj) : getInvalidTypeMessage(property, obj),
41
+ key,
42
+ message: parameters?.origin == null ? getInvalidInputMessage(obj) : getInvalidTypeMessage(key.full, parameters.origin.types, obj),
33
43
  value: obj
34
44
  };
35
- if (reporting.throw) throw new ValidationError([information]);
36
- return reporting.none ? false : [information];
45
+ if (parameters.reporting.throw) throw new ValidationError([information]);
46
+ parameters?.information?.push(information);
47
+ return parameters.reporting.none ? void 0 : [information];
48
+ }
49
+ if (parameters.strict) {
50
+ const objKeys = Object.keys(obj);
51
+ const propertiesKeys = new Set(properties.map((property) => property.key));
52
+ const unknownKeys = objKeys.filter((key) => !propertiesKeys.has(key));
53
+ if (unknownKeys.length > 0) {
54
+ const information = {
55
+ key: parameters?.origin == null ? {
56
+ full: "",
57
+ short: ""
58
+ } : {
59
+ full: join([parameters.prefix, parameters.origin?.key], "."),
60
+ short: parameters.origin.key
61
+ },
62
+ message: getUnknownKeysMessage(unknownKeys.map((key) => join([parameters?.prefix, key], "."))),
63
+ value: obj
64
+ };
65
+ if (parameters.reporting.throw) throw new ValidationError([information]);
66
+ parameters?.information?.push(information);
67
+ return parameters.reporting.none ? void 0 : [information];
68
+ }
37
69
  }
38
70
  const allInformation = [];
71
+ const output = {};
39
72
  const propertiesLength = properties.length;
40
73
  outer: for (let propertyIndex = 0; propertyIndex < propertiesLength; propertyIndex += 1) {
41
74
  const property = properties[propertyIndex];
42
75
  const { key, required, types } = property;
43
- const value = obj[key.short];
76
+ const value = obj[key];
77
+ if (get && value === void 0 && !required) continue;
44
78
  if (value === void 0 && required) {
79
+ const prefixedKey = join([parameters.prefix, key], ".");
45
80
  const information = {
46
81
  value,
47
- key: { ...key },
48
- message: getInvalidMissingMessage(property)
82
+ key: {
83
+ full: prefixedKey,
84
+ short: key
85
+ },
86
+ message: getInvalidMissingMessage(prefixedKey, property.types)
49
87
  };
50
- if (reporting.throw && validation == null) throw new ValidationError([information]);
51
- if (validation != null) validation.push(information);
52
- if (reporting.all) {
88
+ if (parameters.reporting.throw) throw new ValidationError([information]);
89
+ parameters?.information?.push(information);
90
+ if (parameters.reporting.all) {
53
91
  allInformation.push(information);
54
92
  continue;
55
93
  }
56
- return reporting.none ? false : [information];
94
+ return parameters.reporting.none ? void 0 : [information];
57
95
  }
96
+ const prefixedKey = join([parameters.prefix, key], ".");
58
97
  const typesLength = types.length;
59
98
  const information = [];
60
99
  for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
61
100
  const type = types[typeIndex];
62
- if (validateValue(type, property, value, reporting, information)) continue outer;
101
+ if (validateValue(type, value, {
102
+ information,
103
+ output,
104
+ origin: property,
105
+ prefix: prefixedKey,
106
+ reporting: parameters.reporting,
107
+ strict: parameters.strict
108
+ }, get)) {
109
+ if (get) output[key] = clone(value);
110
+ continue outer;
111
+ }
63
112
  }
64
113
  if (information.length === 0) information.push({
65
114
  value,
66
- key: { ...key },
67
- message: getInvalidTypeMessage(property, value)
115
+ key: {
116
+ full: prefixedKey,
117
+ short: key
118
+ },
119
+ message: getInvalidTypeMessage(prefixedKey, property.types, value)
68
120
  });
69
- if (reporting.throw && validation == null) throw new ValidationError(information);
70
- validation?.push(...information);
71
- if (reporting.all) {
121
+ if (parameters.reporting.throw) throw new ValidationError(information);
122
+ parameters?.information?.push(...information);
123
+ if (parameters.reporting.all) {
72
124
  allInformation.push(...information);
73
125
  continue;
74
126
  }
75
- return reporting.none ? false : information;
127
+ return parameters.reporting.none ? void 0 : information;
76
128
  }
77
- return reporting.none ? true : allInformation.length === 0 ? true : allInformation;
129
+ if (get) if (parameters.origin == null) parameters.output = output;
130
+ else parameters.output[parameters.origin.key] = output;
131
+ return parameters.reporting.none || allInformation.length === 0 ? parameters.output : allInformation;
132
+ }
133
+ function validateSchematic(schematic, value, parameters, get) {
134
+ const result = validateObject(value, schematicProperties.get(schematic), parameters, get);
135
+ return result == null || Array.isArray(result) ? false : true;
78
136
  }
79
- function validateValue(type, property, value, reporting, validation) {
137
+ function validateValue(type, value, parameters, get) {
80
138
  switch (true) {
81
139
  case typeof type === "function": return type(value);
82
140
  case Array.isArray(type): {
83
- const nested = validateObject(value, type, reporting, property, validation);
84
- return typeof nested !== "boolean" ? false : nested;
141
+ const result = validateObject(value, type, parameters, get);
142
+ return result == null || Array.isArray(result) ? false : true;
85
143
  }
86
- case isSchematic(type): return type.is(value, reporting);
87
- default: return validateNamed(property, type, value, validation);
144
+ case isSchematic(type): return validateSchematic(type, value, parameters, get);
145
+ default: return validateNamed(type, value, parameters);
88
146
  }
89
147
  }
90
148
  const validators = {