@oscarpalmer/jhunal 0.10.0 → 0.12.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,11 +1,22 @@
1
- import type { Values } from './models';
2
- export declare const EXPRESSION_HAS_NUMBER: RegExp;
1
+ export declare const ERROR_NAME = "SchematicError";
3
2
  export declare const EXPRESSION_INDEX: RegExp;
3
+ export declare const EXPRESSION_KEY_PREFIX: RegExp;
4
+ export declare const EXPRESSION_KEY_VALUE: RegExp;
4
5
  export declare const EXPRESSION_PROPERTY: RegExp;
6
+ export declare const MESSAGE_CONSTRUCTOR = "Expected a constructor function";
7
+ export declare const MESSAGE_SCHEMA_INVALID_EMPTY = "Schema must have at least one property";
8
+ export declare const MESSAGE_SCHEMA_INVALID_PROPERTY_REQUIRED = "'<>.$required' property must be a boolean";
9
+ export declare const MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE = "'<>' property must be of a valid type";
10
+ export declare const MESSAGE_SCHEMA_INVALID_TYPE = "Schema must be an object";
11
+ export declare const MESSAGE_VALIDATOR_INVALID_KEY = "Validator '<>' does not exist";
12
+ export declare const MESSAGE_VALIDATOR_INVALID_TYPE = "Validators must be an object";
13
+ export declare const MESSAGE_VALIDATOR_INVALID_VALUE = "Validator '<>' must be a function or an array of functions";
5
14
  export declare const PROPERTY_REQUIRED = "$required";
6
15
  export declare const PROPERTY_TYPE = "$type";
7
16
  export declare const PROPERTY_VALIDATORS = "$validators";
8
17
  export declare const SCHEMATIC_NAME = "$schematic";
18
+ export declare const TEMPLATE_PATTERN = "<>";
9
19
  export declare const TYPE_OBJECT = "object";
10
20
  export declare const TYPE_UNDEFINED = "undefined";
11
- export declare const TYPE_ALL: Set<keyof Values>;
21
+ export declare const VALIDATABLE_TYPES: Set<keyof import("./models").Values>;
22
+ export declare const TYPE_ALL: Set<keyof import("./models").Values>;
package/types/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { isInstance } from './is';
2
- export type { Schema, TypedSchema } from './models';
1
+ export { instanceOf } from './is';
2
+ export { SchematicError, type Schema, type TypedSchema } from './models';
3
3
  export { schematic, type Schematic } from './schematic';
package/types/is.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import type { Constructor } from './models';
2
2
  import type { Schematic } from './schematic';
3
- export declare function isInstance<Instance>(constructor: Constructor<Instance>): (value: unknown) => value is Instance;
3
+ export declare function instanceOf<Instance>(constructor: Constructor<Instance>): (value: unknown) => value is Instance;
4
4
  export declare function isSchematic(value: unknown): value is Schematic<never>;
package/types/models.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { PlainObject, Simplify } from '@oscarpalmer/atoms/models';
1
+ import type { GenericCallback, PlainObject, Simplify } from '@oscarpalmer/atoms/models';
2
2
  import type { Schematic } from './schematic';
3
3
  export type Constructor<Instance = any> = new (...args: any[]) => Instance;
4
4
  type DeduplicateTuple<Value extends unknown[], Seen extends unknown[] = []> = Value extends [
@@ -23,8 +23,12 @@ type InferRequiredKeys<Model extends Schema> = keyof {
23
23
  [Key in keyof Model as IsOptionalProperty<Model[Key]> extends true ? never : Key]: never;
24
24
  };
25
25
  type InferSchemaEntry<Value> = Value extends (infer Item)[] ? InferSchemaEntryValue<Item> : InferSchemaEntryValue<Value>;
26
- type InferSchemaEntryValue<Value> = Value extends Constructor<infer Instance> ? Instance : Value extends Schematic<infer Model> ? Model : Value extends SchemaProperty ? InferPropertyType<Value['$type']> : Value extends ValueName ? Values[Value & ValueName] : Value extends Schema ? Infer<Value> : never;
27
- type IsOptionalProperty<Value> = Value extends SchemaProperty ? Value['$required'] extends false ? true : false : false;
26
+ type InferSchemaEntryValue<Value> = Value extends Constructor<infer Instance> ? Instance : Value extends Schematic<infer Model> ? Model : Value extends SchemaProperty ? InferPropertyType<Value['$type']> : Value extends NestedSchema ? Infer<Omit<Value, '$required'>> : Value extends ValueName ? Values[Value & ValueName] : Value extends Schema ? Infer<Value> : never;
27
+ type IsOptionalProperty<Value> = Value extends SchemaProperty ? Value['$required'] extends false ? true : false : Value extends {
28
+ $required?: boolean;
29
+ } ? Value extends {
30
+ $required: false;
31
+ } ? true : false : false;
28
32
  type LastOfUnion<Value> = UnionToIntersection<Value extends unknown ? () => Value : never> extends () => infer Item ? Item : never;
29
33
  type MapToValueTypes<Value extends unknown[]> = Value extends [infer Head, ...infer Tail] ? [ToValueType<Head>, ...MapToValueTypes<Tail>] : [];
30
34
  type MapToSchemaPropertyTypes<Value extends unknown[]> = Value extends [infer Head, ...infer Tail] ? [ToSchemaPropertyTypeEach<Head>, ...MapToSchemaPropertyTypes<Tail>] : [];
@@ -33,7 +37,8 @@ type MapToSchemaPropertyTypes<Value extends unknown[]> = Value extends [infer He
33
37
  */
34
38
  export type NestedSchema = {
35
39
  $required?: boolean;
36
- } & Schema;
40
+ [key: string]: any;
41
+ };
37
42
  type OptionalKeys<Value> = {
38
43
  [Key in keyof Value]-?: {} extends Pick<Value, Key> ? Key : never;
39
44
  }[keyof Value];
@@ -45,9 +50,9 @@ type RequiredKeys<Value> = Exclude<keyof Value, OptionalKeys<Value>>;
45
50
  * A schema for validating objects
46
51
  */
47
52
  export type Schema = SchemaIndex;
48
- type SchemaEntry = Constructor | NestedSchema | SchemaProperty | Schematic<unknown> | ValueName;
53
+ type SchemaEntry = Constructor | Schema | SchemaProperty | Schematic<unknown> | ValueName | ((value: unknown) => boolean);
49
54
  interface SchemaIndex {
50
- [key: string]: SchemaEntry | SchemaEntry[];
55
+ [key: string]: NestedSchema | SchemaEntry | SchemaEntry[];
51
56
  }
52
57
  /**
53
58
  * A property definition with explicit type(s) and optional requirement flag
@@ -57,11 +62,14 @@ export type SchemaProperty = {
57
62
  $type: SchemaPropertyType | SchemaPropertyType[];
58
63
  $validators?: PropertyValidators<SchemaPropertyType | SchemaPropertyType[]>;
59
64
  };
60
- type SchemaPropertyType = Constructor | Schema | Schematic<unknown> | ValueName;
65
+ type SchemaPropertyType = Constructor | Schema | Schematic<unknown> | ValueName | ((value: unknown) => boolean);
66
+ export declare class SchematicError extends Error {
67
+ constructor(message: string);
68
+ }
61
69
  type ToSchemaPropertyType<Value> = UnwrapSingle<DeduplicateTuple<MapToSchemaPropertyTypes<UnionToTuple<Value>>>>;
62
- type ToSchemaPropertyTypeEach<Value> = Value extends PlainObject ? TypedSchema<Value> : ToValueType<Value>;
70
+ type ToSchemaPropertyTypeEach<Value> = Value extends NestedSchema ? Omit<Value, '$required'> : Value extends PlainObject ? TypedSchema<Value> : ToValueType<Value>;
63
71
  type ToSchemaType<Value> = UnwrapSingle<DeduplicateTuple<MapToValueTypes<UnionToTuple<Value>>>>;
64
- type ToValueType<Value> = Value extends unknown[] ? 'array' : Value extends bigint ? 'bigint' : Value extends boolean ? 'boolean' : Value extends Date ? 'date' : Value extends Function ? 'function' : Value extends null ? 'null' : Value extends number ? 'number' : Value extends object ? 'object' | ((value: unknown) => value is Value) : Value extends string ? 'string' : Value extends symbol ? 'symbol' : Value extends undefined ? 'undefined' : (value: unknown) => value is Value;
72
+ type ToValueType<Value> = Value extends unknown[] ? 'array' : Value extends bigint ? 'bigint' : Value extends boolean ? 'boolean' : Value extends Date ? 'date' : Value extends Schematic<any> ? Value : Value extends Function ? 'function' : Value extends null ? 'null' : Value extends number ? 'number' : Value extends object ? 'object' | ((value: unknown) => value is Value) : Value extends string ? 'string' : Value extends symbol ? 'symbol' : Value extends undefined ? 'undefined' : (value: unknown) => value is Value;
65
73
  type TuplePermutations<Tuple extends unknown[], Elput extends unknown[] = []> = Tuple['length'] extends 0 ? Elput : {
66
74
  [Key in keyof Tuple]: TuplePermutations<TupleRemoveAt<Tuple, Key & `${number}`>, [
67
75
  ...Elput,
@@ -101,9 +109,9 @@ export type TypedPropertyRequired<Value> = {
101
109
  * Create a schema type constrained to match a TypeScript type
102
110
  */
103
111
  export type TypedSchema<Model extends PlainObject> = Simplify<{
104
- [Key in RequiredKeys<Model>]: Model[Key] extends PlainObject ? TypedSchemaRequired<Model[Key]> : ToSchemaType<Model[Key]> | TypedPropertyRequired<Model[Key]>;
112
+ [Key in RequiredKeys<Model>]: Model[Key] extends PlainObject ? TypedSchemaRequired<Model[Key]> | Schematic<Model[Key]> : ToSchemaType<Model[Key]> | TypedPropertyRequired<Model[Key]>;
105
113
  } & {
106
- [Key in OptionalKeys<Model>]: Exclude<Model[Key], undefined> extends PlainObject ? TypedSchemaOptional<Exclude<Model[Key], undefined>> : TypedPropertyOptional<Model[Key]>;
114
+ [Key in OptionalKeys<Model>]: Exclude<Model[Key], undefined> extends PlainObject ? TypedSchemaOptional<Exclude<Model[Key], undefined>> | Schematic<Exclude<Model[Key], undefined>> : TypedPropertyOptional<Model[Key]>;
107
115
  }>;
108
116
  type TypedSchemaOptional<Model extends PlainObject> = {
109
117
  $required: false;
@@ -115,22 +123,20 @@ type UnionToIntersection<Value> = (Value extends unknown ? (value: Value) => voi
115
123
  type UnionToTuple<Value, Items extends unknown[] = []> = [Value] extends [never] ? Items : UnionToTuple<Exclude<Value, LastOfUnion<Value>>, [LastOfUnion<Value>, ...Items]>;
116
124
  type UnwrapSingle<Value extends unknown[]> = Value extends [infer Only] ? Only : Value['length'] extends 1 | 2 | 3 | 4 | 5 ? TuplePermutations<Value> : Value;
117
125
  export type ValidatedProperty = {
126
+ key: ValidatedPropertyKey;
118
127
  required: boolean;
119
128
  types: ValidatedPropertyType[];
120
129
  validators: ValidatedPropertyValidators;
121
130
  };
122
- export type ValidatedPropertyType = Schematic<unknown> | ValueName;
131
+ export type ValidatedPropertyKey = {
132
+ full: string;
133
+ prefix: string | undefined;
134
+ value: string;
135
+ };
136
+ export type ValidatedPropertyType = GenericCallback | Schematic<unknown> | ValueName;
123
137
  export type ValidatedPropertyValidators = {
124
138
  [Key in ValueName]?: Array<(value: unknown) => boolean>;
125
139
  };
126
- export type ValidatedSchema = {
127
- enabled: boolean;
128
- keys: {
129
- array: string[];
130
- set: Set<string>;
131
- };
132
- properties: Record<string, ValidatedProperty>;
133
- };
134
140
  /**
135
141
  * Valid type name strings
136
142
  */
@@ -1,13 +1,12 @@
1
1
  import type { PlainObject } from '@oscarpalmer/atoms/models';
2
- import type { Infer, Schema, TypedSchema } from './models';
2
+ import { type Infer, type Schema, type TypedSchema, type ValidatedProperty } from './models';
3
3
  /**
4
4
  * A schematic for validating objects
5
5
  */
6
6
  export declare class Schematic<Model> {
7
7
  #private;
8
8
  private readonly $schematic;
9
- get enabled(): boolean;
10
- constructor(schema: Model);
9
+ constructor(properties: ValidatedProperty[]);
11
10
  /**
12
11
  * Does the value match the schema?
13
12
  */
@@ -0,0 +1,3 @@
1
+ import type { PlainObject } from '@oscarpalmer/atoms/models';
2
+ import { type ValidatedProperty } from '../models';
3
+ export declare function getProperties(original: PlainObject): ValidatedProperty[];
@@ -1,3 +1,2 @@
1
- import type { ValidatedProperty, ValidatedPropertyType, ValidatedSchema } from '../models';
2
- export declare function validateType(type: ValidatedPropertyType, property: ValidatedProperty, value: unknown): boolean;
3
- export declare function validateValue(validated: ValidatedSchema, obj: unknown): boolean;
1
+ import type { ValidatedProperty } from '../models';
2
+ export declare function validateObject(obj: unknown, properties: ValidatedProperty[]): boolean;
@@ -1,12 +0,0 @@
1
- function compact(array, strict) {
2
- if (!Array.isArray(array)) return [];
3
- if (strict === true) return array.filter(Boolean);
4
- const { length } = array;
5
- const compacted = [];
6
- for (let index = 0; index < length; index += 1) {
7
- const item = array[index];
8
- if (item != null) compacted.push(item);
9
- }
10
- return compacted;
11
- }
12
- export { compact };
@@ -1,20 +0,0 @@
1
- /**
2
- * Is the value an array or a record?
3
- * @param value Value to check
4
- * @returns `true` if the value is an array or a record, otherwise `false`
5
- */
6
- function isArrayOrPlainObject(value) {
7
- return Array.isArray(value) || isPlainObject(value);
8
- }
9
- /**
10
- * Is the value a plain object?
11
- * @param value Value to check
12
- * @returns `true` if the value is a plain object, otherwise `false`
13
- */
14
- function isPlainObject(value) {
15
- if (value === null || typeof value !== "object") return false;
16
- if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
17
- const prototype = Object.getPrototypeOf(value);
18
- return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
19
- }
20
- export { isArrayOrPlainObject };
@@ -1,24 +0,0 @@
1
- import { compact } from "./array/compact.js";
2
- /**
3
- * Get the string value from any value
4
- * @param value Original value
5
- * @returns String representation of the value
6
- */
7
- function getString(value) {
8
- if (typeof value === "string") return value;
9
- if (value == null) return "";
10
- if (typeof value === "function") return getString(value());
11
- if (typeof value !== "object") return String(value);
12
- const asString = String(value.valueOf?.() ?? value);
13
- return asString.startsWith("[object ") ? JSON.stringify(value) : asString;
14
- }
15
- /**
16
- * Join an array of values into a string
17
- * @param value Array of values
18
- * @param delimiter Delimiter to use between values
19
- * @returns Joined string
20
- */
21
- function join(value, delimiter) {
22
- return compact(value).map(getString).join(typeof delimiter === "string" ? delimiter : "");
23
- }
24
- export { join };
@@ -1,36 +0,0 @@
1
- import { isArrayOrPlainObject } from "../internal/is.js";
2
- import { join } from "../internal/string.js";
3
- function flattenObject(value, depth, smushed, prefix) {
4
- if (depth >= MAX_DEPTH) return {};
5
- if (smushed.has(value)) return smushed.get(value);
6
- const keys = Object.keys(value);
7
- const { length } = keys;
8
- const flattened = {};
9
- for (let index = 0; index < length; index += 1) {
10
- const key = keys[index];
11
- const val = value[key];
12
- if (isArrayOrPlainObject(val)) {
13
- const prefixedKey = join([prefix, key], ".");
14
- flattened[prefixedKey] = Array.isArray(val) ? [...val] : { ...val };
15
- const nested = flattenObject(val, depth + 1, smushed, prefixedKey);
16
- const nestedKeys = Object.keys(nested);
17
- const nestedLength = nestedKeys.length;
18
- for (let nestedIndex = 0; nestedIndex < nestedLength; nestedIndex += 1) {
19
- const nestedKey = nestedKeys[nestedIndex];
20
- flattened[nestedKey] = nested[nestedKey];
21
- }
22
- } else flattened[join([prefix, key], ".")] = val;
23
- }
24
- smushed.set(value, flattened);
25
- return flattened;
26
- }
27
- /**
28
- * Smush an object into a flat object that uses dot notation keys
29
- * @param value Object to smush
30
- * @returns Smushed object with dot notation keys
31
- */
32
- function smush(value) {
33
- return typeof value === "object" && value !== null ? flattenObject(value, 0, /* @__PURE__ */ new WeakMap()) : {};
34
- }
35
- var MAX_DEPTH = 100;
36
- export { smush };
@@ -1,92 +0,0 @@
1
- import { EXPRESSION_HAS_NUMBER, EXPRESSION_INDEX, EXPRESSION_PROPERTY, PROPERTY_REQUIRED, PROPERTY_TYPE, PROPERTY_VALIDATORS, TYPE_ALL, TYPE_OBJECT, TYPE_UNDEFINED } from "../constants.js";
2
- import { isInstance, isSchematic } from "../is.js";
3
- import { smush } from "../node_modules/@oscarpalmer/atoms/dist/value/smush.js";
4
- import { isConstructor } from "@oscarpalmer/atoms/is";
5
- function addPropertyType(to, key, values, validators, required) {
6
- if (to.keys.set.has(key)) {
7
- const property = to.properties[key];
8
- for (const type of values) if (!property.types.includes(type)) property.types.push(type);
9
- } else {
10
- to.keys.array.push(key);
11
- to.keys.set.add(key);
12
- to.properties[key] = {
13
- required,
14
- types: values,
15
- validators: {}
16
- };
17
- }
18
- if (!required && !to.properties[key].types.includes("undefined")) to.properties[key].types.push(TYPE_UNDEFINED);
19
- to.properties[key].validators = validators;
20
- }
21
- function getSchema(schema) {
22
- const validated = {
23
- enabled: false,
24
- keys: {
25
- array: [],
26
- set: /* @__PURE__ */ new Set()
27
- },
28
- properties: {}
29
- };
30
- return typeof schema === "object" && schema !== null ? getValidatedSchema(schema, validated) : validated;
31
- }
32
- function getTypes(value, validated, prefix) {
33
- const propertyTypes = [];
34
- const values = Array.isArray(value) ? value : [value];
35
- const { length } = values;
36
- for (let index = 0; index < length; index += 1) {
37
- const type = values[index];
38
- const typeOfType = typeof type;
39
- if (isSchematic(type) || typeOfType === "string" && TYPE_ALL.has(type)) {
40
- propertyTypes.push(type);
41
- continue;
42
- }
43
- if (typeOfType === "function") {
44
- propertyTypes.push(isConstructor(type) ? isInstance(type) : type);
45
- continue;
46
- }
47
- if (typeOfType !== "object" || type === null) continue;
48
- if ("$type" in type) {
49
- propertyTypes.push(...getTypes(type[PROPERTY_TYPE], validated, prefix));
50
- continue;
51
- }
52
- addPropertyType(validated, prefix, [TYPE_OBJECT], {}, type[PROPERTY_REQUIRED] !== false);
53
- propertyTypes.push(TYPE_OBJECT);
54
- getValidatedSchema(type, validated, prefix);
55
- }
56
- return propertyTypes;
57
- }
58
- function getValidatedSchema(schema, validated, prefix) {
59
- const smushed = smush(schema);
60
- const keys = Object.keys(smushed);
61
- const { length } = keys;
62
- const arrayKeys = /* @__PURE__ */ new Set();
63
- const noPrefix = prefix == null;
64
- prefix = noPrefix ? "" : `${prefix}.`;
65
- for (let index = 0; index < length; index += 1) {
66
- const key = keys[index];
67
- const value = smushed[key];
68
- if (Array.isArray(value)) arrayKeys.add(key);
69
- if (EXPRESSION_PROPERTY.test(key)) continue;
70
- if (EXPRESSION_HAS_NUMBER.test(key) && arrayKeys.has(key.replace(EXPRESSION_INDEX, ""))) continue;
71
- let required = true;
72
- let validators = {};
73
- const isObject = typeof value === "object" && value !== null;
74
- if (isObject && "$required" in value) required = typeof value["$required"] === "boolean" ? value[PROPERTY_REQUIRED] : true;
75
- if (isObject && "$validators" in value) validators = getValidators(value[PROPERTY_VALIDATORS]);
76
- const prefixedKey = `${prefix}${key}`;
77
- const types = getTypes(value, validated, prefixedKey);
78
- if (types.length > 0) addPropertyType(validated, prefixedKey, types, validators, required);
79
- }
80
- if (noPrefix) validated.keys.array.sort();
81
- return validated;
82
- }
83
- function getValidators(original) {
84
- const validators = {};
85
- if (typeof original !== "object" || original === null) return validators;
86
- for (const type of TYPE_ALL) {
87
- const value = original[type];
88
- validators[type] = (Array.isArray(value) ? value : [value]).filter((validator) => typeof validator === "function");
89
- }
90
- return validators;
91
- }
92
- export { getSchema };
@@ -1,192 +0,0 @@
1
- import {isConstructor} from '@oscarpalmer/atoms/is';
2
- import type {PlainObject} from '@oscarpalmer/atoms/models';
3
- import {smush} from '@oscarpalmer/atoms/value/misc';
4
- import {
5
- EXPRESSION_HAS_NUMBER,
6
- EXPRESSION_INDEX,
7
- EXPRESSION_PROPERTY,
8
- PROPERTY_REQUIRED,
9
- PROPERTY_TYPE,
10
- PROPERTY_VALIDATORS,
11
- TYPE_ALL,
12
- TYPE_OBJECT,
13
- TYPE_UNDEFINED,
14
- } from '../constants';
15
- import {isInstance, isSchematic} from '../is';
16
- import type {
17
- Schema,
18
- ValidatedPropertyType,
19
- ValidatedPropertyValidators,
20
- ValidatedSchema,
21
- } from '../models';
22
-
23
- function addPropertyType(
24
- to: ValidatedSchema,
25
- key: string,
26
- values: ValidatedPropertyType[],
27
- validators: ValidatedPropertyValidators,
28
- required: boolean,
29
- ): void {
30
- if (to.keys.set.has(key)) {
31
- const property = to.properties[key];
32
-
33
- for (const type of values) {
34
- if (!property.types.includes(type)) {
35
- property.types.push(type);
36
- }
37
- }
38
- } else {
39
- to.keys.array.push(key);
40
- to.keys.set.add(key);
41
-
42
- to.properties[key] = {
43
- required,
44
- types: values,
45
- validators: {},
46
- };
47
- }
48
-
49
- if (!required && !to.properties[key].types.includes(TYPE_UNDEFINED)) {
50
- to.properties[key].types.push(TYPE_UNDEFINED);
51
- }
52
-
53
- to.properties[key].validators = validators;
54
- }
55
-
56
- export function getSchema(schema: unknown): ValidatedSchema {
57
- const validated: ValidatedSchema = {
58
- enabled: false,
59
- keys: {
60
- array: [],
61
- set: new Set<string>(),
62
- },
63
- properties: {},
64
- };
65
-
66
- return typeof schema === 'object' && schema !== null
67
- ? getValidatedSchema(schema as Schema, validated)
68
- : validated;
69
- }
70
-
71
- function getTypes(
72
- value: unknown,
73
- validated: ValidatedSchema,
74
- prefix: string,
75
- ): ValidatedPropertyType[] {
76
- const propertyTypes: ValidatedPropertyType[] = [];
77
-
78
- const values = Array.isArray(value) ? value : [value];
79
- const {length} = values;
80
-
81
- for (let index = 0; index < length; index += 1) {
82
- const type = values[index];
83
- const typeOfType = typeof type;
84
-
85
- if (isSchematic(type) || (typeOfType === 'string' && TYPE_ALL.has(type as never))) {
86
- propertyTypes.push(type as never);
87
-
88
- continue;
89
- }
90
-
91
- if (typeOfType === 'function') {
92
- propertyTypes.push(isConstructor(type) ? isInstance(type) : type);
93
-
94
- continue;
95
- }
96
-
97
- if (typeOfType !== 'object' || type === null) {
98
- continue;
99
- }
100
-
101
- if (PROPERTY_TYPE in type) {
102
- propertyTypes.push(...getTypes(type[PROPERTY_TYPE], validated, prefix));
103
-
104
- continue;
105
- }
106
-
107
- addPropertyType(validated, prefix, [TYPE_OBJECT], {}, type[PROPERTY_REQUIRED] !== false);
108
-
109
- propertyTypes.push(TYPE_OBJECT);
110
-
111
- getValidatedSchema(type as Schema, validated, prefix);
112
- }
113
-
114
- return propertyTypes;
115
- }
116
-
117
- function getValidatedSchema(
118
- schema: Schema,
119
- validated: ValidatedSchema,
120
- prefix?: string,
121
- ): ValidatedSchema {
122
- const smushed = smush(schema as PlainObject);
123
- const keys = Object.keys(smushed);
124
- const {length} = keys;
125
-
126
- const arrayKeys = new Set<string>();
127
- const noPrefix = prefix == null;
128
-
129
- prefix = noPrefix ? '' : `${prefix}.`;
130
-
131
- for (let index = 0; index < length; index += 1) {
132
- const key = keys[index];
133
- const value = smushed[key];
134
-
135
- if (Array.isArray(value)) {
136
- arrayKeys.add(key);
137
- }
138
-
139
- if (EXPRESSION_PROPERTY.test(key)) {
140
- continue;
141
- }
142
-
143
- if (EXPRESSION_HAS_NUMBER.test(key) && arrayKeys.has(key.replace(EXPRESSION_INDEX, ''))) {
144
- continue;
145
- }
146
-
147
- let required = true;
148
- let validators: ValidatedPropertyValidators = {};
149
-
150
- const isObject = typeof value === 'object' && value !== null;
151
-
152
- if (isObject && PROPERTY_REQUIRED in value) {
153
- required = typeof value[PROPERTY_REQUIRED] === 'boolean' ? value[PROPERTY_REQUIRED] : true;
154
- }
155
-
156
- if (isObject && PROPERTY_VALIDATORS in value) {
157
- validators = getValidators(value[PROPERTY_VALIDATORS]);
158
- }
159
-
160
- const prefixedKey = `${prefix}${key}`;
161
-
162
- const types = getTypes(value, validated, prefixedKey);
163
-
164
- if (types.length > 0) {
165
- addPropertyType(validated, prefixedKey, types, validators, required);
166
- }
167
- }
168
-
169
- if (noPrefix) {
170
- validated.keys.array.sort();
171
- }
172
-
173
- return validated;
174
- }
175
-
176
- function getValidators(original: unknown): ValidatedPropertyValidators {
177
- const validators: ValidatedPropertyValidators = {};
178
-
179
- if (typeof original !== 'object' || original === null) {
180
- return validators;
181
- }
182
-
183
- for (const type of TYPE_ALL) {
184
- const value = (original as PlainObject)[type];
185
-
186
- validators[type] = (Array.isArray(value) ? value : [value]).filter(
187
- validator => typeof validator === 'function',
188
- );
189
- }
190
-
191
- return validators;
192
- }
@@ -1,2 +0,0 @@
1
- import type { ValidatedSchema } from '../models';
2
- export declare function getSchema(schema: unknown): ValidatedSchema;