@lucania/schema 3.0.1 → 3.0.2
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/build/builder.d.ts +117 -6
- package/build/index.d.ts +2 -0
- package/build/index.js +194 -58
- package/build/schema/BaseSchema.d.ts +14 -3
- package/build/schema/ConstantSchema.d.ts +13 -0
- package/build/schema/LenientObject.d.ts +31 -0
- package/build/schema/ObjectSchema.d.ts +0 -1
- package/package.json +1 -1
package/build/builder.d.ts
CHANGED
|
@@ -1,47 +1,158 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { DefaultValue, ModelValue } from "./typing/toolbox";
|
|
1
|
+
import { BaseSchema, SourceValue } from ".";
|
|
3
2
|
import { AnySchema } from "./schema/AnySchema";
|
|
4
3
|
import { ArraySchema, ArraySource } from "./schema/ArraySchema";
|
|
5
4
|
import { BooleanSchema, BooleanSource } from "./schema/BooleanSchema";
|
|
5
|
+
import { ConstantSchema, ConstantSource } from "./schema/ConstantSchema";
|
|
6
6
|
import { DateSchema, DateSource } from "./schema/DateSchema";
|
|
7
7
|
import { DynamicObjectSchema, DynamicObjectSource } from "./schema/DynamicObjectSchema";
|
|
8
8
|
import { EnumerationSchema } from "./schema/EnumerationSchema";
|
|
9
|
+
import { LenientObjectModel, LenientObjectSchema, LenientObjectSource, LenientObjectSubschema } from "./schema/LenientObject";
|
|
9
10
|
import { NumberSchema, NumberSource } from "./schema/NumberSchema";
|
|
10
11
|
import { ObjectSchema, ObjectSource, ObjectSubschema } from "./schema/ObjectSchema";
|
|
11
12
|
import { OrSetSchema, OrSetSchemaSource } from "./schema/OrSetSchema";
|
|
12
13
|
import { StringSchema, StringSource } from "./schema/StringSchema";
|
|
13
|
-
import {
|
|
14
|
+
import { BaseSchemaAny } from "./typing/extended";
|
|
15
|
+
import { DefaultValue, ModelValue } from "./typing/toolbox";
|
|
16
|
+
/**
|
|
17
|
+
* A collection of helper functions used to create the standard set of schemas.
|
|
18
|
+
*/
|
|
14
19
|
export declare namespace Schema {
|
|
20
|
+
/**
|
|
21
|
+
* Creates a schema used to validate a string.
|
|
22
|
+
*
|
|
23
|
+
* @param required Flag representing whether the schema should enforce a value's presence.
|
|
24
|
+
* @param defaultValue A default the schema will use during validation if a value is not present.
|
|
25
|
+
* @returns A schema used to validate a string.
|
|
26
|
+
*/
|
|
15
27
|
function String(): StringSchema<true, undefined>;
|
|
16
28
|
function String<Required extends boolean>(required: Required): StringSchema<Required, undefined>;
|
|
17
29
|
function String<Required extends boolean, Default extends DefaultValue<StringSource>>(required: Required, defaultValue: Default): StringSchema<Required, Default>;
|
|
30
|
+
/**
|
|
31
|
+
* Creates a schema used to validate a number.
|
|
32
|
+
*
|
|
33
|
+
* @param required Flag representing whether the schema should enforce a value's presence.
|
|
34
|
+
* @param defaultValue A default the schema will use during validation if a value is not present.
|
|
35
|
+
* @returns A schema used to validate a number.
|
|
36
|
+
*/
|
|
18
37
|
function Number(): NumberSchema<true, undefined>;
|
|
19
38
|
function Number<Required extends boolean>(required: Required): NumberSchema<Required, undefined>;
|
|
20
39
|
function Number<Required extends boolean, Default extends DefaultValue<NumberSource>>(required: Required, defaultValue: Default): NumberSchema<Required, Default>;
|
|
40
|
+
/**
|
|
41
|
+
* Creates a schema used to validate a boolean.
|
|
42
|
+
*
|
|
43
|
+
* @param required Flag representing whether the schema should enforce a value's presence.
|
|
44
|
+
* @param defaultValue A default the schema will use during validation if a value is not present.
|
|
45
|
+
* @returns A schema used to validate a boolean.
|
|
46
|
+
*/
|
|
21
47
|
function Boolean(): BooleanSchema<true, undefined>;
|
|
22
48
|
function Boolean<Required extends boolean>(required: Required): BooleanSchema<Required, undefined>;
|
|
23
49
|
function Boolean<Required extends boolean, Default extends DefaultValue<BooleanSource>>(required: Required, defaultValue: Default): BooleanSchema<Required, Default>;
|
|
50
|
+
/**
|
|
51
|
+
* Creates a schema used to validate a Date.
|
|
52
|
+
*
|
|
53
|
+
* @param required Flag representing whether the schema should enforce a value's presence.
|
|
54
|
+
* @param defaultValue A default the schema will use during validation if a value is not present.
|
|
55
|
+
* @returns A schema used to validate a Date.
|
|
56
|
+
*/
|
|
24
57
|
function Date(): DateSchema<true, undefined>;
|
|
25
58
|
function Date<Required extends boolean>(required: Required): DateSchema<Required, undefined>;
|
|
26
59
|
function Date<Required extends boolean, Default extends DefaultValue<DateSource>>(required: Required, defaultValue: Default): DateSchema<Required, Default>;
|
|
60
|
+
/**
|
|
61
|
+
* Creates a schema used to validate anything! Any value will pass the validation provided by schemas created by this function.
|
|
62
|
+
*
|
|
63
|
+
* @param required Flag representing whether the schema should enforce a value's presence.
|
|
64
|
+
* @param defaultValue A default the schema will use during validation if a value is not present.
|
|
65
|
+
* @returns A schema used to validate anything.
|
|
66
|
+
*/
|
|
27
67
|
function Any(): AnySchema<true, undefined>;
|
|
28
68
|
function Any<Required extends boolean>(required: Required): AnySchema<Required, undefined>;
|
|
29
69
|
function Any<Required extends boolean, Default extends DefaultValue<any>>(required: Required, defaultValue: Default): AnySchema<Required, Default>;
|
|
70
|
+
/**
|
|
71
|
+
* Creates a schema used to validate an object.
|
|
72
|
+
*
|
|
73
|
+
* This function can be used to create schemas that describe a value's object hierarchy.
|
|
74
|
+
*
|
|
75
|
+
* @note Values validated by schemas created by this function will only retain properties specified by the schema.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* $.Object({ name: $.String() }).validate({ name: "Jeremy", age: 1 })
|
|
80
|
+
* ```
|
|
81
|
+
* ->
|
|
82
|
+
* ```ts
|
|
83
|
+
* { "name": "Jeremy" }
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* @param subschema An object describing the sole keys and values that must be present within an object.
|
|
87
|
+
* @param required Flag representing whether the schema should enforce a value's presence.
|
|
88
|
+
* @param defaultValue A default the schema will use during validation if a value is not present.
|
|
89
|
+
* @returns A schema used to validate an object.
|
|
90
|
+
*/
|
|
30
91
|
function Object<Subschema extends ObjectSubschema>(subschema: Subschema): ObjectSchema<Subschema, true, undefined>;
|
|
31
92
|
function Object<Subschema extends ObjectSubschema, Required extends boolean>(subschema: Subschema, required: Required): ObjectSchema<Subschema, Required, undefined>;
|
|
32
93
|
function Object<Subschema extends ObjectSubschema, Required extends boolean, Default extends DefaultValue<ObjectSource<Subschema>>>(subschema: Subschema, required: Required, defaultValue: Default): ObjectSchema<Subschema, Required, Default>;
|
|
94
|
+
/**
|
|
95
|
+
* Creates a schema used to validate an object.
|
|
96
|
+
*
|
|
97
|
+
* This function can be used to create schemas that describe a value's object hierarchy.
|
|
98
|
+
*
|
|
99
|
+
* @note This function creates schemas that differ from that of `$.Object` in that the values validated by schemas created by this function
|
|
100
|
+
* will RETAIN the properties not specified by the schema.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* $.LenientObject({ name: $.String() }).validate({ name: "Jeremy", age: 1 })
|
|
105
|
+
* ```
|
|
106
|
+
* ->
|
|
107
|
+
* ```ts
|
|
108
|
+
* { "name": "Jeremy", "age": 1 }
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* @param subschema An object describing keys and values that must be present amongst any other keys and values within an object.
|
|
112
|
+
* @param required Flag representing whether the schema should enforce a value's presence.
|
|
113
|
+
* @param defaultValue A default the schema will use during validation if a value is not present.
|
|
114
|
+
* @returns A schema used to validate an object.
|
|
115
|
+
*/
|
|
116
|
+
function LenientObject<Subschema extends LenientObjectSubschema>(subschema: Subschema): LenientObjectSchema<Subschema, LenientObjectSource<Subschema>, LenientObjectModel<Subschema>, true, undefined>;
|
|
117
|
+
function LenientObject<Subschema extends LenientObjectSubschema, Required extends boolean>(subschema: Subschema, required: Required): LenientObjectSchema<Subschema, LenientObjectSource<Subschema>, LenientObjectModel<Subschema>, Required, undefined>;
|
|
118
|
+
function LenientObject<Subschema extends LenientObjectSubschema, Required extends boolean, Default extends DefaultValue<LenientObjectSource<Subschema>>>(subschema: Subschema, required: Required, defaultValue: Default): LenientObjectSchema<Subschema, LenientObjectSource<Subschema>, LenientObjectModel<Subschema>, Required, Default>;
|
|
119
|
+
/**
|
|
120
|
+
* Creates a schema used to validate an object.
|
|
121
|
+
*
|
|
122
|
+
* This function can be used to create schemas that describe a value's object hierarchy.
|
|
123
|
+
*
|
|
124
|
+
* @note This function creates schemas that differ from that of `$.Object` in that schemas created by this function can have ANY string keys
|
|
125
|
+
* and only their values will be validated against the supplied `subschema`.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```ts
|
|
129
|
+
* $.DynamicObject($.String()).validate({ name: "Jeremy", age: 1, randomKey: true })
|
|
130
|
+
* ```
|
|
131
|
+
* ->
|
|
132
|
+
* ```ts
|
|
133
|
+
* { "name": "Jeremy", "age": "1", "randomKey": "true" }
|
|
134
|
+
* ```
|
|
135
|
+
*
|
|
136
|
+
* @param subschema Schema used to validate values within an object with dynamic keys.
|
|
137
|
+
* @param required Flag representing whether the schema should enforce a value's presence.
|
|
138
|
+
* @param defaultValue A default the schema will use during validation if a value is not present.
|
|
139
|
+
* @returns A schema used to validate an object.
|
|
140
|
+
*/
|
|
141
|
+
function DynamicObject<Subschema extends BaseSchemaAny>(subschema: Subschema): DynamicObjectSchema<Subschema, true, undefined>;
|
|
142
|
+
function DynamicObject<Subschema extends BaseSchemaAny, Required extends boolean>(subschema: Subschema, required: Required): DynamicObjectSchema<Subschema, Required, undefined>;
|
|
143
|
+
function DynamicObject<Subschema extends BaseSchemaAny, Required extends boolean, Default extends DefaultValue<DynamicObjectSource<Subschema>>>(subschema: Subschema, required: Required, defaultValue: Default): DynamicObjectSchema<Subschema, Required, Default>;
|
|
33
144
|
function Array<Subschema extends BaseSchemaAny>(subschema: Subschema): ArraySchema<Subschema, true, undefined>;
|
|
34
145
|
function Array<Subschema extends BaseSchemaAny, Required extends boolean>(subschema: Subschema, required: Required): ArraySchema<Subschema, Required, undefined>;
|
|
35
146
|
function Array<Subschema extends BaseSchemaAny, Required extends boolean, Default extends DefaultValue<ArraySource<Subschema>>>(subschema: Subschema, required: Required, defaultValue: Default): ArraySchema<Subschema, Required, Default>;
|
|
36
147
|
function Enumeration<Member extends string>(subschema: TypedMembers<Member>): EnumerationSchema<Member, true, undefined>;
|
|
37
148
|
function Enumeration<Member extends string, Required extends boolean>(subschema: TypedMembers<Member>, required: Required): EnumerationSchema<Member, Required, undefined>;
|
|
38
149
|
function Enumeration<Member extends string, Required extends boolean, Default extends DefaultValue<Member>>(subschema: TypedMembers<Member>, required: Required, defaultValue: Default): EnumerationSchema<Member, Required, Default>;
|
|
39
|
-
function DynamicObject<Subschema extends BaseSchemaAny>(subschema: Subschema): DynamicObjectSchema<Subschema, true, undefined>;
|
|
40
|
-
function DynamicObject<Subschema extends BaseSchemaAny, Required extends boolean>(subschema: Subschema, required: Required): DynamicObjectSchema<Subschema, Required, undefined>;
|
|
41
|
-
function DynamicObject<Subschema extends BaseSchemaAny, Required extends boolean, Default extends DefaultValue<DynamicObjectSource<Subschema>>>(subschema: Subschema, required: Required, defaultValue: Default): DynamicObjectSchema<Subschema, Required, Default>;
|
|
42
150
|
function OrSet<MemberSchema extends BaseSchemaAny>(subschema: TypedMembers<MemberSchema>): OrSetSchema<MemberSchema, true, undefined>;
|
|
43
151
|
function OrSet<MemberSchema extends BaseSchemaAny, Required extends boolean>(subschema: TypedMembers<MemberSchema>, required: Required): OrSetSchema<MemberSchema, Required, undefined>;
|
|
44
152
|
function OrSet<MemberSchema extends BaseSchemaAny, Required extends boolean, Default extends DefaultValue<OrSetSchemaSource<MemberSchema>>>(subschema: TypedMembers<MemberSchema>, required: Required, defaultValue: Default): OrSetSchema<MemberSchema, Required, Default>;
|
|
153
|
+
function Constant<Constant extends ConstantSource>(constant: Constant): ConstantSchema<Constant, true, undefined>;
|
|
154
|
+
function Constant<Constant extends ConstantSource, Required extends boolean>(constant: Constant, required: Required): ConstantSchema<Constant, Required, undefined>;
|
|
155
|
+
function Constant<Constant extends ConstantSource, Required extends boolean, Default extends DefaultValue<Constant>>(constant: Constant, required: Required, defaultValue: Default): ConstantSchema<Constant, Required, Default>;
|
|
45
156
|
type TypedMembers<Member extends any> = {
|
|
46
157
|
$members: Member[];
|
|
47
158
|
};
|
package/build/index.d.ts
CHANGED
|
@@ -5,9 +5,11 @@ export * from "./schema/AnySchema";
|
|
|
5
5
|
export * from "./schema/ArraySchema";
|
|
6
6
|
export * from "./schema/BaseSchema";
|
|
7
7
|
export * from "./schema/BooleanSchema";
|
|
8
|
+
export * from "./schema/ConstantSchema";
|
|
8
9
|
export * from "./schema/DateSchema";
|
|
9
10
|
export * from "./schema/DynamicObjectSchema";
|
|
10
11
|
export * from "./schema/EnumerationSchema";
|
|
12
|
+
export * from "./schema/LenientObject";
|
|
11
13
|
export * from "./schema/NumberSchema";
|
|
12
14
|
export * from "./schema/ObjectSchema";
|
|
13
15
|
export * from "./schema/OrSetSchema";
|
package/build/index.js
CHANGED
|
@@ -99,28 +99,32 @@
|
|
|
99
99
|
};
|
|
100
100
|
try {
|
|
101
101
|
result = this._executeAdditionalValidator(result, pass, "beforeAll");
|
|
102
|
+
// Handle Default
|
|
102
103
|
result = this._executeAdditionalValidator(result, pass, "beforeDefault");
|
|
103
104
|
if (!BaseSchema.isPresent(result) && this.hasDefault()) {
|
|
104
105
|
result = this.getDefault(pass);
|
|
105
106
|
}
|
|
106
107
|
result = this._executeAdditionalValidator(result, pass, "afterDefault");
|
|
107
|
-
|
|
108
|
-
if (BaseSchema.isPresent(result)) {
|
|
109
|
-
if (
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
result = this._validate(result, presentOptions, pass);
|
|
113
|
-
result = this._executeAdditionalValidator(result, pass, "afterConversion");
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
if (this._required) {
|
|
117
|
-
throw pass.causeError(pass.path.length > 0 ? `Missing required value at "${pass.path.join(".")}".` : "Missing required value.");
|
|
108
|
+
// Handle Required
|
|
109
|
+
if (!BaseSchema.isPresent(result)) {
|
|
110
|
+
if (this.isRequired()) {
|
|
111
|
+
throw pass.causeError(pass.path.length > 0 ? `Missing required ${this.type} at path "${pass.path.join(".")}".` : `Missing required ${this.type}.`);
|
|
118
112
|
}
|
|
119
113
|
else {
|
|
120
114
|
result = undefined;
|
|
121
115
|
}
|
|
122
116
|
}
|
|
123
|
-
|
|
117
|
+
// Handle Conversion
|
|
118
|
+
if (result !== undefined) {
|
|
119
|
+
result = this._executeAdditionalValidator(result, pass, "beforeConversion");
|
|
120
|
+
if (BaseSchema.getType(result) !== this.type) {
|
|
121
|
+
result = this.convert(result, pass);
|
|
122
|
+
}
|
|
123
|
+
result = this._executeAdditionalValidator(result, pass, "afterConversion");
|
|
124
|
+
}
|
|
125
|
+
// Handle Validation
|
|
126
|
+
if (this.isRequired() || result !== undefined) {
|
|
127
|
+
result = this._validate(result, presentOptions, pass);
|
|
124
128
|
result = this._executeAdditionalValidator(result, pass, "afterAll");
|
|
125
129
|
}
|
|
126
130
|
}
|
|
@@ -245,12 +249,12 @@
|
|
|
245
249
|
}
|
|
246
250
|
}
|
|
247
251
|
/**
|
|
248
|
-
* Checks to see if a value is present. (Not
|
|
252
|
+
* Checks to see if a value is present. (Not undefined)
|
|
249
253
|
* @param value The value to check the presence of.
|
|
250
|
-
* @returns true if value is
|
|
254
|
+
* @returns true if value is undefined, false otherwise.
|
|
251
255
|
*/
|
|
252
256
|
static isPresent(value) {
|
|
253
|
-
return value !== undefined
|
|
257
|
+
return value !== undefined;
|
|
254
258
|
}
|
|
255
259
|
static getType(value) {
|
|
256
260
|
if (value === null) {
|
|
@@ -369,6 +373,31 @@
|
|
|
369
373
|
}
|
|
370
374
|
}
|
|
371
375
|
|
|
376
|
+
class ConstantSchema extends BaseSchema {
|
|
377
|
+
value;
|
|
378
|
+
constructor(subschema, required, defaultValue, additionalValidationPasses) {
|
|
379
|
+
super(required, defaultValue, additionalValidationPasses);
|
|
380
|
+
this.value = subschema;
|
|
381
|
+
}
|
|
382
|
+
get type() { return BaseSchema.getType(this.value); }
|
|
383
|
+
_validate(source, options, pass) {
|
|
384
|
+
pass.assert(this.value === source, `Supplied source (${JSON.stringify(source)}) did not match expected constant value (${JSON.stringify(this.value)}).`);
|
|
385
|
+
return source;
|
|
386
|
+
}
|
|
387
|
+
convert(value, pass) {
|
|
388
|
+
return value;
|
|
389
|
+
}
|
|
390
|
+
clone() {
|
|
391
|
+
return new ConstantSchema(this.value, this._required, this._default, this._additionalValidationPasses);
|
|
392
|
+
}
|
|
393
|
+
getJsonSchema() {
|
|
394
|
+
return {
|
|
395
|
+
type: "string",
|
|
396
|
+
description: this._getJsonSchemaDescription(),
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
372
401
|
const StandardDate = globalThis.Date;
|
|
373
402
|
class DateSchema extends BaseSchema {
|
|
374
403
|
get type() { return "Date"; }
|
|
@@ -500,6 +529,97 @@
|
|
|
500
529
|
}
|
|
501
530
|
}
|
|
502
531
|
|
|
532
|
+
class LenientObjectSchema extends BaseSchema {
|
|
533
|
+
subschema;
|
|
534
|
+
constructor(subschema, required, defaultValue, additionalValidationPasses) {
|
|
535
|
+
super(required, defaultValue, additionalValidationPasses);
|
|
536
|
+
this.subschema = subschema;
|
|
537
|
+
}
|
|
538
|
+
get type() { return "object"; }
|
|
539
|
+
_validate(source, options, pass) {
|
|
540
|
+
const inputObject = source;
|
|
541
|
+
let outputObject = { ...inputObject };
|
|
542
|
+
for (const key in this.subschema) {
|
|
543
|
+
const nestedSchema = this.subschema[key];
|
|
544
|
+
const nestedValue = inputObject[key];
|
|
545
|
+
outputObject[key] = this.subschema[key].validate(inputObject[key], options, pass.next([...pass.path, key], nestedSchema, nestedValue));
|
|
546
|
+
}
|
|
547
|
+
return outputObject;
|
|
548
|
+
}
|
|
549
|
+
convert(value, pass) {
|
|
550
|
+
pass.assert(typeof value === "object", `Unable to convert ${LenientObjectSchema.getType(value)} to object.`);
|
|
551
|
+
const inputObject = value;
|
|
552
|
+
const outputObject = { ...inputObject };
|
|
553
|
+
for (const key in this.subschema) {
|
|
554
|
+
const nestedSchema = this.subschema[key];
|
|
555
|
+
const nestedValue = inputObject[key];
|
|
556
|
+
outputObject[key] = nestedSchema.convert(nestedValue, pass.next([...pass.path, key], nestedSchema, nestedValue));
|
|
557
|
+
}
|
|
558
|
+
return outputObject;
|
|
559
|
+
}
|
|
560
|
+
// Works at runtime, can't figure out typing.
|
|
561
|
+
// public extend<
|
|
562
|
+
// ExtensionSubschema extends LenientObjectSubschema,
|
|
563
|
+
// ExtensionSource extends LenientObjectSource<ExtensionSubschema>,
|
|
564
|
+
// ExtensionModel extends LenientObjectModel<ExtensionSubschema>,
|
|
565
|
+
// ExtensionDefault extends DefaultValue<ExtensionSource>
|
|
566
|
+
// >(schema: LenientObjectSchema<ExtensionSubschema, ExtensionSource, ExtensionModel, Required, ExtensionDefault>):
|
|
567
|
+
// // LenientObjectSchema<ExtensionSubschema & Subschema, ExtensionSource & Source, ExtensionModel & Model, Required, DefaultValue<ExtensionSource & Source>>
|
|
568
|
+
// ExtendedLenientObjectSchema<this, LenientObjectSchema<ExtensionSubschema, ExtensionSource, ExtensionModel, Required, ExtensionDefault>> {
|
|
569
|
+
// let defaultValue: any = undefined;
|
|
570
|
+
// if (this.hasDefault() !== schema.hasDefault()) {
|
|
571
|
+
// throw new Error("Both or neither default values must be specified in order to extend a schema!");
|
|
572
|
+
// }
|
|
573
|
+
// if (this.hasDefault() && schema.hasDefault()) {
|
|
574
|
+
// defaultValue = (pass: ValidationPass) => {
|
|
575
|
+
// return {
|
|
576
|
+
// ...this.getDefault(pass),
|
|
577
|
+
// ...schema.getDefault(pass)
|
|
578
|
+
// };
|
|
579
|
+
// };
|
|
580
|
+
// }
|
|
581
|
+
// const subschema: any = { ...this.subschema };
|
|
582
|
+
// for (const key in schema.subschema) {
|
|
583
|
+
// if (key in this.subschema) {
|
|
584
|
+
// this.subschema[key].extend(schema.subschema[key]);
|
|
585
|
+
// } else {
|
|
586
|
+
// subschema[key] = schema.subschema[key];
|
|
587
|
+
// }
|
|
588
|
+
// }
|
|
589
|
+
// return new LenientObjectSchema(subschema, this._required, defaultValue) as any;
|
|
590
|
+
// }
|
|
591
|
+
getJsonSchema() {
|
|
592
|
+
const properties = {};
|
|
593
|
+
for (const key in this.subschema) {
|
|
594
|
+
properties[key] = this.subschema[key].getJsonSchema();
|
|
595
|
+
}
|
|
596
|
+
return {
|
|
597
|
+
type: "object",
|
|
598
|
+
description: this._getJsonSchemaDescription(),
|
|
599
|
+
properties
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
clone() {
|
|
603
|
+
const subschema = {};
|
|
604
|
+
for (const key in this.subschema) {
|
|
605
|
+
subschema[key] = this.subschema[key].clone();
|
|
606
|
+
}
|
|
607
|
+
return new LenientObjectSchema(subschema, this._required, this._default, this._additionalValidationPasses);
|
|
608
|
+
}
|
|
609
|
+
toString(level = 0) {
|
|
610
|
+
const indent = " ";
|
|
611
|
+
const prefix = indent.repeat(level);
|
|
612
|
+
const pieces = [];
|
|
613
|
+
pieces.push(`${super.toString()}({\n`);
|
|
614
|
+
for (const schemaKey in this.subschema) {
|
|
615
|
+
const subschema = this.subschema[schemaKey];
|
|
616
|
+
pieces.push(`${prefix}${indent}${schemaKey}: ${subschema.toString(level + 1)}\n`);
|
|
617
|
+
}
|
|
618
|
+
pieces.push(`${prefix}})`);
|
|
619
|
+
return pieces.join("");
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
503
623
|
class NumberSchema extends BaseSchema {
|
|
504
624
|
get type() { return "number"; }
|
|
505
625
|
_validate(source, options, pass) {
|
|
@@ -587,21 +707,6 @@
|
|
|
587
707
|
}
|
|
588
708
|
return model;
|
|
589
709
|
}
|
|
590
|
-
extend(schema) {
|
|
591
|
-
let defaultValue = undefined;
|
|
592
|
-
if (this.hasDefault() !== schema.hasDefault()) {
|
|
593
|
-
throw new Error("Both or neither default values must be specified in order to extend a schema!");
|
|
594
|
-
}
|
|
595
|
-
if (this.hasDefault() && schema.hasDefault()) {
|
|
596
|
-
defaultValue = (pass) => {
|
|
597
|
-
return {
|
|
598
|
-
...this.getDefault(pass),
|
|
599
|
-
...schema.getDefault(pass)
|
|
600
|
-
};
|
|
601
|
-
};
|
|
602
|
-
}
|
|
603
|
-
return new ObjectSchema({ ...this.subschema, ...schema.subschema }, this._required, defaultValue);
|
|
604
|
-
}
|
|
605
710
|
getJsonSchema() {
|
|
606
711
|
const properties = {};
|
|
607
712
|
for (const key in this.subschema) {
|
|
@@ -644,34 +749,52 @@
|
|
|
644
749
|
return "string";
|
|
645
750
|
}
|
|
646
751
|
_validate(source, options, pass) {
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
try {
|
|
654
|
-
if (BaseSchema.getType(result) === schema.type) {
|
|
655
|
-
result = schema.validate(result, options, pass);
|
|
656
|
-
done = true;
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
catch (error) {
|
|
660
|
-
if (error instanceof Error) {
|
|
661
|
-
failureMessages.push(`Schema #${i + 1}: ${error.message}`);
|
|
662
|
-
}
|
|
663
|
-
else {
|
|
664
|
-
failureMessages.push(`Schema #${i + 1}: ${String(error)}`);
|
|
665
|
-
}
|
|
752
|
+
const errors = {};
|
|
753
|
+
for (let i = 0; i < this.schemas.length; i++) {
|
|
754
|
+
const schema = this.schemas[i];
|
|
755
|
+
try {
|
|
756
|
+
if (BaseSchema.getType(source) !== schema.type) {
|
|
757
|
+
throw new ValidationError(new ValidationPass(schema, source, undefined), `Conversions for schemas in an OrSet are disabled.`);
|
|
666
758
|
}
|
|
759
|
+
return schema.validate(source);
|
|
667
760
|
}
|
|
668
|
-
|
|
669
|
-
|
|
761
|
+
catch (error) {
|
|
762
|
+
errors[i] = error;
|
|
670
763
|
}
|
|
671
|
-
pass.assert(failureMessages.length === 0, `Provided value (${BaseSchema.getType(result)}) matched no schemas ` +
|
|
672
|
-
`(${this.schemas.map((schema) => schema.type).join(", ")}).\n${failureMessages.join("\n")}`);
|
|
673
764
|
}
|
|
674
|
-
|
|
765
|
+
const errorMessages = Object.entries(errors).map(([index, error]) => `Schema #${parseInt(index) + 1}: ${error === undefined ? "Unknown error." : error.message}`);
|
|
766
|
+
throw pass.causeError(`Provided value (${BaseSchema.getType(source)}) matched no schemas ` +
|
|
767
|
+
`(${this.schemas.map((schema) => schema.type).join(", ")}).\n` +
|
|
768
|
+
`${errorMessages.join("\n")}`);
|
|
769
|
+
// let result = source;
|
|
770
|
+
// if (result !== undefined) {
|
|
771
|
+
// let done = false;
|
|
772
|
+
// const failureMessages: string[] = [];
|
|
773
|
+
// for (let i = 0; i < this.schemas.length && !done; i++) {
|
|
774
|
+
// const schema = this.schemas[i];
|
|
775
|
+
// try {
|
|
776
|
+
// if (BaseSchema.getType(result) === schema.type) {
|
|
777
|
+
// result = schema.validate(result, options, pass);
|
|
778
|
+
// done = true;
|
|
779
|
+
// }
|
|
780
|
+
// } catch (error) {
|
|
781
|
+
// if (error instanceof Error) {
|
|
782
|
+
// failureMessages.push(`Schema #${i + 1}: ${error.message}`);
|
|
783
|
+
// } else {
|
|
784
|
+
// failureMessages.push(`Schema #${i + 1}: ${String(error)}`);
|
|
785
|
+
// }
|
|
786
|
+
// }
|
|
787
|
+
// }
|
|
788
|
+
// if (!done) {
|
|
789
|
+
// failureMessages.push(`Conversions for schemas in an OrSet are disabled.`);
|
|
790
|
+
// }
|
|
791
|
+
// pass.assert(
|
|
792
|
+
// failureMessages.length === 0,
|
|
793
|
+
// `Provided value (${BaseSchema.getType(result)}) matched no schemas ` +
|
|
794
|
+
// `(${this.schemas.map((schema) => schema.type).join(", ")}).\n${failureMessages.join("\n")}`
|
|
795
|
+
// );
|
|
796
|
+
// }
|
|
797
|
+
// return result;
|
|
675
798
|
}
|
|
676
799
|
convert(value, pass) {
|
|
677
800
|
return value;
|
|
@@ -753,6 +876,9 @@
|
|
|
753
876
|
}
|
|
754
877
|
}
|
|
755
878
|
|
|
879
|
+
/**
|
|
880
|
+
* A collection of helper functions used to create the standard set of schemas.
|
|
881
|
+
*/
|
|
756
882
|
exports.Schema = void 0;
|
|
757
883
|
(function (Schema) {
|
|
758
884
|
function String(required = true, defaultValue = undefined) {
|
|
@@ -779,6 +905,14 @@
|
|
|
779
905
|
return new ObjectSchema(subschema, required, defaultValue);
|
|
780
906
|
}
|
|
781
907
|
Schema.Object = Object;
|
|
908
|
+
function LenientObject(subschema, required = true, defaultValue = undefined) {
|
|
909
|
+
return new LenientObjectSchema(subschema, required, defaultValue);
|
|
910
|
+
}
|
|
911
|
+
Schema.LenientObject = LenientObject;
|
|
912
|
+
function DynamicObject(subschema, required = true, defaultValue = undefined) {
|
|
913
|
+
return new DynamicObjectSchema(subschema, required, defaultValue);
|
|
914
|
+
}
|
|
915
|
+
Schema.DynamicObject = DynamicObject;
|
|
782
916
|
function Array(subschema, required = true, defaultValue = undefined) {
|
|
783
917
|
return new ArraySchema(subschema, required, defaultValue);
|
|
784
918
|
}
|
|
@@ -787,14 +921,14 @@
|
|
|
787
921
|
return new EnumerationSchema(members.$members, required, defaultValue);
|
|
788
922
|
}
|
|
789
923
|
Schema.Enumeration = Enumeration;
|
|
790
|
-
function DynamicObject(subschema, required = true, defaultValue = undefined) {
|
|
791
|
-
return new DynamicObjectSchema(subschema, required, defaultValue);
|
|
792
|
-
}
|
|
793
|
-
Schema.DynamicObject = DynamicObject;
|
|
794
924
|
function OrSet(members, required = true, defaultValue = undefined) {
|
|
795
925
|
return new OrSetSchema(members.$members, required, defaultValue);
|
|
796
926
|
}
|
|
797
927
|
Schema.OrSet = OrSet;
|
|
928
|
+
function Constant(value, required = true, defaultValue = undefined) {
|
|
929
|
+
return new ConstantSchema(value, required, defaultValue);
|
|
930
|
+
}
|
|
931
|
+
Schema.Constant = Constant;
|
|
798
932
|
function Members(...members) {
|
|
799
933
|
/*
|
|
800
934
|
* HACK START: The hermes JS engine doesn't use globalThis.Array when interpreting `...members`
|
|
@@ -823,9 +957,11 @@
|
|
|
823
957
|
exports.ArraySchema = ArraySchema;
|
|
824
958
|
exports.BaseSchema = BaseSchema;
|
|
825
959
|
exports.BooleanSchema = BooleanSchema;
|
|
960
|
+
exports.ConstantSchema = ConstantSchema;
|
|
826
961
|
exports.DateSchema = DateSchema;
|
|
827
962
|
exports.DynamicObjectSchema = DynamicObjectSchema;
|
|
828
963
|
exports.EnumerationSchema = EnumerationSchema;
|
|
964
|
+
exports.LenientObjectSchema = LenientObjectSchema;
|
|
829
965
|
exports.NumberSchema = NumberSchema;
|
|
830
966
|
exports.ObjectSchema = ObjectSchema;
|
|
831
967
|
exports.OrSetSchema = OrSetSchema;
|
|
@@ -8,6 +8,17 @@ export declare abstract class BaseSchema<Source, Model, Required extends boolean
|
|
|
8
8
|
constructor(required: Required, defaultValue: Default, additionalValidationPasses?: AdditionalValidationPasses<Source, Model>);
|
|
9
9
|
abstract get type(): string;
|
|
10
10
|
validate(source: SourceValue<Source, Required, Default>, options?: OptionalValidationOptions, pass?: ValidationPass): ModelValue<Source, Model, Required, Default>;
|
|
11
|
+
/**
|
|
12
|
+
* Responsible for validating that a supplied source matches the schema this class represents.
|
|
13
|
+
*
|
|
14
|
+
* Some assumptions can be made about `source`:
|
|
15
|
+
* * It will never be `null`/`undefined`.
|
|
16
|
+
* * Its type returned by `BaseSchema.getType` will match that of this classes `type` property.
|
|
17
|
+
*
|
|
18
|
+
* @param source Source to be validated.
|
|
19
|
+
* @param options Validation options.
|
|
20
|
+
* @param pass Validation pass.
|
|
21
|
+
*/
|
|
11
22
|
protected abstract _validate(source: ModelValue<Source, Model, Required, Default>, options: ValidationOptions, pass: ValidationPass): ModelValue<Source, Model, Required, Default>;
|
|
12
23
|
abstract convert(value: Source, pass: ValidationPass): Model;
|
|
13
24
|
custom(additionalValidator: AdditionalValidator<SourceValue<Source, Required, Default>>, type: AdditionalValidatorBeforeType): this;
|
|
@@ -47,10 +58,10 @@ export declare abstract class BaseSchema<Source, Model, Required extends boolean
|
|
|
47
58
|
*/
|
|
48
59
|
toString(level?: number): string;
|
|
49
60
|
/**
|
|
50
|
-
* Checks to see if a value is present. (Not
|
|
61
|
+
* Checks to see if a value is present. (Not undefined)
|
|
51
62
|
* @param value The value to check the presence of.
|
|
52
|
-
* @returns true if value is
|
|
63
|
+
* @returns true if value is undefined, false otherwise.
|
|
53
64
|
*/
|
|
54
|
-
static isPresent(value: any): value is Exclude<
|
|
65
|
+
static isPresent(value: any): value is Exclude<any, undefined>;
|
|
55
66
|
static getType(value: any): any;
|
|
56
67
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ValidationPass } from "../error/ValidationPass";
|
|
2
|
+
import { AdditionalValidationPasses, DefaultValue, ModelValue, ValidationOptions } from "../typing/toolbox";
|
|
3
|
+
import { BaseSchema } from "./BaseSchema";
|
|
4
|
+
export type ConstantSource = string | number | boolean | null;
|
|
5
|
+
export declare class ConstantSchema<Constant extends ConstantSource, Required extends boolean, Default extends DefaultValue<Constant>> extends BaseSchema<Constant, Constant, Required, Default> {
|
|
6
|
+
readonly value: Constant;
|
|
7
|
+
constructor(subschema: Constant, required: Required, defaultValue: Default, additionalValidationPasses?: AdditionalValidationPasses<Constant, Constant>);
|
|
8
|
+
get type(): any;
|
|
9
|
+
protected _validate(source: ModelValue<Constant, Constant, Required, Default>, options: ValidationOptions, pass: ValidationPass): ModelValue<Constant, Constant, Required, Default>;
|
|
10
|
+
convert(value: Constant, pass: ValidationPass): Constant;
|
|
11
|
+
clone(): ConstantSchema<Constant, Required, Default>;
|
|
12
|
+
getJsonSchema(): object;
|
|
13
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ValidationPass } from "../error/ValidationPass";
|
|
2
|
+
import { BaseSchemaAny } from "../typing/extended";
|
|
3
|
+
import type { AdditionalValidationPasses, DefaultValue, Merge, ModelRequirement, ModelValue, SourceRequirement, SourceValue, ValidationOptions } from "../typing/toolbox";
|
|
4
|
+
import { BaseSchema } from "./BaseSchema";
|
|
5
|
+
export type LenientObjectSubschema = {
|
|
6
|
+
[Key: string]: BaseSchemaAny;
|
|
7
|
+
};
|
|
8
|
+
export type LenientObjectSource<Subschema extends LenientObjectSubschema> = ({
|
|
9
|
+
[Key: string]: any;
|
|
10
|
+
} & Merge<{
|
|
11
|
+
[Key in keyof Subschema as SourceRequirement<Subschema[Key]> extends true ? Key : never]: (Subschema[Key] extends BaseSchema<infer Source, any, infer Required, infer Default> ? (SourceValue<Source, Required, Default>) : never);
|
|
12
|
+
}, {
|
|
13
|
+
[Key in keyof Subschema as SourceRequirement<Subschema[Key]> extends false ? Key : never]?: (Subschema[Key] extends BaseSchema<infer Source, any, infer Required, infer Default> ? (SourceValue<Source, Required, Default>) : never);
|
|
14
|
+
}>);
|
|
15
|
+
export type LenientObjectModel<Subschema extends LenientObjectSubschema> = ({
|
|
16
|
+
[Key: string]: any;
|
|
17
|
+
} & Merge<{
|
|
18
|
+
[Key in keyof Subschema as ModelRequirement<Subschema[Key]> extends true ? Key : never]: (Subschema[Key] extends BaseSchema<infer Source, infer Model, infer Required, infer Default> ? (ModelValue<Source, Model, Required, Default>) : never);
|
|
19
|
+
}, {
|
|
20
|
+
[Key in keyof Subschema as ModelRequirement<Subschema[Key]> extends false ? Key : never]?: (Subschema[Key] extends BaseSchema<infer Source, infer Model, infer Required, infer Default> ? (ModelValue<Source, Model, Required, Default>) : never);
|
|
21
|
+
}>);
|
|
22
|
+
export declare class LenientObjectSchema<Subschema extends LenientObjectSubschema, Source extends LenientObjectSource<Subschema>, Model extends LenientObjectModel<Subschema>, Required extends boolean, Default extends DefaultValue<Source>> extends BaseSchema<Source, Model, Required, Default> {
|
|
23
|
+
readonly subschema: Subschema;
|
|
24
|
+
constructor(subschema: Subschema, required: Required, defaultValue: Default, additionalValidationPasses?: AdditionalValidationPasses<Source, Model>);
|
|
25
|
+
get type(): string;
|
|
26
|
+
protected _validate(source: ModelValue<Source, Model, Required, Default>, options: ValidationOptions, pass: ValidationPass): ModelValue<Source, Model, Required, Default>;
|
|
27
|
+
convert(value: Source, pass: ValidationPass): Model;
|
|
28
|
+
getJsonSchema(): object;
|
|
29
|
+
clone(): LenientObjectSchema<Subschema, Source, Model, Required, Default>;
|
|
30
|
+
toString(level?: number): string;
|
|
31
|
+
}
|
|
@@ -21,7 +21,6 @@ export declare class ObjectSchema<Subschema extends ObjectSubschema, Required ex
|
|
|
21
21
|
get type(): string;
|
|
22
22
|
protected _validate(source: ModelValue<ObjectSource<Subschema>, ObjectModel<Subschema>, Required, Default>, options: ValidationOptions, pass: ValidationPass): ModelValue<ObjectSource<Subschema>, ObjectModel<Subschema>, Required, Default>;
|
|
23
23
|
convert(value: ObjectSource<Subschema>, pass: ValidationPass): ObjectModel<Subschema>;
|
|
24
|
-
extend<ExtensionSubschema extends ObjectSubschema, ExtensionDefault extends DefaultValue<ObjectSource<ExtensionSubschema>>>(schema: ObjectSchema<ExtensionSubschema, Required, ExtensionDefault>): ObjectSchema<Subschema & ExtensionSubschema, Required, any>;
|
|
25
24
|
getJsonSchema(): object;
|
|
26
25
|
clone(): ObjectSchema<Subschema, Required, Default>;
|
|
27
26
|
toString(level?: number): string;
|