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.
Files changed (301) hide show
  1. package/CHANGELOG.md +85 -6
  2. package/README.md +143 -28
  3. package/dist/adapters/index.d.ts +50 -8
  4. package/dist/adapters/index.d.ts.map +1 -1
  5. package/dist/adapters/index.js +169 -48
  6. package/dist/aot/index.d.ts +19 -3
  7. package/dist/aot/index.d.ts.map +1 -1
  8. package/dist/aot/index.js +115 -17
  9. package/dist/async/index.d.ts +28 -56
  10. package/dist/async/index.d.ts.map +1 -1
  11. package/dist/async/index.js +94 -37
  12. package/dist/builders/composite.d.ts +43 -9
  13. package/dist/builders/composite.d.ts.map +1 -1
  14. package/dist/builders/composite.js +100 -17
  15. package/dist/builders/index.d.ts +8 -5
  16. package/dist/builders/index.d.ts.map +1 -1
  17. package/dist/builders/index.js +7 -4
  18. package/dist/builders/modifier.d.ts +36 -5
  19. package/dist/builders/modifier.d.ts.map +1 -1
  20. package/dist/builders/modifier.js +52 -5
  21. package/dist/builders/object/guard.d.ts +72 -24
  22. package/dist/builders/object/guard.d.ts.map +1 -1
  23. package/dist/builders/object/guard.js +139 -29
  24. package/dist/builders/object/index.d.ts +4 -2
  25. package/dist/builders/object/index.d.ts.map +1 -1
  26. package/dist/builders/object/index.js +3 -1
  27. package/dist/builders/object/schema.d.ts +88 -11
  28. package/dist/builders/object/schema.d.ts.map +1 -1
  29. package/dist/builders/object/schema.js +290 -23
  30. package/dist/builders/object/types.d.ts +20 -31
  31. package/dist/builders/object/types.d.ts.map +1 -1
  32. package/dist/builders/object/types.js +2 -0
  33. package/dist/builders/runtime.d.ts +40 -0
  34. package/dist/builders/runtime.d.ts.map +1 -0
  35. package/dist/builders/runtime.js +150 -0
  36. package/dist/builders/scalar.d.ts +49 -9
  37. package/dist/builders/scalar.d.ts.map +1 -1
  38. package/dist/builders/scalar.js +87 -9
  39. package/dist/builders/table.d.ts +35 -5
  40. package/dist/builders/table.d.ts.map +1 -1
  41. package/dist/builders/table.js +35 -5
  42. package/dist/builders/types.d.ts +20 -4
  43. package/dist/builders/types.d.ts.map +1 -1
  44. package/dist/builders/types.js +2 -0
  45. package/dist/compile/check-composite.d.ts +25 -2
  46. package/dist/compile/check-composite.d.ts.map +1 -1
  47. package/dist/compile/check-composite.js +699 -27
  48. package/dist/compile/check-scalar.d.ts +88 -0
  49. package/dist/compile/check-scalar.d.ts.map +1 -1
  50. package/dist/compile/check-scalar.js +570 -3
  51. package/dist/compile/check.d.ts +12 -0
  52. package/dist/compile/check.d.ts.map +1 -1
  53. package/dist/compile/check.js +62 -3
  54. package/dist/compile/context.d.ts +47 -9
  55. package/dist/compile/context.d.ts.map +1 -1
  56. package/dist/compile/context.js +53 -8
  57. package/dist/compile/first.d.ts +26 -0
  58. package/dist/compile/first.d.ts.map +1 -0
  59. package/dist/compile/first.js +850 -0
  60. package/dist/compile/graph-predicate.d.ts +4 -2
  61. package/dist/compile/graph-predicate.d.ts.map +1 -1
  62. package/dist/compile/graph-predicate.js +2272 -165
  63. package/dist/compile/guard.d.ts +16 -24
  64. package/dist/compile/guard.d.ts.map +1 -1
  65. package/dist/compile/guard.js +202 -72
  66. package/dist/compile/index.d.ts +3 -1
  67. package/dist/compile/index.d.ts.map +1 -1
  68. package/dist/compile/index.js +2 -0
  69. package/dist/compile/issue.d.ts +110 -0
  70. package/dist/compile/issue.d.ts.map +1 -1
  71. package/dist/compile/issue.js +184 -1
  72. package/dist/compile/names.d.ts +12 -2
  73. package/dist/compile/names.d.ts.map +1 -1
  74. package/dist/compile/names.js +19 -3
  75. package/dist/compile/predicate.d.ts +24 -0
  76. package/dist/compile/predicate.d.ts.map +1 -1
  77. package/dist/compile/predicate.js +287 -10
  78. package/dist/compile/runtime.d.ts +100 -13
  79. package/dist/compile/runtime.d.ts.map +1 -1
  80. package/dist/compile/runtime.js +56 -6
  81. package/dist/compile/source.d.ts +10 -2
  82. package/dist/compile/source.d.ts.map +1 -1
  83. package/dist/compile/source.js +385 -26
  84. package/dist/compile/types.d.ts +22 -0
  85. package/dist/compile/types.d.ts.map +1 -1
  86. package/dist/compile/types.js +2 -0
  87. package/dist/decoder/index.d.ts +92 -46
  88. package/dist/decoder/index.d.ts.map +1 -1
  89. package/dist/decoder/index.js +266 -39
  90. package/dist/evaluate/check-composite.d.ts +111 -2
  91. package/dist/evaluate/check-composite.d.ts.map +1 -1
  92. package/dist/evaluate/check-composite.js +343 -8
  93. package/dist/evaluate/check-scalar.d.ts +25 -0
  94. package/dist/evaluate/check-scalar.d.ts.map +1 -1
  95. package/dist/evaluate/check-scalar.js +124 -3
  96. package/dist/evaluate/check.d.ts +7 -0
  97. package/dist/evaluate/check.d.ts.map +1 -1
  98. package/dist/evaluate/check.js +62 -4
  99. package/dist/evaluate/index.d.ts +2 -0
  100. package/dist/evaluate/index.d.ts.map +1 -1
  101. package/dist/evaluate/index.js +2 -0
  102. package/dist/evaluate/issue.d.ts +11 -1
  103. package/dist/evaluate/issue.d.ts.map +1 -1
  104. package/dist/evaluate/issue.js +15 -1
  105. package/dist/evaluate/predicate.d.ts +16 -5
  106. package/dist/evaluate/predicate.d.ts.map +1 -1
  107. package/dist/evaluate/predicate.js +20 -5
  108. package/dist/evaluate/shared.d.ts +78 -13
  109. package/dist/evaluate/shared.d.ts.map +1 -1
  110. package/dist/evaluate/shared.js +101 -8
  111. package/dist/evaluate/state.d.ts +35 -13
  112. package/dist/evaluate/state.d.ts.map +1 -1
  113. package/dist/evaluate/state.js +35 -2
  114. package/dist/guard/array.d.ts +48 -0
  115. package/dist/guard/array.d.ts.map +1 -0
  116. package/dist/guard/array.js +84 -0
  117. package/dist/guard/base.d.ts +111 -31
  118. package/dist/guard/base.d.ts.map +1 -1
  119. package/dist/guard/base.js +165 -32
  120. package/dist/guard/date.d.ts +34 -0
  121. package/dist/guard/date.d.ts.map +1 -0
  122. package/dist/guard/date.js +60 -0
  123. package/dist/guard/error.d.ts +10 -5
  124. package/dist/guard/error.d.ts.map +1 -1
  125. package/dist/guard/error.js +10 -5
  126. package/dist/guard/index.d.ts +4 -0
  127. package/dist/guard/index.d.ts.map +1 -1
  128. package/dist/guard/index.js +4 -0
  129. package/dist/guard/number.d.ts +86 -11
  130. package/dist/guard/number.d.ts.map +1 -1
  131. package/dist/guard/number.js +159 -11
  132. package/dist/guard/props.d.ts +27 -3
  133. package/dist/guard/props.d.ts.map +1 -1
  134. package/dist/guard/props.js +27 -3
  135. package/dist/guard/read.d.ts +115 -10
  136. package/dist/guard/read.d.ts.map +1 -1
  137. package/dist/guard/read.js +185 -10
  138. package/dist/guard/registry.d.ts +12 -2
  139. package/dist/guard/registry.d.ts.map +1 -1
  140. package/dist/guard/registry.js +15 -3
  141. package/dist/guard/string.d.ts +115 -13
  142. package/dist/guard/string.d.ts.map +1 -1
  143. package/dist/guard/string.js +250 -13
  144. package/dist/guard/types.d.ts +110 -40
  145. package/dist/guard/types.d.ts.map +1 -1
  146. package/dist/guard/types.js +2 -0
  147. package/dist/index.d.ts +5 -5
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/index.js +4 -4
  150. package/dist/internal/index.d.ts +42 -6
  151. package/dist/internal/index.d.ts.map +1 -1
  152. package/dist/internal/index.js +51 -8
  153. package/dist/ir/builder.d.ts +17 -127
  154. package/dist/ir/builder.d.ts.map +1 -1
  155. package/dist/ir/builder.js +80 -137
  156. package/dist/ir/freeze.d.ts +4 -0
  157. package/dist/ir/freeze.d.ts.map +1 -1
  158. package/dist/ir/freeze.js +66 -0
  159. package/dist/ir/index.d.ts +3 -1
  160. package/dist/ir/index.d.ts.map +1 -1
  161. package/dist/ir/index.js +2 -0
  162. package/dist/ir/regexp.d.ts +2 -0
  163. package/dist/ir/regexp.d.ts.map +1 -1
  164. package/dist/ir/regexp.js +2 -0
  165. package/dist/ir/types.d.ts +94 -56
  166. package/dist/ir/types.d.ts.map +1 -1
  167. package/dist/ir/types.js +2 -0
  168. package/dist/ir/validate.d.ts +8 -1
  169. package/dist/ir/validate.d.ts.map +1 -1
  170. package/dist/ir/validate.js +511 -61
  171. package/dist/issue/index.d.ts +42 -10
  172. package/dist/issue/index.d.ts.map +1 -1
  173. package/dist/issue/index.js +65 -11
  174. package/dist/json-schema/emit-combinator.d.ts +44 -4
  175. package/dist/json-schema/emit-combinator.d.ts.map +1 -1
  176. package/dist/json-schema/emit-combinator.js +44 -4
  177. package/dist/json-schema/emit-composite.d.ts +16 -2
  178. package/dist/json-schema/emit-composite.d.ts.map +1 -1
  179. package/dist/json-schema/emit-composite.js +81 -13
  180. package/dist/json-schema/emit-scalar.d.ts +26 -3
  181. package/dist/json-schema/emit-scalar.d.ts.map +1 -1
  182. package/dist/json-schema/emit-scalar.js +124 -10
  183. package/dist/json-schema/emit-types.d.ts +11 -1
  184. package/dist/json-schema/emit-types.d.ts.map +1 -1
  185. package/dist/json-schema/emit-types.js +2 -0
  186. package/dist/json-schema/emit.d.ts +12 -1
  187. package/dist/json-schema/emit.d.ts.map +1 -1
  188. package/dist/json-schema/emit.js +23 -3
  189. package/dist/json-schema/freeze.d.ts +13 -2
  190. package/dist/json-schema/freeze.d.ts.map +1 -1
  191. package/dist/json-schema/freeze.js +41 -8
  192. package/dist/json-schema/index.d.ts +16 -2
  193. package/dist/json-schema/index.d.ts.map +1 -1
  194. package/dist/json-schema/index.js +23 -3
  195. package/dist/json-schema/issue.d.ts +4 -1
  196. package/dist/json-schema/issue.d.ts.map +1 -1
  197. package/dist/json-schema/issue.js +4 -1
  198. package/dist/json-schema/read.d.ts +24 -3
  199. package/dist/json-schema/read.d.ts.map +1 -1
  200. package/dist/json-schema/read.js +59 -12
  201. package/dist/json-schema/types.d.ts +45 -16
  202. package/dist/json-schema/types.d.ts.map +1 -1
  203. package/dist/json-schema/types.js +2 -0
  204. package/dist/kind/index.d.ts +40 -28
  205. package/dist/kind/index.d.ts.map +1 -1
  206. package/dist/kind/index.js +41 -13
  207. package/dist/lower/index.d.ts +6 -1
  208. package/dist/lower/index.d.ts.map +1 -1
  209. package/dist/lower/index.js +462 -46
  210. package/dist/message/index.d.ts +64 -10
  211. package/dist/message/index.d.ts.map +1 -1
  212. package/dist/message/index.js +155 -17
  213. package/dist/optimize/algebraic.d.ts +54 -0
  214. package/dist/optimize/algebraic.d.ts.map +1 -0
  215. package/dist/optimize/algebraic.js +314 -0
  216. package/dist/optimize/compact.d.ts +8 -1
  217. package/dist/optimize/compact.d.ts.map +1 -1
  218. package/dist/optimize/compact.js +13 -2
  219. package/dist/optimize/domain.d.ts +16 -0
  220. package/dist/optimize/domain.d.ts.map +1 -0
  221. package/dist/optimize/domain.js +619 -0
  222. package/dist/optimize/fold-boolean.d.ts +17 -2
  223. package/dist/optimize/fold-boolean.d.ts.map +1 -1
  224. package/dist/optimize/fold-boolean.js +59 -14
  225. package/dist/optimize/fold-common.d.ts +43 -8
  226. package/dist/optimize/fold-common.d.ts.map +1 -1
  227. package/dist/optimize/fold-common.js +37 -6
  228. package/dist/optimize/fold-constraints.d.ts +33 -0
  229. package/dist/optimize/fold-constraints.d.ts.map +1 -0
  230. package/dist/optimize/fold-constraints.js +484 -0
  231. package/dist/optimize/fold-scalar.d.ts +98 -13
  232. package/dist/optimize/fold-scalar.d.ts.map +1 -1
  233. package/dist/optimize/fold-scalar.js +98 -13
  234. package/dist/optimize/fold.d.ts +8 -1
  235. package/dist/optimize/fold.d.ts.map +1 -1
  236. package/dist/optimize/fold.js +22 -2
  237. package/dist/optimize/index.d.ts +9 -1
  238. package/dist/optimize/index.d.ts.map +1 -1
  239. package/dist/optimize/index.js +18 -3
  240. package/dist/optimize/map-node.d.ts +3 -1
  241. package/dist/optimize/map-node.d.ts.map +1 -1
  242. package/dist/optimize/map-node.js +48 -3
  243. package/dist/optimize/peephole.d.ts +16 -0
  244. package/dist/optimize/peephole.d.ts.map +1 -0
  245. package/dist/optimize/peephole.js +254 -0
  246. package/dist/optimize/remap.d.ts +2 -0
  247. package/dist/optimize/remap.d.ts.map +1 -1
  248. package/dist/optimize/remap.js +2 -0
  249. package/dist/optimize/rewrite.d.ts +13 -8
  250. package/dist/optimize/rewrite.d.ts.map +1 -1
  251. package/dist/optimize/rewrite.js +13 -8
  252. package/dist/plan/cache.d.ts +9 -3
  253. package/dist/plan/cache.d.ts.map +1 -1
  254. package/dist/plan/cache.js +34 -6
  255. package/dist/plan/index.d.ts +2 -0
  256. package/dist/plan/index.d.ts.map +1 -1
  257. package/dist/plan/index.js +2 -0
  258. package/dist/plan/predicate.d.ts +2 -0
  259. package/dist/plan/predicate.d.ts.map +1 -1
  260. package/dist/plan/predicate.js +298 -29
  261. package/dist/plan/schema-predicate.d.ts +6 -0
  262. package/dist/plan/schema-predicate.d.ts.map +1 -1
  263. package/dist/plan/schema-predicate.js +382 -19
  264. package/dist/plan/types.d.ts +2 -0
  265. package/dist/plan/types.d.ts.map +1 -1
  266. package/dist/plan/types.js +2 -0
  267. package/dist/result/index.d.ts +19 -5
  268. package/dist/result/index.d.ts.map +1 -1
  269. package/dist/result/index.js +10 -2
  270. package/dist/schema/common.d.ts +69 -6
  271. package/dist/schema/common.d.ts.map +1 -1
  272. package/dist/schema/common.js +104 -10
  273. package/dist/schema/freeze.d.ts +4 -0
  274. package/dist/schema/freeze.d.ts.map +1 -1
  275. package/dist/schema/freeze.js +40 -0
  276. package/dist/schema/index.d.ts +5 -2
  277. package/dist/schema/index.d.ts.map +1 -1
  278. package/dist/schema/index.js +4 -1
  279. package/dist/schema/lazy.d.ts +4 -0
  280. package/dist/schema/lazy.d.ts.map +1 -1
  281. package/dist/schema/lazy.js +4 -0
  282. package/dist/schema/literal.d.ts +7 -1
  283. package/dist/schema/literal.d.ts.map +1 -1
  284. package/dist/schema/literal.js +7 -1
  285. package/dist/schema/types.d.ts +109 -100
  286. package/dist/schema/types.d.ts.map +1 -1
  287. package/dist/schema/types.js +13 -2
  288. package/dist/schema/undefined.d.ts +17 -0
  289. package/dist/schema/undefined.d.ts.map +1 -0
  290. package/dist/schema/undefined.js +77 -0
  291. package/dist/schema/validate.d.ts +8 -1
  292. package/dist/schema/validate.d.ts.map +1 -1
  293. package/dist/schema/validate.js +255 -57
  294. package/docs/api.md +128 -8
  295. package/docs/assets/benchmark-headline.svg +163 -0
  296. package/docs/engine-notes.md +62 -15
  297. package/docs/index.html +1340 -702
  298. package/docs/ko/api.md +375 -0
  299. package/docs/ko/engine-notes.md +156 -0
  300. package/docs/ko/readme.md +378 -0
  301. package/package.json +66 -65
@@ -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 run symbol.
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 decoder.
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 base decoder.
38
- * @details Owns its state directly; methods expose receiver checks and explicit result flow.
39
- * @invariant Construction leaves the instance in a fully usable state before it escapes.
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 transform.
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 coerce.
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 is decoder value.
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":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/decoder/index.ts"],"names":[],"mappings":"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"}
@@ -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 run symbol.
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 constructed decoders.
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 base decoder.
16
- * @details Owns its state directly; methods expose receiver checks and explicit result flow.
17
- * @invariant Construction leaves the instance in a fully usable state before it escapes.
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
- Object.freeze(this);
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 decoder.
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 make decoder.
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 coerce.
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 is decoder value.
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 is constructed decoder.
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 read decode source runner.
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 read decoder runner.
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 read guard schema.
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["schema"];
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 ok result.
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 fail.
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 actual type.
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 define readonly property.
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 is record.
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 number schema.
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,