@oscarpalmer/jhunal 0.24.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 +4 -4
- package/dist/constants.mjs +4 -4
- package/dist/helpers/misc.helper.d.mts +3 -3
- package/dist/helpers/misc.helper.mjs +3 -3
- package/dist/index.d.mts +62 -62
- package/dist/index.mjs +17 -17
- 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} +18 -18
- package/dist/models/{schema.typed.model.d.mts → schematic.typed.model.d.mts} +8 -8
- package/dist/models/transform.model.d.mts +6 -6
- package/dist/models/validation.model.d.mts +2 -2
- package/dist/{schematic.d.mts → schema.d.mts} +18 -18
- package/dist/{schematic.mjs → schema.mjs} +12 -12
- package/dist/validator/object.validator.mjs +4 -4
- 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 +3 -3
- package/src/helpers/misc.helper.ts +5 -5
- 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} +20 -20
- package/src/models/{schema.typed.model.ts → schematic.typed.model.ts} +8 -8
- package/src/models/transform.model.ts +6 -6
- package/src/models/validation.model.ts +2 -2
- package/src/{schematic.ts → schema.ts} +23 -23
- package/src/validator/object.validator.ts +4 -4
- 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,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Schema } from "../schema.mjs";
|
|
2
2
|
import { ExtractValueNames, ValueName, Values } from "./misc.model.mjs";
|
|
3
3
|
import { Constructor } from "@oscarpalmer/atoms/models";
|
|
4
4
|
|
|
5
|
-
//#region src/models/
|
|
5
|
+
//#region src/models/schematic.plain.model.d.ts
|
|
6
6
|
/**
|
|
7
|
-
* A generic
|
|
7
|
+
* A generic schematic allowing nested schematics, {@link SchematicEntry} values, or arrays of {@link SchematicEntry} as values
|
|
8
8
|
*/
|
|
9
|
-
type
|
|
10
|
-
[key: string]:
|
|
9
|
+
type PlainSchematic = {
|
|
10
|
+
[key: string]: PlainSchematic | SchematicEntry | SchematicEntry[] | undefined;
|
|
11
11
|
} & {
|
|
12
12
|
$default?: never;
|
|
13
13
|
$required?: never;
|
|
@@ -15,30 +15,30 @@ type PlainSchema = {
|
|
|
15
15
|
$validators?: never;
|
|
16
16
|
};
|
|
17
17
|
/**
|
|
18
|
-
* A
|
|
18
|
+
* A schematic for validating objects
|
|
19
19
|
*
|
|
20
20
|
* @example
|
|
21
21
|
* ```ts
|
|
22
|
-
* const
|
|
22
|
+
* const schematic = {
|
|
23
23
|
* name: 'string',
|
|
24
24
|
* age: 'number',
|
|
25
25
|
* tags: ['string', 'number'],
|
|
26
|
-
* };
|
|
26
|
+
* } satisfies Schematic;
|
|
27
27
|
* ```
|
|
28
28
|
*/
|
|
29
|
-
type
|
|
29
|
+
type Schematic = PlainSchematic;
|
|
30
30
|
/**
|
|
31
|
-
* A union of all valid types for a single
|
|
31
|
+
* A union of all valid types for a single schematic entry
|
|
32
32
|
*
|
|
33
|
-
* Can be a {@link Constructor}, {@link
|
|
33
|
+
* Can be a {@link Constructor}, {@link PlainSchematic}, {@link SchematicProperty}, {@link Schema}, {@link ValueName}, or a custom validator function
|
|
34
34
|
*/
|
|
35
|
-
type
|
|
35
|
+
type SchematicEntry = Constructor | PlainSchematic | Schema<unknown> | SchematicProperty | ValueName | ((value: unknown) => boolean);
|
|
36
36
|
/**
|
|
37
37
|
* A property definition with explicit type(s), an optional requirement flag, and optional validators
|
|
38
38
|
*
|
|
39
39
|
* @example
|
|
40
40
|
* ```ts
|
|
41
|
-
* const prop:
|
|
41
|
+
* const prop: SchematicProperty = {
|
|
42
42
|
* $required: false,
|
|
43
43
|
* $type: ['string', 'number'],
|
|
44
44
|
* $validators: {
|
|
@@ -48,7 +48,7 @@ type SchemaEntry = Constructor | PlainSchema | SchemaProperty | Schematic<unknow
|
|
|
48
48
|
* };
|
|
49
49
|
* ```
|
|
50
50
|
*/
|
|
51
|
-
type
|
|
51
|
+
type SchematicProperty = {
|
|
52
52
|
$default?: unknown;
|
|
53
53
|
/**
|
|
54
54
|
* Whether the property is required _(defaults to `true`)_
|
|
@@ -64,11 +64,11 @@ type SchemaProperty = {
|
|
|
64
64
|
$validators?: PropertyValidators<SchemaPropertyType | SchemaPropertyType[]>;
|
|
65
65
|
};
|
|
66
66
|
/**
|
|
67
|
-
* A union of valid types for a {@link
|
|
67
|
+
* A union of valid types for a {@link SchematicProperty}'s `$type` field
|
|
68
68
|
*
|
|
69
|
-
* Can be a {@link Constructor}, {@link
|
|
69
|
+
* Can be a {@link Constructor}, {@link PlainSchematic}, {@link Schema}, {@link ValueName} string, or a custom validator function
|
|
70
70
|
*/
|
|
71
|
-
type SchemaPropertyType = Constructor |
|
|
71
|
+
type SchemaPropertyType = Constructor | PlainSchematic | Schema<unknown> | ValueName | ((value: unknown) => boolean);
|
|
72
72
|
/**
|
|
73
73
|
* A map of optional validator functions keyed by {@link ValueName}, used to add custom validation to {@link SchemaProperty} definitions
|
|
74
74
|
*
|
|
@@ -85,4 +85,4 @@ type SchemaPropertyType = Constructor | PlainSchema | Schematic<unknown> | Value
|
|
|
85
85
|
*/
|
|
86
86
|
type PropertyValidators<Value> = { [Key in ExtractValueNames<Value>]?: ((value: Values[Key]) => boolean) | Array<(value: Values[Key]) => boolean> };
|
|
87
87
|
//#endregion
|
|
88
|
-
export {
|
|
88
|
+
export { PlainSchematic, PropertyValidators, SchemaPropertyType, Schematic, SchematicEntry, SchematicProperty };
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { ToSchemaPropertyType, ToSchemaType } from "./transform.model.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { PropertyValidators } from "./
|
|
2
|
+
import { Schema } from "../schema.mjs";
|
|
3
|
+
import { PropertyValidators } from "./schematic.plain.model.mjs";
|
|
4
4
|
import { OptionalKeys, RequiredKeys } from "./misc.model.mjs";
|
|
5
5
|
import { PlainObject, Simplify } from "@oscarpalmer/atoms/models";
|
|
6
6
|
|
|
7
|
-
//#region src/models/
|
|
7
|
+
//#region src/models/schematic.typed.model.d.ts
|
|
8
8
|
/**
|
|
9
|
-
* A typed optional property definition generated by {@link
|
|
9
|
+
* A typed optional property definition generated by {@link TypedSchematic} for optional keys, with `$required` set to `false` and excludes `undefined` from the type
|
|
10
10
|
*
|
|
11
11
|
* @template Value Property's type _(including `undefined`)_
|
|
12
12
|
*
|
|
@@ -24,7 +24,7 @@ type TypedPropertyOptional<Value> = {
|
|
|
24
24
|
$validators?: PropertyValidators<ToSchemaPropertyType<Exclude<Value, undefined>>>;
|
|
25
25
|
};
|
|
26
26
|
/**
|
|
27
|
-
* 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`
|
|
28
28
|
*
|
|
29
29
|
* @template Value Property's type
|
|
30
30
|
*
|
|
@@ -44,7 +44,7 @@ type TypedPropertyRequired<Value> = {
|
|
|
44
44
|
/**
|
|
45
45
|
* Creates a schema type constrained to match a TypeScript type
|
|
46
46
|
*
|
|
47
|
-
* Required keys map to {@link ToSchemaType} or {@link TypedPropertyRequired}; plain object values may also use {@link
|
|
47
|
+
* Required keys map to {@link ToSchemaType} or {@link TypedPropertyRequired}; plain object values may also use {@link Schema}
|
|
48
48
|
*
|
|
49
49
|
* @template Model Object type to generate a schema for
|
|
50
50
|
*
|
|
@@ -59,6 +59,6 @@ type TypedPropertyRequired<Value> = {
|
|
|
59
59
|
* };
|
|
60
60
|
* ```
|
|
61
61
|
*/
|
|
62
|
-
type
|
|
62
|
+
type TypedSchematic<Model extends PlainObject> = Simplify<{ [Key in RequiredKeys<Model>]: Model[Key] extends PlainObject ? Schema<Model[Key]> : ToSchemaType<Model[Key]> | TypedPropertyRequired<Model[Key]> } & { [Key in OptionalKeys<Model>]: Exclude<Model[Key], undefined> extends PlainObject ? Schema<Exclude<Model[Key], undefined>> : TypedPropertyOptional<Model[Key]> }>;
|
|
63
63
|
//#endregion
|
|
64
|
-
export { TypedPropertyOptional, TypedPropertyRequired,
|
|
64
|
+
export { TypedPropertyOptional, TypedPropertyRequired, TypedSchematic };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { TypedSchematic } from "./schematic.typed.model.mjs";
|
|
2
|
+
import { Schema } from "../schema.mjs";
|
|
3
3
|
import { DeduplicateTuple, UnionToTuple, UnwrapSingle, Values } from "./misc.model.mjs";
|
|
4
4
|
import { PlainObject } from "@oscarpalmer/atoms/models";
|
|
5
5
|
|
|
@@ -25,11 +25,11 @@ type ToSchemaPropertyType<Value> = UnwrapSingle<DeduplicateTuple<MapToSchemaProp
|
|
|
25
25
|
/**
|
|
26
26
|
* Converts a single type to its schema property equivalent
|
|
27
27
|
*
|
|
28
|
-
* Plain objects become {@link
|
|
28
|
+
* Plain objects become {@link TypedSchematic}; primitives go through {@link ToValueType}
|
|
29
29
|
*
|
|
30
30
|
* @template Value Type to convert
|
|
31
31
|
*/
|
|
32
|
-
type ToSchemaPropertyTypeEach<Value> = Value extends PlainObject ?
|
|
32
|
+
type ToSchemaPropertyTypeEach<Value> = Value extends PlainObject ? TypedSchematic<Value> : ToValueType<Value>;
|
|
33
33
|
/**
|
|
34
34
|
* Converts a TypeScript type to its {@link ValueName} representation, suitable for use as a top-level schema entry
|
|
35
35
|
*
|
|
@@ -39,7 +39,7 @@ type ToSchemaType<Value> = UnwrapSingle<DeduplicateTuple<MapToValueTypes<UnionTo
|
|
|
39
39
|
/**
|
|
40
40
|
* Maps a type to its {@link ValueName} string equivalent
|
|
41
41
|
*
|
|
42
|
-
* Resolves {@link
|
|
42
|
+
* 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
|
|
43
43
|
*
|
|
44
44
|
* @template Value Type to map
|
|
45
45
|
*
|
|
@@ -50,6 +50,6 @@ type ToSchemaType<Value> = UnwrapSingle<DeduplicateTuple<MapToValueTypes<UnionTo
|
|
|
50
50
|
* // ToValueType<Date> => 'date'
|
|
51
51
|
* ```
|
|
52
52
|
*/
|
|
53
|
-
type ToValueType<Value> = Value extends
|
|
53
|
+
type ToValueType<Value> = Value extends Schema<any> ? Value : { [Key in keyof Omit<Values, 'object'>]: Value extends Values[Key] ? Key : never }[keyof Omit<Values, 'object'>] extends infer Match ? [Match] extends [never] ? Value extends object ? 'object' | ((value: unknown) => value is Value) : (value: unknown) => value is Value : Match : never;
|
|
54
54
|
//#endregion
|
|
55
55
|
export { MapToSchemaPropertyTypes, MapToValueTypes, ToSchemaPropertyType, ToSchemaPropertyTypeEach, ToSchemaType, ToValueType };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Schema } from "../schema.mjs";
|
|
2
2
|
import { ValueName } from "./misc.model.mjs";
|
|
3
3
|
import { GenericCallback, PlainObject } from "@oscarpalmer/atoms/models";
|
|
4
4
|
|
|
@@ -87,6 +87,6 @@ type ValidatorParameters = {
|
|
|
87
87
|
reporting: ReportingInformation;
|
|
88
88
|
strict: boolean;
|
|
89
89
|
};
|
|
90
|
-
type ValidatorType = Function | PlainObject |
|
|
90
|
+
type ValidatorType = Function | PlainObject | Schema<unknown> | ValueName;
|
|
91
91
|
//#endregion
|
|
92
92
|
export { GetOptions, IsOptions, NamedValidatorHandlers, NamedValidators, ReportingInformation, ReportingType, SchematicError, ValidationError, ValidationInformation, ValidationInformationKey, Validator, ValidatorDefaults, ValidatorItem, ValidatorParameters, ValidatorType };
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { Infer } from "./models/infer.model.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { TypedSchematic } from "./models/schematic.typed.model.mjs";
|
|
3
3
|
import { GetOptions, IsOptions, ValidationInformation, Validator } from "./models/validation.model.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { Schematic } from "./models/schematic.plain.model.mjs";
|
|
5
5
|
import { PlainObject } from "@oscarpalmer/atoms/models";
|
|
6
6
|
import { Result } from "@oscarpalmer/atoms/result/models";
|
|
7
7
|
|
|
8
|
-
//#region src/
|
|
8
|
+
//#region src/schema.d.ts
|
|
9
9
|
/**
|
|
10
|
-
* A
|
|
10
|
+
* A schema for validating objects
|
|
11
11
|
*/
|
|
12
|
-
declare class
|
|
12
|
+
declare class Schema<Model> {
|
|
13
13
|
#private;
|
|
14
|
-
private readonly $
|
|
14
|
+
private readonly $schema;
|
|
15
15
|
constructor(validator: Validator);
|
|
16
16
|
/**
|
|
17
17
|
* Parse a value according to the schema
|
|
@@ -159,21 +159,21 @@ declare class Schematic<Model> {
|
|
|
159
159
|
is(value: unknown, strict?: true): value is Model;
|
|
160
160
|
}
|
|
161
161
|
/**
|
|
162
|
-
* Create a
|
|
162
|
+
* Create a schema from a schematic
|
|
163
163
|
* @template Model Schema type
|
|
164
|
-
* @param schema
|
|
165
|
-
* @throws Throws {@link SchematicError} if the
|
|
166
|
-
* @returns A
|
|
164
|
+
* @param schema Schematic to create the schema from
|
|
165
|
+
* @throws Throws {@link SchematicError} if the schematic can not be converted into a schema
|
|
166
|
+
* @returns A schema for the given schematic
|
|
167
167
|
*/
|
|
168
|
-
declare function
|
|
168
|
+
declare function schema<Model extends Schematic>(schema: Model): Schema<Infer<Model>>;
|
|
169
169
|
/**
|
|
170
|
-
* Create a
|
|
170
|
+
* Create a schema from a typed schematic
|
|
171
171
|
* @template Model Existing type
|
|
172
|
-
* @param schema Typed
|
|
173
|
-
* @throws Throws {@link SchematicError} if the
|
|
174
|
-
* @returns A
|
|
172
|
+
* @param schema Typed schematic to create the schema from
|
|
173
|
+
* @throws Throws {@link SchematicError} if the schematic can not be converted into a schema
|
|
174
|
+
* @returns A schema for the given typed schematic
|
|
175
175
|
*/
|
|
176
|
-
declare function
|
|
177
|
-
declare const
|
|
176
|
+
declare function schema<Model extends PlainObject>(schema: TypedSchematic<Model>): Schema<Model>;
|
|
177
|
+
declare const schemaValidators: WeakMap<Schema<unknown>, Validator>;
|
|
178
178
|
//#endregion
|
|
179
|
-
export {
|
|
179
|
+
export { Schema, schema, schemaValidators };
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { getParameters,
|
|
1
|
+
import { PROPERTY_SCHEMA, SCHEMATIC_MESSAGE_SCHEMA_INVALID_TYPE } from "./constants.mjs";
|
|
2
|
+
import { getParameters, isSchema } from "./helpers/misc.helper.mjs";
|
|
3
3
|
import { SchematicError } from "./models/validation.model.mjs";
|
|
4
4
|
import { getObjectValidator } from "./validator/object.validator.mjs";
|
|
5
5
|
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
6
6
|
import { error, ok } from "@oscarpalmer/atoms/result/misc";
|
|
7
|
-
//#region src/
|
|
7
|
+
//#region src/schema.ts
|
|
8
8
|
/**
|
|
9
|
-
* A
|
|
9
|
+
* A schema for validating objects
|
|
10
10
|
*/
|
|
11
|
-
var
|
|
11
|
+
var Schema = class {
|
|
12
12
|
#validator;
|
|
13
13
|
constructor(validator) {
|
|
14
|
-
Object.defineProperty(this,
|
|
14
|
+
Object.defineProperty(this, PROPERTY_SCHEMA, { value: true });
|
|
15
15
|
this.#validator = validator;
|
|
16
|
-
|
|
16
|
+
schemaValidators.set(this, validator);
|
|
17
17
|
}
|
|
18
18
|
get(value, options) {
|
|
19
19
|
const parameters = getParameters(options);
|
|
@@ -30,11 +30,11 @@ var Schematic = class {
|
|
|
30
30
|
return error(parameters.reporting.all ? result : result[0]);
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
|
-
function
|
|
34
|
-
if (
|
|
33
|
+
function schema(schema) {
|
|
34
|
+
if (isSchema(schema)) return schema;
|
|
35
35
|
if (!isPlainObject(schema)) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_TYPE);
|
|
36
|
-
return new
|
|
36
|
+
return new Schema(getObjectValidator(schema));
|
|
37
37
|
}
|
|
38
|
-
const
|
|
38
|
+
const schemaValidators = /* @__PURE__ */ new WeakMap();
|
|
39
39
|
//#endregion
|
|
40
|
-
export {
|
|
40
|
+
export { Schema, schema, schemaValidators };
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { PROPERTY_DEFAULT, PROPERTY_REQUIRED, PROPERTY_TYPE, PROPERTY_VALIDATORS, SCHEMATIC_MESSAGE_SCHEMA_INVALID_EMPTY, TYPE_ALL } from "../constants.mjs";
|
|
2
|
-
import { getParameters,
|
|
2
|
+
import { getParameters, isSchema } from "../helpers/misc.helper.mjs";
|
|
3
3
|
import { SchematicError, ValidationError } from "../models/validation.model.mjs";
|
|
4
4
|
import { getDefaultRequiredMessage, getDefaultTypeMessage, getDisallowedMessage, getInputPropertyMissingMessage, getInputPropertyTypeMessage, getInputTypeMessage, getRequiredMessage, getSchematicPropertyNullableMessage, getSchematicPropertyTypeMessage, getUnknownKeysMessage } from "../helpers/message.helper.mjs";
|
|
5
5
|
import { getBaseValidator } from "./base.validator.mjs";
|
|
6
6
|
import { getFunctionValidator } from "./function.validator.mjs";
|
|
7
7
|
import { getNamedHandlers } from "./named.handler.mjs";
|
|
8
8
|
import { getNamedValidator } from "./named.validator.mjs";
|
|
9
|
-
import {
|
|
9
|
+
import { getSchemaValidator } from "./schematic.validator.mjs";
|
|
10
10
|
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
11
11
|
import { join } from "@oscarpalmer/atoms/string";
|
|
12
12
|
import { clone } from "@oscarpalmer/atoms/value/clone";
|
|
@@ -67,8 +67,8 @@ function getObjectValidator(original, origin, fromType) {
|
|
|
67
67
|
case isPlainObject(type):
|
|
68
68
|
validator = getObjectValidator(type, fullKey, typed);
|
|
69
69
|
break;
|
|
70
|
-
case
|
|
71
|
-
validator =
|
|
70
|
+
case isSchema(type):
|
|
71
|
+
validator = getSchemaValidator(type);
|
|
72
72
|
break;
|
|
73
73
|
case TYPE_ALL.has(type):
|
|
74
74
|
validator = getNamedValidator(fullKey, type, handlers);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Validator } from "../models/validation.model.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { Schema } from "../schema.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/validator/schematic.validator.d.ts
|
|
5
|
-
declare function
|
|
5
|
+
declare function getSchemaValidator(schematic: Schema<unknown>): Validator;
|
|
6
6
|
//#endregion
|
|
7
|
-
export {
|
|
7
|
+
export { getSchemaValidator };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { schemaValidators } from "../schema.mjs";
|
|
2
2
|
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
3
3
|
//#region src/validator/schematic.validator.ts
|
|
4
|
-
function
|
|
5
|
-
const validator =
|
|
4
|
+
function getSchemaValidator(schematic) {
|
|
5
|
+
const validator = schemaValidators.get(schematic);
|
|
6
6
|
return (input, parameters, get) => {
|
|
7
7
|
let result;
|
|
8
8
|
if (isPlainObject(input)) result = validator(input, parameters, get);
|
|
@@ -13,4 +13,4 @@ function getSchematicValidator(schematic) {
|
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
//#endregion
|
|
16
|
-
export {
|
|
16
|
+
export { getSchemaValidator };
|
package/package.json
CHANGED
package/src/constants.ts
CHANGED
|
@@ -23,9 +23,9 @@ export const MESSAGE_CONSTRUCTOR = 'Expected a constructor function';
|
|
|
23
23
|
|
|
24
24
|
// #region Names
|
|
25
25
|
|
|
26
|
-
export const
|
|
26
|
+
export const NAME_SCHEMA = 'Schema';
|
|
27
27
|
|
|
28
|
-
export const
|
|
28
|
+
export const NAME_SCHEMA_PREFIXED = 'a Schema';
|
|
29
29
|
|
|
30
30
|
export const NAME_ERROR_SCHEMATIC = 'SchematicError';
|
|
31
31
|
|
|
@@ -39,7 +39,7 @@ export const PROPERTY_DEFAULT = '$default';
|
|
|
39
39
|
|
|
40
40
|
export const PROPERTY_REQUIRED = '$required';
|
|
41
41
|
|
|
42
|
-
export const
|
|
42
|
+
export const PROPERTY_SCHEMA = '$schema';
|
|
43
43
|
|
|
44
44
|
export const PROPERTY_TYPE = '$type';
|
|
45
45
|
|
|
@@ -2,7 +2,7 @@ import {isConstructor, isPlainObject} from '@oscarpalmer/atoms/is';
|
|
|
2
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,
|
|
@@ -14,7 +14,7 @@ import type {
|
|
|
14
14
|
ReportingType,
|
|
15
15
|
ValidatorParameters,
|
|
16
16
|
} from '../models/validation.model';
|
|
17
|
-
import type {
|
|
17
|
+
import type {Schema} from '../schema';
|
|
18
18
|
|
|
19
19
|
export function getParameters(input?: unknown): ValidatorParameters {
|
|
20
20
|
if (typeof input === 'boolean') {
|
|
@@ -82,11 +82,11 @@ export function instanceOf<Instance>(
|
|
|
82
82
|
* @param value Value to check
|
|
83
83
|
* @returns `true` if the value is a schematic, `false` otherwise
|
|
84
84
|
*/
|
|
85
|
-
export function
|
|
85
|
+
export function isSchema(value: unknown): value is Schema<never> {
|
|
86
86
|
return (
|
|
87
87
|
typeof value === 'object' &&
|
|
88
88
|
value !== null &&
|
|
89
|
-
|
|
90
|
-
value[
|
|
89
|
+
PROPERTY_SCHEMA in value &&
|
|
90
|
+
value[PROPERTY_SCHEMA] === true
|
|
91
91
|
);
|
|
92
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
|