@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.
@@ -25,19 +25,13 @@ type PlainSchema = {
25
25
  * };
26
26
  * ```
27
27
  */
28
- type Schema = SchemaIndex;
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, SchemaIndex, SchemaProperty, SchemaPropertyType };
86
+ export { PlainSchema, PropertyValidators, Schema, SchemaEntry, SchemaProperty, SchemaPropertyType };
@@ -3,19 +3,18 @@ import { ValueName } from "./misc.model.mjs";
3
3
  import { GenericCallback, PlainObject } from "@oscarpalmer/atoms/models";
4
4
 
5
5
  //#region src/models/validation.model.d.ts
6
- /**
7
- * Maps each {@link ReportingType} to a boolean flag
8
- */
6
+ type NamedValidatorHandlers = { [Key in ValueName]?: Array<(value: unknown) => boolean> };
7
+ type NamedValidators = Record<ValueName, (value: unknown) => boolean>;
9
8
  type ReportingInformation = Record<ReportingType, boolean> & {
10
9
  type: ReportingType;
11
10
  };
12
11
  /**
13
12
  * Controls how validation failures are reported
14
13
  *
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
14
+ * - `'none'`, returns a boolean _(default)_
15
+ * - `'first'`, returns the first failure as a `Result`
16
+ * - `'all'`, returns all failures as a `Result` _(from same level)_
17
+ * - `'throw'`, throws a {@link ValidationError} on failure
19
18
  */
20
19
  type ReportingType = 'all' | 'first' | 'none' | 'throw';
21
20
  /**
@@ -24,49 +23,6 @@ type ReportingType = 'all' | 'first' | 'none' | 'throw';
24
23
  declare class SchematicError extends Error {
25
24
  constructor(message: string);
26
25
  }
27
- /**
28
- * The runtime representation of a parsed schema property, used internally during validation
29
- *
30
- * @example
31
- * ```ts
32
- * const parsed: ValidatedProperty = {
33
- * key: 'age',
34
- * required: true,
35
- * types: ['number'],
36
- * validators: { number: [(v) => v > 0] },
37
- * };
38
- * ```
39
- */
40
- type ValidatedProperty = {
41
- /**
42
- * The property name in the schema
43
- */
44
- key: string;
45
- /**
46
- * Whether the property is required
47
- */
48
- required: boolean;
49
- /**
50
- * The allowed types for this property
51
- */
52
- types: ValidatedPropertyType[];
53
- /**
54
- * Custom validators grouped by {@link ValueName}
55
- */
56
- validators: ValidatedPropertyValidators;
57
- };
58
- /**
59
- * A union of valid types for a {@link ValidatedProperty}'s `types` array
60
- *
61
- * Can be a callback _(custom validator)_, a {@link Schematic}, a nested {@link ValidatedProperty}, or a {@link ValueName} string
62
- */
63
- type ValidatedPropertyType = GenericCallback | ValidatedProperty[] | Schematic<unknown> | ValueName;
64
- /**
65
- * A map of validator functions keyed by {@link ValueName}, used at runtime in {@link ValidatedProperty}
66
- *
67
- * Each key holds an array of validator functions that receive an `unknown` value and return a `boolean`
68
- */
69
- type ValidatedPropertyValidators = { [Key in ValueName]?: Array<(value: unknown) => boolean> };
70
26
  /**
71
27
  * Thrown in `'throw'` mode when one or more properties fail validation; `information` holds all failures
72
28
  */
@@ -103,13 +59,13 @@ type ValidationOptions<Errors extends ReportingType> = {
103
59
  */
104
60
  strict?: boolean;
105
61
  };
106
- type ValidationParameters = {
62
+ type Validator = (input: unknown, parameters: ValidatorParameters, get: boolean) => boolean | ValidationInformation[];
63
+ type ValidatorParameters = {
107
64
  information?: ValidationInformation[];
108
- origin?: ValidatedProperty;
109
65
  output: PlainObject;
110
- prefix?: string;
111
66
  reporting: ReportingInformation;
112
67
  strict: boolean;
113
68
  };
69
+ type ValidatorType = Function | PlainObject | Schematic<unknown> | ValueName;
114
70
  //#endregion
115
- export { ReportingInformation, ReportingType, SchematicError, ValidatedProperty, ValidatedPropertyType, ValidatedPropertyValidators, ValidationError, ValidationInformation, ValidationInformationKey, ValidationOptions, ValidationParameters };
71
+ export { NamedValidatorHandlers, NamedValidators, ReportingInformation, ReportingType, SchematicError, ValidationError, ValidationInformation, ValidationInformationKey, ValidationOptions, Validator, ValidatorParameters, ValidatorType };
@@ -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, ValidationOptions } from "./models/validation.model.mjs";
3
+ import { ValidationInformation, ValidationOptions, Validator } 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";
@@ -12,7 +12,7 @@ import { Result } from "@oscarpalmer/atoms/result/models";
12
12
  declare class Schematic<Model> {
13
13
  #private;
14
14
  private readonly $schematic;
15
- constructor(properties: ValidatedProperty[]);
15
+ constructor(validator: Validator);
16
16
  /**
17
17
  * Parse a value according to the schema
18
18
  *
@@ -156,6 +156,6 @@ declare function schematic<Model extends Schema>(schema: Model): Schematic<Infer
156
156
  * @returns A schematic for the given typed schema
157
157
  */
158
158
  declare function schematic<Model extends PlainObject>(schema: TypedSchema<Model>): Schematic<Model>;
159
- declare const schematicProperties: WeakMap<Schematic<unknown>, ValidatedProperty[]>;
159
+ declare const schematicValidator: WeakMap<Schematic<unknown>, Validator>;
160
160
  //#endregion
161
- export { Schematic, schematic, schematicProperties };
161
+ export { Schematic, schematic, schematicValidator };
@@ -1,8 +1,7 @@
1
1
  import { PROPERTY_SCHEMATIC, SCHEMATIC_MESSAGE_SCHEMA_INVALID_TYPE } from "./constants.mjs";
2
2
  import { getParameters, isSchematic } from "./helpers.mjs";
3
3
  import { SchematicError } from "./models/validation.model.mjs";
4
- import { getProperties } from "./validation/property.validation.mjs";
5
- import { validateObject } from "./validation/value.validation.mjs";
4
+ import { getObjectValidator } from "./validation.mjs";
6
5
  import { isPlainObject } from "@oscarpalmer/atoms/is";
7
6
  import { error, ok } from "@oscarpalmer/atoms/result/misc";
8
7
  //#region src/schematic.ts
@@ -10,32 +9,30 @@ import { error, ok } from "@oscarpalmer/atoms/result/misc";
10
9
  * A schematic for validating objects
11
10
  */
12
11
  var Schematic = class {
13
- #properties;
14
- constructor(properties) {
12
+ #validator;
13
+ constructor(validator) {
15
14
  Object.defineProperty(this, PROPERTY_SCHEMATIC, { value: true });
16
- this.#properties = properties;
17
- schematicProperties.set(this, properties);
15
+ this.#validator = validator;
16
+ schematicValidator.set(this, validator);
18
17
  }
19
18
  get(value, options) {
20
19
  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);
20
+ const result = this.#validator(value, parameters, true);
21
+ if (typeof result === "boolean") return parameters.reporting.none ? result ? parameters.output : void 0 : ok(parameters.output);
24
22
  return error(parameters.reporting.all ? result : result[0]);
25
23
  }
26
24
  is(value, options) {
27
25
  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);
26
+ const result = this.#validator(value, parameters, false);
27
+ if (typeof result === "boolean") return parameters.reporting.none ? result : ok(result);
31
28
  return error(parameters.reporting.all ? result : result[0]);
32
29
  }
33
30
  };
34
31
  function schematic(schema) {
35
32
  if (isSchematic(schema)) return schema;
36
33
  if (!isPlainObject(schema)) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_TYPE);
37
- return new Schematic(getProperties(schema));
34
+ return new Schematic(getObjectValidator(schema));
38
35
  }
39
- const schematicProperties = /* @__PURE__ */ new WeakMap();
36
+ const schematicValidator = /* @__PURE__ */ new WeakMap();
40
37
  //#endregion
41
- export { Schematic, schematic, schematicProperties };
38
+ export { Schematic, schematic, schematicValidator };
@@ -0,0 +1,7 @@
1
+ import { ValidationInformationKey, Validator } from "./models/validation.model.mjs";
2
+ import { PlainObject } from "@oscarpalmer/atoms";
3
+
4
+ //#region src/validation.d.ts
5
+ declare function getObjectValidator(original: PlainObject, origin?: ValidationInformationKey, fromType?: boolean): Validator;
6
+ //#endregion
7
+ export { getObjectValidator };
@@ -0,0 +1,245 @@
1
+ import { PROPERTY_REQUIRED, PROPERTY_TYPE, PROPERTY_VALIDATORS, SCHEMATIC_MESSAGE_SCHEMA_INVALID_EMPTY, SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED, SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE, SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_REQUIRED, SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE, SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY, SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE, SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE, TYPE_ALL } from "./constants.mjs";
2
+ import { getInvalidInputMessage, getInvalidMissingMessage, getInvalidTypeMessage, getInvalidValidatorMessage, getUnknownKeysMessage, instanceOf, isSchematic } from "./helpers.mjs";
3
+ import { SchematicError, ValidationError } from "./models/validation.model.mjs";
4
+ import { schematicValidator } from "./schematic.mjs";
5
+ import { isConstructor, isPlainObject } from "@oscarpalmer/atoms/is";
6
+ import { join } from "@oscarpalmer/atoms";
7
+ import { clone } from "@oscarpalmer/atoms/value/clone";
8
+ //#region src/validation.ts
9
+ function getDisallowedProperty(obj) {
10
+ if ("$required" in obj) return PROPERTY_REQUIRED;
11
+ if ("$type" in obj) return PROPERTY_TYPE;
12
+ if ("$validators" in obj) return PROPERTY_VALIDATORS;
13
+ }
14
+ function getFunctionValidator(fn) {
15
+ const validator = isConstructor(fn) ? instanceOf(fn) : fn;
16
+ return (input) => validator(input) === true;
17
+ }
18
+ function getNamedValidator(key, name, handlers) {
19
+ const validator = namedValidators[name];
20
+ const named = handlers[name] ?? [];
21
+ const { length } = named;
22
+ return (input, parameters) => {
23
+ if (!validator(input)) return false;
24
+ for (let index = 0; index < length; index += 1) {
25
+ const handler = named[index];
26
+ if (handler(input) === true) continue;
27
+ const information = {
28
+ key,
29
+ validator,
30
+ message: getInvalidValidatorMessage(key.full, name, index, length),
31
+ value: input
32
+ };
33
+ parameters.information?.push(information);
34
+ return parameters.reporting.none ? false : [information];
35
+ }
36
+ return true;
37
+ };
38
+ }
39
+ function getNamedHandlers(original, prefix) {
40
+ const handlers = {};
41
+ if (original == null) return handlers;
42
+ if (!isPlainObject(original)) throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE);
43
+ const keys = Object.keys(original);
44
+ const { length } = keys;
45
+ for (let index = 0; index < length; index += 1) {
46
+ const key = keys[index];
47
+ if (!TYPE_ALL.has(key)) throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY.replace("<>", key));
48
+ const value = original[key];
49
+ handlers[key] = (Array.isArray(value) ? value : [value]).map((item) => {
50
+ if (typeof item !== "function") throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE.replace("<>", key).replace("<>", prefix));
51
+ return item;
52
+ });
53
+ }
54
+ return handlers;
55
+ }
56
+ function getObjectValidator(original, origin, fromType) {
57
+ const keys = Object.keys(original);
58
+ const keysLength = keys.length;
59
+ if (keysLength === 0) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_EMPTY);
60
+ if (fromType ?? false) {
61
+ const property = getDisallowedProperty(original);
62
+ if (property != null) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED.replace("<>", origin.full).replace("<>", property));
63
+ }
64
+ const set = /* @__PURE__ */ new Set();
65
+ const items = [];
66
+ for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
67
+ const key = keys[keyIndex];
68
+ const value = original[key];
69
+ if (value == null) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE.replace("<>", join([origin?.full, key], ".")));
70
+ const prefixedKey = origin == null ? key : join([origin.full, key], ".");
71
+ const fullKey = {
72
+ full: prefixedKey,
73
+ short: key
74
+ };
75
+ let handlers = {};
76
+ let required = true;
77
+ let typed = false;
78
+ let types;
79
+ const validators = [];
80
+ if (isPlainObject(value)) {
81
+ typed = PROPERTY_TYPE in value;
82
+ const type = typed ? value[PROPERTY_TYPE] : value;
83
+ handlers = getNamedHandlers(value[PROPERTY_VALIDATORS], prefixedKey);
84
+ required = getRequired(key, value) ?? required;
85
+ types = Array.isArray(type) ? type : [type];
86
+ } else types = Array.isArray(value) ? value : [value];
87
+ if (types.length === 0) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE.replace("<>", prefixedKey).replace("<>", String(value)));
88
+ const typesLength = types.length;
89
+ for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
90
+ const type = types[typeIndex];
91
+ let validator;
92
+ switch (true) {
93
+ case typeof type === "function":
94
+ validator = getFunctionValidator(type);
95
+ break;
96
+ case isPlainObject(type):
97
+ validator = getObjectValidator(type, fullKey, typed);
98
+ break;
99
+ case isSchematic(type):
100
+ validator = getSchematicValidator(type);
101
+ break;
102
+ case TYPE_ALL.has(type):
103
+ validator = getNamedValidator(fullKey, type, handlers);
104
+ break;
105
+ default: throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE.replace("<>", prefixedKey).replace("<>", String(type)));
106
+ }
107
+ validators.push(validator);
108
+ }
109
+ set.add(key);
110
+ items.push({
111
+ types,
112
+ key: fullKey,
113
+ required: required && !types.includes("undefined"),
114
+ validator: getValidator(validators)
115
+ });
116
+ }
117
+ const validatorsLength = items.length;
118
+ return (input, parameters, get) => {
119
+ if (!isPlainObject(input)) {
120
+ if (origin != null) return false;
121
+ const information = {
122
+ key: {
123
+ full: "",
124
+ short: ""
125
+ },
126
+ value: input,
127
+ message: getInvalidInputMessage(input)
128
+ };
129
+ if (parameters.reporting.throw) throw new ValidationError([information]);
130
+ parameters.information?.push(information);
131
+ return parameters.reporting.none ? false : [information];
132
+ }
133
+ if (parameters.strict) {
134
+ const unknownKeys = Object.keys(input).filter((key) => !set.has(key));
135
+ if (unknownKeys.length > 0) {
136
+ const information = {
137
+ key: origin ?? {
138
+ full: "",
139
+ short: ""
140
+ },
141
+ message: getUnknownKeysMessage(unknownKeys),
142
+ value: input
143
+ };
144
+ if (parameters.reporting.throw) throw new ValidationError([information]);
145
+ parameters.information?.push(information);
146
+ return parameters.reporting.none ? false : [information];
147
+ }
148
+ }
149
+ const allInformation = [];
150
+ const output = {};
151
+ for (let validatorIndex = 0; validatorIndex < validatorsLength; validatorIndex += 1) {
152
+ const { key, required, types, validator } = items[validatorIndex];
153
+ const value = input[key.short];
154
+ if (value === void 0) {
155
+ if (required) {
156
+ if (parameters.reporting.none) return false;
157
+ const information = {
158
+ key,
159
+ value,
160
+ message: getInvalidMissingMessage(key.full, types)
161
+ };
162
+ if (parameters.reporting.throw) throw new ValidationError([information]);
163
+ parameters.information?.push(information);
164
+ if (parameters.reporting.all) {
165
+ allInformation.push(information);
166
+ continue;
167
+ }
168
+ return [information];
169
+ }
170
+ continue;
171
+ }
172
+ const previousOutput = parameters.output;
173
+ parameters.output = output;
174
+ const result = validator(value, parameters, get);
175
+ parameters.output = previousOutput;
176
+ if (result === false) continue;
177
+ if (result === true) {
178
+ if (get) output[key.short] = clone(value);
179
+ continue;
180
+ }
181
+ if (parameters.reporting.none) return false;
182
+ const information = typeof result !== "boolean" && result.length > 0 ? result : [{
183
+ key,
184
+ value,
185
+ message: getInvalidTypeMessage(key.full, types, value)
186
+ }];
187
+ if (parameters.reporting.throw) throw new ValidationError(information);
188
+ if (parameters.reporting.all) {
189
+ allInformation.push(...information);
190
+ continue;
191
+ }
192
+ return information;
193
+ }
194
+ if (get) if (origin == null) parameters.output = output;
195
+ else parameters.output[origin.short] = output;
196
+ return parameters.reporting.none || allInformation.length === 0 ? true : allInformation;
197
+ };
198
+ }
199
+ function getRequired(key, obj) {
200
+ if (!("$required" in obj)) return;
201
+ if (typeof obj["$required"] !== "boolean") throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_REQUIRED.replace("<>", key));
202
+ return obj[PROPERTY_REQUIRED];
203
+ }
204
+ function getSchematicValidator(schematic) {
205
+ const validator = schematicValidator.get(schematic);
206
+ return (input, parameters, get) => {
207
+ let result = false;
208
+ if (isPlainObject(input)) result = validator(input, parameters, get);
209
+ if (typeof result === "boolean") return result;
210
+ parameters.information?.push(...result);
211
+ return result.length === 0 ? true : result;
212
+ };
213
+ }
214
+ function getValidator(validators) {
215
+ const { length } = validators;
216
+ return (input, parameters, get) => {
217
+ const allInformation = [];
218
+ for (let index = 0; index < length; index += 1) {
219
+ const previousInformation = parameters.information;
220
+ parameters.information = [];
221
+ const result = validators[index](input, parameters, get);
222
+ parameters.information = previousInformation;
223
+ if (result === false) continue;
224
+ if (result === true) return true;
225
+ parameters.information?.push(...result);
226
+ allInformation.push(...result);
227
+ }
228
+ return allInformation;
229
+ };
230
+ }
231
+ const namedValidators = {
232
+ array: Array.isArray,
233
+ bigint: (value) => typeof value === "bigint",
234
+ boolean: (value) => typeof value === "boolean",
235
+ date: (value) => value instanceof Date,
236
+ function: (value) => typeof value === "function",
237
+ null: (value) => value === null,
238
+ number: (value) => typeof value === "number",
239
+ object: (value) => typeof value === "object" && value !== null,
240
+ string: (value) => typeof value === "string",
241
+ symbol: (value) => typeof value === "symbol",
242
+ undefined: (value) => value === void 0
243
+ };
244
+ //#endregion
245
+ export { getObjectValidator };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oscarpalmer/jhunal",
3
- "version": "0.21.0",
3
+ "version": "0.22.0",
4
4
  "description": "Flies free beneath the glistening moons…",
5
5
  "keywords": [
6
6
  "schema",
package/src/helpers.ts CHANGED
@@ -30,9 +30,8 @@ import type {ValueName} from './models/misc.model';
30
30
  import type {
31
31
  ReportingInformation,
32
32
  ReportingType,
33
- ValidatedProperty,
34
- ValidatedPropertyType,
35
- ValidationParameters,
33
+ ValidatorParameters,
34
+ ValidatorType,
36
35
  } from './models/validation.model';
37
36
  import type {Schematic} from './schematic';
38
37
 
@@ -40,7 +39,7 @@ export function getInvalidInputMessage(actual: unknown): string {
40
39
  return VALIDATION_MESSAGE_INVALID_INPUT.replace(TEMPLATE_PATTERN, getValueType(actual));
41
40
  }
42
41
 
43
- export function getInvalidMissingMessage(key: string, types: ValidatedPropertyType[]): string {
42
+ export function getInvalidMissingMessage(key: string, types: ValidatorType[]): string {
44
43
  let message = VALIDATION_MESSAGE_INVALID_REQUIRED.replace(TEMPLATE_PATTERN, renderTypes(types));
45
44
 
46
45
  message = message.replace(TEMPLATE_PATTERN, key);
@@ -50,7 +49,7 @@ export function getInvalidMissingMessage(key: string, types: ValidatedPropertyTy
50
49
 
51
50
  export function getInvalidTypeMessage(
52
51
  key: string,
53
- types: ValidatedPropertyType[],
52
+ types: ValidatorType[],
54
53
  actual: unknown,
55
54
  ): string {
56
55
  let message = VALIDATION_MESSAGE_INVALID_TYPE.replace(TEMPLATE_PATTERN, renderTypes(types));
@@ -78,7 +77,7 @@ export function getInvalidValidatorMessage(
78
77
  return message;
79
78
  }
80
79
 
81
- export function getParameters(input?: unknown): ValidationParameters {
80
+ export function getParameters(input?: unknown): ValidatorParameters {
82
81
  if (typeof input === 'boolean') {
83
82
  return {
84
83
  output: {},
@@ -104,12 +103,16 @@ export function getParameters(input?: unknown): ValidationParameters {
104
103
  };
105
104
  }
106
105
 
107
- function getPropertyType(original: ValidatedPropertyType): string {
106
+ function getPropertyType(original: ValidatorType): string {
108
107
  if (typeof original === 'function') {
109
108
  return 'a validated value';
110
109
  }
111
110
 
112
111
  if (Array.isArray(original)) {
112
+ return `'array'`;
113
+ }
114
+
115
+ if (isPlainObject(original)) {
113
116
  return `'${TYPE_OBJECT}'`;
114
117
  }
115
118
 
@@ -227,7 +230,7 @@ function renderParts(parts: string[], delimiterShort: string, delimiterLong: str
227
230
  return rendered;
228
231
  }
229
232
 
230
- function renderTypes(types: ValidatedPropertyType[]): string {
233
+ function renderTypes(types: ValidatorType[]): string {
231
234
  const unique = new Set<string>();
232
235
  const parts: string[] = [];
233
236
 
package/src/index.ts CHANGED
@@ -1,5 +1,10 @@
1
1
  export {instanceOf, isSchematic} from './helpers';
2
2
  export type {Schema} from './models/schema.plain.model';
3
3
  export type {TypedSchema} from './models/schema.typed.model';
4
- export {SchematicError, ValidationError} from './models/validation.model';
4
+ export {
5
+ SchematicError,
6
+ ValidationError,
7
+ type ValidationInformation,
8
+ type ValidationOptions,
9
+ } from './models/validation.model';
5
10
  export {schematic, type Schematic} from './schematic';
@@ -25,7 +25,7 @@ export type PlainSchema = {
25
25
  * };
26
26
  * ```
27
27
  */
28
- export type Schema = SchemaIndex;
28
+ export type Schema = PlainSchema;
29
29
 
30
30
  /**
31
31
  * A union of all valid types for a single schema entry
@@ -40,13 +40,6 @@ export type SchemaEntry =
40
40
  | ValueName
41
41
  | ((value: unknown) => boolean);
42
42
 
43
- /**
44
- * Index signature interface backing {@link Schema}, allowing string-keyed entries of {@link PlainSchema}, {@link SchemaEntry}, or arrays of {@link SchemaEntry}
45
- */
46
- export interface SchemaIndex {
47
- [key: string]: PlainSchema | SchemaEntry | SchemaEntry[];
48
- }
49
-
50
43
  /**
51
44
  * A property definition with explicit type(s), an optional requirement flag, and optional validators
52
45
  *