@sinclair/typebox 0.24.6 → 0.24.9
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 +6 -5
- package/compiler/compiler.js +102 -101
- package/compiler/index.d.ts +1 -1
- package/compiler/index.js +0 -1
- package/guard/guard.d.ts +1 -1
- package/package.json +1 -1
- package/readme.md +33 -19
- package/typebox.d.ts +1 -3
- package/typebox.js +1 -1
- package/value/cast.d.ts +5 -0
- package/value/cast.js +249 -0
- package/value/check.d.ts +2 -3
- package/value/check.js +173 -119
- package/value/create.d.ts +3 -4
- package/value/create.js +85 -100
- package/value/errors.d.ts +10 -0
- package/{compiler → value}/errors.js +71 -92
- package/value/index.d.ts +1 -0
- package/value/value.d.ts +17 -13
- package/value/value.js +20 -32
- package/compiler/errors.d.ts +0 -10
- package/value/clone.d.ts +0 -3
- package/value/clone.js +0 -94
- package/value/delta.d.ts +0 -13
- package/value/delta.js +0 -191
- package/value/pointer.d.ts +0 -12
- package/value/pointer.js +0 -110
- package/value/reflect.d.ts +0 -2
- package/value/reflect.js +0 -42
- package/value/upcast.d.ts +0 -4
- package/value/upcast.js +0 -247
package/compiler/compiler.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ValueError } from '../value/errors';
|
|
2
2
|
import * as Types from '../typebox';
|
|
3
3
|
export declare type CheckFunction = (value: unknown) => boolean;
|
|
4
4
|
export declare class TypeCheck<T extends Types.TSchema> {
|
|
@@ -7,14 +7,15 @@ export declare class TypeCheck<T extends Types.TSchema> {
|
|
|
7
7
|
private readonly checkFunc;
|
|
8
8
|
private readonly code;
|
|
9
9
|
constructor(schema: T, additional: Types.TSchema[], checkFunc: CheckFunction, code: string);
|
|
10
|
-
/** Returns the generated validation code used to validate this type */
|
|
10
|
+
/** Returns the generated validation code used to validate this type. */
|
|
11
11
|
Code(): string;
|
|
12
|
-
/** Returns an iterator for each
|
|
13
|
-
Errors(value: unknown):
|
|
12
|
+
/** Returns an iterator for each error in this value. */
|
|
13
|
+
Errors(value: unknown): IterableIterator<ValueError>;
|
|
14
14
|
/** Returns true if the value matches the given type. */
|
|
15
15
|
Check(value: unknown): value is Types.Static<T>;
|
|
16
16
|
}
|
|
17
|
+
/** Compiles TypeBox Types for Runtime Type Checking */
|
|
17
18
|
export declare namespace TypeCompiler {
|
|
18
19
|
/** Compiles the given type for runtime type checking. This compiler only accepts known TypeBox types non-inclusive of unsafe types. */
|
|
19
|
-
function Compile<T extends Types.TSchema>(schema: T,
|
|
20
|
+
function Compile<T extends Types.TSchema>(schema: T, references?: Types.TSchema[]): TypeCheck<T>;
|
|
20
21
|
}
|
package/compiler/compiler.js
CHANGED
|
@@ -28,7 +28,7 @@ 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("../value/errors");
|
|
32
32
|
const Types = require("../typebox");
|
|
33
33
|
// -------------------------------------------------------------------
|
|
34
34
|
// TypeCheck
|
|
@@ -44,13 +44,13 @@ class TypeCheck {
|
|
|
44
44
|
this.checkFunc = checkFunc;
|
|
45
45
|
this.code = code;
|
|
46
46
|
}
|
|
47
|
-
/** Returns the generated validation code used to validate this type */
|
|
47
|
+
/** Returns the generated validation code used to validate this type. */
|
|
48
48
|
Code() {
|
|
49
49
|
return this.code;
|
|
50
50
|
}
|
|
51
|
-
/** Returns an iterator for each
|
|
51
|
+
/** Returns an iterator for each error in this value. */
|
|
52
52
|
Errors(value) {
|
|
53
|
-
return errors_1.
|
|
53
|
+
return errors_1.ValueErrors.Errors(this.schema, this.additional, value);
|
|
54
54
|
}
|
|
55
55
|
/** Returns true if the value matches the given type. */
|
|
56
56
|
Check(value) {
|
|
@@ -61,70 +61,71 @@ exports.TypeCheck = TypeCheck;
|
|
|
61
61
|
// -------------------------------------------------------------------
|
|
62
62
|
// TypeCompiler
|
|
63
63
|
// -------------------------------------------------------------------
|
|
64
|
+
/** Compiles TypeBox Types for Runtime Type Checking */
|
|
64
65
|
var TypeCompiler;
|
|
65
66
|
(function (TypeCompiler) {
|
|
66
67
|
// -------------------------------------------------------------------
|
|
67
68
|
// Schemas
|
|
68
69
|
// -------------------------------------------------------------------
|
|
69
|
-
function* Any(schema,
|
|
70
|
+
function* Any(schema, value) {
|
|
70
71
|
yield '(true)';
|
|
71
72
|
}
|
|
72
|
-
function* Array(schema,
|
|
73
|
+
function* Array(schema, value) {
|
|
73
74
|
const expr = [...Visit(schema.items, `value`)].map((condition) => condition).join(' && ');
|
|
74
|
-
yield `(Array.isArray(${
|
|
75
|
+
yield `(Array.isArray(${value}) && ${value}.every(value => ${expr}))`;
|
|
75
76
|
}
|
|
76
|
-
function* Boolean(schema,
|
|
77
|
-
yield `(typeof ${
|
|
77
|
+
function* Boolean(schema, value) {
|
|
78
|
+
yield `(typeof ${value} === 'boolean')`;
|
|
78
79
|
}
|
|
79
|
-
function* Constructor(schema,
|
|
80
|
-
yield* Visit(schema.
|
|
80
|
+
function* Constructor(schema, value) {
|
|
81
|
+
yield* Visit(schema.returns, value);
|
|
81
82
|
}
|
|
82
|
-
function* Function(schema,
|
|
83
|
-
yield `(typeof ${
|
|
83
|
+
function* Function(schema, value) {
|
|
84
|
+
yield `(typeof ${value} === 'function')`;
|
|
84
85
|
}
|
|
85
|
-
function* Integer(schema,
|
|
86
|
-
yield `(typeof ${
|
|
86
|
+
function* Integer(schema, value) {
|
|
87
|
+
yield `(typeof ${value} === 'number' && Number.isInteger(${value}))`;
|
|
87
88
|
if (schema.multipleOf)
|
|
88
|
-
yield `(${
|
|
89
|
+
yield `(${value} % ${schema.multipleOf} === 0)`;
|
|
89
90
|
if (schema.exclusiveMinimum)
|
|
90
|
-
yield `(${
|
|
91
|
+
yield `(${value} > ${schema.exclusiveMinimum})`;
|
|
91
92
|
if (schema.exclusiveMaximum)
|
|
92
|
-
yield `(${
|
|
93
|
+
yield `(${value} < ${schema.exclusiveMaximum})`;
|
|
93
94
|
if (schema.minimum)
|
|
94
|
-
yield `(${
|
|
95
|
+
yield `(${value} >= ${schema.minimum})`;
|
|
95
96
|
if (schema.maximum)
|
|
96
|
-
yield `(${
|
|
97
|
+
yield `(${value} <= ${schema.maximum})`;
|
|
97
98
|
}
|
|
98
|
-
function* Literal(schema,
|
|
99
|
+
function* Literal(schema, value) {
|
|
99
100
|
if (typeof schema.const === 'string') {
|
|
100
|
-
yield `(${
|
|
101
|
+
yield `(${value} === '${schema.const}')`;
|
|
101
102
|
}
|
|
102
103
|
else {
|
|
103
|
-
yield `(${
|
|
104
|
+
yield `(${value} === ${schema.const})`;
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
|
-
function* Null(schema,
|
|
107
|
-
yield `(${
|
|
107
|
+
function* Null(schema, value) {
|
|
108
|
+
yield `(${value} === null)`;
|
|
108
109
|
}
|
|
109
|
-
function* Number(schema,
|
|
110
|
-
yield `(typeof ${
|
|
110
|
+
function* Number(schema, value) {
|
|
111
|
+
yield `(typeof ${value} === 'number')`;
|
|
111
112
|
if (schema.multipleOf)
|
|
112
|
-
yield `(${
|
|
113
|
+
yield `(${value} % ${schema.multipleOf} === 0)`;
|
|
113
114
|
if (schema.exclusiveMinimum)
|
|
114
|
-
yield `(${
|
|
115
|
+
yield `(${value} > ${schema.exclusiveMinimum})`;
|
|
115
116
|
if (schema.exclusiveMaximum)
|
|
116
|
-
yield `(${
|
|
117
|
+
yield `(${value} < ${schema.exclusiveMaximum})`;
|
|
117
118
|
if (schema.minimum)
|
|
118
|
-
yield `(${
|
|
119
|
+
yield `(${value} >= ${schema.minimum})`;
|
|
119
120
|
if (schema.maximum)
|
|
120
|
-
yield `(${
|
|
121
|
+
yield `(${value} <= ${schema.maximum})`;
|
|
121
122
|
}
|
|
122
|
-
function* Object(schema,
|
|
123
|
-
yield `(typeof ${
|
|
123
|
+
function* Object(schema, value) {
|
|
124
|
+
yield `(typeof ${value} === 'object' && ${value} !== null && !Array.isArray(${value}))`;
|
|
124
125
|
if (schema.minProperties !== undefined)
|
|
125
|
-
yield `(Object.keys(${
|
|
126
|
+
yield `(Object.keys(${value}).length >= ${schema.minProperties})`;
|
|
126
127
|
if (schema.maxProperties !== undefined)
|
|
127
|
-
yield `(Object.keys(${
|
|
128
|
+
yield `(Object.keys(${value}).length <= ${schema.maxProperties})`;
|
|
128
129
|
const propertyKeys = globalThis.Object.keys(schema.properties);
|
|
129
130
|
if (schema.additionalProperties === false) {
|
|
130
131
|
// optimization: If the property key length matches the required keys length
|
|
@@ -132,36 +133,36 @@ var TypeCompiler;
|
|
|
132
133
|
// of the property key length. This is because exhaustive testing for values
|
|
133
134
|
// will occur in subsequent property tests.
|
|
134
135
|
if (schema.required && schema.required.length === propertyKeys.length) {
|
|
135
|
-
yield `(Object.keys(${
|
|
136
|
+
yield `(Object.keys(${value}).length === ${propertyKeys.length})`;
|
|
136
137
|
}
|
|
137
138
|
else {
|
|
138
139
|
const keys = `[${propertyKeys.map((key) => `'${key}'`).join(', ')}]`;
|
|
139
|
-
yield `(Object.keys(${
|
|
140
|
+
yield `(Object.keys(${value}).every(key => ${keys}.includes(key)))`;
|
|
140
141
|
}
|
|
141
142
|
}
|
|
142
143
|
for (const propertyKey of propertyKeys) {
|
|
143
144
|
const propertySchema = schema.properties[propertyKey];
|
|
144
145
|
if (schema.required && schema.required.includes(propertyKey)) {
|
|
145
|
-
yield* Visit(propertySchema, `${
|
|
146
|
+
yield* Visit(propertySchema, `${value}.${propertyKey}`);
|
|
146
147
|
}
|
|
147
148
|
else {
|
|
148
|
-
const expr = [...Visit(propertySchema, `${
|
|
149
|
-
yield `(${
|
|
149
|
+
const expr = [...Visit(propertySchema, `${value}.${propertyKey}`)].map((condition) => condition).join(' && ');
|
|
150
|
+
yield `(${value}.${propertyKey} === undefined ? true : (${expr}))`;
|
|
150
151
|
}
|
|
151
152
|
}
|
|
152
153
|
}
|
|
153
|
-
function* Promise(schema,
|
|
154
|
-
yield `(typeof value === 'object' && typeof ${
|
|
154
|
+
function* Promise(schema, value) {
|
|
155
|
+
yield `(typeof value === 'object' && typeof ${value}.then === 'function')`;
|
|
155
156
|
}
|
|
156
|
-
function* Record(schema,
|
|
157
|
-
yield `(typeof ${
|
|
157
|
+
function* Record(schema, value) {
|
|
158
|
+
yield `(typeof ${value} === 'object' && ${value} !== null && !Array.isArray(${value}))`;
|
|
158
159
|
const [keyPattern, valueSchema] = globalThis.Object.entries(schema.patternProperties)[0];
|
|
159
160
|
const local = PushLocal(`const local = new RegExp(/${keyPattern}/)`);
|
|
160
|
-
yield `(Object.keys(${
|
|
161
|
+
yield `(Object.keys(${value}).every(key => ${local}.test(key)))`;
|
|
161
162
|
const expr = [...Visit(valueSchema, 'value')].map((condition) => condition).join(' && ');
|
|
162
|
-
yield `(Object.values(${
|
|
163
|
+
yield `(Object.values(${value}).every(value => ${expr}))`;
|
|
163
164
|
}
|
|
164
|
-
function* Ref(schema,
|
|
165
|
+
function* Ref(schema, value) {
|
|
165
166
|
// reference: referenced schemas can originate from either additional
|
|
166
167
|
// schemas or inline in the schema itself. Ideally the recursive
|
|
167
168
|
// path should align to reference path. Consider for review.
|
|
@@ -174,50 +175,50 @@ var TypeCompiler;
|
|
|
174
175
|
PushLocal(body);
|
|
175
176
|
}
|
|
176
177
|
const func = CreateFunctionName(schema.$ref);
|
|
177
|
-
yield `(${func}(${
|
|
178
|
+
yield `(${func}(${value}))`;
|
|
178
179
|
}
|
|
179
|
-
function* Self(schema,
|
|
180
|
+
function* Self(schema, value) {
|
|
180
181
|
const func = CreateFunctionName(schema.$ref);
|
|
181
|
-
yield `(${func}(${
|
|
182
|
+
yield `(${func}(${value}))`;
|
|
182
183
|
}
|
|
183
|
-
function* String(schema,
|
|
184
|
-
yield `(typeof ${
|
|
184
|
+
function* String(schema, value) {
|
|
185
|
+
yield `(typeof ${value} === 'string')`;
|
|
185
186
|
if (schema.pattern !== undefined) {
|
|
186
187
|
const local = PushLocal(`const local = new RegExp('${schema.pattern}');`);
|
|
187
|
-
yield `(${local}.test(${
|
|
188
|
+
yield `(${local}.test(${value}))`;
|
|
188
189
|
}
|
|
189
190
|
}
|
|
190
|
-
function* Tuple(schema,
|
|
191
|
-
yield `(Array.isArray(${
|
|
191
|
+
function* Tuple(schema, value) {
|
|
192
|
+
yield `(Array.isArray(${value}))`;
|
|
192
193
|
if (schema.items === undefined)
|
|
193
|
-
return yield `(${
|
|
194
|
-
yield `(${
|
|
194
|
+
return yield `(${value}.length === 0)`;
|
|
195
|
+
yield `(${value}.length === ${schema.maxItems})`;
|
|
195
196
|
for (let i = 0; i < schema.items.length; i++) {
|
|
196
|
-
const expr = [...Visit(schema.items[i], `${
|
|
197
|
+
const expr = [...Visit(schema.items[i], `${value}[${i}]`)].map((condition) => condition).join(' && ');
|
|
197
198
|
yield `(${expr})`;
|
|
198
199
|
}
|
|
199
200
|
}
|
|
200
|
-
function* Undefined(schema,
|
|
201
|
-
yield
|
|
201
|
+
function* Undefined(schema, value) {
|
|
202
|
+
yield `(${value} === undefined)`;
|
|
202
203
|
}
|
|
203
|
-
function* Union(schema,
|
|
204
|
-
const exprs = schema.anyOf.map((schema) => [...Visit(schema,
|
|
204
|
+
function* Union(schema, value) {
|
|
205
|
+
const exprs = schema.anyOf.map((schema) => [...Visit(schema, value)].map((condition) => condition).join(' && '));
|
|
205
206
|
yield `(${exprs.join(' || ')})`;
|
|
206
207
|
}
|
|
207
|
-
function* Uint8Array(schema,
|
|
208
|
-
yield `(${
|
|
208
|
+
function* Uint8Array(schema, value) {
|
|
209
|
+
yield `(${value} instanceof Uint8Array)`;
|
|
209
210
|
if (schema.maxByteLength)
|
|
210
|
-
yield `(${
|
|
211
|
+
yield `(${value}.length <= ${schema.maxByteLength})`;
|
|
211
212
|
if (schema.minByteLength)
|
|
212
|
-
yield `(${
|
|
213
|
+
yield `(${value}.length >= ${schema.minByteLength})`;
|
|
213
214
|
}
|
|
214
|
-
function* Unknown(schema,
|
|
215
|
+
function* Unknown(schema, value) {
|
|
215
216
|
yield '(true)';
|
|
216
217
|
}
|
|
217
|
-
function* Void(schema,
|
|
218
|
-
yield `(${
|
|
218
|
+
function* Void(schema, value) {
|
|
219
|
+
yield `(${value} === null)`;
|
|
219
220
|
}
|
|
220
|
-
function* Visit(schema,
|
|
221
|
+
function* Visit(schema, value) {
|
|
221
222
|
// reference: referenced schemas can originate from either additional
|
|
222
223
|
// schemas or inline in the schema itself. Ideally the recursive
|
|
223
224
|
// path should align to reference path. Consider for review.
|
|
@@ -227,55 +228,55 @@ var TypeCompiler;
|
|
|
227
228
|
const name = CreateFunctionName(schema.$id);
|
|
228
229
|
const body = CreateFunction(name, conditions);
|
|
229
230
|
PushLocal(body);
|
|
230
|
-
yield `(${name}(${
|
|
231
|
+
yield `(${name}(${value}))`;
|
|
231
232
|
return;
|
|
232
233
|
}
|
|
233
234
|
const anySchema = schema;
|
|
234
235
|
switch (anySchema[Types.Kind]) {
|
|
235
236
|
case 'Any':
|
|
236
|
-
return yield* Any(anySchema,
|
|
237
|
+
return yield* Any(anySchema, value);
|
|
237
238
|
case 'Array':
|
|
238
|
-
return yield* Array(anySchema,
|
|
239
|
+
return yield* Array(anySchema, value);
|
|
239
240
|
case 'Boolean':
|
|
240
|
-
return yield* Boolean(anySchema,
|
|
241
|
+
return yield* Boolean(anySchema, value);
|
|
241
242
|
case 'Constructor':
|
|
242
|
-
return yield* Constructor(anySchema,
|
|
243
|
+
return yield* Constructor(anySchema, value);
|
|
243
244
|
case 'Function':
|
|
244
|
-
return yield* Function(anySchema,
|
|
245
|
+
return yield* Function(anySchema, value);
|
|
245
246
|
case 'Integer':
|
|
246
|
-
return yield* Integer(anySchema,
|
|
247
|
+
return yield* Integer(anySchema, value);
|
|
247
248
|
case 'Literal':
|
|
248
|
-
return yield* Literal(anySchema,
|
|
249
|
+
return yield* Literal(anySchema, value);
|
|
249
250
|
case 'Null':
|
|
250
|
-
return yield* Null(anySchema,
|
|
251
|
+
return yield* Null(anySchema, value);
|
|
251
252
|
case 'Number':
|
|
252
|
-
return yield* Number(anySchema,
|
|
253
|
+
return yield* Number(anySchema, value);
|
|
253
254
|
case 'Object':
|
|
254
|
-
return yield* Object(anySchema,
|
|
255
|
+
return yield* Object(anySchema, value);
|
|
255
256
|
case 'Promise':
|
|
256
|
-
return yield* Promise(anySchema,
|
|
257
|
+
return yield* Promise(anySchema, value);
|
|
257
258
|
case 'Record':
|
|
258
|
-
return yield* Record(anySchema,
|
|
259
|
+
return yield* Record(anySchema, value);
|
|
259
260
|
case 'Ref':
|
|
260
|
-
return yield* Ref(anySchema,
|
|
261
|
+
return yield* Ref(anySchema, value);
|
|
261
262
|
case 'Self':
|
|
262
|
-
return yield* Self(anySchema,
|
|
263
|
+
return yield* Self(anySchema, value);
|
|
263
264
|
case 'String':
|
|
264
|
-
return yield* String(anySchema,
|
|
265
|
+
return yield* String(anySchema, value);
|
|
265
266
|
case 'Tuple':
|
|
266
|
-
return yield* Tuple(anySchema,
|
|
267
|
+
return yield* Tuple(anySchema, value);
|
|
267
268
|
case 'Undefined':
|
|
268
|
-
return yield* Undefined(anySchema,
|
|
269
|
+
return yield* Undefined(anySchema, value);
|
|
269
270
|
case 'Union':
|
|
270
|
-
return yield* Union(anySchema,
|
|
271
|
+
return yield* Union(anySchema, value);
|
|
271
272
|
case 'Uint8Array':
|
|
272
|
-
return yield* Uint8Array(anySchema,
|
|
273
|
+
return yield* Uint8Array(anySchema, value);
|
|
273
274
|
case 'Unknown':
|
|
274
|
-
return yield* Unknown(anySchema,
|
|
275
|
+
return yield* Unknown(anySchema, value);
|
|
275
276
|
case 'Void':
|
|
276
|
-
return yield* Void(anySchema,
|
|
277
|
+
return yield* Void(anySchema, value);
|
|
277
278
|
default:
|
|
278
|
-
throw Error(`Unknown schema kind '${schema[Types.Kind]}'`);
|
|
279
|
+
throw new Error(`TypeCompiler: Unknown schema kind '${schema[Types.Kind]}'`);
|
|
279
280
|
}
|
|
280
281
|
}
|
|
281
282
|
// -------------------------------------------------------------------
|
|
@@ -292,9 +293,9 @@ var TypeCompiler;
|
|
|
292
293
|
function PushReferences(schemas = []) {
|
|
293
294
|
for (const schema of schemas) {
|
|
294
295
|
if (!schema.$id)
|
|
295
|
-
throw Error(`Referenced schemas must specify an $id
|
|
296
|
+
throw new Error(`TypeCompiler: Referenced schemas must specify an $id.`);
|
|
296
297
|
if (referenceMap.has(schema.$id))
|
|
297
|
-
throw Error(`Duplicate schema $id
|
|
298
|
+
throw new Error(`TypeCompiler: Duplicate schema $id found for '${schema.$id}'`);
|
|
298
299
|
referenceMap.set(schema.$id, schema);
|
|
299
300
|
}
|
|
300
301
|
}
|
|
@@ -319,18 +320,18 @@ var TypeCompiler;
|
|
|
319
320
|
// -------------------------------------------------------------------
|
|
320
321
|
// Compile
|
|
321
322
|
// -------------------------------------------------------------------
|
|
322
|
-
function Build(schema,
|
|
323
|
+
function Build(schema, references = []) {
|
|
323
324
|
ClearLocals();
|
|
324
|
-
PushReferences(
|
|
325
|
+
PushReferences(references);
|
|
325
326
|
const conditions = [...Visit(schema, 'value')]; // locals populated during yield
|
|
326
327
|
const locals = GetLocals();
|
|
327
328
|
return `${locals.join('\n')}\nreturn ${CreateFunction('check', conditions)}`;
|
|
328
329
|
}
|
|
329
330
|
/** Compiles the given type for runtime type checking. This compiler only accepts known TypeBox types non-inclusive of unsafe types. */
|
|
330
|
-
function Compile(schema,
|
|
331
|
-
const code = Build(schema,
|
|
331
|
+
function Compile(schema, references = []) {
|
|
332
|
+
const code = Build(schema, references);
|
|
332
333
|
const func = globalThis.Function(code);
|
|
333
|
-
return new TypeCheck(schema,
|
|
334
|
+
return new TypeCheck(schema, references, func(), code);
|
|
334
335
|
}
|
|
335
336
|
TypeCompiler.Compile = Compile;
|
|
336
337
|
})(TypeCompiler = exports.TypeCompiler || (exports.TypeCompiler = {}));
|
package/compiler/index.d.ts
CHANGED
package/compiler/index.js
CHANGED
package/guard/guard.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export declare namespace TypeGuard {
|
|
|
28
28
|
/** Returns true if the given schema is TSelf */
|
|
29
29
|
function TSelf(schema: any): schema is Types.TSelf;
|
|
30
30
|
/** Returns true if the given schema is TRef */
|
|
31
|
-
function TRef(schema: any): schema is Types.
|
|
31
|
+
function TRef(schema: any): schema is Types.TRef;
|
|
32
32
|
/** Returns true if the given schema is TString */
|
|
33
33
|
function TString(schema: any): schema is Types.TString;
|
|
34
34
|
/** Returns true if the given schema is TTuple */
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -450,7 +450,8 @@ In addition to JSON schema types, TypeBox provides several extended types that a
|
|
|
450
450
|
│ │ │ │
|
|
451
451
|
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
452
452
|
│ const T = Type.Undefined() │ type T = undefined │ const T = { │
|
|
453
|
-
│ │ │ type: '
|
|
453
|
+
│ │ │ type: 'object', │
|
|
454
|
+
│ │ │ specialized: 'Undefined' │
|
|
454
455
|
│ │ │ } │
|
|
455
456
|
│ │ │ │
|
|
456
457
|
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
@@ -553,7 +554,7 @@ type U = Static<typeof U> // type U = number | null
|
|
|
553
554
|
|
|
554
555
|
### Unsafe Types
|
|
555
556
|
|
|
556
|
-
In some
|
|
557
|
+
In some scenarios, you may need specific schemas not provided by TypeBox. In these cases, it's common to want to define a custom schema with custom static inference rules. The `Type.Unsafe(...)` function provides this functionality. This function enables one to specify both schema representation and a static type to infer. Consider the following which defines a `number` schema but infers as `string`.
|
|
557
558
|
|
|
558
559
|
```typescript
|
|
559
560
|
const T = Type.Unsafe<string>({ type: 'number' }) // const T = {
|
|
@@ -563,7 +564,7 @@ const T = Type.Unsafe<string>({ type: 'number' }) // const T = {
|
|
|
563
564
|
type T = Static<typeof T> // type T = string
|
|
564
565
|
```
|
|
565
566
|
|
|
566
|
-
The `Type.Unsafe(...)` function can be
|
|
567
|
+
The `Type.Unsafe(...)` function can be combined with function generics to create user defined schemas for validators that need specific schema representations. An example of this might be the OpenAPI `nullable` and `string-enum` schema representations which are not provided by TypeBox. The following demonstrates creating these schemas using the `Type.Unsafe(...)` function.
|
|
567
568
|
|
|
568
569
|
```typescript
|
|
569
570
|
import { Type, Static, TSchema } from '@sinclair/typebox'
|
|
@@ -606,36 +607,51 @@ type T = Static<typeof T> // type T = 'A' | 'B' | 'C'
|
|
|
606
607
|
|
|
607
608
|
### Values
|
|
608
609
|
|
|
609
|
-
TypeBox can
|
|
610
|
+
TypeBox can create values from types. It creates reasonable defaults for each value which can overrided by specifying a `default` value.
|
|
610
611
|
|
|
611
612
|
```typescript
|
|
612
613
|
import { Value } from '@sinclair/typebox/value'
|
|
613
|
-
import { Type }
|
|
614
|
+
import { Type } from '@sinclair/typebox'
|
|
614
615
|
|
|
615
616
|
const T = Type.Object({
|
|
616
617
|
x: Type.Number({ default: 1 }),
|
|
617
|
-
y: Type.Number(
|
|
618
|
-
z: Type.Number()
|
|
618
|
+
y: Type.Number(),
|
|
619
619
|
})
|
|
620
620
|
|
|
621
621
|
const V = Value.Create(T) // const V = {
|
|
622
622
|
// x: 1,
|
|
623
|
-
// y:
|
|
624
|
-
// z: 0
|
|
623
|
+
// y: 0,
|
|
625
624
|
// }
|
|
626
625
|
```
|
|
626
|
+
TypeBox also allows values to be upgraded to match the schematics of a given type. The `Value.Cast(...)` function can be used to upgrade a value into a target type while retaining as much information of the original value as possible. Casts are immutable operations.
|
|
627
|
+
|
|
628
|
+
```typescript
|
|
629
|
+
import { Value } from '@sinclair/typebox/value'
|
|
630
|
+
import { Type } from '@sinclair/typebox'
|
|
631
|
+
|
|
632
|
+
const T = Type.Object({
|
|
633
|
+
x: Type.Number(),
|
|
634
|
+
y: Type.Number()
|
|
635
|
+
})
|
|
636
|
+
|
|
637
|
+
const A = Value.Cast(T, null) // const A = { x: 0, y: 0 }
|
|
638
|
+
|
|
639
|
+
const B = Value.Cast(T, { x: 1 }) // const B = { x: 1, y: 0 }
|
|
640
|
+
|
|
641
|
+
const C = Value.Cast(T, { x: 1, y: 2, z: 3 }) // const C = { x: 1, y: 2 }
|
|
642
|
+
```
|
|
627
643
|
|
|
628
644
|
<a name="Guards"></a>
|
|
629
645
|
|
|
630
646
|
### Guards
|
|
631
647
|
|
|
632
|
-
|
|
648
|
+
If reflecting on TypeBox types, it can be helpful to test if a value matches a TypeBox schematic. This can be achieved using the TypeGuard namespace. The TypeGuard namespace offers exhaustive checks for each known TypeBox type.
|
|
633
649
|
|
|
634
650
|
```typescript
|
|
635
651
|
import { TypeGuard } from '@sinclair/typebox/guard'
|
|
636
652
|
import { Type } from '@sinclair/typebox'
|
|
637
653
|
|
|
638
|
-
const T: any =
|
|
654
|
+
const T: any = {} // T is any
|
|
639
655
|
|
|
640
656
|
const { type } = T // unsafe: type is any
|
|
641
657
|
|
|
@@ -646,8 +662,6 @@ if(TypeGuard.TString(T)) {
|
|
|
646
662
|
|
|
647
663
|
```
|
|
648
664
|
|
|
649
|
-
|
|
650
|
-
|
|
651
665
|
<a name="Strict"></a>
|
|
652
666
|
|
|
653
667
|
### Strict
|
|
@@ -727,7 +741,7 @@ const ajv = addFormats(new Ajv({}), [
|
|
|
727
741
|
//
|
|
728
742
|
//--------------------------------------------------------------------------------------------
|
|
729
743
|
|
|
730
|
-
const
|
|
744
|
+
const T = Type.Object({
|
|
731
745
|
x: Type.Number(),
|
|
732
746
|
y: Type.Number(),
|
|
733
747
|
z: Type.Number(),
|
|
@@ -739,7 +753,7 @@ const Vector = Type.Object({
|
|
|
739
753
|
//
|
|
740
754
|
//--------------------------------------------------------------------------------------------
|
|
741
755
|
|
|
742
|
-
const OK = ajv.validate(
|
|
756
|
+
const OK = ajv.validate(T, {
|
|
743
757
|
x: 1,
|
|
744
758
|
y: 2,
|
|
745
759
|
z: 3
|
|
@@ -752,7 +766,7 @@ Please refer to the official AJV [documentation](https://ajv.js.org/guide/gettin
|
|
|
752
766
|
|
|
753
767
|
### Compiler
|
|
754
768
|
|
|
755
|
-
TypeBox includes a specialized
|
|
769
|
+
TypeBox includes a specialized `TypeCompiler` that can be used as a runtime type checker in lieu of a JSON Schema validator. This compiler is optimized for high throughput Web Socket messaging and can perform better than AJV for some structural checks. Please note that this compiler is not fully JSON Schema compliant and is limited to known TypeBox types only. The `TypeCompiler` contains a `Compile(T)` function that returns a `TypeCheck<T>` object that can be used to test the validity of a value as well as obtain errors.
|
|
756
770
|
|
|
757
771
|
```typescript
|
|
758
772
|
import { TypeCompiler } from '@sinclair/typebox/compiler'
|
|
@@ -772,7 +786,7 @@ const OK = C.Check({
|
|
|
772
786
|
z: 3
|
|
773
787
|
}) // -> true
|
|
774
788
|
```
|
|
775
|
-
Errors can be obtained by calling the `Errors(...)` function. This function returns an iterator that may contain zero or more errors for the given value. For performance, you should only call `Errors(V)` if the `Check(V)` function returns false
|
|
789
|
+
Errors can be obtained by calling the `Errors(...)` function. This function returns an iterator that may contain zero or more errors for the given value. For performance, you should only call `Errors(V)` if the `Check(V)` function returns `false`.
|
|
776
790
|
```typescript
|
|
777
791
|
const C = TypeCompiler.Compile(Type.Object({
|
|
778
792
|
x: Type.Number(),
|
|
@@ -788,7 +802,7 @@ if(!C.Check(V)) {
|
|
|
788
802
|
}
|
|
789
803
|
}
|
|
790
804
|
```
|
|
791
|
-
|
|
805
|
+
The TypeCompiler generates JavaScript validation routines types that are evaluated at runtime. You can inspect the generated code by calling the `Code()` function of the `TypeCheck<T>` object.
|
|
792
806
|
|
|
793
807
|
```typescript
|
|
794
808
|
const C = TypeCompiler.Compile(Type.String())
|
|
@@ -808,4 +822,4 @@ console.log(C.Code())
|
|
|
808
822
|
|
|
809
823
|
### Contribute
|
|
810
824
|
|
|
811
|
-
TypeBox is open to community contribution
|
|
825
|
+
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/typebox.d.ts
CHANGED
|
@@ -22,12 +22,10 @@ export interface SchemaOptions {
|
|
|
22
22
|
title?: string;
|
|
23
23
|
/** Description of this schema */
|
|
24
24
|
description?: string;
|
|
25
|
-
/** Default value
|
|
25
|
+
/** Default value for this schema */
|
|
26
26
|
default?: any;
|
|
27
27
|
/** Example values matching this schema. */
|
|
28
28
|
examples?: any;
|
|
29
|
-
/** Design metadata for this schema */
|
|
30
|
-
design?: DesignType;
|
|
31
29
|
[prop: string]: any;
|
|
32
30
|
}
|
|
33
31
|
export interface TSchema extends SchemaOptions {
|
package/typebox.js
CHANGED
|
@@ -227,7 +227,7 @@ class TypeBuilder {
|
|
|
227
227
|
/** Creates a reference schema */
|
|
228
228
|
Ref(schema, options = {}) {
|
|
229
229
|
if (schema.$id === undefined)
|
|
230
|
-
throw Error('
|
|
230
|
+
throw Error('Type.Ref: Referenced schema must specify an $id');
|
|
231
231
|
return this.Create({ ...options, [exports.Kind]: 'Ref', $ref: schema.$id });
|
|
232
232
|
}
|
|
233
233
|
/** Creates a string type from a regular expression */
|
package/value/cast.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import * as Types from '../typebox';
|
|
2
|
+
export declare namespace ValueCast {
|
|
3
|
+
function Visit(schema: Types.TSchema, references: Types.TSchema[], value: any): any;
|
|
4
|
+
function Cast<T extends Types.TSchema, R extends Types.TSchema[]>(schema: T, references: [...R], value: any): Types.Static<T>;
|
|
5
|
+
}
|