@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
package/dist/constants.d.mts
CHANGED
|
@@ -8,13 +8,13 @@ declare const CONJUNCTION_OR_COMMA = ", or ";
|
|
|
8
8
|
declare const CONJUNCTION_AND = " and ";
|
|
9
9
|
declare const CONJUNCTION_AND_COMMA = ", and ";
|
|
10
10
|
declare const MESSAGE_CONSTRUCTOR = "Expected a constructor function";
|
|
11
|
-
declare const
|
|
12
|
-
declare const
|
|
11
|
+
declare const NAME_SCHEMA = "Schema";
|
|
12
|
+
declare const NAME_SCHEMA_PREFIXED = "a Schema";
|
|
13
13
|
declare const NAME_ERROR_SCHEMATIC = "SchematicError";
|
|
14
14
|
declare const NAME_ERROR_VALIDATION = "ValidationError";
|
|
15
15
|
declare const PROPERTY_DEFAULT = "$default";
|
|
16
16
|
declare const PROPERTY_REQUIRED = "$required";
|
|
17
|
-
declare const
|
|
17
|
+
declare const PROPERTY_SCHEMA = "$schema";
|
|
18
18
|
declare const PROPERTY_TYPE = "$type";
|
|
19
19
|
declare const PROPERTY_VALIDATORS = "$validators";
|
|
20
20
|
declare const VALIDATION_MESSAGE_INVALID_INPUT = "Expected an object as input but received <>";
|
|
@@ -50,4 +50,4 @@ declare const VALIDATABLE_TYPES: Set<keyof Values>;
|
|
|
50
50
|
declare const TYPE_ALL: Set<keyof Values>;
|
|
51
51
|
declare const PREFIXED_TYPES: Record<ValueName, string>;
|
|
52
52
|
//#endregion
|
|
53
|
-
export { COMMA, CONJUNCTION_AND, CONJUNCTION_AND_COMMA, CONJUNCTION_OR, CONJUNCTION_OR_COMMA, MESSAGE_CONSTRUCTOR, NAME_ERROR_SCHEMATIC, NAME_ERROR_VALIDATION,
|
|
53
|
+
export { COMMA, CONJUNCTION_AND, CONJUNCTION_AND_COMMA, CONJUNCTION_OR, CONJUNCTION_OR_COMMA, MESSAGE_CONSTRUCTOR, NAME_ERROR_SCHEMATIC, NAME_ERROR_VALIDATION, NAME_SCHEMA, NAME_SCHEMA_PREFIXED, PREFIXED_TYPES, PROPERTY_DEFAULT, PROPERTY_REQUIRED, PROPERTY_SCHEMA, PROPERTY_TYPE, PROPERTY_VALIDATORS, REPORTING_ALL, REPORTING_FIRST, REPORTING_NONE, REPORTING_THROW, REPORTING_TYPES, SCHEMATIC_MESSAGE_SCHEMA_INVALID_DEFAULT_REQUIRED, SCHEMATIC_MESSAGE_SCHEMA_INVALID_DEFAULT_TYPE, SCHEMATIC_MESSAGE_SCHEMA_INVALID_EMPTY, SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED, SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE, SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_REQUIRED, SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE, SCHEMATIC_MESSAGE_SCHEMA_INVALID_TYPE, SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY, SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE, SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE, TEMPLATE_PATTERN, TYPE_ALL, TYPE_ARRAY, TYPE_FUNCTION, TYPE_FUNCTION_RESULT, TYPE_NULL, TYPE_OBJECT, TYPE_UNDEFINED, VALIDATABLE_TYPES, VALIDATION_MESSAGE_INVALID_INPUT, VALIDATION_MESSAGE_INVALID_REQUIRED, VALIDATION_MESSAGE_INVALID_TYPE, VALIDATION_MESSAGE_INVALID_VALUE, VALIDATION_MESSAGE_INVALID_VALUE_SUFFIX, VALIDATION_MESSAGE_UNKNOWN_KEYS };
|
package/dist/constants.mjs
CHANGED
|
@@ -5,13 +5,13 @@ const CONJUNCTION_OR_COMMA = ", or ";
|
|
|
5
5
|
const CONJUNCTION_AND = " and ";
|
|
6
6
|
const CONJUNCTION_AND_COMMA = ", and ";
|
|
7
7
|
const MESSAGE_CONSTRUCTOR = "Expected a constructor function";
|
|
8
|
-
const
|
|
9
|
-
const
|
|
8
|
+
const NAME_SCHEMA = "Schema";
|
|
9
|
+
const NAME_SCHEMA_PREFIXED = "a Schema";
|
|
10
10
|
const NAME_ERROR_SCHEMATIC = "SchematicError";
|
|
11
11
|
const NAME_ERROR_VALIDATION = "ValidationError";
|
|
12
12
|
const PROPERTY_DEFAULT = "$default";
|
|
13
13
|
const PROPERTY_REQUIRED = "$required";
|
|
14
|
-
const
|
|
14
|
+
const PROPERTY_SCHEMA = "$schema";
|
|
15
15
|
const PROPERTY_TYPE = "$type";
|
|
16
16
|
const PROPERTY_VALIDATORS = "$validators";
|
|
17
17
|
const VALIDATION_MESSAGE_INVALID_INPUT = "Expected an object as input but received <>";
|
|
@@ -78,4 +78,4 @@ const PREFIXED_TYPES = {
|
|
|
78
78
|
[TYPE_UNDEFINED]: TYPE_UNDEFINED
|
|
79
79
|
};
|
|
80
80
|
//#endregion
|
|
81
|
-
export { COMMA, CONJUNCTION_AND, CONJUNCTION_AND_COMMA, CONJUNCTION_OR, CONJUNCTION_OR_COMMA, MESSAGE_CONSTRUCTOR, NAME_ERROR_SCHEMATIC, NAME_ERROR_VALIDATION,
|
|
81
|
+
export { COMMA, CONJUNCTION_AND, CONJUNCTION_AND_COMMA, CONJUNCTION_OR, CONJUNCTION_OR_COMMA, MESSAGE_CONSTRUCTOR, NAME_ERROR_SCHEMATIC, NAME_ERROR_VALIDATION, NAME_SCHEMA, NAME_SCHEMA_PREFIXED, PREFIXED_TYPES, PROPERTY_DEFAULT, PROPERTY_REQUIRED, PROPERTY_SCHEMA, PROPERTY_TYPE, PROPERTY_VALIDATORS, REPORTING_ALL, REPORTING_FIRST, REPORTING_NONE, REPORTING_THROW, REPORTING_TYPES, SCHEMATIC_MESSAGE_SCHEMA_INVALID_DEFAULT_REQUIRED, SCHEMATIC_MESSAGE_SCHEMA_INVALID_DEFAULT_TYPE, SCHEMATIC_MESSAGE_SCHEMA_INVALID_EMPTY, SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED, SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE, SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_REQUIRED, SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE, SCHEMATIC_MESSAGE_SCHEMA_INVALID_TYPE, SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY, SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE, SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE, TEMPLATE_PATTERN, TYPE_ALL, TYPE_ARRAY, TYPE_FUNCTION, TYPE_FUNCTION_RESULT, TYPE_NULL, TYPE_OBJECT, TYPE_UNDEFINED, VALIDATABLE_TYPES, VALIDATION_MESSAGE_INVALID_INPUT, VALIDATION_MESSAGE_INVALID_REQUIRED, VALIDATION_MESSAGE_INVALID_TYPE, VALIDATION_MESSAGE_INVALID_VALUE, VALIDATION_MESSAGE_INVALID_VALUE_SUFFIX, VALIDATION_MESSAGE_UNKNOWN_KEYS };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReportingInformation, ValidatorParameters } from "../models/validation.model.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { Schema } from "../schema.mjs";
|
|
3
3
|
import { Constructor } from "@oscarpalmer/atoms/models";
|
|
4
4
|
|
|
5
5
|
//#region src/helpers/misc.helper.d.ts
|
|
@@ -17,6 +17,6 @@ declare function instanceOf<Instance>(constructor: Constructor<Instance>): (valu
|
|
|
17
17
|
* @param value Value to check
|
|
18
18
|
* @returns `true` if the value is a schematic, `false` otherwise
|
|
19
19
|
*/
|
|
20
|
-
declare function
|
|
20
|
+
declare function isSchema(value: unknown): value is Schema<never>;
|
|
21
21
|
//#endregion
|
|
22
|
-
export { getParameters, getReporting, instanceOf,
|
|
22
|
+
export { getParameters, getReporting, instanceOf, isSchema };
|
|
@@ -49,8 +49,8 @@ function instanceOf(constructor) {
|
|
|
49
49
|
* @param value Value to check
|
|
50
50
|
* @returns `true` if the value is a schematic, `false` otherwise
|
|
51
51
|
*/
|
|
52
|
-
function
|
|
53
|
-
return typeof value === "object" && value !== null && "$
|
|
52
|
+
function isSchema(value) {
|
|
53
|
+
return typeof value === "object" && value !== null && "$schema" in value && value["$schema"] === true;
|
|
54
54
|
}
|
|
55
55
|
//#endregion
|
|
56
|
-
export { getParameters, getReporting, instanceOf,
|
|
56
|
+
export { getParameters, getReporting, instanceOf, isSchema };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Constructor, GenericCallback, PlainObject, Simplify } from "@oscarpalmer/atoms/models";
|
|
2
2
|
import { Result } from "@oscarpalmer/atoms/result/models";
|
|
3
3
|
|
|
4
|
-
//#region src/models/
|
|
4
|
+
//#region src/models/schematic.plain.model.d.ts
|
|
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
|
-
type
|
|
9
|
-
[key: string]:
|
|
8
|
+
type PlainSchematic = {
|
|
9
|
+
[key: string]: PlainSchematic | SchematicEntry | SchematicEntry[] | undefined;
|
|
10
10
|
} & {
|
|
11
11
|
$default?: never;
|
|
12
12
|
$required?: never;
|
|
@@ -14,30 +14,30 @@ type PlainSchema = {
|
|
|
14
14
|
$validators?: never;
|
|
15
15
|
};
|
|
16
16
|
/**
|
|
17
|
-
* A
|
|
17
|
+
* A schematic for validating objects
|
|
18
18
|
*
|
|
19
19
|
* @example
|
|
20
20
|
* ```ts
|
|
21
|
-
* const
|
|
21
|
+
* const schematic = {
|
|
22
22
|
* name: 'string',
|
|
23
23
|
* age: 'number',
|
|
24
24
|
* tags: ['string', 'number'],
|
|
25
|
-
* };
|
|
25
|
+
* } satisfies Schematic;
|
|
26
26
|
* ```
|
|
27
27
|
*/
|
|
28
|
-
type
|
|
28
|
+
type Schematic = PlainSchematic;
|
|
29
29
|
/**
|
|
30
|
-
* A union of all valid types for a single
|
|
30
|
+
* A union of all valid types for a single schematic entry
|
|
31
31
|
*
|
|
32
|
-
* Can be a {@link Constructor}, {@link
|
|
32
|
+
* Can be a {@link Constructor}, {@link PlainSchematic}, {@link SchematicProperty}, {@link Schema}, {@link ValueName}, or a custom validator function
|
|
33
33
|
*/
|
|
34
|
-
type
|
|
34
|
+
type SchematicEntry = Constructor | PlainSchematic | Schema<unknown> | SchematicProperty | ValueName | ((value: unknown) => boolean);
|
|
35
35
|
/**
|
|
36
36
|
* A property definition with explicit type(s), an optional requirement flag, and optional validators
|
|
37
37
|
*
|
|
38
38
|
* @example
|
|
39
39
|
* ```ts
|
|
40
|
-
* const prop:
|
|
40
|
+
* const prop: SchematicProperty = {
|
|
41
41
|
* $required: false,
|
|
42
42
|
* $type: ['string', 'number'],
|
|
43
43
|
* $validators: {
|
|
@@ -47,7 +47,7 @@ type SchemaEntry = Constructor | PlainSchema | SchemaProperty | Schematic<unknow
|
|
|
47
47
|
* };
|
|
48
48
|
* ```
|
|
49
49
|
*/
|
|
50
|
-
type
|
|
50
|
+
type SchematicProperty = {
|
|
51
51
|
$default?: unknown;
|
|
52
52
|
/**
|
|
53
53
|
* Whether the property is required _(defaults to `true`)_
|
|
@@ -63,11 +63,11 @@ type SchemaProperty = {
|
|
|
63
63
|
$validators?: PropertyValidators<SchemaPropertyType | SchemaPropertyType[]>;
|
|
64
64
|
};
|
|
65
65
|
/**
|
|
66
|
-
* A union of valid types for a {@link
|
|
66
|
+
* A union of valid types for a {@link SchematicProperty}'s `$type` field
|
|
67
67
|
*
|
|
68
|
-
* Can be a {@link Constructor}, {@link
|
|
68
|
+
* Can be a {@link Constructor}, {@link PlainSchematic}, {@link Schema}, {@link ValueName} string, or a custom validator function
|
|
69
69
|
*/
|
|
70
|
-
type SchemaPropertyType = Constructor |
|
|
70
|
+
type SchemaPropertyType = Constructor | PlainSchematic | Schema<unknown> | ValueName | ((value: unknown) => boolean);
|
|
71
71
|
/**
|
|
72
72
|
* A map of optional validator functions keyed by {@link ValueName}, used to add custom validation to {@link SchemaProperty} definitions
|
|
73
73
|
*
|
|
@@ -113,11 +113,11 @@ type ExtractValueNames<Value> = Value extends ValueName ? Value : Value extends
|
|
|
113
113
|
/**
|
|
114
114
|
* Determines whether a schema entry is optional
|
|
115
115
|
*
|
|
116
|
-
* Returns `true` if the entry is a {@link
|
|
116
|
+
* Returns `true` if the entry is a {@link SchematicProperty} with `$required` set to `false`; otherwise returns `false`
|
|
117
117
|
*
|
|
118
118
|
* @template Value Schema entry to check
|
|
119
119
|
*/
|
|
120
|
-
type IsOptionalProperty<Value> = Value extends
|
|
120
|
+
type IsOptionalProperty<Value> = Value extends SchematicProperty ? Value['$required'] extends false ? true : false : false;
|
|
121
121
|
/**
|
|
122
122
|
* Extracts the last member from a union type by leveraging contravariance of function parameter types
|
|
123
123
|
*
|
|
@@ -227,31 +227,31 @@ type Values = {
|
|
|
227
227
|
//#endregion
|
|
228
228
|
//#region src/models/infer.model.d.ts
|
|
229
229
|
/**
|
|
230
|
-
* Infers the TypeScript type from a {@link
|
|
230
|
+
* Infers the TypeScript type from a {@link Schematic} definition
|
|
231
231
|
*
|
|
232
|
-
* @template Model
|
|
232
|
+
* @template Model Schematic to infer types from
|
|
233
233
|
*
|
|
234
234
|
* @example
|
|
235
235
|
* ```ts
|
|
236
|
-
* const
|
|
236
|
+
* const userSchematic = {
|
|
237
237
|
* name: 'string',
|
|
238
238
|
* age: 'number',
|
|
239
239
|
* address: { $required: false, $type: 'string' },
|
|
240
|
-
* } satisfies
|
|
240
|
+
* } satisfies Schematic;
|
|
241
241
|
*
|
|
242
|
-
* type User = Infer<typeof
|
|
242
|
+
* type User = Infer<typeof userSchematic>;
|
|
243
243
|
* // { name: string; age: number; address?: string }
|
|
244
244
|
* ```
|
|
245
245
|
*/
|
|
246
|
-
type Infer<Model extends
|
|
246
|
+
type Infer<Model extends Schematic> = Simplify<{ [Key in InferRequiredKeys<Model>]: InferSchemaEntry<Model[Key]> } & { [Key in InferOptionalKeys<Model>]?: InferSchemaEntry<Model[Key]> }>;
|
|
247
247
|
/**
|
|
248
|
-
* Extracts keys from a {@link
|
|
248
|
+
* Extracts keys from a {@link Schematic} whose entries are optional _(i.e., `$required` is `false`)_
|
|
249
249
|
*
|
|
250
|
-
* @template Model - {@link
|
|
250
|
+
* @template Model - {@link Schematic} to extract optional keys from
|
|
251
251
|
*/
|
|
252
|
-
type InferOptionalKeys<Model extends
|
|
252
|
+
type InferOptionalKeys<Model extends Schematic> = keyof { [Key in keyof Model as IsOptionalProperty<Model[Key]> extends true ? Key : never]: never };
|
|
253
253
|
/**
|
|
254
|
-
* Infers the TypeScript type from a {@link
|
|
254
|
+
* Infers the TypeScript type from a {@link SchematicProperty}'s `$type` field
|
|
255
255
|
*
|
|
256
256
|
* @template Value `$type` value _(single or array)_
|
|
257
257
|
*/
|
|
@@ -259,31 +259,31 @@ type InferPropertyType<Value> = Value extends (infer Item)[] ? InferPropertyValu
|
|
|
259
259
|
/**
|
|
260
260
|
* Maps a single `$type` definition to its TypeScript equivalent
|
|
261
261
|
*
|
|
262
|
-
* Resolves, in order: {@link Constructor}
|
|
262
|
+
* Resolves, in order: {@link Constructor}s, {@link Schema} instances, {@link ValueName} values, and nested {@link PlainSchematic} objects
|
|
263
263
|
*
|
|
264
264
|
* @template Value single type definition
|
|
265
265
|
*/
|
|
266
|
-
type InferPropertyValue<Value> = Value extends Constructor<infer Instance> ? Instance : Value extends
|
|
266
|
+
type InferPropertyValue<Value> = Value extends Constructor<infer Instance> ? Instance : Value extends Schema<infer Model> ? Model : Value extends ValueName ? Values[Value & ValueName] : Value extends PlainSchematic ? Infer<Value> : never;
|
|
267
267
|
/**
|
|
268
|
-
* Extracts keys from a {@link
|
|
268
|
+
* Extracts keys from a {@link Schematic} whose entries are required _(i.e., `$required` is not `false`)_
|
|
269
269
|
*
|
|
270
|
-
* @template Model
|
|
270
|
+
* @template Model Schematic to extract required keys from
|
|
271
271
|
*/
|
|
272
|
-
type InferRequiredKeys<Model extends
|
|
272
|
+
type InferRequiredKeys<Model extends Schematic> = keyof { [Key in keyof Model as IsOptionalProperty<Model[Key]> extends true ? never : Key]: never };
|
|
273
273
|
/**
|
|
274
|
-
* Infers the TypeScript type from a top-level {@link
|
|
274
|
+
* Infers the TypeScript type from a top-level {@link Schematic} entry
|
|
275
275
|
*
|
|
276
|
-
* @template Value
|
|
276
|
+
* @template Value Schematic entry value _(single or array)_
|
|
277
277
|
*/
|
|
278
278
|
type InferSchemaEntry<Value> = Value extends (infer Item)[] ? InferSchemaEntryValue<Item> : InferSchemaEntryValue<Value>;
|
|
279
279
|
/**
|
|
280
280
|
* Maps a single top-level schema entry to its TypeScript type
|
|
281
281
|
*
|
|
282
|
-
* Resolves, in order: {@link Constructor}
|
|
282
|
+
* Resolves, in order: {@link Constructor}s, {@link Schema} instances, {@link SchemaProperty} objects, {@link PlainSchematic} objects, and {@link ValueName} values
|
|
283
283
|
*
|
|
284
284
|
* @template Value single schema entry
|
|
285
285
|
*/
|
|
286
|
-
type InferSchemaEntryValue<Value> = Value extends Constructor<infer Instance> ? Instance : Value extends
|
|
286
|
+
type InferSchemaEntryValue<Value> = Value extends Constructor<infer Instance> ? Instance : Value extends Schema<infer Model> ? Model : Value extends SchematicProperty ? InferPropertyType<Value['$type']> : Value extends PlainSchematic ? Infer<Value & Schematic> : Value extends ValueName ? Values[Value & ValueName] : never;
|
|
287
287
|
//#endregion
|
|
288
288
|
//#region src/models/transform.model.d.ts
|
|
289
289
|
/**
|
|
@@ -307,11 +307,11 @@ type ToSchemaPropertyType<Value> = UnwrapSingle<DeduplicateTuple<MapToSchemaProp
|
|
|
307
307
|
/**
|
|
308
308
|
* Converts a single type to its schema property equivalent
|
|
309
309
|
*
|
|
310
|
-
* Plain objects become {@link
|
|
310
|
+
* Plain objects become {@link TypedSchematic}; primitives go through {@link ToValueType}
|
|
311
311
|
*
|
|
312
312
|
* @template Value Type to convert
|
|
313
313
|
*/
|
|
314
|
-
type ToSchemaPropertyTypeEach<Value> = Value extends PlainObject ?
|
|
314
|
+
type ToSchemaPropertyTypeEach<Value> = Value extends PlainObject ? TypedSchematic<Value> : ToValueType<Value>;
|
|
315
315
|
/**
|
|
316
316
|
* Converts a TypeScript type to its {@link ValueName} representation, suitable for use as a top-level schema entry
|
|
317
317
|
*
|
|
@@ -321,7 +321,7 @@ type ToSchemaType<Value> = UnwrapSingle<DeduplicateTuple<MapToValueTypes<UnionTo
|
|
|
321
321
|
/**
|
|
322
322
|
* Maps a type to its {@link ValueName} string equivalent
|
|
323
323
|
*
|
|
324
|
-
* Resolves {@link
|
|
324
|
+
* 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
|
|
325
325
|
*
|
|
326
326
|
* @template Value Type to map
|
|
327
327
|
*
|
|
@@ -332,11 +332,11 @@ type ToSchemaType<Value> = UnwrapSingle<DeduplicateTuple<MapToValueTypes<UnionTo
|
|
|
332
332
|
* // ToValueType<Date> => 'date'
|
|
333
333
|
* ```
|
|
334
334
|
*/
|
|
335
|
-
type ToValueType<Value> = Value extends
|
|
335
|
+
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;
|
|
336
336
|
//#endregion
|
|
337
|
-
//#region src/models/
|
|
337
|
+
//#region src/models/schematic.typed.model.d.ts
|
|
338
338
|
/**
|
|
339
|
-
* A typed optional property definition generated by {@link
|
|
339
|
+
* A typed optional property definition generated by {@link TypedSchematic} for optional keys, with `$required` set to `false` and excludes `undefined` from the type
|
|
340
340
|
*
|
|
341
341
|
* @template Value Property's type _(including `undefined`)_
|
|
342
342
|
*
|
|
@@ -354,7 +354,7 @@ type TypedPropertyOptional<Value> = {
|
|
|
354
354
|
$validators?: PropertyValidators<ToSchemaPropertyType<Exclude<Value, undefined>>>;
|
|
355
355
|
};
|
|
356
356
|
/**
|
|
357
|
-
* A typed required property definition generated by {@link
|
|
357
|
+
* A typed required property definition generated by {@link TypedSchematic} for required keys, with `$required` defaulting to `true`
|
|
358
358
|
*
|
|
359
359
|
* @template Value Property's type
|
|
360
360
|
*
|
|
@@ -374,7 +374,7 @@ type TypedPropertyRequired<Value> = {
|
|
|
374
374
|
/**
|
|
375
375
|
* Creates a schema type constrained to match a TypeScript type
|
|
376
376
|
*
|
|
377
|
-
* Required keys map to {@link ToSchemaType} or {@link TypedPropertyRequired}; plain object values may also use {@link
|
|
377
|
+
* Required keys map to {@link ToSchemaType} or {@link TypedPropertyRequired}; plain object values may also use {@link Schema}
|
|
378
378
|
*
|
|
379
379
|
* @template Model Object type to generate a schema for
|
|
380
380
|
*
|
|
@@ -389,15 +389,15 @@ type TypedPropertyRequired<Value> = {
|
|
|
389
389
|
* };
|
|
390
390
|
* ```
|
|
391
391
|
*/
|
|
392
|
-
type
|
|
392
|
+
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]> }>;
|
|
393
393
|
//#endregion
|
|
394
|
-
//#region src/
|
|
394
|
+
//#region src/schema.d.ts
|
|
395
395
|
/**
|
|
396
|
-
* A
|
|
396
|
+
* A schema for validating objects
|
|
397
397
|
*/
|
|
398
|
-
declare class
|
|
398
|
+
declare class Schema<Model> {
|
|
399
399
|
#private;
|
|
400
|
-
private readonly $
|
|
400
|
+
private readonly $schema;
|
|
401
401
|
constructor(validator: Validator);
|
|
402
402
|
/**
|
|
403
403
|
* Parse a value according to the schema
|
|
@@ -545,21 +545,21 @@ declare class Schematic<Model> {
|
|
|
545
545
|
is(value: unknown, strict?: true): value is Model;
|
|
546
546
|
}
|
|
547
547
|
/**
|
|
548
|
-
* Create a
|
|
548
|
+
* Create a schema from a schematic
|
|
549
549
|
* @template Model Schema type
|
|
550
|
-
* @param schema
|
|
551
|
-
* @throws Throws {@link SchematicError} if the
|
|
552
|
-
* @returns A
|
|
550
|
+
* @param schema Schematic to create the schema from
|
|
551
|
+
* @throws Throws {@link SchematicError} if the schematic can not be converted into a schema
|
|
552
|
+
* @returns A schema for the given schematic
|
|
553
553
|
*/
|
|
554
|
-
declare function
|
|
554
|
+
declare function schema<Model extends Schematic>(schema: Model): Schema<Infer<Model>>;
|
|
555
555
|
/**
|
|
556
|
-
* Create a
|
|
556
|
+
* Create a schema from a typed schematic
|
|
557
557
|
* @template Model Existing type
|
|
558
|
-
* @param schema Typed
|
|
559
|
-
* @throws Throws {@link SchematicError} if the
|
|
560
|
-
* @returns A
|
|
558
|
+
* @param schema Typed schematic to create the schema from
|
|
559
|
+
* @throws Throws {@link SchematicError} if the schematic can not be converted into a schema
|
|
560
|
+
* @returns A schema for the given typed schematic
|
|
561
561
|
*/
|
|
562
|
-
declare function
|
|
562
|
+
declare function schema<Model extends PlainObject>(schema: TypedSchematic<Model>): Schema<Model>;
|
|
563
563
|
//#endregion
|
|
564
564
|
//#region src/models/validation.model.d.ts
|
|
565
565
|
type ReportingInformation = Record<ReportingType, boolean> & {
|
|
@@ -648,6 +648,6 @@ declare function instanceOf<Instance>(constructor: Constructor<Instance>): (valu
|
|
|
648
648
|
* @param value Value to check
|
|
649
649
|
* @returns `true` if the value is a schematic, `false` otherwise
|
|
650
650
|
*/
|
|
651
|
-
declare function
|
|
651
|
+
declare function isSchema(value: unknown): value is Schema<never>;
|
|
652
652
|
//#endregion
|
|
653
|
-
export { type GetOptions, type IsOptions, type Schema, type Schematic, SchematicError, type
|
|
653
|
+
export { type GetOptions, type IsOptions, type Schema, type Schematic, SchematicError, type TypedSchematic, ValidationError, instanceOf, isSchema, schema };
|
package/dist/index.mjs
CHANGED
|
@@ -12,7 +12,7 @@ const NAME_ERROR_SCHEMATIC = "SchematicError";
|
|
|
12
12
|
const NAME_ERROR_VALIDATION = "ValidationError";
|
|
13
13
|
const PROPERTY_DEFAULT = "$default";
|
|
14
14
|
const PROPERTY_REQUIRED = "$required";
|
|
15
|
-
const
|
|
15
|
+
const PROPERTY_SCHEMA = "$schema";
|
|
16
16
|
const PROPERTY_TYPE = "$type";
|
|
17
17
|
const PROPERTY_VALIDATORS = "$validators";
|
|
18
18
|
const VALIDATION_MESSAGE_INVALID_INPUT = "Expected an object as input but received <>";
|
|
@@ -125,8 +125,8 @@ function instanceOf(constructor) {
|
|
|
125
125
|
* @param value Value to check
|
|
126
126
|
* @returns `true` if the value is a schematic, `false` otherwise
|
|
127
127
|
*/
|
|
128
|
-
function
|
|
129
|
-
return typeof value === "object" && value !== null && "$
|
|
128
|
+
function isSchema(value) {
|
|
129
|
+
return typeof value === "object" && value !== null && "$schema" in value && value["$schema"] === true;
|
|
130
130
|
}
|
|
131
131
|
//#endregion
|
|
132
132
|
//#region src/models/validation.model.ts
|
|
@@ -320,8 +320,8 @@ const namedValidators = {
|
|
|
320
320
|
};
|
|
321
321
|
//#endregion
|
|
322
322
|
//#region src/validator/schematic.validator.ts
|
|
323
|
-
function
|
|
324
|
-
const validator =
|
|
323
|
+
function getSchemaValidator(schematic) {
|
|
324
|
+
const validator = schemaValidators.get(schematic);
|
|
325
325
|
return (input, parameters, get) => {
|
|
326
326
|
let result;
|
|
327
327
|
if (isPlainObject(input)) result = validator(input, parameters, get);
|
|
@@ -389,8 +389,8 @@ function getObjectValidator(original, origin, fromType) {
|
|
|
389
389
|
case isPlainObject(type):
|
|
390
390
|
validator = getObjectValidator(type, fullKey, typed);
|
|
391
391
|
break;
|
|
392
|
-
case
|
|
393
|
-
validator =
|
|
392
|
+
case isSchema(type):
|
|
393
|
+
validator = getSchemaValidator(type);
|
|
394
394
|
break;
|
|
395
395
|
case TYPE_ALL.has(type):
|
|
396
396
|
validator = getNamedValidator(fullKey, type, handlers);
|
|
@@ -504,16 +504,16 @@ function getRequired(obj, key, allowed) {
|
|
|
504
504
|
return obj[PROPERTY_REQUIRED];
|
|
505
505
|
}
|
|
506
506
|
//#endregion
|
|
507
|
-
//#region src/
|
|
507
|
+
//#region src/schema.ts
|
|
508
508
|
/**
|
|
509
|
-
* A
|
|
509
|
+
* A schema for validating objects
|
|
510
510
|
*/
|
|
511
|
-
var
|
|
511
|
+
var Schema = class {
|
|
512
512
|
#validator;
|
|
513
513
|
constructor(validator) {
|
|
514
|
-
Object.defineProperty(this,
|
|
514
|
+
Object.defineProperty(this, PROPERTY_SCHEMA, { value: true });
|
|
515
515
|
this.#validator = validator;
|
|
516
|
-
|
|
516
|
+
schemaValidators.set(this, validator);
|
|
517
517
|
}
|
|
518
518
|
get(value, options) {
|
|
519
519
|
const parameters = getParameters(options);
|
|
@@ -530,11 +530,11 @@ var Schematic = class {
|
|
|
530
530
|
return error(parameters.reporting.all ? result : result[0]);
|
|
531
531
|
}
|
|
532
532
|
};
|
|
533
|
-
function
|
|
534
|
-
if (
|
|
533
|
+
function schema(schema) {
|
|
534
|
+
if (isSchema(schema)) return schema;
|
|
535
535
|
if (!isPlainObject(schema)) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_TYPE);
|
|
536
|
-
return new
|
|
536
|
+
return new Schema(getObjectValidator(schema));
|
|
537
537
|
}
|
|
538
|
-
const
|
|
538
|
+
const schemaValidators = /* @__PURE__ */ new WeakMap();
|
|
539
539
|
//#endregion
|
|
540
|
-
export { SchematicError, ValidationError, instanceOf,
|
|
540
|
+
export { SchematicError, ValidationError, instanceOf, isSchema, schema };
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Schema } from "../schema.mjs";
|
|
2
|
+
import { PlainSchematic, Schematic, SchematicProperty } from "./schematic.plain.model.mjs";
|
|
3
3
|
import { IsOptionalProperty, ValueName, Values } from "./misc.model.mjs";
|
|
4
4
|
import { Constructor, Simplify } from "@oscarpalmer/atoms/models";
|
|
5
5
|
|
|
6
6
|
//#region src/models/infer.model.d.ts
|
|
7
7
|
/**
|
|
8
|
-
* Infers the TypeScript type from a {@link
|
|
8
|
+
* Infers the TypeScript type from a {@link Schematic} definition
|
|
9
9
|
*
|
|
10
|
-
* @template Model
|
|
10
|
+
* @template Model Schematic to infer types from
|
|
11
11
|
*
|
|
12
12
|
* @example
|
|
13
13
|
* ```ts
|
|
14
|
-
* const
|
|
14
|
+
* const userSchematic = {
|
|
15
15
|
* name: 'string',
|
|
16
16
|
* age: 'number',
|
|
17
17
|
* address: { $required: false, $type: 'string' },
|
|
18
|
-
* } satisfies
|
|
18
|
+
* } satisfies Schematic;
|
|
19
19
|
*
|
|
20
|
-
* type User = Infer<typeof
|
|
20
|
+
* type User = Infer<typeof userSchematic>;
|
|
21
21
|
* // { name: string; age: number; address?: string }
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
|
-
type Infer<Model extends
|
|
24
|
+
type Infer<Model extends Schematic> = Simplify<{ [Key in InferRequiredKeys<Model>]: InferSchemaEntry<Model[Key]> } & { [Key in InferOptionalKeys<Model>]?: InferSchemaEntry<Model[Key]> }>;
|
|
25
25
|
/**
|
|
26
|
-
* Extracts keys from a {@link
|
|
26
|
+
* Extracts keys from a {@link Schematic} whose entries are optional _(i.e., `$required` is `false`)_
|
|
27
27
|
*
|
|
28
|
-
* @template Model - {@link
|
|
28
|
+
* @template Model - {@link Schematic} to extract optional keys from
|
|
29
29
|
*/
|
|
30
|
-
type InferOptionalKeys<Model extends
|
|
30
|
+
type InferOptionalKeys<Model extends Schematic> = keyof { [Key in keyof Model as IsOptionalProperty<Model[Key]> extends true ? Key : never]: never };
|
|
31
31
|
/**
|
|
32
|
-
* Infers the TypeScript type from a {@link
|
|
32
|
+
* Infers the TypeScript type from a {@link SchematicProperty}'s `$type` field
|
|
33
33
|
*
|
|
34
34
|
* @template Value `$type` value _(single or array)_
|
|
35
35
|
*/
|
|
@@ -37,30 +37,30 @@ type InferPropertyType<Value> = Value extends (infer Item)[] ? InferPropertyValu
|
|
|
37
37
|
/**
|
|
38
38
|
* Maps a single `$type` definition to its TypeScript equivalent
|
|
39
39
|
*
|
|
40
|
-
* Resolves, in order: {@link Constructor}
|
|
40
|
+
* Resolves, in order: {@link Constructor}s, {@link Schema} instances, {@link ValueName} values, and nested {@link PlainSchematic} objects
|
|
41
41
|
*
|
|
42
42
|
* @template Value single type definition
|
|
43
43
|
*/
|
|
44
|
-
type InferPropertyValue<Value> = Value extends Constructor<infer Instance> ? Instance : Value extends
|
|
44
|
+
type InferPropertyValue<Value> = Value extends Constructor<infer Instance> ? Instance : Value extends Schema<infer Model> ? Model : Value extends ValueName ? Values[Value & ValueName] : Value extends PlainSchematic ? Infer<Value> : never;
|
|
45
45
|
/**
|
|
46
|
-
* Extracts keys from a {@link
|
|
46
|
+
* Extracts keys from a {@link Schematic} whose entries are required _(i.e., `$required` is not `false`)_
|
|
47
47
|
*
|
|
48
|
-
* @template Model
|
|
48
|
+
* @template Model Schematic to extract required keys from
|
|
49
49
|
*/
|
|
50
|
-
type InferRequiredKeys<Model extends
|
|
50
|
+
type InferRequiredKeys<Model extends Schematic> = keyof { [Key in keyof Model as IsOptionalProperty<Model[Key]> extends true ? never : Key]: never };
|
|
51
51
|
/**
|
|
52
|
-
* Infers the TypeScript type from a top-level {@link
|
|
52
|
+
* Infers the TypeScript type from a top-level {@link Schematic} entry
|
|
53
53
|
*
|
|
54
|
-
* @template Value
|
|
54
|
+
* @template Value Schematic entry value _(single or array)_
|
|
55
55
|
*/
|
|
56
56
|
type InferSchemaEntry<Value> = Value extends (infer Item)[] ? InferSchemaEntryValue<Item> : InferSchemaEntryValue<Value>;
|
|
57
57
|
/**
|
|
58
58
|
* Maps a single top-level schema entry to its TypeScript type
|
|
59
59
|
*
|
|
60
|
-
* Resolves, in order: {@link Constructor}
|
|
60
|
+
* Resolves, in order: {@link Constructor}s, {@link Schema} instances, {@link SchemaProperty} objects, {@link PlainSchematic} objects, and {@link ValueName} values
|
|
61
61
|
*
|
|
62
62
|
* @template Value single schema entry
|
|
63
63
|
*/
|
|
64
|
-
type InferSchemaEntryValue<Value> = Value extends Constructor<infer Instance> ? Instance : Value extends
|
|
64
|
+
type InferSchemaEntryValue<Value> = Value extends Constructor<infer Instance> ? Instance : Value extends Schema<infer Model> ? Model : Value extends SchematicProperty ? InferPropertyType<Value['$type']> : Value extends PlainSchematic ? Infer<Value & Schematic> : Value extends ValueName ? Values[Value & ValueName] : never;
|
|
65
65
|
//#endregion
|
|
66
66
|
export { Infer, InferOptionalKeys, InferPropertyType, InferPropertyValue, InferRequiredKeys, InferSchemaEntry, InferSchemaEntryValue };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SchematicProperty } from "./schematic.plain.model.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/models/misc.model.d.ts
|
|
4
4
|
/**
|
|
@@ -29,11 +29,11 @@ type ExtractValueNames<Value> = Value extends ValueName ? Value : Value extends
|
|
|
29
29
|
/**
|
|
30
30
|
* Determines whether a schema entry is optional
|
|
31
31
|
*
|
|
32
|
-
* Returns `true` if the entry is a {@link
|
|
32
|
+
* Returns `true` if the entry is a {@link SchematicProperty} with `$required` set to `false`; otherwise returns `false`
|
|
33
33
|
*
|
|
34
34
|
* @template Value Schema entry to check
|
|
35
35
|
*/
|
|
36
|
-
type IsOptionalProperty<Value> = Value extends
|
|
36
|
+
type IsOptionalProperty<Value> = Value extends SchematicProperty ? Value['$required'] extends false ? true : false : false;
|
|
37
37
|
/**
|
|
38
38
|
* Extracts the last member from a union type by leveraging contravariance of function parameter types
|
|
39
39
|
*
|