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,72 +1,152 @@
1
1
  /**
2
2
  * @file base.ts
3
3
  * @brief Base guard implementation.
4
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
5
+ * existing guard instance.
4
6
  */
5
- import type { CheckResult } from "../issue/index.js";
7
+ import { SchemaTag } from "../kind/index.js";
8
+ import { type CheckResult } from "../issue/index.js";
6
9
  import type { Graph } from "../ir/index.js";
7
10
  import type { Schema } from "../schema/index.js";
11
+ import type { ArrayGuard } from "./array.js";
8
12
  import type { Brand, Guard, Infer, Presence, PresenceSymbol, RuntimeValue, TypeSymbol } from "./types.js";
13
+ type ArraySchemaRecord = Extract<Schema, {
14
+ readonly tag: typeof SchemaTag.Array;
15
+ }>;
16
+ type ArrayGuardFactory = <TItem>(schema: ArraySchemaRecord) => ArrayGuard<TItem>;
9
17
  /**
10
- * @brief base guard.
11
- * @details Owns its state directly; methods expose receiver checks and explicit result flow.
12
- * @invariant Construction leaves the instance in a fully usable state before it escapes.
18
+ * @brief Register the concrete array guard factory.
19
+ * @param factory Constructor wrapper supplied by the array guard module.
20
+ * @details BaseGuard cannot import ArrayGuard directly without creating an
21
+ * initialization cycle. The guard barrel loads ArrayGuard, which installs this
22
+ * factory before public code can call fluent `array()`.
23
+ */
24
+ export declare function setArrayGuardFactory(factory: ArrayGuardFactory): void;
25
+ /**
26
+ * @brief Schema-backed guard base.
27
+ * @details Methods accept an unknown receiver on purpose. Public JavaScript can
28
+ * detach or forge methods, so every entry point re-reads the runtime schema
29
+ * before executing validation.
30
+ * @invariant The stored schema is immutable after construction.
13
31
  */
14
32
  export declare class BaseGuard<TValue, TPresence extends Presence = "required"> implements Guard<TValue, TPresence> {
15
33
  readonly [TypeSymbol]: TValue;
16
34
  readonly [PresenceSymbol]: TPresence;
17
35
  readonly schema: Schema;
18
36
  /**
19
- * @brief constructor.
20
- * @post The receiver is initialized according to the class invariant before it can be observed.
37
+ * @brief Construct a schema-backed guard.
38
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
39
+ * existing guard instance.
40
+ * @param schema Runtime schema owned by the guard.
41
+ * @post The schema slot is frozen and the receiver is registered for fast checks.
21
42
  */
22
43
  constructor(schema: Schema);
23
44
  /**
24
- * @brief is.
25
- */
45
+ * @brief Test whether a value satisfies this guard.
46
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
47
+ * existing guard instance.
48
+ * @param value Candidate runtime value.
49
+ * @returns True when the value is accepted by the guard schema.
50
+ */
26
51
  is(this: unknown, value: unknown): value is RuntimeValue<TValue, TPresence>;
27
52
  /**
28
- * @brief check.
29
- */
53
+ * @brief Validate a value and return explicit diagnostics.
54
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
55
+ * existing guard instance.
56
+ * @param value Candidate runtime value.
57
+ * @returns Result carrying the value on success or frozen issues on failure.
58
+ */
30
59
  check(this: unknown, value: unknown): CheckResult<RuntimeValue<TValue, TPresence>>;
31
60
  /**
32
- * @brief assert.
33
- */
61
+ * @brief Validate a value and keep only the first diagnostic.
62
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
63
+ * existing guard instance.
64
+ * @param value Candidate runtime value.
65
+ * @returns Result carrying the value on success or one frozen issue on failure.
66
+ */
67
+ checkFirst(this: unknown, value: unknown): CheckResult<RuntimeValue<TValue, TPresence>>;
68
+ /**
69
+ * @brief Validate a value and throw TypeSeaAssertionError on failure.
70
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
71
+ * existing guard instance.
72
+ * @param value Candidate runtime value.
73
+ * @throws TypeSeaAssertionError when validation fails.
74
+ */
34
75
  assert(this: unknown, value: unknown): asserts value is RuntimeValue<TValue, TPresence>;
35
76
  /**
36
- * @brief graph.
37
- */
77
+ * @brief Return the optimized validation graph for introspection.
78
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
79
+ * existing guard instance.
80
+ * @returns Sea-of-Nodes graph derived from the guard schema.
81
+ */
38
82
  graph(this: unknown): Graph;
39
83
  /**
40
- * @brief optional.
41
- */
84
+ * @brief Mark this guard as optional in object shapes.
85
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
86
+ * existing guard instance.
87
+ * @returns Fresh guard whose runtime value also allows absent object keys.
88
+ */
42
89
  optional(): BaseGuard<TValue, "optional">;
43
90
  /**
44
- * @brief undefinedable.
45
- */
91
+ * @brief Allow the explicit undefined value.
92
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
93
+ * existing guard instance.
94
+ * @returns Fresh guard wrapping this schema in Undefinedable.
95
+ */
46
96
  undefinedable(): BaseGuard<TValue | undefined, TPresence>;
47
97
  /**
48
- * @brief nullable.
49
- */
98
+ * @brief Allow the explicit null value.
99
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
100
+ * existing guard instance.
101
+ * @returns Fresh guard wrapping this schema in Nullable.
102
+ */
50
103
  nullable(): BaseGuard<TValue | null, TPresence>;
51
104
  /**
52
- * @brief array.
53
- */
54
- array(): BaseGuard<RuntimeValue<TValue, TPresence>[]>;
105
+ * @brief Build an array guard using this guard as the item schema.
106
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
107
+ * existing guard instance.
108
+ * @returns Fresh array guard.
109
+ */
110
+ array(): ArrayGuard<RuntimeValue<TValue, TPresence>>;
55
111
  /**
56
- * @brief brand.
57
- */
112
+ * @brief Attach a compile-time brand without changing runtime validation.
113
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
114
+ * existing guard instance.
115
+ * @returns Fresh branded guard with the same runtime schema.
116
+ */
58
117
  brand<TBrand extends string>(): BaseGuard<Brand<TValue, TBrand>, TPresence>;
59
118
  /**
60
- * @brief refine.
61
- */
119
+ * @brief Append a user refinement predicate after this guard succeeds.
120
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
121
+ * existing guard instance.
122
+ * @param predicate Function that must return the boolean literal true.
123
+ * @param name Diagnostic name for refinement failure.
124
+ * @returns Fresh refined guard.
125
+ */
62
126
  refine(predicate: (value: RuntimeValue<TValue, TPresence>) => boolean, name: string): BaseGuard<TValue, TPresence>;
63
127
  /**
64
- * @brief or.
65
- */
128
+ * @brief Build a union of this guard and another guard.
129
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
130
+ * existing guard instance.
131
+ * @param other Right-hand guard.
132
+ * @returns Fresh union guard preserving both runtime schemas.
133
+ */
66
134
  or<TOther extends Guard<unknown, Presence>>(other: TOther): BaseGuard<RuntimeValue<TValue, TPresence> | Infer<TOther>>;
67
135
  /**
68
- * @brief intersect.
69
- */
136
+ * @brief Build an intersection of this guard and another guard.
137
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
138
+ * existing guard instance.
139
+ * @param other Right-hand guard.
140
+ * @returns Fresh intersection guard requiring both schemas to pass.
141
+ */
70
142
  intersect<TOther extends Guard<unknown, Presence>>(other: TOther): BaseGuard<RuntimeValue<TValue, TPresence> & Infer<TOther>>;
143
+ /**
144
+ * @brief Require one own data property after this guard succeeds.
145
+ * @param key Own string property key to inspect.
146
+ * @param value Guard applied to the property value.
147
+ * @returns Fresh guard that preserves the base domain and property proof.
148
+ */
149
+ property<const TKey extends string, TGuard extends Guard<unknown, Presence>>(key: TKey, value: TGuard): BaseGuard<RuntimeValue<TValue, TPresence> & Readonly<Record<TKey, Infer<TGuard>>>>;
71
150
  }
151
+ export {};
72
152
  //# sourceMappingURL=base.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/guard/base.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AASjD,OAAO,KAAK,EACV,KAAK,EACL,KAAK,EACL,KAAK,EACL,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,UAAU,EACX,MAAM,YAAY,CAAC;AAEpB;;;;GAIG;AACH,qBAAa,SAAS,CACpB,MAAM,EACN,SAAS,SAAS,QAAQ,GAAG,UAAU,CACvC,YAAW,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC;IACnC,SAAwB,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7C,SAAwB,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC;IACpD,SAAwB,MAAM,EAAE,MAAM,CAAC;IAEvC;;;OAGG;gBACgB,MAAM,EAAE,MAAM;IAQjC;;eAEW;IACJ,EAAE,CACP,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC;IAI3C;;eAEW;IACJ,KAAK,CACV,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,OAAO,GACb,WAAW,CAAC,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAO/C;;eAEW;IACJ,MAAM,CACX,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,KAAK,IAAI,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC;IAUnD;;aAES;IACF,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,KAAK;IAIlC;;WAEO;IACA,QAAQ,IAAI,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC;IAOhD;;WAEO;IACA,aAAa,IAAI,SAAS,CAAC,MAAM,GAAG,SAAS,EAAE,SAAS,CAAC;IAOhE;;WAEO;IACA,QAAQ,IAAI,SAAS,CAAC,MAAM,GAAG,IAAI,EAAE,SAAS,CAAC;IAOtD;;WAEO;IACA,KAAK,IAAI,SAAS,CAAC,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC;IAO5D;;WAEO;IACA,KAAK,CAAC,MAAM,SAAS,MAAM,KAAK,SAAS,CAC9C,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,EACrB,SAAS,CACV;IAQD;;eAEW;IACJ,MAAM,CACX,SAAS,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,OAAO,EAC9D,IAAI,EAAE,MAAM,GACX,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC;IAW/B;;aAES;IACF,EAAE,CAAC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAC/C,KAAK,EAAE,MAAM,GACZ,SAAS,CAAC,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAY7D;;aAES;IACF,SAAS,CAAC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EACtD,KAAK,EAAE,MAAM,GACZ,SAAS,CAAC,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;CAO9D"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/guard/base.ts"],"names":[],"mappings":"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"}
@@ -1,46 +1,100 @@
1
1
  /**
2
2
  * @file base.ts
3
3
  * @brief Base guard implementation.
4
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
5
+ * existing guard instance.
4
6
  */
5
7
  import { SchemaTag } from "../kind/index.js";
6
8
  import { checkSchema, isSchema } from "../evaluate/index.js";
7
9
  import { makeValidationPlan } from "../plan/index.js";
10
+ import { freezeIssueArray } from "../issue/index.js";
11
+ import { err } from "../result/index.js";
8
12
  import { TypeSeaAssertionError } from "./error.js";
9
13
  import { checkRefinementInput, readConstructorSchema, readGuardSchema } from "./read.js";
10
14
  import { defineReadonlyProperty, isStrictTrue } from "./props.js";
11
15
  import { registerConstructedGuard } from "./registry.js";
16
+ let arrayGuardFactory;
12
17
  /**
13
- * @brief base guard.
14
- * @details Owns its state directly; methods expose receiver checks and explicit result flow.
15
- * @invariant Construction leaves the instance in a fully usable state before it escapes.
18
+ * @brief Register the concrete array guard factory.
19
+ * @param factory Constructor wrapper supplied by the array guard module.
20
+ * @details BaseGuard cannot import ArrayGuard directly without creating an
21
+ * initialization cycle. The guard barrel loads ArrayGuard, which installs this
22
+ * factory before public code can call fluent `array()`.
23
+ */
24
+ export function setArrayGuardFactory(factory) {
25
+ arrayGuardFactory = factory;
26
+ }
27
+ /**
28
+ * @brief Schema-backed guard base.
29
+ * @details Methods accept an unknown receiver on purpose. Public JavaScript can
30
+ * detach or forge methods, so every entry point re-reads the runtime schema
31
+ * before executing validation.
32
+ * @invariant The stored schema is immutable after construction.
16
33
  */
17
34
  export class BaseGuard {
18
35
  /**
19
- * @brief constructor.
20
- * @post The receiver is initialized according to the class invariant before it can be observed.
36
+ * @brief Construct a schema-backed guard.
37
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
38
+ * existing guard instance.
39
+ * @param schema Runtime schema owned by the guard.
40
+ * @post The schema slot is frozen and the receiver is registered for fast checks.
21
41
  */
22
42
  constructor(schema) {
23
43
  defineReadonlyProperty(this, "schema", readConstructorSchema(schema), true);
24
44
  registerConstructedGuard(this);
25
45
  if (new.target === BaseGuard) {
46
+ /*
47
+ * Direct BaseGuard instances have no subclass state. Freeze them here
48
+ * so user code cannot mutate the public validation object after setup.
49
+ */
26
50
  Object.freeze(this);
27
51
  }
28
52
  }
29
53
  /**
30
- * @brief is.
31
- */
54
+ * @brief Test whether a value satisfies this guard.
55
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
56
+ * existing guard instance.
57
+ * @param value Candidate runtime value.
58
+ * @returns True when the value is accepted by the guard schema.
59
+ */
32
60
  is(value) {
61
+ /*
62
+ * Methods may be detached from their instance in JavaScript. Re-reading
63
+ * the schema from `this` makes receiver forgery fail before validation.
64
+ */
33
65
  return isSchema(readGuardSchema(this, "guard receiver"), value);
34
66
  }
35
67
  /**
36
- * @brief check.
37
- */
68
+ * @brief Validate a value and return explicit diagnostics.
69
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
70
+ * existing guard instance.
71
+ * @param value Candidate runtime value.
72
+ * @returns Result carrying the value on success or frozen issues on failure.
73
+ */
38
74
  check(value) {
39
75
  return checkSchema(readGuardSchema(this, "guard receiver"), value);
40
76
  }
41
77
  /**
42
- * @brief assert.
43
- */
78
+ * @brief Validate a value and keep only the first diagnostic.
79
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
80
+ * existing guard instance.
81
+ * @param value Candidate runtime value.
82
+ * @returns Result carrying the value on success or one frozen issue on failure.
83
+ */
84
+ checkFirst(value) {
85
+ const result = checkSchema(readGuardSchema(this, "guard receiver"), value);
86
+ if (result.ok) {
87
+ return result;
88
+ }
89
+ return err(freezeIssueArray(readFirstIssue(result.error)));
90
+ }
91
+ /**
92
+ * @brief Validate a value and throw TypeSeaAssertionError on failure.
93
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
94
+ * existing guard instance.
95
+ * @param value Candidate runtime value.
96
+ * @throws TypeSeaAssertionError when validation fails.
97
+ */
44
98
  assert(value) {
45
99
  const result = checkSchema(readGuardSchema(this, "guard receiver"), value);
46
100
  if (!result.ok) {
@@ -48,14 +102,20 @@ export class BaseGuard {
48
102
  }
49
103
  }
50
104
  /**
51
- * @brief graph.
52
- */
105
+ * @brief Return the optimized validation graph for introspection.
106
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
107
+ * existing guard instance.
108
+ * @returns Sea-of-Nodes graph derived from the guard schema.
109
+ */
53
110
  graph() {
54
111
  return makeValidationPlan(readGuardSchema(this, "guard receiver")).graph;
55
112
  }
56
113
  /**
57
- * @brief optional.
58
- */
114
+ * @brief Mark this guard as optional in object shapes.
115
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
116
+ * existing guard instance.
117
+ * @returns Fresh guard whose runtime value also allows absent object keys.
118
+ */
59
119
  optional() {
60
120
  return new BaseGuard({
61
121
  tag: SchemaTag.Optional,
@@ -63,8 +123,11 @@ export class BaseGuard {
63
123
  });
64
124
  }
65
125
  /**
66
- * @brief undefinedable.
67
- */
126
+ * @brief Allow the explicit undefined value.
127
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
128
+ * existing guard instance.
129
+ * @returns Fresh guard wrapping this schema in Undefinedable.
130
+ */
68
131
  undefinedable() {
69
132
  return new BaseGuard({
70
133
  tag: SchemaTag.Undefinedable,
@@ -72,8 +135,11 @@ export class BaseGuard {
72
135
  });
73
136
  }
74
137
  /**
75
- * @brief nullable.
76
- */
138
+ * @brief Allow the explicit null value.
139
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
140
+ * existing guard instance.
141
+ * @returns Fresh guard wrapping this schema in Nullable.
142
+ */
77
143
  nullable() {
78
144
  return new BaseGuard({
79
145
  tag: SchemaTag.Nullable,
@@ -81,17 +147,28 @@ export class BaseGuard {
81
147
  });
82
148
  }
83
149
  /**
84
- * @brief array.
85
- */
150
+ * @brief Build an array guard using this guard as the item schema.
151
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
152
+ * existing guard instance.
153
+ * @returns Fresh array guard.
154
+ */
86
155
  array() {
87
- return new BaseGuard({
156
+ const schema = {
88
157
  tag: SchemaTag.Array,
89
- item: readGuardSchema(this, "array item")
90
- });
158
+ item: readGuardSchema(this, "array item"),
159
+ checks: []
160
+ };
161
+ if (arrayGuardFactory === undefined) {
162
+ throw new TypeError("ArrayGuard factory is not initialized");
163
+ }
164
+ return arrayGuardFactory(schema);
91
165
  }
92
166
  /**
93
- * @brief brand.
94
- */
167
+ * @brief Attach a compile-time brand without changing runtime validation.
168
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
169
+ * existing guard instance.
170
+ * @returns Fresh branded guard with the same runtime schema.
171
+ */
95
172
  brand() {
96
173
  return new BaseGuard({
97
174
  tag: SchemaTag.Brand,
@@ -100,20 +177,33 @@ export class BaseGuard {
100
177
  });
101
178
  }
102
179
  /**
103
- * @brief refine.
104
- */
180
+ * @brief Append a user refinement predicate after this guard succeeds.
181
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
182
+ * existing guard instance.
183
+ * @param predicate Function that must return the boolean literal true.
184
+ * @param name Diagnostic name for refinement failure.
185
+ * @returns Fresh refined guard.
186
+ */
105
187
  refine(predicate, name) {
106
188
  checkRefinementInput(predicate, name);
107
189
  return new BaseGuard({
108
190
  tag: SchemaTag.Refine,
109
191
  inner: readGuardSchema(this, "refine inner"),
192
+ /*
193
+ * The predicate is wrapped so only strict true succeeds. Truthy
194
+ * non-boolean values stay failures, matching the interpreter helper.
195
+ */
110
196
  predicate: (value) => isStrictTrue(predicate(value)),
111
197
  name
112
198
  });
113
199
  }
114
200
  /**
115
- * @brief or.
116
- */
201
+ * @brief Build a union of this guard and another guard.
202
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
203
+ * existing guard instance.
204
+ * @param other Right-hand guard.
205
+ * @returns Fresh union guard preserving both runtime schemas.
206
+ */
117
207
  or(other) {
118
208
  return new BaseGuard({
119
209
  tag: SchemaTag.Union,
@@ -124,8 +214,12 @@ export class BaseGuard {
124
214
  });
125
215
  }
126
216
  /**
127
- * @brief intersect.
128
- */
217
+ * @brief Build an intersection of this guard and another guard.
218
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
219
+ * existing guard instance.
220
+ * @param other Right-hand guard.
221
+ * @returns Fresh intersection guard requiring both schemas to pass.
222
+ */
129
223
  intersect(other) {
130
224
  return new BaseGuard({
131
225
  tag: SchemaTag.Intersection,
@@ -133,4 +227,43 @@ export class BaseGuard {
133
227
  right: readGuardSchema(other, "intersection right")
134
228
  });
135
229
  }
230
+ /**
231
+ * @brief Require one own data property after this guard succeeds.
232
+ * @param key Own string property key to inspect.
233
+ * @param value Guard applied to the property value.
234
+ * @returns Fresh guard that preserves the base domain and property proof.
235
+ */
236
+ property(key, value) {
237
+ if (typeof key !== "string") {
238
+ throw new TypeError("property key must be a string");
239
+ }
240
+ return new BaseGuard({
241
+ tag: SchemaTag.Property,
242
+ base: readGuardSchema(this, "property base"),
243
+ key,
244
+ value: readGuardSchema(value, "property value")
245
+ });
246
+ }
247
+ }
248
+ /**
249
+ * @brief Copy the first issue into a single-slot diagnostic vector.
250
+ * @details The full checker owns the original frozen issue vector. checkFirst
251
+ * publishes a narrower vector so callers cannot observe or retain extra issues.
252
+ * @param issues Issue vector returned by the full checker.
253
+ * @returns Mutable vector containing zero or one copied issue.
254
+ */
255
+ function readFirstIssue(issues) {
256
+ const first = issues[0];
257
+ if (first === undefined) {
258
+ return [];
259
+ }
260
+ return [
261
+ {
262
+ path: first.path.slice(),
263
+ code: first.code,
264
+ expected: first.expected,
265
+ actual: first.actual,
266
+ message: first.message
267
+ }
268
+ ];
136
269
  }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * @file date.ts
3
+ * @brief Date guard implementation.
4
+ * @details Date helpers store normalized epoch-millisecond bounds so runtime
5
+ * validation never has to read caller-owned Date objects again.
6
+ */
7
+ import type { DateSchema } from "../schema/index.js";
8
+ import { BaseGuard } from "./base.js";
9
+ import type { Presence } from "./types.js";
10
+ /**
11
+ * @brief Persistent builder for valid Date predicates.
12
+ * @details Bound methods allocate fresh schema records and keep the source guard
13
+ * immutable, matching the scalar guard discipline used by number and string.
14
+ */
15
+ export declare class DateGuard<TPresence extends Presence = "required"> extends BaseGuard<Date, TPresence> {
16
+ /**
17
+ * @brief Construct a frozen Date guard.
18
+ * @param schema Date schema backing this guard.
19
+ */
20
+ constructor(schema: DateSchema);
21
+ /**
22
+ * @brief Add an inclusive lower Date bound.
23
+ * @param value Valid Date object used as the lower bound.
24
+ * @returns Fresh DateGuard with an appended min check.
25
+ */
26
+ min(value: Date): DateGuard<TPresence>;
27
+ /**
28
+ * @brief Add an inclusive upper Date bound.
29
+ * @param value Valid Date object used as the upper bound.
30
+ * @returns Fresh DateGuard with an appended max check.
31
+ */
32
+ max(value: Date): DateGuard<TPresence>;
33
+ }
34
+ //# sourceMappingURL=date.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/guard/date.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAMtC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C;;;;GAIG;AACH,qBAAa,SAAS,CAClB,SAAS,SAAS,QAAQ,GAAG,UAAU,CACzC,SAAQ,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC;IAEhC;;;OAGG;gBACgB,MAAM,EAAE,UAAU;IAKrC;;;;OAIG;IACI,GAAG,CAAC,KAAK,EAAE,IAAI,GAAG,SAAS,CAAC,SAAS,CAAC;IAc7C;;;;OAIG;IACI,GAAG,CAAC,KAAK,EAAE,IAAI,GAAG,SAAS,CAAC,SAAS,CAAC;CAahD"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @file date.ts
3
+ * @brief Date guard implementation.
4
+ * @details Date helpers store normalized epoch-millisecond bounds so runtime
5
+ * validation never has to read caller-owned Date objects again.
6
+ */
7
+ import { DateCheckTag, SchemaTag } from "../kind/index.js";
8
+ import { BaseGuard } from "./base.js";
9
+ import { checkDateBound, readDateConstructorSchema, readDateMethodSchema } from "./read.js";
10
+ /**
11
+ * @brief Persistent builder for valid Date predicates.
12
+ * @details Bound methods allocate fresh schema records and keep the source guard
13
+ * immutable, matching the scalar guard discipline used by number and string.
14
+ */
15
+ export class DateGuard extends BaseGuard {
16
+ /**
17
+ * @brief Construct a frozen Date guard.
18
+ * @param schema Date schema backing this guard.
19
+ */
20
+ constructor(schema) {
21
+ super(readDateConstructorSchema(schema));
22
+ Object.freeze(this);
23
+ }
24
+ /**
25
+ * @brief Add an inclusive lower Date bound.
26
+ * @param value Valid Date object used as the lower bound.
27
+ * @returns Fresh DateGuard with an appended min check.
28
+ */
29
+ min(value) {
30
+ const schema = readDateMethodSchema(this, "date min receiver");
31
+ return new DateGuard({
32
+ tag: SchemaTag.Date,
33
+ checks: [
34
+ ...schema.checks,
35
+ {
36
+ tag: DateCheckTag.Min,
37
+ value: checkDateBound(value, "min")
38
+ }
39
+ ]
40
+ });
41
+ }
42
+ /**
43
+ * @brief Add an inclusive upper Date bound.
44
+ * @param value Valid Date object used as the upper bound.
45
+ * @returns Fresh DateGuard with an appended max check.
46
+ */
47
+ max(value) {
48
+ const schema = readDateMethodSchema(this, "date max receiver");
49
+ return new DateGuard({
50
+ tag: SchemaTag.Date,
51
+ checks: [
52
+ ...schema.checks,
53
+ {
54
+ tag: DateCheckTag.Max,
55
+ value: checkDateBound(value, "max")
56
+ }
57
+ ]
58
+ });
59
+ }
60
+ }
@@ -1,18 +1,23 @@
1
1
  /**
2
2
  * @file error.ts
3
3
  * @brief TypeSea assertion error.
4
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
5
+ * existing guard instance.
4
6
  */
5
7
  import type { Issue } from "../issue/index.js";
6
8
  /**
7
- * @brief type sea assertion error.
8
- * @details Owns its state directly; methods expose receiver checks and explicit result flow.
9
- * @invariant Construction leaves the instance in a fully usable state before it escapes.
9
+ * @brief Error thrown by assert() after validation has already produced issues.
10
+ * @details The issue array is copied before publication so callers cannot mutate
11
+ * diagnostic state through the error object.
10
12
  */
11
13
  export declare class TypeSeaAssertionError extends Error {
12
14
  readonly issues: readonly Issue[];
13
15
  /**
14
- * @brief constructor.
15
- * @post The receiver is initialized according to the class invariant before it can be observed.
16
+ * @brief Construct an assertion error from validation issues.
17
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
18
+ * existing guard instance.
19
+ * @param issues Issues produced by checkSchema.
20
+ * @post Published issues are copied and exposed through a readonly property.
16
21
  */
17
22
  constructor(issues: readonly Issue[]);
18
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/guard/error.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAI/C;;;;GAIG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,SAAwB,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IAEjD;;;OAGG;gBACgB,MAAM,EAAE,SAAS,KAAK,EAAE;CAK5C"}
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/guard/error.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAI/C;;;;GAIG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC5C,SAAwB,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IAEjD;;;;;;OAMG;gBACgB,MAAM,EAAE,SAAS,KAAK,EAAE;CAK9C"}
@@ -1,18 +1,23 @@
1
1
  /**
2
2
  * @file error.ts
3
3
  * @brief TypeSea assertion error.
4
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
5
+ * existing guard instance.
4
6
  */
5
7
  import { copyIssueArray } from "../issue/index.js";
6
8
  import { defineReadonlyProperty } from "./props.js";
7
9
  /**
8
- * @brief type sea assertion error.
9
- * @details Owns its state directly; methods expose receiver checks and explicit result flow.
10
- * @invariant Construction leaves the instance in a fully usable state before it escapes.
10
+ * @brief Error thrown by assert() after validation has already produced issues.
11
+ * @details The issue array is copied before publication so callers cannot mutate
12
+ * diagnostic state through the error object.
11
13
  */
12
14
  export class TypeSeaAssertionError extends Error {
13
15
  /**
14
- * @brief constructor.
15
- * @post The receiver is initialized according to the class invariant before it can be observed.
16
+ * @brief Construct an assertion error from validation issues.
17
+ * @details Guard helpers build new immutable schema wrappers so fluent APIs never mutate an
18
+ * existing guard instance.
19
+ * @param issues Issues produced by checkSchema.
20
+ * @post Published issues are copied and exposed through a readonly property.
16
21
  */
17
22
  constructor(issues) {
18
23
  super("TypeSea assertion failed");