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.
- package/build/schema/engine/_stack.d.mts +4 -4
- package/build/schema/engine/_stack.mjs +52 -18
- package/build/schema/engine/dynamicRef.d.mts +6 -0
- package/build/schema/engine/dynamicRef.mjs +25 -0
- package/build/schema/engine/recursiveRef.mjs +3 -3
- package/build/schema/engine/ref.mjs +3 -3
- package/build/schema/engine/schema.mjs +9 -4
- package/build/schema/resolve/ref.d.mts +1 -0
- package/build/schema/resolve/ref.mjs +61 -11
- package/package.json +30 -30
- package/readme.md +141 -24
|
@@ -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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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.
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
105
|
+
return FromArray(schema, nextBase, ref);
|
|
84
106
|
if (Guard.IsObject(schema))
|
|
85
|
-
return FromObject(schema,
|
|
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.
|
|
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
|
-
"./
|
|
20
|
-
"import": "./build/
|
|
21
|
-
"default": "./build/
|
|
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
|
-
"./
|
|
36
|
-
"import": "./build/
|
|
37
|
-
"default": "./build/
|
|
27
|
+
"./compile": {
|
|
28
|
+
"import": "./build/compile/index.mjs",
|
|
29
|
+
"default": "./build/compile/index.mjs"
|
|
38
30
|
},
|
|
39
|
-
"./
|
|
40
|
-
"import": "./build/
|
|
41
|
-
"default": "./build/
|
|
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
|
-
"
|
|
59
|
-
"./build/
|
|
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
|
-
"
|
|
71
|
-
"./build/
|
|
64
|
+
"compile": [
|
|
65
|
+
"./build/compile/index.d.mts"
|
|
72
66
|
],
|
|
73
|
-
"
|
|
74
|
-
"./build/
|
|
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
|
|
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
|
|
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/
|
|
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
|
|
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
|
|
352
|
+
TypeBox ships two distinct versions that span two generations of the TypeScript compiler.
|
|
236
353
|
|
|
237
354
|
| TypeBox | TypeScript | Description |
|
|
238
355
|
| :--- | :--- | :--- |
|