@sinclair/typebox 0.24.20 → 0.24.23
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/compiler/compiler.d.ts +1 -1
- package/compiler/compiler.js +50 -55
- package/compiler/index.d.ts +1 -1
- package/compiler/index.js +3 -0
- package/compiler/property.d.ts +4 -0
- package/compiler/property.js +64 -0
- package/error/errors.d.ts +52 -0
- package/{value → error}/errors.js +93 -43
- package/package.json +1 -1
- package/readme.md +79 -101
- package/value/index.d.ts +1 -1
- package/value/index.js +3 -0
- package/value/value.d.ts +1 -1
- package/value/value.js +1 -1
- package/value/errors.d.ts +0 -10
package/compiler/compiler.d.ts
CHANGED
package/compiler/compiler.js
CHANGED
|
@@ -28,7 +28,8 @@ THE SOFTWARE.
|
|
|
28
28
|
---------------------------------------------------------------------------*/
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
30
|
exports.TypeCompiler = exports.TypeCheck = void 0;
|
|
31
|
-
const errors_1 = require("../
|
|
31
|
+
const errors_1 = require("../error/errors");
|
|
32
|
+
const property_1 = require("./property");
|
|
32
33
|
const Types = require("../typebox");
|
|
33
34
|
// -------------------------------------------------------------------
|
|
34
35
|
// TypeCheck
|
|
@@ -61,13 +62,13 @@ exports.TypeCheck = TypeCheck;
|
|
|
61
62
|
var TypeCompiler;
|
|
62
63
|
(function (TypeCompiler) {
|
|
63
64
|
// -------------------------------------------------------------------
|
|
64
|
-
//
|
|
65
|
+
// Types
|
|
65
66
|
// -------------------------------------------------------------------
|
|
66
67
|
function* Any(schema, value) {
|
|
67
68
|
yield '(true)';
|
|
68
69
|
}
|
|
69
70
|
function* Array(schema, value) {
|
|
70
|
-
const expression =
|
|
71
|
+
const expression = CreateExpression(schema.items, 'value');
|
|
71
72
|
if (schema.minItems !== undefined)
|
|
72
73
|
yield `(${value}.length >= ${schema.minItems})`;
|
|
73
74
|
if (schema.maxItems !== undefined)
|
|
@@ -143,13 +144,14 @@ var TypeCompiler;
|
|
|
143
144
|
}
|
|
144
145
|
}
|
|
145
146
|
for (const propertyKey of propertyKeys) {
|
|
147
|
+
const memberExpression = property_1.Property.Check(propertyKey) ? `${value}.${propertyKey}` : `${value}['${propertyKey}']`;
|
|
146
148
|
const propertySchema = schema.properties[propertyKey];
|
|
147
149
|
if (schema.required && schema.required.includes(propertyKey)) {
|
|
148
|
-
yield* Visit(propertySchema,
|
|
150
|
+
yield* Visit(propertySchema, memberExpression);
|
|
149
151
|
}
|
|
150
152
|
else {
|
|
151
|
-
const
|
|
152
|
-
yield `(${
|
|
153
|
+
const expression = CreateExpression(propertySchema, memberExpression);
|
|
154
|
+
yield `(${memberExpression} === undefined ? true : (${expression}))`;
|
|
153
155
|
}
|
|
154
156
|
}
|
|
155
157
|
}
|
|
@@ -159,25 +161,16 @@ var TypeCompiler;
|
|
|
159
161
|
function* Record(schema, value) {
|
|
160
162
|
yield `(typeof ${value} === 'object' && ${value} !== null && !Array.isArray(${value}))`;
|
|
161
163
|
const [keyPattern, valueSchema] = globalThis.Object.entries(schema.patternProperties)[0];
|
|
162
|
-
const local = PushLocal(`
|
|
164
|
+
const local = PushLocal(`new RegExp(/${keyPattern}/)`);
|
|
163
165
|
yield `(Object.keys(${value}).every(key => ${local}.test(key)))`;
|
|
164
|
-
const
|
|
165
|
-
yield `(Object.values(${value}).every(value => ${
|
|
166
|
+
const expression = CreateExpression(valueSchema, 'value');
|
|
167
|
+
yield `(Object.values(${value}).every(value => ${expression}))`;
|
|
166
168
|
}
|
|
167
169
|
function* Ref(schema, value) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const reference = referenceMap.get(schema.$ref);
|
|
173
|
-
functionNames.add(schema.$ref);
|
|
174
|
-
const conditions = [...Visit(reference, 'value')];
|
|
175
|
-
const name = CreateFunctionName(schema.$ref);
|
|
176
|
-
const body = CreateFunction(name, conditions);
|
|
177
|
-
PushLocal(body);
|
|
178
|
-
}
|
|
179
|
-
const func = CreateFunctionName(schema.$ref);
|
|
180
|
-
yield `(${func}(${value}))`;
|
|
170
|
+
if (!referenceMap.has(schema.$ref))
|
|
171
|
+
throw Error(`TypeCompiler.Ref: Cannot de-reference schema with $id '${schema.$ref}'`);
|
|
172
|
+
const reference = referenceMap.get(schema.$ref);
|
|
173
|
+
yield* Visit(reference, value);
|
|
181
174
|
}
|
|
182
175
|
function* Self(schema, value) {
|
|
183
176
|
const func = CreateFunctionName(schema.$ref);
|
|
@@ -192,7 +185,7 @@ var TypeCompiler;
|
|
|
192
185
|
yield `(${value}.length <= ${schema.maxLength})`;
|
|
193
186
|
}
|
|
194
187
|
if (schema.pattern !== undefined) {
|
|
195
|
-
const local = PushLocal(`
|
|
188
|
+
const local = PushLocal(`new RegExp(/${schema.pattern}/);`);
|
|
196
189
|
yield `(${local}.test(${value}))`;
|
|
197
190
|
}
|
|
198
191
|
}
|
|
@@ -202,16 +195,16 @@ var TypeCompiler;
|
|
|
202
195
|
return yield `(${value}.length === 0)`;
|
|
203
196
|
yield `(${value}.length === ${schema.maxItems})`;
|
|
204
197
|
for (let i = 0; i < schema.items.length; i++) {
|
|
205
|
-
const
|
|
206
|
-
yield `(${
|
|
198
|
+
const expression = CreateExpression(schema.items[i], `${value}[${i}]`);
|
|
199
|
+
yield `(${expression})`;
|
|
207
200
|
}
|
|
208
201
|
}
|
|
209
202
|
function* Undefined(schema, value) {
|
|
210
203
|
yield `(${value} === undefined)`;
|
|
211
204
|
}
|
|
212
205
|
function* Union(schema, value) {
|
|
213
|
-
const
|
|
214
|
-
yield `(${
|
|
206
|
+
const expressions = schema.anyOf.map((schema) => CreateExpression(schema, value));
|
|
207
|
+
yield `(${expressions.join(' || ')})`;
|
|
215
208
|
}
|
|
216
209
|
function* Uint8Array(schema, value) {
|
|
217
210
|
yield `(${value} instanceof Uint8Array)`;
|
|
@@ -230,12 +223,11 @@ var TypeCompiler;
|
|
|
230
223
|
// reference: referenced schemas can originate from either additional
|
|
231
224
|
// schemas or inline in the schema itself. Ideally the recursive
|
|
232
225
|
// path should align to reference path. Consider for review.
|
|
233
|
-
if (schema.$id && !
|
|
234
|
-
|
|
235
|
-
const conditions = [...Visit(schema, 'value')];
|
|
226
|
+
if (schema.$id && !names.has(schema.$id)) {
|
|
227
|
+
names.add(schema.$id);
|
|
236
228
|
const name = CreateFunctionName(schema.$id);
|
|
237
|
-
const body = CreateFunction(name,
|
|
238
|
-
|
|
229
|
+
const body = CreateFunction(name, schema, 'value');
|
|
230
|
+
PushFunction(body);
|
|
239
231
|
yield `(${name}(${value}))`;
|
|
240
232
|
return;
|
|
241
233
|
}
|
|
@@ -288,17 +280,17 @@ var TypeCompiler;
|
|
|
288
280
|
}
|
|
289
281
|
}
|
|
290
282
|
// -------------------------------------------------------------------
|
|
291
|
-
//
|
|
283
|
+
// Compile State
|
|
292
284
|
// -------------------------------------------------------------------
|
|
293
285
|
const referenceMap = new Map();
|
|
294
|
-
const
|
|
295
|
-
const
|
|
296
|
-
function
|
|
297
|
-
functionLocals.clear();
|
|
298
|
-
functionNames.clear();
|
|
286
|
+
const locals = new Set(); // local variables and functions
|
|
287
|
+
const names = new Set(); // cache of local functions
|
|
288
|
+
function ResetCompiler() {
|
|
299
289
|
referenceMap.clear();
|
|
290
|
+
locals.clear();
|
|
291
|
+
names.clear();
|
|
300
292
|
}
|
|
301
|
-
function
|
|
293
|
+
function AddReferences(schemas = []) {
|
|
302
294
|
for (const schema of schemas) {
|
|
303
295
|
if (!schema.$id)
|
|
304
296
|
throw new Error(`TypeCompiler: Referenced schemas must specify an $id.`);
|
|
@@ -307,33 +299,36 @@ var TypeCompiler;
|
|
|
307
299
|
referenceMap.set(schema.$id, schema);
|
|
308
300
|
}
|
|
309
301
|
}
|
|
310
|
-
function
|
|
311
|
-
|
|
312
|
-
functionLocals.add(code.replace('local', name));
|
|
313
|
-
return name;
|
|
314
|
-
}
|
|
315
|
-
function GetLocals() {
|
|
316
|
-
return [...functionLocals.values()];
|
|
302
|
+
function CreateExpression(schema, value) {
|
|
303
|
+
return [...Visit(schema, value)].join(' && ');
|
|
317
304
|
}
|
|
318
|
-
// -------------------------------------------------------------------
|
|
319
|
-
// Functions
|
|
320
|
-
// -------------------------------------------------------------------
|
|
321
305
|
function CreateFunctionName($id) {
|
|
322
306
|
return `check_${$id.replace(/-/g, '_')}`;
|
|
323
307
|
}
|
|
324
|
-
function CreateFunction(name,
|
|
325
|
-
const expression =
|
|
308
|
+
function CreateFunction(name, schema, value) {
|
|
309
|
+
const expression = [...Visit(schema, value)].map((condition) => ` ${condition}`).join(' &&\n');
|
|
326
310
|
return `function ${name}(value) {\n return (\n${expression}\n )\n}`;
|
|
327
311
|
}
|
|
312
|
+
function PushFunction(functionBody) {
|
|
313
|
+
locals.add(functionBody);
|
|
314
|
+
}
|
|
315
|
+
function PushLocal(expression) {
|
|
316
|
+
const local = `local_${locals.size}`;
|
|
317
|
+
locals.add(`const ${local} = ${expression}`);
|
|
318
|
+
return local;
|
|
319
|
+
}
|
|
320
|
+
function GetLocals() {
|
|
321
|
+
return [...locals.values()];
|
|
322
|
+
}
|
|
328
323
|
// -------------------------------------------------------------------
|
|
329
324
|
// Compile
|
|
330
325
|
// -------------------------------------------------------------------
|
|
331
326
|
function Build(schema, references = []) {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
const
|
|
327
|
+
ResetCompiler();
|
|
328
|
+
AddReferences(references);
|
|
329
|
+
const check = CreateFunction('check', schema, 'value');
|
|
335
330
|
const locals = GetLocals();
|
|
336
|
-
return `${locals.join('\n')}\nreturn ${
|
|
331
|
+
return `${locals.join('\n')}\nreturn ${check}`;
|
|
337
332
|
}
|
|
338
333
|
/** Compiles the given type for runtime type checking. This compiler only accepts known TypeBox types non-inclusive of unsafe types. */
|
|
339
334
|
function Compile(schema, references = []) {
|
package/compiler/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { ValueError, ValueErrorType } from '../error/errors';
|
|
2
2
|
export * from './compiler';
|
package/compiler/index.js
CHANGED
|
@@ -41,4 +41,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
41
41
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
42
42
|
};
|
|
43
43
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.ValueErrorType = void 0;
|
|
45
|
+
var errors_1 = require("../error/errors");
|
|
46
|
+
Object.defineProperty(exports, "ValueErrorType", { enumerable: true, get: function () { return errors_1.ValueErrorType; } });
|
|
44
47
|
__exportStar(require("./compiler"), exports);
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*--------------------------------------------------------------------------
|
|
3
|
+
|
|
4
|
+
@sinclair/typebox/compiler
|
|
5
|
+
|
|
6
|
+
The MIT License (MIT)
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2022 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in
|
|
18
|
+
all copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
26
|
+
THE SOFTWARE.
|
|
27
|
+
|
|
28
|
+
---------------------------------------------------------------------------*/
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.Property = void 0;
|
|
31
|
+
var Property;
|
|
32
|
+
(function (Property) {
|
|
33
|
+
function DollarSign(char) {
|
|
34
|
+
return char === 36;
|
|
35
|
+
}
|
|
36
|
+
function Underscore(char) {
|
|
37
|
+
return char === 95;
|
|
38
|
+
}
|
|
39
|
+
function Numeric(char) {
|
|
40
|
+
return char >= 48 && char <= 57;
|
|
41
|
+
}
|
|
42
|
+
function Alpha(char) {
|
|
43
|
+
return (char >= 65 && char <= 90) || (char >= 97 && char <= 122);
|
|
44
|
+
}
|
|
45
|
+
/** Tests if this property name can be used in a member expression */
|
|
46
|
+
function Check(propertyName) {
|
|
47
|
+
if (propertyName.length === 0)
|
|
48
|
+
return false;
|
|
49
|
+
{
|
|
50
|
+
const code = propertyName.charCodeAt(0);
|
|
51
|
+
if (!(DollarSign(code) || Underscore(code) || Alpha(code))) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
for (let i = 1; i < propertyName.length; i++) {
|
|
56
|
+
const code = propertyName.charCodeAt(i);
|
|
57
|
+
if (!(DollarSign(code) || Underscore(code) || Alpha(code) || Numeric(code))) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
Property.Check = Check;
|
|
64
|
+
})(Property = exports.Property || (exports.Property = {}));
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as Types from '../typebox';
|
|
2
|
+
export declare enum ValueErrorType {
|
|
3
|
+
Array = 0,
|
|
4
|
+
ArrayMinItems = 1,
|
|
5
|
+
ArrayMaxItems = 2,
|
|
6
|
+
ArrayUniqueItems = 3,
|
|
7
|
+
Boolean = 4,
|
|
8
|
+
Function = 5,
|
|
9
|
+
Integer = 6,
|
|
10
|
+
IntegerMultipleOf = 7,
|
|
11
|
+
IntegerExclusiveMinimum = 8,
|
|
12
|
+
IntegerExclusiveMaximum = 9,
|
|
13
|
+
IntegerMinimum = 10,
|
|
14
|
+
IntegerMaximum = 11,
|
|
15
|
+
Literal = 12,
|
|
16
|
+
Null = 13,
|
|
17
|
+
Number = 14,
|
|
18
|
+
NumberMultipleOf = 15,
|
|
19
|
+
NumberExclusiveMinimum = 16,
|
|
20
|
+
NumberExclusiveMaximum = 17,
|
|
21
|
+
NumberMinumum = 18,
|
|
22
|
+
NumberMaximum = 19,
|
|
23
|
+
Object = 20,
|
|
24
|
+
ObjectMinProperties = 21,
|
|
25
|
+
ObjectMaxProperties = 22,
|
|
26
|
+
ObjectAdditionalProperties = 23,
|
|
27
|
+
Promise = 24,
|
|
28
|
+
RecordKeyNumeric = 25,
|
|
29
|
+
RecordKeyString = 26,
|
|
30
|
+
String = 27,
|
|
31
|
+
StringMinLength = 28,
|
|
32
|
+
StringMaxLength = 29,
|
|
33
|
+
StringPattern = 30,
|
|
34
|
+
TupleZeroLength = 31,
|
|
35
|
+
TupleLength = 32,
|
|
36
|
+
Undefined = 33,
|
|
37
|
+
Union = 34,
|
|
38
|
+
Uint8Array = 35,
|
|
39
|
+
Uint8ArrayMinByteLength = 36,
|
|
40
|
+
Uint8ArrayMaxByteLength = 37,
|
|
41
|
+
Void = 38
|
|
42
|
+
}
|
|
43
|
+
export interface ValueError {
|
|
44
|
+
type: ValueErrorType;
|
|
45
|
+
schema: Types.TSchema;
|
|
46
|
+
path: string;
|
|
47
|
+
value: unknown;
|
|
48
|
+
message: string;
|
|
49
|
+
}
|
|
50
|
+
export declare namespace ValueErrors {
|
|
51
|
+
function Errors<T extends Types.TSchema>(schema: T, references: Types.TSchema[], value: any): IterableIterator<ValueError>;
|
|
52
|
+
}
|
|
@@ -27,23 +27,71 @@ THE SOFTWARE.
|
|
|
27
27
|
|
|
28
28
|
---------------------------------------------------------------------------*/
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
-
exports.ValueErrors = void 0;
|
|
30
|
+
exports.ValueErrors = exports.ValueErrorType = void 0;
|
|
31
31
|
const Types = require("../typebox");
|
|
32
|
+
// -------------------------------------------------------------------
|
|
33
|
+
// ValueErrorType
|
|
34
|
+
// -------------------------------------------------------------------
|
|
35
|
+
var ValueErrorType;
|
|
36
|
+
(function (ValueErrorType) {
|
|
37
|
+
ValueErrorType[ValueErrorType["Array"] = 0] = "Array";
|
|
38
|
+
ValueErrorType[ValueErrorType["ArrayMinItems"] = 1] = "ArrayMinItems";
|
|
39
|
+
ValueErrorType[ValueErrorType["ArrayMaxItems"] = 2] = "ArrayMaxItems";
|
|
40
|
+
ValueErrorType[ValueErrorType["ArrayUniqueItems"] = 3] = "ArrayUniqueItems";
|
|
41
|
+
ValueErrorType[ValueErrorType["Boolean"] = 4] = "Boolean";
|
|
42
|
+
ValueErrorType[ValueErrorType["Function"] = 5] = "Function";
|
|
43
|
+
ValueErrorType[ValueErrorType["Integer"] = 6] = "Integer";
|
|
44
|
+
ValueErrorType[ValueErrorType["IntegerMultipleOf"] = 7] = "IntegerMultipleOf";
|
|
45
|
+
ValueErrorType[ValueErrorType["IntegerExclusiveMinimum"] = 8] = "IntegerExclusiveMinimum";
|
|
46
|
+
ValueErrorType[ValueErrorType["IntegerExclusiveMaximum"] = 9] = "IntegerExclusiveMaximum";
|
|
47
|
+
ValueErrorType[ValueErrorType["IntegerMinimum"] = 10] = "IntegerMinimum";
|
|
48
|
+
ValueErrorType[ValueErrorType["IntegerMaximum"] = 11] = "IntegerMaximum";
|
|
49
|
+
ValueErrorType[ValueErrorType["Literal"] = 12] = "Literal";
|
|
50
|
+
ValueErrorType[ValueErrorType["Null"] = 13] = "Null";
|
|
51
|
+
ValueErrorType[ValueErrorType["Number"] = 14] = "Number";
|
|
52
|
+
ValueErrorType[ValueErrorType["NumberMultipleOf"] = 15] = "NumberMultipleOf";
|
|
53
|
+
ValueErrorType[ValueErrorType["NumberExclusiveMinimum"] = 16] = "NumberExclusiveMinimum";
|
|
54
|
+
ValueErrorType[ValueErrorType["NumberExclusiveMaximum"] = 17] = "NumberExclusiveMaximum";
|
|
55
|
+
ValueErrorType[ValueErrorType["NumberMinumum"] = 18] = "NumberMinumum";
|
|
56
|
+
ValueErrorType[ValueErrorType["NumberMaximum"] = 19] = "NumberMaximum";
|
|
57
|
+
ValueErrorType[ValueErrorType["Object"] = 20] = "Object";
|
|
58
|
+
ValueErrorType[ValueErrorType["ObjectMinProperties"] = 21] = "ObjectMinProperties";
|
|
59
|
+
ValueErrorType[ValueErrorType["ObjectMaxProperties"] = 22] = "ObjectMaxProperties";
|
|
60
|
+
ValueErrorType[ValueErrorType["ObjectAdditionalProperties"] = 23] = "ObjectAdditionalProperties";
|
|
61
|
+
ValueErrorType[ValueErrorType["Promise"] = 24] = "Promise";
|
|
62
|
+
ValueErrorType[ValueErrorType["RecordKeyNumeric"] = 25] = "RecordKeyNumeric";
|
|
63
|
+
ValueErrorType[ValueErrorType["RecordKeyString"] = 26] = "RecordKeyString";
|
|
64
|
+
ValueErrorType[ValueErrorType["String"] = 27] = "String";
|
|
65
|
+
ValueErrorType[ValueErrorType["StringMinLength"] = 28] = "StringMinLength";
|
|
66
|
+
ValueErrorType[ValueErrorType["StringMaxLength"] = 29] = "StringMaxLength";
|
|
67
|
+
ValueErrorType[ValueErrorType["StringPattern"] = 30] = "StringPattern";
|
|
68
|
+
ValueErrorType[ValueErrorType["TupleZeroLength"] = 31] = "TupleZeroLength";
|
|
69
|
+
ValueErrorType[ValueErrorType["TupleLength"] = 32] = "TupleLength";
|
|
70
|
+
ValueErrorType[ValueErrorType["Undefined"] = 33] = "Undefined";
|
|
71
|
+
ValueErrorType[ValueErrorType["Union"] = 34] = "Union";
|
|
72
|
+
ValueErrorType[ValueErrorType["Uint8Array"] = 35] = "Uint8Array";
|
|
73
|
+
ValueErrorType[ValueErrorType["Uint8ArrayMinByteLength"] = 36] = "Uint8ArrayMinByteLength";
|
|
74
|
+
ValueErrorType[ValueErrorType["Uint8ArrayMaxByteLength"] = 37] = "Uint8ArrayMaxByteLength";
|
|
75
|
+
ValueErrorType[ValueErrorType["Void"] = 38] = "Void";
|
|
76
|
+
})(ValueErrorType = exports.ValueErrorType || (exports.ValueErrorType = {}));
|
|
77
|
+
// -------------------------------------------------------------------
|
|
78
|
+
// ValueErrors
|
|
79
|
+
// -------------------------------------------------------------------
|
|
32
80
|
var ValueErrors;
|
|
33
81
|
(function (ValueErrors) {
|
|
34
82
|
function* Any(schema, references, path, value) { }
|
|
35
83
|
function* Array(schema, references, path, value) {
|
|
36
84
|
if (!globalThis.Array.isArray(value)) {
|
|
37
|
-
return yield { schema, path, value, message: `Expected array` };
|
|
85
|
+
return yield { type: ValueErrorType.Array, schema, path, value, message: `Expected array` };
|
|
38
86
|
}
|
|
39
87
|
if (schema.minItems !== undefined && !(value.length >= schema.minItems)) {
|
|
40
|
-
yield { schema, path, value, message: `Expected array length to be greater or equal to ${schema.minItems}` };
|
|
88
|
+
yield { type: ValueErrorType.ArrayMinItems, schema, path, value, message: `Expected array length to be greater or equal to ${schema.minItems}` };
|
|
41
89
|
}
|
|
42
90
|
if (schema.maxItems !== undefined && !(value.length <= schema.maxItems)) {
|
|
43
|
-
yield { schema, path, value, message: `Expected array length to be less or equal to ${schema.maxItems}` };
|
|
91
|
+
yield { type: ValueErrorType.ArrayMinItems, schema, path, value, message: `Expected array length to be less or equal to ${schema.maxItems}` };
|
|
44
92
|
}
|
|
45
93
|
if (schema.uniqueItems === true && !(new Set(value).size === value.length)) {
|
|
46
|
-
yield { schema, path, value, message: `Expected array elements to be unique` };
|
|
94
|
+
yield { type: ValueErrorType.ArrayUniqueItems, schema, path, value, message: `Expected array elements to be unique` };
|
|
47
95
|
}
|
|
48
96
|
for (let i = 0; i < value.length; i++) {
|
|
49
97
|
yield* Visit(schema.items, references, `${path}/${i}`, value[i]);
|
|
@@ -51,7 +99,7 @@ var ValueErrors;
|
|
|
51
99
|
}
|
|
52
100
|
function* Boolean(schema, references, path, value) {
|
|
53
101
|
if (!(typeof value === 'boolean')) {
|
|
54
|
-
return yield { schema, path, value, message: `Expected boolean` };
|
|
102
|
+
return yield { type: ValueErrorType.Boolean, schema, path, value, message: `Expected boolean` };
|
|
55
103
|
}
|
|
56
104
|
}
|
|
57
105
|
function* Constructor(schema, references, path, value) {
|
|
@@ -59,78 +107,78 @@ var ValueErrors;
|
|
|
59
107
|
}
|
|
60
108
|
function* Function(schema, references, path, value) {
|
|
61
109
|
if (!(typeof value === 'function')) {
|
|
62
|
-
return yield { schema, path, value, message: `Expected function` };
|
|
110
|
+
return yield { type: ValueErrorType.Function, schema, path, value, message: `Expected function` };
|
|
63
111
|
}
|
|
64
112
|
}
|
|
65
113
|
function* Integer(schema, references, path, value) {
|
|
66
114
|
if (!(typeof value === 'number')) {
|
|
67
|
-
return yield { schema, path, value, message: `Expected number` };
|
|
115
|
+
return yield { type: ValueErrorType.Number, schema, path, value, message: `Expected number` };
|
|
68
116
|
}
|
|
69
117
|
if (!globalThis.Number.isInteger(value)) {
|
|
70
|
-
yield { schema, path, value, message: `Expected integer` };
|
|
118
|
+
yield { type: ValueErrorType.Integer, schema, path, value, message: `Expected integer` };
|
|
71
119
|
}
|
|
72
120
|
if (schema.multipleOf && !(value % schema.multipleOf === 0)) {
|
|
73
|
-
yield { schema, path, value, message: `Expected integer to be a multiple of ${schema.multipleOf}` };
|
|
121
|
+
yield { type: ValueErrorType.IntegerMultipleOf, schema, path, value, message: `Expected integer to be a multiple of ${schema.multipleOf}` };
|
|
74
122
|
}
|
|
75
123
|
if (schema.exclusiveMinimum && !(value > schema.exclusiveMinimum)) {
|
|
76
|
-
yield { schema, path, value, message: `Expected integer to be greater than ${schema.exclusiveMinimum}` };
|
|
124
|
+
yield { type: ValueErrorType.IntegerExclusiveMinimum, schema, path, value, message: `Expected integer to be greater than ${schema.exclusiveMinimum}` };
|
|
77
125
|
}
|
|
78
126
|
if (schema.exclusiveMaximum && !(value < schema.exclusiveMaximum)) {
|
|
79
|
-
yield { schema, path, value, message: `Expected integer to be less than ${schema.exclusiveMaximum}` };
|
|
127
|
+
yield { type: ValueErrorType.IntegerExclusiveMaximum, schema, path, value, message: `Expected integer to be less than ${schema.exclusiveMaximum}` };
|
|
80
128
|
}
|
|
81
129
|
if (schema.minimum && !(value >= schema.minimum)) {
|
|
82
|
-
yield { schema, path, value, message: `Expected integer to be greater or equal to ${schema.minimum}` };
|
|
130
|
+
yield { type: ValueErrorType.IntegerMinimum, schema, path, value, message: `Expected integer to be greater or equal to ${schema.minimum}` };
|
|
83
131
|
}
|
|
84
132
|
if (schema.maximum && !(value <= schema.maximum)) {
|
|
85
|
-
yield { schema, path, value, message: `Expected integer to be less or equal to ${schema.maximum}` };
|
|
133
|
+
yield { type: ValueErrorType.IntegerMaximum, schema, path, value, message: `Expected integer to be less or equal to ${schema.maximum}` };
|
|
86
134
|
}
|
|
87
135
|
}
|
|
88
136
|
function* Literal(schema, references, path, value) {
|
|
89
137
|
if (!(value === schema.const)) {
|
|
90
138
|
const error = typeof schema.const === 'string' ? `'${schema.const}'` : schema.const;
|
|
91
|
-
return yield { schema, path, value, message: `Expected ${error}` };
|
|
139
|
+
return yield { type: ValueErrorType.Literal, schema, path, value, message: `Expected ${error}` };
|
|
92
140
|
}
|
|
93
141
|
}
|
|
94
142
|
function* Null(schema, references, path, value) {
|
|
95
143
|
if (!(value === null)) {
|
|
96
|
-
return yield { schema, path, value, message: `Expected null` };
|
|
144
|
+
return yield { type: ValueErrorType.Null, schema, path, value, message: `Expected null` };
|
|
97
145
|
}
|
|
98
146
|
}
|
|
99
147
|
function* Number(schema, references, path, value) {
|
|
100
148
|
if (!(typeof value === 'number')) {
|
|
101
|
-
return yield { schema, path, value, message: `Expected number` };
|
|
149
|
+
return yield { type: ValueErrorType.Number, schema, path, value, message: `Expected number` };
|
|
102
150
|
}
|
|
103
151
|
if (schema.multipleOf && !(value % schema.multipleOf === 0)) {
|
|
104
|
-
yield { schema, path, value, message: `Expected number to be a multiple of ${schema.multipleOf}` };
|
|
152
|
+
yield { type: ValueErrorType.NumberMultipleOf, schema, path, value, message: `Expected number to be a multiple of ${schema.multipleOf}` };
|
|
105
153
|
}
|
|
106
154
|
if (schema.exclusiveMinimum && !(value > schema.exclusiveMinimum)) {
|
|
107
|
-
yield { schema, path, value, message: `Expected number to be greater than ${schema.exclusiveMinimum}` };
|
|
155
|
+
yield { type: ValueErrorType.NumberExclusiveMinimum, schema, path, value, message: `Expected number to be greater than ${schema.exclusiveMinimum}` };
|
|
108
156
|
}
|
|
109
157
|
if (schema.exclusiveMaximum && !(value < schema.exclusiveMaximum)) {
|
|
110
|
-
yield { schema, path, value, message: `Expected number to be less than ${schema.exclusiveMaximum}` };
|
|
158
|
+
yield { type: ValueErrorType.NumberExclusiveMaximum, schema, path, value, message: `Expected number to be less than ${schema.exclusiveMaximum}` };
|
|
111
159
|
}
|
|
112
160
|
if (schema.minimum && !(value >= schema.minimum)) {
|
|
113
|
-
yield { schema, path, value, message: `Expected number to be greater or equal to ${schema.minimum}` };
|
|
161
|
+
yield { type: ValueErrorType.NumberMaximum, schema, path, value, message: `Expected number to be greater or equal to ${schema.minimum}` };
|
|
114
162
|
}
|
|
115
163
|
if (schema.maximum && !(value <= schema.maximum)) {
|
|
116
|
-
yield { schema, path, value, message: `Expected number to be less or equal to ${schema.maximum}` };
|
|
164
|
+
yield { type: ValueErrorType.NumberMinumum, schema, path, value, message: `Expected number to be less or equal to ${schema.maximum}` };
|
|
117
165
|
}
|
|
118
166
|
}
|
|
119
167
|
function* Object(schema, references, path, value) {
|
|
120
168
|
if (!(typeof value === 'object' && value !== null && !globalThis.Array.isArray(value))) {
|
|
121
|
-
return yield { schema, path, value, message: `Expected object` };
|
|
169
|
+
return yield { type: ValueErrorType.Object, schema, path, value, message: `Expected object` };
|
|
122
170
|
}
|
|
123
171
|
if (schema.minProperties !== undefined && !(globalThis.Object.keys(value).length >= schema.minProperties)) {
|
|
124
|
-
yield { schema, path, value, message: `Expected object to have at least ${schema.minProperties} properties` };
|
|
172
|
+
yield { type: ValueErrorType.ObjectMinProperties, schema, path, value, message: `Expected object to have at least ${schema.minProperties} properties` };
|
|
125
173
|
}
|
|
126
174
|
if (schema.maxProperties !== undefined && !(globalThis.Object.keys(value).length <= schema.maxProperties)) {
|
|
127
|
-
yield { schema, path, value, message: `Expected object to have less than ${schema.minProperties} properties` };
|
|
175
|
+
yield { type: ValueErrorType.ObjectMaxProperties, schema, path, value, message: `Expected object to have less than ${schema.minProperties} properties` };
|
|
128
176
|
}
|
|
129
177
|
const propertyKeys = globalThis.Object.keys(schema.properties);
|
|
130
178
|
if (schema.additionalProperties === false) {
|
|
131
179
|
for (const propKey of globalThis.Object.keys(value)) {
|
|
132
180
|
if (!propertyKeys.includes(propKey)) {
|
|
133
|
-
yield { schema, path: `${path}/${propKey}`, value: value[propKey], message: 'Unexpected property' };
|
|
181
|
+
yield { type: ValueErrorType.ObjectAdditionalProperties, schema, path: `${path}/${propKey}`, value: value[propKey], message: 'Unexpected property' };
|
|
134
182
|
}
|
|
135
183
|
}
|
|
136
184
|
}
|
|
@@ -148,18 +196,20 @@ var ValueErrors;
|
|
|
148
196
|
}
|
|
149
197
|
function* Promise(schema, references, path, value) {
|
|
150
198
|
if (!(typeof value === 'object' && typeof value.then === 'function')) {
|
|
151
|
-
yield { schema, path, value, message: `Expected Promise` };
|
|
199
|
+
yield { type: ValueErrorType.Promise, schema, path, value, message: `Expected Promise` };
|
|
152
200
|
}
|
|
153
201
|
}
|
|
154
202
|
function* Record(schema, references, path, value) {
|
|
155
203
|
if (!(typeof value === 'object' && value !== null && !globalThis.Array.isArray(value))) {
|
|
156
|
-
return yield { schema, path, value, message: `Expected object` };
|
|
204
|
+
return yield { type: ValueErrorType.Object, schema, path, value, message: `Expected object` };
|
|
157
205
|
}
|
|
158
206
|
const [keyPattern, valueSchema] = globalThis.Object.entries(schema.patternProperties)[0];
|
|
159
207
|
const regex = new RegExp(keyPattern);
|
|
160
208
|
if (!globalThis.Object.keys(value).every((key) => regex.test(key))) {
|
|
161
|
-
const
|
|
162
|
-
|
|
209
|
+
const numeric = keyPattern === '^(0|[1-9][0-9]*)$';
|
|
210
|
+
const type = numeric ? ValueErrorType.RecordKeyNumeric : ValueErrorType.RecordKeyString;
|
|
211
|
+
const message = numeric ? 'Expected all object property keys to be numeric' : 'Expected all object property keys to be strings';
|
|
212
|
+
return yield { type, schema, path, value, message };
|
|
163
213
|
}
|
|
164
214
|
for (const [propKey, propValue] of globalThis.Object.entries(value)) {
|
|
165
215
|
yield* Visit(valueSchema, references, `${path}/${propKey}`, propValue);
|
|
@@ -179,30 +229,30 @@ var ValueErrors;
|
|
|
179
229
|
}
|
|
180
230
|
function* String(schema, references, path, value) {
|
|
181
231
|
if (!(typeof value === 'string')) {
|
|
182
|
-
return yield { schema, path, value, message: 'Expected string' };
|
|
232
|
+
return yield { type: ValueErrorType.String, schema, path, value, message: 'Expected string' };
|
|
183
233
|
}
|
|
184
234
|
if (schema.minLength !== undefined && !(value.length >= schema.minLength)) {
|
|
185
|
-
yield { schema, path, value, message: `Expected string length greater or equal to ${schema.minLength}` };
|
|
235
|
+
yield { type: ValueErrorType.StringMinLength, schema, path, value, message: `Expected string length greater or equal to ${schema.minLength}` };
|
|
186
236
|
}
|
|
187
237
|
if (schema.maxLength !== undefined && !(value.length <= schema.maxLength)) {
|
|
188
|
-
yield { schema, path, value, message: `Expected string length less or equal to ${schema.maxLength}` };
|
|
238
|
+
yield { type: ValueErrorType.StringMaxLength, schema, path, value, message: `Expected string length less or equal to ${schema.maxLength}` };
|
|
189
239
|
}
|
|
190
240
|
if (schema.pattern !== undefined) {
|
|
191
241
|
const regex = new RegExp(schema.pattern);
|
|
192
242
|
if (!regex.test(value)) {
|
|
193
|
-
yield { schema, path, value, message: `Expected string to match pattern ${schema.pattern}` };
|
|
243
|
+
yield { type: ValueErrorType.StringPattern, schema, path, value, message: `Expected string to match pattern ${schema.pattern}` };
|
|
194
244
|
}
|
|
195
245
|
}
|
|
196
246
|
}
|
|
197
247
|
function* Tuple(schema, references, path, value) {
|
|
198
248
|
if (!globalThis.Array.isArray(value)) {
|
|
199
|
-
return yield { schema, path, value, message: 'Expected Array' };
|
|
249
|
+
return yield { type: ValueErrorType.Array, schema, path, value, message: 'Expected Array' };
|
|
200
250
|
}
|
|
201
251
|
if (schema.items === undefined && !(value.length === 0)) {
|
|
202
|
-
return yield { schema, path, value, message: 'Expected tuple to have 0 elements' };
|
|
252
|
+
return yield { type: ValueErrorType.TupleZeroLength, schema, path, value, message: 'Expected tuple to have 0 elements' };
|
|
203
253
|
}
|
|
204
254
|
if (!(value.length === schema.maxItems)) {
|
|
205
|
-
yield { schema, path, value, message: `Expected tuple to have ${schema.maxItems} elements` };
|
|
255
|
+
yield { type: ValueErrorType.TupleLength, schema, path, value, message: `Expected tuple to have ${schema.maxItems} elements` };
|
|
206
256
|
}
|
|
207
257
|
if (!schema.items) {
|
|
208
258
|
return;
|
|
@@ -213,7 +263,7 @@ var ValueErrors;
|
|
|
213
263
|
}
|
|
214
264
|
function* Undefined(schema, references, path, value) {
|
|
215
265
|
if (!(value === undefined)) {
|
|
216
|
-
yield { schema, path, value, message: `Expected undefined` };
|
|
266
|
+
yield { type: ValueErrorType.Undefined, schema, path, value, message: `Expected undefined` };
|
|
217
267
|
}
|
|
218
268
|
}
|
|
219
269
|
function* Union(schema, references, path, value) {
|
|
@@ -228,24 +278,24 @@ var ValueErrors;
|
|
|
228
278
|
yield error;
|
|
229
279
|
}
|
|
230
280
|
if (errors.length > 0) {
|
|
231
|
-
yield { schema, path, value, message: 'Expected value of union' };
|
|
281
|
+
yield { type: ValueErrorType.Union, schema, path, value, message: 'Expected value of union' };
|
|
232
282
|
}
|
|
233
283
|
}
|
|
234
284
|
function* Uint8Array(schema, references, path, value) {
|
|
235
285
|
if (!(value instanceof globalThis.Uint8Array)) {
|
|
236
|
-
return yield { schema, path, value, message: `Expected Uint8Array` };
|
|
286
|
+
return yield { type: ValueErrorType.Uint8Array, schema, path, value, message: `Expected Uint8Array` };
|
|
237
287
|
}
|
|
238
288
|
if (schema.maxByteLength && !(value.length <= schema.maxByteLength)) {
|
|
239
|
-
yield { schema, path, value, message: `Expected Uint8Array to have a byte length less or equal to ${schema.maxByteLength}` };
|
|
289
|
+
yield { type: ValueErrorType.Uint8ArrayMaxByteLength, schema, path, value, message: `Expected Uint8Array to have a byte length less or equal to ${schema.maxByteLength}` };
|
|
240
290
|
}
|
|
241
291
|
if (schema.minByteLength && !(value.length >= schema.minByteLength)) {
|
|
242
|
-
yield { schema, path, value, message: `Expected Uint8Array to have a byte length greater or equal to ${schema.maxByteLength}` };
|
|
292
|
+
yield { type: ValueErrorType.Uint8ArrayMinByteLength, schema, path, value, message: `Expected Uint8Array to have a byte length greater or equal to ${schema.maxByteLength}` };
|
|
243
293
|
}
|
|
244
294
|
}
|
|
245
295
|
function* Unknown(schema, references, path, value) { }
|
|
246
296
|
function* Void(schema, references, path, value) {
|
|
247
297
|
if (!(value === null)) {
|
|
248
|
-
return yield { schema, path, value, message: `Expected null` };
|
|
298
|
+
return yield { type: ValueErrorType.Void, schema, path, value, message: `Expected null` };
|
|
249
299
|
}
|
|
250
300
|
}
|
|
251
301
|
function* Visit(schema, references, path, value) {
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -47,30 +47,30 @@ type T = Static<typeof T> // type T = string
|
|
|
47
47
|
|
|
48
48
|
TypeBox is a type builder library that creates in-memory JSON Schema objects that can be statically inferred as TypeScript types. The schemas produced by this library are designed to match the static type checking rules of the TypeScript compiler. TypeBox enables one to create unified types that can be statically checked by TypeScript and runtime asserted using standard JSON Schema validation.
|
|
49
49
|
|
|
50
|
-
TypeBox can be used as a simple tool to build up complex schemas or integrated into RPC or REST services to help validate data received over the wire.
|
|
50
|
+
TypeBox can be used as a simple tool to build up complex schemas or integrated into RPC or REST services to help validate JSON data received over the wire.
|
|
51
51
|
|
|
52
52
|
License MIT
|
|
53
53
|
|
|
54
54
|
## Contents
|
|
55
|
-
- [Install](#
|
|
56
|
-
- [Overview](#
|
|
57
|
-
- [Usage](#
|
|
58
|
-
- [Types](#
|
|
59
|
-
- [Modifiers](#
|
|
60
|
-
- [Options](#
|
|
61
|
-
- [Extended Types](#
|
|
62
|
-
- [Reference Types](#
|
|
63
|
-
- [Recursive Types](#
|
|
64
|
-
- [Generic Types](#
|
|
65
|
-
- [Unsafe Types](#
|
|
66
|
-
- [Conditional Types](#
|
|
67
|
-
- [Values](#
|
|
68
|
-
- [Guards](#
|
|
69
|
-
- [Strict](#
|
|
70
|
-
- [Validation](#
|
|
71
|
-
- [Compiler](#
|
|
72
|
-
- [Benchmark](#
|
|
73
|
-
- [Contribute](#
|
|
55
|
+
- [Install](#install)
|
|
56
|
+
- [Overview](#overview)
|
|
57
|
+
- [Usage](#usage)
|
|
58
|
+
- [Types](#types)
|
|
59
|
+
- [Modifiers](#modifiers)
|
|
60
|
+
- [Options](#options)
|
|
61
|
+
- [Extended Types](#extended-types)
|
|
62
|
+
- [Reference Types](#reference-types)
|
|
63
|
+
- [Recursive Types](#recursive-types)
|
|
64
|
+
- [Generic Types](#generic-types)
|
|
65
|
+
- [Unsafe Types](#unsafe-types)
|
|
66
|
+
- [Conditional Types](#conditional-types)
|
|
67
|
+
- [Values](#values)
|
|
68
|
+
- [Guards](#guards)
|
|
69
|
+
- [Strict](#strict)
|
|
70
|
+
- [Validation](#validation)
|
|
71
|
+
- [Compiler](#compiler)
|
|
72
|
+
- [Benchmark](#benchmark)
|
|
73
|
+
- [Contribute](#contribute)
|
|
74
74
|
|
|
75
75
|
<a name="Example"></a>
|
|
76
76
|
|
|
@@ -147,8 +147,6 @@ function receive(value: T) { // ... as a Type
|
|
|
147
147
|
}
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
<a name="Types"></a>
|
|
151
|
-
|
|
152
150
|
## Types
|
|
153
151
|
|
|
154
152
|
The following table outlines the TypeBox mappings between TypeScript and JSON schema.
|
|
@@ -342,7 +340,6 @@ The following table outlines the TypeBox mappings between TypeScript and JSON sc
|
|
|
342
340
|
│ │ │ │
|
|
343
341
|
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
|
|
344
342
|
```
|
|
345
|
-
<a name="Modifiers"></a>
|
|
346
343
|
|
|
347
344
|
## Modifiers
|
|
348
345
|
|
|
@@ -386,8 +383,6 @@ TypeBox provides modifiers that can be applied to an objects properties. This al
|
|
|
386
383
|
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
|
|
387
384
|
```
|
|
388
385
|
|
|
389
|
-
<a name="Options"></a>
|
|
390
|
-
|
|
391
386
|
## Options
|
|
392
387
|
|
|
393
388
|
You can pass additional JSON schema options on the last argument of any given type. The following are some examples.
|
|
@@ -403,8 +398,6 @@ const T = Type.Number({ multipleOf: 2 })
|
|
|
403
398
|
const T = Type.Array(Type.Integer(), { minItems: 5 })
|
|
404
399
|
```
|
|
405
400
|
|
|
406
|
-
<a name="Extended-Types"></a>
|
|
407
|
-
|
|
408
401
|
## Extended Types
|
|
409
402
|
|
|
410
403
|
In addition to JSON schema types, TypeBox provides several extended types that allow for `function` and `constructor` types to be composed. These additional types are not valid JSON Schema and will not validate using typical JSON Schema validation. However, these types can be used to frame JSON schema and describe callable interfaces that may receive JSON validated data. These types are as follows.
|
|
@@ -467,8 +460,6 @@ In addition to JSON schema types, TypeBox provides several extended types that a
|
|
|
467
460
|
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
|
|
468
461
|
```
|
|
469
462
|
|
|
470
|
-
<a name="Reference-Types"></a>
|
|
471
|
-
|
|
472
463
|
## Reference Types
|
|
473
464
|
|
|
474
465
|
Use `Type.Ref(...)` to create referenced types. The target type must specify an `$id`.
|
|
@@ -484,8 +475,6 @@ const R = Type.Ref(T) // const R = {
|
|
|
484
475
|
// }
|
|
485
476
|
```
|
|
486
477
|
|
|
487
|
-
<a name="Recursive-Types"></a>
|
|
488
|
-
|
|
489
478
|
## Recursive Types
|
|
490
479
|
|
|
491
480
|
Use `Type.Recursive(...)` to create recursive types.
|
|
@@ -524,11 +513,9 @@ function test(node: Node) {
|
|
|
524
513
|
}
|
|
525
514
|
```
|
|
526
515
|
|
|
527
|
-
<a name="Generic-Types"></a>
|
|
528
|
-
|
|
529
516
|
## Generic Types
|
|
530
517
|
|
|
531
|
-
|
|
518
|
+
Use functions to create generic types. The following creates a generic `Nullable<T>` type.
|
|
532
519
|
|
|
533
520
|
```typescript
|
|
534
521
|
import { Type, Static, TSchema } from '@sinclair/typebox'
|
|
@@ -556,8 +543,6 @@ const U = Nullable(Type.Number()) // const U = {
|
|
|
556
543
|
type U = Static<typeof U> // type U = number | null
|
|
557
544
|
```
|
|
558
545
|
|
|
559
|
-
<a name="Unsafe-Types"></a>
|
|
560
|
-
|
|
561
546
|
## Unsafe Types
|
|
562
547
|
|
|
563
548
|
Use `Type.Unsafe(...)` to create custom schemas with user defined inference rules.
|
|
@@ -594,12 +579,12 @@ type T = Static<typeof T> // type T = string | null
|
|
|
594
579
|
|
|
595
580
|
//--------------------------------------------------------------------------------------------
|
|
596
581
|
//
|
|
597
|
-
//
|
|
582
|
+
// StringEnum<string[]>
|
|
598
583
|
//
|
|
599
584
|
//--------------------------------------------------------------------------------------------
|
|
600
585
|
|
|
601
586
|
function StringEnum<T extends string[]>(values: [...T]) {
|
|
602
|
-
return Type.Unsafe<T[number]>({ enum: values })
|
|
587
|
+
return Type.Unsafe<T[number]>({ type: 'string', enum: values })
|
|
603
588
|
}
|
|
604
589
|
|
|
605
590
|
const T = StringEnum(['A', 'B', 'C']) // const T = {
|
|
@@ -609,8 +594,6 @@ const T = StringEnum(['A', 'B', 'C']) // const T = {
|
|
|
609
594
|
type T = Static<typeof T> // type T = 'A' | 'B' | 'C'
|
|
610
595
|
```
|
|
611
596
|
|
|
612
|
-
<a name="Conditional-Types"></a>
|
|
613
|
-
|
|
614
597
|
## Conditional Types
|
|
615
598
|
|
|
616
599
|
Use `Conditional.Extends(...)` to create conditional mapped types.
|
|
@@ -660,8 +643,6 @@ The following table shows the TypeBox mappings between TypeScript and JSON schem
|
|
|
660
643
|
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
|
|
661
644
|
```
|
|
662
645
|
|
|
663
|
-
<a name="Values"></a>
|
|
664
|
-
|
|
665
646
|
## Values
|
|
666
647
|
|
|
667
648
|
Use `Value.Create(...)` to generate values from types.
|
|
@@ -697,8 +678,6 @@ const B = Value.Cast(T, { x: 1 }) // const B = { x: 1, y: 0
|
|
|
697
678
|
const C = Value.Cast(T, { x: 1, y: 2, z: 3 }) // const C = { x: 1, y: 2 }
|
|
698
679
|
```
|
|
699
680
|
|
|
700
|
-
<a name="Guards"></a>
|
|
701
|
-
|
|
702
681
|
## Guards
|
|
703
682
|
|
|
704
683
|
Use a `TypeGuard` to test if a value meets a TypeBox type specification. Guards can be helpful when reflecting types.
|
|
@@ -716,8 +695,6 @@ if(TypeGuard.TString(T)) {
|
|
|
716
695
|
|
|
717
696
|
```
|
|
718
697
|
|
|
719
|
-
<a name="Strict"></a>
|
|
720
|
-
|
|
721
698
|
## Strict
|
|
722
699
|
|
|
723
700
|
TypeBox schemas contain the `Kind` and `Modifier` symbol properties. These properties are provided to enable runtime type reflection on schemas, as well as helping TypeBox internally compose types. These properties are not strictly valid JSON schema; so in some cases it may be desirable to omit them. TypeBox provides a `Type.Strict()` function that will omit these properties if necessary.
|
|
@@ -745,8 +722,6 @@ const U = Type.Strict(T) // const U = {
|
|
|
745
722
|
// }
|
|
746
723
|
```
|
|
747
724
|
|
|
748
|
-
<a name="Validation"></a>
|
|
749
|
-
|
|
750
725
|
## Validation
|
|
751
726
|
|
|
752
727
|
TypeBox schemas target JSON Schema draft 6 so any validator capable of draft 6 should be fine. A good library to use for validation in JavaScript environments is [Ajv](https://www.npmjs.com/package/ajv). The following example shows setting up Ajv to work with TypeBox.
|
|
@@ -812,8 +787,6 @@ const R = ajv.validate(T, { x: 1, y: 2, z: 3 }) // const R = true
|
|
|
812
787
|
|
|
813
788
|
Please refer to the official Ajv [documentation](https://ajv.js.org/guide/getting-started.html) for additional information on using Ajv.
|
|
814
789
|
|
|
815
|
-
<a name="Compiler"></a>
|
|
816
|
-
|
|
817
790
|
## Compiler
|
|
818
791
|
|
|
819
792
|
TypeBox provides an optional high performance runtime type checker that can be used in applications that require extremely fast validation. This type checker is optimized for TypeBox types only whose schematics are known in advance. If defining custom schemas with `Type.Unsafe<T>` please consider Ajv.
|
|
@@ -845,16 +818,19 @@ const C = TypeCompiler.Compile(Type.Object({ // const C: TypeCheck<TObje
|
|
|
845
818
|
const value = { }
|
|
846
819
|
|
|
847
820
|
const errors = [...C.Errors(value)] // const errors = [{
|
|
821
|
+
// type: ValueErrorType.Number,
|
|
848
822
|
// schema: { type: 'number' },
|
|
849
823
|
// path: '/x',
|
|
850
824
|
// value: undefined,
|
|
851
825
|
// message: 'Expected number'
|
|
852
826
|
// }, {
|
|
827
|
+
// type: ValueErrorType.Number,
|
|
853
828
|
// schema: { type: 'number' },
|
|
854
829
|
// path: '/y',
|
|
855
830
|
// value: undefined,
|
|
856
831
|
// message: 'Expected number'
|
|
857
832
|
// }, {
|
|
833
|
+
// type: ValueErrorType.Number,
|
|
858
834
|
// schema: { type: 'number' },
|
|
859
835
|
// path: '/z',
|
|
860
836
|
// value: undefined,
|
|
@@ -874,9 +850,13 @@ console.log(C.Code()) // return function check(va
|
|
|
874
850
|
// }
|
|
875
851
|
```
|
|
876
852
|
|
|
853
|
+
|
|
854
|
+
|
|
877
855
|
## Benchmark
|
|
878
856
|
|
|
879
|
-
This project maintains benchmarks that measure Ajv and TypeCompiler
|
|
857
|
+
This project maintains a set of benchmarks that measure Ajv and TypeCompiler compilation and validation performance. These benchmarks can be run locally by cloning this repository and running `npm run benchmark`. The results below show for Ajv version 8.11.0.
|
|
858
|
+
|
|
859
|
+
For additional comparative benchmarks, please refer to [typescript-runtime-type-benchmarks](https://moltar.github.io/typescript-runtime-type-benchmarks/).
|
|
880
860
|
|
|
881
861
|
### Validate
|
|
882
862
|
|
|
@@ -886,31 +866,31 @@ This benchmark measures validation performance for varying types. You can review
|
|
|
886
866
|
┌──────────────────┬────────────┬──────────────┬──────────────┬──────────────┐
|
|
887
867
|
│ (index) │ Iterations │ Ajv │ TypeCompiler │ Performance │
|
|
888
868
|
├──────────────────┼────────────┼──────────────┼──────────────┼──────────────┤
|
|
889
|
-
│ Number │
|
|
890
|
-
│ String │
|
|
891
|
-
│ Boolean │
|
|
892
|
-
│ Null │
|
|
893
|
-
│ RegEx │
|
|
894
|
-
│ ObjectA │
|
|
895
|
-
│ ObjectB │
|
|
896
|
-
│ Tuple │
|
|
897
|
-
│ Union │
|
|
898
|
-
│ Recursive │
|
|
899
|
-
│ Vector4 │
|
|
900
|
-
│ Matrix4 │
|
|
901
|
-
│ Literal_String │
|
|
902
|
-
│ Literal_Number │
|
|
903
|
-
│ Literal_Boolean │
|
|
904
|
-
│ Array_Number │
|
|
905
|
-
│ Array_String │
|
|
906
|
-
│ Array_Boolean │
|
|
907
|
-
│ Array_ObjectA │
|
|
908
|
-
│ Array_ObjectB │
|
|
909
|
-
│ Array_Tuple │
|
|
910
|
-
│ Array_Union │
|
|
911
|
-
│ Array_Recursive │
|
|
912
|
-
│ Array_Vector4 │
|
|
913
|
-
│ Array_Matrix4 │
|
|
869
|
+
│ Number │ 4000000 │ ' 17 ms' │ ' 16 ms' │ ' 1.06 x' │
|
|
870
|
+
│ String │ 4000000 │ ' 74 ms' │ ' 37 ms' │ ' 2.00 x' │
|
|
871
|
+
│ Boolean │ 4000000 │ ' 68 ms' │ ' 36 ms' │ ' 1.89 x' │
|
|
872
|
+
│ Null │ 4000000 │ ' 68 ms' │ ' 36 ms' │ ' 1.89 x' │
|
|
873
|
+
│ RegEx │ 4000000 │ ' 170 ms' │ ' 143 ms' │ ' 1.19 x' │
|
|
874
|
+
│ ObjectA │ 4000000 │ ' 122 ms' │ ' 84 ms' │ ' 1.45 x' │
|
|
875
|
+
│ ObjectB │ 4000000 │ ' 182 ms' │ ' 137 ms' │ ' 1.33 x' │
|
|
876
|
+
│ Tuple │ 4000000 │ ' 82 ms' │ ' 48 ms' │ ' 1.71 x' │
|
|
877
|
+
│ Union │ 4000000 │ ' 84 ms' │ ' 52 ms' │ ' 1.62 x' │
|
|
878
|
+
│ Recursive │ 4000000 │ ' 1526 ms' │ ' 631 ms' │ ' 2.42 x' │
|
|
879
|
+
│ Vector4 │ 4000000 │ ' 80 ms' │ ' 42 ms' │ ' 1.90 x' │
|
|
880
|
+
│ Matrix4 │ 4000000 │ ' 157 ms' │ ' 113 ms' │ ' 1.39 x' │
|
|
881
|
+
│ Literal_String │ 4000000 │ ' 69 ms' │ ' 36 ms' │ ' 1.92 x' │
|
|
882
|
+
│ Literal_Number │ 4000000 │ ' 69 ms' │ ' 35 ms' │ ' 1.97 x' │
|
|
883
|
+
│ Literal_Boolean │ 4000000 │ ' 68 ms' │ ' 35 ms' │ ' 1.94 x' │
|
|
884
|
+
│ Array_Number │ 4000000 │ ' 119 ms' │ ' 60 ms' │ ' 1.98 x' │
|
|
885
|
+
│ Array_String │ 4000000 │ ' 119 ms' │ ' 76 ms' │ ' 1.57 x' │
|
|
886
|
+
│ Array_Boolean │ 4000000 │ ' 131 ms' │ ' 88 ms' │ ' 1.49 x' │
|
|
887
|
+
│ Array_ObjectA │ 4000000 │ ' 10615 ms' │ ' 7053 ms' │ ' 1.51 x' │
|
|
888
|
+
│ Array_ObjectB │ 4000000 │ ' 11305 ms' │ ' 8128 ms' │ ' 1.39 x' │
|
|
889
|
+
│ Array_Tuple │ 4000000 │ ' 355 ms' │ ' 271 ms' │ ' 1.31 x' │
|
|
890
|
+
│ Array_Union │ 4000000 │ ' 910 ms' │ ' 340 ms' │ ' 2.68 x' │
|
|
891
|
+
│ Array_Recursive │ 4000000 │ ' 29101 ms' │ ' 10837 ms' │ ' 2.69 x' │
|
|
892
|
+
│ Array_Vector4 │ 4000000 │ ' 381 ms' │ ' 212 ms' │ ' 1.80 x' │
|
|
893
|
+
│ Array_Matrix4 │ 4000000 │ ' 1534 ms' │ ' 1344 ms' │ ' 1.14 x' │
|
|
914
894
|
└──────────────────┴────────────┴──────────────┴──────────────┴──────────────┘
|
|
915
895
|
```
|
|
916
896
|
|
|
@@ -922,34 +902,32 @@ This benchmark measures compilation performance for varying types. You can revie
|
|
|
922
902
|
┌──────────────────┬────────────┬──────────────┬──────────────┬──────────────┐
|
|
923
903
|
│ (index) │ Iterations │ Ajv │ TypeCompiler │ Performance │
|
|
924
904
|
├──────────────────┼────────────┼──────────────┼──────────────┼──────────────┤
|
|
925
|
-
│ Number │ 2000 │ '
|
|
926
|
-
│ String │ 2000 │ '
|
|
927
|
-
│ Boolean │ 2000 │ '
|
|
928
|
-
│ Null │ 2000 │ '
|
|
929
|
-
│ RegEx │ 2000 │ '
|
|
930
|
-
│ ObjectA │ 2000 │ '
|
|
931
|
-
│ ObjectB │ 2000 │ '
|
|
932
|
-
│ Tuple │ 2000 │ '
|
|
933
|
-
│ Union │ 2000 │ '
|
|
934
|
-
│ Vector4 │ 2000 │ '
|
|
935
|
-
│ Matrix4 │ 2000 │ '
|
|
936
|
-
│ Literal_String │ 2000 │ '
|
|
937
|
-
│ Literal_Number │ 2000 │ '
|
|
938
|
-
│ Literal_Boolean │ 2000 │ '
|
|
939
|
-
│ Array_Number │ 2000 │ '
|
|
940
|
-
│ Array_String │ 2000 │ '
|
|
941
|
-
│ Array_Boolean │ 2000 │ '
|
|
942
|
-
│ Array_ObjectA │ 2000 │ '
|
|
943
|
-
│ Array_ObjectB │ 2000 │ '
|
|
944
|
-
│ Array_Tuple │ 2000 │ '
|
|
945
|
-
│ Array_Union │ 2000 │ '
|
|
946
|
-
│ Array_Vector4 │ 2000 │ '
|
|
947
|
-
│ Array_Matrix4 │ 2000 │ '
|
|
905
|
+
│ Number │ 2000 │ ' 384 ms' │ ' 7 ms' │ ' 54.86 x' │
|
|
906
|
+
│ String │ 2000 │ ' 311 ms' │ ' 6 ms' │ ' 51.83 x' │
|
|
907
|
+
│ Boolean │ 2000 │ ' 304 ms' │ ' 5 ms' │ ' 60.80 x' │
|
|
908
|
+
│ Null │ 2000 │ ' 252 ms' │ ' 5 ms' │ ' 50.40 x' │
|
|
909
|
+
│ RegEx │ 2000 │ ' 480 ms' │ ' 7 ms' │ ' 68.57 x' │
|
|
910
|
+
│ ObjectA │ 2000 │ ' 2786 ms' │ ' 27 ms' │ ' 103.19 x' │
|
|
911
|
+
│ ObjectB │ 2000 │ ' 2946 ms' │ ' 22 ms' │ ' 133.91 x' │
|
|
912
|
+
│ Tuple │ 2000 │ ' 1277 ms' │ ' 16 ms' │ ' 79.81 x' │
|
|
913
|
+
│ Union │ 2000 │ ' 1288 ms' │ ' 16 ms' │ ' 80.50 x' │
|
|
914
|
+
│ Vector4 │ 2000 │ ' 1628 ms' │ ' 12 ms' │ ' 135.67 x' │
|
|
915
|
+
│ Matrix4 │ 2000 │ ' 912 ms' │ ' 7 ms' │ ' 130.29 x' │
|
|
916
|
+
│ Literal_String │ 2000 │ ' 344 ms' │ ' 5 ms' │ ' 68.80 x' │
|
|
917
|
+
│ Literal_Number │ 2000 │ ' 432 ms' │ ' 5 ms' │ ' 86.40 x' │
|
|
918
|
+
│ Literal_Boolean │ 2000 │ ' 407 ms' │ ' 4 ms' │ ' 101.75 x' │
|
|
919
|
+
│ Array_Number │ 2000 │ ' 788 ms' │ ' 9 ms' │ ' 87.56 x' │
|
|
920
|
+
│ Array_String │ 2000 │ ' 823 ms' │ ' 7 ms' │ ' 117.57 x' │
|
|
921
|
+
│ Array_Boolean │ 2000 │ ' 816 ms' │ ' 5 ms' │ ' 163.20 x' │
|
|
922
|
+
│ Array_ObjectA │ 2000 │ ' 4270 ms' │ ' 24 ms' │ ' 177.92 x' │
|
|
923
|
+
│ Array_ObjectB │ 2000 │ ' 4008 ms' │ ' 28 ms' │ ' 143.14 x' │
|
|
924
|
+
│ Array_Tuple │ 2000 │ ' 2243 ms' │ ' 13 ms' │ ' 172.54 x' │
|
|
925
|
+
│ Array_Union │ 2000 │ ' 1734 ms' │ ' 16 ms' │ ' 108.38 x' │
|
|
926
|
+
│ Array_Vector4 │ 2000 │ ' 2348 ms' │ ' 14 ms' │ ' 167.71 x' │
|
|
927
|
+
│ Array_Matrix4 │ 2000 │ ' 1608 ms' │ ' 11 ms' │ ' 146.18 x' │
|
|
948
928
|
└──────────────────┴────────────┴──────────────┴──────────────┴──────────────┘
|
|
949
929
|
```
|
|
950
930
|
|
|
951
|
-
<a name="Contribute"></a>
|
|
952
|
-
|
|
953
931
|
## Contribute
|
|
954
932
|
|
|
955
933
|
TypeBox is open to community contribution. Please ensure you submit an open issue before submitting your pull request. The TypeBox project preferences open community discussion prior to accepting new features.
|
package/value/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { ValueError, ValueErrorType } from '../error/errors';
|
|
2
2
|
export * from './value';
|
package/value/index.js
CHANGED
|
@@ -41,4 +41,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
41
41
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
42
42
|
};
|
|
43
43
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.ValueErrorType = void 0;
|
|
45
|
+
var errors_1 = require("../error/errors");
|
|
46
|
+
Object.defineProperty(exports, "ValueErrorType", { enumerable: true, get: function () { return errors_1.ValueErrorType; } });
|
|
44
47
|
__exportStar(require("./value"), exports);
|
package/value/value.d.ts
CHANGED
package/value/value.js
CHANGED
|
@@ -28,7 +28,7 @@ THE SOFTWARE.
|
|
|
28
28
|
---------------------------------------------------------------------------*/
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
30
|
exports.Value = void 0;
|
|
31
|
-
const errors_1 = require("
|
|
31
|
+
const errors_1 = require("../error/errors");
|
|
32
32
|
const cast_1 = require("./cast");
|
|
33
33
|
const create_1 = require("./create");
|
|
34
34
|
const check_1 = require("./check");
|
package/value/errors.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import * as Types from '../typebox';
|
|
2
|
-
export interface ValueError {
|
|
3
|
-
schema: Types.TSchema;
|
|
4
|
-
path: string;
|
|
5
|
-
value: unknown;
|
|
6
|
-
message: string;
|
|
7
|
-
}
|
|
8
|
-
export declare namespace ValueErrors {
|
|
9
|
-
function Errors<T extends Types.TSchema>(schema: T, references: Types.TSchema[], value: any): IterableIterator<ValueError>;
|
|
10
|
-
}
|