@sinclair/typebox 0.28.16 → 0.28.18

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.
@@ -26,10 +26,13 @@ export declare class TypeCompilerTypeGuardError extends Error {
26
26
  readonly schema: Types.TSchema;
27
27
  constructor(schema: Types.TSchema);
28
28
  }
29
+ export interface TypeCompilerOptions {
30
+ language?: 'typescript' | 'javascript';
31
+ }
29
32
  /** Compiles Types for Runtime Type Checking */
30
33
  export declare namespace TypeCompiler {
31
34
  /** Returns the generated assertion code used to validate this type. */
32
- function Code<T extends Types.TSchema>(schema: T, references?: Types.TSchema[]): string;
35
+ function Code<T extends Types.TSchema>(schema: T, references?: Types.TSchema[], options?: TypeCompilerOptions): string;
33
36
  /** Compiles the given type for runtime type checking. This compiler only accepts known TypeBox types non-inclusive of unsafe types. */
34
37
  function Compile<T extends Types.TSchema>(schema: T, references?: Types.TSchema[]): TypeCheck<T>;
35
38
  }
@@ -207,7 +207,8 @@ var TypeCompiler;
207
207
  if (schema.uniqueItems === true)
208
208
  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 })())`;
209
209
  const expression = CreateExpression(schema.items, references, 'value');
210
- yield `${value}.every(value => ${expression})`;
210
+ const parameter = CreateParameter('value', 'any');
211
+ yield `${value}.every((${parameter}) => ${expression})`;
211
212
  }
212
213
  function* BigInt(schema, references, value) {
213
214
  yield `(typeof ${value} === 'bigint')`;
@@ -223,7 +224,7 @@ var TypeCompiler;
223
224
  yield `${value} <= BigInt(${schema.maximum})`;
224
225
  }
225
226
  function* Boolean(schema, references, value) {
226
- yield `typeof ${value} === 'boolean'`;
227
+ yield `(typeof ${value} === 'boolean')`;
227
228
  }
228
229
  function* Constructor(schema, references, value) {
229
230
  yield* Visit(schema.returns, references, `${value}.prototype`);
@@ -240,7 +241,7 @@ var TypeCompiler;
240
241
  yield `${value}.getTime() <= ${schema.maximumTimestamp}`;
241
242
  }
242
243
  function* Function(schema, references, value) {
243
- yield `typeof ${value} === 'function'`;
244
+ yield `(typeof ${value} === 'function')`;
244
245
  }
245
246
  function* Integer(schema, references, value) {
246
247
  yield `(typeof ${value} === 'number' && Number.isInteger(${value}))`;
@@ -260,23 +261,23 @@ var TypeCompiler;
260
261
  if (schema.unevaluatedProperties === false) {
261
262
  const keyCheck = PushLocal(`${new RegExp(Types.KeyResolver.ResolvePattern(schema))};`);
262
263
  const check2 = `Object.getOwnPropertyNames(${value}).every(key => ${keyCheck}.test(key))`;
263
- yield `${check1} && ${check2}`;
264
+ yield `(${check1} && ${check2})`;
264
265
  }
265
266
  else if (Types.TypeGuard.TSchema(schema.unevaluatedProperties)) {
266
267
  const keyCheck = PushLocal(`${new RegExp(Types.KeyResolver.ResolvePattern(schema))};`);
267
268
  const check2 = `Object.getOwnPropertyNames(${value}).every(key => ${keyCheck}.test(key) || ${CreateExpression(schema.unevaluatedProperties, references, `${value}[key]`)})`;
268
- yield `${check1} && ${check2}`;
269
+ yield `(${check1} && ${check2})`;
269
270
  }
270
271
  else {
271
- yield `${check1}`;
272
+ yield `(${check1})`;
272
273
  }
273
274
  }
274
275
  function* Literal(schema, references, value) {
275
276
  if (typeof schema.const === 'number' || typeof schema.const === 'boolean') {
276
- yield `${value} === ${schema.const}`;
277
+ yield `(${value} === ${schema.const})`;
277
278
  }
278
279
  else {
279
- yield `${value} === '${schema.const}'`;
280
+ yield `(${value} === '${schema.const}')`;
280
281
  }
281
282
  }
282
283
  function* Never(schema, references, value) {
@@ -288,7 +289,7 @@ var TypeCompiler;
288
289
  yield `!${left} && ${right}`;
289
290
  }
290
291
  function* Null(schema, references, value) {
291
- yield `${value} === null`;
292
+ yield `(${value} === null)`;
292
293
  }
293
294
  function* Number(schema, references, value) {
294
295
  yield IsNumberCheck(value);
@@ -362,7 +363,7 @@ var TypeCompiler;
362
363
  // Reference: If we have seen this reference before we can just yield and
363
364
  // return the function call. If this isn't the case we defer to visit to
364
365
  // generate and set the function for subsequent passes.
365
- if (state_local_function_names.has(schema.$ref))
366
+ if (state.functions.has(schema.$ref))
366
367
  return yield `${CreateFunctionName(schema.$ref)}(${value})`;
367
368
  yield* Visit(target, references, value);
368
369
  }
@@ -423,8 +424,8 @@ var TypeCompiler;
423
424
  yield IsVoidCheck(value);
424
425
  }
425
426
  function* UserDefined(schema, references, value) {
426
- const schema_key = `schema_key_${state_remote_custom_types.size}`;
427
- state_remote_custom_types.set(schema_key, schema);
427
+ const schema_key = `schema_key_${state.customs.size}`;
428
+ state.customs.set(schema_key, schema);
428
429
  yield `custom('${schema[Types.Kind]}', '${schema_key}', ${value})`;
429
430
  }
430
431
  function* Visit(schema, references, value, root = false) {
@@ -439,8 +440,8 @@ var TypeCompiler;
439
440
  // by refactoring the logic below. Consider for review.
440
441
  if (IsString(schema.$id)) {
441
442
  const name = CreateFunctionName(schema.$id);
442
- if (!state_local_function_names.has(schema.$id)) {
443
- state_local_function_names.add(schema.$id);
443
+ if (!state.functions.has(schema.$id)) {
444
+ state.functions.add(schema.$id);
444
445
  const body = CreateFunction(name, schema, references, 'value');
445
446
  PushFunction(body);
446
447
  }
@@ -513,49 +514,63 @@ var TypeCompiler;
513
514
  // -------------------------------------------------------------------
514
515
  // Compiler State
515
516
  // -------------------------------------------------------------------
516
- const state_local_variables = new Set(); // local variables and functions
517
- const state_local_function_names = new Set(); // local function names used call ref validators
518
- const state_remote_custom_types = new Map(); // remote custom types used during compilation
519
- function ResetCompiler() {
520
- state_local_variables.clear();
521
- state_local_function_names.clear();
522
- state_remote_custom_types.clear();
517
+ // prettier-ignore
518
+ const state = {
519
+ language: 'javascript',
520
+ variables: new Set(),
521
+ functions: new Set(),
522
+ customs: new Map(), // custom type data
523
+ };
524
+ function CreateFunctionName($id) {
525
+ return `check_${Identifier.Encode($id)}`;
523
526
  }
524
527
  function CreateExpression(schema, references, value) {
525
528
  return `(${[...Visit(schema, references, value)].join(' && ')})`;
526
529
  }
527
- function CreateFunctionName($id) {
528
- return `check_${Identifier.Encode($id)}`;
530
+ function CreateParameter(name, type) {
531
+ const annotation = state.language === 'typescript' ? `: ${type}` : '';
532
+ return `${name}${annotation}`;
533
+ }
534
+ function CreateReturns(type) {
535
+ return state.language === 'typescript' ? `: ${type}` : '';
529
536
  }
530
537
  function CreateFunction(name, schema, references, value) {
531
538
  const expression = [...Visit(schema, references, value, true)].map((condition) => ` ${condition}`).join(' &&\n');
532
- return `function ${name}(value) {\n return (\n${expression}\n )\n}`;
539
+ const parameter = CreateParameter('value', 'any');
540
+ const returns = CreateReturns('boolean');
541
+ return `function ${name}(${parameter})${returns} {\n return (\n${expression}\n )\n}`;
533
542
  }
534
543
  function PushFunction(functionBody) {
535
- state_local_variables.add(functionBody);
544
+ state.variables.add(functionBody);
536
545
  }
537
546
  function PushLocal(expression) {
538
- const local = `local_${state_local_variables.size}`;
539
- state_local_variables.add(`const ${local} = ${expression}`);
547
+ const local = `local_${state.variables.size}`;
548
+ state.variables.add(`const ${local} = ${expression}`);
540
549
  return local;
541
550
  }
542
551
  function GetLocals() {
543
- return [...state_local_variables.values()];
552
+ return [...state.variables.values()];
544
553
  }
545
554
  // -------------------------------------------------------------------
546
555
  // Compile
547
556
  // -------------------------------------------------------------------
548
557
  function Build(schema, references) {
549
- ResetCompiler();
550
558
  const check = CreateFunction('check', schema, references, 'value'); // interior visit
551
559
  const locals = GetLocals();
560
+ const parameter = CreateParameter('value', 'any');
561
+ const returns = CreateReturns('boolean');
552
562
  // prettier-ignore
553
563
  return IsString(schema.$id) // ensure top level schemas with $id's are hoisted
554
- ? `${locals.join('\n')}\nreturn function check(value) {\n return ${CreateFunctionName(schema.$id)}(value)\n}`
564
+ ? `${locals.join('\n')}\nreturn function check(${parameter})${returns} {\n return ${CreateFunctionName(schema.$id)}(value)\n}`
555
565
  : `${locals.join('\n')}\nreturn ${check}`;
556
566
  }
557
567
  /** Returns the generated assertion code used to validate this type. */
558
- function Code(schema, references = []) {
568
+ function Code(schema, references = [], options = { language: 'javascript' }) {
569
+ // compiler-reset
570
+ state.language = options.language;
571
+ state.variables.clear();
572
+ state.functions.clear();
573
+ state.customs.clear();
559
574
  if (!Types.TypeGuard.TSchema(schema))
560
575
  throw new TypeCompilerTypeGuardError(schema);
561
576
  for (const schema of references)
@@ -566,13 +581,13 @@ var TypeCompiler;
566
581
  TypeCompiler.Code = Code;
567
582
  /** Compiles the given type for runtime type checking. This compiler only accepts known TypeBox types non-inclusive of unsafe types. */
568
583
  function Compile(schema, references = []) {
569
- const code = Code(schema, references);
570
- const custom_schemas = new Map(state_remote_custom_types);
584
+ const code = Code(schema, references, { language: 'javascript' });
585
+ const customs = new Map(state.customs);
571
586
  const compiledFunction = globalThis.Function('custom', 'format', 'hash', code);
572
587
  const checkFunction = compiledFunction((kind, schema_key, value) => {
573
- if (!Types.TypeRegistry.Has(kind) || !custom_schemas.has(schema_key))
588
+ if (!Types.TypeRegistry.Has(kind) || !customs.has(schema_key))
574
589
  return false;
575
- const schema = custom_schemas.get(schema_key);
590
+ const schema = customs.get(schema_key);
576
591
  const func = Types.TypeRegistry.Get(kind);
577
592
  return func(schema, value);
578
593
  }, (format, value) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sinclair/typebox",
3
- "version": "0.28.16",
3
+ "version": "0.28.18",
4
4
  "description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
5
5
  "keywords": [
6
6
  "typescript",