@oscarpalmer/jhunal 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/model.ts CHANGED
@@ -1,90 +1,113 @@
1
- import type {
2
- OptionalKeysOf,
3
- RequiredKeysOf,
4
- Simplify,
5
- UnionToTuple,
6
- } from 'type-fest';
1
+ import type {Simplify} from '@oscarpalmer/atoms/models';
2
+ import type {Schematic} from './schematic';
7
3
 
8
- export type GetKey<Value> = {
9
- [Key in keyof Values]: Value extends Values[Key] ? Key : never;
10
- }[keyof Values];
11
-
12
- export type GetTypes<Value extends unknown[]> = Value extends [infer Single]
13
- ? Single
14
- : Value;
15
-
16
- export type GetType<Value> = GetTypes<UnionToTuple<GetKey<Value>>>;
4
+ export type AutoInferExclude = 'date-like' | 'numerical';
17
5
 
18
6
  export type InferProperty<Value> = Value extends Property
19
- ? Value['type'] extends keyof Values
20
- ? Values[Value['type']]
21
- : Value['type'] extends (keyof Values)[]
22
- ? Values[Value['type'][number]]
23
- : never
7
+ ? InferPropertyType<Value['type']>
8
+ : never;
9
+
10
+ type InferPropertyType<Value> = Value extends (infer Type)[]
11
+ ? InferPropertyTypeValue<Type>[]
12
+ : InferPropertyTypeValue<Value>;
13
+
14
+ type InferPropertyTypeValue<Value> = Value extends PropertyType
15
+ ? Value extends Schema
16
+ ? Inferred<Value>
17
+ : Value extends Schematic<infer Model>
18
+ ? Model
19
+ : Value extends ValueKey
20
+ ? Values[Value]
21
+ : Value extends (infer NestedElementType)[]
22
+ ? InferPropertyTypeValue<NestedElementType>[]
23
+ : Value
24
24
  : never;
25
25
 
26
- export type InferValue<Value> = Value extends keyof Values
26
+ export type InferValue<Value> = Value extends ValueKey
27
27
  ? Values[Value]
28
- : Value extends (keyof Values)[]
28
+ : Value extends ValueKey[]
29
29
  ? Values[Value[number]]
30
30
  : never;
31
31
 
32
- export type Inferred<Model extends Schema> = {
33
- [Key in InferredRequiredProperties<Model>]: Model[Key] extends Property
34
- ? InferProperty<Model[Key]>
35
- : InferValue<Model[Key]>;
36
- } & {
37
- [Key in InferredOptionalProperties<Model>]?: Model[Key] extends Property
38
- ? InferProperty<Model[Key]>
39
- : never;
32
+ export type Inferred<Model extends Schema> = Simplify<
33
+ {
34
+ [Key in InferredRequiredProperties<Model>]: Model[Key] extends Property
35
+ ? InferProperty<Model[Key]>
36
+ : InferValue<Model[Key]>;
37
+ } & {
38
+ [Key in InferredOptionalProperties<Model>]?: Model[Key] extends Property
39
+ ? InferProperty<Model[Key]>
40
+ : never;
41
+ }
42
+ >;
43
+
44
+ export type InferredOptionalProperties<Model extends Schema> = keyof {
45
+ [Key in keyof Model as IsOptionalInSchema<Model[Key]> extends true ? Key : never]: never;
40
46
  };
41
47
 
42
- export type InferredOptionalProperties<Model extends Schema> = {
43
- [Key in keyof Model]: Model[Key] extends Property
44
- ? Model[Key]['required'] extends false
45
- ? Key
46
- : never
47
- : never;
48
- }[keyof Model];
48
+ export type InferredRequiredProperties<Model extends Schema> = keyof {
49
+ [Key in keyof Model as IsOptionalInSchema<Model[Key]> extends true ? never : Key]: never;
50
+ };
49
51
 
50
- export type InferredRequiredProperties<Model extends Schema> = {
51
- [Key in keyof Model]: Model[Key] extends Property
52
- ? Model[Key]['required'] extends false
53
- ? never
54
- : Key
55
- : Key;
56
- }[keyof Model];
52
+ type IsNestedObject<Value> = Value extends object
53
+ ? Value extends any[] | Date | Function
54
+ ? false
55
+ : true
56
+ : false;
57
+
58
+ type IsOptionalInSchema<Prop> = Prop extends Property
59
+ ? Prop['required'] extends false
60
+ ? true
61
+ : false
62
+ : false;
63
+
64
+ export type OptionalKeys<Value> = {
65
+ [Key in keyof Value]-?: {} extends Pick<Value, Key> ? Key : never;
66
+ }[keyof Value];
57
67
 
58
68
  export type OptionalProperty<Type> = {
59
69
  required: false;
60
- type: GetType<Type>;
70
+ type: PropertyTypeFor<Type>;
61
71
  };
62
72
 
63
73
  export type Property = {
64
74
  required?: boolean;
65
- type: keyof Values | (keyof Values)[];
75
+ type: PropertyType | PropertyType[];
66
76
  };
67
77
 
78
+ type PropertyType = Schema | Schematic<unknown> | ValueKey;
79
+
80
+ type PropertyTypeFor<Value> =
81
+ IsNestedObject<Value> extends true
82
+ ? Value extends Typed
83
+ ? TypedSchema<Value>
84
+ : never
85
+ : ValueToType<Value>;
86
+
87
+ type RequiredKeys<Value> = Exclude<keyof Value, OptionalKeys<Value>>;
88
+
68
89
  export type RequiredProperty<Type> = {
69
90
  required: true;
70
- type: GetType<Type>;
91
+ type: PropertyTypeFor<Type>;
71
92
  };
72
93
 
73
94
  /**
74
95
  * A schema for validating objects
75
96
  */
76
- export type Schema = Record<string, keyof Values | (keyof Values)[] | Property>;
77
-
78
- /**
79
- * A schematic for validating objects
80
- */
81
- export type Schematic<Model> = {
82
- /**
83
- * Does the value match the schema?
84
- */
85
- is(value: unknown): value is Model;
97
+ export type Schema = {
98
+ [key: string]: Property | ValueKey | ValueKey[];
86
99
  };
87
100
 
101
+ export type TypeToValueKey<Value> = {
102
+ [Key in Exclude<ValueKey, AutoInferExclude>]: Value extends Values[Key] ? Key : never;
103
+ }[Exclude<ValueKey, AutoInferExclude>] extends infer SpecificKey
104
+ ? SpecificKey extends never
105
+ ? {
106
+ [Key in AutoInferExclude]: Value extends Values[Key] ? Key : never;
107
+ }[AutoInferExclude]
108
+ : SpecificKey
109
+ : never;
110
+
88
111
  export type Typed = Record<string, unknown>;
89
112
 
90
113
  /**
@@ -92,34 +115,69 @@ export type Typed = Record<string, unknown>;
92
115
  */
93
116
  export type TypedSchema<Model extends Typed> = Simplify<
94
117
  {
95
- [Key in RequiredKeysOf<Model>]:
96
- | GetType<Model[Key]>
97
- | RequiredProperty<Model[Key]>;
118
+ [Key in RequiredKeys<Model>]: IsNestedObject<Model[Key]> extends true
119
+ ? Model[Key] extends Typed
120
+ ? TypedSchema<Model[Key]>
121
+ : never
122
+ : ValueToType<Model[Key]> | RequiredProperty<Model[Key]>;
98
123
  } & {
99
- [Key in OptionalKeysOf<Model>]: OptionalProperty<Model[Key]>;
124
+ [Key in OptionalKeys<Model>]: IsNestedObject<Model[Key]> extends true
125
+ ? Exclude<Model[Key], undefined> extends Typed
126
+ ? TypedSchema<Exclude<Model[Key], undefined>> | OptionalProperty<Model[Key]>
127
+ : never
128
+ : OptionalProperty<Model[Key]>;
100
129
  }
101
130
  >;
102
131
 
132
+ type UnionToIntersection<Value> = (Value extends any ? (value: Value) => void : never) extends (
133
+ item: infer Item,
134
+ ) => void
135
+ ? Item
136
+ : never;
137
+
138
+ type LastOfUnion<Value> =
139
+ UnionToIntersection<Value extends any ? () => Value : never> extends () => infer Item
140
+ ? Item
141
+ : never;
142
+
143
+ type UnionToTuple<Value, Values extends any[] = []> = [Value] extends [never]
144
+ ? Values
145
+ : UnionToTuple<Exclude<Value, LastOfUnion<Value>>, [LastOfUnion<Value>, ...Values]>;
146
+
103
147
  export type ValidatedProperty = {
104
148
  required: boolean;
105
- types: (keyof Values)[];
149
+ types: ValidatedPropertyType[];
106
150
  };
107
151
 
152
+ export type ValidatedPropertyType = Schematic<unknown> | ValidatedSchema | ValueKey;
153
+
108
154
  export type ValidatedSchema = {
109
155
  keys: string[];
110
156
  length: number;
111
- properties: Record<string, ValidatedProperty>;
157
+ properties: ValidatedSchemaProperties;
112
158
  };
113
159
 
160
+ type ValidatedSchemaProperties = {
161
+ [key: string]: ValidatedProperty;
162
+ };
163
+
164
+ export type ValueKey = keyof Values;
165
+
166
+ export type ValueToType<Value> = ValueToTypes<UnionToTuple<TypeToValueKey<Value>>>;
167
+
168
+ export type ValueToTypes<Value extends unknown[]> = Value extends [infer Type] ? Type : Value;
169
+
114
170
  export type Values = {
115
171
  array: unknown[];
116
172
  bigint: bigint;
117
173
  boolean: boolean;
118
174
  date: Date;
175
+ 'date-like': number | string | Date;
119
176
  // biome-ignore lint/complexity/noBannedTypes: it's the most basic value type, so I think it's ok
120
177
  function: Function;
121
178
  null: null;
122
179
  number: number;
180
+ numerical: bigint | number;
123
181
  object: object;
124
182
  string: string;
125
183
  symbol: symbol;
package/src/schematic.ts CHANGED
@@ -1,26 +1,48 @@
1
- import type {Inferred, Schema, Schematic, Typed, TypedSchema} from './model';
2
- import {getValidatedSchema, validate} from './validation';
1
+ import type {Inferred, Schema, Typed, TypedSchema, ValidatedSchema} from './model';
2
+ import {validateSchema} from './validation/schema.validation';
3
+ import {validateValue} from './validation/value.validation';
3
4
 
4
5
  /**
5
- * Create a schematic from a typed schema
6
+ * A schematic for validating objects
6
7
  */
7
- export function schematic<Model extends Typed>(
8
- schema: TypedSchema<Model>,
9
- ): Schematic<Model>;
8
+ export class Schematic<Model> {
9
+ declare private readonly $schematic: true;
10
+
11
+ #schema: ValidatedSchema;
12
+ #validatable: boolean;
13
+
14
+ get validatable(): boolean {
15
+ return this.#validatable;
16
+ }
17
+
18
+ constructor(schema: Model) {
19
+ Object.defineProperty(this, '$schematic', {
20
+ value: true,
21
+ });
22
+
23
+ this.#schema = validateSchema(schema as unknown as Schema);
24
+
25
+ this.#validatable = this.#schema.length > 0;
26
+ }
27
+
28
+ /**
29
+ * Does the value match the schema?
30
+ */
31
+ is(value: unknown): value is Model {
32
+ return this.#validatable && validateValue(this.#schema, value);
33
+ }
34
+ }
10
35
 
11
36
  /**
12
37
  * Create a schematic from a schema
13
38
  */
14
- export function schematic<Model extends Schema>(
15
- schema: Model,
16
- ): Schematic<Inferred<Model>>;
17
-
18
- export function schematic<Model extends Schema>(schema: Model) {
19
- const validated = getValidatedSchema(schema);
39
+ export function schematic<Model extends Schema>(schema: Model): Schematic<Inferred<Model>>;
20
40
 
21
- const canValidate = validated.length > 0;
41
+ /**
42
+ * Create a schematic from a typed schema
43
+ */
44
+ export function schematic<Model extends Typed>(schema: TypedSchema<Model>): Schematic<Model>;
22
45
 
23
- return Object.freeze({
24
- is: (value: unknown) => canValidate && validate(validated, value),
25
- });
46
+ export function schematic<Model extends Schema>(schema: Model): Schematic<Model> {
47
+ return new Schematic<Model>(schema);
26
48
  }
@@ -0,0 +1,63 @@
1
+ import type {PlainObject} from '@oscarpalmer/atoms/models';
2
+ import {getTypes} from '../helpers';
3
+ import type {Schema, ValidatedPropertyType, ValidatedSchema} from '../model';
4
+
5
+ export function validateSchema(schema: unknown): ValidatedSchema {
6
+ if (validatedSchemas.has(schema as never)) {
7
+ return validatedSchemas.get(schema as never) as ValidatedSchema;
8
+ }
9
+
10
+ const validated: ValidatedSchema = {
11
+ keys: [],
12
+ length: 0,
13
+ properties: {},
14
+ };
15
+
16
+ if (typeof schema !== 'object' || schema === null) {
17
+ return validated;
18
+ }
19
+
20
+ const keys = Object.keys(schema);
21
+ const {length} = keys;
22
+
23
+ for (let index = 0; index < length; index += 1) {
24
+ const key = keys[index];
25
+ const value = (schema as Schema)[key];
26
+
27
+ let required = true;
28
+ let types: ValidatedPropertyType[];
29
+
30
+ if (Array.isArray(value)) {
31
+ types = getTypes(value);
32
+ } else if (typeof value === 'object' && value !== null) {
33
+ if (typeof (value as PlainObject).required === 'boolean') {
34
+ required = (value as PlainObject).required as boolean;
35
+ }
36
+
37
+ types = getTypes((value as PlainObject).type);
38
+ } else {
39
+ types = getTypes(value);
40
+ }
41
+
42
+ if (types.length > 0) {
43
+ if (!required && !types.includes('undefined')) {
44
+ types.push('undefined');
45
+ }
46
+
47
+ validated.keys.push(key);
48
+
49
+ validated.properties[key] = {
50
+ required,
51
+ types,
52
+ };
53
+
54
+ validated.length += 1;
55
+ }
56
+ }
57
+
58
+ validatedSchemas.set(schema as never, validated);
59
+
60
+ return validated;
61
+ }
62
+
63
+ export const validatedSchemas = new WeakMap<Schema, ValidatedSchema>();
@@ -0,0 +1,69 @@
1
+ import type {PlainObject} from '@oscarpalmer/atoms/models';
2
+ import {isDateLike, isSchematic} from '../is';
3
+ import type {ValidatedPropertyType, ValidatedSchema, Values} from '../model';
4
+
5
+ export function validateType(type: ValidatedPropertyType, value: unknown): boolean {
6
+ if (typeof type === 'string') {
7
+ return validators[type](value);
8
+ }
9
+
10
+ if (isSchematic(type)) {
11
+ return type.is(value);
12
+ }
13
+
14
+ return validateValue(type as ValidatedSchema, value);
15
+ }
16
+
17
+ export function validateValue(validated: ValidatedSchema, obj: unknown): boolean {
18
+ if (typeof obj !== 'object' || obj === null) {
19
+ return false;
20
+ }
21
+
22
+ outer: for (let keyIndex = 0; keyIndex < validated.length; keyIndex += 1) {
23
+ const key = validated.keys[keyIndex];
24
+ const property = validated.properties[key];
25
+ const value = (obj as PlainObject)[key];
26
+
27
+ if (value === undefined && property.required && !property.types.includes('undefined')) {
28
+ return false;
29
+ }
30
+
31
+ const typesLength = property.types.length;
32
+
33
+ if (typesLength === 1) {
34
+ if (!validateType(property.types[0], value)) {
35
+ return false;
36
+ }
37
+
38
+ continue;
39
+ }
40
+
41
+ for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
42
+ if (validateType(property.types[typeIndex], value)) {
43
+ continue outer;
44
+ }
45
+ }
46
+
47
+ return false;
48
+ }
49
+
50
+ return true;
51
+ }
52
+
53
+ //
54
+
55
+ const validators: Record<keyof Values, (value: unknown) => boolean> = {
56
+ array: Array.isArray,
57
+ bigint: value => typeof value === 'bigint',
58
+ boolean: value => typeof value === 'boolean',
59
+ date: value => value instanceof Date,
60
+ 'date-like': isDateLike,
61
+ function: value => typeof value === 'function',
62
+ null: value => value === null,
63
+ number: value => typeof value === 'number',
64
+ numerical: value => validators.bigint(value) || validators.number(value),
65
+ object: value => typeof value === 'object' && value !== null,
66
+ string: value => typeof value === 'string',
67
+ symbol: value => typeof value === 'symbol',
68
+ undefined: value => value === undefined,
69
+ };
@@ -1,2 +1,2 @@
1
- import type { Values } from './model';
2
- export declare function getTypes(value: unknown): (keyof Values)[];
1
+ import type { ValidatedPropertyType } from './model';
2
+ export declare function getTypes(value: unknown): ValidatedPropertyType[];
package/types/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export type { Schema, Schematic } from './model';
2
- export * from './schematic';
1
+ export type { Schema, TypedSchema } from './model';
2
+ export { schematic, type Schematic } from './schematic';
package/types/is.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { Schematic } from './schematic';
2
+ export declare function isDateLike(value: unknown): value is Date;
3
+ export declare function isSchematic(value: unknown): value is Schematic<never>;
package/types/model.d.ts CHANGED
@@ -1,75 +1,93 @@
1
- import type { OptionalKeysOf, RequiredKeysOf, Simplify, UnionToTuple } from 'type-fest';
2
- export type GetKey<Value> = {
3
- [Key in keyof Values]: Value extends Values[Key] ? Key : never;
4
- }[keyof Values];
5
- export type GetTypes<Value extends unknown[]> = Value extends [infer Single] ? Single : Value;
6
- export type GetType<Value> = GetTypes<UnionToTuple<GetKey<Value>>>;
7
- export type InferProperty<Value> = Value extends Property ? Value['type'] extends keyof Values ? Values[Value['type']] : Value['type'] extends (keyof Values)[] ? Values[Value['type'][number]] : never : never;
8
- export type InferValue<Value> = Value extends keyof Values ? Values[Value] : Value extends (keyof Values)[] ? Values[Value[number]] : never;
9
- export type Inferred<Model extends Schema> = {
1
+ import type { Simplify } from '@oscarpalmer/atoms/models';
2
+ import type { Schematic } from './schematic';
3
+ export type AutoInferExclude = 'date-like' | 'numerical';
4
+ export type InferProperty<Value> = Value extends Property ? InferPropertyType<Value['type']> : never;
5
+ type InferPropertyType<Value> = Value extends (infer Type)[] ? InferPropertyTypeValue<Type>[] : InferPropertyTypeValue<Value>;
6
+ type InferPropertyTypeValue<Value> = Value extends PropertyType ? Value extends Schema ? Inferred<Value> : Value extends Schematic<infer Model> ? Model : Value extends ValueKey ? Values[Value] : Value extends (infer NestedElementType)[] ? InferPropertyTypeValue<NestedElementType>[] : Value : never;
7
+ export type InferValue<Value> = Value extends ValueKey ? Values[Value] : Value extends ValueKey[] ? Values[Value[number]] : never;
8
+ export type Inferred<Model extends Schema> = Simplify<{
10
9
  [Key in InferredRequiredProperties<Model>]: Model[Key] extends Property ? InferProperty<Model[Key]> : InferValue<Model[Key]>;
11
10
  } & {
12
11
  [Key in InferredOptionalProperties<Model>]?: Model[Key] extends Property ? InferProperty<Model[Key]> : never;
12
+ }>;
13
+ export type InferredOptionalProperties<Model extends Schema> = keyof {
14
+ [Key in keyof Model as IsOptionalInSchema<Model[Key]> extends true ? Key : never]: never;
15
+ };
16
+ export type InferredRequiredProperties<Model extends Schema> = keyof {
17
+ [Key in keyof Model as IsOptionalInSchema<Model[Key]> extends true ? never : Key]: never;
13
18
  };
14
- export type InferredOptionalProperties<Model extends Schema> = {
15
- [Key in keyof Model]: Model[Key] extends Property ? Model[Key]['required'] extends false ? Key : never : never;
16
- }[keyof Model];
17
- export type InferredRequiredProperties<Model extends Schema> = {
18
- [Key in keyof Model]: Model[Key] extends Property ? Model[Key]['required'] extends false ? never : Key : Key;
19
- }[keyof Model];
19
+ type IsNestedObject<Value> = Value extends object ? Value extends any[] | Date | Function ? false : true : false;
20
+ type IsOptionalInSchema<Prop> = Prop extends Property ? Prop['required'] extends false ? true : false : false;
21
+ export type OptionalKeys<Value> = {
22
+ [Key in keyof Value]-?: {} extends Pick<Value, Key> ? Key : never;
23
+ }[keyof Value];
20
24
  export type OptionalProperty<Type> = {
21
25
  required: false;
22
- type: GetType<Type>;
26
+ type: PropertyTypeFor<Type>;
23
27
  };
24
28
  export type Property = {
25
29
  required?: boolean;
26
- type: keyof Values | (keyof Values)[];
30
+ type: PropertyType | PropertyType[];
27
31
  };
32
+ type PropertyType = Schema | Schematic<unknown> | ValueKey;
33
+ type PropertyTypeFor<Value> = IsNestedObject<Value> extends true ? Value extends Typed ? TypedSchema<Value> : never : ValueToType<Value>;
34
+ type RequiredKeys<Value> = Exclude<keyof Value, OptionalKeys<Value>>;
28
35
  export type RequiredProperty<Type> = {
29
36
  required: true;
30
- type: GetType<Type>;
37
+ type: PropertyTypeFor<Type>;
31
38
  };
32
39
  /**
33
40
  * A schema for validating objects
34
41
  */
35
- export type Schema = Record<string, keyof Values | (keyof Values)[] | Property>;
36
- /**
37
- * A schematic for validating objects
38
- */
39
- export type Schematic<Model> = {
40
- /**
41
- * Does the value match the schema?
42
- */
43
- is(value: unknown): value is Model;
42
+ export type Schema = {
43
+ [key: string]: Property | ValueKey | ValueKey[];
44
44
  };
45
+ export type TypeToValueKey<Value> = {
46
+ [Key in Exclude<ValueKey, AutoInferExclude>]: Value extends Values[Key] ? Key : never;
47
+ }[Exclude<ValueKey, AutoInferExclude>] extends infer SpecificKey ? SpecificKey extends never ? {
48
+ [Key in AutoInferExclude]: Value extends Values[Key] ? Key : never;
49
+ }[AutoInferExclude] : SpecificKey : never;
45
50
  export type Typed = Record<string, unknown>;
46
51
  /**
47
52
  * A typed schema for validating objects
48
53
  */
49
54
  export type TypedSchema<Model extends Typed> = Simplify<{
50
- [Key in RequiredKeysOf<Model>]: GetType<Model[Key]> | RequiredProperty<Model[Key]>;
55
+ [Key in RequiredKeys<Model>]: IsNestedObject<Model[Key]> extends true ? Model[Key] extends Typed ? TypedSchema<Model[Key]> : never : ValueToType<Model[Key]> | RequiredProperty<Model[Key]>;
51
56
  } & {
52
- [Key in OptionalKeysOf<Model>]: OptionalProperty<Model[Key]>;
57
+ [Key in OptionalKeys<Model>]: IsNestedObject<Model[Key]> extends true ? Exclude<Model[Key], undefined> extends Typed ? TypedSchema<Exclude<Model[Key], undefined>> | OptionalProperty<Model[Key]> : never : OptionalProperty<Model[Key]>;
53
58
  }>;
59
+ type UnionToIntersection<Value> = (Value extends any ? (value: Value) => void : never) extends (item: infer Item) => void ? Item : never;
60
+ type LastOfUnion<Value> = UnionToIntersection<Value extends any ? () => Value : never> extends () => infer Item ? Item : never;
61
+ type UnionToTuple<Value, Values extends any[] = []> = [Value] extends [never] ? Values : UnionToTuple<Exclude<Value, LastOfUnion<Value>>, [LastOfUnion<Value>, ...Values]>;
54
62
  export type ValidatedProperty = {
55
63
  required: boolean;
56
- types: (keyof Values)[];
64
+ types: ValidatedPropertyType[];
57
65
  };
66
+ export type ValidatedPropertyType = Schematic<unknown> | ValidatedSchema | ValueKey;
58
67
  export type ValidatedSchema = {
59
68
  keys: string[];
60
69
  length: number;
61
- properties: Record<string, ValidatedProperty>;
70
+ properties: ValidatedSchemaProperties;
71
+ };
72
+ type ValidatedSchemaProperties = {
73
+ [key: string]: ValidatedProperty;
62
74
  };
75
+ export type ValueKey = keyof Values;
76
+ export type ValueToType<Value> = ValueToTypes<UnionToTuple<TypeToValueKey<Value>>>;
77
+ export type ValueToTypes<Value extends unknown[]> = Value extends [infer Type] ? Type : Value;
63
78
  export type Values = {
64
79
  array: unknown[];
65
80
  bigint: bigint;
66
81
  boolean: boolean;
67
82
  date: Date;
83
+ 'date-like': number | string | Date;
68
84
  function: Function;
69
85
  null: null;
70
86
  number: number;
87
+ numerical: bigint | number;
71
88
  object: object;
72
89
  string: string;
73
90
  symbol: symbol;
74
91
  undefined: undefined;
75
92
  };
93
+ export {};
@@ -1,9 +1,22 @@
1
- import type { Inferred, Schema, Schematic, Typed, TypedSchema } from './model';
1
+ import type { Inferred, Schema, Typed, TypedSchema } from './model';
2
2
  /**
3
- * Create a schematic from a typed schema
3
+ * A schematic for validating objects
4
4
  */
5
- export declare function schematic<Model extends Typed>(schema: TypedSchema<Model>): Schematic<Model>;
5
+ export declare class Schematic<Model> {
6
+ #private;
7
+ private readonly $schematic;
8
+ get validatable(): boolean;
9
+ constructor(schema: Model);
10
+ /**
11
+ * Does the value match the schema?
12
+ */
13
+ is(value: unknown): value is Model;
14
+ }
6
15
  /**
7
16
  * Create a schematic from a schema
8
17
  */
9
18
  export declare function schematic<Model extends Schema>(schema: Model): Schematic<Inferred<Model>>;
19
+ /**
20
+ * Create a schematic from a typed schema
21
+ */
22
+ export declare function schematic<Model extends Typed>(schema: TypedSchema<Model>): Schematic<Model>;
@@ -0,0 +1,3 @@
1
+ import type { Schema, ValidatedSchema } from '../model';
2
+ export declare function validateSchema(schema: unknown): ValidatedSchema;
3
+ export declare const validatedSchemas: WeakMap<Schema, ValidatedSchema>;
@@ -0,0 +1,3 @@
1
+ import type { ValidatedPropertyType, ValidatedSchema } from '../model';
2
+ export declare function validateType(type: ValidatedPropertyType, value: unknown): boolean;
3
+ export declare function validateValue(validated: ValidatedSchema, obj: unknown): boolean;
package/dist/helpers.cjs DELETED
@@ -1,24 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
-
5
- function getTypes(value) {
6
- return (Array.isArray(value) ? value : [value]).filter(
7
- (item) => types.has(item)
8
- );
9
- }
10
- const types = /* @__PURE__ */ new Set([
11
- "array",
12
- "bigint",
13
- "boolean",
14
- "date",
15
- "function",
16
- "null",
17
- "number",
18
- "object",
19
- "string",
20
- "symbol",
21
- "undefined"
22
- ]);
23
-
24
- exports.getTypes = getTypes;
package/dist/index.cjs DELETED
@@ -1,9 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
-
5
- const schematic = require('./schematic.cjs');
6
-
7
-
8
-
9
- exports.schematic = schematic.schematic;
package/dist/model.cjs DELETED
@@ -1,2 +0,0 @@
1
- 'use strict';
2
-