typebox 1.1.23 → 1.1.24

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.
@@ -1,5 +1,6 @@
1
1
  import * as Schema from '../types/index.mjs';
2
2
  export declare class Stack {
3
+ #private;
3
4
  private readonly context;
4
5
  private readonly schema;
5
6
  private readonly ids;
@@ -11,8 +12,7 @@ export declare class Stack {
11
12
  Base(): Schema.XSchemaObject;
12
13
  Push(schema: Schema.XSchema): void;
13
14
  Pop(schema: Schema.XSchema): void;
14
- private FromContext;
15
- private FromRef;
16
- Ref(ref: string): Schema.XSchema | undefined;
17
- RecursiveRef(recursiveRef: string): Schema.XSchema | undefined;
15
+ Ref(ref: Schema.XRef): Schema.XSchema | undefined;
16
+ RecursiveRef(recursiveRef: Schema.XRecursiveRef): Schema.XSchema | undefined;
17
+ DynamicRef(dynamicRef: Schema.XDynamicRef): Schema.XSchema | undefined;
18
18
  }
@@ -1,9 +1,16 @@
1
1
  // deno-fmt-ignore-file
2
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
5
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
+ };
7
+ var _Stack_instances, _Stack_PushResourceAnchors, _Stack_PopResourceAnchors, _Stack_FromContext, _Stack_FromRef;
2
8
  import * as Schema from '../types/index.mjs';
3
9
  import { Guard as G } from '../../guard/index.mjs';
4
10
  import { Resolve } from '../resolve/index.mjs';
5
11
  export class Stack {
6
12
  constructor(context, schema) {
13
+ _Stack_instances.add(this);
7
14
  this.context = context;
8
15
  this.schema = schema;
9
16
  this.ids = [];
@@ -26,8 +33,10 @@ export class Stack {
26
33
  Push(schema) {
27
34
  if (!Schema.IsSchemaObject(schema))
28
35
  return;
29
- if (Schema.IsId(schema))
36
+ if (Schema.IsId(schema)) {
30
37
  this.ids.push(schema);
38
+ __classPrivateFieldGet(this, _Stack_instances, "m", _Stack_PushResourceAnchors).call(this, schema);
39
+ }
31
40
  if (Schema.IsAnchor(schema))
32
41
  this.anchors.push(schema);
33
42
  if (Schema.IsRecursiveAnchorTrue(schema))
@@ -38,8 +47,10 @@ export class Stack {
38
47
  Pop(schema) {
39
48
  if (!Schema.IsSchemaObject(schema))
40
49
  return;
41
- if (Schema.IsId(schema))
50
+ if (Schema.IsId(schema)) {
42
51
  this.ids.pop();
52
+ __classPrivateFieldGet(this, _Stack_instances, "m", _Stack_PopResourceAnchors).call(this, schema);
53
+ }
43
54
  if (Schema.IsAnchor(schema))
44
55
  this.anchors.pop();
45
56
  if (Schema.IsRecursiveAnchorTrue(schema))
@@ -47,27 +58,50 @@ export class Stack {
47
58
  if (Schema.IsDynamicAnchor(schema))
48
59
  this.dynamicAnchors.pop();
49
60
  }
50
- // ----------------------------------------------------------------
51
- // Ref
52
- // ----------------------------------------------------------------
53
- FromContext(ref) {
54
- return G.HasPropertyKey(this.context, ref) ? this.context[ref] : undefined;
55
- }
56
- FromRef(ref) {
57
- return !ref.startsWith('#')
58
- ? Resolve.Ref(this.schema, ref)
59
- : Resolve.Ref(this.Base(), ref);
60
- }
61
61
  Ref(ref) {
62
- return this.FromContext(ref) ?? this.FromRef(ref);
62
+ return __classPrivateFieldGet(this, _Stack_instances, "m", _Stack_FromContext).call(this, ref) ?? __classPrivateFieldGet(this, _Stack_instances, "m", _Stack_FromRef).call(this, ref);
63
63
  }
64
64
  // ----------------------------------------------------------------
65
65
  // RecursiveRef
66
66
  // ----------------------------------------------------------------
67
67
  RecursiveRef(recursiveRef) {
68
- if (Schema.IsRecursiveAnchorTrue(this.Base())) {
69
- return Resolve.Ref(this.recursiveAnchors[0], recursiveRef);
70
- }
71
- return Resolve.Ref(this.Base(), recursiveRef);
68
+ return Schema.IsRecursiveAnchorTrue(this.Base())
69
+ ? Resolve.Ref(this.recursiveAnchors[0], recursiveRef.$recursiveRef)
70
+ : Resolve.Ref(this.Base(), recursiveRef.$recursiveRef);
71
+ }
72
+ // ----------------------------------------------------------------
73
+ // DynamicRef
74
+ // ----------------------------------------------------------------
75
+ DynamicRef(dynamicRef) {
76
+ const root = this.schema;
77
+ return Resolve.DynamicRef(root, this.Base(), dynamicRef, this.dynamicAnchors);
72
78
  }
73
79
  }
80
+ _Stack_instances = new WeakSet(), _Stack_PushResourceAnchors = function _Stack_PushResourceAnchors(schema, isRoot = true) {
81
+ if (!Schema.IsSchemaObject(schema))
82
+ return;
83
+ const current = schema;
84
+ if (!isRoot && Schema.IsId(current))
85
+ return;
86
+ if (!isRoot && Schema.IsDynamicAnchor(current))
87
+ this.dynamicAnchors.push(current);
88
+ for (const key of G.Keys(current))
89
+ __classPrivateFieldGet(this, _Stack_instances, "m", _Stack_PushResourceAnchors).call(this, current[key], false);
90
+ }, _Stack_PopResourceAnchors = function _Stack_PopResourceAnchors(schema, isRoot = true) {
91
+ if (!Schema.IsSchemaObject(schema))
92
+ return;
93
+ const current = schema;
94
+ if (!isRoot && Schema.IsId(current))
95
+ return;
96
+ if (!isRoot && Schema.IsDynamicAnchor(current))
97
+ this.dynamicAnchors.pop();
98
+ for (const key of G.Keys(current))
99
+ __classPrivateFieldGet(this, _Stack_instances, "m", _Stack_PopResourceAnchors).call(this, current[key], false);
100
+ }, _Stack_FromContext = function _Stack_FromContext(ref) {
101
+ return G.HasPropertyKey(this.context, ref.$ref) ? this.context[ref.$ref] : undefined;
102
+ }, _Stack_FromRef = function _Stack_FromRef(ref) {
103
+ const root = this.schema;
104
+ return !ref.$ref.startsWith('#')
105
+ ? Resolve.Ref(root, ref.$ref)
106
+ : Resolve.Ref(this.Base(), ref.$ref);
107
+ };
@@ -0,0 +1,6 @@
1
+ import * as Schema from '../types/index.mjs';
2
+ import { Stack } from './_stack.mjs';
3
+ import { BuildContext, CheckContext, ErrorContext } from './_context.mjs';
4
+ export declare function BuildDynamicRef(stack: Stack, context: BuildContext, schema: Schema.XDynamicRef, value: string): string;
5
+ export declare function CheckDynamicRef(stack: Stack, context: CheckContext, schema: Schema.XDynamicRef, value: unknown): boolean;
6
+ export declare function ErrorDynamicRef(stack: Stack, context: ErrorContext, _schemaPath: string, instancePath: string, schema: Schema.XDynamicRef, value: unknown): boolean;
@@ -0,0 +1,25 @@
1
+ // deno-fmt-ignore-file
2
+ import * as Functions from './_functions.mjs';
3
+ import * as Schema from '../types/index.mjs';
4
+ import { CheckSchema, ErrorSchema } from './schema.mjs';
5
+ // ------------------------------------------------------------------
6
+ // Build
7
+ // ------------------------------------------------------------------
8
+ export function BuildDynamicRef(stack, context, schema, value) {
9
+ const target = stack.DynamicRef(schema) ?? false;
10
+ return Functions.CreateFunction(stack, context, target, value);
11
+ }
12
+ // ------------------------------------------------------------------
13
+ // Check
14
+ // ------------------------------------------------------------------
15
+ export function CheckDynamicRef(stack, context, schema, value) {
16
+ const target = stack.DynamicRef(schema) ?? false;
17
+ return (Schema.IsSchema(target) && CheckSchema(stack, context, target, value));
18
+ }
19
+ // ------------------------------------------------------------------
20
+ // Error
21
+ // ------------------------------------------------------------------
22
+ export function ErrorDynamicRef(stack, context, _schemaPath, instancePath, schema, value) {
23
+ const target = stack.DynamicRef(schema) ?? false;
24
+ return (Schema.IsSchema(target) && ErrorSchema(stack, context, '#', instancePath, target, value));
25
+ }
@@ -6,20 +6,20 @@ import { CheckSchema, ErrorSchema } from './schema.mjs';
6
6
  // Build
7
7
  // ------------------------------------------------------------------
8
8
  export function BuildRecursiveRef(stack, context, schema, value) {
9
- const target = stack.RecursiveRef(schema.$recursiveRef) ?? false;
9
+ const target = stack.RecursiveRef(schema) ?? false;
10
10
  return Functions.CreateFunction(stack, context, target, value);
11
11
  }
12
12
  // ------------------------------------------------------------------
13
13
  // Check
14
14
  // ------------------------------------------------------------------
15
15
  export function CheckRecursiveRef(stack, context, schema, value) {
16
- const target = stack.RecursiveRef(schema.$recursiveRef) ?? false;
16
+ const target = stack.RecursiveRef(schema) ?? false;
17
17
  return (Schema.IsSchema(target) && CheckSchema(stack, context, target, value));
18
18
  }
19
19
  // ------------------------------------------------------------------
20
20
  // Error
21
21
  // ------------------------------------------------------------------
22
22
  export function ErrorRecursiveRef(stack, context, _schemaPath, instancePath, schema, value) {
23
- const target = stack.RecursiveRef(schema.$recursiveRef) ?? false;
23
+ const target = stack.RecursiveRef(schema) ?? false;
24
24
  return (Schema.IsSchema(target) && ErrorSchema(stack, context, '#', instancePath, target, value));
25
25
  }
@@ -27,7 +27,7 @@ function BuildRefFast(stack, context, target, value) {
27
27
  // BuildRef
28
28
  // ------------------------------------------------------------------
29
29
  export function BuildRef(stack, context, schema, value) {
30
- const target = stack.Ref(schema.$ref) ?? false;
30
+ const target = stack.Ref(schema) ?? false;
31
31
  return context.UseUnevaluated()
32
32
  ? BuildRefStandard(stack, context, target, value)
33
33
  : BuildRefFast(stack, context, target, value);
@@ -36,7 +36,7 @@ export function BuildRef(stack, context, schema, value) {
36
36
  // Check
37
37
  // ------------------------------------------------------------------
38
38
  export function CheckRef(stack, context, schema, value) {
39
- const target = stack.Ref(schema.$ref) ?? false;
39
+ const target = stack.Ref(schema) ?? false;
40
40
  const nextContext = new CheckContext();
41
41
  const result = (Schema.IsSchema(target) && CheckSchema(stack, nextContext, target, value));
42
42
  if (result)
@@ -47,7 +47,7 @@ export function CheckRef(stack, context, schema, value) {
47
47
  // Error
48
48
  // ------------------------------------------------------------------
49
49
  export function ErrorRef(stack, context, _schemaPath, instancePath, schema, value) {
50
- const target = stack.Ref(schema.$ref) ?? false;
50
+ const target = stack.Ref(schema) ?? false;
51
51
  const nextContext = new AccumulatedErrorContext();
52
52
  const result = (Schema.IsSchema(target) && ErrorSchema(stack, nextContext, '#', instancePath, target, value));
53
53
  if (result)
@@ -13,6 +13,7 @@ import { BuildContains, CheckContains, ErrorContains } from './contains.mjs';
13
13
  import { BuildDependencies, CheckDependencies, ErrorDependencies } from './dependencies.mjs';
14
14
  import { BuildDependentRequired, CheckDependentRequired, ErrorDependentRequired } from './dependentRequired.mjs';
15
15
  import { BuildDependentSchemas, CheckDependentSchemas, ErrorDependentSchemas } from './dependentSchemas.mjs';
16
+ import { BuildDynamicRef, CheckDynamicRef, ErrorDynamicRef } from './dynamicRef.mjs';
16
17
  import { BuildEnum, CheckEnum, ErrorEnum } from './enum.mjs';
17
18
  import { BuildExclusiveMaximum, CheckExclusiveMaximum, ErrorExclusiveMaximum } from './exclusiveMaximum.mjs';
18
19
  import { BuildExclusiveMinimum, CheckExclusiveMinimum, ErrorExclusiveMinimum } from './exclusiveMinimum.mjs';
@@ -209,10 +210,12 @@ export function BuildSchema(stack, context, schema, value) {
209
210
  const guarded = E.Or(E.Not(E.Or(E.IsNumber(value), E.IsBigInt(value))), reduced);
210
211
  conditions.push(HasNumberType(schema) ? reduced : guarded);
211
212
  }
212
- if (Schema.IsRecursiveRef(schema))
213
- conditions.push(BuildRecursiveRef(stack, context, schema, value));
214
213
  if (Schema.IsRef(schema))
215
214
  conditions.push(BuildRef(stack, context, schema, value));
215
+ if (Schema.IsRecursiveRef(schema))
216
+ conditions.push(BuildRecursiveRef(stack, context, schema, value));
217
+ if (Schema.IsDynamicRef(schema))
218
+ conditions.push(BuildDynamicRef(stack, context, schema, value));
216
219
  if (Schema.IsGuard(schema))
217
220
  conditions.push(BuildGuard(stack, context, schema, value));
218
221
  if (Schema.IsConst(schema))
@@ -276,8 +279,9 @@ export function CheckSchema(stack, context, schema, value) {
276
279
  (!Schema.IsMaximum(schema) || CheckMaximum(stack, context, schema, value)) &&
277
280
  (!Schema.IsMinimum(schema) || CheckMinimum(stack, context, schema, value)) &&
278
281
  (!Schema.IsMultipleOf(schema) || CheckMultipleOf(stack, context, schema, value)))) &&
279
- (!Schema.IsRecursiveRef(schema) || CheckRecursiveRef(stack, context, schema, value)) &&
280
282
  (!Schema.IsRef(schema) || CheckRef(stack, context, schema, value)) &&
283
+ (!Schema.IsRecursiveRef(schema) || CheckRecursiveRef(stack, context, schema, value)) &&
284
+ (!Schema.IsDynamicRef(schema) || CheckDynamicRef(stack, context, schema, value)) &&
281
285
  (!Schema.IsGuard(schema) || CheckGuard(stack, context, schema, value)) &&
282
286
  (!Schema.IsConst(schema) || CheckConst(stack, context, schema, value)) &&
283
287
  (!Schema.IsEnum(schema) || CheckEnum(stack, context, schema, value)) &&
@@ -329,8 +333,9 @@ export function ErrorSchema(stack, context, schemaPath, instancePath, schema, va
329
333
  +(!Schema.IsMaximum(schema) || ErrorMaximum(stack, context, schemaPath, instancePath, schema, value)) &
330
334
  +(!Schema.IsMinimum(schema) || ErrorMinimum(stack, context, schemaPath, instancePath, schema, value)) &
331
335
  +(!Schema.IsMultipleOf(schema) || ErrorMultipleOf(stack, context, schemaPath, instancePath, schema, value)))) &
332
- +(!Schema.IsRecursiveRef(schema) || ErrorRecursiveRef(stack, context, schemaPath, instancePath, schema, value)) &
333
336
  +(!Schema.IsRef(schema) || ErrorRef(stack, context, schemaPath, instancePath, schema, value)) &
337
+ +(!Schema.IsRecursiveRef(schema) || ErrorRecursiveRef(stack, context, schemaPath, instancePath, schema, value)) &
338
+ +(!Schema.IsDynamicRef(schema) || ErrorDynamicRef(stack, context, schemaPath, instancePath, schema, value)) &
334
339
  +(!Schema.IsGuard(schema) || ErrorGuard(stack, context, schemaPath, instancePath, schema, value)) &
335
340
  +(!Schema.IsConst(schema) || ErrorConst(stack, context, schemaPath, instancePath, schema, value)) &
336
341
  +(!Schema.IsEnum(schema) || ErrorEnum(stack, context, schemaPath, instancePath, schema, value)) &
@@ -1,2 +1,3 @@
1
1
  import * as Schema from '../types/index.mjs';
2
2
  export declare function Ref(schema: Schema.XSchemaObject, ref: string): Schema.XSchema | undefined;
3
+ export declare function DynamicRef(root: Schema.XSchemaObject, base: Schema.XSchemaObject, dynamicRef: Schema.XDynamicRef, dynamicAnchors: Schema.XDynamicAnchor[]): Schema.XSchema | undefined;
@@ -21,19 +21,34 @@ function MatchId(schema, base, ref) {
21
21
  function MatchAnchor(schema, base, ref) {
22
22
  const absoluteAnchor = new URL(`#${schema.$anchor}`, base.href);
23
23
  const absoluteRef = new URL(ref.href, base.href);
24
- if (Guard.IsEqual(absoluteAnchor.href, absoluteRef.href))
25
- return schema;
26
- return undefined;
24
+ return Guard.IsEqual(absoluteAnchor.href, absoluteRef.href) ? schema : undefined;
25
+ }
26
+ // ------------------------------------------------------------------
27
+ // Match: DynamicAnchor
28
+ // ------------------------------------------------------------------
29
+ function MatchDynamicAnchor(schema, base, ref) {
30
+ const absoluteAnchor = new URL(`#${schema.$dynamicAnchor}`, base.href);
31
+ const absoluteRef = new URL(ref.href, base.href);
32
+ return Guard.IsEqual(absoluteAnchor.href, absoluteRef.href) ? schema : undefined;
27
33
  }
28
34
  // ------------------------------------------------------------------
29
35
  // Match: Hash
36
+ //
37
+ // Resolves JSON Pointer fragments only. Plain anchor-style fragments
38
+ // (no leading '/') are handled exclusively by MatchAnchor and
39
+ // MatchDynamicAnchor to prevent accidentally resolving an anchor name
40
+ // as a pointer into the schema tree.
41
+ //
30
42
  // ------------------------------------------------------------------
31
43
  function MatchHash(schema, _base, ref) {
32
44
  if (ref.href.endsWith('#'))
33
45
  return schema;
34
- return ref.hash.startsWith('#')
35
- ? Pointer.Get(schema, decodeURIComponent(ref.hash.slice(1)))
36
- : undefined;
46
+ if (!ref.hash.startsWith('#'))
47
+ return undefined;
48
+ const fragment = decodeURIComponent(ref.hash.slice(1));
49
+ if (!fragment.startsWith('/'))
50
+ return undefined;
51
+ return Pointer.Get(schema, fragment);
37
52
  }
38
53
  // ------------------------------------------------------------------
39
54
  // Match
@@ -49,6 +64,11 @@ function Match(schema, base, ref) {
49
64
  if (!Guard.IsUndefined(result))
50
65
  return result;
51
66
  }
67
+ if (Schema.IsDynamicAnchor(schema)) {
68
+ const result = MatchDynamicAnchor(schema, base, ref);
69
+ if (!Guard.IsUndefined(result))
70
+ return result;
71
+ }
52
72
  return MatchHash(schema, base, ref);
53
73
  }
54
74
  // ------------------------------------------------------------------
@@ -73,24 +93,54 @@ function FromObject(schema, base, ref) {
73
93
  // FromValue
74
94
  // ------------------------------------------------------------------
75
95
  function FromValue(schema, base, ref) {
76
- base = Schema.IsSchemaObject(schema) && Schema.IsId(schema) ? new URL(schema.$id, base.href) : base;
96
+ const nextBase = Schema.IsSchemaObject(schema) && Schema.IsId(schema)
97
+ ? new URL(schema.$id, base.href)
98
+ : base;
77
99
  if (Schema.IsSchemaObject(schema)) {
78
- const result = Match(schema, base, ref);
100
+ const result = Match(schema, nextBase, ref);
79
101
  if (!Guard.IsUndefined(result))
80
102
  return result;
81
103
  }
82
104
  if (Guard.IsArray(schema))
83
- return FromArray(schema, base, ref);
105
+ return FromArray(schema, nextBase, ref);
84
106
  if (Guard.IsObject(schema))
85
- return FromObject(schema, base, ref);
107
+ return FromObject(schema, nextBase, ref);
86
108
  return undefined;
87
109
  }
88
110
  // ------------------------------------------------------------------
89
111
  // Ref
90
112
  // ------------------------------------------------------------------
91
113
  export function Ref(schema, ref) {
92
- const defaultBase = new URL('http://unknown');
114
+ const defaultBase = new URL('http://unknown/');
93
115
  const initialBase = Schema.IsId(schema) ? new URL(schema.$id, defaultBase.href) : defaultBase;
94
116
  const initialRef = new URL(ref, initialBase.href);
95
117
  return FromValue(schema, initialBase, initialRef);
96
118
  }
119
+ // ------------------------------------------------------------------
120
+ // DynamicRef
121
+ // ------------------------------------------------------------------
122
+ export function DynamicRef(root, base, dynamicRef, dynamicAnchors) {
123
+ // Resolve the static target using either the local base (for fragment‑only references)
124
+ // or the document root (for absolute URI references).
125
+ const fragmentTarget = dynamicRef.$dynamicRef.startsWith('#')
126
+ ? Ref(base, dynamicRef.$dynamicRef)
127
+ : Ref(root, dynamicRef.$dynamicRef);
128
+ if (Guard.IsUndefined(fragmentTarget))
129
+ return undefined;
130
+ // Dynamic override only applies if the resolved target itself declares a $dynamicAnchor.
131
+ // If it does not, return the static target unchanged.
132
+ if (!Schema.IsSchemaObject(fragmentTarget) || !Schema.IsDynamicAnchor(fragmentTarget))
133
+ return fragmentTarget;
134
+ // Extract the fragment portion of the reference. According to the test suite,
135
+ // only plain fragment names (e.g., "#foo") trigger the dynamic scope; JSON
136
+ // Pointer fragments (e.g., "#/definitions/foo") bypass dynamic resolution.
137
+ const fragment = new URL(dynamicRef.$dynamicRef, 'http://unknown/').hash;
138
+ if (fragment.startsWith('#/'))
139
+ return fragmentTarget;
140
+ // Search the live dynamic anchor stack for a schema whose $dynamicAnchor matches the
141
+ // target's $dynamicAnchor. The stack reflects the current evaluation path, and
142
+ // find() returns the outermost (first encountered) match, which is the correct
143
+ // lexical scope per the specification.
144
+ const anchorTarget = dynamicAnchors.find(anchor => anchor.$dynamicAnchor === fragmentTarget.$dynamicAnchor);
145
+ return anchorTarget ?? fragmentTarget;
146
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "typebox",
3
3
  "description": "Json Schema Type Builder with Static Type Resolution for TypeScript",
4
- "version": "1.1.23",
4
+ "version": "1.1.24",
5
5
  "keywords": [
6
6
  "typescript",
7
7
  "jsonschema"
@@ -16,29 +16,21 @@
16
16
  "types": "./build/index.d.mts",
17
17
  "module": "./build/index.mjs",
18
18
  "exports": {
19
- "./system": {
20
- "import": "./build/system/index.mjs",
21
- "default": "./build/system/index.mjs"
22
- },
23
- "./compile": {
24
- "import": "./build/compile/index.mjs",
25
- "default": "./build/compile/index.mjs"
26
- },
27
- "./value": {
28
- "import": "./build/value/index.mjs",
29
- "default": "./build/value/index.mjs"
19
+ "./guard": {
20
+ "import": "./build/guard/index.mjs",
21
+ "default": "./build/guard/index.mjs"
30
22
  },
31
23
  "./error": {
32
24
  "import": "./build/error/index.mjs",
33
25
  "default": "./build/error/index.mjs"
34
26
  },
35
- "./guard": {
36
- "import": "./build/guard/index.mjs",
37
- "default": "./build/guard/index.mjs"
27
+ "./compile": {
28
+ "import": "./build/compile/index.mjs",
29
+ "default": "./build/compile/index.mjs"
38
30
  },
39
- "./schema": {
40
- "import": "./build/schema/index.mjs",
41
- "default": "./build/schema/index.mjs"
31
+ "./system": {
32
+ "import": "./build/system/index.mjs",
33
+ "default": "./build/system/index.mjs"
42
34
  },
43
35
  "./format": {
44
36
  "import": "./build/format/index.mjs",
@@ -48,6 +40,14 @@
48
40
  "import": "./build/type/index.mjs",
49
41
  "default": "./build/type/index.mjs"
50
42
  },
43
+ "./schema": {
44
+ "import": "./build/schema/index.mjs",
45
+ "default": "./build/schema/index.mjs"
46
+ },
47
+ "./value": {
48
+ "import": "./build/value/index.mjs",
49
+ "default": "./build/value/index.mjs"
50
+ },
51
51
  ".": {
52
52
  "import": "./build/index.mjs",
53
53
  "default": "./build/index.mjs"
@@ -55,23 +55,17 @@
55
55
  },
56
56
  "typesVersions": {
57
57
  "*": {
58
- "system": [
59
- "./build/system/index.d.mts"
60
- ],
61
- "compile": [
62
- "./build/compile/index.d.mts"
63
- ],
64
- "value": [
65
- "./build/value/index.d.mts"
58
+ "guard": [
59
+ "./build/guard/index.d.mts"
66
60
  ],
67
61
  "error": [
68
62
  "./build/error/index.d.mts"
69
63
  ],
70
- "guard": [
71
- "./build/guard/index.d.mts"
64
+ "compile": [
65
+ "./build/compile/index.d.mts"
72
66
  ],
73
- "schema": [
74
- "./build/schema/index.d.mts"
67
+ "system": [
68
+ "./build/system/index.d.mts"
75
69
  ],
76
70
  "format": [
77
71
  "./build/format/index.d.mts"
@@ -79,6 +73,12 @@
79
73
  "type": [
80
74
  "./build/type/index.d.mts"
81
75
  ],
76
+ "schema": [
77
+ "./build/schema/index.d.mts"
78
+ ],
79
+ "value": [
80
+ "./build/value/index.d.mts"
81
+ ],
82
82
  ".": [
83
83
  "./build/index.d.mts"
84
84
  ]
package/readme.md CHANGED
@@ -43,6 +43,7 @@ type T = Type.Static<typeof T> // type T = {
43
43
  // y: number,
44
44
  // z: number
45
45
  // }
46
+
46
47
  ```
47
48
 
48
49
  ## Overview
@@ -51,7 +52,7 @@ type T = Type.Static<typeof T> // type T = {
51
52
 
52
53
  TypeBox is a runtime type system that creates in-memory JSON Schema objects that infer as TypeScript types. The schematics produced by this library are designed to match the static type checking rules of the TypeScript compiler. TypeBox offers a unified type system that can be statically checked by TypeScript and validated at runtime using standard JSON Schema.
53
54
 
54
- This library is designed to allow JSON Schema to compose similar to how types compose within TypeScript's type system. It can be used as a simple tool to build up complex schematics or integrated into REST and RPC services to help validate data received over the wire.
55
+ This library is designed to allow JSON Schema to compose similar to how types compose within TypeScript's type system. It can be used as a simple tool to build up complex schematics or integrated into REST, RPC and MCP services to help validate data received over the wire.
55
56
 
56
57
  License: MIT
57
58
 
@@ -79,9 +80,8 @@ The following creates a User type and infers with Static.
79
80
  ```typescript
80
81
  import Type from 'typebox'
81
82
 
82
- // -------------------------------------------------------------------------------
83
+
83
84
  // Type
84
- // -------------------------------------------------------------------------------
85
85
 
86
86
  const User = Type.Object({ // const User = {
87
87
  id: Type.String(), // type: 'object',
@@ -100,22 +100,22 @@ const User = Type.Object({ // const User = {
100
100
  // ]
101
101
  // }
102
102
 
103
- // -------------------------------------------------------------------------------
103
+
104
104
  // Static
105
- // -------------------------------------------------------------------------------
106
105
 
107
106
  type User = Type.Static<typeof User> // type User = {
108
107
  // id: string,
109
108
  // name: string,
110
109
  // email: string
111
110
  // }
111
+
112
112
  ```
113
113
 
114
114
  ## Script
115
115
 
116
116
  [Documentation](https://sinclairzx81.github.io/typebox/#/docs/script/overview) | [Example 1](https://www.typescriptlang.org/play/#code/JYWwDg9gTgLgBAFQJ5gKZwGZQiOByGFVAIwgA88AoSgehrgFonmXW32POvueHb6AygGMowMDH6Ne0mbLnNqQiADsAzvADecAKqrUUADQ69UbWAAmAQxjoAvnAC8iIgDpho8QAoABtThxgZRsoDEshdABRIOBCOA1Kf39gcwAuOHVRZQBzBLhbPwCg-VDw4304VDIbZXNVOCiYGKQ4uFz-ZUsQVDSMwKyjNoqQS2AAGx6YTKzW-3zcwjQy0wtrdCcIgDdLUYBXVYAeQYAFYCEAa33dfSMz1CQIDHrowgA+OAAyGcSjy1hgbf2AHkQDFLiYbncHk9Gq8Xrk4ZRvABKah0KTyDGYzGSABKqAwo1QQgkaKxZPJvEUKlUEEJLlGECyniuUCRiXZHM5XK5aPi3P5AsFgrR-gW3XwEGIACsiTA8AZBkKlcrOSK4GBsGg-qhVGk+SqDYa1UlUi0xWk8L1sng8grDfblca4B0unq4Ob8FasjbbHaHf7+U7UMMxm6PZbJn0fYqA7G4GrfTG4-61VBUABHHbANOmgDaSeT9qdeGS8q+hdjxZdqDLBYrKuLwZGoyo9cr9H8AF0622hWi5ko1LTUPTGcyTGYrDY2YXeT3ewK1eHJTLifL5wvuWqNRAtY0dXqN5vVR3Eskw0QLV6fX7jw3T+1OuKtOHr7aj3fEkGQ+MzZfPZG1p5B+n7xqeiagY6p5ppm2aoHmJbmHg3aQUq-aovQFJYdhLCSAIMDWKckg4SRFLUGKSyOM4aBuARjRCPsYpQiybxofQFEslR+qocKp7nukgH9CBoFqtWExTLePGBqeTahgJUzCZ+6GUBxE4rDYVHIDR+GEQxTGPCyk6rKxaKqfoRkaU43FSVufGml6kk2SeiTVgA-OJfSOU57JqrJozufJfSKXe6FAA) | [Example 2](https://www.typescriptlang.org/play/#code/JYWwDg9gTgLgBAFQJ5gKZwGZQiOByGFVAIwgA88AoSgehrgFonmXW32POvnb7k1ejbsJGj21AMYQAdgGd4AUWkxghOAF5ERAHQBJZaigYAhhNQAKANoBdADRwA3pThxgAEwBcWtNoDKMKGBpAHNzAEpKAF8Iyik5eABVWUMNb1Q9AyNTC0slFUI7R2c4aWMQVC9+dP9AkPDbYtQQY2AAG0qdGqDQiOjJGXk4JMMEsDdjGHRNKu0FADdjVoBXCYsZ-UmoZIkYK2KZgAVgCQBrc2GoexmAaVQkAHkMczzVJDCwhpdD41hgRfMZvcQKpzslLmltLcHk8XoR3hFrO9qHQhGI0eiMdxBAAlVAYVqoHaCTEk0mY-pyCAE7StCChC5hFxM5ks1lslkopzs7k83m8lEuQhoLx4CDEABWhJgeE+fLl8u5ArgYGwaF+qFkXi5Cp1uqVLncWrgQoq+HktWCeDgkVlurtfP1JTKpocxqIIvN3StNuK9r97MdTRa7UcbuFZoCXutvv9saZSp9caTLiVUFQAEclsA0544JYY8m-Y68O4ZXAC4W7cXSuUyxXKzri0G2lQG-6ldZ6225SjIhTZFT0rT6WDRuNJozk5yu93+fRBe78GLJTsZTPZ4r58rVYYVBqteuN2zHYbQyaPZGQt7bUee1uXDWXWHTXhPVfrTfb3OWc2Q67zxGFreoeX7xluiagQ6W5ppm2aoLmlglm4eCdpBUHRsSZJYdhnCCP4EzHJhOHEcR1AmkMYKpDM+EqBIAA8JoQBgFGGAAfPKKLkRcqTamhPJKqeb7BJ+fGskqj5eEJImicySq-pJl7BCBaG9mRRAsVAY6rFRnQwAR9GMcxFxaZM7FwJx6nGWM2maLxMliVugmKdJ9nmVuj4APwKRaLn2XJzRtF5cBCcpkG9kAA)
117
117
 
118
- TypeBox can transform TypeScript definitions into JSON Schema. The Script function provides an optional programmatic syntax to rapidly convert type definitions into JSON Schema, or serve more generally as an alternative to Type.* builders. The Script function is designed to handle a wide array of complex TypeScript type-level expressions.
118
+ The TypeBox Script function is a micro DSL for constructing JSON Schema from TypeScript syntax. It offers a full syntactic frontend to Type.* with broad support for type-level expressions including Conditional, Mapped, Infer, Generic, Distributive types and more. This feature is implemented symmetrically at both runtime and in the type system.
119
119
 
120
120
  ### Example
121
121
 
@@ -124,9 +124,8 @@ The following uses the Script function to parse TypeScript interfaces into JSON
124
124
  ```typescript
125
125
  import Type from 'typebox'
126
126
 
127
- // -------------------------------------------------------------------------------
127
+
128
128
  // Script
129
- // -------------------------------------------------------------------------------
130
129
 
131
130
  const { User, UserUpdate } = Type.Script(`
132
131
 
@@ -146,9 +145,8 @@ const { User, UserUpdate } = Type.Script(`
146
145
 
147
146
  `)
148
147
 
149
- // -------------------------------------------------------------------------------
148
+
150
149
  // Reflect
151
- // -------------------------------------------------------------------------------
152
150
 
153
151
  console.log(User) // {
154
152
  // type: 'object',
@@ -174,9 +172,8 @@ console.log(UserUpdate) // {
174
172
  // required: ['id']
175
173
  // }
176
174
 
177
- // -------------------------------------------------------------------------------
175
+
178
176
  // Static
179
- // -------------------------------------------------------------------------------
180
177
 
181
178
  type User = Type.Static<typeof User> // type User = {
182
179
  // id: string,
@@ -190,15 +187,16 @@ type UserUpdate = Type.Static<typeof UserUpdate> // type UserUpdate = {
190
187
  // email?: string
191
188
  // }
192
189
 
190
+
193
191
  ```
194
192
 
195
193
  <a name="Schema"></a>
196
194
 
197
195
  ## Schema
198
196
 
199
- [Documentation](https://sinclairzx81.github.io/typebox/#/docs/schema/overview) | [Example 1](https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAZQMYAsCmICGcBmUIhwDkMAnmGgEYQAeA9AM6oaZEBQokscAKuWrnyES-ajXZs6dOAFo58hYqXKVqteo0zJ0gMIEwwADZptszeYuWr8tmyQQAdg3gBVBmihwAvImZYAdHrgRmgAFHwU-gDylABWaEgwoQDebHBwwAAmAFy8-P4IMFDADgDmoQCUADRpcA6YIGi5EWgFRSXl1bUsRs35hcVlKbjQWDC5RD2GRHAAvhVs8wum1qtr61pScAAKmFDuKxtHx6q29k7wAK7unj5uHv67+2HJ6W-vH5-vW+fOcNceXKpdJZCYANgArDgAIyYABMlAAzEgACyZCFoME4ADsmAAHJQAJxIAAMmWhRCqX2pcC2IJycGcg1KNXS9UaEwBUEpNN5fO+0jZDSajPaZVZcCmnJuAAFMgRMCV-PYQDN+by6ZKsL1RczFhV1YajR8trNvHB-JagA) | [Example 2](https://www.typescriptlang.org/play/#code/JYWwDg9gTgLgBAZQMYAsCmICGcBmUIhwDkMAnmGgEYQAeA9AM6oaZEBQbddcAtH-wMFDhI0WPESenbgGECYYABs003pPUbNW-hyQQAdg3gBVBmihwAvImZYAdHPBK0ACgDebOHDIUAXMQhKACs0JBgiABpPODB8ClhgNAZ-Dy8vYAATFO9yNH8iIyhgfQBzIjgAXyi0uH1MEDy4Nxy-YkLissrqtJYlbJ9Ggpgi0sjcaCwYfN7FcoroquioNABHAFdgZay4AG1oryJMsf3iOobjmqIZ9i8AXTYKgEoOLjVtd4+P1QAFTCgzVSfIHAyS6AxGOBrMwWaymcx2X7-VzNGqotHouCvPSGeBQ8wpaKZfIANgArDgAIyYABMlAAzEgACwZUloYk4ADsmAAHJQAJxIAAMGQpYwx6Ne6W27VK3TOgzxUDF4pVqq8ktq9UaMpK3Rm+UVAAEMgRMMU7HoQOU1SqNfq4DqHo8bS7XajXhUrHA7D6gA) | [Specification](https://sinclairzx81.github.io/typebox/#/docs/schema/6_specification)
197
+ [Documentation](https://sinclairzx81.github.io/typebox/#/docs/schema/overview) | [Example 1](https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAZQMYAsCmICGcBmUIhwDkMAnmGgEYQAeA9AM6oaZEBQokscAKuWrnyES-ajXZs6dOAFo58hYqXKVqteo0zJ0gMIEwwADZptszeYuWr8tmyQQAdg3gBVBmihwAvImZYAdHrgRmgAFHwU-gDylABWaEgwoQDebHBwwAAmAFy8-P4IMFDADgDmoQCUADRpcA6YIGi5EWgFRSXl1bUsRs35hcVlKbjQWDC5RD2GRHAAvhVs8wum1qtr61pScAAKmFDuKxtHx6q29k7wAK7unj5uHv67+2HJ6W-vH5-vW+fOcNceXKpdJZCYANgArDgAIyYABMlAAzEgACyZCFoME4ADsmAAHJQAJxIAAMmWhRCqX2pcC2IJycGcg1KNXS9UaEwBUEpNN5fO+0jZDSajPaZVZcCmnJuAAFMgRMCV-PYQDN+by6ZKsL1RczFhV1YajR8trNvHB-JagA) | [Example 2](https://www.typescriptlang.org/play/#code/JYWwDg9gTgLgBAZQMYAsCmICGcBmUIhwDkMAnmGgEYQAeA9AM6oaZEBQbddcAtH-wMFDhI0WPESenbgGECYYABs003pPUbNW-hyQQAdg3gBVBmihwAvImZYAdHPBK0ACgDebOHDIUAXMQhKACs0JBgiABpPODB8ClhgNAZ-Dy8vYAATFO9yNH8iIyhgfQBzIjgAXyi0uH1MEDy4Nxy-YkLissrqtJYlbJ9Ggpgi0sjcaCwYfN7FcoroquioNABHAFdgZay4AG1oryJMsf3iOobjmqIZ9i8AXTYKgEoOLjVtd4+P1QAFTCgzVSfIHAyS6AxGOBrMwWaymcx2X7-VzNGqotHouCvPSGeBQ8wpaKZfIANgArDgAIyYABMlAAzEgACwZUloYk4ADsmAAHJQAJxIAAMGQpYwx6Ne6W27VK3TOgzxUDF4pVqq8ktq9UaMpK3Rm+UVAAEMgRMMU7HoQOU1SqNfq4DqHo8bS7XajXhUrHA7D6gA) | [Specification](https://sinclairzx81.github.io/typebox/#/docs/schema/1_spec)
200
198
 
201
- TypeBox includes a JSON Schema compiler designed for high-performance JIT validation. It also provides automatic fallback to dynamic interpreted checking for JIT restrictive environments such as Cloudflare Workers. The compiler is designed to be a lightweight, spec compliant alternative to Ajv for high-throughput applications based on the JSON Schema standard.
199
+ TypeBox has a high-performance JSON Schema compiler that supports drafts 3 to 2020-12. The compiler is designed to be an industry-grade alternative to Ajv and offers improved compilation and validation performance. It also offers automatic fallback to dynamic checking in JIT-restricted environments such as Cloudflare Workers.
202
200
 
203
201
  ### Example
204
202
 
@@ -207,32 +205,151 @@ The following uses the Schema submodule to compile a TypeBox type.
207
205
  ```typescript
208
206
  import Schema from 'typebox/schema'
209
207
 
210
- // -------------------------------------------------------------------------------
208
+
211
209
  // Compile
212
- // -------------------------------------------------------------------------------
213
210
 
214
- const User = Schema.Compile(Type.Object({
215
- id: Type.String(),
216
- name: Type.String(),
217
- email: Type.String({ format: 'email' })
218
- }))
211
+ const User = Schema.Compile(Type.Object({ // const User = Validator<Type.TObject<{
212
+ id: Type.String(), // id: Type.TString;
213
+ name: Type.String(), // name: Type.TString;
214
+ email: Type.String({ format: 'email' }) // email: Type.TString;
215
+ })) // }>, { ... }>
216
+
219
217
 
220
- // -------------------------------------------------------------------------------
221
218
  // Parse
222
- // -------------------------------------------------------------------------------
223
219
 
224
220
  const user = User.Parse({ // const user: {
225
221
  id: '65f1a2b3c4d5e6f7a8b9c0d1', // id: string,
226
222
  name: 'user', // name: string,
227
223
  email: 'user@domain.com' // email: string
228
224
  }) // } = ...
225
+
226
+ ```
227
+
228
+ ### Specification
229
+
230
+ TypeBox tests against the official JSON Schema [test suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite). The following table shows specification coverage across drafts 3 to the v1 candidate.
231
+
232
+ | Spec | 3 | 4 | 6 | 7 | 2019-09 | 2020-12 | v1 |
233
+ |:-----|:--|:--|:--|:--|:--|:--|:--|
234
+ | additionalItems | ✅ | ✅ | ✅ | ✅ | ✅ | - | - |
235
+ | additionalProperties | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
236
+ | allOf | - | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
237
+ | anchor | - | - | - | - | ✅ | ✅ | ✅ |
238
+ | anyOf | - | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
239
+ | boolean_schema | - | - | ✅ | ✅ | ✅ | ✅ | ✅ |
240
+ | const | - | - | ✅ | ✅ | ✅ | ✅ | ✅ |
241
+ | contains | - | - | ✅ | ✅ | ✅ | ✅ | ✅ |
242
+ | content | - | - | - | - | ✅ | ✅ | ✅ |
243
+ | default | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
244
+ | dependencies | 17/18 | ✅ | ✅ | ✅ | - | - | - |
245
+ | dependentRequired | - | - | - | - | ✅ | ✅ | ✅ |
246
+ | dependentSchemas | - | - | - | - | ✅ | ✅ | ✅ |
247
+ | dynamicRef | - | - | - | - | - | 38/44 | 19/27 |
248
+ | enum | 14/16 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
249
+ | exclusiveMaximum | - | - | ✅ | ✅ | ✅ | ✅ | ✅ |
250
+ | exclusiveMinimum | - | - | ✅ | ✅ | ✅ | ✅ | ✅ |
251
+ | if-then-else | - | - | - | ✅ | ✅ | ✅ | ✅ |
252
+ | infinite-loop-detection | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
253
+ | items | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
254
+ | maxContains | - | - | - | - | ✅ | ✅ | ✅ |
255
+ | maximum | 13/14 | 13/14 | ✅ | ✅ | ✅ | ✅ | ✅ |
256
+ | maxItems | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
257
+ | maxLength | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
258
+ | maxProperties | - | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
259
+ | minContains | - | - | - | - | ✅ | ✅ | ✅ |
260
+ | minimum | 12/13 | 16/17 | ✅ | ✅ | ✅ | ✅ | ✅ |
261
+ | minItems | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
262
+ | minLength | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
263
+ | minProperties | - | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
264
+ | multipleOf | - | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
265
+ | not | - | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
266
+ | oneOf | - | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
267
+ | pattern | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
268
+ | patternProperties | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
269
+ | prefixItems | - | - | - | - | - | ✅ | ✅ |
270
+ | properties | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
271
+ | propertyNames | - | - | ✅ | ✅ | ✅ | ✅ | ✅ |
272
+ | recursiveRef | - | - | - | - | ✅ | - | - |
273
+ | ref | 23/27 | 37/45 | 67/70 | 75/78 | 79/81 | 77/79 | 77/79 |
274
+ | required | 3/4 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
275
+ | type | 73/80 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
276
+ | unevaluatedItems | - | - | - | - | ✅ | 65/71 | 64/71 |
277
+ | unevaluatedProperties | - | - | - | - | ✅ | ✅ | 124/125 |
278
+ | uniqueItems | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
279
+
280
+
281
+ ### Performance
282
+
283
+ The following is compilation throughput for various JSON Schema structures using AJV8 as the baseline.
284
+
285
+ ```python
286
+ ┌──────────────────────┬─────────────┬─────────────┐
287
+ │ Compile │ TB1X │ AJV8 │
288
+ ├──────────────────────┼─────────────┼─────────────┤
289
+ │ Boolean │ 28.4K ops/s │ 7K ops/s │
290
+ │ Number │ 21.8K ops/s │ 7.7K ops/s │
291
+ │ String │ 47.8K ops/s │ 7.3K ops/s │
292
+ │ Null │ 35.6K ops/s │ 7.8K ops/s │
293
+ │ Literal_String │ 28.6K ops/s │ 6.3K ops/s │
294
+ │ Literal_Number │ 46.6K ops/s │ 6.2K ops/s │
295
+ │ Literal_Boolean │ 40.8K ops/s │ 6.6K ops/s │
296
+ │ Pattern │ 29.7K ops/s │ 4.9K ops/s │
297
+ │ Object_Open │ 6.8K ops/s │ 1.1K ops/s │
298
+ │ Object_Close │ 7.4K ops/s │ 833 ops/s │
299
+ │ Object_Vector3 │ 19.4K ops/s │ 2.1K ops/s │
300
+ │ Object_Basis3 │ 6K ops/s │ 895 ops/s │
301
+ │ Intersect_And │ 12K ops/s │ 3.5K ops/s │
302
+ │ Intersect_Structural │ 8.4K ops/s │ 1.1K ops/s │
303
+ │ Union_Or │ 18.2K ops/s │ 2.5K ops/s │
304
+ │ Union_Structural │ 10.9K ops/s │ 1.3K ops/s │
305
+ │ Tuple_Values │ 7.3K ops/s │ 1.6K ops/s │
306
+ │ Tuple_Objects │ 1.9K ops/s │ 339 ops/s │
307
+ │ Array_Numbers_4 │ 29.9K ops/s │ 3.4K ops/s │
308
+ │ Array_Numbers_8 │ 20.3K ops/s │ 3.4K ops/s │
309
+ │ Array_Numbers_16 │ 29.4K ops/s │ 3.3K ops/s │
310
+ │ Array_Objects_Open │ 6.3K ops/s │ 684 ops/s │
311
+ │ Array_Objects_Close │ 7.3K ops/s │ 762 ops/s │
312
+ └──────────────────────┴─────────────┴─────────────┘
313
+ ```
314
+
315
+
316
+ The following is the validation throughput for various JSON Schema structures using AJV8 as the baseline.
317
+
318
+ ```python
319
+ ┌──────────────────────┬──────────────┬──────────────┐
320
+ │ Validate │ TB1X │ AJV8 │
321
+ ├──────────────────────┼──────────────┼──────────────┤
322
+ │ Boolean │ 164.1M ops/s │ 181.5M ops/s │
323
+ │ Number │ 107M ops/s │ 50.2M ops/s │
324
+ │ String │ 102.2M ops/s │ 61.9M ops/s │
325
+ │ Null │ 112.1M ops/s │ 48.2M ops/s │
326
+ │ Literal_String │ 102.8M ops/s │ 61.5M ops/s │
327
+ │ Literal_Number │ 109.1M ops/s │ 46.4M ops/s │
328
+ │ Literal_Boolean │ 109.6M ops/s │ 63.3M ops/s │
329
+ │ Pattern │ 24.7M ops/s │ 20.3M ops/s │
330
+ │ Object_Open │ 75.4M ops/s │ 37.3M ops/s │
331
+ │ Object_Close │ 35.9M ops/s │ 21.9M ops/s │
332
+ │ Object_Vector3 │ 77.6M ops/s │ 47.4M ops/s │
333
+ │ Object_Basis3 │ 37M ops/s │ 24.3M ops/s │
334
+ │ Intersect_And │ 93.3M ops/s │ 61.1M ops/s │
335
+ │ Intersect_Structural │ 83M ops/s │ 36.4M ops/s │
336
+ │ Union_Or │ 99.7M ops/s │ 8.6M ops/s │
337
+ │ Union_Structural │ 81.3M ops/s │ 43.5M ops/s │
338
+ │ Tuple_Values │ 72.4M ops/s │ 41.7M ops/s │
339
+ │ Tuple_Objects │ 32.6M ops/s │ 22.4M ops/s │
340
+ │ Array_Numbers_4 │ 94.1M ops/s │ 42.8M ops/s │
341
+ │ Array_Numbers_8 │ 90.6M ops/s │ 42.3M ops/s │
342
+ │ Array_Numbers_16 │ 77.5M ops/s │ 40.2M ops/s │
343
+ │ Array_Objects_Open │ 26.3M ops/s │ 19.6M ops/s │
344
+ │ Array_Objects_Close │ 9.1M ops/s │ 10M ops/s │
345
+ └──────────────────────┴──────────────┴──────────────┘
229
346
  ```
230
347
 
231
348
  <a name="Versions"></a>
232
349
 
233
350
  ## Versions
234
351
 
235
- TypeBox provides two distinct versions that span two generations of the TypeScript compiler.
352
+ TypeBox ships two distinct versions that span two generations of the TypeScript compiler.
236
353
 
237
354
  | TypeBox | TypeScript | Description |
238
355
  | :--- | :--- | :--- |