typebox 1.2.14 → 1.2.16
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/system/settings/settings.d.mts +15 -0
- package/build/system/settings/settings.mjs +3 -1
- package/build/type/engine/evaluate/broaden.d.mts +1 -2
- package/build/type/engine/evaluate/broaden.mjs +2 -6
- package/build/type/engine/evaluate/evaluate.d.mts +2 -2
- package/build/type/engine/evaluate/evaluate.mjs +4 -2
- package/build/type/engine/index.d.mts +1 -0
- package/build/type/engine/index.mjs +1 -0
- package/build/type/engine/priority/index.d.mts +1 -0
- package/build/type/engine/priority/index.mjs +1 -0
- package/build/type/engine/priority/priority.d.mts +20 -0
- package/build/type/engine/priority/priority.mjs +28 -0
- package/build/type/types/record.d.mts +1 -1
- package/build/type/types/record.mjs +3 -3
- package/build/value/clean/clean.mjs +4 -2
- package/build/value/clean/from_union.d.mts +1 -1
- package/build/value/clean/from_union.mjs +1 -2
- package/build/value/codec/decode.mjs +4 -2
- package/build/value/codec/encode.mjs +4 -2
- package/build/value/codec/from_array.mjs +1 -4
- package/build/value/codec/from_object.mjs +1 -4
- package/build/value/codec/from_record.mjs +2 -7
- package/build/value/codec/from_tuple.mjs +1 -4
- package/build/value/codec/from_union.mjs +2 -3
- package/build/value/shared/union_priority_sort.d.mts +6 -2
- package/build/value/shared/union_priority_sort.mjs +62 -26
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@ export interface TSettings {
|
|
|
3
3
|
* Determines whether types should be instantiated as immutable using `Object.freeze(...)`.
|
|
4
4
|
* This helps prevent unintended schema mutation. Enabling this option introduces a slight
|
|
5
5
|
* performance overhead during instantiation.
|
|
6
|
+
*
|
|
6
7
|
* @default false
|
|
7
8
|
*/
|
|
8
9
|
immutableTypes: boolean;
|
|
@@ -11,6 +12,7 @@ export interface TSettings {
|
|
|
11
12
|
* performs exhaustive checks to gather diagnostics for invalid values, which can result in
|
|
12
13
|
* excessive buffering for large or complex types. This setting limits the number of buffered
|
|
13
14
|
* errors and acts as a safeguard against potential denial-of-service (DoS) attacks.
|
|
15
|
+
*
|
|
14
16
|
* @default 8
|
|
15
17
|
*/
|
|
16
18
|
maxErrors: number;
|
|
@@ -20,6 +22,7 @@ export interface TSettings {
|
|
|
20
22
|
* generated code. If evaluation is not permitted, it falls back to dynamic checking. Setting
|
|
21
23
|
* this to `false` disables evaluation entirely, which may be desirable in applications that
|
|
22
24
|
* restrict runtime code evaluation, regardless of Content Security Policy (CSP).
|
|
25
|
+
*
|
|
23
26
|
* @default true
|
|
24
27
|
*/
|
|
25
28
|
useAcceleration: boolean;
|
|
@@ -30,11 +33,13 @@ export interface TSettings {
|
|
|
30
33
|
* TypeScript semantics to remain consistent with the language. This option is provided to align
|
|
31
34
|
* runtime check semantics with projects that configure 'exactOptionalPropertyTypes: true' in
|
|
32
35
|
* tsconfig.json.
|
|
36
|
+
*
|
|
33
37
|
* @default false
|
|
34
38
|
*/
|
|
35
39
|
exactOptionalPropertyTypes: boolean;
|
|
36
40
|
/**
|
|
37
41
|
* Controls whether internal compositor properties (`~kind`, `~readonly`, `~optional`) are enumerable.
|
|
42
|
+
*
|
|
38
43
|
* @default false
|
|
39
44
|
*/
|
|
40
45
|
enumerableKind: boolean;
|
|
@@ -44,9 +49,19 @@ export interface TSettings {
|
|
|
44
49
|
* the value, followed by a subsequent `Assert`. Enabling this option may incur significant performance
|
|
45
50
|
* overhead for invalid values. It is recommended to keep this disabled in performance-sensitive
|
|
46
51
|
* applications.
|
|
52
|
+
*
|
|
47
53
|
* @default false
|
|
48
54
|
*/
|
|
49
55
|
correctiveParse: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Controls whether TypeBox sorts Union variants by specificity (narrowest first) for operations
|
|
58
|
+
* that require deterministic value matching, such as Clean, Decode, and Encode. When enabled,
|
|
59
|
+
* more specific types (e.g. Literal) always take precedence over broader types (e.g. String),
|
|
60
|
+
* regardless of the order variants are declared.
|
|
61
|
+
*
|
|
62
|
+
* @default true
|
|
63
|
+
*/
|
|
64
|
+
unionPrioritySort: boolean;
|
|
50
65
|
}
|
|
51
66
|
/** Resets system settings to defaults */
|
|
52
67
|
export declare function Reset(): void;
|
|
@@ -6,7 +6,8 @@ const settings = {
|
|
|
6
6
|
useAcceleration: true,
|
|
7
7
|
exactOptionalPropertyTypes: false,
|
|
8
8
|
enumerableKind: false,
|
|
9
|
-
correctiveParse: false
|
|
9
|
+
correctiveParse: false,
|
|
10
|
+
unionPrioritySort: true
|
|
10
11
|
};
|
|
11
12
|
/** Resets system settings to defaults */
|
|
12
13
|
export function Reset() {
|
|
@@ -16,6 +17,7 @@ export function Reset() {
|
|
|
16
17
|
settings.exactOptionalPropertyTypes = false;
|
|
17
18
|
settings.enumerableKind = false;
|
|
18
19
|
settings.correctiveParse = false;
|
|
20
|
+
settings.unionPrioritySort = true;
|
|
19
21
|
}
|
|
20
22
|
/** Sets system settings */
|
|
21
23
|
export function Set(options) {
|
|
@@ -2,7 +2,6 @@ import { type TSchema } from '../../types/schema.mjs';
|
|
|
2
2
|
import { type TAny } from '../../types/any.mjs';
|
|
3
3
|
import { type TNever } from '../../types/never.mjs';
|
|
4
4
|
import { type TObject } from '../../types/object.mjs';
|
|
5
|
-
import { type TUnion } from '../../types/union.mjs';
|
|
6
5
|
import { type TCompare, ResultRightInside, ResultLeftInside, ResultEqual } from './compare.mjs';
|
|
7
6
|
import { type TFlatten } from './flatten.mjs';
|
|
8
7
|
import { type TEvaluateType } from './evaluate.mjs';
|
|
@@ -10,7 +9,7 @@ type TBroadFilter<Type extends TSchema, Types extends TSchema[], Result extends
|
|
|
10
9
|
type TIsBroadestType<Type extends TSchema, Types extends TSchema[]> = (Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TCompare<Type, Left> extends typeof ResultLeftInside | typeof ResultEqual ? false : TIsBroadestType<Type, Right> : true);
|
|
11
10
|
type TBroadenType<Type extends TSchema, Types extends TSchema[], Evaluated extends TSchema = TEvaluateType<Type>, Result extends TSchema[] = (Evaluated extends TAny ? [Evaluated] : TIsBroadestType<Evaluated, Types> extends true ? [...TBroadFilter<Evaluated, Types>, Evaluated] : Types)> = Result;
|
|
12
11
|
type TBroadenTypes<Types extends TSchema[], Result extends TSchema[] = []> = (Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? (Left extends TObject ? TBroadenTypes<Right, [...Result, Left]> : Left extends TNever ? TBroadenTypes<Right, Result> : TBroadenTypes<Right, TBroadenType<Left, Result>>) : Result);
|
|
13
|
-
export type TBroaden<Types extends TSchema[], Broadened extends TSchema[] = TBroadenTypes<Types>, Flattened extends TSchema[] = TFlatten<Broadened
|
|
12
|
+
export type TBroaden<Types extends TSchema[], Broadened extends TSchema[] = TBroadenTypes<Types>, Flattened extends TSchema[] = TFlatten<Broadened>> = Flattened;
|
|
14
13
|
/** Broadens a set of types and returns either the most broad type, or union or disjoint types. */
|
|
15
14
|
export declare function Broaden<Types extends TSchema[]>(types: [...Types]): TBroaden<Types>;
|
|
16
15
|
export {};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
// deno-fmt-ignore-file
|
|
2
2
|
import { Guard } from '../../../guard/index.mjs';
|
|
3
3
|
import { IsAny } from '../../types/any.mjs';
|
|
4
|
-
import {
|
|
4
|
+
import { IsNever } from '../../types/never.mjs';
|
|
5
5
|
import { IsObject } from '../../types/object.mjs';
|
|
6
|
-
import { Union } from '../../types/union.mjs';
|
|
7
6
|
import { Compare, ResultRightInside, ResultLeftInside, ResultEqual } from './compare.mjs';
|
|
8
7
|
import { Flatten } from './flatten.mjs';
|
|
9
8
|
import { EvaluateType } from './evaluate.mjs';
|
|
@@ -40,8 +39,5 @@ function BroadenTypes(types) {
|
|
|
40
39
|
export function Broaden(types) {
|
|
41
40
|
const broadened = BroadenTypes(types);
|
|
42
41
|
const flattened = Flatten(broadened);
|
|
43
|
-
|
|
44
|
-
flattened.length === 1 ? flattened[0] :
|
|
45
|
-
Union(flattened));
|
|
46
|
-
return result;
|
|
42
|
+
return flattened;
|
|
47
43
|
}
|
|
@@ -14,11 +14,11 @@ export type TEvaluateDependent<If extends TSchema, Then extends TSchema, Else ex
|
|
|
14
14
|
export declare function EvaluateDependent<If extends TSchema, Then extends TSchema, Else extends TSchema>(if_: If, then_: Then, else_: Else): TEvaluateDependent<If, Then, Else>;
|
|
15
15
|
export type TEvaluateEnum<Values extends TEnumValue[], Result extends TSchema[] = []> = (Values extends [infer Left extends TEnumValue, ...infer Right extends TEnumValue[]] ? TEvaluateEnum<Right, [...Result, TLiteral<Left>]> : TEvaluateUnion<Result>);
|
|
16
16
|
export declare function EvaluateEnum<Values extends TEnumValue[]>(values: [...Values]): TEvaluateEnum<Values>;
|
|
17
|
-
export type TEvaluateIntersect<Types extends TSchema[], Distribution extends TSchema[] = TDistribute<Types>,
|
|
17
|
+
export type TEvaluateIntersect<Types extends TSchema[], Distribution extends TSchema[] = TDistribute<Types>, Broadend extends TSchema[] = TBroaden<Distribution>, Result extends TSchema = TEvaluateUnionFast<Broadend>> = Result;
|
|
18
18
|
export declare function EvaluateIntersect<Types extends TSchema[]>(types: [...Types]): TEvaluateIntersect<Types>;
|
|
19
19
|
export type TEvaluateTemplateLiteral<Pattern extends string, Evaluated extends TSchema = TTemplateLiteralDecode<Pattern>, Result extends TSchema = TEvaluateType<Evaluated>> = Result;
|
|
20
20
|
export declare function EvaluateTemplateLiteral<Pattern extends string>(pattern: Pattern): TEvaluateTemplateLiteral<Pattern>;
|
|
21
|
-
export type TEvaluateUnion<Types extends TSchema[],
|
|
21
|
+
export type TEvaluateUnion<Types extends TSchema[], Broadend extends TSchema[] = TBroaden<Types>, Result extends TSchema = TEvaluateUnionFast<Broadend>> = Result;
|
|
22
22
|
export declare function EvaluateUnion<Types extends TSchema[]>(types: [...Types]): TEvaluateUnion<Types>;
|
|
23
23
|
export type TEvaluateType<Type extends TSchema, Result extends TSchema = (Type extends TDependent<infer If extends TSchema, infer Then extends TSchema, infer Else extends TSchema> ? TEvaluateDependent<If, Then, Else> : Type extends TEnum<infer Values extends TEnumValue[]> ? TEvaluateEnum<Values> : Type extends TIntersect<infer Types extends TSchema[]> ? TEvaluateIntersect<Types> : Type extends TTemplateLiteral<infer Pattern extends string> ? TEvaluateTemplateLiteral<Pattern> : Type extends TUnion<infer Types extends TSchema[]> ? TEvaluateUnion<Types> : Type)> = Result;
|
|
24
24
|
export declare function EvaluateType<Type extends TSchema>(type: Type): TEvaluateType<Type>;
|
|
@@ -23,7 +23,8 @@ export function EvaluateEnum(values) {
|
|
|
23
23
|
}
|
|
24
24
|
export function EvaluateIntersect(types) {
|
|
25
25
|
const distribution = Distribute(types);
|
|
26
|
-
const
|
|
26
|
+
const broadend = Broaden(distribution);
|
|
27
|
+
const result = EvaluateUnionFast(broadend);
|
|
27
28
|
return result;
|
|
28
29
|
}
|
|
29
30
|
export function EvaluateTemplateLiteral(pattern) {
|
|
@@ -32,7 +33,8 @@ export function EvaluateTemplateLiteral(pattern) {
|
|
|
32
33
|
return result;
|
|
33
34
|
}
|
|
34
35
|
export function EvaluateUnion(types) {
|
|
35
|
-
const
|
|
36
|
+
const broadend = Broaden(types);
|
|
37
|
+
const result = EvaluateUnionFast(broadend);
|
|
36
38
|
return result;
|
|
37
39
|
}
|
|
38
40
|
export function EvaluateType(type) {
|
|
@@ -22,6 +22,7 @@ export * from './parameters/index.mjs';
|
|
|
22
22
|
export * from './patterns/index.mjs';
|
|
23
23
|
export * from './partial/index.mjs';
|
|
24
24
|
export * from './pick/index.mjs';
|
|
25
|
+
export * from './priority/index.mjs';
|
|
25
26
|
export * from './readonly_object/index.mjs';
|
|
26
27
|
export * from './record/index.mjs';
|
|
27
28
|
export * from './ref/index.mjs';
|
|
@@ -28,6 +28,7 @@ export * from './parameters/index.mjs';
|
|
|
28
28
|
export * from './patterns/index.mjs';
|
|
29
29
|
export * from './partial/index.mjs';
|
|
30
30
|
export * from './pick/index.mjs';
|
|
31
|
+
export * from './priority/index.mjs';
|
|
31
32
|
export * from './readonly_object/index.mjs';
|
|
32
33
|
export * from './record/index.mjs';
|
|
33
34
|
export * from './ref/index.mjs';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './priority.mjs';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './priority.mjs';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type TSchema } from '../../types/schema.mjs';
|
|
2
|
+
import { type TCompare, type TCompareResult } from '../evaluate/compare.mjs';
|
|
3
|
+
type TComparer<Left extends TSchema, Right extends TSchema, CompareResult extends TCompareResult = TCompare<Left, Right>, Result extends 0 | 1 = (CompareResult extends 'right-inside' ? 1 : CompareResult extends 'disjoint' ? 1 : 0)> = Result;
|
|
4
|
+
type TInsert<Type extends TSchema, Types extends TSchema[], Result extends TSchema[] = []> = (Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TComparer<Type, Left> extends 1 ? TInsert<Type, Right, [...Result, Left]> : [...Result, Type, ...Types] : [...Result, Type]);
|
|
5
|
+
type TSort<Types extends TSchema[], Result extends TSchema[] = []> = (Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TSort<Right, TInsert<Left, Result>> : Result);
|
|
6
|
+
/**
|
|
7
|
+
* Priority sorts types in sequence of narrowest to broadest using a Drop Sort algorithm.
|
|
8
|
+
* This function is typically used to sequence types for union variant checks to ensure
|
|
9
|
+
* that values are checked against the most narrow types before the broadest, which in
|
|
10
|
+
* turn helps ensure order-independent checking.
|
|
11
|
+
*/
|
|
12
|
+
export type TPriority<Types extends TSchema[], Result extends TSchema[] = TSort<Types>> = Result;
|
|
13
|
+
/**
|
|
14
|
+
* Priority sorts types in sequence of narrowest to broadest using a Drop Sort algorithm.
|
|
15
|
+
* This function is typically used to sequence types for union variant checks to ensure
|
|
16
|
+
* that values are checked against the most narrow types before the broadest, which in
|
|
17
|
+
* turn helps ensure order-independent checking.
|
|
18
|
+
*/
|
|
19
|
+
export declare function Priority<Types extends TSchema[]>(types: [...Types]): TPriority<Types>;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// deno-fmt-ignore-file
|
|
2
|
+
import { Guard } from '../../../guard/index.mjs';
|
|
3
|
+
import { Compare } from '../evaluate/compare.mjs';
|
|
4
|
+
function Comparer(left, right) {
|
|
5
|
+
const compareResult = Compare(left, right);
|
|
6
|
+
const result = (Guard.IsEqual(compareResult, 'right-inside') ? 1 :
|
|
7
|
+
Guard.IsEqual(compareResult, 'disjoint') ? 1 :
|
|
8
|
+
0);
|
|
9
|
+
return result;
|
|
10
|
+
}
|
|
11
|
+
function Insert(type, types, result = []) {
|
|
12
|
+
return Guard.ShiftLeft(types, (left, right) => Guard.IsEqual(Comparer(type, left), 1)
|
|
13
|
+
? Insert(type, right, [...result, left])
|
|
14
|
+
: [...result, type, ...types], () => [...result, type]);
|
|
15
|
+
}
|
|
16
|
+
function Sort(types, result = []) {
|
|
17
|
+
return Guard.ShiftLeft(types, (left, right) => Sort(right, Insert(left, result)), () => result);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Priority sorts types in sequence of narrowest to broadest using a Drop Sort algorithm.
|
|
21
|
+
* This function is typically used to sequence types for union variant checks to ensure
|
|
22
|
+
* that values are checked against the most narrow types before the broadest, which in
|
|
23
|
+
* turn helps ensure order-independent checking.
|
|
24
|
+
*/
|
|
25
|
+
export function Priority(types) {
|
|
26
|
+
const result = Sort(types);
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
@@ -30,7 +30,7 @@ export declare function RecordDeferred<Key extends TSchema, Value extends TSchem
|
|
|
30
30
|
/** Creates a Record type. */
|
|
31
31
|
export declare function Record<Key extends TSchema, Value extends TSchema>(key: Key, value: Value, options?: TObjectOptions): TRecordAction<Key, Value>;
|
|
32
32
|
/** Creates a Record type from regular expression pattern. */
|
|
33
|
-
export declare function RecordFromPattern<Pattern extends string, Value extends TSchema>(
|
|
33
|
+
export declare function RecordFromPattern<Pattern extends string, Value extends TSchema>(pattern: Pattern, value: Value): TRecord<Pattern, Value>;
|
|
34
34
|
/** Transforms a Record Pattern to a Type */
|
|
35
35
|
export type TRecordPatternToType<Pattern extends string, Result extends TSchema = (Pattern extends typeof StringKey ? TString : Pattern extends typeof IntegerKey ? TInteger : Pattern extends typeof NumberKey ? TNumber : TTemplateLiteralDecodeUnsafe<Pattern>)> = Result;
|
|
36
36
|
/** Transforms a Record Pattern to a Type */
|
|
@@ -24,11 +24,11 @@ export function Record(key, value, options = {}) {
|
|
|
24
24
|
return RecordAction(key, value, options);
|
|
25
25
|
}
|
|
26
26
|
// -------------------------------------------------------------------
|
|
27
|
-
//
|
|
27
|
+
// RecordFromPattern
|
|
28
28
|
// -------------------------------------------------------------------
|
|
29
29
|
/** Creates a Record type from regular expression pattern. */
|
|
30
|
-
export function RecordFromPattern(
|
|
31
|
-
return CreateRecord(
|
|
30
|
+
export function RecordFromPattern(pattern, value) {
|
|
31
|
+
return CreateRecord(pattern, value);
|
|
32
32
|
}
|
|
33
33
|
/** Transforms a Record Pattern to a Type */
|
|
34
34
|
export function RecordPatternToType(pattern) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Arguments } from '../../system/
|
|
1
|
+
import { Arguments, Settings } from '../../system/index.mjs';
|
|
2
2
|
import { FromType } from './from_type.mjs';
|
|
3
|
+
import { UnionPrioritySort } from '../shared/union_priority_sort.mjs';
|
|
3
4
|
/**
|
|
4
5
|
* Cleans a value by removing non-evaluated properties and elements as derived from the provided type.
|
|
5
6
|
* This function returns unknown so callers should Check the return value before use. This function
|
|
@@ -11,5 +12,6 @@ export function Clean(...args) {
|
|
|
11
12
|
3: (context, type, value) => [context, type, value],
|
|
12
13
|
2: (type, value) => [{}, type, value]
|
|
13
14
|
});
|
|
14
|
-
|
|
15
|
+
const sorted = Settings.Get().unionPrioritySort ? UnionPrioritySort(type) : type;
|
|
16
|
+
return FromType(context, sorted, value);
|
|
15
17
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type TProperties, type TUnion } from '../../type/index.mjs';
|
|
2
2
|
export declare function FromUnion(context: TProperties, type: TUnion, value: unknown): unknown;
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
import { Check } from '../check/index.mjs';
|
|
3
3
|
import { Clone } from '../clone/index.mjs';
|
|
4
4
|
import { FromType } from './from_type.mjs';
|
|
5
|
-
import { UnionPrioritySort } from '../shared/union_priority_sort.mjs';
|
|
6
5
|
export function FromUnion(context, type, value) {
|
|
7
|
-
for (const schema of
|
|
6
|
+
for (const schema of type.anyOf) {
|
|
8
7
|
const clean = FromType(context, schema, Clone(value));
|
|
9
8
|
if (Check(context, schema, clean))
|
|
10
9
|
return clean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// deno-fmt-ignore-file
|
|
2
|
-
import { Arguments } from '../../system/
|
|
2
|
+
import { Arguments, Settings } from '../../system/index.mjs';
|
|
3
3
|
import { AssertError } from '../assert/index.mjs';
|
|
4
4
|
import { Check } from '../check/index.mjs';
|
|
5
5
|
import { Errors } from '../errors/index.mjs';
|
|
@@ -9,6 +9,7 @@ import { Convert } from '../convert/index.mjs';
|
|
|
9
9
|
import { Default } from '../default/index.mjs';
|
|
10
10
|
import { Pipeline } from '../pipeline/index.mjs';
|
|
11
11
|
import { FromType } from './from_type.mjs';
|
|
12
|
+
import { UnionPrioritySort } from '../shared/union_priority_sort.mjs';
|
|
12
13
|
// ------------------------------------------------------------------
|
|
13
14
|
// Assert
|
|
14
15
|
// ------------------------------------------------------------------
|
|
@@ -27,7 +28,8 @@ function Assert(context, type, value) {
|
|
|
27
28
|
// ------------------------------------------------------------------
|
|
28
29
|
/** Executes Decode callbacks only */
|
|
29
30
|
export function DecodeUnsafe(context, type, value) {
|
|
30
|
-
|
|
31
|
+
const sorted = Settings.Get().unionPrioritySort ? UnionPrioritySort(type) : type;
|
|
32
|
+
return FromType('Decode', context, sorted, value);
|
|
31
33
|
}
|
|
32
34
|
// ------------------------------------------------------------------
|
|
33
35
|
// Decoder
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// deno-fmt-ignore-file
|
|
2
|
-
import { Arguments } from '../../system/
|
|
2
|
+
import { Arguments, Settings } from '../../system/index.mjs';
|
|
3
3
|
import { AssertError } from '../assert/index.mjs';
|
|
4
4
|
import { Check } from '../check/index.mjs';
|
|
5
5
|
import { Errors } from '../errors/index.mjs';
|
|
@@ -9,6 +9,7 @@ import { Convert } from '../convert/index.mjs';
|
|
|
9
9
|
import { Default } from '../default/index.mjs';
|
|
10
10
|
import { Pipeline } from '../pipeline/index.mjs';
|
|
11
11
|
import { FromType } from './from_type.mjs';
|
|
12
|
+
import { UnionPrioritySort } from '../shared/union_priority_sort.mjs';
|
|
12
13
|
// ------------------------------------------------------------------
|
|
13
14
|
// Assert
|
|
14
15
|
// ------------------------------------------------------------------
|
|
@@ -27,7 +28,8 @@ function Assert(context, type, value) {
|
|
|
27
28
|
// ------------------------------------------------------------------
|
|
28
29
|
/** Executes Encode callbacks only */
|
|
29
30
|
export function EncodeUnsafe(context, type, value) {
|
|
30
|
-
|
|
31
|
+
const sorted = Settings.Get().unionPrioritySort ? UnionPrioritySort(type) : type;
|
|
32
|
+
return FromType('Encode', context, sorted, value);
|
|
31
33
|
}
|
|
32
34
|
// ------------------------------------------------------------------
|
|
33
35
|
// Encoder
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// deno-fmt-ignore-file
|
|
2
|
-
import { Unreachable } from '../../system/unreachable/index.mjs';
|
|
3
2
|
import { Guard } from '../../guard/index.mjs';
|
|
4
3
|
import { FromType } from './from_type.mjs';
|
|
5
4
|
import { Callback } from './callback.mjs';
|
|
@@ -7,10 +6,8 @@ import { Callback } from './callback.mjs';
|
|
|
7
6
|
// Decode
|
|
8
7
|
// ------------------------------------------------------------------
|
|
9
8
|
function Decode(direction, context, type, value) {
|
|
10
|
-
// deno-coverage-ignore-start - unreachable | checked
|
|
11
9
|
if (!Guard.IsArray(value))
|
|
12
|
-
return
|
|
13
|
-
// deno-coverage-ignore-stop
|
|
10
|
+
return value;
|
|
14
11
|
for (let i = 0; i < value.length; i++) {
|
|
15
12
|
value[i] = FromType(direction, context, type.items, value[i]);
|
|
16
13
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// deno-fmt-ignore-file
|
|
2
|
-
import { Unreachable } from '../../system/unreachable/index.mjs';
|
|
3
2
|
import { Guard } from '../../guard/index.mjs';
|
|
4
3
|
import { FromType } from './from_type.mjs';
|
|
5
4
|
import { Callback } from './callback.mjs';
|
|
@@ -8,10 +7,8 @@ import { IsOptionalUndefined } from '../shared/optional_undefined.mjs';
|
|
|
8
7
|
// Decode
|
|
9
8
|
// ------------------------------------------------------------------
|
|
10
9
|
function Decode(direction, context, type, value) {
|
|
11
|
-
// deno-coverage-ignore-start - unreachable | checked
|
|
12
10
|
if (!Guard.IsObjectNotArray(value))
|
|
13
|
-
return
|
|
14
|
-
// deno-coverage-ignore-stop
|
|
11
|
+
return value;
|
|
15
12
|
for (const key of Guard.Keys(type.properties)) {
|
|
16
13
|
// Ignore for non-present or optional-undefined
|
|
17
14
|
if (!Guard.HasPropertyKey(value, key) || IsOptionalUndefined(type.properties[key], key, value))
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// deno-fmt-ignore-file
|
|
2
|
-
import { Unreachable } from '../../system/unreachable/index.mjs';
|
|
3
2
|
import { Guard } from '../../guard/index.mjs';
|
|
4
3
|
import { RecordPattern, RecordValue } from '../../type/index.mjs';
|
|
5
4
|
import { FromType } from './from_type.mjs';
|
|
@@ -8,16 +7,12 @@ import { Callback } from './callback.mjs';
|
|
|
8
7
|
// Decode
|
|
9
8
|
// ------------------------------------------------------------------
|
|
10
9
|
function Decode(direction, context, type, value) {
|
|
11
|
-
// deno-coverage-ignore-start - unreachable | checked
|
|
12
10
|
if (!Guard.IsObjectNotArray(value))
|
|
13
|
-
return
|
|
14
|
-
// deno-coverage-ignore-stop
|
|
11
|
+
return value;
|
|
15
12
|
const regexp = new RegExp(RecordPattern(type));
|
|
16
13
|
for (const key of Guard.Keys(value)) {
|
|
17
|
-
// deno-coverage-ignore-start - unreachable | checked
|
|
18
14
|
if (!regexp.test(key))
|
|
19
|
-
|
|
20
|
-
// deno-coverage-ignore-stop
|
|
15
|
+
continue;
|
|
21
16
|
value[key] = FromType(direction, context, RecordValue(type), value[key]);
|
|
22
17
|
}
|
|
23
18
|
return Callback(direction, context, type, value);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// deno-fmt-ignore-file
|
|
2
|
-
import { Unreachable } from '../../system/unreachable/index.mjs';
|
|
3
2
|
import { Guard } from '../../guard/index.mjs';
|
|
4
3
|
import { FromType } from './from_type.mjs';
|
|
5
4
|
import { Callback } from './callback.mjs';
|
|
@@ -7,10 +6,8 @@ import { Callback } from './callback.mjs';
|
|
|
7
6
|
// Decode
|
|
8
7
|
// ------------------------------------------------------------------
|
|
9
8
|
function Decode(direction, context, type, value) {
|
|
10
|
-
// deno-coverage-ignore-start - unreachable | checked
|
|
11
9
|
if (!Guard.IsArray(value))
|
|
12
|
-
return
|
|
13
|
-
// deno-coverage-ignore-stop
|
|
10
|
+
return value;
|
|
14
11
|
for (let i = 0; i < Math.min(type.items.length, value.length); i++) {
|
|
15
12
|
value[i] = FromType(direction, context, type.items[i], value[i]);
|
|
16
13
|
}
|
|
@@ -4,12 +4,11 @@ import { Callback } from './callback.mjs';
|
|
|
4
4
|
import { FromType } from './from_type.mjs';
|
|
5
5
|
import { Clone } from '../clone/index.mjs';
|
|
6
6
|
import { Check } from '../check/index.mjs';
|
|
7
|
-
import { UnionPrioritySort } from '../shared/union_priority_sort.mjs';
|
|
8
7
|
// ------------------------------------------------------------------
|
|
9
8
|
// Decode
|
|
10
9
|
// ------------------------------------------------------------------
|
|
11
10
|
function Decode(direction, context, type, value) {
|
|
12
|
-
for (const schema of
|
|
11
|
+
for (const schema of type.anyOf) {
|
|
13
12
|
if (!Check(context, schema, value))
|
|
14
13
|
continue;
|
|
15
14
|
const variant = FromType(direction, context, schema, value);
|
|
@@ -22,7 +21,7 @@ function Decode(direction, context, type, value) {
|
|
|
22
21
|
// ------------------------------------------------------------------
|
|
23
22
|
function Encode(direction, context, type, value) {
|
|
24
23
|
const exterior = Callback(direction, context, type, value);
|
|
25
|
-
for (const schema of
|
|
24
|
+
for (const schema of type.anyOf) {
|
|
26
25
|
const variant = FromType(direction, context, schema, Clone(exterior));
|
|
27
26
|
if (!Check(context, schema, variant))
|
|
28
27
|
continue;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import { type TSchema } from '../../type/index.mjs';
|
|
2
|
-
/**
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* (Type-Preprocessor) Recursively reorders Union variants from narrowest to broadest, ensuring
|
|
4
|
+
* more specific types (e.g. Literal) are evaluated before broader types (e.g. String). Used
|
|
5
|
+
* prior to Clean, Decode, and Encode operations.
|
|
6
|
+
*/
|
|
7
|
+
export declare function UnionPrioritySort(type: TSchema): TSchema;
|
|
@@ -1,36 +1,72 @@
|
|
|
1
1
|
// deno-fmt-ignore-file
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import Guard from '../../guard/index.mjs';
|
|
3
|
+
import { IsArray, Array as _Array_, ArrayOptions } from '../../type/index.mjs';
|
|
4
|
+
import { IsUnion, Union } from '../../type/index.mjs';
|
|
5
|
+
import { IsObject, Object as _Object_ } from '../../type/index.mjs';
|
|
6
|
+
import { IsRecord, Record, RecordKey, RecordValue } from '../../type/index.mjs';
|
|
7
|
+
import { IsTuple, Tuple } from '../../type/index.mjs';
|
|
8
|
+
import { IsIntersect, Intersect } from '../../type/index.mjs';
|
|
9
|
+
import { Priority } from '../../type/index.mjs';
|
|
4
10
|
// ------------------------------------------------------------------
|
|
5
|
-
//
|
|
11
|
+
// Modifiers (Mutable)
|
|
6
12
|
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// alphabetical alignment of named constants.
|
|
13
|
+
// Prioritized types lose `~modifier` properties and additional constraints
|
|
14
|
+
// (e.g. additionalProperties) during the mapping phase and need to be
|
|
15
|
+
// reassigned afterward. This is a fast mutable assignment to handle that,
|
|
16
|
+
// but we should consider a more general solution. (review)
|
|
12
17
|
//
|
|
13
18
|
// ------------------------------------------------------------------
|
|
14
|
-
function
|
|
15
|
-
|
|
19
|
+
function Modifiers(type, next) {
|
|
20
|
+
for (const key of Guard.Keys(type)) {
|
|
21
|
+
if (Guard.HasPropertyKey(next, key))
|
|
22
|
+
continue;
|
|
23
|
+
next[key] = type[key];
|
|
24
|
+
}
|
|
25
|
+
return next;
|
|
26
|
+
}
|
|
27
|
+
// ------------------------------------------------------------------
|
|
28
|
+
// Properties
|
|
29
|
+
// ------------------------------------------------------------------
|
|
30
|
+
function FromProperties(properties) {
|
|
31
|
+
const result = {};
|
|
32
|
+
for (const key of Guard.Keys(properties))
|
|
33
|
+
result[key] = FromType(properties[key]);
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
// ------------------------------------------------------------------
|
|
37
|
+
// PriorityTypes
|
|
38
|
+
// ------------------------------------------------------------------
|
|
39
|
+
function FromPriorityTypes(types) {
|
|
40
|
+
return FromTypes(Priority(types));
|
|
41
|
+
}
|
|
42
|
+
// ------------------------------------------------------------------
|
|
43
|
+
// Types
|
|
44
|
+
// ------------------------------------------------------------------
|
|
45
|
+
function FromTypes(types) {
|
|
46
|
+
return types.map(type => FromType(type));
|
|
47
|
+
}
|
|
48
|
+
// ------------------------------------------------------------------
|
|
49
|
+
// Type
|
|
50
|
+
// ------------------------------------------------------------------
|
|
51
|
+
function FromType(type) {
|
|
52
|
+
const next = (IsArray(type) ? _Array_(FromType(type.items), ArrayOptions(type)) :
|
|
53
|
+
IsIntersect(type) ? Intersect(FromTypes(type.allOf)) :
|
|
54
|
+
IsUnion(type) ? Union(FromPriorityTypes(type.anyOf)) :
|
|
55
|
+
IsObject(type) ? _Object_(FromProperties(type.properties)) :
|
|
56
|
+
IsRecord(type) ? Record(RecordKey(type), FromType(RecordValue(type))) :
|
|
57
|
+
IsTuple(type) ? Tuple(FromTypes(type.items)) :
|
|
58
|
+
type);
|
|
59
|
+
return Modifiers(type, next);
|
|
16
60
|
}
|
|
17
61
|
// ------------------------------------------------------------------
|
|
18
62
|
// UnionPrioritySort
|
|
19
|
-
//
|
|
20
|
-
// Performs a deterministic sort on Union members. By default, this
|
|
21
|
-
// function ensures that narrow (more specific) types precede broader
|
|
22
|
-
// types in the resulting array. The order can be reversed by setting
|
|
23
|
-
// the order property to -1 which will reverse unions from broader
|
|
24
|
-
// to more narrow.
|
|
25
|
-
//
|
|
26
63
|
// ------------------------------------------------------------------
|
|
27
|
-
/**
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
});
|
|
64
|
+
/**
|
|
65
|
+
* (Type-Preprocessor) Recursively reorders Union variants from narrowest to broadest, ensuring
|
|
66
|
+
* more specific types (e.g. Literal) are evaluated before broader types (e.g. String). Used
|
|
67
|
+
* prior to Clean, Decode, and Encode operations.
|
|
68
|
+
*/
|
|
69
|
+
export function UnionPrioritySort(type) {
|
|
70
|
+
const result = FromType(type);
|
|
71
|
+
return result;
|
|
36
72
|
}
|