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