@oscarpalmer/jhunal 0.18.0 → 0.20.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/dist/constants.d.mts +7 -1
- package/dist/constants.mjs +7 -1
- package/dist/helpers.d.mts +6 -1
- package/dist/helpers.mjs +36 -10
- package/dist/index.d.mts +138 -94
- package/dist/index.mjs +128 -43
- package/dist/models/infer.model.d.mts +12 -12
- package/dist/models/misc.model.d.mts +20 -29
- package/dist/models/schema.plain.model.d.mts +4 -4
- package/dist/models/schema.typed.model.d.mts +5 -23
- package/dist/models/transform.model.d.mts +9 -13
- package/dist/models/validation.model.d.mts +49 -13
- package/dist/models/validation.model.mjs +4 -1
- package/dist/schematic.d.mts +52 -4
- package/dist/schematic.mjs +13 -4
- package/dist/validation/value.validation.d.mts +2 -2
- package/dist/validation/value.validation.mjs +78 -33
- package/package.json +1 -1
- package/src/constants.ts +16 -0
- package/src/helpers.ts +61 -15
- package/src/models/infer.model.ts +12 -12
- package/src/models/misc.model.ts +20 -29
- package/src/models/schema.plain.model.ts +4 -4
- package/src/models/schema.typed.model.ts +5 -23
- package/src/models/transform.model.ts +9 -13
- package/src/models/validation.model.ts +51 -9
- package/src/schematic.ts +79 -9
- package/src/validation/property.validation.ts +3 -4
- package/src/validation/value.validation.ts +120 -43
package/src/models/misc.model.ts
CHANGED
|
@@ -3,8 +3,8 @@ import type {SchemaProperty} from './schema.plain.model';
|
|
|
3
3
|
/**
|
|
4
4
|
* Removes duplicate types from a tuple, preserving first occurrence order
|
|
5
5
|
*
|
|
6
|
-
* @template Value
|
|
7
|
-
* @template Seen
|
|
6
|
+
* @template Value Tuple to deduplicate
|
|
7
|
+
* @template Seen Accumulator for already-seen types _(internal)_
|
|
8
8
|
*
|
|
9
9
|
* @example
|
|
10
10
|
* ```ts
|
|
@@ -24,7 +24,7 @@ export type DeduplicateTuple<Value extends unknown[], Seen extends unknown[] = [
|
|
|
24
24
|
/**
|
|
25
25
|
* Recursively extracts {@link ValueName} strings from a type, unwrapping arrays and readonly arrays
|
|
26
26
|
*
|
|
27
|
-
* @template Value
|
|
27
|
+
* @template Value Type to extract value names from
|
|
28
28
|
*
|
|
29
29
|
* @example
|
|
30
30
|
* ```ts
|
|
@@ -43,9 +43,9 @@ export type ExtractValueNames<Value> = Value extends ValueName
|
|
|
43
43
|
/**
|
|
44
44
|
* Determines whether a schema entry is optional
|
|
45
45
|
*
|
|
46
|
-
* Returns `true` if the entry is a {@link SchemaProperty}
|
|
46
|
+
* Returns `true` if the entry is a {@link SchemaProperty} with `$required` set to `false`; otherwise returns `false`
|
|
47
47
|
*
|
|
48
|
-
* @template Value
|
|
48
|
+
* @template Value Schema entry to check
|
|
49
49
|
*/
|
|
50
50
|
export type IsOptionalProperty<Value> = Value extends SchemaProperty
|
|
51
51
|
? Value['$required'] extends false
|
|
@@ -54,9 +54,9 @@ export type IsOptionalProperty<Value> = Value extends SchemaProperty
|
|
|
54
54
|
: false;
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
|
-
* Extracts the last member from a union type by leveraging
|
|
57
|
+
* Extracts the last member from a union type by leveraging contravariance of function parameter types
|
|
58
58
|
*
|
|
59
|
-
* @template Value
|
|
59
|
+
* @template Value Union type
|
|
60
60
|
*/
|
|
61
61
|
export type LastOfUnion<Value> =
|
|
62
62
|
UnionToIntersection<Value extends unknown ? () => Value : never> extends () => infer Item
|
|
@@ -66,7 +66,7 @@ export type LastOfUnion<Value> =
|
|
|
66
66
|
/**
|
|
67
67
|
* Extracts keys from an object type that are optional
|
|
68
68
|
*
|
|
69
|
-
* @template Value
|
|
69
|
+
* @template Value Object type to inspect
|
|
70
70
|
*/
|
|
71
71
|
export type OptionalKeys<Value> = {
|
|
72
72
|
[Key in keyof Value]-?: {} extends Pick<Value, Key> ? Key : never;
|
|
@@ -75,7 +75,7 @@ export type OptionalKeys<Value> = {
|
|
|
75
75
|
/**
|
|
76
76
|
* Extracts keys from an object type that are required _(i.e., not optional)_
|
|
77
77
|
*
|
|
78
|
-
* @template Value
|
|
78
|
+
* @template Value Object type to inspect
|
|
79
79
|
*/
|
|
80
80
|
export type RequiredKeys<Value> = Exclude<keyof Value, OptionalKeys<Value>>;
|
|
81
81
|
|
|
@@ -84,8 +84,8 @@ export type RequiredKeys<Value> = Exclude<keyof Value, OptionalKeys<Value>>;
|
|
|
84
84
|
*
|
|
85
85
|
* Used by {@link UnwrapSingle} to allow schema types in any order for small tuples _(length ≤ 5)_
|
|
86
86
|
*
|
|
87
|
-
* @template Tuple
|
|
88
|
-
* @template Elput
|
|
87
|
+
* @template Tuple Tuple to permute
|
|
88
|
+
* @template Elput Accumulator for the current permutation _(internal; name is Tuple backwards)_
|
|
89
89
|
*
|
|
90
90
|
* @example
|
|
91
91
|
* ```ts
|
|
@@ -110,9 +110,9 @@ export type TuplePermutations<
|
|
|
110
110
|
*
|
|
111
111
|
* Used internally by {@link TuplePermutations}
|
|
112
112
|
*
|
|
113
|
-
* @template Items
|
|
114
|
-
* @template Item
|
|
115
|
-
* @template Prefix
|
|
113
|
+
* @template Items Tuple to remove from
|
|
114
|
+
* @template Item Index as a string literal
|
|
115
|
+
* @template Prefix Accumulator for elements before the target _(internal)_
|
|
116
116
|
*/
|
|
117
117
|
export type TupleRemoveAt<
|
|
118
118
|
Items extends unknown[],
|
|
@@ -129,7 +129,7 @@ export type TupleRemoveAt<
|
|
|
129
129
|
*
|
|
130
130
|
* Uses the contravariance of function parameter types to collapse a union into an intersection
|
|
131
131
|
*
|
|
132
|
-
* @template Value
|
|
132
|
+
* @template Value Union type to convert
|
|
133
133
|
*
|
|
134
134
|
* @example
|
|
135
135
|
* ```ts
|
|
@@ -148,8 +148,8 @@ export type UnionToIntersection<Value> = (
|
|
|
148
148
|
*
|
|
149
149
|
* Repeatedly extracts the {@link LastOfUnion} member and prepends it to the accumulator
|
|
150
150
|
*
|
|
151
|
-
* @template Value
|
|
152
|
-
* @template Items
|
|
151
|
+
* @template Value Union type to convert
|
|
152
|
+
* @template Items Accumulator for the resulting tuple _(internal)_
|
|
153
153
|
*
|
|
154
154
|
* @example
|
|
155
155
|
* ```ts
|
|
@@ -166,7 +166,7 @@ export type UnionToTuple<Value, Items extends unknown[] = []> = [Value] extends
|
|
|
166
166
|
*
|
|
167
167
|
* For tuples of length 2–5, returns all {@link TuplePermutations} to allow types in any order. Longer tuples are returned as-is
|
|
168
168
|
*
|
|
169
|
-
* @template Value
|
|
169
|
+
* @template Value Tuple to potentially unwrap
|
|
170
170
|
*
|
|
171
171
|
* @example
|
|
172
172
|
* ```ts
|
|
@@ -181,21 +181,12 @@ export type UnwrapSingle<Value extends unknown[]> = Value extends [infer Only]
|
|
|
181
181
|
: Value;
|
|
182
182
|
|
|
183
183
|
/**
|
|
184
|
-
*
|
|
184
|
+
* A union of valid type name strings, e.g. `'string'`, `'number'`, `'date'`
|
|
185
185
|
*/
|
|
186
186
|
export type ValueName = keyof Values;
|
|
187
187
|
|
|
188
188
|
/**
|
|
189
|
-
* Maps
|
|
190
|
-
*
|
|
191
|
-
* Used by the type system to resolve {@link ValueName} strings into actual types
|
|
192
|
-
*
|
|
193
|
-
* @example
|
|
194
|
-
* ```ts
|
|
195
|
-
* // Values['string'] => string
|
|
196
|
-
* // Values['date'] => Date
|
|
197
|
-
* // Values['null'] => null
|
|
198
|
-
* ```
|
|
189
|
+
* Maps {@link ValueName} strings to their TypeScript equivalents
|
|
199
190
|
*/
|
|
200
191
|
export type Values = {
|
|
201
192
|
array: unknown[];
|
|
@@ -3,7 +3,7 @@ import type {Schematic} from '../schematic';
|
|
|
3
3
|
import type {ExtractValueNames, ValueName, Values} from './misc.model';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* A generic schema allowing
|
|
6
|
+
* A generic schema allowing nested schemas, {@link SchemaEntry} values, or arrays of {@link SchemaEntry} as values
|
|
7
7
|
*/
|
|
8
8
|
export type PlainSchema = {
|
|
9
9
|
[key: string]: PlainSchema | SchemaEntry | SchemaEntry[] | undefined;
|
|
@@ -30,7 +30,7 @@ export type Schema = SchemaIndex;
|
|
|
30
30
|
/**
|
|
31
31
|
* A union of all valid types for a single schema entry
|
|
32
32
|
*
|
|
33
|
-
* Can be a {@link Constructor},
|
|
33
|
+
* Can be a {@link Constructor}, {@link PlainSchema}, {@link SchemaProperty}, {@link Schematic}, {@link ValueName} string, or a custom validator function
|
|
34
34
|
*/
|
|
35
35
|
export type SchemaEntry =
|
|
36
36
|
| Constructor
|
|
@@ -41,7 +41,7 @@ export type SchemaEntry =
|
|
|
41
41
|
| ((value: unknown) => boolean);
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
* Index signature interface backing {@link Schema}, allowing string-keyed entries of {@link
|
|
44
|
+
* Index signature interface backing {@link Schema}, allowing string-keyed entries of {@link PlainSchema}, {@link SchemaEntry}, or arrays of {@link SchemaEntry}
|
|
45
45
|
*/
|
|
46
46
|
export interface SchemaIndex {
|
|
47
47
|
[key: string]: PlainSchema | SchemaEntry | SchemaEntry[];
|
|
@@ -94,7 +94,7 @@ export type SchemaPropertyType =
|
|
|
94
94
|
*
|
|
95
95
|
* Each key may hold a single validator or an array of validators that receive the typed value
|
|
96
96
|
*
|
|
97
|
-
* @template Value
|
|
97
|
+
* @template Value `$type` value(s) to derive validator keys from
|
|
98
98
|
*
|
|
99
99
|
* @example
|
|
100
100
|
* ```ts
|
|
@@ -7,7 +7,7 @@ import type {ToSchemaPropertyType, ToSchemaType} from './transform.model';
|
|
|
7
7
|
/**
|
|
8
8
|
* A typed optional property definition generated by {@link TypedSchema} for optional keys, with `$required` set to `false` and excludes `undefined` from the type
|
|
9
9
|
*
|
|
10
|
-
* @template Value
|
|
10
|
+
* @template Value Property's type _(including `undefined`)_
|
|
11
11
|
*
|
|
12
12
|
* @example
|
|
13
13
|
* ```ts
|
|
@@ -17,24 +17,15 @@ import type {ToSchemaPropertyType, ToSchemaType} from './transform.model';
|
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
19
|
export type TypedPropertyOptional<Value> = {
|
|
20
|
-
/**
|
|
21
|
-
* The property is not required
|
|
22
|
-
*/
|
|
23
20
|
$required: false;
|
|
24
|
-
/**
|
|
25
|
-
* The type(s) of the property
|
|
26
|
-
*/
|
|
27
21
|
$type: ToSchemaPropertyType<Exclude<Value, undefined>>;
|
|
28
|
-
/**
|
|
29
|
-
* Custom validators for the property and its types
|
|
30
|
-
*/
|
|
31
22
|
$validators?: PropertyValidators<ToSchemaPropertyType<Exclude<Value, undefined>>>;
|
|
32
23
|
};
|
|
33
24
|
|
|
34
25
|
/**
|
|
35
26
|
* A typed required property definition generated by {@link TypedSchema} for required keys, with `$required` defaulting to `true`
|
|
36
27
|
*
|
|
37
|
-
* @template Value
|
|
28
|
+
* @template Value Property's type
|
|
38
29
|
*
|
|
39
30
|
* @example
|
|
40
31
|
* ```ts
|
|
@@ -44,17 +35,8 @@ export type TypedPropertyOptional<Value> = {
|
|
|
44
35
|
* ```
|
|
45
36
|
*/
|
|
46
37
|
export type TypedPropertyRequired<Value> = {
|
|
47
|
-
/**
|
|
48
|
-
* The property is required _(defaults to `true`)_
|
|
49
|
-
*/
|
|
50
38
|
$required?: true;
|
|
51
|
-
/**
|
|
52
|
-
* The type(s) of the property
|
|
53
|
-
*/
|
|
54
39
|
$type: ToSchemaPropertyType<Value>;
|
|
55
|
-
/**
|
|
56
|
-
* Custom validators for the property and its types
|
|
57
|
-
*/
|
|
58
40
|
$validators?: PropertyValidators<ToSchemaPropertyType<Value>>;
|
|
59
41
|
};
|
|
60
42
|
|
|
@@ -63,7 +45,7 @@ export type TypedPropertyRequired<Value> = {
|
|
|
63
45
|
*
|
|
64
46
|
* Required keys map to {@link ToSchemaType} or {@link TypedPropertyRequired}; plain object values may also use {@link Schematic}. Optional keys map to {@link TypedPropertyOptional} or, for plain objects, {@link TypedSchemaOptional}
|
|
65
47
|
*
|
|
66
|
-
* @template Model
|
|
48
|
+
* @template Model Object type to generate a schema for
|
|
67
49
|
*
|
|
68
50
|
* @example
|
|
69
51
|
* ```ts
|
|
@@ -93,7 +75,7 @@ export type TypedSchema<Model extends PlainObject> = Simplify<
|
|
|
93
75
|
/**
|
|
94
76
|
* A {@link TypedSchema} variant for optional nested objects, with `$required` fixed to `false`
|
|
95
77
|
*
|
|
96
|
-
* @template Model
|
|
78
|
+
* @template Model Nested object type
|
|
97
79
|
*/
|
|
98
80
|
type TypedSchemaOptional<Model extends PlainObject> = {
|
|
99
81
|
$required: false;
|
|
@@ -102,7 +84,7 @@ type TypedSchemaOptional<Model extends PlainObject> = {
|
|
|
102
84
|
/**
|
|
103
85
|
* A {@link TypedSchema} variant for required nested objects, with `$required` defaulting to `true`
|
|
104
86
|
*
|
|
105
|
-
* @template Model
|
|
87
|
+
* @template Model Nested object type
|
|
106
88
|
*/
|
|
107
89
|
type TypedSchemaRequired<Model extends PlainObject> = {
|
|
108
90
|
$required?: true;
|
|
@@ -6,7 +6,7 @@ import type {TypedSchema} from './schema.typed.model';
|
|
|
6
6
|
/**
|
|
7
7
|
* Maps each element of a tuple through {@link ToValueType}
|
|
8
8
|
*
|
|
9
|
-
* @template Value
|
|
9
|
+
* @template Value Tuple of types to map
|
|
10
10
|
*/
|
|
11
11
|
export type MapToValueTypes<Value extends unknown[]> = Value extends [infer Head, ...infer Tail]
|
|
12
12
|
? [ToValueType<Head>, ...MapToValueTypes<Tail>]
|
|
@@ -15,7 +15,7 @@ export type MapToValueTypes<Value extends unknown[]> = Value extends [infer Head
|
|
|
15
15
|
/**
|
|
16
16
|
* Maps each element of a tuple through {@link ToSchemaPropertyTypeEach}
|
|
17
17
|
*
|
|
18
|
-
* @template Value
|
|
18
|
+
* @template Value Tuple of types to map
|
|
19
19
|
*/
|
|
20
20
|
export type MapToSchemaPropertyTypes<Value extends unknown[]> = Value extends [
|
|
21
21
|
infer Head,
|
|
@@ -25,11 +25,9 @@ export type MapToSchemaPropertyTypes<Value extends unknown[]> = Value extends [
|
|
|
25
25
|
: [];
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
* Converts a type
|
|
28
|
+
* Converts a TypeScript type to its {@link SchemaPropertyType} representation, suitable for use in a typed schema
|
|
29
29
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* @template Value - type to convert
|
|
30
|
+
* @template Value Type to convert
|
|
33
31
|
*/
|
|
34
32
|
export type ToSchemaPropertyType<Value> = UnwrapSingle<
|
|
35
33
|
DeduplicateTuple<MapToSchemaPropertyTypes<UnionToTuple<Value>>>
|
|
@@ -38,20 +36,18 @@ export type ToSchemaPropertyType<Value> = UnwrapSingle<
|
|
|
38
36
|
/**
|
|
39
37
|
* Converts a single type to its schema property equivalent
|
|
40
38
|
*
|
|
41
|
-
*
|
|
39
|
+
* Plain objects become {@link TypedSchema}; primitives go through {@link ToValueType}
|
|
42
40
|
*
|
|
43
|
-
* @template Value
|
|
41
|
+
* @template Value Type to convert
|
|
44
42
|
*/
|
|
45
43
|
export type ToSchemaPropertyTypeEach<Value> = Value extends PlainObject
|
|
46
44
|
? TypedSchema<Value>
|
|
47
45
|
: ToValueType<Value>;
|
|
48
46
|
|
|
49
47
|
/**
|
|
50
|
-
* Converts a type
|
|
51
|
-
*
|
|
52
|
-
* Deduplicates and unwraps single-element tuples via {@link UnwrapSingle}
|
|
48
|
+
* Converts a TypeScript type to its {@link ValueName} representation, suitable for use as a top-level schema entry
|
|
53
49
|
*
|
|
54
|
-
* @template Value
|
|
50
|
+
* @template Value Type to convert
|
|
55
51
|
*/
|
|
56
52
|
export type ToSchemaType<Value> = UnwrapSingle<
|
|
57
53
|
DeduplicateTuple<MapToValueTypes<UnionToTuple<Value>>>
|
|
@@ -62,7 +58,7 @@ export type ToSchemaType<Value> = UnwrapSingle<
|
|
|
62
58
|
*
|
|
63
59
|
* 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
|
|
64
60
|
*
|
|
65
|
-
* @template Value
|
|
61
|
+
* @template Value Type to map
|
|
66
62
|
*
|
|
67
63
|
* @example
|
|
68
64
|
* ```ts
|
|
@@ -6,8 +6,21 @@ import type {ValueName} from './misc.model';
|
|
|
6
6
|
|
|
7
7
|
// #region Reporting
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Maps each {@link ReportingType} to a boolean flag
|
|
11
|
+
*/
|
|
12
|
+
export type ReportingInformation = Record<ReportingType, boolean> & {
|
|
13
|
+
type: ReportingType;
|
|
14
|
+
};
|
|
10
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Controls how validation failures are reported
|
|
18
|
+
*
|
|
19
|
+
* - `'none'` — returns a boolean _(default)_
|
|
20
|
+
* - `'first'` — returns the first failure as a `Result`
|
|
21
|
+
* - `'all'` — returns all failures as a `Result` _(from same level)_
|
|
22
|
+
* - `'throw'` — throws a {@link ValidationError} on failure
|
|
23
|
+
*/
|
|
11
24
|
export type ReportingType = 'all' | 'first' | 'none' | 'throw';
|
|
12
25
|
|
|
13
26
|
// #endregion
|
|
@@ -15,7 +28,7 @@ export type ReportingType = 'all' | 'first' | 'none' | 'throw';
|
|
|
15
28
|
// #region Schematic validation
|
|
16
29
|
|
|
17
30
|
/**
|
|
18
|
-
*
|
|
31
|
+
* Thrown when a schema definition is invalid
|
|
19
32
|
*/
|
|
20
33
|
export class SchematicError extends Error {
|
|
21
34
|
constructor(message: string) {
|
|
@@ -62,16 +75,12 @@ export type ValidatedProperty = {
|
|
|
62
75
|
};
|
|
63
76
|
|
|
64
77
|
/**
|
|
65
|
-
*
|
|
78
|
+
* The full and short forms of a property's key path
|
|
79
|
+
*
|
|
80
|
+
* For a nested property `address.street`: `full` is `'address.street'`, `short` is `'street'`
|
|
66
81
|
*/
|
|
67
82
|
export type ValidatedPropertyKey = {
|
|
68
|
-
/**
|
|
69
|
-
* Full property key, including parent keys for nested properties _(e.g., `address.street`)_
|
|
70
|
-
*/
|
|
71
83
|
full: string;
|
|
72
|
-
/**
|
|
73
|
-
* The last segment of the property key _(e.g., `street` for `address.street`)_
|
|
74
|
-
*/
|
|
75
84
|
short: string;
|
|
76
85
|
};
|
|
77
86
|
|
|
@@ -99,6 +108,9 @@ export type ValidatedPropertyValidators = {
|
|
|
99
108
|
|
|
100
109
|
// #region Property validation
|
|
101
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Thrown in `'throw'` mode when one or more properties fail validation; `information` holds all failures
|
|
113
|
+
*/
|
|
102
114
|
export class ValidationError extends Error {
|
|
103
115
|
constructor(readonly information: ValidationInformation[]) {
|
|
104
116
|
super(
|
|
@@ -112,12 +124,42 @@ export class ValidationError extends Error {
|
|
|
112
124
|
}
|
|
113
125
|
}
|
|
114
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Describes a single validation failure
|
|
129
|
+
*/
|
|
115
130
|
export type ValidationInformation = {
|
|
131
|
+
/** The key path of the property that failed */
|
|
116
132
|
key: ValidationInformationKey;
|
|
133
|
+
/** Human-readable description of the failure */
|
|
117
134
|
message: string;
|
|
135
|
+
/** The validator function that failed, if the failure was from a `$validators` entry */
|
|
118
136
|
validator?: GenericCallback;
|
|
137
|
+
/** The value that was provided */
|
|
138
|
+
value: unknown;
|
|
119
139
|
};
|
|
120
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Same shape as {@link ValidatedPropertyKey}; the key path of a failed property
|
|
143
|
+
*/
|
|
121
144
|
export type ValidationInformationKey = ValidatedPropertyKey;
|
|
122
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Options for validation
|
|
148
|
+
*/
|
|
149
|
+
export type ValidationOptions<Errors extends ReportingType> = {
|
|
150
|
+
/**
|
|
151
|
+
* How should validation failures be reported; see {@link ReportingType} _(defaults to `'none'`)_
|
|
152
|
+
*/
|
|
153
|
+
errors?: Errors;
|
|
154
|
+
/**
|
|
155
|
+
* Validate if unknown keys are present in the object? _(defaults to `false`)_
|
|
156
|
+
*/
|
|
157
|
+
strict?: boolean;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
export type ValidationOptionsExtended = {
|
|
161
|
+
reporting: ReportingInformation;
|
|
162
|
+
strict: boolean;
|
|
163
|
+
};
|
|
164
|
+
|
|
123
165
|
// #endregion
|
package/src/schematic.ts
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
2
2
|
import type {PlainObject} from '@oscarpalmer/atoms/models';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import {error} from '@oscarpalmer/atoms/result/misc';
|
|
4
|
+
import type {Result} from '@oscarpalmer/atoms/result/models';
|
|
5
|
+
import {PROPERTY_SCHEMATIC, SCHEMATIC_MESSAGE_SCHEMA_INVALID_TYPE} from './constants';
|
|
6
|
+
import {getOptions, isSchematic} from './helpers';
|
|
5
7
|
import type {Infer} from './models/infer.model';
|
|
6
8
|
import type {Schema} from './models/schema.plain.model';
|
|
7
9
|
import type {TypedSchema} from './models/schema.typed.model';
|
|
8
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
SchematicError,
|
|
12
|
+
type ValidatedProperty,
|
|
13
|
+
type ValidationInformation,
|
|
14
|
+
type ValidationOptions,
|
|
15
|
+
} from './models/validation.model';
|
|
9
16
|
import {getProperties} from './validation/property.validation';
|
|
10
17
|
import {validateObject} from './validation/value.validation';
|
|
11
18
|
|
|
@@ -23,29 +30,90 @@ export class Schematic<Model> {
|
|
|
23
30
|
});
|
|
24
31
|
|
|
25
32
|
this.#properties = properties;
|
|
33
|
+
|
|
34
|
+
schematicProperties.set(this, properties);
|
|
26
35
|
}
|
|
27
36
|
|
|
28
37
|
/**
|
|
29
38
|
* Does the value match the schema?
|
|
30
|
-
*
|
|
39
|
+
*
|
|
31
40
|
* 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.
|
|
32
41
|
* @param value Value to validate
|
|
33
|
-
* @param
|
|
42
|
+
* @param options Validation options
|
|
43
|
+
* @returns `true` if the value matches the schema, otherwise throws an error
|
|
44
|
+
*/
|
|
45
|
+
is(value: unknown, options: ValidationOptions<'throw'>): asserts value is Model;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Does the value match the schema?
|
|
49
|
+
*
|
|
50
|
+
* 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.
|
|
51
|
+
* @param value Value to validate
|
|
52
|
+
* @param errors Reporting type
|
|
34
53
|
* @returns `true` if the value matches the schema, otherwise throws an error
|
|
35
54
|
*/
|
|
36
55
|
is(value: unknown, errors: 'throw'): asserts value is Model;
|
|
37
56
|
|
|
38
57
|
/**
|
|
39
58
|
* Does the value match the schema?
|
|
40
|
-
*
|
|
59
|
+
*
|
|
60
|
+
* 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.
|
|
61
|
+
* @param value Value to validate
|
|
62
|
+
* @param options Validation options
|
|
63
|
+
* @returns `true` if the value matches the schema, otherwise `false`
|
|
64
|
+
*/
|
|
65
|
+
is(value: unknown, options: ValidationOptions<'all'>): Result<true, ValidationInformation[]>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Does the value match the schema?
|
|
69
|
+
*
|
|
70
|
+
* 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.
|
|
71
|
+
* @param value Value to validate
|
|
72
|
+
* @param errors Reporting type
|
|
73
|
+
* @returns `true` if the value matches the schema, otherwise `false`
|
|
74
|
+
*/
|
|
75
|
+
is(value: unknown, errors: 'all'): Result<true, ValidationInformation[]>;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Does the value match the schema?
|
|
79
|
+
*
|
|
80
|
+
* Will validate that the value matches the schema and return a result of `true` or all validation information for the failing property.
|
|
81
|
+
* @param value Value to validate
|
|
82
|
+
* @param options Validation options
|
|
83
|
+
* @returns `true` if the value matches the schema, otherwise `false`
|
|
84
|
+
*/
|
|
85
|
+
is(value: unknown, options: ValidationOptions<'first'>): Result<true, ValidationInformation>;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Does the value match the schema?
|
|
89
|
+
*
|
|
90
|
+
* Will validate that the value matches the schema and return a result of `true` or all validation information for the failing property.
|
|
91
|
+
* @param value Value to validate
|
|
92
|
+
* @param errors Reporting type
|
|
93
|
+
* @returns `true` if the value matches the schema, otherwise `false`
|
|
94
|
+
*/
|
|
95
|
+
is(value: unknown, errors: 'first'): Result<true, ValidationInformation>;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Does the value match the schema?
|
|
99
|
+
*
|
|
41
100
|
* Will validate that the value matches the schema and return `true` or `false`, without any validation information for validation failures.
|
|
42
101
|
* @param value Value to validate
|
|
102
|
+
* @param strict Validate if unknown keys are present in the object? _(defaults to `false`)_
|
|
43
103
|
* @returns `true` if the value matches the schema, otherwise `false`
|
|
44
104
|
*/
|
|
45
|
-
is(value: unknown): value is Model;
|
|
105
|
+
is(value: unknown, strict?: true): value is Model;
|
|
46
106
|
|
|
47
|
-
is(value: unknown,
|
|
48
|
-
|
|
107
|
+
is(value: unknown, options?: unknown): unknown {
|
|
108
|
+
const {reporting, strict} = getOptions(options);
|
|
109
|
+
|
|
110
|
+
const result = validateObject(value, this.#properties, {reporting, strict});
|
|
111
|
+
|
|
112
|
+
if (typeof result === 'boolean') {
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return error(reporting.all ? result : result[0]);
|
|
49
117
|
}
|
|
50
118
|
}
|
|
51
119
|
|
|
@@ -78,3 +146,5 @@ export function schematic<Model extends Schema>(schema: Model): Schematic<Model>
|
|
|
78
146
|
|
|
79
147
|
return new Schematic<Model>(getProperties(schema));
|
|
80
148
|
}
|
|
149
|
+
|
|
150
|
+
export const schematicProperties = new WeakMap<Schematic<unknown>, ValidatedProperty[]>();
|
|
@@ -2,6 +2,9 @@ import {isConstructor, isPlainObject} from '@oscarpalmer/atoms/is';
|
|
|
2
2
|
import type {PlainObject} from '@oscarpalmer/atoms/models';
|
|
3
3
|
import {join} from '@oscarpalmer/atoms/string';
|
|
4
4
|
import {
|
|
5
|
+
PROPERTY_REQUIRED,
|
|
6
|
+
PROPERTY_TYPE,
|
|
7
|
+
PROPERTY_VALIDATORS,
|
|
5
8
|
SCHEMATIC_MESSAGE_SCHEMA_INVALID_EMPTY,
|
|
6
9
|
SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED,
|
|
7
10
|
SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE,
|
|
@@ -10,12 +13,8 @@ import {
|
|
|
10
13
|
SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY,
|
|
11
14
|
SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE,
|
|
12
15
|
SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE,
|
|
13
|
-
PROPERTY_REQUIRED,
|
|
14
|
-
PROPERTY_TYPE,
|
|
15
|
-
PROPERTY_VALIDATORS,
|
|
16
16
|
TEMPLATE_PATTERN,
|
|
17
17
|
TYPE_ALL,
|
|
18
|
-
TYPE_OBJECT,
|
|
19
18
|
TYPE_UNDEFINED,
|
|
20
19
|
VALIDATABLE_TYPES,
|
|
21
20
|
} from '../constants';
|