typesea 0.1.0 → 0.3.0
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/CHANGELOG.md +85 -6
- package/README.md +143 -28
- package/dist/adapters/index.d.ts +50 -8
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +169 -48
- package/dist/aot/index.d.ts +19 -3
- package/dist/aot/index.d.ts.map +1 -1
- package/dist/aot/index.js +115 -17
- package/dist/async/index.d.ts +28 -56
- package/dist/async/index.d.ts.map +1 -1
- package/dist/async/index.js +94 -37
- package/dist/builders/composite.d.ts +43 -9
- package/dist/builders/composite.d.ts.map +1 -1
- package/dist/builders/composite.js +100 -17
- package/dist/builders/index.d.ts +8 -5
- package/dist/builders/index.d.ts.map +1 -1
- package/dist/builders/index.js +7 -4
- package/dist/builders/modifier.d.ts +36 -5
- package/dist/builders/modifier.d.ts.map +1 -1
- package/dist/builders/modifier.js +52 -5
- package/dist/builders/object/guard.d.ts +72 -24
- package/dist/builders/object/guard.d.ts.map +1 -1
- package/dist/builders/object/guard.js +139 -29
- package/dist/builders/object/index.d.ts +4 -2
- package/dist/builders/object/index.d.ts.map +1 -1
- package/dist/builders/object/index.js +3 -1
- package/dist/builders/object/schema.d.ts +88 -11
- package/dist/builders/object/schema.d.ts.map +1 -1
- package/dist/builders/object/schema.js +290 -23
- package/dist/builders/object/types.d.ts +20 -31
- package/dist/builders/object/types.d.ts.map +1 -1
- package/dist/builders/object/types.js +2 -0
- package/dist/builders/runtime.d.ts +40 -0
- package/dist/builders/runtime.d.ts.map +1 -0
- package/dist/builders/runtime.js +150 -0
- package/dist/builders/scalar.d.ts +49 -9
- package/dist/builders/scalar.d.ts.map +1 -1
- package/dist/builders/scalar.js +87 -9
- package/dist/builders/table.d.ts +35 -5
- package/dist/builders/table.d.ts.map +1 -1
- package/dist/builders/table.js +35 -5
- package/dist/builders/types.d.ts +20 -4
- package/dist/builders/types.d.ts.map +1 -1
- package/dist/builders/types.js +2 -0
- package/dist/compile/check-composite.d.ts +25 -2
- package/dist/compile/check-composite.d.ts.map +1 -1
- package/dist/compile/check-composite.js +699 -27
- package/dist/compile/check-scalar.d.ts +88 -0
- package/dist/compile/check-scalar.d.ts.map +1 -1
- package/dist/compile/check-scalar.js +570 -3
- package/dist/compile/check.d.ts +12 -0
- package/dist/compile/check.d.ts.map +1 -1
- package/dist/compile/check.js +62 -3
- package/dist/compile/context.d.ts +47 -9
- package/dist/compile/context.d.ts.map +1 -1
- package/dist/compile/context.js +53 -8
- package/dist/compile/first.d.ts +26 -0
- package/dist/compile/first.d.ts.map +1 -0
- package/dist/compile/first.js +850 -0
- package/dist/compile/graph-predicate.d.ts +4 -2
- package/dist/compile/graph-predicate.d.ts.map +1 -1
- package/dist/compile/graph-predicate.js +2272 -165
- package/dist/compile/guard.d.ts +16 -24
- package/dist/compile/guard.d.ts.map +1 -1
- package/dist/compile/guard.js +202 -72
- package/dist/compile/index.d.ts +3 -1
- package/dist/compile/index.d.ts.map +1 -1
- package/dist/compile/index.js +2 -0
- package/dist/compile/issue.d.ts +110 -0
- package/dist/compile/issue.d.ts.map +1 -1
- package/dist/compile/issue.js +184 -1
- package/dist/compile/names.d.ts +12 -2
- package/dist/compile/names.d.ts.map +1 -1
- package/dist/compile/names.js +19 -3
- package/dist/compile/predicate.d.ts +24 -0
- package/dist/compile/predicate.d.ts.map +1 -1
- package/dist/compile/predicate.js +287 -10
- package/dist/compile/runtime.d.ts +100 -13
- package/dist/compile/runtime.d.ts.map +1 -1
- package/dist/compile/runtime.js +56 -6
- package/dist/compile/source.d.ts +10 -2
- package/dist/compile/source.d.ts.map +1 -1
- package/dist/compile/source.js +385 -26
- package/dist/compile/types.d.ts +22 -0
- package/dist/compile/types.d.ts.map +1 -1
- package/dist/compile/types.js +2 -0
- package/dist/decoder/index.d.ts +92 -46
- package/dist/decoder/index.d.ts.map +1 -1
- package/dist/decoder/index.js +266 -39
- package/dist/evaluate/check-composite.d.ts +111 -2
- package/dist/evaluate/check-composite.d.ts.map +1 -1
- package/dist/evaluate/check-composite.js +343 -8
- package/dist/evaluate/check-scalar.d.ts +25 -0
- package/dist/evaluate/check-scalar.d.ts.map +1 -1
- package/dist/evaluate/check-scalar.js +124 -3
- package/dist/evaluate/check.d.ts +7 -0
- package/dist/evaluate/check.d.ts.map +1 -1
- package/dist/evaluate/check.js +62 -4
- package/dist/evaluate/index.d.ts +2 -0
- package/dist/evaluate/index.d.ts.map +1 -1
- package/dist/evaluate/index.js +2 -0
- package/dist/evaluate/issue.d.ts +11 -1
- package/dist/evaluate/issue.d.ts.map +1 -1
- package/dist/evaluate/issue.js +15 -1
- package/dist/evaluate/predicate.d.ts +16 -5
- package/dist/evaluate/predicate.d.ts.map +1 -1
- package/dist/evaluate/predicate.js +20 -5
- package/dist/evaluate/shared.d.ts +78 -13
- package/dist/evaluate/shared.d.ts.map +1 -1
- package/dist/evaluate/shared.js +101 -8
- package/dist/evaluate/state.d.ts +35 -13
- package/dist/evaluate/state.d.ts.map +1 -1
- package/dist/evaluate/state.js +35 -2
- package/dist/guard/array.d.ts +48 -0
- package/dist/guard/array.d.ts.map +1 -0
- package/dist/guard/array.js +84 -0
- package/dist/guard/base.d.ts +111 -31
- package/dist/guard/base.d.ts.map +1 -1
- package/dist/guard/base.js +165 -32
- package/dist/guard/date.d.ts +34 -0
- package/dist/guard/date.d.ts.map +1 -0
- package/dist/guard/date.js +60 -0
- package/dist/guard/error.d.ts +10 -5
- package/dist/guard/error.d.ts.map +1 -1
- package/dist/guard/error.js +10 -5
- package/dist/guard/index.d.ts +4 -0
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +4 -0
- package/dist/guard/number.d.ts +86 -11
- package/dist/guard/number.d.ts.map +1 -1
- package/dist/guard/number.js +159 -11
- package/dist/guard/props.d.ts +27 -3
- package/dist/guard/props.d.ts.map +1 -1
- package/dist/guard/props.js +27 -3
- package/dist/guard/read.d.ts +115 -10
- package/dist/guard/read.d.ts.map +1 -1
- package/dist/guard/read.js +185 -10
- package/dist/guard/registry.d.ts +12 -2
- package/dist/guard/registry.d.ts.map +1 -1
- package/dist/guard/registry.js +15 -3
- package/dist/guard/string.d.ts +115 -13
- package/dist/guard/string.d.ts.map +1 -1
- package/dist/guard/string.js +250 -13
- package/dist/guard/types.d.ts +110 -40
- package/dist/guard/types.d.ts.map +1 -1
- package/dist/guard/types.js +2 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/internal/index.d.ts +42 -6
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +51 -8
- package/dist/ir/builder.d.ts +17 -127
- package/dist/ir/builder.d.ts.map +1 -1
- package/dist/ir/builder.js +80 -137
- package/dist/ir/freeze.d.ts +4 -0
- package/dist/ir/freeze.d.ts.map +1 -1
- package/dist/ir/freeze.js +66 -0
- package/dist/ir/index.d.ts +3 -1
- package/dist/ir/index.d.ts.map +1 -1
- package/dist/ir/index.js +2 -0
- package/dist/ir/regexp.d.ts +2 -0
- package/dist/ir/regexp.d.ts.map +1 -1
- package/dist/ir/regexp.js +2 -0
- package/dist/ir/types.d.ts +94 -56
- package/dist/ir/types.d.ts.map +1 -1
- package/dist/ir/types.js +2 -0
- package/dist/ir/validate.d.ts +8 -1
- package/dist/ir/validate.d.ts.map +1 -1
- package/dist/ir/validate.js +511 -61
- package/dist/issue/index.d.ts +42 -10
- package/dist/issue/index.d.ts.map +1 -1
- package/dist/issue/index.js +65 -11
- package/dist/json-schema/emit-combinator.d.ts +44 -4
- package/dist/json-schema/emit-combinator.d.ts.map +1 -1
- package/dist/json-schema/emit-combinator.js +44 -4
- package/dist/json-schema/emit-composite.d.ts +16 -2
- package/dist/json-schema/emit-composite.d.ts.map +1 -1
- package/dist/json-schema/emit-composite.js +81 -13
- package/dist/json-schema/emit-scalar.d.ts +26 -3
- package/dist/json-schema/emit-scalar.d.ts.map +1 -1
- package/dist/json-schema/emit-scalar.js +124 -10
- package/dist/json-schema/emit-types.d.ts +11 -1
- package/dist/json-schema/emit-types.d.ts.map +1 -1
- package/dist/json-schema/emit-types.js +2 -0
- package/dist/json-schema/emit.d.ts +12 -1
- package/dist/json-schema/emit.d.ts.map +1 -1
- package/dist/json-schema/emit.js +23 -3
- package/dist/json-schema/freeze.d.ts +13 -2
- package/dist/json-schema/freeze.d.ts.map +1 -1
- package/dist/json-schema/freeze.js +41 -8
- package/dist/json-schema/index.d.ts +16 -2
- package/dist/json-schema/index.d.ts.map +1 -1
- package/dist/json-schema/index.js +23 -3
- package/dist/json-schema/issue.d.ts +4 -1
- package/dist/json-schema/issue.d.ts.map +1 -1
- package/dist/json-schema/issue.js +4 -1
- package/dist/json-schema/read.d.ts +24 -3
- package/dist/json-schema/read.d.ts.map +1 -1
- package/dist/json-schema/read.js +59 -12
- package/dist/json-schema/types.d.ts +45 -16
- package/dist/json-schema/types.d.ts.map +1 -1
- package/dist/json-schema/types.js +2 -0
- package/dist/kind/index.d.ts +40 -28
- package/dist/kind/index.d.ts.map +1 -1
- package/dist/kind/index.js +41 -13
- package/dist/lower/index.d.ts +6 -1
- package/dist/lower/index.d.ts.map +1 -1
- package/dist/lower/index.js +462 -46
- package/dist/message/index.d.ts +64 -10
- package/dist/message/index.d.ts.map +1 -1
- package/dist/message/index.js +155 -17
- package/dist/optimize/algebraic.d.ts +54 -0
- package/dist/optimize/algebraic.d.ts.map +1 -0
- package/dist/optimize/algebraic.js +314 -0
- package/dist/optimize/compact.d.ts +8 -1
- package/dist/optimize/compact.d.ts.map +1 -1
- package/dist/optimize/compact.js +13 -2
- package/dist/optimize/domain.d.ts +16 -0
- package/dist/optimize/domain.d.ts.map +1 -0
- package/dist/optimize/domain.js +619 -0
- package/dist/optimize/fold-boolean.d.ts +17 -2
- package/dist/optimize/fold-boolean.d.ts.map +1 -1
- package/dist/optimize/fold-boolean.js +59 -14
- package/dist/optimize/fold-common.d.ts +43 -8
- package/dist/optimize/fold-common.d.ts.map +1 -1
- package/dist/optimize/fold-common.js +37 -6
- package/dist/optimize/fold-constraints.d.ts +33 -0
- package/dist/optimize/fold-constraints.d.ts.map +1 -0
- package/dist/optimize/fold-constraints.js +484 -0
- package/dist/optimize/fold-scalar.d.ts +98 -13
- package/dist/optimize/fold-scalar.d.ts.map +1 -1
- package/dist/optimize/fold-scalar.js +98 -13
- package/dist/optimize/fold.d.ts +8 -1
- package/dist/optimize/fold.d.ts.map +1 -1
- package/dist/optimize/fold.js +22 -2
- package/dist/optimize/index.d.ts +9 -1
- package/dist/optimize/index.d.ts.map +1 -1
- package/dist/optimize/index.js +18 -3
- package/dist/optimize/map-node.d.ts +3 -1
- package/dist/optimize/map-node.d.ts.map +1 -1
- package/dist/optimize/map-node.js +48 -3
- package/dist/optimize/peephole.d.ts +16 -0
- package/dist/optimize/peephole.d.ts.map +1 -0
- package/dist/optimize/peephole.js +254 -0
- package/dist/optimize/remap.d.ts +2 -0
- package/dist/optimize/remap.d.ts.map +1 -1
- package/dist/optimize/remap.js +2 -0
- package/dist/optimize/rewrite.d.ts +13 -8
- package/dist/optimize/rewrite.d.ts.map +1 -1
- package/dist/optimize/rewrite.js +13 -8
- package/dist/plan/cache.d.ts +9 -3
- package/dist/plan/cache.d.ts.map +1 -1
- package/dist/plan/cache.js +34 -6
- package/dist/plan/index.d.ts +2 -0
- package/dist/plan/index.d.ts.map +1 -1
- package/dist/plan/index.js +2 -0
- package/dist/plan/predicate.d.ts +2 -0
- package/dist/plan/predicate.d.ts.map +1 -1
- package/dist/plan/predicate.js +298 -29
- package/dist/plan/schema-predicate.d.ts +6 -0
- package/dist/plan/schema-predicate.d.ts.map +1 -1
- package/dist/plan/schema-predicate.js +382 -19
- package/dist/plan/types.d.ts +2 -0
- package/dist/plan/types.d.ts.map +1 -1
- package/dist/plan/types.js +2 -0
- package/dist/result/index.d.ts +19 -5
- package/dist/result/index.d.ts.map +1 -1
- package/dist/result/index.js +10 -2
- package/dist/schema/common.d.ts +69 -6
- package/dist/schema/common.d.ts.map +1 -1
- package/dist/schema/common.js +104 -10
- package/dist/schema/freeze.d.ts +4 -0
- package/dist/schema/freeze.d.ts.map +1 -1
- package/dist/schema/freeze.js +40 -0
- package/dist/schema/index.d.ts +5 -2
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +4 -1
- package/dist/schema/lazy.d.ts +4 -0
- package/dist/schema/lazy.d.ts.map +1 -1
- package/dist/schema/lazy.js +4 -0
- package/dist/schema/literal.d.ts +7 -1
- package/dist/schema/literal.d.ts.map +1 -1
- package/dist/schema/literal.js +7 -1
- package/dist/schema/types.d.ts +109 -100
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js +13 -2
- package/dist/schema/undefined.d.ts +17 -0
- package/dist/schema/undefined.d.ts.map +1 -0
- package/dist/schema/undefined.js +77 -0
- package/dist/schema/validate.d.ts +8 -1
- package/dist/schema/validate.d.ts.map +1 -1
- package/dist/schema/validate.js +255 -57
- package/docs/api.md +128 -8
- package/docs/assets/benchmark-headline.svg +163 -0
- package/docs/engine-notes.md +62 -15
- package/docs/index.html +1340 -702
- package/docs/ko/api.md +375 -0
- package/docs/ko/engine-notes.md +156 -0
- package/docs/ko/readme.md +378 -0
- package/package.json +66 -65
package/dist/decoder/index.d.ts
CHANGED
|
@@ -1,85 +1,121 @@
|
|
|
1
1
|
import type { Guard, Presence, RuntimeValue } from "../guard/index.js";
|
|
2
2
|
import type { CheckResult } from "../issue/index.js";
|
|
3
|
-
/**
|
|
4
|
-
* @brief decode runner.
|
|
5
|
-
*/
|
|
6
3
|
type DecodeRunner<TValue> = (value: unknown) => CheckResult<TValue>;
|
|
4
|
+
type EncodeRunner<TValue> = (value: unknown) => CheckResult<TValue>;
|
|
5
|
+
type DefaultInput<TValue> = TValue | (() => TValue);
|
|
7
6
|
/**
|
|
8
|
-
* @brief decoder
|
|
7
|
+
* @brief Private runner slot for decoder instances.
|
|
8
|
+
* @details A symbol slot keeps the public object small while avoiding accidental
|
|
9
|
+
* collision with user-visible properties.
|
|
9
10
|
*/
|
|
10
11
|
declare const DecoderRunSymbol: unique symbol;
|
|
11
|
-
|
|
12
|
-
* @brief decode source.
|
|
13
|
-
*/
|
|
12
|
+
declare const CodecEncodeSymbol: unique symbol;
|
|
14
13
|
export type DecodeSource = Guard<unknown, Presence> | Decoder<unknown>;
|
|
15
|
-
/**
|
|
16
|
-
* @brief infer decoder.
|
|
17
|
-
*/
|
|
18
14
|
export type InferDecoder<TSource> = TSource extends Decoder<infer TValue> ? TValue : TSource extends Guard<infer TValue, infer TPresence> ? RuntimeValue<TValue, TPresence> : never;
|
|
19
15
|
/**
|
|
20
|
-
* @brief
|
|
16
|
+
* @brief Synchronous decode pipeline.
|
|
17
|
+
* @details Decoders are explicit Result producers; they do not throw for data
|
|
18
|
+
* validation failure.
|
|
21
19
|
*/
|
|
22
20
|
export interface Decoder<TValue> {
|
|
23
|
-
/**
|
|
24
|
-
* @brief decode.
|
|
25
|
-
*/
|
|
26
21
|
decode(value: unknown): CheckResult<TValue>;
|
|
27
|
-
/**
|
|
28
|
-
* @brief transform.
|
|
29
|
-
*/
|
|
30
22
|
transform<TNext>(mapper: (value: TValue) => TNext): BaseDecoder<TNext>;
|
|
31
|
-
/**
|
|
32
|
-
* @brief pipe.
|
|
33
|
-
*/
|
|
34
23
|
pipe<TNext extends DecodeSource>(next: TNext): BaseDecoder<InferDecoder<TNext>>;
|
|
24
|
+
default(fallback: DefaultInput<TValue>): BaseDecoder<TValue>;
|
|
25
|
+
prefault(fallback: unknown): BaseDecoder<TValue>;
|
|
26
|
+
catch(fallback: DefaultInput<TValue>): BaseDecoder<TValue>;
|
|
27
|
+
}
|
|
28
|
+
export interface Codec<TEncoded, TDecoded> extends Decoder<TDecoded> {
|
|
29
|
+
encode(value: TDecoded): CheckResult<TEncoded>;
|
|
35
30
|
}
|
|
36
31
|
/**
|
|
37
|
-
* @brief
|
|
38
|
-
* @details
|
|
39
|
-
*
|
|
32
|
+
* @brief Frozen decoder wrapper around one runner function.
|
|
33
|
+
* @details Methods re-read the symbol runner from the receiver so detached
|
|
34
|
+
* method calls fail with TypeSea errors instead of touching undefined state.
|
|
40
35
|
*/
|
|
41
36
|
export declare class BaseDecoder<TValue> implements Decoder<TValue> {
|
|
42
37
|
private readonly [DecoderRunSymbol];
|
|
43
|
-
/**
|
|
44
|
-
* @brief constructor.
|
|
45
|
-
* @post The receiver is initialized according to the class invariant before it can be observed.
|
|
46
|
-
*/
|
|
47
38
|
constructor(run: DecodeRunner<TValue>);
|
|
48
|
-
/**
|
|
49
|
-
* @brief decode.
|
|
50
|
-
*/
|
|
51
39
|
decode(this: unknown, value: unknown): CheckResult<TValue>;
|
|
52
|
-
/**
|
|
53
|
-
* @brief transform.
|
|
54
|
-
*/
|
|
55
40
|
transform<TNext>(mapper: (value: TValue) => TNext): BaseDecoder<TNext>;
|
|
56
|
-
/**
|
|
57
|
-
* @brief pipe.
|
|
58
|
-
*/
|
|
59
41
|
pipe<TNext extends DecodeSource>(next: TNext): BaseDecoder<InferDecoder<TNext>>;
|
|
42
|
+
default(fallback: DefaultInput<TValue>): BaseDecoder<TValue>;
|
|
43
|
+
prefault(fallback: unknown): BaseDecoder<TValue>;
|
|
44
|
+
catch(fallback: DefaultInput<TValue>): BaseDecoder<TValue>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* @brief Frozen bidirectional codec wrapper.
|
|
48
|
+
* @details Decode uses the BaseDecoder runner. Encode has a separate private
|
|
49
|
+
* symbol so detached encode calls fail through the same receiver discipline.
|
|
50
|
+
*/
|
|
51
|
+
export declare class BaseCodec<TEncoded, TDecoded> extends BaseDecoder<TDecoded> implements Codec<TEncoded, TDecoded> {
|
|
52
|
+
private readonly [CodecEncodeSymbol];
|
|
53
|
+
constructor(decodeRun: DecodeRunner<TDecoded>, encodeRun: EncodeRunner<TEncoded>);
|
|
54
|
+
encode(this: unknown, value: TDecoded): CheckResult<TEncoded>;
|
|
60
55
|
}
|
|
61
56
|
/**
|
|
62
|
-
* @brief decoder.
|
|
57
|
+
* @brief Wrap a guard or decoder as a synchronous decoder pipeline.
|
|
58
|
+
* @details Decoder helpers keep validation failures explicit in Result values while
|
|
59
|
+
* preserving the original input value.
|
|
63
60
|
*/
|
|
64
61
|
export declare function decoder<TValue, TPresence extends Presence>(source: Guard<TValue, TPresence>): BaseDecoder<RuntimeValue<TValue, TPresence>>;
|
|
65
62
|
/**
|
|
66
|
-
* @brief decoder.
|
|
63
|
+
* @brief Execute decoder.
|
|
64
|
+
* @details This helper keeps a local invariant explicit at the module boundary.
|
|
67
65
|
*/
|
|
68
66
|
export declare function decoder<TValue>(source: Decoder<TValue>): BaseDecoder<TValue>;
|
|
69
67
|
/**
|
|
70
|
-
* @brief
|
|
68
|
+
* @brief Build a decoder and append a synchronous mapper.
|
|
69
|
+
* @details Decoder helpers keep validation failures explicit in Result values while
|
|
70
|
+
* preserving the original input value.
|
|
71
71
|
*/
|
|
72
72
|
export declare function transform<TValue, TPresence extends Presence, TNext>(source: Guard<TValue, TPresence>, mapper: (value: RuntimeValue<TValue, TPresence>) => TNext): BaseDecoder<TNext>;
|
|
73
73
|
/**
|
|
74
|
-
* @brief transform.
|
|
74
|
+
* @brief Execute transform.
|
|
75
|
+
* @details This helper keeps a local invariant explicit at the module boundary.
|
|
75
76
|
*/
|
|
76
77
|
export declare function transform<TValue, TNext>(source: Decoder<TValue>, mapper: (value: TValue) => TNext): BaseDecoder<TNext>;
|
|
77
78
|
/**
|
|
78
|
-
* @brief pipe.
|
|
79
|
+
* @brief Execute pipe.
|
|
80
|
+
* @details This helper keeps a local invariant explicit at the module boundary.
|
|
79
81
|
*/
|
|
80
82
|
export declare function pipe<TNext extends DecodeSource>(source: DecodeSource, next: TNext): BaseDecoder<InferDecoder<TNext>>;
|
|
81
83
|
/**
|
|
82
|
-
* @brief
|
|
84
|
+
* @brief Add a short-circuit default output for undefined input.
|
|
85
|
+
* @param source Guard or decoder used for non-undefined input.
|
|
86
|
+
* @param fallback Output value or zero-argument producer.
|
|
87
|
+
* @returns Decoder that returns fallback output when input is undefined.
|
|
88
|
+
*/
|
|
89
|
+
export declare function defaultValue<TSource extends DecodeSource>(source: TSource, fallback: DefaultInput<InferDecoder<TSource>>): BaseDecoder<InferDecoder<TSource>>;
|
|
90
|
+
/**
|
|
91
|
+
* @brief Add a pre-parse fallback input for undefined input.
|
|
92
|
+
* @param source Guard or decoder used for actual validation.
|
|
93
|
+
* @param fallback Input value passed through the source when input is undefined.
|
|
94
|
+
* @returns Decoder that validates fallback input instead of short-circuiting.
|
|
95
|
+
*/
|
|
96
|
+
export declare function prefault<TSource extends DecodeSource>(source: TSource, fallback: unknown): BaseDecoder<InferDecoder<TSource>>;
|
|
97
|
+
/**
|
|
98
|
+
* @brief Add a failure fallback output for decode errors.
|
|
99
|
+
* @param source Guard or decoder used for validation.
|
|
100
|
+
* @param fallback Output value or zero-argument producer returned on failure.
|
|
101
|
+
* @returns Decoder that converts validation failure into fallback success.
|
|
102
|
+
*/
|
|
103
|
+
export declare function catchValue<TSource extends DecodeSource>(source: TSource, fallback: DefaultInput<InferDecoder<TSource>>): BaseDecoder<InferDecoder<TSource>>;
|
|
104
|
+
/**
|
|
105
|
+
* @brief Build a bidirectional codec from input and output validation sources.
|
|
106
|
+
* @param input Source schema for encoded values.
|
|
107
|
+
* @param output Source schema for decoded values.
|
|
108
|
+
* @param mapping Decode and encode mapping functions.
|
|
109
|
+
* @returns Codec that validates both sides of each conversion.
|
|
110
|
+
*/
|
|
111
|
+
export declare function codec<TInput extends DecodeSource, TOutput extends DecodeSource>(input: TInput, output: TOutput, mapping: {
|
|
112
|
+
readonly decode: (value: InferDecoder<TInput>) => InferDecoder<TOutput>;
|
|
113
|
+
readonly encode: (value: InferDecoder<TOutput>) => InferDecoder<TInput>;
|
|
114
|
+
}): BaseCodec<InferDecoder<TInput>, InferDecoder<TOutput>>;
|
|
115
|
+
/**
|
|
116
|
+
* @brief Primitive coercion decoders with explicit failure issues.
|
|
117
|
+
* @details Decoder helpers keep validation failures explicit in Result values while
|
|
118
|
+
* preserving the original input value.
|
|
83
119
|
*/
|
|
84
120
|
export declare const coerce: Readonly<{
|
|
85
121
|
readonly string: typeof coerceString;
|
|
@@ -87,20 +123,30 @@ export declare const coerce: Readonly<{
|
|
|
87
123
|
readonly boolean: typeof coerceBoolean;
|
|
88
124
|
}>;
|
|
89
125
|
/**
|
|
90
|
-
* @brief coerce string.
|
|
126
|
+
* @brief Execute coerce string.
|
|
127
|
+
* @details This helper keeps a local invariant explicit at the module boundary.
|
|
91
128
|
*/
|
|
92
129
|
export declare function coerceString(): BaseDecoder<string>;
|
|
93
130
|
/**
|
|
94
|
-
* @brief coerce number.
|
|
131
|
+
* @brief Execute coerce number.
|
|
132
|
+
* @details This helper keeps a local invariant explicit at the module boundary.
|
|
95
133
|
*/
|
|
96
134
|
export declare function coerceNumber(): BaseDecoder<number>;
|
|
97
135
|
/**
|
|
98
|
-
* @brief coerce boolean.
|
|
136
|
+
* @brief Execute coerce boolean.
|
|
137
|
+
* @details This helper keeps a local invariant explicit at the module boundary.
|
|
99
138
|
*/
|
|
100
139
|
export declare function coerceBoolean(): BaseDecoder<boolean>;
|
|
101
140
|
/**
|
|
102
|
-
* @brief
|
|
141
|
+
* @brief Check decoder value.
|
|
142
|
+
* @details This helper keeps a local invariant explicit at the module boundary.
|
|
103
143
|
*/
|
|
104
144
|
export declare function isDecoderValue(value: unknown): value is Decoder<unknown>;
|
|
145
|
+
/**
|
|
146
|
+
* @brief Check codec value.
|
|
147
|
+
* @param value Candidate runtime value.
|
|
148
|
+
* @returns True when the value is a TypeSea codec.
|
|
149
|
+
*/
|
|
150
|
+
export declare function isCodecValue(value: unknown): value is Codec<unknown, unknown>;
|
|
105
151
|
export {};
|
|
106
152
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/decoder/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAa,MAAM,mBAAmB,CAAC;AAMhE
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/decoder/index.ts"],"names":[],"mappings":"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"}
|
package/dist/decoder/index.js
CHANGED
|
@@ -4,40 +4,37 @@ import { SchemaTag } from "../kind/index.js";
|
|
|
4
4
|
import { err } from "../result/index.js";
|
|
5
5
|
import { freezeSchema, isSchemaValue } from "../schema/index.js";
|
|
6
6
|
/**
|
|
7
|
-
* @brief decoder
|
|
7
|
+
* @brief Private runner slot for decoder instances.
|
|
8
|
+
* @details A symbol slot keeps the public object small while avoiding accidental
|
|
9
|
+
* collision with user-visible properties.
|
|
8
10
|
*/
|
|
9
11
|
const DecoderRunSymbol = Symbol("TypeSea.decoder.run");
|
|
12
|
+
const CodecEncodeSymbol = Symbol("TypeSea.codec.encode");
|
|
10
13
|
/**
|
|
11
|
-
* @brief
|
|
14
|
+
* @brief Real decoder instances tracked without extending object lifetime.
|
|
15
|
+
* @details Decoder helpers keep validation failures explicit in Result values while
|
|
16
|
+
* preserving the original input value.
|
|
12
17
|
*/
|
|
13
18
|
const constructedDecoders = new WeakSet();
|
|
14
19
|
/**
|
|
15
|
-
* @brief
|
|
16
|
-
* @details
|
|
17
|
-
*
|
|
20
|
+
* @brief Frozen decoder wrapper around one runner function.
|
|
21
|
+
* @details Methods re-read the symbol runner from the receiver so detached
|
|
22
|
+
* method calls fail with TypeSea errors instead of touching undefined state.
|
|
18
23
|
*/
|
|
19
24
|
export class BaseDecoder {
|
|
20
|
-
/**
|
|
21
|
-
* @brief constructor.
|
|
22
|
-
* @post The receiver is initialized according to the class invariant before it can be observed.
|
|
23
|
-
*/
|
|
24
25
|
constructor(run) {
|
|
25
26
|
if (typeof run !== "function") {
|
|
26
27
|
throw new TypeError("decoder run must be a function");
|
|
27
28
|
}
|
|
28
29
|
defineReadonlyProperty(this, DecoderRunSymbol, run, false);
|
|
29
30
|
constructedDecoders.add(this);
|
|
30
|
-
|
|
31
|
+
if (new.target === BaseDecoder) {
|
|
32
|
+
Object.freeze(this);
|
|
33
|
+
}
|
|
31
34
|
}
|
|
32
|
-
/**
|
|
33
|
-
* @brief decode.
|
|
34
|
-
*/
|
|
35
35
|
decode(value) {
|
|
36
36
|
return readDecoderRunner(this, "decoder receiver")(value);
|
|
37
37
|
}
|
|
38
|
-
/**
|
|
39
|
-
* @brief transform.
|
|
40
|
-
*/
|
|
41
38
|
transform(mapper) {
|
|
42
39
|
if (typeof mapper !== "function") {
|
|
43
40
|
throw new TypeError("decoder transform mapper must be a function");
|
|
@@ -51,9 +48,6 @@ export class BaseDecoder {
|
|
|
51
48
|
return okResult(mapper(decoded.value));
|
|
52
49
|
});
|
|
53
50
|
}
|
|
54
|
-
/**
|
|
55
|
-
* @brief pipe.
|
|
56
|
-
*/
|
|
57
51
|
pipe(next) {
|
|
58
52
|
const run = readDecoderRunner(this, "decoder pipe receiver");
|
|
59
53
|
const nextRun = readDecodeSourceRunner(next, "decoder pipe target");
|
|
@@ -65,34 +59,151 @@ export class BaseDecoder {
|
|
|
65
59
|
return nextRun(decoded.value);
|
|
66
60
|
});
|
|
67
61
|
}
|
|
62
|
+
default(fallback) {
|
|
63
|
+
const run = readDecoderRunner(this, "decoder default receiver");
|
|
64
|
+
return new BaseDecoder((value) => {
|
|
65
|
+
if (value === undefined) {
|
|
66
|
+
return okResult(resolveDefault(fallback));
|
|
67
|
+
}
|
|
68
|
+
return run(value);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
prefault(fallback) {
|
|
72
|
+
const run = readDecoderRunner(this, "decoder prefault receiver");
|
|
73
|
+
return new BaseDecoder((value) => run(value === undefined ? fallback : value));
|
|
74
|
+
}
|
|
75
|
+
catch(fallback) {
|
|
76
|
+
const run = readDecoderRunner(this, "decoder catch receiver");
|
|
77
|
+
return new BaseDecoder((value) => {
|
|
78
|
+
const decoded = run(value);
|
|
79
|
+
if (decoded.ok) {
|
|
80
|
+
return decoded;
|
|
81
|
+
}
|
|
82
|
+
return okResult(resolveDefault(fallback));
|
|
83
|
+
});
|
|
84
|
+
}
|
|
68
85
|
}
|
|
69
86
|
/**
|
|
70
|
-
* @brief
|
|
87
|
+
* @brief Frozen bidirectional codec wrapper.
|
|
88
|
+
* @details Decode uses the BaseDecoder runner. Encode has a separate private
|
|
89
|
+
* symbol so detached encode calls fail through the same receiver discipline.
|
|
90
|
+
*/
|
|
91
|
+
export class BaseCodec extends BaseDecoder {
|
|
92
|
+
constructor(decodeRun, encodeRun) {
|
|
93
|
+
super(decodeRun);
|
|
94
|
+
if (typeof encodeRun !== "function") {
|
|
95
|
+
throw new TypeError("codec encode run must be a function");
|
|
96
|
+
}
|
|
97
|
+
defineReadonlyProperty(this, CodecEncodeSymbol, encodeRun, false);
|
|
98
|
+
Object.freeze(this);
|
|
99
|
+
}
|
|
100
|
+
encode(value) {
|
|
101
|
+
return readCodecEncodeRunner(this, "codec receiver")(value);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* @brief Execute decoder.
|
|
106
|
+
* @details This helper keeps a local invariant explicit at the module boundary.
|
|
71
107
|
*/
|
|
72
108
|
export function decoder(source) {
|
|
73
109
|
return makeDecoder(source);
|
|
74
110
|
}
|
|
75
111
|
/**
|
|
76
|
-
* @brief
|
|
112
|
+
* @brief Build decoder.
|
|
113
|
+
* @details This helper keeps a local invariant explicit at the module boundary.
|
|
77
114
|
*/
|
|
78
115
|
function makeDecoder(source) {
|
|
79
116
|
const run = readDecodeSourceRunner(source, "decoder source");
|
|
80
117
|
return new BaseDecoder(run);
|
|
81
118
|
}
|
|
82
119
|
/**
|
|
83
|
-
* @brief transform.
|
|
120
|
+
* @brief Execute transform.
|
|
121
|
+
* @details This helper keeps a local invariant explicit at the module boundary.
|
|
84
122
|
*/
|
|
85
123
|
export function transform(source, mapper) {
|
|
86
124
|
return makeDecoder(source).transform(mapper);
|
|
87
125
|
}
|
|
88
126
|
/**
|
|
89
|
-
* @brief pipe.
|
|
127
|
+
* @brief Execute pipe.
|
|
128
|
+
* @details This helper keeps a local invariant explicit at the module boundary.
|
|
90
129
|
*/
|
|
91
130
|
export function pipe(source, next) {
|
|
92
131
|
return makeDecoder(source).pipe(next);
|
|
93
132
|
}
|
|
94
133
|
/**
|
|
95
|
-
* @brief
|
|
134
|
+
* @brief Add a short-circuit default output for undefined input.
|
|
135
|
+
* @param source Guard or decoder used for non-undefined input.
|
|
136
|
+
* @param fallback Output value or zero-argument producer.
|
|
137
|
+
* @returns Decoder that returns fallback output when input is undefined.
|
|
138
|
+
*/
|
|
139
|
+
export function defaultValue(source, fallback) {
|
|
140
|
+
const run = readDecodeSourceRunner(source, "default source");
|
|
141
|
+
return new BaseDecoder((value) => {
|
|
142
|
+
if (value === undefined) {
|
|
143
|
+
return okResult(resolveDefault(fallback));
|
|
144
|
+
}
|
|
145
|
+
return run(value);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* @brief Add a pre-parse fallback input for undefined input.
|
|
150
|
+
* @param source Guard or decoder used for actual validation.
|
|
151
|
+
* @param fallback Input value passed through the source when input is undefined.
|
|
152
|
+
* @returns Decoder that validates fallback input instead of short-circuiting.
|
|
153
|
+
*/
|
|
154
|
+
export function prefault(source, fallback) {
|
|
155
|
+
const run = readDecodeSourceRunner(source, "prefault source");
|
|
156
|
+
return new BaseDecoder((value) => run(value === undefined ? fallback : value));
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* @brief Add a failure fallback output for decode errors.
|
|
160
|
+
* @param source Guard or decoder used for validation.
|
|
161
|
+
* @param fallback Output value or zero-argument producer returned on failure.
|
|
162
|
+
* @returns Decoder that converts validation failure into fallback success.
|
|
163
|
+
*/
|
|
164
|
+
export function catchValue(source, fallback) {
|
|
165
|
+
const run = readDecodeSourceRunner(source, "catch source");
|
|
166
|
+
return new BaseDecoder((value) => {
|
|
167
|
+
const decoded = run(value);
|
|
168
|
+
if (decoded.ok) {
|
|
169
|
+
return decoded;
|
|
170
|
+
}
|
|
171
|
+
return okResult(resolveDefault(fallback));
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* @brief Build a bidirectional codec from input and output validation sources.
|
|
176
|
+
* @param input Source schema for encoded values.
|
|
177
|
+
* @param output Source schema for decoded values.
|
|
178
|
+
* @param mapping Decode and encode mapping functions.
|
|
179
|
+
* @returns Codec that validates both sides of each conversion.
|
|
180
|
+
*/
|
|
181
|
+
export function codec(input, output, mapping) {
|
|
182
|
+
if (!isRecord(mapping) ||
|
|
183
|
+
typeof mapping.decode !== "function" ||
|
|
184
|
+
typeof mapping.encode !== "function") {
|
|
185
|
+
throw new TypeError("codec mapping must contain decode and encode functions");
|
|
186
|
+
}
|
|
187
|
+
const inputRun = readDecodeSourceRunner(input, "codec input");
|
|
188
|
+
const outputRun = readDecodeSourceRunner(output, "codec output");
|
|
189
|
+
return new BaseCodec((value) => {
|
|
190
|
+
const decodedInput = inputRun(value);
|
|
191
|
+
if (!decodedInput.ok) {
|
|
192
|
+
return decodedInput;
|
|
193
|
+
}
|
|
194
|
+
return outputRun(mapping.decode(decodedInput.value));
|
|
195
|
+
}, (value) => {
|
|
196
|
+
const decodedOutput = outputRun(value);
|
|
197
|
+
if (!decodedOutput.ok) {
|
|
198
|
+
return decodedOutput;
|
|
199
|
+
}
|
|
200
|
+
return inputRun(mapping.encode(decodedOutput.value));
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* @brief Primitive coercion decoders with explicit failure issues.
|
|
205
|
+
* @details Decoder helpers keep validation failures explicit in Result values while
|
|
206
|
+
* preserving the original input value.
|
|
96
207
|
*/
|
|
97
208
|
export const coerce = Object.freeze({
|
|
98
209
|
string: coerceString,
|
|
@@ -100,7 +211,8 @@ export const coerce = Object.freeze({
|
|
|
100
211
|
boolean: coerceBoolean
|
|
101
212
|
});
|
|
102
213
|
/**
|
|
103
|
-
* @brief coerce string.
|
|
214
|
+
* @brief Execute coerce string.
|
|
215
|
+
* @details This helper keeps a local invariant explicit at the module boundary.
|
|
104
216
|
*/
|
|
105
217
|
export function coerceString() {
|
|
106
218
|
return new BaseDecoder((value) => {
|
|
@@ -122,7 +234,8 @@ export function coerceString() {
|
|
|
122
234
|
});
|
|
123
235
|
}
|
|
124
236
|
/**
|
|
125
|
-
* @brief coerce number.
|
|
237
|
+
* @brief Execute coerce number.
|
|
238
|
+
* @details This helper keeps a local invariant explicit at the module boundary.
|
|
126
239
|
*/
|
|
127
240
|
export function coerceNumber() {
|
|
128
241
|
return new BaseDecoder((value) => {
|
|
@@ -140,7 +253,8 @@ export function coerceNumber() {
|
|
|
140
253
|
});
|
|
141
254
|
}
|
|
142
255
|
/**
|
|
143
|
-
* @brief coerce boolean.
|
|
256
|
+
* @brief Execute coerce boolean.
|
|
257
|
+
* @details This helper keeps a local invariant explicit at the module boundary.
|
|
144
258
|
*/
|
|
145
259
|
export function coerceBoolean() {
|
|
146
260
|
return new BaseDecoder((value) => {
|
|
@@ -161,19 +275,56 @@ export function coerceBoolean() {
|
|
|
161
275
|
});
|
|
162
276
|
}
|
|
163
277
|
/**
|
|
164
|
-
* @brief
|
|
278
|
+
* @brief Check decoder value.
|
|
279
|
+
* @details This helper keeps a local invariant explicit at the module boundary.
|
|
165
280
|
*/
|
|
166
281
|
export function isDecoderValue(value) {
|
|
167
282
|
return isConstructedDecoder(value);
|
|
168
283
|
}
|
|
169
284
|
/**
|
|
170
|
-
* @brief
|
|
285
|
+
* @brief Check codec value.
|
|
286
|
+
* @param value Candidate runtime value.
|
|
287
|
+
* @returns True when the value is a TypeSea codec.
|
|
288
|
+
*/
|
|
289
|
+
export function isCodecValue(value) {
|
|
290
|
+
return isConstructedCodec(value);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* @brief Test decoder identity through the private registry.
|
|
294
|
+
* @details Decoder helpers keep validation failures explicit in Result values while
|
|
295
|
+
* preserving the original input value.
|
|
296
|
+
* @param value Candidate decoder.
|
|
297
|
+
* @returns True when TypeSea constructed the decoder instance.
|
|
171
298
|
*/
|
|
172
299
|
function isConstructedDecoder(value) {
|
|
173
300
|
return isRecord(value) && constructedDecoders.has(value);
|
|
174
301
|
}
|
|
175
302
|
/**
|
|
176
|
-
* @brief
|
|
303
|
+
* @brief Test codec identity through the private encode slot.
|
|
304
|
+
* @param value Candidate codec.
|
|
305
|
+
* @returns True when TypeSea constructed the codec instance.
|
|
306
|
+
*/
|
|
307
|
+
function isConstructedCodec(value) {
|
|
308
|
+
return isConstructedDecoder(value) &&
|
|
309
|
+
Object.prototype.hasOwnProperty.call(value, CodecEncodeSymbol);
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* @brief Resolve a default value or zero-argument producer.
|
|
313
|
+
* @param fallback Stored fallback value or producer.
|
|
314
|
+
* @returns Concrete fallback output.
|
|
315
|
+
*/
|
|
316
|
+
function resolveDefault(fallback) {
|
|
317
|
+
return typeof fallback === "function"
|
|
318
|
+
? fallback()
|
|
319
|
+
: fallback;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* @brief Resolve a decode source into an executable runner.
|
|
323
|
+
* @param source Decoder or guard-like value supplied by the caller.
|
|
324
|
+
* @param label Message prefix for TypeError diagnostics.
|
|
325
|
+
* @returns Function that validates one runtime value.
|
|
326
|
+
* @details Real decoders keep a private runner symbol. Guard-like values are
|
|
327
|
+
* lowered to schema checks after hardened schema normalization.
|
|
177
328
|
*/
|
|
178
329
|
function readDecodeSourceRunner(source, label) {
|
|
179
330
|
if (isConstructedDecoder(source)) {
|
|
@@ -183,7 +334,13 @@ function readDecodeSourceRunner(source, label) {
|
|
|
183
334
|
return (value) => checkSchema(schema, value);
|
|
184
335
|
}
|
|
185
336
|
/**
|
|
186
|
-
* @brief
|
|
337
|
+
* @brief Read the private runner from a constructed decoder.
|
|
338
|
+
* @details Decoder helpers keep validation failures explicit in Result values while
|
|
339
|
+
* preserving the original input value.
|
|
340
|
+
* @param value Candidate decoder object.
|
|
341
|
+
* @param label Message prefix for TypeError diagnostics.
|
|
342
|
+
* @returns Stored decode runner.
|
|
343
|
+
* @throws TypeError when the value was not registered by a decoder constructor.
|
|
187
344
|
*/
|
|
188
345
|
function readDecoderRunner(value, label) {
|
|
189
346
|
if (!isConstructedDecoder(value)) {
|
|
@@ -192,20 +349,43 @@ function readDecoderRunner(value, label) {
|
|
|
192
349
|
return value[DecoderRunSymbol];
|
|
193
350
|
}
|
|
194
351
|
/**
|
|
195
|
-
* @brief
|
|
352
|
+
* @brief Read the private encode runner from a constructed codec.
|
|
353
|
+
* @param value Candidate codec object.
|
|
354
|
+
* @param label Message prefix for TypeError diagnostics.
|
|
355
|
+
* @returns Stored encode runner.
|
|
356
|
+
* @throws TypeError when the receiver is not a TypeSea codec.
|
|
357
|
+
*/
|
|
358
|
+
function readCodecEncodeRunner(value, label) {
|
|
359
|
+
if (!isConstructedCodec(value)) {
|
|
360
|
+
throw new TypeError(`${label} must be a TypeSea codec`);
|
|
361
|
+
}
|
|
362
|
+
return value[CodecEncodeSymbol];
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* @brief Normalize a guard-like value used as a decode source.
|
|
366
|
+
* @param value Candidate guard-like source.
|
|
367
|
+
* @param label Message prefix for TypeError diagnostics.
|
|
368
|
+
* @returns Frozen schema used by the generated decode runner.
|
|
369
|
+
* @throws TypeError when the schema slot is absent or malformed.
|
|
370
|
+
* @details Descriptor reads keep inherited schema getters out of the decode
|
|
371
|
+
* pipeline before the schema is frozen for repeated use.
|
|
196
372
|
*/
|
|
197
373
|
function readGuardSchema(value, label) {
|
|
198
374
|
if (!isRecord(value)) {
|
|
199
375
|
throw new TypeError(`${label} must be a TypeSea guard or decoder`);
|
|
200
376
|
}
|
|
201
|
-
const schema = value
|
|
377
|
+
const schema = readOwnDataProperty(value, "schema");
|
|
202
378
|
if (!isSchemaValue(schema)) {
|
|
203
379
|
throw new TypeError(`${label} must contain a valid TypeSea schema`);
|
|
204
380
|
}
|
|
205
381
|
return freezeSchema(schema);
|
|
206
382
|
}
|
|
207
383
|
/**
|
|
208
|
-
* @brief
|
|
384
|
+
* @brief Build a frozen success Result for decoder transforms.
|
|
385
|
+
* @details Decoder helpers keep validation failures explicit in Result values while
|
|
386
|
+
* preserving the original input value.
|
|
387
|
+
* @param value Decoded value.
|
|
388
|
+
* @returns Frozen ok result.
|
|
209
389
|
*/
|
|
210
390
|
function okResult(value) {
|
|
211
391
|
return Object.freeze({
|
|
@@ -214,7 +394,13 @@ function okResult(value) {
|
|
|
214
394
|
});
|
|
215
395
|
}
|
|
216
396
|
/**
|
|
217
|
-
* @brief
|
|
397
|
+
* @brief Build a frozen single-issue failure Result.
|
|
398
|
+
* @details Decoder helpers keep validation failures explicit in Result values while
|
|
399
|
+
* preserving the original input value.
|
|
400
|
+
* @param code Issue code.
|
|
401
|
+
* @param expected Expected value description.
|
|
402
|
+
* @param value Runtime value that failed validation.
|
|
403
|
+
* @returns Failure result with a root-level issue.
|
|
218
404
|
*/
|
|
219
405
|
function fail(code, expected, value) {
|
|
220
406
|
return err(freezeIssueArray([
|
|
@@ -222,7 +408,11 @@ function fail(code, expected, value) {
|
|
|
222
408
|
]));
|
|
223
409
|
}
|
|
224
410
|
/**
|
|
225
|
-
* @brief
|
|
411
|
+
* @brief Produce the compact runtime type label used in decoder issues.
|
|
412
|
+
* @details Decoder helpers keep validation failures explicit in Result values while
|
|
413
|
+
* preserving the original input value.
|
|
414
|
+
* @param value Runtime value.
|
|
415
|
+
* @returns Stable diagnostic type name.
|
|
226
416
|
*/
|
|
227
417
|
function actualType(value) {
|
|
228
418
|
if (value === null) {
|
|
@@ -231,13 +421,28 @@ function actualType(value) {
|
|
|
231
421
|
if (Array.isArray(value)) {
|
|
232
422
|
return "array";
|
|
233
423
|
}
|
|
424
|
+
if (value instanceof Date) {
|
|
425
|
+
return "date";
|
|
426
|
+
}
|
|
427
|
+
if (value instanceof Map) {
|
|
428
|
+
return "map";
|
|
429
|
+
}
|
|
430
|
+
if (value instanceof Set) {
|
|
431
|
+
return "set";
|
|
432
|
+
}
|
|
234
433
|
if (typeof value === "number" && Number.isNaN(value)) {
|
|
235
434
|
return "nan";
|
|
236
435
|
}
|
|
237
436
|
return typeof value;
|
|
238
437
|
}
|
|
239
438
|
/**
|
|
240
|
-
* @brief
|
|
439
|
+
* @brief Define one immutable decoder instance slot.
|
|
440
|
+
* @details Decoder helpers keep validation failures explicit in Result values while
|
|
441
|
+
* preserving the original input value.
|
|
442
|
+
* @param target Decoder instance.
|
|
443
|
+
* @param key Public key or private symbol.
|
|
444
|
+
* @param value Stored field value.
|
|
445
|
+
* @param enumerable Whether the field should appear in enumeration.
|
|
241
446
|
*/
|
|
242
447
|
function defineReadonlyProperty(target, key, value, enumerable) {
|
|
243
448
|
Object.defineProperty(target, key, {
|
|
@@ -248,13 +453,35 @@ function defineReadonlyProperty(target, key, value, enumerable) {
|
|
|
248
453
|
});
|
|
249
454
|
}
|
|
250
455
|
/**
|
|
251
|
-
* @brief
|
|
456
|
+
* @brief Accept objects that can carry decoder or guard fields.
|
|
457
|
+
* @details Decoder helpers keep validation failures explicit in Result values while
|
|
458
|
+
* preserving the original input value.
|
|
459
|
+
* @param value Candidate object.
|
|
460
|
+
* @returns True for non-array objects.
|
|
252
461
|
*/
|
|
253
462
|
function isRecord(value) {
|
|
254
463
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
255
464
|
}
|
|
256
465
|
/**
|
|
257
|
-
* @brief
|
|
466
|
+
* @brief Read one own data slot from a decode source.
|
|
467
|
+
* @details Decoder helpers keep validation failures explicit in Result values while
|
|
468
|
+
* preserving the original input value.
|
|
469
|
+
* @param value Object being normalized.
|
|
470
|
+
* @param key Field name or symbol.
|
|
471
|
+
* @returns Stored field value, or undefined when absent.
|
|
472
|
+
*/
|
|
473
|
+
function readOwnDataProperty(value, key) {
|
|
474
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
475
|
+
if (descriptor === undefined ||
|
|
476
|
+
!Object.prototype.hasOwnProperty.call(descriptor, "value")) {
|
|
477
|
+
return undefined;
|
|
478
|
+
}
|
|
479
|
+
return descriptor.value;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* @brief Reused finite-number schema for string-to-number coercion.
|
|
483
|
+
* @details Decoder helpers keep validation failures explicit in Result values while
|
|
484
|
+
* preserving the original input value.
|
|
258
485
|
*/
|
|
259
486
|
const numberSchema = Object.freeze({
|
|
260
487
|
tag: SchemaTag.Number,
|