@oscarpalmer/jhunal 0.23.0 → 0.25.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 +8 -5
- package/dist/constants.mjs +20 -23
- package/dist/helpers/message.helper.d.mts +11 -5
- package/dist/helpers/message.helper.mjs +31 -9
- package/dist/helpers/misc.helper.d.mts +4 -4
- package/dist/helpers/misc.helper.mjs +4 -4
- package/dist/index.d.mts +66 -78
- package/dist/index.mjs +100 -62
- package/dist/models/infer.model.d.mts +21 -21
- package/dist/models/misc.model.d.mts +3 -3
- package/dist/models/{schema.plain.model.d.mts → schematic.plain.model.d.mts} +20 -18
- package/dist/models/{schema.typed.model.d.mts → schematic.typed.model.d.mts} +10 -24
- package/dist/models/transform.model.d.mts +6 -6
- package/dist/models/validation.model.d.mts +13 -3
- package/dist/{schematic.d.mts → schema.d.mts} +18 -18
- package/dist/{schematic.mjs → schema.mjs} +12 -12
- package/dist/validator/named.handler.d.mts +1 -1
- package/dist/validator/named.handler.mjs +3 -2
- package/dist/validator/named.validator.mjs +2 -3
- package/dist/validator/object.validator.mjs +40 -22
- package/dist/validator/schematic.validator.d.mts +3 -3
- package/dist/validator/schematic.validator.mjs +4 -4
- package/package.json +1 -1
- package/src/constants.ts +24 -28
- package/src/helpers/message.helper.ts +74 -9
- package/src/helpers/misc.helper.ts +9 -10
- package/src/index.ts +4 -4
- package/src/models/infer.model.ts +26 -28
- package/src/models/misc.model.ts +3 -3
- package/src/models/{schema.plain.model.ts → schematic.plain.model.ts} +22 -20
- package/src/models/{schema.typed.model.ts → schematic.typed.model.ts} +10 -28
- package/src/models/transform.model.ts +6 -6
- package/src/models/validation.model.ts +14 -2
- package/src/{schematic.ts → schema.ts} +23 -23
- package/src/validator/named.handler.ts +16 -1
- package/src/validator/named.validator.ts +3 -4
- package/src/validator/object.validator.ts +81 -55
- package/src/validator/schematic.validator.ts +3 -3
- /package/dist/models/{schema.plain.model.mjs → schematic.plain.model.mjs} +0 -0
- /package/dist/models/{schema.typed.model.mjs → schematic.typed.model.mjs} +0 -0
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
import {isConstructor, isPlainObject} from '@oscarpalmer/atoms/is';
|
|
2
|
-
import type {Constructor
|
|
2
|
+
import type {Constructor} from '@oscarpalmer/atoms/models';
|
|
3
3
|
import {
|
|
4
4
|
MESSAGE_CONSTRUCTOR,
|
|
5
|
-
|
|
5
|
+
PROPERTY_SCHEMA,
|
|
6
6
|
REPORTING_ALL,
|
|
7
7
|
REPORTING_FIRST,
|
|
8
8
|
REPORTING_NONE,
|
|
9
9
|
REPORTING_THROW,
|
|
10
10
|
REPORTING_TYPES,
|
|
11
|
-
TYPE_OBJECT,
|
|
12
11
|
} from '../constants';
|
|
13
12
|
import type {
|
|
14
13
|
ReportingInformation,
|
|
15
14
|
ReportingType,
|
|
16
15
|
ValidatorParameters,
|
|
17
16
|
} from '../models/validation.model';
|
|
18
|
-
import type {
|
|
17
|
+
import type {Schema} from '../schema';
|
|
19
18
|
|
|
20
19
|
export function getParameters(input?: unknown): ValidatorParameters {
|
|
21
20
|
if (typeof input === 'boolean') {
|
|
22
21
|
return {
|
|
23
22
|
clone: true,
|
|
24
23
|
output: {},
|
|
25
|
-
reporting: getReporting(
|
|
24
|
+
reporting: getReporting(),
|
|
26
25
|
strict: input,
|
|
27
26
|
};
|
|
28
27
|
}
|
|
@@ -46,7 +45,7 @@ export function getParameters(input?: unknown): ValidatorParameters {
|
|
|
46
45
|
};
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
export function getReporting(value
|
|
48
|
+
export function getReporting(value?: unknown): ReportingInformation {
|
|
50
49
|
const type = REPORTING_TYPES.has(value as ReportingType)
|
|
51
50
|
? (value as ReportingType)
|
|
52
51
|
: REPORTING_NONE;
|
|
@@ -83,11 +82,11 @@ export function instanceOf<Instance>(
|
|
|
83
82
|
* @param value Value to check
|
|
84
83
|
* @returns `true` if the value is a schematic, `false` otherwise
|
|
85
84
|
*/
|
|
86
|
-
export function
|
|
85
|
+
export function isSchema(value: unknown): value is Schema<never> {
|
|
87
86
|
return (
|
|
88
|
-
typeof value ===
|
|
87
|
+
typeof value === 'object' &&
|
|
89
88
|
value !== null &&
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
PROPERTY_SCHEMA in value &&
|
|
90
|
+
value[PROPERTY_SCHEMA] === true
|
|
92
91
|
);
|
|
93
92
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export {instanceOf,
|
|
2
|
-
export type {
|
|
3
|
-
export type {
|
|
1
|
+
export {instanceOf, isSchema} from './helpers/misc.helper';
|
|
2
|
+
export type {Schematic} from './models/schematic.plain.model';
|
|
3
|
+
export type {TypedSchematic} from './models/schematic.typed.model';
|
|
4
4
|
export {
|
|
5
5
|
SchematicError,
|
|
6
6
|
ValidationError,
|
|
7
7
|
type GetOptions,
|
|
8
8
|
type IsOptions,
|
|
9
9
|
} from './models/validation.model';
|
|
10
|
-
export {
|
|
10
|
+
export {schema, type Schema} from './schema';
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import type {Constructor, Simplify} from '@oscarpalmer/atoms/models';
|
|
2
|
-
import type {
|
|
2
|
+
import type {Schema} from '../schema';
|
|
3
3
|
import type {IsOptionalProperty, ValueName, Values} from './misc.model';
|
|
4
|
-
import type {
|
|
4
|
+
import type {PlainSchematic, Schematic, SchematicProperty} from './schematic.plain.model';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Infers the TypeScript type from a {@link
|
|
7
|
+
* Infers the TypeScript type from a {@link Schematic} definition
|
|
8
8
|
*
|
|
9
|
-
* @template Model
|
|
9
|
+
* @template Model Schematic to infer types from
|
|
10
10
|
*
|
|
11
11
|
* @example
|
|
12
12
|
* ```ts
|
|
13
|
-
* const
|
|
13
|
+
* const userSchematic = {
|
|
14
14
|
* name: 'string',
|
|
15
15
|
* age: 'number',
|
|
16
16
|
* address: { $required: false, $type: 'string' },
|
|
17
|
-
* } satisfies
|
|
17
|
+
* } satisfies Schematic;
|
|
18
18
|
*
|
|
19
|
-
* type User = Infer<typeof
|
|
19
|
+
* type User = Infer<typeof userSchematic>;
|
|
20
20
|
* // { name: string; age: number; address?: string }
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
|
-
export type Infer<Model extends
|
|
23
|
+
export type Infer<Model extends Schematic> = Simplify<
|
|
24
24
|
{
|
|
25
25
|
[Key in InferRequiredKeys<Model>]: InferSchemaEntry<Model[Key]>;
|
|
26
26
|
} & {
|
|
@@ -29,16 +29,16 @@ export type Infer<Model extends Schema> = Simplify<
|
|
|
29
29
|
>;
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
|
-
* Extracts keys from a {@link
|
|
32
|
+
* Extracts keys from a {@link Schematic} whose entries are optional _(i.e., `$required` is `false`)_
|
|
33
33
|
*
|
|
34
|
-
* @template Model - {@link
|
|
34
|
+
* @template Model - {@link Schematic} to extract optional keys from
|
|
35
35
|
*/
|
|
36
|
-
export type InferOptionalKeys<Model extends
|
|
36
|
+
export type InferOptionalKeys<Model extends Schematic> = keyof {
|
|
37
37
|
[Key in keyof Model as IsOptionalProperty<Model[Key]> extends true ? Key : never]: never;
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
* Infers the TypeScript type from a {@link
|
|
41
|
+
* Infers the TypeScript type from a {@link SchematicProperty}'s `$type` field
|
|
42
42
|
*
|
|
43
43
|
* @template Value `$type` value _(single or array)_
|
|
44
44
|
*/
|
|
@@ -49,34 +49,34 @@ export type InferPropertyType<Value> = Value extends (infer Item)[]
|
|
|
49
49
|
/**
|
|
50
50
|
* Maps a single `$type` definition to its TypeScript equivalent
|
|
51
51
|
*
|
|
52
|
-
* Resolves, in order: {@link Constructor}
|
|
52
|
+
* Resolves, in order: {@link Constructor}s, {@link Schema} instances, {@link ValueName} values, and nested {@link PlainSchematic} objects
|
|
53
53
|
*
|
|
54
54
|
* @template Value single type definition
|
|
55
55
|
*/
|
|
56
56
|
export type InferPropertyValue<Value> =
|
|
57
57
|
Value extends Constructor<infer Instance>
|
|
58
58
|
? Instance
|
|
59
|
-
: Value extends
|
|
59
|
+
: Value extends Schema<infer Model>
|
|
60
60
|
? Model
|
|
61
61
|
: Value extends ValueName
|
|
62
62
|
? Values[Value & ValueName]
|
|
63
|
-
: Value extends
|
|
63
|
+
: Value extends PlainSchematic
|
|
64
64
|
? Infer<Value>
|
|
65
65
|
: never;
|
|
66
66
|
|
|
67
67
|
/**
|
|
68
|
-
* Extracts keys from a {@link
|
|
68
|
+
* Extracts keys from a {@link Schematic} whose entries are required _(i.e., `$required` is not `false`)_
|
|
69
69
|
*
|
|
70
|
-
* @template Model
|
|
70
|
+
* @template Model Schematic to extract required keys from
|
|
71
71
|
*/
|
|
72
|
-
export type InferRequiredKeys<Model extends
|
|
72
|
+
export type InferRequiredKeys<Model extends Schematic> = keyof {
|
|
73
73
|
[Key in keyof Model as IsOptionalProperty<Model[Key]> extends true ? never : Key]: never;
|
|
74
74
|
};
|
|
75
75
|
|
|
76
76
|
/**
|
|
77
|
-
* Infers the TypeScript type from a top-level {@link
|
|
77
|
+
* Infers the TypeScript type from a top-level {@link Schematic} entry
|
|
78
78
|
*
|
|
79
|
-
* @template Value
|
|
79
|
+
* @template Value Schematic entry value _(single or array)_
|
|
80
80
|
*/
|
|
81
81
|
export type InferSchemaEntry<Value> = Value extends (infer Item)[]
|
|
82
82
|
? InferSchemaEntryValue<Item>
|
|
@@ -85,21 +85,19 @@ export type InferSchemaEntry<Value> = Value extends (infer Item)[]
|
|
|
85
85
|
/**
|
|
86
86
|
* Maps a single top-level schema entry to its TypeScript type
|
|
87
87
|
*
|
|
88
|
-
* Resolves, in order: {@link Constructor}
|
|
88
|
+
* Resolves, in order: {@link Constructor}s, {@link Schema} instances, {@link SchemaProperty} objects, {@link PlainSchematic} objects, and {@link ValueName} values
|
|
89
89
|
*
|
|
90
90
|
* @template Value single schema entry
|
|
91
91
|
*/
|
|
92
92
|
export type InferSchemaEntryValue<Value> =
|
|
93
93
|
Value extends Constructor<infer Instance>
|
|
94
94
|
? Instance
|
|
95
|
-
: Value extends
|
|
95
|
+
: Value extends Schema<infer Model>
|
|
96
96
|
? Model
|
|
97
|
-
: Value extends
|
|
97
|
+
: Value extends SchematicProperty
|
|
98
98
|
? InferPropertyType<Value['$type']>
|
|
99
|
-
: Value extends
|
|
100
|
-
? Infer<Value &
|
|
99
|
+
: Value extends PlainSchematic
|
|
100
|
+
? Infer<Value & Schematic>
|
|
101
101
|
: Value extends ValueName
|
|
102
102
|
? Values[Value & ValueName]
|
|
103
|
-
:
|
|
104
|
-
? Infer<Value>
|
|
105
|
-
: never;
|
|
103
|
+
: never;
|
package/src/models/misc.model.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {SchematicProperty} from './schematic.plain.model';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Removes duplicate types from a tuple, preserving first occurrence order
|
|
@@ -43,11 +43,11 @@ 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
|
|
46
|
+
* Returns `true` if the entry is a {@link SchematicProperty} with `$required` set to `false`; otherwise returns `false`
|
|
47
47
|
*
|
|
48
48
|
* @template Value Schema entry to check
|
|
49
49
|
*/
|
|
50
|
-
export type IsOptionalProperty<Value> = Value extends
|
|
50
|
+
export type IsOptionalProperty<Value> = Value extends SchematicProperty
|
|
51
51
|
? Value['$required'] extends false
|
|
52
52
|
? true
|
|
53
53
|
: false
|
|
@@ -1,42 +1,43 @@
|
|
|
1
1
|
import type {Constructor} from '@oscarpalmer/atoms/models';
|
|
2
|
-
import type {
|
|
2
|
+
import type {Schema} from '../schema';
|
|
3
3
|
import type {ExtractValueNames, ValueName, Values} from './misc.model';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* A generic
|
|
6
|
+
* A generic schematic allowing nested schematics, {@link SchematicEntry} values, or arrays of {@link SchematicEntry} as values
|
|
7
7
|
*/
|
|
8
|
-
export type
|
|
9
|
-
[key: string]:
|
|
8
|
+
export type PlainSchematic = {
|
|
9
|
+
[key: string]: PlainSchematic | SchematicEntry | SchematicEntry[] | undefined;
|
|
10
10
|
} & {
|
|
11
|
+
$default?: never;
|
|
11
12
|
$required?: never;
|
|
12
13
|
$type?: never;
|
|
13
14
|
$validators?: never;
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
|
-
* A
|
|
18
|
+
* A schematic for validating objects
|
|
18
19
|
*
|
|
19
20
|
* @example
|
|
20
21
|
* ```ts
|
|
21
|
-
* const
|
|
22
|
+
* const schematic = {
|
|
22
23
|
* name: 'string',
|
|
23
24
|
* age: 'number',
|
|
24
25
|
* tags: ['string', 'number'],
|
|
25
|
-
* };
|
|
26
|
+
* } satisfies Schematic;
|
|
26
27
|
* ```
|
|
27
28
|
*/
|
|
28
|
-
export type
|
|
29
|
+
export type Schematic = PlainSchematic;
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
|
-
* A union of all valid types for a single
|
|
32
|
+
* A union of all valid types for a single schematic entry
|
|
32
33
|
*
|
|
33
|
-
* Can be a {@link Constructor}, {@link
|
|
34
|
+
* Can be a {@link Constructor}, {@link PlainSchematic}, {@link SchematicProperty}, {@link Schema}, {@link ValueName}, or a custom validator function
|
|
34
35
|
*/
|
|
35
|
-
export type
|
|
36
|
+
export type SchematicEntry =
|
|
36
37
|
| Constructor
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
38
|
+
| PlainSchematic
|
|
39
|
+
| Schema<unknown>
|
|
40
|
+
| SchematicProperty
|
|
40
41
|
| ValueName
|
|
41
42
|
| ((value: unknown) => boolean);
|
|
42
43
|
|
|
@@ -45,7 +46,7 @@ export type SchemaEntry =
|
|
|
45
46
|
*
|
|
46
47
|
* @example
|
|
47
48
|
* ```ts
|
|
48
|
-
* const prop:
|
|
49
|
+
* const prop: SchematicProperty = {
|
|
49
50
|
* $required: false,
|
|
50
51
|
* $type: ['string', 'number'],
|
|
51
52
|
* $validators: {
|
|
@@ -55,7 +56,8 @@ export type SchemaEntry =
|
|
|
55
56
|
* };
|
|
56
57
|
* ```
|
|
57
58
|
*/
|
|
58
|
-
export type
|
|
59
|
+
export type SchematicProperty = {
|
|
60
|
+
$default?: unknown;
|
|
59
61
|
/**
|
|
60
62
|
* Whether the property is required _(defaults to `true`)_
|
|
61
63
|
*/
|
|
@@ -71,14 +73,14 @@ export type SchemaProperty = {
|
|
|
71
73
|
};
|
|
72
74
|
|
|
73
75
|
/**
|
|
74
|
-
* A union of valid types for a {@link
|
|
76
|
+
* A union of valid types for a {@link SchematicProperty}'s `$type` field
|
|
75
77
|
*
|
|
76
|
-
* Can be a {@link Constructor}, {@link
|
|
78
|
+
* Can be a {@link Constructor}, {@link PlainSchematic}, {@link Schema}, {@link ValueName} string, or a custom validator function
|
|
77
79
|
*/
|
|
78
80
|
export type SchemaPropertyType =
|
|
79
81
|
| Constructor
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
+
| PlainSchematic
|
|
83
|
+
| Schema<unknown>
|
|
82
84
|
| ValueName
|
|
83
85
|
| ((value: unknown) => boolean);
|
|
84
86
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type {PlainObject, Simplify} from '@oscarpalmer/atoms/models';
|
|
2
|
-
import type {
|
|
2
|
+
import type {Schema} from '../schema';
|
|
3
3
|
import type {OptionalKeys, RequiredKeys} from './misc.model';
|
|
4
|
-
import type {PropertyValidators} from './
|
|
4
|
+
import type {PropertyValidators} from './schematic.plain.model';
|
|
5
5
|
import type {ToSchemaPropertyType, ToSchemaType} from './transform.model';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* A typed optional property definition generated by {@link
|
|
8
|
+
* A typed optional property definition generated by {@link TypedSchematic} for optional keys, with `$required` set to `false` and excludes `undefined` from the type
|
|
9
9
|
*
|
|
10
10
|
* @template Value Property's type _(including `undefined`)_
|
|
11
11
|
*
|
|
@@ -17,13 +17,14 @@ import type {ToSchemaPropertyType, ToSchemaType} from './transform.model';
|
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
19
|
export type TypedPropertyOptional<Value> = {
|
|
20
|
+
$default?: never;
|
|
20
21
|
$required: false;
|
|
21
22
|
$type: ToSchemaPropertyType<Exclude<Value, undefined>>;
|
|
22
23
|
$validators?: PropertyValidators<ToSchemaPropertyType<Exclude<Value, undefined>>>;
|
|
23
24
|
};
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
|
-
* A typed required property definition generated by {@link
|
|
27
|
+
* A typed required property definition generated by {@link TypedSchematic} for required keys, with `$required` defaulting to `true`
|
|
27
28
|
*
|
|
28
29
|
* @template Value Property's type
|
|
29
30
|
*
|
|
@@ -35,6 +36,7 @@ export type TypedPropertyOptional<Value> = {
|
|
|
35
36
|
* ```
|
|
36
37
|
*/
|
|
37
38
|
export type TypedPropertyRequired<Value> = {
|
|
39
|
+
$default?: unknown;
|
|
38
40
|
$required?: true;
|
|
39
41
|
$type: ToSchemaPropertyType<Value>;
|
|
40
42
|
$validators?: PropertyValidators<ToSchemaPropertyType<Value>>;
|
|
@@ -43,7 +45,7 @@ export type TypedPropertyRequired<Value> = {
|
|
|
43
45
|
/**
|
|
44
46
|
* Creates a schema type constrained to match a TypeScript type
|
|
45
47
|
*
|
|
46
|
-
* Required keys map to {@link ToSchemaType} or {@link TypedPropertyRequired}; plain object values may also use {@link
|
|
48
|
+
* Required keys map to {@link ToSchemaType} or {@link TypedPropertyRequired}; plain object values may also use {@link Schema}
|
|
47
49
|
*
|
|
48
50
|
* @template Model Object type to generate a schema for
|
|
49
51
|
*
|
|
@@ -58,34 +60,14 @@ export type TypedPropertyRequired<Value> = {
|
|
|
58
60
|
* };
|
|
59
61
|
* ```
|
|
60
62
|
*/
|
|
61
|
-
export type
|
|
63
|
+
export type TypedSchematic<Model extends PlainObject> = Simplify<
|
|
62
64
|
{
|
|
63
65
|
[Key in RequiredKeys<Model>]: Model[Key] extends PlainObject
|
|
64
|
-
?
|
|
66
|
+
? Schema<Model[Key]>
|
|
65
67
|
: ToSchemaType<Model[Key]> | TypedPropertyRequired<Model[Key]>;
|
|
66
68
|
} & {
|
|
67
69
|
[Key in OptionalKeys<Model>]: Exclude<Model[Key], undefined> extends PlainObject
|
|
68
|
-
?
|
|
69
|
-
| TypedSchemaOptional<Exclude<Model[Key], undefined>>
|
|
70
|
-
| Schematic<Exclude<Model[Key], undefined>>
|
|
70
|
+
? Schema<Exclude<Model[Key], undefined>>
|
|
71
71
|
: TypedPropertyOptional<Model[Key]>;
|
|
72
72
|
}
|
|
73
73
|
>;
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* A {@link TypedSchema} variant for optional nested objects, with `$required` fixed to `false`
|
|
77
|
-
*
|
|
78
|
-
* @template Model Nested object type
|
|
79
|
-
*/
|
|
80
|
-
type TypedSchemaOptional<Model extends PlainObject> = {
|
|
81
|
-
$required: false;
|
|
82
|
-
} & TypedSchema<Model>;
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* A {@link TypedSchema} variant for required nested objects, with `$required` defaulting to `true`
|
|
86
|
-
*
|
|
87
|
-
* @template Model Nested object type
|
|
88
|
-
*/
|
|
89
|
-
type TypedSchemaRequired<Model extends PlainObject> = {
|
|
90
|
-
$required?: true;
|
|
91
|
-
} & TypedSchema<Model>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {PlainObject} from '@oscarpalmer/atoms/models';
|
|
2
|
-
import type {
|
|
2
|
+
import type {Schema} from '../schema';
|
|
3
3
|
import type {DeduplicateTuple, UnionToTuple, UnwrapSingle, Values} from './misc.model';
|
|
4
|
-
import type {
|
|
4
|
+
import type {TypedSchematic} from './schematic.typed.model';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Maps each element of a tuple through {@link ToValueType}
|
|
@@ -36,12 +36,12 @@ export type ToSchemaPropertyType<Value> = UnwrapSingle<
|
|
|
36
36
|
/**
|
|
37
37
|
* Converts a single type to its schema property equivalent
|
|
38
38
|
*
|
|
39
|
-
* Plain objects become {@link
|
|
39
|
+
* Plain objects become {@link TypedSchematic}; primitives go through {@link ToValueType}
|
|
40
40
|
*
|
|
41
41
|
* @template Value Type to convert
|
|
42
42
|
*/
|
|
43
43
|
export type ToSchemaPropertyTypeEach<Value> = Value extends PlainObject
|
|
44
|
-
?
|
|
44
|
+
? TypedSchematic<Value>
|
|
45
45
|
: ToValueType<Value>;
|
|
46
46
|
|
|
47
47
|
/**
|
|
@@ -56,7 +56,7 @@ export type ToSchemaType<Value> = UnwrapSingle<
|
|
|
56
56
|
/**
|
|
57
57
|
* Maps a type to its {@link ValueName} string equivalent
|
|
58
58
|
*
|
|
59
|
-
* Resolves {@link
|
|
59
|
+
* Resolves {@link Schema} 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
|
|
60
60
|
*
|
|
61
61
|
* @template Value Type to map
|
|
62
62
|
*
|
|
@@ -68,7 +68,7 @@ export type ToSchemaType<Value> = UnwrapSingle<
|
|
|
68
68
|
* ```
|
|
69
69
|
*/
|
|
70
70
|
export type ToValueType<Value> =
|
|
71
|
-
Value extends
|
|
71
|
+
Value extends Schema<any>
|
|
72
72
|
? Value
|
|
73
73
|
: {
|
|
74
74
|
[Key in keyof Omit<Values, 'object'>]: Value extends Values[Key] ? Key : never;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {GenericCallback, PlainObject} from '@oscarpalmer/atoms/models';
|
|
2
2
|
import {join} from '@oscarpalmer/atoms/string';
|
|
3
3
|
import {NAME_ERROR_SCHEMATIC, NAME_ERROR_VALIDATION} from '../constants';
|
|
4
|
-
import type {
|
|
4
|
+
import type {Schema} from '../schema';
|
|
5
5
|
import type {ValueName} from './misc.model';
|
|
6
6
|
|
|
7
7
|
// #region Named validation
|
|
@@ -127,6 +127,18 @@ export type Validator = (
|
|
|
127
127
|
get: boolean,
|
|
128
128
|
) => true | ValidationInformation[];
|
|
129
129
|
|
|
130
|
+
export type ValidatorDefaults = {
|
|
131
|
+
value: unknown;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export type ValidatorItem = {
|
|
135
|
+
defaults: ValidatorDefaults | undefined;
|
|
136
|
+
key: ValidationInformationKey;
|
|
137
|
+
required: boolean;
|
|
138
|
+
types: ValidatorType[];
|
|
139
|
+
validator: Validator;
|
|
140
|
+
};
|
|
141
|
+
|
|
130
142
|
export type ValidatorParameters = {
|
|
131
143
|
clone: boolean;
|
|
132
144
|
information?: ValidationInformation[];
|
|
@@ -135,6 +147,6 @@ export type ValidatorParameters = {
|
|
|
135
147
|
strict: boolean;
|
|
136
148
|
};
|
|
137
149
|
|
|
138
|
-
export type ValidatorType = Function | PlainObject |
|
|
150
|
+
export type ValidatorType = Function | PlainObject | Schema<unknown> | ValueName;
|
|
139
151
|
|
|
140
152
|
// #endregion
|
|
@@ -2,11 +2,11 @@ import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
|
2
2
|
import type {PlainObject} from '@oscarpalmer/atoms/models';
|
|
3
3
|
import {error, ok} from '@oscarpalmer/atoms/result/misc';
|
|
4
4
|
import type {Result} from '@oscarpalmer/atoms/result/models';
|
|
5
|
-
import {
|
|
6
|
-
import {getParameters,
|
|
5
|
+
import {PROPERTY_SCHEMA, SCHEMATIC_MESSAGE_SCHEMA_INVALID_TYPE} from './constants';
|
|
6
|
+
import {getParameters, isSchema} from './helpers/misc.helper';
|
|
7
7
|
import type {Infer} from './models/infer.model';
|
|
8
|
-
import type {
|
|
9
|
-
import type {
|
|
8
|
+
import type {Schematic} from './models/schematic.plain.model';
|
|
9
|
+
import type {TypedSchematic} from './models/schematic.typed.model';
|
|
10
10
|
import {
|
|
11
11
|
SchematicError,
|
|
12
12
|
type GetOptions,
|
|
@@ -17,21 +17,21 @@ import {
|
|
|
17
17
|
import {getObjectValidator} from './validator/object.validator';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* A
|
|
20
|
+
* A schema for validating objects
|
|
21
21
|
*/
|
|
22
|
-
export class
|
|
23
|
-
declare private readonly $
|
|
22
|
+
export class Schema<Model> {
|
|
23
|
+
declare private readonly $schema: true;
|
|
24
24
|
|
|
25
25
|
#validator: Validator;
|
|
26
26
|
|
|
27
27
|
constructor(validator: Validator) {
|
|
28
|
-
Object.defineProperty(this,
|
|
28
|
+
Object.defineProperty(this, PROPERTY_SCHEMA, {
|
|
29
29
|
value: true,
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
this.#validator = validator;
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
schemaValidators.set(this, validator);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
/**
|
|
@@ -230,25 +230,25 @@ export class Schematic<Model> {
|
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
/**
|
|
233
|
-
* Create a
|
|
233
|
+
* Create a schema from a schematic
|
|
234
234
|
* @template Model Schema type
|
|
235
|
-
* @param schema
|
|
236
|
-
* @throws Throws {@link SchematicError} if the
|
|
237
|
-
* @returns A
|
|
235
|
+
* @param schema Schematic to create the schema from
|
|
236
|
+
* @throws Throws {@link SchematicError} if the schematic can not be converted into a schema
|
|
237
|
+
* @returns A schema for the given schematic
|
|
238
238
|
*/
|
|
239
|
-
export function
|
|
239
|
+
export function schema<Model extends Schematic>(schema: Model): Schema<Infer<Model>>;
|
|
240
240
|
|
|
241
241
|
/**
|
|
242
|
-
* Create a
|
|
242
|
+
* Create a schema from a typed schematic
|
|
243
243
|
* @template Model Existing type
|
|
244
|
-
* @param schema Typed
|
|
245
|
-
* @throws Throws {@link SchematicError} if the
|
|
246
|
-
* @returns A
|
|
244
|
+
* @param schema Typed schematic to create the schema from
|
|
245
|
+
* @throws Throws {@link SchematicError} if the schematic can not be converted into a schema
|
|
246
|
+
* @returns A schema for the given typed schematic
|
|
247
247
|
*/
|
|
248
|
-
export function
|
|
248
|
+
export function schema<Model extends PlainObject>(schema: TypedSchematic<Model>): Schema<Model>;
|
|
249
249
|
|
|
250
|
-
export function
|
|
251
|
-
if (
|
|
250
|
+
export function schema<Model extends Schematic>(schema: Model): Schema<Model> {
|
|
251
|
+
if (isSchema(schema)) {
|
|
252
252
|
return schema;
|
|
253
253
|
}
|
|
254
254
|
|
|
@@ -256,7 +256,7 @@ export function schematic<Model extends Schema>(schema: Model): Schematic<Model>
|
|
|
256
256
|
throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_TYPE);
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
-
return new
|
|
259
|
+
return new Schema<Model>(getObjectValidator(schema));
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
-
export const
|
|
262
|
+
export const schemaValidators = new WeakMap<Schema<unknown>, Validator>();
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
2
2
|
import {
|
|
3
|
+
PROPERTY_VALIDATORS,
|
|
4
|
+
SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED,
|
|
3
5
|
SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY,
|
|
4
6
|
SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE,
|
|
5
7
|
SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE,
|
|
@@ -9,13 +11,26 @@ import {
|
|
|
9
11
|
import type {ValueName} from '../models/misc.model';
|
|
10
12
|
import type {NamedValidatorHandlers} from '../models/validation.model';
|
|
11
13
|
|
|
12
|
-
export function getNamedHandlers(
|
|
14
|
+
export function getNamedHandlers(
|
|
15
|
+
original: unknown,
|
|
16
|
+
prefix: string,
|
|
17
|
+
allowed: boolean,
|
|
18
|
+
): NamedValidatorHandlers {
|
|
13
19
|
const handlers: NamedValidatorHandlers = {};
|
|
14
20
|
|
|
15
21
|
if (original == null) {
|
|
16
22
|
return handlers;
|
|
17
23
|
}
|
|
18
24
|
|
|
25
|
+
if (!allowed) {
|
|
26
|
+
throw new TypeError(
|
|
27
|
+
SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED.replace(
|
|
28
|
+
TEMPLATE_PATTERN,
|
|
29
|
+
prefix,
|
|
30
|
+
).replace(TEMPLATE_PATTERN, PROPERTY_VALIDATORS),
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
19
34
|
if (!isPlainObject(original)) {
|
|
20
35
|
throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE);
|
|
21
36
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {getInvalidValidatorMessage} from '../helpers/message.helper';
|
|
1
|
+
import {getInputPropertyValidatorMessage} from '../helpers/message.helper';
|
|
3
2
|
import type {ValueName} from '../models/misc.model';
|
|
4
3
|
import type {
|
|
5
4
|
NamedValidatorHandlers,
|
|
@@ -34,7 +33,7 @@ export function getNamedValidator(
|
|
|
34
33
|
const information: ValidationInformation = {
|
|
35
34
|
key,
|
|
36
35
|
validator,
|
|
37
|
-
message:
|
|
36
|
+
message: getInputPropertyValidatorMessage(key.full, name, index, length),
|
|
38
37
|
value: input,
|
|
39
38
|
};
|
|
40
39
|
|
|
@@ -55,7 +54,7 @@ const namedValidators: NamedValidators = {
|
|
|
55
54
|
function: value => typeof value === 'function',
|
|
56
55
|
null: value => value === null,
|
|
57
56
|
number: value => typeof value === 'number',
|
|
58
|
-
object: value => typeof value ===
|
|
57
|
+
object: value => typeof value === 'object' && value !== null,
|
|
59
58
|
string: value => typeof value === 'string',
|
|
60
59
|
symbol: value => typeof value === 'symbol',
|
|
61
60
|
undefined: value => value === undefined,
|