@sinclair/typebox 0.26.0-dev.4 → 0.26.0-dev.5
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 +9 -4
- package/compiler/compiler.js +121 -97
- package/errors/errors.d.ts +5 -1
- package/errors/errors.js +173 -157
- package/package.json +1 -1
- package/readme.md +70 -71
- package/typebox.d.ts +16 -27
- package/typebox.js +104 -163
- package/value/cast.d.ts +6 -2
- package/value/cast.js +130 -111
- package/value/check.d.ts +5 -1
- package/value/check.js +168 -154
- package/value/convert.d.ts +6 -6
- package/value/convert.js +83 -74
- package/value/create.d.ts +6 -2
- package/value/create.js +102 -77
- package/value/value.d.ts +13 -3
- package/value/value.js +15 -15
package/compiler/compiler.d.ts
CHANGED
|
@@ -3,9 +3,10 @@ import { ValueErrorIterator } from '../errors/index';
|
|
|
3
3
|
export type CheckFunction = (value: unknown) => boolean;
|
|
4
4
|
export declare class TypeCheck<T extends Types.TSchema> {
|
|
5
5
|
private readonly schema;
|
|
6
|
+
private readonly references;
|
|
6
7
|
private readonly checkFunc;
|
|
7
8
|
private readonly code;
|
|
8
|
-
constructor(schema: T, checkFunc: CheckFunction, code: string);
|
|
9
|
+
constructor(schema: T, references: Types.TSchema[], checkFunc: CheckFunction, code: string);
|
|
9
10
|
/** Returns the generated assertion code used to validate this type. */
|
|
10
11
|
Code(): string;
|
|
11
12
|
/** Returns an iterator for each error in this value. */
|
|
@@ -20,14 +21,18 @@ export declare class TypeCompilerUnknownTypeError extends Error {
|
|
|
20
21
|
readonly schema: Types.TSchema;
|
|
21
22
|
constructor(schema: Types.TSchema);
|
|
22
23
|
}
|
|
23
|
-
export declare class
|
|
24
|
+
export declare class TypeCompilerDereferenceError extends Error {
|
|
25
|
+
readonly schema: Types.TRef;
|
|
26
|
+
constructor(schema: Types.TRef);
|
|
27
|
+
}
|
|
28
|
+
export declare class TypeCompilerTypeGuardError extends Error {
|
|
24
29
|
readonly schema: Types.TSchema;
|
|
25
30
|
constructor(schema: Types.TSchema);
|
|
26
31
|
}
|
|
27
32
|
/** Compiles Types for Runtime Type Checking */
|
|
28
33
|
export declare namespace TypeCompiler {
|
|
29
34
|
/** Returns the generated assertion code used to validate this type. */
|
|
30
|
-
function Code<T extends Types.TSchema>(schema: T): string;
|
|
35
|
+
function Code<T extends Types.TSchema>(schema: T, references: Types.TSchema[]): string;
|
|
31
36
|
/** Compiles the given type for runtime type checking. This compiler only accepts known TypeBox types non-inclusive of unsafe types. */
|
|
32
|
-
function Compile<T extends Types.TSchema>(schema: T): TypeCheck<T>;
|
|
37
|
+
function Compile<T extends Types.TSchema>(schema: T, references?: Types.TSchema[]): TypeCheck<T>;
|
|
33
38
|
}
|
package/compiler/compiler.js
CHANGED
|
@@ -27,7 +27,7 @@ THE SOFTWARE.
|
|
|
27
27
|
|
|
28
28
|
---------------------------------------------------------------------------*/
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
-
exports.TypeCompiler = exports.
|
|
30
|
+
exports.TypeCompiler = exports.TypeCompilerTypeGuardError = exports.TypeCompilerDereferenceError = exports.TypeCompilerUnknownTypeError = exports.MemberExpression = exports.TypeCheck = void 0;
|
|
31
31
|
const Types = require("../typebox");
|
|
32
32
|
const index_1 = require("../errors/index");
|
|
33
33
|
const index_2 = require("../system/index");
|
|
@@ -36,8 +36,9 @@ const hash_1 = require("../value/hash");
|
|
|
36
36
|
// TypeCheck
|
|
37
37
|
// -------------------------------------------------------------------
|
|
38
38
|
class TypeCheck {
|
|
39
|
-
constructor(schema, checkFunc, code) {
|
|
39
|
+
constructor(schema, references, checkFunc, code) {
|
|
40
40
|
this.schema = schema;
|
|
41
|
+
this.references = references;
|
|
41
42
|
this.checkFunc = checkFunc;
|
|
42
43
|
this.code = code;
|
|
43
44
|
}
|
|
@@ -47,7 +48,7 @@ class TypeCheck {
|
|
|
47
48
|
}
|
|
48
49
|
/** Returns an iterator for each error in this value. */
|
|
49
50
|
Errors(value) {
|
|
50
|
-
return index_1.ValueErrors.Errors(this.schema, value);
|
|
51
|
+
return index_1.ValueErrors.Errors(this.schema, this.references, value);
|
|
51
52
|
}
|
|
52
53
|
/** Returns true if the value matches the compiled type. */
|
|
53
54
|
Check(value) {
|
|
@@ -134,13 +135,20 @@ class TypeCompilerUnknownTypeError extends Error {
|
|
|
134
135
|
}
|
|
135
136
|
}
|
|
136
137
|
exports.TypeCompilerUnknownTypeError = TypeCompilerUnknownTypeError;
|
|
137
|
-
class
|
|
138
|
+
class TypeCompilerDereferenceError extends Error {
|
|
138
139
|
constructor(schema) {
|
|
139
|
-
super(
|
|
140
|
+
super(`TypeCompiler: Unable to dereference schema with $id '${schema.$ref}'`);
|
|
140
141
|
this.schema = schema;
|
|
141
142
|
}
|
|
142
143
|
}
|
|
143
|
-
exports.
|
|
144
|
+
exports.TypeCompilerDereferenceError = TypeCompilerDereferenceError;
|
|
145
|
+
class TypeCompilerTypeGuardError extends Error {
|
|
146
|
+
constructor(schema) {
|
|
147
|
+
super('TypeCompiler: Preflight validation check failed to guard for the given schema');
|
|
148
|
+
this.schema = schema;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
exports.TypeCompilerTypeGuardError = TypeCompilerTypeGuardError;
|
|
144
152
|
/** Compiles Types for Runtime Type Checking */
|
|
145
153
|
var TypeCompiler;
|
|
146
154
|
(function (TypeCompiler) {
|
|
@@ -153,14 +161,17 @@ var TypeCompiler;
|
|
|
153
161
|
function IsNumber(value) {
|
|
154
162
|
return typeof value === 'number' && globalThis.Number.isFinite(value);
|
|
155
163
|
}
|
|
164
|
+
function IsString(value) {
|
|
165
|
+
return typeof value === 'string';
|
|
166
|
+
}
|
|
156
167
|
// -------------------------------------------------------------------
|
|
157
168
|
// Types
|
|
158
169
|
// -------------------------------------------------------------------
|
|
159
|
-
function* Any(schema, value) {
|
|
170
|
+
function* Any(schema, references, value) {
|
|
160
171
|
yield 'true';
|
|
161
172
|
}
|
|
162
|
-
function* Array(schema, value) {
|
|
163
|
-
const expression = CreateExpression(schema.items, 'value');
|
|
173
|
+
function* Array(schema, references, value) {
|
|
174
|
+
const expression = CreateExpression(schema.items, references, 'value');
|
|
164
175
|
yield `Array.isArray(${value}) && ${value}.every(value => ${expression})`;
|
|
165
176
|
if (IsNumber(schema.minItems))
|
|
166
177
|
yield `${value}.length >= ${schema.minItems}`;
|
|
@@ -169,7 +180,7 @@ var TypeCompiler;
|
|
|
169
180
|
if (schema.uniqueItems === true)
|
|
170
181
|
yield `((function() { const set = new Set(); for(const element of ${value}) { const hashed = hash(element); if(set.has(hashed)) { return false } else { set.add(hashed) } } return true })())`;
|
|
171
182
|
}
|
|
172
|
-
function* BigInt(schema, value) {
|
|
183
|
+
function* BigInt(schema, references, value) {
|
|
173
184
|
yield `(typeof ${value} === 'bigint')`;
|
|
174
185
|
if (IsBigInt(schema.multipleOf))
|
|
175
186
|
yield `(${value} % BigInt(${schema.multipleOf})) === 0`;
|
|
@@ -182,13 +193,13 @@ var TypeCompiler;
|
|
|
182
193
|
if (IsBigInt(schema.maximum))
|
|
183
194
|
yield `${value} <= BigInt(${schema.maximum})`;
|
|
184
195
|
}
|
|
185
|
-
function* Boolean(schema, value) {
|
|
196
|
+
function* Boolean(schema, references, value) {
|
|
186
197
|
yield `typeof ${value} === 'boolean'`;
|
|
187
198
|
}
|
|
188
|
-
function* Constructor(schema, value) {
|
|
189
|
-
yield* Visit(schema.returns, `${value}.prototype`);
|
|
199
|
+
function* Constructor(schema, references, value) {
|
|
200
|
+
yield* Visit(schema.returns, references, `${value}.prototype`);
|
|
190
201
|
}
|
|
191
|
-
function* Date(schema, value) {
|
|
202
|
+
function* Date(schema, references, value) {
|
|
192
203
|
yield `(${value} instanceof Date) && Number.isFinite(${value}.getTime())`;
|
|
193
204
|
if (IsNumber(schema.exclusiveMinimumTimestamp))
|
|
194
205
|
yield `${value}.getTime() > ${schema.exclusiveMinimumTimestamp}`;
|
|
@@ -199,10 +210,10 @@ var TypeCompiler;
|
|
|
199
210
|
if (IsNumber(schema.maximumTimestamp))
|
|
200
211
|
yield `${value}.getTime() <= ${schema.maximumTimestamp}`;
|
|
201
212
|
}
|
|
202
|
-
function* Function(schema, value) {
|
|
213
|
+
function* Function(schema, references, value) {
|
|
203
214
|
yield `typeof ${value} === 'function'`;
|
|
204
215
|
}
|
|
205
|
-
function* Integer(schema, value) {
|
|
216
|
+
function* Integer(schema, references, value) {
|
|
206
217
|
yield `(typeof ${value} === 'number' && Number.isInteger(${value}))`;
|
|
207
218
|
if (IsNumber(schema.multipleOf))
|
|
208
219
|
yield `(${value} % ${schema.multipleOf}) === 0`;
|
|
@@ -215,28 +226,28 @@ var TypeCompiler;
|
|
|
215
226
|
if (IsNumber(schema.maximum))
|
|
216
227
|
yield `${value} <= ${schema.maximum}`;
|
|
217
228
|
}
|
|
218
|
-
function* Intersect(schema, value) {
|
|
229
|
+
function* Intersect(schema, references, value) {
|
|
219
230
|
if (schema.unevaluatedProperties === undefined) {
|
|
220
|
-
const expressions = schema.allOf.map((schema) => CreateExpression(schema, value));
|
|
231
|
+
const expressions = schema.allOf.map((schema) => CreateExpression(schema, references, value));
|
|
221
232
|
yield `${expressions.join(' && ')}`;
|
|
222
233
|
}
|
|
223
234
|
else if (schema.unevaluatedProperties === false) {
|
|
224
235
|
// prettier-ignore
|
|
225
236
|
const schemaKeys = Types.KeyResolver.Resolve(schema).map((key) => `'${key}'`).join(', ');
|
|
226
|
-
const expressions = schema.allOf.map((schema) => CreateExpression(schema, value));
|
|
237
|
+
const expressions = schema.allOf.map((schema) => CreateExpression(schema, references, value));
|
|
227
238
|
const expression1 = `Object.getOwnPropertyNames(${value}).every(key => [${schemaKeys}].includes(key))`;
|
|
228
239
|
yield `${expressions.join(' && ')} && ${expression1}`;
|
|
229
240
|
}
|
|
230
241
|
else if (typeof schema.unevaluatedProperties === 'object') {
|
|
231
242
|
// prettier-ignore
|
|
232
243
|
const schemaKeys = Types.KeyResolver.Resolve(schema).map((key) => `'${key}'`).join(', ');
|
|
233
|
-
const expressions = schema.allOf.map((schema) => CreateExpression(schema, value));
|
|
234
|
-
const expression1 = CreateExpression(schema.unevaluatedProperties, 'value[key]');
|
|
244
|
+
const expressions = schema.allOf.map((schema) => CreateExpression(schema, references, value));
|
|
245
|
+
const expression1 = CreateExpression(schema.unevaluatedProperties, references, 'value[key]');
|
|
235
246
|
const expression2 = `Object.getOwnPropertyNames(${value}).every(key => [${schemaKeys}].includes(key) || ${expression1})`;
|
|
236
247
|
yield `${expressions.join(' && ')} && ${expression2}`;
|
|
237
248
|
}
|
|
238
249
|
}
|
|
239
|
-
function* Literal(schema, value) {
|
|
250
|
+
function* Literal(schema, references, value) {
|
|
240
251
|
if (typeof schema.const === 'number' || typeof schema.const === 'boolean') {
|
|
241
252
|
yield `${value} === ${schema.const}`;
|
|
242
253
|
}
|
|
@@ -244,18 +255,18 @@ var TypeCompiler;
|
|
|
244
255
|
yield `${value} === '${schema.const}'`;
|
|
245
256
|
}
|
|
246
257
|
}
|
|
247
|
-
function* Never(schema, value) {
|
|
258
|
+
function* Never(schema, references, value) {
|
|
248
259
|
yield `false`;
|
|
249
260
|
}
|
|
250
|
-
function* Not(schema, value) {
|
|
251
|
-
const left = CreateExpression(schema.allOf[0].not, value);
|
|
252
|
-
const right = CreateExpression(schema.allOf[1], value);
|
|
261
|
+
function* Not(schema, references, value) {
|
|
262
|
+
const left = CreateExpression(schema.allOf[0].not, references, value);
|
|
263
|
+
const right = CreateExpression(schema.allOf[1], references, value);
|
|
253
264
|
yield `!${left} && ${right}`;
|
|
254
265
|
}
|
|
255
|
-
function* Null(schema, value) {
|
|
266
|
+
function* Null(schema, references, value) {
|
|
256
267
|
yield `${value} === null`;
|
|
257
268
|
}
|
|
258
|
-
function* Number(schema, value) {
|
|
269
|
+
function* Number(schema, references, value) {
|
|
259
270
|
yield `typeof ${value} === 'number'`;
|
|
260
271
|
if (!index_2.TypeSystem.AllowNaN)
|
|
261
272
|
yield `Number.isFinite(${value})`;
|
|
@@ -270,8 +281,13 @@ var TypeCompiler;
|
|
|
270
281
|
if (IsNumber(schema.maximum))
|
|
271
282
|
yield `${value} <= ${schema.maximum}`;
|
|
272
283
|
}
|
|
273
|
-
function* Object(schema, value) {
|
|
274
|
-
|
|
284
|
+
function* Object(schema, references, value) {
|
|
285
|
+
if (!index_2.TypeSystem.AllowArrayObjects) {
|
|
286
|
+
yield `(typeof ${value} === 'object' && ${value} !== null && !Array.isArray(${value}))`;
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
yield `(typeof ${value} === 'object' && ${value} !== null)`;
|
|
290
|
+
}
|
|
275
291
|
if (!index_2.TypeSystem.AllowArrayObjects)
|
|
276
292
|
yield `!Array.isArray(${value})`;
|
|
277
293
|
if (IsNumber(schema.minProperties))
|
|
@@ -283,12 +299,12 @@ var TypeCompiler;
|
|
|
283
299
|
const memberExpression = MemberExpression.Encode(value, schemaKey);
|
|
284
300
|
const property = schema.properties[schemaKey];
|
|
285
301
|
if (schema.required && schema.required.includes(schemaKey)) {
|
|
286
|
-
yield* Visit(property, memberExpression);
|
|
302
|
+
yield* Visit(property, references, memberExpression);
|
|
287
303
|
if (Types.ExtendsUndefined.Check(property))
|
|
288
304
|
yield `('${schemaKey}' in ${value})`;
|
|
289
305
|
}
|
|
290
306
|
else {
|
|
291
|
-
const expression = CreateExpression(property, memberExpression);
|
|
307
|
+
const expression = CreateExpression(property, references, memberExpression);
|
|
292
308
|
yield `('${schemaKey}' in ${value} ? ${expression} : true)`;
|
|
293
309
|
}
|
|
294
310
|
}
|
|
@@ -302,37 +318,41 @@ var TypeCompiler;
|
|
|
302
318
|
}
|
|
303
319
|
}
|
|
304
320
|
if (typeof schema.additionalProperties === 'object') {
|
|
305
|
-
const expression = CreateExpression(schema.additionalProperties, 'value[key]');
|
|
321
|
+
const expression = CreateExpression(schema.additionalProperties, references, 'value[key]');
|
|
306
322
|
const keys = `[${schemaKeys.map((key) => `'${key}'`).join(', ')}]`;
|
|
307
323
|
yield `(Object.getOwnPropertyNames(${value}).every(key => ${keys}.includes(key) || ${expression}))`;
|
|
308
324
|
}
|
|
309
325
|
}
|
|
310
|
-
function* Promise(schema, value) {
|
|
326
|
+
function* Promise(schema, references, value) {
|
|
311
327
|
yield `(typeof value === 'object' && typeof ${value}.then === 'function')`;
|
|
312
328
|
}
|
|
313
|
-
function* Record(schema, value) {
|
|
314
|
-
yield `(typeof ${value} === 'object' && ${value} !== null && !(${value} instanceof Date))`;
|
|
329
|
+
function* Record(schema, references, value) {
|
|
330
|
+
yield `(typeof ${value} === 'object' && ${value} !== null && !(${value} instanceof Date) && !(${value} instanceof Uint8Array))`;
|
|
315
331
|
if (!index_2.TypeSystem.AllowArrayObjects)
|
|
316
332
|
yield `!Array.isArray(${value})`;
|
|
317
333
|
const [keyPattern, valueSchema] = globalThis.Object.entries(schema.patternProperties)[0];
|
|
318
334
|
const local = PushLocal(`new RegExp(/${keyPattern}/)`);
|
|
319
335
|
yield `(Object.getOwnPropertyNames(${value}).every(key => ${local}.test(key)))`;
|
|
320
|
-
const expression = CreateExpression(valueSchema, 'value');
|
|
336
|
+
const expression = CreateExpression(valueSchema, references, 'value');
|
|
321
337
|
yield `Object.values(${value}).every(value => ${expression})`;
|
|
322
338
|
}
|
|
323
|
-
function* Ref(schema, value) {
|
|
339
|
+
function* Ref(schema, references, value) {
|
|
340
|
+
const index = references.findIndex((foreign) => foreign.$id === schema.$ref);
|
|
341
|
+
if (index === -1)
|
|
342
|
+
throw new TypeCompilerDereferenceError(schema);
|
|
343
|
+
const target = references[index];
|
|
324
344
|
// Reference: If we have seen this reference before we can just yield and return
|
|
325
345
|
// the function call. If this isn't the case we defer to visit to generate and
|
|
326
346
|
// set the function for subsequent passes. Consider for refactor.
|
|
327
347
|
if (state_local_function_names.has(schema.$ref))
|
|
328
348
|
return yield `${CreateFunctionName(schema.$ref)}(${value})`;
|
|
329
|
-
yield* Visit(
|
|
349
|
+
yield* Visit(target, references, value);
|
|
330
350
|
}
|
|
331
|
-
function* Self(schema, value) {
|
|
351
|
+
function* Self(schema, references, value) {
|
|
332
352
|
const func = CreateFunctionName(schema.$ref);
|
|
333
353
|
yield `${func}(${value})`;
|
|
334
354
|
}
|
|
335
|
-
function* String(schema, value) {
|
|
355
|
+
function* String(schema, references, value) {
|
|
336
356
|
yield `(typeof ${value} === 'string')`;
|
|
337
357
|
if (IsNumber(schema.minLength))
|
|
338
358
|
yield `${value}.length >= ${schema.minLength}`;
|
|
@@ -346,37 +366,37 @@ var TypeCompiler;
|
|
|
346
366
|
yield `format('${schema.format}', ${value})`;
|
|
347
367
|
}
|
|
348
368
|
}
|
|
349
|
-
function* Symbol(schema, value) {
|
|
369
|
+
function* Symbol(schema, references, value) {
|
|
350
370
|
yield `(typeof ${value} === 'symbol')`;
|
|
351
371
|
}
|
|
352
|
-
function* Tuple(schema, value) {
|
|
372
|
+
function* Tuple(schema, references, value) {
|
|
353
373
|
yield `(Array.isArray(${value}))`;
|
|
354
374
|
if (schema.items === undefined)
|
|
355
375
|
return yield `${value}.length === 0`;
|
|
356
376
|
yield `(${value}.length === ${schema.maxItems})`;
|
|
357
377
|
for (let i = 0; i < schema.items.length; i++) {
|
|
358
|
-
const expression = CreateExpression(schema.items[i], `${value}[${i}]`);
|
|
378
|
+
const expression = CreateExpression(schema.items[i], references, `${value}[${i}]`);
|
|
359
379
|
yield `${expression}`;
|
|
360
380
|
}
|
|
361
381
|
}
|
|
362
|
-
function* Undefined(schema, value) {
|
|
382
|
+
function* Undefined(schema, references, value) {
|
|
363
383
|
yield `${value} === undefined`;
|
|
364
384
|
}
|
|
365
|
-
function* Union(schema, value) {
|
|
366
|
-
const expressions = schema.anyOf.map((schema) => CreateExpression(schema, value));
|
|
385
|
+
function* Union(schema, references, value) {
|
|
386
|
+
const expressions = schema.anyOf.map((schema) => CreateExpression(schema, references, value));
|
|
367
387
|
yield `(${expressions.join(' || ')})`;
|
|
368
388
|
}
|
|
369
|
-
function* Uint8Array(schema, value) {
|
|
389
|
+
function* Uint8Array(schema, references, value) {
|
|
370
390
|
yield `${value} instanceof Uint8Array`;
|
|
371
391
|
if (IsNumber(schema.maxByteLength))
|
|
372
392
|
yield `(${value}.length <= ${schema.maxByteLength})`;
|
|
373
393
|
if (IsNumber(schema.minByteLength))
|
|
374
394
|
yield `(${value}.length >= ${schema.minByteLength})`;
|
|
375
395
|
}
|
|
376
|
-
function* Unknown(schema, value) {
|
|
396
|
+
function* Unknown(schema, references, value) {
|
|
377
397
|
yield 'true';
|
|
378
398
|
}
|
|
379
|
-
function* Void(schema, value) {
|
|
399
|
+
function* Void(schema, references, value) {
|
|
380
400
|
if (index_2.TypeSystem.AllowVoidNull) {
|
|
381
401
|
yield `(${value} === undefined || ${value} === null)`;
|
|
382
402
|
}
|
|
@@ -384,83 +404,84 @@ var TypeCompiler;
|
|
|
384
404
|
yield `${value} === undefined`;
|
|
385
405
|
}
|
|
386
406
|
}
|
|
387
|
-
function* UserDefined(schema, value) {
|
|
407
|
+
function* UserDefined(schema, references, value) {
|
|
388
408
|
const schema_key = `schema_key_${state_remote_custom_types.size}`;
|
|
389
409
|
state_remote_custom_types.set(schema_key, schema);
|
|
390
410
|
yield `custom('${schema[Types.Kind]}', '${schema_key}', ${value})`;
|
|
391
411
|
}
|
|
392
|
-
function* Visit(schema, value) {
|
|
412
|
+
function* Visit(schema, references, value) {
|
|
413
|
+
const references_ = IsString(schema.$id) ? [...references, schema] : references;
|
|
414
|
+
const schema_ = schema;
|
|
393
415
|
// Reference: Referenced schemas can originate from either additional schemas
|
|
394
416
|
// or inline in the schema itself. Ideally the recursive path should align to
|
|
395
417
|
// reference path. Consider for refactor.
|
|
396
|
-
if (schema.$id && !state_local_function_names.has(schema.$id)) {
|
|
418
|
+
if (IsString(schema.$id) && !state_local_function_names.has(schema.$id)) {
|
|
397
419
|
state_local_function_names.add(schema.$id);
|
|
398
420
|
const name = CreateFunctionName(schema.$id);
|
|
399
|
-
const body = CreateFunction(name, schema, 'value');
|
|
421
|
+
const body = CreateFunction(name, schema, references, 'value');
|
|
400
422
|
PushFunction(body);
|
|
401
423
|
yield `${name}(${value})`;
|
|
402
424
|
return;
|
|
403
425
|
}
|
|
404
|
-
|
|
405
|
-
switch (anySchema[Types.Kind]) {
|
|
426
|
+
switch (schema_[Types.Kind]) {
|
|
406
427
|
case 'Any':
|
|
407
|
-
return yield* Any(
|
|
428
|
+
return yield* Any(schema_, references_, value);
|
|
408
429
|
case 'Array':
|
|
409
|
-
return yield* Array(
|
|
430
|
+
return yield* Array(schema_, references_, value);
|
|
410
431
|
case 'BigInt':
|
|
411
|
-
return yield* BigInt(
|
|
432
|
+
return yield* BigInt(schema_, references_, value);
|
|
412
433
|
case 'Boolean':
|
|
413
|
-
return yield* Boolean(
|
|
434
|
+
return yield* Boolean(schema_, references_, value);
|
|
414
435
|
case 'Constructor':
|
|
415
|
-
return yield* Constructor(
|
|
436
|
+
return yield* Constructor(schema_, references_, value);
|
|
416
437
|
case 'Date':
|
|
417
|
-
return yield* Date(
|
|
438
|
+
return yield* Date(schema_, references_, value);
|
|
418
439
|
case 'Function':
|
|
419
|
-
return yield* Function(
|
|
440
|
+
return yield* Function(schema_, references_, value);
|
|
420
441
|
case 'Integer':
|
|
421
|
-
return yield* Integer(
|
|
442
|
+
return yield* Integer(schema_, references_, value);
|
|
422
443
|
case 'Intersect':
|
|
423
|
-
return yield* Intersect(
|
|
444
|
+
return yield* Intersect(schema_, references_, value);
|
|
424
445
|
case 'Literal':
|
|
425
|
-
return yield* Literal(
|
|
446
|
+
return yield* Literal(schema_, references_, value);
|
|
426
447
|
case 'Never':
|
|
427
|
-
return yield* Never(
|
|
448
|
+
return yield* Never(schema_, references_, value);
|
|
428
449
|
case 'Not':
|
|
429
|
-
return yield* Not(
|
|
450
|
+
return yield* Not(schema_, references_, value);
|
|
430
451
|
case 'Null':
|
|
431
|
-
return yield* Null(
|
|
452
|
+
return yield* Null(schema_, references_, value);
|
|
432
453
|
case 'Number':
|
|
433
|
-
return yield* Number(
|
|
454
|
+
return yield* Number(schema_, references_, value);
|
|
434
455
|
case 'Object':
|
|
435
|
-
return yield* Object(
|
|
456
|
+
return yield* Object(schema_, references_, value);
|
|
436
457
|
case 'Promise':
|
|
437
|
-
return yield* Promise(
|
|
458
|
+
return yield* Promise(schema_, references_, value);
|
|
438
459
|
case 'Record':
|
|
439
|
-
return yield* Record(
|
|
460
|
+
return yield* Record(schema_, references_, value);
|
|
440
461
|
case 'Ref':
|
|
441
|
-
return yield* Ref(
|
|
462
|
+
return yield* Ref(schema_, references_, value);
|
|
442
463
|
case 'Self':
|
|
443
|
-
return yield* Self(
|
|
464
|
+
return yield* Self(schema_, references_, value);
|
|
444
465
|
case 'String':
|
|
445
|
-
return yield* String(
|
|
466
|
+
return yield* String(schema_, references_, value);
|
|
446
467
|
case 'Symbol':
|
|
447
|
-
return yield* Symbol(
|
|
468
|
+
return yield* Symbol(schema_, references_, value);
|
|
448
469
|
case 'Tuple':
|
|
449
|
-
return yield* Tuple(
|
|
470
|
+
return yield* Tuple(schema_, references_, value);
|
|
450
471
|
case 'Undefined':
|
|
451
|
-
return yield* Undefined(
|
|
472
|
+
return yield* Undefined(schema_, references_, value);
|
|
452
473
|
case 'Union':
|
|
453
|
-
return yield* Union(
|
|
474
|
+
return yield* Union(schema_, references_, value);
|
|
454
475
|
case 'Uint8Array':
|
|
455
|
-
return yield* Uint8Array(
|
|
476
|
+
return yield* Uint8Array(schema_, references_, value);
|
|
456
477
|
case 'Unknown':
|
|
457
|
-
return yield* Unknown(
|
|
478
|
+
return yield* Unknown(schema_, references_, value);
|
|
458
479
|
case 'Void':
|
|
459
|
-
return yield* Void(
|
|
480
|
+
return yield* Void(schema_, references_, value);
|
|
460
481
|
default:
|
|
461
|
-
if (!Types.TypeRegistry.Has(
|
|
482
|
+
if (!Types.TypeRegistry.Has(schema_[Types.Kind]))
|
|
462
483
|
throw new TypeCompilerUnknownTypeError(schema);
|
|
463
|
-
return yield* UserDefined(
|
|
484
|
+
return yield* UserDefined(schema_, references_, value);
|
|
464
485
|
}
|
|
465
486
|
}
|
|
466
487
|
// -------------------------------------------------------------------
|
|
@@ -474,14 +495,14 @@ var TypeCompiler;
|
|
|
474
495
|
state_local_function_names.clear();
|
|
475
496
|
state_remote_custom_types.clear();
|
|
476
497
|
}
|
|
477
|
-
function CreateExpression(schema, value) {
|
|
478
|
-
return `(${[...Visit(schema, value)].join(' && ')})`;
|
|
498
|
+
function CreateExpression(schema, references, value) {
|
|
499
|
+
return `(${[...Visit(schema, references, value)].join(' && ')})`;
|
|
479
500
|
}
|
|
480
501
|
function CreateFunctionName($id) {
|
|
481
502
|
return `check_${Identifier.Encode($id)}`;
|
|
482
503
|
}
|
|
483
|
-
function CreateFunction(name, schema, value) {
|
|
484
|
-
const expression = [...Visit(schema, value)].map((condition) => ` ${condition}`).join(' &&\n');
|
|
504
|
+
function CreateFunction(name, schema, references, value) {
|
|
505
|
+
const expression = [...Visit(schema, references, value)].map((condition) => ` ${condition}`).join(' &&\n');
|
|
485
506
|
return `function ${name}(value) {\n return (\n${expression}\n )\n}`;
|
|
486
507
|
}
|
|
487
508
|
function PushFunction(functionBody) {
|
|
@@ -498,22 +519,25 @@ var TypeCompiler;
|
|
|
498
519
|
// -------------------------------------------------------------------
|
|
499
520
|
// Compile
|
|
500
521
|
// -------------------------------------------------------------------
|
|
501
|
-
function Build(schema) {
|
|
522
|
+
function Build(schema, references) {
|
|
502
523
|
ResetCompiler();
|
|
503
|
-
const check = CreateFunction('check', schema, 'value');
|
|
524
|
+
const check = CreateFunction('check', schema, references, 'value');
|
|
504
525
|
const locals = GetLocals();
|
|
505
526
|
return `${locals.join('\n')}\nreturn ${check}`;
|
|
506
527
|
}
|
|
507
528
|
/** Returns the generated assertion code used to validate this type. */
|
|
508
|
-
function Code(schema) {
|
|
529
|
+
function Code(schema, references) {
|
|
509
530
|
if (!Types.TypeGuard.TSchema(schema))
|
|
510
|
-
throw new
|
|
511
|
-
|
|
531
|
+
throw new TypeCompilerTypeGuardError(schema);
|
|
532
|
+
for (const schema of references)
|
|
533
|
+
if (!Types.TypeGuard.TSchema(schema))
|
|
534
|
+
throw new TypeCompilerTypeGuardError(schema);
|
|
535
|
+
return Build(schema, references);
|
|
512
536
|
}
|
|
513
537
|
TypeCompiler.Code = Code;
|
|
514
538
|
/** Compiles the given type for runtime type checking. This compiler only accepts known TypeBox types non-inclusive of unsafe types. */
|
|
515
|
-
function Compile(schema) {
|
|
516
|
-
const code = Code(schema);
|
|
539
|
+
function Compile(schema, references = []) {
|
|
540
|
+
const code = Code(schema, references);
|
|
517
541
|
const custom_schemas = new Map(state_remote_custom_types);
|
|
518
542
|
const compiledFunction = globalThis.Function('custom', 'format', 'hash', code);
|
|
519
543
|
const checkFunction = compiledFunction((kind, schema_key, value) => {
|
|
@@ -530,7 +554,7 @@ var TypeCompiler;
|
|
|
530
554
|
}, (value) => {
|
|
531
555
|
return hash_1.ValueHash.Create(value);
|
|
532
556
|
});
|
|
533
|
-
return new TypeCheck(schema, checkFunction, code);
|
|
557
|
+
return new TypeCheck(schema, references, checkFunction, code);
|
|
534
558
|
}
|
|
535
559
|
TypeCompiler.Compile = Compile;
|
|
536
560
|
})(TypeCompiler = exports.TypeCompiler || (exports.TypeCompiler = {}));
|
package/errors/errors.d.ts
CHANGED
|
@@ -78,7 +78,11 @@ export declare class ValueErrorsUnknownTypeError extends Error {
|
|
|
78
78
|
readonly schema: Types.TSchema;
|
|
79
79
|
constructor(schema: Types.TSchema);
|
|
80
80
|
}
|
|
81
|
+
export declare class ValueErrorsDereferenceError extends Error {
|
|
82
|
+
readonly schema: Types.TRef | Types.TSelf;
|
|
83
|
+
constructor(schema: Types.TRef | Types.TSelf);
|
|
84
|
+
}
|
|
81
85
|
/** Provides functionality to generate a sequence of errors against a TypeBox type. */
|
|
82
86
|
export declare namespace ValueErrors {
|
|
83
|
-
function Errors<T extends Types.TSchema>(schema: T, value: any): ValueErrorIterator;
|
|
87
|
+
function Errors<T extends Types.TSchema>(schema: T, references: Types.TSchema[], value: any): ValueErrorIterator;
|
|
84
88
|
}
|