@lucania/schema 3.0.1 → 3.0.3
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 +203 -58
- package/build/schema/ArraySchema.d.ts +1 -1
- 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) {
|
|
@@ -315,6 +319,15 @@
|
|
|
315
319
|
else if (typeof value === "string") {
|
|
316
320
|
return [value];
|
|
317
321
|
}
|
|
322
|
+
else if (typeof value === "object") {
|
|
323
|
+
return Object.entries(value).reduce((array, [key, item]) => {
|
|
324
|
+
const index = parseInt(key);
|
|
325
|
+
pass.assert(!isNaN(index), `Unable to convert ${BaseSchema.getType(value)} to array. ` +
|
|
326
|
+
`Encountered key that is not a valid array index: "${key}"`);
|
|
327
|
+
array[index] = item;
|
|
328
|
+
return array;
|
|
329
|
+
}, []);
|
|
330
|
+
}
|
|
318
331
|
else {
|
|
319
332
|
throw pass.causeError(`Unable to convert ${BaseSchema.getType(value)} to array.`);
|
|
320
333
|
}
|
|
@@ -369,6 +382,31 @@
|
|
|
369
382
|
}
|
|
370
383
|
}
|
|
371
384
|
|
|
385
|
+
class ConstantSchema extends BaseSchema {
|
|
386
|
+
value;
|
|
387
|
+
constructor(subschema, required, defaultValue, additionalValidationPasses) {
|
|
388
|
+
super(required, defaultValue, additionalValidationPasses);
|
|
389
|
+
this.value = subschema;
|
|
390
|
+
}
|
|
391
|
+
get type() { return BaseSchema.getType(this.value); }
|
|
392
|
+
_validate(source, options, pass) {
|
|
393
|
+
pass.assert(this.value === source, `Supplied source (${JSON.stringify(source)}) did not match expected constant value (${JSON.stringify(this.value)}).`);
|
|
394
|
+
return source;
|
|
395
|
+
}
|
|
396
|
+
convert(value, pass) {
|
|
397
|
+
return value;
|
|
398
|
+
}
|
|
399
|
+
clone() {
|
|
400
|
+
return new ConstantSchema(this.value, this._required, this._default, this._additionalValidationPasses);
|
|
401
|
+
}
|
|
402
|
+
getJsonSchema() {
|
|
403
|
+
return {
|
|
404
|
+
type: "string",
|
|
405
|
+
description: this._getJsonSchemaDescription(),
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
372
410
|
const StandardDate = globalThis.Date;
|
|
373
411
|
class DateSchema extends BaseSchema {
|
|
374
412
|
get type() { return "Date"; }
|
|
@@ -500,6 +538,97 @@
|
|
|
500
538
|
}
|
|
501
539
|
}
|
|
502
540
|
|
|
541
|
+
class LenientObjectSchema extends BaseSchema {
|
|
542
|
+
subschema;
|
|
543
|
+
constructor(subschema, required, defaultValue, additionalValidationPasses) {
|
|
544
|
+
super(required, defaultValue, additionalValidationPasses);
|
|
545
|
+
this.subschema = subschema;
|
|
546
|
+
}
|
|
547
|
+
get type() { return "object"; }
|
|
548
|
+
_validate(source, options, pass) {
|
|
549
|
+
const inputObject = source;
|
|
550
|
+
let outputObject = { ...inputObject };
|
|
551
|
+
for (const key in this.subschema) {
|
|
552
|
+
const nestedSchema = this.subschema[key];
|
|
553
|
+
const nestedValue = inputObject[key];
|
|
554
|
+
outputObject[key] = this.subschema[key].validate(inputObject[key], options, pass.next([...pass.path, key], nestedSchema, nestedValue));
|
|
555
|
+
}
|
|
556
|
+
return outputObject;
|
|
557
|
+
}
|
|
558
|
+
convert(value, pass) {
|
|
559
|
+
pass.assert(typeof value === "object", `Unable to convert ${LenientObjectSchema.getType(value)} to object.`);
|
|
560
|
+
const inputObject = value;
|
|
561
|
+
const outputObject = { ...inputObject };
|
|
562
|
+
for (const key in this.subschema) {
|
|
563
|
+
const nestedSchema = this.subschema[key];
|
|
564
|
+
const nestedValue = inputObject[key];
|
|
565
|
+
outputObject[key] = nestedSchema.convert(nestedValue, pass.next([...pass.path, key], nestedSchema, nestedValue));
|
|
566
|
+
}
|
|
567
|
+
return outputObject;
|
|
568
|
+
}
|
|
569
|
+
// Works at runtime, can't figure out typing.
|
|
570
|
+
// public extend<
|
|
571
|
+
// ExtensionSubschema extends LenientObjectSubschema,
|
|
572
|
+
// ExtensionSource extends LenientObjectSource<ExtensionSubschema>,
|
|
573
|
+
// ExtensionModel extends LenientObjectModel<ExtensionSubschema>,
|
|
574
|
+
// ExtensionDefault extends DefaultValue<ExtensionSource>
|
|
575
|
+
// >(schema: LenientObjectSchema<ExtensionSubschema, ExtensionSource, ExtensionModel, Required, ExtensionDefault>):
|
|
576
|
+
// // LenientObjectSchema<ExtensionSubschema & Subschema, ExtensionSource & Source, ExtensionModel & Model, Required, DefaultValue<ExtensionSource & Source>>
|
|
577
|
+
// ExtendedLenientObjectSchema<this, LenientObjectSchema<ExtensionSubschema, ExtensionSource, ExtensionModel, Required, ExtensionDefault>> {
|
|
578
|
+
// let defaultValue: any = undefined;
|
|
579
|
+
// if (this.hasDefault() !== schema.hasDefault()) {
|
|
580
|
+
// throw new Error("Both or neither default values must be specified in order to extend a schema!");
|
|
581
|
+
// }
|
|
582
|
+
// if (this.hasDefault() && schema.hasDefault()) {
|
|
583
|
+
// defaultValue = (pass: ValidationPass) => {
|
|
584
|
+
// return {
|
|
585
|
+
// ...this.getDefault(pass),
|
|
586
|
+
// ...schema.getDefault(pass)
|
|
587
|
+
// };
|
|
588
|
+
// };
|
|
589
|
+
// }
|
|
590
|
+
// const subschema: any = { ...this.subschema };
|
|
591
|
+
// for (const key in schema.subschema) {
|
|
592
|
+
// if (key in this.subschema) {
|
|
593
|
+
// this.subschema[key].extend(schema.subschema[key]);
|
|
594
|
+
// } else {
|
|
595
|
+
// subschema[key] = schema.subschema[key];
|
|
596
|
+
// }
|
|
597
|
+
// }
|
|
598
|
+
// return new LenientObjectSchema(subschema, this._required, defaultValue) as any;
|
|
599
|
+
// }
|
|
600
|
+
getJsonSchema() {
|
|
601
|
+
const properties = {};
|
|
602
|
+
for (const key in this.subschema) {
|
|
603
|
+
properties[key] = this.subschema[key].getJsonSchema();
|
|
604
|
+
}
|
|
605
|
+
return {
|
|
606
|
+
type: "object",
|
|
607
|
+
description: this._getJsonSchemaDescription(),
|
|
608
|
+
properties
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
clone() {
|
|
612
|
+
const subschema = {};
|
|
613
|
+
for (const key in this.subschema) {
|
|
614
|
+
subschema[key] = this.subschema[key].clone();
|
|
615
|
+
}
|
|
616
|
+
return new LenientObjectSchema(subschema, this._required, this._default, this._additionalValidationPasses);
|
|
617
|
+
}
|
|
618
|
+
toString(level = 0) {
|
|
619
|
+
const indent = " ";
|
|
620
|
+
const prefix = indent.repeat(level);
|
|
621
|
+
const pieces = [];
|
|
622
|
+
pieces.push(`${super.toString()}({\n`);
|
|
623
|
+
for (const schemaKey in this.subschema) {
|
|
624
|
+
const subschema = this.subschema[schemaKey];
|
|
625
|
+
pieces.push(`${prefix}${indent}${schemaKey}: ${subschema.toString(level + 1)}\n`);
|
|
626
|
+
}
|
|
627
|
+
pieces.push(`${prefix}})`);
|
|
628
|
+
return pieces.join("");
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
503
632
|
class NumberSchema extends BaseSchema {
|
|
504
633
|
get type() { return "number"; }
|
|
505
634
|
_validate(source, options, pass) {
|
|
@@ -587,21 +716,6 @@
|
|
|
587
716
|
}
|
|
588
717
|
return model;
|
|
589
718
|
}
|
|
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
719
|
getJsonSchema() {
|
|
606
720
|
const properties = {};
|
|
607
721
|
for (const key in this.subschema) {
|
|
@@ -644,34 +758,52 @@
|
|
|
644
758
|
return "string";
|
|
645
759
|
}
|
|
646
760
|
_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
|
-
}
|
|
761
|
+
const errors = {};
|
|
762
|
+
for (let i = 0; i < this.schemas.length; i++) {
|
|
763
|
+
const schema = this.schemas[i];
|
|
764
|
+
try {
|
|
765
|
+
if (BaseSchema.getType(source) !== schema.type) {
|
|
766
|
+
throw new ValidationError(new ValidationPass(schema, source, undefined), `Conversions for schemas in an OrSet are disabled.`);
|
|
666
767
|
}
|
|
768
|
+
return schema.validate(source);
|
|
667
769
|
}
|
|
668
|
-
|
|
669
|
-
|
|
770
|
+
catch (error) {
|
|
771
|
+
errors[i] = error;
|
|
670
772
|
}
|
|
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
773
|
}
|
|
674
|
-
|
|
774
|
+
const errorMessages = Object.entries(errors).map(([index, error]) => `Schema #${parseInt(index) + 1}: ${error === undefined ? "Unknown error." : error.message}`);
|
|
775
|
+
throw pass.causeError(`Provided value (${BaseSchema.getType(source)}) matched no schemas ` +
|
|
776
|
+
`(${this.schemas.map((schema) => schema.type).join(", ")}).\n` +
|
|
777
|
+
`${errorMessages.join("\n")}`);
|
|
778
|
+
// let result = source;
|
|
779
|
+
// if (result !== undefined) {
|
|
780
|
+
// let done = false;
|
|
781
|
+
// const failureMessages: string[] = [];
|
|
782
|
+
// for (let i = 0; i < this.schemas.length && !done; i++) {
|
|
783
|
+
// const schema = this.schemas[i];
|
|
784
|
+
// try {
|
|
785
|
+
// if (BaseSchema.getType(result) === schema.type) {
|
|
786
|
+
// result = schema.validate(result, options, pass);
|
|
787
|
+
// done = true;
|
|
788
|
+
// }
|
|
789
|
+
// } catch (error) {
|
|
790
|
+
// if (error instanceof Error) {
|
|
791
|
+
// failureMessages.push(`Schema #${i + 1}: ${error.message}`);
|
|
792
|
+
// } else {
|
|
793
|
+
// failureMessages.push(`Schema #${i + 1}: ${String(error)}`);
|
|
794
|
+
// }
|
|
795
|
+
// }
|
|
796
|
+
// }
|
|
797
|
+
// if (!done) {
|
|
798
|
+
// failureMessages.push(`Conversions for schemas in an OrSet are disabled.`);
|
|
799
|
+
// }
|
|
800
|
+
// pass.assert(
|
|
801
|
+
// failureMessages.length === 0,
|
|
802
|
+
// `Provided value (${BaseSchema.getType(result)}) matched no schemas ` +
|
|
803
|
+
// `(${this.schemas.map((schema) => schema.type).join(", ")}).\n${failureMessages.join("\n")}`
|
|
804
|
+
// );
|
|
805
|
+
// }
|
|
806
|
+
// return result;
|
|
675
807
|
}
|
|
676
808
|
convert(value, pass) {
|
|
677
809
|
return value;
|
|
@@ -753,6 +885,9 @@
|
|
|
753
885
|
}
|
|
754
886
|
}
|
|
755
887
|
|
|
888
|
+
/**
|
|
889
|
+
* A collection of helper functions used to create the standard set of schemas.
|
|
890
|
+
*/
|
|
756
891
|
exports.Schema = void 0;
|
|
757
892
|
(function (Schema) {
|
|
758
893
|
function String(required = true, defaultValue = undefined) {
|
|
@@ -779,6 +914,14 @@
|
|
|
779
914
|
return new ObjectSchema(subschema, required, defaultValue);
|
|
780
915
|
}
|
|
781
916
|
Schema.Object = Object;
|
|
917
|
+
function LenientObject(subschema, required = true, defaultValue = undefined) {
|
|
918
|
+
return new LenientObjectSchema(subschema, required, defaultValue);
|
|
919
|
+
}
|
|
920
|
+
Schema.LenientObject = LenientObject;
|
|
921
|
+
function DynamicObject(subschema, required = true, defaultValue = undefined) {
|
|
922
|
+
return new DynamicObjectSchema(subschema, required, defaultValue);
|
|
923
|
+
}
|
|
924
|
+
Schema.DynamicObject = DynamicObject;
|
|
782
925
|
function Array(subschema, required = true, defaultValue = undefined) {
|
|
783
926
|
return new ArraySchema(subschema, required, defaultValue);
|
|
784
927
|
}
|
|
@@ -787,14 +930,14 @@
|
|
|
787
930
|
return new EnumerationSchema(members.$members, required, defaultValue);
|
|
788
931
|
}
|
|
789
932
|
Schema.Enumeration = Enumeration;
|
|
790
|
-
function DynamicObject(subschema, required = true, defaultValue = undefined) {
|
|
791
|
-
return new DynamicObjectSchema(subschema, required, defaultValue);
|
|
792
|
-
}
|
|
793
|
-
Schema.DynamicObject = DynamicObject;
|
|
794
933
|
function OrSet(members, required = true, defaultValue = undefined) {
|
|
795
934
|
return new OrSetSchema(members.$members, required, defaultValue);
|
|
796
935
|
}
|
|
797
936
|
Schema.OrSet = OrSet;
|
|
937
|
+
function Constant(value, required = true, defaultValue = undefined) {
|
|
938
|
+
return new ConstantSchema(value, required, defaultValue);
|
|
939
|
+
}
|
|
940
|
+
Schema.Constant = Constant;
|
|
798
941
|
function Members(...members) {
|
|
799
942
|
/*
|
|
800
943
|
* HACK START: The hermes JS engine doesn't use globalThis.Array when interpreting `...members`
|
|
@@ -823,9 +966,11 @@
|
|
|
823
966
|
exports.ArraySchema = ArraySchema;
|
|
824
967
|
exports.BaseSchema = BaseSchema;
|
|
825
968
|
exports.BooleanSchema = BooleanSchema;
|
|
969
|
+
exports.ConstantSchema = ConstantSchema;
|
|
826
970
|
exports.DateSchema = DateSchema;
|
|
827
971
|
exports.DynamicObjectSchema = DynamicObjectSchema;
|
|
828
972
|
exports.EnumerationSchema = EnumerationSchema;
|
|
973
|
+
exports.LenientObjectSchema = LenientObjectSchema;
|
|
829
974
|
exports.NumberSchema = NumberSchema;
|
|
830
975
|
exports.ObjectSchema = ObjectSchema;
|
|
831
976
|
exports.OrSetSchema = OrSetSchema;
|
|
@@ -2,7 +2,7 @@ import { ValidationPass } from "../error/ValidationPass";
|
|
|
2
2
|
import { BaseSchemaAny } from "../typing/extended";
|
|
3
3
|
import type { AdditionalValidationPasses, DefaultValue, ModelValue, SourceValue, ValidationOptions } from "../typing/toolbox";
|
|
4
4
|
import { BaseSchema } from "./BaseSchema";
|
|
5
|
-
export type ArraySource<Subschema extends BaseSchemaAny> = (Subschema extends BaseSchema<infer Source, any, infer Required, infer Default> ? (SourceValue<Source, Required, Default>[]) : never);
|
|
5
|
+
export type ArraySource<Subschema extends BaseSchemaAny> = (Subschema extends BaseSchema<infer Source, any, infer Required, infer Default> ? (Record<number, SourceValue<Source, Required, Default>> | SourceValue<Source, Required, Default>[]) : never);
|
|
6
6
|
export type ArrayModel<Subschema extends BaseSchemaAny> = (Subschema extends BaseSchema<infer Source, infer Model, infer Required, infer Default> ? (ModelValue<Source, Model, Required, Default>[]) : never);
|
|
7
7
|
export declare class ArraySchema<Subschema extends BaseSchemaAny, Required extends boolean, Default extends DefaultValue<ArraySource<Subschema>>> extends BaseSchema<ArraySource<Subschema>, ArrayModel<Subschema>, Required, Default> {
|
|
8
8
|
readonly subschema: Subschema;
|
|
@@ -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;
|