typebox 1.3.6 → 1.3.8
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/guard/emit.d.mts +3 -1
- package/build/guard/emit.mjs +12 -5
- package/build/guard/guard.d.mts +8 -2
- package/build/guard/guard.mjs +23 -2
- package/build/schema/engine/_context.mjs +3 -3
- package/build/schema/engine/_functions.mjs +1 -2
- package/build/schema/engine/additionalItems.mjs +17 -7
- package/build/schema/engine/contains.mjs +18 -6
- package/build/schema/engine/enum.mjs +1 -1
- package/build/schema/engine/items.mjs +26 -6
- package/build/schema/engine/maxContains.mjs +3 -3
- package/build/schema/engine/minContains.mjs +14 -4
- package/build/schema/engine/not.mjs +4 -2
- package/build/schema/engine/oneOf.mjs +7 -6
- package/build/schema/engine/ref.mjs +1 -7
- package/build/schema/engine/schema.mjs +1 -1
- package/build/schema/engine/type.mjs +1 -1
- package/build/value/errors/errors.d.mts +2 -2
- package/build/value/errors/errors.mjs +1 -1
- package/package.json +23 -23
- package/readme.md +39 -46
package/build/guard/emit.d.mts
CHANGED
|
@@ -33,6 +33,9 @@ export declare function IsGreaterEqualThan(left: string, right: string): string;
|
|
|
33
33
|
export declare function IsMinLength(value: string, length: string): string;
|
|
34
34
|
export declare function IsMaxLength(value: string, length: string): string;
|
|
35
35
|
export declare function Every(value: string, offset: string, params: [value: string, index: string], expression: string): string;
|
|
36
|
+
export declare function Some(value: string, params: [value: string, index: string], expression: string): string;
|
|
37
|
+
export declare function SomeAll(value: string, params: [value: string, index: string], expression: string): string;
|
|
38
|
+
export declare function Counted(value: string, params: [value: string, index: string], expression: string): string;
|
|
36
39
|
export declare function Entries(value: string): string;
|
|
37
40
|
export declare function Keys(value: string): string;
|
|
38
41
|
export declare function HasPropertyKey(value: string, key: string): string;
|
|
@@ -50,5 +53,4 @@ export declare function If(condition: string, then: string): string;
|
|
|
50
53
|
export declare function Return(expression: string): string;
|
|
51
54
|
export declare function ReduceAnd(operands: string[]): string;
|
|
52
55
|
export declare function ReduceOr(operands: string[]): string;
|
|
53
|
-
export declare function PrefixIncrement(expression: string): string;
|
|
54
56
|
export declare function MultipleOf(dividend: string, divisor: string): string;
|
package/build/guard/emit.mjs
CHANGED
|
@@ -110,6 +110,15 @@ export function Every(value, offset, params, expression) {
|
|
|
110
110
|
? `${value}.every((${params[0]}, ${params[1]}) => ${expression})`
|
|
111
111
|
: `((value, callback) => { for(let index = ${offset}; index < value.length; index++) if (!callback(value[index], index)) return false; return true })(${value}, (${params[0]}, ${params[1]}) => ${expression})`;
|
|
112
112
|
}
|
|
113
|
+
export function Some(value, params, expression) {
|
|
114
|
+
return `${value}.some((${params[0]}, ${params[1]}) => ${expression})`;
|
|
115
|
+
}
|
|
116
|
+
export function SomeAll(value, params, expression) {
|
|
117
|
+
return `((value, callback) => { let result = false; for(let index = 0; index < value.length; index++) if (callback(value[index], index)) result = true; return result })(${value}, (${params[0]}, ${params[1]}) => ${expression})`;
|
|
118
|
+
}
|
|
119
|
+
export function Counted(value, params, expression) {
|
|
120
|
+
return `${value}.reduce((result, ${params[0]}, ${params[1]}) => (${expression}) ? ++result : result, 0)`;
|
|
121
|
+
}
|
|
113
122
|
// --------------------------------------------------------------------------
|
|
114
123
|
// Objects
|
|
115
124
|
// --------------------------------------------------------------------------
|
|
@@ -145,6 +154,8 @@ export function Member(left, right) {
|
|
|
145
154
|
return `${left}${IsIdentifier(right) ? `.${right}` : `[${Constant(right)}]`}`;
|
|
146
155
|
}
|
|
147
156
|
export function Constant(value) {
|
|
157
|
+
if (!G.IsValueLike(value))
|
|
158
|
+
throw Error('Unsupported Constant');
|
|
148
159
|
return G.IsString(value) ? JSON.stringify(value) : `${value}`;
|
|
149
160
|
}
|
|
150
161
|
export function Ternary(condition, true_, false_) {
|
|
@@ -172,15 +183,11 @@ export function ReduceAnd(operands) {
|
|
|
172
183
|
return G.IsEqual(operands.length, 0) ? 'true' : operands.reduce((left, right) => And(left, right));
|
|
173
184
|
}
|
|
174
185
|
export function ReduceOr(operands) {
|
|
175
|
-
// deno-coverage-ignore - we never observe 0 operands
|
|
176
186
|
return G.IsEqual(operands.length, 0) ? 'false' : operands.reduce((left, right) => Or(left, right));
|
|
177
187
|
}
|
|
178
188
|
// --------------------------------------------------------------------------
|
|
179
|
-
//
|
|
189
|
+
// MultipleOf
|
|
180
190
|
// --------------------------------------------------------------------------
|
|
181
|
-
export function PrefixIncrement(expression) {
|
|
182
|
-
return `++${expression}`;
|
|
183
|
-
}
|
|
184
191
|
export function MultipleOf(dividend, divisor) {
|
|
185
192
|
return `Guard.IsMultipleOf(${dividend}, ${divisor})`;
|
|
186
193
|
}
|
package/build/guard/guard.d.mts
CHANGED
|
@@ -39,10 +39,16 @@ export declare function GraphemeCount(value: string): number;
|
|
|
39
39
|
export declare function IsMaxLength(value: string, length: number): boolean;
|
|
40
40
|
/** Returns true if the string has at least the given number of graphemes */
|
|
41
41
|
export declare function IsMinLength(value: string, length: number): boolean;
|
|
42
|
-
/** Returns true if
|
|
42
|
+
/** Returns true if every element from offset satisfies the callback, short-circuiting on the first failure */
|
|
43
43
|
export declare function Every<T>(value: T[], offset: number, callback: (value: T, index: number) => boolean): boolean;
|
|
44
|
-
/** Returns true if
|
|
44
|
+
/** Returns true if every element from offset satisfies the callback, using exhaustive enumeration */
|
|
45
45
|
export declare function EveryAll<T>(value: T[], offset: number, callback: (value: T, index: number) => boolean): boolean;
|
|
46
|
+
/** Returns true if some element satisfies the callback, short-circuiting on the first success */
|
|
47
|
+
export declare function Some<T>(value: T[], callback: (value: T, index: number) => boolean): boolean;
|
|
48
|
+
/** Returns true if some element satisfies the callback, using exhaustive enumeration */
|
|
49
|
+
export declare function SomeAll<T>(value: T[], callback: (value: T, index: number) => boolean): boolean;
|
|
50
|
+
/** Returns the count of elements that satisfy the callback */
|
|
51
|
+
export declare function Counted(value: unknown[], callback: (value: unknown, index: number) => boolean): number;
|
|
46
52
|
/** Shifts the left-most element from an array and dispatches to the true arm, or the false arm if empty */
|
|
47
53
|
export declare function ShiftLeft<T, True extends (left: T, right: T[]) => unknown, False extends () => unknown>(array: T[], true_: True, false_: False): ReturnType<True> | ReturnType<False>;
|
|
48
54
|
/** Returns true if the PropertyKey is Unsafe (ref: prototype-pollution). */
|
package/build/guard/guard.mjs
CHANGED
|
@@ -138,7 +138,7 @@ export function IsMinLength(value, length) {
|
|
|
138
138
|
// --------------------------------------------------------------------------
|
|
139
139
|
// Array
|
|
140
140
|
// --------------------------------------------------------------------------
|
|
141
|
-
/** Returns true if
|
|
141
|
+
/** Returns true if every element from offset satisfies the callback, short-circuiting on the first failure */
|
|
142
142
|
export function Every(value, offset, callback) {
|
|
143
143
|
for (let index = offset; index < value.length; index++) {
|
|
144
144
|
if (!callback(value[index], index))
|
|
@@ -146,7 +146,7 @@ export function Every(value, offset, callback) {
|
|
|
146
146
|
}
|
|
147
147
|
return true;
|
|
148
148
|
}
|
|
149
|
-
/** Returns true if
|
|
149
|
+
/** Returns true if every element from offset satisfies the callback, using exhaustive enumeration */
|
|
150
150
|
export function EveryAll(value, offset, callback) {
|
|
151
151
|
let result = true;
|
|
152
152
|
for (let index = offset; index < value.length; index++) {
|
|
@@ -155,6 +155,27 @@ export function EveryAll(value, offset, callback) {
|
|
|
155
155
|
}
|
|
156
156
|
return result;
|
|
157
157
|
}
|
|
158
|
+
/** Returns true if some element satisfies the callback, short-circuiting on the first success */
|
|
159
|
+
export function Some(value, callback) {
|
|
160
|
+
for (let index = 0; index < value.length; index++) {
|
|
161
|
+
if (callback(value[index], index))
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
/** Returns true if some element satisfies the callback, using exhaustive enumeration */
|
|
167
|
+
export function SomeAll(value, callback) {
|
|
168
|
+
let result = false;
|
|
169
|
+
for (let index = 0; index < value.length; index++) {
|
|
170
|
+
if (callback(value[index], index))
|
|
171
|
+
result = true;
|
|
172
|
+
}
|
|
173
|
+
return result;
|
|
174
|
+
}
|
|
175
|
+
/** Returns the count of elements that satisfy the callback */
|
|
176
|
+
export function Counted(value, callback) {
|
|
177
|
+
return value.reduce((result, value, index) => callback(value, index) ? ++result : result, 0);
|
|
178
|
+
}
|
|
158
179
|
/** Shifts the left-most element from an array and dispatches to the true arm, or the false arm if empty */
|
|
159
180
|
export function ShiftLeft(array, true_, false_) {
|
|
160
181
|
return (IsEqual(array.length, 0) ? false_() : true_(array[0], array.slice(1)));
|
|
@@ -7,10 +7,10 @@ import { Guard as G, EmitGuard as E } from '../../guard/index.mjs';
|
|
|
7
7
|
function HasUnevaluatedFromObject(value) {
|
|
8
8
|
return (Schema.IsUnevaluatedItems(value)
|
|
9
9
|
|| Schema.IsUnevaluatedProperties(value)
|
|
10
|
-
|| G.Keys(value)
|
|
10
|
+
|| G.Some(G.Keys(value), key => HasUnevaluatedFromUnknown(value[key])));
|
|
11
11
|
}
|
|
12
12
|
function HasUnevaluatedFromArray(value) {
|
|
13
|
-
return
|
|
13
|
+
return G.Some(value, value => HasUnevaluatedFromUnknown(value));
|
|
14
14
|
}
|
|
15
15
|
function HasUnevaluatedFromUnknown(value) {
|
|
16
16
|
return (G.IsArray(value) ? HasUnevaluatedFromArray(value) :
|
|
@@ -18,7 +18,7 @@ function HasUnevaluatedFromUnknown(value) {
|
|
|
18
18
|
false);
|
|
19
19
|
}
|
|
20
20
|
export function HasUnevaluated(context, schema) {
|
|
21
|
-
return HasUnevaluatedFromUnknown(schema) || G.Keys(context)
|
|
21
|
+
return HasUnevaluatedFromUnknown(schema) || G.Some(G.Keys(context), key => HasUnevaluatedFromUnknown(context[key]));
|
|
22
22
|
}
|
|
23
23
|
// ------------------------------------------------------------------
|
|
24
24
|
// BuildContext
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// deno-fmt-ignore-file
|
|
2
|
-
import { Hashing } from '../../system/hashing/index.mjs';
|
|
3
2
|
import { EmitGuard as E } from '../../guard/index.mjs';
|
|
4
3
|
import { BuildSchema } from './schema.mjs';
|
|
5
4
|
const index = [0];
|
|
@@ -9,7 +8,7 @@ const funcs = new Map();
|
|
|
9
8
|
// CreateName
|
|
10
9
|
// ------------------------------------------------------------------
|
|
11
10
|
function NextName() {
|
|
12
|
-
return
|
|
11
|
+
return `${index[0]++}`;
|
|
13
12
|
}
|
|
14
13
|
function CreateName(schema, href) {
|
|
15
14
|
if (!names.has(schema))
|
|
@@ -12,15 +12,25 @@ function IsValid(schema) {
|
|
|
12
12
|
// ------------------------------------------------------------------
|
|
13
13
|
// Build
|
|
14
14
|
// ------------------------------------------------------------------
|
|
15
|
-
|
|
16
|
-
if (!IsValid(schema))
|
|
17
|
-
return E.Constant(true);
|
|
15
|
+
function BuildAdditionalItemsStandard(stack, context, schema, value) {
|
|
18
16
|
const [item, index] = [Unique(), Unique()];
|
|
19
17
|
const isSchema = BuildSchemaPushStack(stack, context, schema.additionalItems, item);
|
|
20
18
|
const isLength = E.IsLessThan(index, E.Constant(schema.items.length));
|
|
21
19
|
const addIndex = context.AddIndex(index);
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
return E.Every(value, E.Constant(0), [item, index], E.Or(isLength, E.And(isSchema, addIndex)));
|
|
21
|
+
}
|
|
22
|
+
function BuildAdditionalItemsFast(stack, context, schema, value) {
|
|
23
|
+
const [item, index] = [Unique(), Unique()];
|
|
24
|
+
const isSchema = BuildSchemaPushStack(stack, context, schema.additionalItems, item);
|
|
25
|
+
const isLength = E.IsLessThan(index, E.Constant(schema.items.length));
|
|
26
|
+
return E.Every(value, E.Constant(0), [item, index], E.Or(isLength, isSchema));
|
|
27
|
+
}
|
|
28
|
+
export function BuildAdditionalItems(stack, context, schema, value) {
|
|
29
|
+
if (!IsValid(schema))
|
|
30
|
+
return E.Constant(true);
|
|
31
|
+
return context.UseUnevaluated()
|
|
32
|
+
? BuildAdditionalItemsStandard(stack, context, schema, value)
|
|
33
|
+
: BuildAdditionalItemsFast(stack, context, schema, value);
|
|
24
34
|
}
|
|
25
35
|
// ------------------------------------------------------------------
|
|
26
36
|
// Check
|
|
@@ -28,7 +38,7 @@ export function BuildAdditionalItems(stack, context, schema, value) {
|
|
|
28
38
|
export function CheckAdditionalItems(stack, context, schema, value) {
|
|
29
39
|
if (!IsValid(schema))
|
|
30
40
|
return true;
|
|
31
|
-
const isAdditionalItems =
|
|
41
|
+
const isAdditionalItems = G.Every(value, 0, (item, index) => {
|
|
32
42
|
return G.IsLessThan(index, schema.items.length)
|
|
33
43
|
|| (CheckSchemaPushStack(stack, context, schema.additionalItems, item) && context.AddIndex(index));
|
|
34
44
|
});
|
|
@@ -40,7 +50,7 @@ export function CheckAdditionalItems(stack, context, schema, value) {
|
|
|
40
50
|
export function ErrorAdditionalItems(stack, context, schemaPath, instancePath, schema, value) {
|
|
41
51
|
if (!IsValid(schema))
|
|
42
52
|
return true;
|
|
43
|
-
const isAdditionalItems =
|
|
53
|
+
const isAdditionalItems = G.Every(value, 0, (item, index) => {
|
|
44
54
|
const nextSchemaPath = `${schemaPath}/additionalItems`;
|
|
45
55
|
const nextInstancePath = `${instancePath}/${index}`;
|
|
46
56
|
return G.IsLessThan(index, schema.items.length) ||
|
|
@@ -12,13 +12,24 @@ function IsValid(schema) {
|
|
|
12
12
|
// ------------------------------------------------------------------
|
|
13
13
|
// Build
|
|
14
14
|
// ------------------------------------------------------------------
|
|
15
|
+
function BuildContainsStandard(stack, context, schema, value) {
|
|
16
|
+
const [item, index] = [Unique(), Unique()];
|
|
17
|
+
const isLength = E.Not(E.IsEqual(E.Member(value, 'length'), E.Constant(0)));
|
|
18
|
+
const isSome = E.SomeAll(value, [item, index], E.And(BuildSchema(stack, context, schema.contains, item), context.AddIndex(index)));
|
|
19
|
+
return E.And(isLength, isSome);
|
|
20
|
+
}
|
|
21
|
+
function BuildContainsFast(stack, context, schema, value) {
|
|
22
|
+
const [item] = [Unique()];
|
|
23
|
+
const isLength = E.Not(E.IsEqual(E.Member(value, 'length'), E.Constant(0)));
|
|
24
|
+
const isSome = E.Some(value, [item, '_'], BuildSchema(stack, context, schema.contains, item));
|
|
25
|
+
return E.And(isLength, isSome);
|
|
26
|
+
}
|
|
15
27
|
export function BuildContains(stack, context, schema, value) {
|
|
16
28
|
if (!IsValid(schema))
|
|
17
29
|
return E.Constant(true);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return E.And(isLength, isSome);
|
|
30
|
+
return context.UseUnevaluated()
|
|
31
|
+
? BuildContainsStandard(stack, context, schema, value)
|
|
32
|
+
: BuildContainsFast(stack, context, schema, value);
|
|
22
33
|
}
|
|
23
34
|
// ------------------------------------------------------------------
|
|
24
35
|
// Check
|
|
@@ -26,8 +37,9 @@ export function BuildContains(stack, context, schema, value) {
|
|
|
26
37
|
export function CheckContains(stack, context, schema, value) {
|
|
27
38
|
if (!IsValid(schema))
|
|
28
39
|
return true;
|
|
29
|
-
return !G.IsEqual(value.length, 0) &&
|
|
30
|
-
|
|
40
|
+
return !G.IsEqual(value.length, 0) && G.SomeAll(value, (item, index) => {
|
|
41
|
+
return CheckSchema(stack, context, schema.contains, item) && context.AddIndex(index);
|
|
42
|
+
});
|
|
31
43
|
}
|
|
32
44
|
// ------------------------------------------------------------------
|
|
33
45
|
// Error
|
|
@@ -16,7 +16,7 @@ export function BuildEnum(_stack, _context, schema, value) {
|
|
|
16
16
|
// Check
|
|
17
17
|
// ------------------------------------------------------------------
|
|
18
18
|
export function CheckEnum(_stack, _context, schema, value) {
|
|
19
|
-
return schema.enum
|
|
19
|
+
return G.Some(schema.enum, option => G.IsValueLike(option)
|
|
20
20
|
? G.IsEqual(value, option)
|
|
21
21
|
: G.IsDeepEqual(value, option));
|
|
22
22
|
}
|
|
@@ -5,15 +5,26 @@ import { BuildSchemaPushStack, CheckSchemaPushStack, ErrorSchemaPushStack } from
|
|
|
5
5
|
// ------------------------------------------------------------------
|
|
6
6
|
// ItemsSized
|
|
7
7
|
// ------------------------------------------------------------------
|
|
8
|
-
function
|
|
8
|
+
function BuildItemsSizedStandard(stack, context, schema, value) {
|
|
9
9
|
return E.ReduceAnd(schema.items.map((schema, index) => {
|
|
10
10
|
const isLength = E.IsLessEqualThan(E.Member(value, 'length'), E.Constant(index));
|
|
11
11
|
const isSchema = BuildSchemaPushStack(stack, context, schema, `${value}[${index}]`);
|
|
12
12
|
const addIndex = context.AddIndex(E.Constant(index));
|
|
13
|
-
|
|
14
|
-
return E.Or(isLength, guarded);
|
|
13
|
+
return E.Or(isLength, E.And(isSchema, addIndex));
|
|
15
14
|
}));
|
|
16
15
|
}
|
|
16
|
+
function BuildItemsSizedFast(stack, context, schema, value) {
|
|
17
|
+
return E.ReduceAnd(schema.items.map((schema, index) => {
|
|
18
|
+
const isLength = E.IsLessEqualThan(E.Member(value, 'length'), E.Constant(index));
|
|
19
|
+
const isSchema = BuildSchemaPushStack(stack, context, schema, `${value}[${index}]`);
|
|
20
|
+
return E.Or(isLength, isSchema);
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
function BuildItemsSized(stack, context, schema, value) {
|
|
24
|
+
return context.UseUnevaluated()
|
|
25
|
+
? BuildItemsSizedStandard(stack, context, schema, value)
|
|
26
|
+
: BuildItemsSizedFast(stack, context, schema, value);
|
|
27
|
+
}
|
|
17
28
|
function CheckItemsSized(stack, context, schema, value) {
|
|
18
29
|
return G.Every(schema.items, 0, (schema, index) => {
|
|
19
30
|
return G.IsLessEqualThan(value.length, index)
|
|
@@ -31,12 +42,21 @@ function ErrorItemsSized(stack, context, schemaPath, instancePath, schema, value
|
|
|
31
42
|
// ------------------------------------------------------------------
|
|
32
43
|
// ItemsUnsized
|
|
33
44
|
// ------------------------------------------------------------------
|
|
34
|
-
function
|
|
45
|
+
function BuildItemsUnsizedStandard(stack, context, schema, value) {
|
|
35
46
|
const offset = Schema.IsPrefixItems(schema) ? schema.prefixItems.length : 0;
|
|
36
47
|
const isSchema = BuildSchemaPushStack(stack, context, schema.items, 'element');
|
|
37
48
|
const addIndex = context.AddIndex('index');
|
|
38
|
-
|
|
39
|
-
|
|
49
|
+
return E.Every(value, E.Constant(offset), ['element', 'index'], E.And(isSchema, addIndex));
|
|
50
|
+
}
|
|
51
|
+
function BuildItemsUnsizedFast(stack, context, schema, value) {
|
|
52
|
+
const offset = Schema.IsPrefixItems(schema) ? schema.prefixItems.length : 0;
|
|
53
|
+
const isSchema = BuildSchemaPushStack(stack, context, schema.items, 'element');
|
|
54
|
+
return E.Every(value, E.Constant(offset), ['element', 'index'], isSchema);
|
|
55
|
+
}
|
|
56
|
+
function BuildItemsUnsized(stack, context, schema, value) {
|
|
57
|
+
return context.UseUnevaluated()
|
|
58
|
+
? BuildItemsUnsizedStandard(stack, context, schema, value)
|
|
59
|
+
: BuildItemsUnsizedFast(stack, context, schema, value);
|
|
40
60
|
}
|
|
41
61
|
function CheckItemsUnsized(stack, context, schema, value) {
|
|
42
62
|
const offset = Schema.IsPrefixItems(schema) ? schema.prefixItems.length : 0;
|
|
@@ -15,8 +15,8 @@ function IsValid(schema) {
|
|
|
15
15
|
export function BuildMaxContains(stack, context, schema, value) {
|
|
16
16
|
if (!IsValid(schema))
|
|
17
17
|
return E.Constant(true);
|
|
18
|
-
const [
|
|
19
|
-
const count = E.
|
|
18
|
+
const [item] = [Unique()];
|
|
19
|
+
const count = E.Counted(value, [item, '_'], BuildSchema(stack, context, schema.contains, item));
|
|
20
20
|
return E.IsLessEqualThan(count, E.Constant(schema.maxContains));
|
|
21
21
|
}
|
|
22
22
|
// ------------------------------------------------------------------
|
|
@@ -25,7 +25,7 @@ export function BuildMaxContains(stack, context, schema, value) {
|
|
|
25
25
|
export function CheckMaxContains(stack, context, schema, value) {
|
|
26
26
|
if (!IsValid(schema))
|
|
27
27
|
return true;
|
|
28
|
-
const count =
|
|
28
|
+
const count = G.Counted(value, (item) => CheckSchema(stack, context, schema.contains, item));
|
|
29
29
|
return G.IsLessEqualThan(count, schema.maxContains);
|
|
30
30
|
}
|
|
31
31
|
// ------------------------------------------------------------------
|
|
@@ -12,12 +12,22 @@ function IsValid(schema) {
|
|
|
12
12
|
// ------------------------------------------------------------------
|
|
13
13
|
// Build
|
|
14
14
|
// ------------------------------------------------------------------
|
|
15
|
+
function BuildMinContainsStandard(stack, context, schema, value) {
|
|
16
|
+
const [item, index] = [Unique(), Unique()];
|
|
17
|
+
const count = E.Counted(value, [item, index], E.And(BuildSchema(stack, context, schema.contains, item), context.AddIndex(index)));
|
|
18
|
+
return E.IsGreaterEqualThan(count, E.Constant(schema.minContains));
|
|
19
|
+
}
|
|
20
|
+
function BuildMinContainsFast(stack, context, schema, value) {
|
|
21
|
+
const [item] = [Unique()];
|
|
22
|
+
const count = E.Counted(value, [item, '_'], BuildSchema(stack, context, schema.contains, item));
|
|
23
|
+
return E.IsGreaterEqualThan(count, E.Constant(schema.minContains));
|
|
24
|
+
}
|
|
15
25
|
export function BuildMinContains(stack, context, schema, value) {
|
|
16
26
|
if (!IsValid(schema))
|
|
17
27
|
return E.Constant(true);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
28
|
+
return context.UseUnevaluated()
|
|
29
|
+
? BuildMinContainsStandard(stack, context, schema, value)
|
|
30
|
+
: BuildMinContainsFast(stack, context, schema, value);
|
|
21
31
|
}
|
|
22
32
|
// ------------------------------------------------------------------
|
|
23
33
|
// Check
|
|
@@ -25,7 +35,7 @@ export function BuildMinContains(stack, context, schema, value) {
|
|
|
25
35
|
export function CheckMinContains(stack, context, schema, value) {
|
|
26
36
|
if (!IsValid(schema))
|
|
27
37
|
return true;
|
|
28
|
-
const count =
|
|
38
|
+
const count = G.Counted(value, (item, index) => CheckSchema(stack, context, schema.contains, item) && context.AddIndex(index));
|
|
29
39
|
return G.IsGreaterEqualThan(count, schema.minContains);
|
|
30
40
|
}
|
|
31
41
|
// ------------------------------------------------------------------
|
|
@@ -6,14 +6,16 @@ import { BuildSchema, CheckSchema } from './schema.mjs';
|
|
|
6
6
|
// ------------------------------------------------------------------
|
|
7
7
|
// Build
|
|
8
8
|
// ------------------------------------------------------------------
|
|
9
|
-
function
|
|
9
|
+
function BuildNotStandard(stack, context, schema, value) {
|
|
10
10
|
return Reducer(stack, context, [schema.not], value, E.Not(E.IsEqual(E.Member('results', 'length'), E.Constant(1))));
|
|
11
11
|
}
|
|
12
12
|
function BuildNotFast(stack, context, schema, value) {
|
|
13
13
|
return E.Not(BuildSchema(stack, context, schema.not, value));
|
|
14
14
|
}
|
|
15
15
|
export function BuildNot(stack, context, schema, value) {
|
|
16
|
-
return context.UseUnevaluated()
|
|
16
|
+
return context.UseUnevaluated()
|
|
17
|
+
? BuildNotStandard(stack, context, schema, value)
|
|
18
|
+
: BuildNotFast(stack, context, schema, value);
|
|
17
19
|
}
|
|
18
20
|
// ------------------------------------------------------------------
|
|
19
21
|
// Check
|
|
@@ -3,22 +3,23 @@ import { CheckContext, AccumulatedErrorContext } from './_context.mjs';
|
|
|
3
3
|
import { Reducer } from './_reducer.mjs';
|
|
4
4
|
import { EmitGuard as E, Guard as G } from '../../guard/index.mjs';
|
|
5
5
|
import { BuildSchema, CheckSchema, ErrorSchema } from './schema.mjs';
|
|
6
|
+
import { Unique } from './_unique.mjs';
|
|
6
7
|
// ------------------------------------------------------------------
|
|
7
8
|
// Build
|
|
8
9
|
// ------------------------------------------------------------------
|
|
9
|
-
function
|
|
10
|
+
function BuildOneOfStandard(stack, context, schema, value) {
|
|
10
11
|
return Reducer(stack, context, schema.oneOf, value, E.IsEqual(E.Member('results', 'length'), E.Constant(1)));
|
|
11
12
|
}
|
|
12
13
|
function BuildOneOfFast(stack, context, schema, value) {
|
|
14
|
+
const [result] = [Unique()];
|
|
13
15
|
const results = E.ArrayLiteral(schema.oneOf.map((schema) => BuildSchema(stack, context, schema, value)));
|
|
14
|
-
const count = E.
|
|
15
|
-
E.ArrowFunction(['count', 'result'], E.Ternary(E.IsEqual('result', E.Constant(true)), E.PrefixIncrement('count'), 'count')),
|
|
16
|
-
E.Constant(0),
|
|
17
|
-
]);
|
|
16
|
+
const count = E.Counted(results, [result, '_'], E.IsEqual(result, E.Constant(true)));
|
|
18
17
|
return E.IsEqual(count, E.Constant(1));
|
|
19
18
|
}
|
|
20
19
|
export function BuildOneOf(stack, context, schema, value) {
|
|
21
|
-
return context.UseUnevaluated()
|
|
20
|
+
return context.UseUnevaluated()
|
|
21
|
+
? BuildOneOfStandard(stack, context, schema, value)
|
|
22
|
+
: BuildOneOfFast(stack, context, schema, value);
|
|
22
23
|
}
|
|
23
24
|
// ------------------------------------------------------------------
|
|
24
25
|
// Check
|
|
@@ -5,7 +5,7 @@ import { CheckContext, AccumulatedErrorContext } from './_context.mjs';
|
|
|
5
5
|
import { EmitGuard as E } from '../../guard/index.mjs';
|
|
6
6
|
import { CheckSchema, ErrorSchema } from './schema.mjs';
|
|
7
7
|
// ------------------------------------------------------------------
|
|
8
|
-
//
|
|
8
|
+
// BuildRef
|
|
9
9
|
// ------------------------------------------------------------------
|
|
10
10
|
function BuildRefStandard(stack, context, target, value) {
|
|
11
11
|
const interior = E.ArrowFunction(['context', 'value'], Functions.CreateFunction(stack, context, target, 'value'));
|
|
@@ -17,15 +17,9 @@ function BuildRefStandard(stack, context, target, value) {
|
|
|
17
17
|
]));
|
|
18
18
|
return E.Call(exterior, ['context', value]);
|
|
19
19
|
}
|
|
20
|
-
// ------------------------------------------------------------------
|
|
21
|
-
// BuildRefStandard
|
|
22
|
-
// ------------------------------------------------------------------
|
|
23
20
|
function BuildRefFast(stack, context, target, value) {
|
|
24
21
|
return Functions.CreateFunction(stack, context, target, value);
|
|
25
22
|
}
|
|
26
|
-
// ------------------------------------------------------------------
|
|
27
|
-
// BuildRef
|
|
28
|
-
// ------------------------------------------------------------------
|
|
29
23
|
export function BuildRef(stack, context, schema, value) {
|
|
30
24
|
const target = stack.Ref(schema) ?? false;
|
|
31
25
|
return context.UseUnevaluated()
|
|
@@ -49,7 +49,7 @@ import { BuildUniqueItems, CheckUniqueItems, ErrorUniqueItems } from './uniqueIt
|
|
|
49
49
|
// ----------------------------------------------------------------
|
|
50
50
|
function HasTypeName(schema, typename) {
|
|
51
51
|
return Schema.IsType(schema) &&
|
|
52
|
-
(G.IsArray(schema.type) && schema.type.
|
|
52
|
+
(G.IsArray(schema.type) && G.IsGreaterThan(schema.type.length, 0) && G.Every(schema.type, 0, type => G.IsEqual(type, typename)) ||
|
|
53
53
|
G.IsEqual(schema.type, typename));
|
|
54
54
|
}
|
|
55
55
|
// ----------------------------------------------------------------
|
|
@@ -48,7 +48,7 @@ function BuildTypeNames(stack, context, typenames, value) {
|
|
|
48
48
|
return E.ReduceOr(typenames.map(type => BuildTypeName(stack, context, type, value)));
|
|
49
49
|
}
|
|
50
50
|
function CheckTypeNames(stack, context, types, schema, value) {
|
|
51
|
-
return
|
|
51
|
+
return G.Some(types, type => CheckTypeName(stack, context, type, schema, value));
|
|
52
52
|
}
|
|
53
53
|
// ------------------------------------------------------------------
|
|
54
54
|
// Type
|
|
@@ -3,14 +3,14 @@ import type { TLocalizedValidationError } from '../../error/index.mjs';
|
|
|
3
3
|
/**
|
|
4
4
|
* Performs an exhaustive Check on the specified value and reports any errors found.
|
|
5
5
|
* If no errors are found, an empty array is returned. Unlike Check, this function
|
|
6
|
-
* does not terminate at the first
|
|
6
|
+
* does not terminate at the first occurrence of an error. For best performance, call
|
|
7
7
|
* Check first and call Errors only if Check returns false.
|
|
8
8
|
*/
|
|
9
9
|
export declare function Errors<Type extends TSchema>(type: Type, value: unknown): TLocalizedValidationError[];
|
|
10
10
|
/**
|
|
11
11
|
* Performs an exhaustive Check on the specified value and reports any errors found.
|
|
12
12
|
* If no errors are found, an empty array is returned. Unlike Check, this function
|
|
13
|
-
* does not terminate at the first
|
|
13
|
+
* does not terminate at the first occurrence of an error. For best performance, call
|
|
14
14
|
* Check first and call Errors only if Check returns false.
|
|
15
15
|
*/
|
|
16
16
|
export declare function Errors<Context extends TProperties, Type extends TSchema>(context: Context, type: Type, value: unknown): TLocalizedValidationError[];
|
|
@@ -4,7 +4,7 @@ import { Errors as SchemaErrors, } from '../../schema/index.mjs';
|
|
|
4
4
|
/**
|
|
5
5
|
* Performs an exhaustive Check on the specified value and reports any errors found.
|
|
6
6
|
* If no errors are found, an empty array is returned. Unlike Check, this function
|
|
7
|
-
* does not terminate at the first
|
|
7
|
+
* does not terminate at the first occurrence of an error. For best performance, call
|
|
8
8
|
* Check first and call Errors only if Check returns false.
|
|
9
9
|
*/
|
|
10
10
|
export function Errors(...args) {
|
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.3.
|
|
4
|
+
"version": "1.3.8",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
7
7
|
"jsonschema"
|
|
@@ -16,17 +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/
|
|
19
|
+
"./error": {
|
|
20
|
+
"import": "./build/error/index.mjs",
|
|
21
|
+
"default": "./build/error/index.mjs"
|
|
22
|
+
},
|
|
23
|
+
"./value": {
|
|
24
|
+
"import": "./build/value/index.mjs",
|
|
25
|
+
"default": "./build/value/index.mjs"
|
|
22
26
|
},
|
|
23
27
|
"./system": {
|
|
24
28
|
"import": "./build/system/index.mjs",
|
|
25
29
|
"default": "./build/system/index.mjs"
|
|
26
30
|
},
|
|
27
|
-
"./
|
|
28
|
-
"import": "./build/
|
|
29
|
-
"default": "./build/
|
|
31
|
+
"./guard": {
|
|
32
|
+
"import": "./build/guard/index.mjs",
|
|
33
|
+
"default": "./build/guard/index.mjs"
|
|
30
34
|
},
|
|
31
35
|
"./format": {
|
|
32
36
|
"import": "./build/format/index.mjs",
|
|
@@ -40,13 +44,9 @@
|
|
|
40
44
|
"import": "./build/type/index.mjs",
|
|
41
45
|
"default": "./build/type/index.mjs"
|
|
42
46
|
},
|
|
43
|
-
"./
|
|
44
|
-
"import": "./build/
|
|
45
|
-
"default": "./build/
|
|
46
|
-
},
|
|
47
|
-
"./error": {
|
|
48
|
-
"import": "./build/error/index.mjs",
|
|
49
|
-
"default": "./build/error/index.mjs"
|
|
47
|
+
"./schema": {
|
|
48
|
+
"import": "./build/schema/index.mjs",
|
|
49
|
+
"default": "./build/schema/index.mjs"
|
|
50
50
|
},
|
|
51
51
|
".": {
|
|
52
52
|
"import": "./build/index.mjs",
|
|
@@ -55,14 +55,17 @@
|
|
|
55
55
|
},
|
|
56
56
|
"typesVersions": {
|
|
57
57
|
"*": {
|
|
58
|
-
"
|
|
59
|
-
"./build/
|
|
58
|
+
"error": [
|
|
59
|
+
"./build/error/index.d.mts"
|
|
60
|
+
],
|
|
61
|
+
"value": [
|
|
62
|
+
"./build/value/index.d.mts"
|
|
60
63
|
],
|
|
61
64
|
"system": [
|
|
62
65
|
"./build/system/index.d.mts"
|
|
63
66
|
],
|
|
64
|
-
"
|
|
65
|
-
"./build/
|
|
67
|
+
"guard": [
|
|
68
|
+
"./build/guard/index.d.mts"
|
|
66
69
|
],
|
|
67
70
|
"format": [
|
|
68
71
|
"./build/format/index.d.mts"
|
|
@@ -73,11 +76,8 @@
|
|
|
73
76
|
"type": [
|
|
74
77
|
"./build/type/index.d.mts"
|
|
75
78
|
],
|
|
76
|
-
"
|
|
77
|
-
"./build/
|
|
78
|
-
],
|
|
79
|
-
"error": [
|
|
80
|
-
"./build/error/index.d.mts"
|
|
79
|
+
"schema": [
|
|
80
|
+
"./build/schema/index.d.mts"
|
|
81
81
|
],
|
|
82
82
|
".": [
|
|
83
83
|
"./build/index.d.mts"
|
package/readme.md
CHANGED
|
@@ -91,7 +91,7 @@ const User = Type.Object({ // const User = {
|
|
|
91
91
|
// type: 'string',
|
|
92
92
|
// format: 'email'
|
|
93
93
|
// }
|
|
94
|
-
// }
|
|
94
|
+
// },
|
|
95
95
|
// required: [
|
|
96
96
|
// 'id',
|
|
97
97
|
// 'name',
|
|
@@ -111,9 +111,9 @@ type User = Type.Static<typeof User> // type User = {
|
|
|
111
111
|
|
|
112
112
|
## Script
|
|
113
113
|
|
|
114
|
-
[Documentation](https://sinclairzx81.github.io/typebox/#/docs/script/overview) | [Example 1](https://www.typescriptlang.org/play/?target=99&module=7#code/
|
|
114
|
+
[Documentation](https://sinclairzx81.github.io/typebox/#/docs/script/overview) | [Example 1](https://www.typescriptlang.org/play/?target=99&module=7#code/JYWwDg9gTgLgBAFQJ5gKZwGZQiOByGFVAIwgA88AoSgehrgFkIATAVwBtVKBjCAOwDO8AN5wAChCFwAvnAC8iIgDoAytyjAwMABQADSnDiE0cAKoDUUeXGEHDcYMwBccPqxDFLAGjuG+AQxBUFyENPgBzO2k7Y3QAYRwgvngFW3sHZ1d3TygfdJhUMhgQmDDwvPt-VhgAC2gXc0somKJxSRSbXwyXNw9vLphgGE4SsorDUmYkUeAI8bgq2vqzC1yu3hAkmAEXBM3UZIBtAF1m3QBKajo4ACVUDE5uQf5KCSElMGw0WGBUASVHK92h8vpZBn8lINhlw3jAQRBvuD-os6lB4Yjfv9AbD0WDMUoUdBcT8IQEgkD3p8EXiIRstliCiB-lSMRCCkUKXCWTT-nSDtsAYzmaCScjqqjiUiAcxOZL8XzkgzUEy5RDCWjuaKlGSuLR6ABJPgYSwHbhcDCsPhPYD8OCfP787SQIQuZBoVQwfyDbgAHliEAwbSEAD5zp1DM64YCI8CoZw7JGCeKidG7cD1drAlwY+8FdtDgAGY6QwowBPAvMCQvFjOpxOV6tJpZonWUaRAA) | [Example 2](https://www.typescriptlang.org/play/?target=99&module=7#code/JYWwDg9gTgLgBAFQJ5gKZwGZQiOByGFVAIwgA88AoSgehrgFkIATAVwBtVKBjCAOwDO8AKoDUUOAF5ERAHQB5YgCtU3GAAoA3pThxgzAFwy0sgHKsQxceoCUAGh1w+AQxCojyEwGUYUYHwBzW0oAXxsefiE4AGEcNz54aU9UBWVVDW1dfQ85c0tre0cYVDIYHO9ffyDC3WdWGAALaCNRcVDw3kF4AAUIKKS5RRU1LUds4xS8qyhbB10YYBhOcpSfP0DZx1JmJBXZNarN2vqmqBaxKDm4XhB4mAE9gEEoKGckdVjb1ATwsOo6OAAJVQGE4amA-EovSEsjA2DQsGAqAEsn0UL6MFh8PEC2RsgWSy40MxcIgCNxKLqjWgWLJOKRKLRxNp5IZsippxZ9LxLjc6JhpNZeJud0ZxRAKMF3JRxVK-JJ2MRwri33uqPFksVFPZJxpUqVjOY8q5BtkItVYtQEpN2o5eq1bN5XFo9AAknwMOJvtwuBhWHxwfw4HDkar1JAhHsfM4FtwADyENAQDBwYkAPhscEywYxqKNugjmIJnEchZ11KgedLubtlad1Zh5oSAgA2gAGAC6+JKMAbmKb93bXdrVYLuYHrc75c59ZCQA) | [Challenge](test/typescript/readme.md)
|
|
115
115
|
|
|
116
|
-
TypeBox includes a runtime
|
|
116
|
+
TypeBox includes a runtime TypeScript engine that can transform TypeScript definitions to JSON Schema. The engine is fully type-safe and supports many programmable constructs including Conditional, Mapped, Indexed, Generics, Distributive Generics, and more.
|
|
117
117
|
|
|
118
118
|
### Example
|
|
119
119
|
|
|
@@ -121,50 +121,43 @@ Syntax highlighting is available via the [Visual Studio Marketplace](https://mar
|
|
|
121
121
|
|
|
122
122
|
```typescript
|
|
123
123
|
// Module
|
|
124
|
-
const
|
|
125
|
-
type
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
`)
|
|
129
|
-
|
|
130
|
-
// Dependent Module
|
|
131
|
-
const { Mesh } = Type.Script(Math, `
|
|
132
|
-
type Vertex = {
|
|
133
|
-
position: Vector4,
|
|
134
|
-
normal: Vector3,
|
|
135
|
-
uv: Vector2
|
|
136
|
-
}
|
|
137
|
-
type Geometry = {
|
|
138
|
-
vertices: Vertex[],
|
|
139
|
-
indices: number[]
|
|
124
|
+
const { Post } = Type.Script(`
|
|
125
|
+
type User = {
|
|
126
|
+
id: number,
|
|
127
|
+
name: string
|
|
140
128
|
}
|
|
141
|
-
type
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
129
|
+
type Comment = {
|
|
130
|
+
id: number,
|
|
131
|
+
text: string,
|
|
132
|
+
author: User
|
|
145
133
|
}
|
|
146
|
-
type
|
|
147
|
-
|
|
148
|
-
|
|
134
|
+
type Post = {
|
|
135
|
+
id: number,
|
|
136
|
+
title: string,
|
|
137
|
+
body: string,
|
|
138
|
+
author: User,
|
|
139
|
+
comments: Comment[]
|
|
149
140
|
}
|
|
150
141
|
`)
|
|
151
142
|
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
143
|
+
// Reflection
|
|
144
|
+
Post.properties.id
|
|
145
|
+
Post.properties.title
|
|
146
|
+
Post.properties.author.properties.id
|
|
147
|
+
Post.properties.author.properties.name
|
|
148
|
+
Post.properties.comments.items.properties.text
|
|
149
|
+
Post.properties.comments.items.properties.author.properties.id
|
|
150
|
+
Post.properties.comments.items.properties.author.properties.name
|
|
151
|
+
|
|
152
|
+
// Inference
|
|
153
|
+
function present(post: Type.Static<typeof Post>) {
|
|
154
|
+
post.id
|
|
155
|
+
post.title
|
|
156
|
+
post.author.id
|
|
157
|
+
post.author.name
|
|
158
|
+
post.comments[0].text
|
|
159
|
+
post.comments[0].author.id
|
|
160
|
+
post.comments[0].author.name
|
|
168
161
|
}
|
|
169
162
|
```
|
|
170
163
|
|
|
@@ -236,7 +229,7 @@ const value = Vector.Parse({ // const value: {
|
|
|
236
229
|
|
|
237
230
|
The following table shows specification coverage implemented by TypeBox.
|
|
238
231
|
|
|
239
|
-
|
|
232
|
+
[JSON Schema Test Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite)
|
|
240
233
|
|
|
241
234
|
| Spec | 3 | 4 | 6 | 7 | 2019-09 | 2020-12 | v1 |
|
|
242
235
|
|:-----|:--|:--|:--|:--|:--|:--|:--|
|
|
@@ -279,11 +272,11 @@ Ref: [JSON Schema Test Suite](https://github.com/json-schema-org/JSON-Schema-Tes
|
|
|
279
272
|
| properties | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
280
273
|
| propertyNames | - | - | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
281
274
|
| recursiveRef | - | - | - | - | ✅ | - | - |
|
|
282
|
-
| ref |
|
|
275
|
+
| ref | 22/27 | 37/45 | 67/70 | 75/78 | 79/81 | 77/79 | 77/79 |
|
|
283
276
|
| required | 3/4 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
284
277
|
| type | 73/80 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
285
|
-
| unevaluatedItems | - | - | - | - | ✅ |
|
|
286
|
-
| unevaluatedProperties | - | - | - | - | ✅ | ✅ |
|
|
278
|
+
| unevaluatedItems | - | - | - | - | ✅ | ✅ | 70/71 |
|
|
279
|
+
| unevaluatedProperties | - | - | - | - | ✅ | ✅ | 128/129 |
|
|
287
280
|
| uniqueItems | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
288
281
|
|
|
289
282
|
|