typesea 0.1.0 → 0.2.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 (285) hide show
  1. package/CHANGELOG.md +67 -6
  2. package/README.md +98 -17
  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 +18 -2
  7. package/dist/aot/index.d.ts.map +1 -1
  8. package/dist/aot/index.js +93 -14
  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 +37 -6
  13. package/dist/builders/composite.d.ts.map +1 -1
  14. package/dist/builders/composite.js +84 -10
  15. package/dist/builders/index.d.ts +2 -0
  16. package/dist/builders/index.d.ts.map +1 -1
  17. package/dist/builders/index.js +2 -0
  18. package/dist/builders/modifier.d.ts +30 -5
  19. package/dist/builders/modifier.d.ts.map +1 -1
  20. package/dist/builders/modifier.js +38 -5
  21. package/dist/builders/object/guard.d.ts +18 -22
  22. package/dist/builders/object/guard.d.ts.map +1 -1
  23. package/dist/builders/object/guard.js +26 -26
  24. package/dist/builders/object/index.d.ts +2 -0
  25. package/dist/builders/object/index.d.ts.map +1 -1
  26. package/dist/builders/object/index.js +2 -0
  27. package/dist/builders/object/schema.d.ts +55 -9
  28. package/dist/builders/object/schema.d.ts.map +1 -1
  29. package/dist/builders/object/schema.js +92 -15
  30. package/dist/builders/object/types.d.ts +5 -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/scalar.d.ts +29 -8
  34. package/dist/builders/scalar.d.ts.map +1 -1
  35. package/dist/builders/scalar.js +33 -8
  36. package/dist/builders/table.d.ts +4 -0
  37. package/dist/builders/table.d.ts.map +1 -1
  38. package/dist/builders/table.js +4 -0
  39. package/dist/builders/types.d.ts +14 -4
  40. package/dist/builders/types.d.ts.map +1 -1
  41. package/dist/builders/types.js +2 -0
  42. package/dist/compile/check-composite.d.ts +22 -1
  43. package/dist/compile/check-composite.d.ts.map +1 -1
  44. package/dist/compile/check-composite.js +564 -24
  45. package/dist/compile/check-scalar.d.ts +78 -0
  46. package/dist/compile/check-scalar.d.ts.map +1 -1
  47. package/dist/compile/check-scalar.js +432 -1
  48. package/dist/compile/check.d.ts +12 -0
  49. package/dist/compile/check.d.ts.map +1 -1
  50. package/dist/compile/check.js +37 -0
  51. package/dist/compile/context.d.ts +47 -9
  52. package/dist/compile/context.d.ts.map +1 -1
  53. package/dist/compile/context.js +51 -8
  54. package/dist/compile/graph-predicate.d.ts +4 -2
  55. package/dist/compile/graph-predicate.d.ts.map +1 -1
  56. package/dist/compile/graph-predicate.js +1907 -171
  57. package/dist/compile/guard.d.ts +15 -24
  58. package/dist/compile/guard.d.ts.map +1 -1
  59. package/dist/compile/guard.js +158 -74
  60. package/dist/compile/index.d.ts +3 -1
  61. package/dist/compile/index.d.ts.map +1 -1
  62. package/dist/compile/index.js +2 -0
  63. package/dist/compile/issue.d.ts +110 -0
  64. package/dist/compile/issue.d.ts.map +1 -1
  65. package/dist/compile/issue.js +184 -1
  66. package/dist/compile/names.d.ts +12 -2
  67. package/dist/compile/names.d.ts.map +1 -1
  68. package/dist/compile/names.js +19 -3
  69. package/dist/compile/predicate.d.ts +24 -0
  70. package/dist/compile/predicate.d.ts.map +1 -1
  71. package/dist/compile/predicate.js +131 -5
  72. package/dist/compile/runtime.d.ts +80 -12
  73. package/dist/compile/runtime.d.ts.map +1 -1
  74. package/dist/compile/runtime.js +25 -6
  75. package/dist/compile/source.d.ts +10 -2
  76. package/dist/compile/source.d.ts.map +1 -1
  77. package/dist/compile/source.js +361 -26
  78. package/dist/compile/types.d.ts +20 -0
  79. package/dist/compile/types.d.ts.map +1 -1
  80. package/dist/compile/types.js +2 -0
  81. package/dist/decoder/index.d.ts +32 -46
  82. package/dist/decoder/index.d.ts.map +1 -1
  83. package/dist/decoder/index.js +102 -38
  84. package/dist/evaluate/check-composite.d.ts +59 -0
  85. package/dist/evaluate/check-composite.d.ts.map +1 -1
  86. package/dist/evaluate/check-composite.js +151 -3
  87. package/dist/evaluate/check-scalar.d.ts +16 -0
  88. package/dist/evaluate/check-scalar.d.ts.map +1 -1
  89. package/dist/evaluate/check-scalar.js +32 -0
  90. package/dist/evaluate/check.d.ts +7 -0
  91. package/dist/evaluate/check.d.ts.map +1 -1
  92. package/dist/evaluate/check.js +43 -0
  93. package/dist/evaluate/index.d.ts +2 -0
  94. package/dist/evaluate/index.d.ts.map +1 -1
  95. package/dist/evaluate/index.js +2 -0
  96. package/dist/evaluate/issue.d.ts +11 -1
  97. package/dist/evaluate/issue.d.ts.map +1 -1
  98. package/dist/evaluate/issue.js +15 -1
  99. package/dist/evaluate/predicate.d.ts +16 -5
  100. package/dist/evaluate/predicate.d.ts.map +1 -1
  101. package/dist/evaluate/predicate.js +20 -5
  102. package/dist/evaluate/shared.d.ts +59 -13
  103. package/dist/evaluate/shared.d.ts.map +1 -1
  104. package/dist/evaluate/shared.js +66 -8
  105. package/dist/evaluate/state.d.ts +35 -13
  106. package/dist/evaluate/state.d.ts.map +1 -1
  107. package/dist/evaluate/state.js +35 -2
  108. package/dist/guard/base.d.ts +79 -29
  109. package/dist/guard/base.d.ts.map +1 -1
  110. package/dist/guard/base.js +91 -29
  111. package/dist/guard/error.d.ts +10 -5
  112. package/dist/guard/error.d.ts.map +1 -1
  113. package/dist/guard/error.js +10 -5
  114. package/dist/guard/index.d.ts +2 -0
  115. package/dist/guard/index.d.ts.map +1 -1
  116. package/dist/guard/index.js +2 -0
  117. package/dist/guard/number.d.ts +26 -11
  118. package/dist/guard/number.d.ts.map +1 -1
  119. package/dist/guard/number.js +30 -11
  120. package/dist/guard/props.d.ts +27 -3
  121. package/dist/guard/props.d.ts.map +1 -1
  122. package/dist/guard/props.js +27 -3
  123. package/dist/guard/read.d.ts +62 -9
  124. package/dist/guard/read.d.ts.map +1 -1
  125. package/dist/guard/read.js +83 -10
  126. package/dist/guard/registry.d.ts +12 -2
  127. package/dist/guard/registry.d.ts.map +1 -1
  128. package/dist/guard/registry.js +15 -3
  129. package/dist/guard/string.d.ts +33 -13
  130. package/dist/guard/string.d.ts.map +1 -1
  131. package/dist/guard/string.js +37 -13
  132. package/dist/guard/types.d.ts +92 -40
  133. package/dist/guard/types.d.ts.map +1 -1
  134. package/dist/guard/types.js +2 -0
  135. package/dist/index.d.ts +1 -1
  136. package/dist/index.d.ts.map +1 -1
  137. package/dist/internal/index.d.ts +42 -6
  138. package/dist/internal/index.d.ts.map +1 -1
  139. package/dist/internal/index.js +51 -8
  140. package/dist/ir/builder.d.ts +16 -126
  141. package/dist/ir/builder.d.ts.map +1 -1
  142. package/dist/ir/builder.js +77 -137
  143. package/dist/ir/freeze.d.ts +4 -0
  144. package/dist/ir/freeze.d.ts.map +1 -1
  145. package/dist/ir/freeze.js +59 -0
  146. package/dist/ir/index.d.ts +3 -1
  147. package/dist/ir/index.d.ts.map +1 -1
  148. package/dist/ir/index.js +2 -0
  149. package/dist/ir/regexp.d.ts +2 -0
  150. package/dist/ir/regexp.d.ts.map +1 -1
  151. package/dist/ir/regexp.js +2 -0
  152. package/dist/ir/types.d.ts +90 -55
  153. package/dist/ir/types.d.ts.map +1 -1
  154. package/dist/ir/types.js +2 -0
  155. package/dist/ir/validate.d.ts +8 -1
  156. package/dist/ir/validate.d.ts.map +1 -1
  157. package/dist/ir/validate.js +477 -61
  158. package/dist/issue/index.d.ts +41 -9
  159. package/dist/issue/index.d.ts.map +1 -1
  160. package/dist/issue/index.js +61 -11
  161. package/dist/json-schema/emit-combinator.d.ts +44 -4
  162. package/dist/json-schema/emit-combinator.d.ts.map +1 -1
  163. package/dist/json-schema/emit-combinator.js +44 -4
  164. package/dist/json-schema/emit-composite.d.ts +10 -0
  165. package/dist/json-schema/emit-composite.d.ts.map +1 -1
  166. package/dist/json-schema/emit-composite.js +15 -1
  167. package/dist/json-schema/emit-scalar.d.ts +26 -3
  168. package/dist/json-schema/emit-scalar.d.ts.map +1 -1
  169. package/dist/json-schema/emit-scalar.js +70 -9
  170. package/dist/json-schema/emit-types.d.ts +11 -1
  171. package/dist/json-schema/emit-types.d.ts.map +1 -1
  172. package/dist/json-schema/emit-types.js +2 -0
  173. package/dist/json-schema/emit.d.ts +12 -1
  174. package/dist/json-schema/emit.d.ts.map +1 -1
  175. package/dist/json-schema/emit.js +12 -1
  176. package/dist/json-schema/freeze.d.ts +13 -2
  177. package/dist/json-schema/freeze.d.ts.map +1 -1
  178. package/dist/json-schema/freeze.js +41 -8
  179. package/dist/json-schema/index.d.ts +16 -2
  180. package/dist/json-schema/index.d.ts.map +1 -1
  181. package/dist/json-schema/index.js +23 -3
  182. package/dist/json-schema/issue.d.ts +4 -1
  183. package/dist/json-schema/issue.d.ts.map +1 -1
  184. package/dist/json-schema/issue.js +4 -1
  185. package/dist/json-schema/read.d.ts +24 -3
  186. package/dist/json-schema/read.d.ts.map +1 -1
  187. package/dist/json-schema/read.js +59 -12
  188. package/dist/json-schema/types.d.ts +38 -15
  189. package/dist/json-schema/types.d.ts.map +1 -1
  190. package/dist/json-schema/types.js +2 -0
  191. package/dist/kind/index.d.ts +15 -28
  192. package/dist/kind/index.d.ts.map +1 -1
  193. package/dist/kind/index.js +15 -10
  194. package/dist/lower/index.d.ts +6 -1
  195. package/dist/lower/index.d.ts.map +1 -1
  196. package/dist/lower/index.js +411 -44
  197. package/dist/message/index.d.ts +46 -10
  198. package/dist/message/index.d.ts.map +1 -1
  199. package/dist/message/index.js +88 -17
  200. package/dist/optimize/algebraic.d.ts +54 -0
  201. package/dist/optimize/algebraic.d.ts.map +1 -0
  202. package/dist/optimize/algebraic.js +314 -0
  203. package/dist/optimize/compact.d.ts +8 -1
  204. package/dist/optimize/compact.d.ts.map +1 -1
  205. package/dist/optimize/compact.js +13 -2
  206. package/dist/optimize/domain.d.ts +16 -0
  207. package/dist/optimize/domain.d.ts.map +1 -0
  208. package/dist/optimize/domain.js +615 -0
  209. package/dist/optimize/fold-boolean.d.ts +17 -2
  210. package/dist/optimize/fold-boolean.d.ts.map +1 -1
  211. package/dist/optimize/fold-boolean.js +59 -14
  212. package/dist/optimize/fold-common.d.ts +43 -8
  213. package/dist/optimize/fold-common.d.ts.map +1 -1
  214. package/dist/optimize/fold-common.js +37 -6
  215. package/dist/optimize/fold-constraints.d.ts +33 -0
  216. package/dist/optimize/fold-constraints.d.ts.map +1 -0
  217. package/dist/optimize/fold-constraints.js +484 -0
  218. package/dist/optimize/fold-scalar.d.ts +98 -13
  219. package/dist/optimize/fold-scalar.d.ts.map +1 -1
  220. package/dist/optimize/fold-scalar.js +98 -13
  221. package/dist/optimize/fold.d.ts +8 -1
  222. package/dist/optimize/fold.d.ts.map +1 -1
  223. package/dist/optimize/fold.js +22 -2
  224. package/dist/optimize/index.d.ts +9 -1
  225. package/dist/optimize/index.d.ts.map +1 -1
  226. package/dist/optimize/index.js +18 -3
  227. package/dist/optimize/map-node.d.ts +3 -1
  228. package/dist/optimize/map-node.d.ts.map +1 -1
  229. package/dist/optimize/map-node.js +45 -3
  230. package/dist/optimize/peephole.d.ts +16 -0
  231. package/dist/optimize/peephole.d.ts.map +1 -0
  232. package/dist/optimize/peephole.js +254 -0
  233. package/dist/optimize/remap.d.ts +2 -0
  234. package/dist/optimize/remap.d.ts.map +1 -1
  235. package/dist/optimize/remap.js +2 -0
  236. package/dist/optimize/rewrite.d.ts +13 -8
  237. package/dist/optimize/rewrite.d.ts.map +1 -1
  238. package/dist/optimize/rewrite.js +13 -8
  239. package/dist/plan/cache.d.ts +9 -3
  240. package/dist/plan/cache.d.ts.map +1 -1
  241. package/dist/plan/cache.js +21 -5
  242. package/dist/plan/index.d.ts +2 -0
  243. package/dist/plan/index.d.ts.map +1 -1
  244. package/dist/plan/index.js +2 -0
  245. package/dist/plan/predicate.d.ts +2 -0
  246. package/dist/plan/predicate.d.ts.map +1 -1
  247. package/dist/plan/predicate.js +268 -29
  248. package/dist/plan/schema-predicate.d.ts +6 -0
  249. package/dist/plan/schema-predicate.d.ts.map +1 -1
  250. package/dist/plan/schema-predicate.js +117 -13
  251. package/dist/plan/types.d.ts +2 -0
  252. package/dist/plan/types.d.ts.map +1 -1
  253. package/dist/plan/types.js +2 -0
  254. package/dist/result/index.d.ts +19 -5
  255. package/dist/result/index.d.ts.map +1 -1
  256. package/dist/result/index.js +10 -2
  257. package/dist/schema/common.d.ts +69 -6
  258. package/dist/schema/common.d.ts.map +1 -1
  259. package/dist/schema/common.js +104 -10
  260. package/dist/schema/freeze.d.ts +4 -0
  261. package/dist/schema/freeze.d.ts.map +1 -1
  262. package/dist/schema/freeze.js +18 -0
  263. package/dist/schema/index.d.ts +3 -0
  264. package/dist/schema/index.d.ts.map +1 -1
  265. package/dist/schema/index.js +3 -0
  266. package/dist/schema/lazy.d.ts +4 -0
  267. package/dist/schema/lazy.d.ts.map +1 -1
  268. package/dist/schema/lazy.js +4 -0
  269. package/dist/schema/literal.d.ts +7 -1
  270. package/dist/schema/literal.d.ts.map +1 -1
  271. package/dist/schema/literal.js +7 -1
  272. package/dist/schema/types.d.ts +20 -96
  273. package/dist/schema/types.d.ts.map +1 -1
  274. package/dist/schema/types.js +5 -1
  275. package/dist/schema/undefined.d.ts +17 -0
  276. package/dist/schema/undefined.d.ts.map +1 -0
  277. package/dist/schema/undefined.js +72 -0
  278. package/dist/schema/validate.d.ts +8 -1
  279. package/dist/schema/validate.d.ts.map +1 -1
  280. package/dist/schema/validate.js +146 -55
  281. package/docs/api.md +57 -0
  282. package/docs/assets/benchmark-headline.svg +163 -0
  283. package/docs/engine-notes.md +58 -15
  284. package/docs/index.html +130 -110
  285. package/package.json +65 -65
@@ -1,11 +1,14 @@
1
1
  import { isAsyncDecoderValue } from "../async/index.js";
2
2
  import { isDecoderValue } from "../decoder/index.js";
3
3
  import { TypeSeaAssertionError } from "../guard/index.js";
4
+ import { isConstructedGuard } from "../guard/registry.js";
4
5
  import { formatIssue } from "../message/index.js";
5
6
  import { toJsonSchema } from "../json-schema/index.js";
6
7
  import { isSchemaValue } from "../schema/index.js";
7
8
  /**
8
9
  * @brief to trpc parser.
10
+ * @details Adapter shapes stay local so TypeSea diagnostics can be translated without
11
+ * adding framework dependencies.
9
12
  */
10
13
  export function toTrpcParser(source) {
11
14
  readSyncAdapterSource(source, "tRPC parser source");
@@ -21,6 +24,8 @@ export function toTrpcParser(source) {
21
24
  }
22
25
  /**
23
26
  * @brief to async trpc parser.
27
+ * @details Adapter shapes stay local so TypeSea diagnostics can be translated without
28
+ * adding framework dependencies.
24
29
  */
25
30
  export function toAsyncTrpcParser(source) {
26
31
  readAsyncAdapterSource(source, "async tRPC parser source");
@@ -36,6 +41,8 @@ export function toAsyncTrpcParser(source) {
36
41
  }
37
42
  /**
38
43
  * @brief to fastify route schema.
44
+ * @details Adapter shapes stay local so TypeSea diagnostics can be translated without
45
+ * adding framework dependencies.
39
46
  */
40
47
  export function toFastifyRouteSchema(guard, options) {
41
48
  const part = readFastifyPart(options);
@@ -52,6 +59,8 @@ export function toFastifyRouteSchema(guard, options) {
52
59
  }
53
60
  /**
54
61
  * @brief to fastify validator compiler.
62
+ * @details Adapter shapes stay local so TypeSea diagnostics can be translated without
63
+ * adding framework dependencies.
55
64
  */
56
65
  export function toFastifyValidatorCompiler(source) {
57
66
  const readSource = readFastifyValidatorCompilerSource(source);
@@ -72,6 +81,8 @@ export function toFastifyValidatorCompiler(source) {
72
81
  }
73
82
  /**
74
83
  * @brief to react hook form resolver.
84
+ * @details Adapter shapes stay local so TypeSea diagnostics can be translated without
85
+ * adding framework dependencies.
75
86
  */
76
87
  export function toReactHookFormResolver(source, options) {
77
88
  const config = readReactHookFormOptions(options);
@@ -91,7 +102,13 @@ export function toReactHookFormResolver(source, options) {
91
102
  };
92
103
  }
93
104
  /**
94
- * @brief decode sync source.
105
+ * @brief Run a synchronous adapter source against one submitted value.
106
+ * @param source Guard or decoder selected for the adapter call.
107
+ * @param value Framework payload being validated.
108
+ * @returns TypeSea Result produced by the selected source.
109
+ * @details Decoders already own their result shape. Guard-like values are first
110
+ * normalized through readGuard so structural receivers cannot smuggle inherited
111
+ * schema or check fields into adapter execution.
95
112
  */
96
113
  function decodeSyncSource(source, value) {
97
114
  if (isDecoderValue(source)) {
@@ -101,7 +118,13 @@ function decodeSyncSource(source, value) {
101
118
  return guard.check(value);
102
119
  }
103
120
  /**
104
- * @brief decode async source.
121
+ * @brief Run a possibly asynchronous adapter source.
122
+ * @param source Guard, decoder, or async decoder selected for the adapter call.
123
+ * @param value Framework payload being validated.
124
+ * @returns Promise resolving to a TypeSea Result.
125
+ * @details The ordering keeps native async decoders on their own private runner
126
+ * path while preserving the same hardened guard normalization used by sync
127
+ * adapters.
105
128
  */
106
129
  async function decodeAsyncSource(source, value) {
107
130
  if (isAsyncDecoderValue(source)) {
@@ -114,21 +137,36 @@ async function decodeAsyncSource(source, value) {
114
137
  return guard.check(value);
115
138
  }
116
139
  /**
117
- * @brief read guard.
140
+ * @brief Normalize a guard-like adapter source.
141
+ * @param value Candidate adapter source.
142
+ * @param label Message prefix for TypeError diagnostics.
143
+ * @returns Guard object safe to call through the adapter layer.
144
+ * @throws TypeError when schema or check are not valid guard fields.
145
+ * @details Constructed guards use registry identity. Structural guard support is
146
+ * limited to own data `schema` and `check` slots so adapter entry points do not
147
+ * execute prototype getters supplied by a framework payload or plugin wrapper.
118
148
  */
119
149
  function readGuard(value, label) {
150
+ if (isConstructedGuard(value)) {
151
+ return value;
152
+ }
120
153
  if (!isRecord(value)) {
121
154
  throw new TypeError(`${label} must be a TypeSea guard or decoder`);
122
155
  }
123
156
  const guard = value;
124
- const schema = value["schema"];
125
- if (!isSchemaValue(schema) || typeof guard.check !== "function") {
157
+ const schema = readOwnDataProperty(value, "schema");
158
+ const check = readOwnDataProperty(value, "check");
159
+ if (!isSchemaValue(schema) || typeof check !== "function") {
126
160
  throw new TypeError(`${label} must be a TypeSea guard or decoder`);
127
161
  }
128
162
  return guard;
129
163
  }
130
164
  /**
131
- * @brief read sync adapter source.
165
+ * @brief Validate a source accepted by sync-only adapters.
166
+ * @details Adapter shapes stay local so TypeSea diagnostics can be translated without
167
+ * adding framework dependencies.
168
+ * @param source Candidate guard or decoder.
169
+ * @param label Message prefix for TypeError diagnostics.
132
170
  */
133
171
  function readSyncAdapterSource(source, label) {
134
172
  if (isDecoderValue(source)) {
@@ -137,8 +175,11 @@ function readSyncAdapterSource(source, label) {
137
175
  readGuard(source, label);
138
176
  }
139
177
  /**
140
- * @brief read fastify validator compiler source.
141
- * @details Normalizes a single validator source or a route-part source table into one selector.
178
+ * @brief Normalize Fastify validator sources into a route selector.
179
+ * @details A single source applies to all route parts. A source map is copied
180
+ * into a null-prototype table so route selection cannot observe later prototype
181
+ * mutations or inherited body/querystring/params/headers fields.
182
+ * @param source Guard, decoder, or route-part source table supplied by the user.
142
183
  * @returns Source selector used by the Fastify compiler callback.
143
184
  */
144
185
  function readFastifyValidatorCompilerSource(source) {
@@ -149,10 +190,15 @@ function readFastifyValidatorCompilerSource(source) {
149
190
  if (!isRecord(source)) {
150
191
  throw new TypeError("Fastify validator source must be a TypeSea guard, decoder, or route map");
151
192
  }
152
- readFastifyCompilerMap(source);
193
+ /*
194
+ * Route maps are copied once before Fastify requests per-route validators.
195
+ * Later route selection reads the hardened copy, not caller-controlled
196
+ * prototype state.
197
+ */
198
+ const sourceMap = readFastifyCompilerMap(source);
153
199
  return (route) => {
154
200
  const part = readFastifyRouteHttpPart(route);
155
- const selected = source[part];
201
+ const selected = sourceMap[part];
156
202
  if (selected === undefined) {
157
203
  throw new TypeError(`Fastify validator source is missing ${part}`);
158
204
  }
@@ -160,46 +206,79 @@ function readFastifyValidatorCompilerSource(source) {
160
206
  };
161
207
  }
162
208
  /**
163
- * @brief is guard value.
164
- * @details Performs the same structural guard check as `readGuard` without throwing.
209
+ * @brief Test whether a value is usable as a guard source.
210
+ * @details Performs the same structural guard check as `readGuard` without
211
+ * throwing, which lets the Fastify source normalizer distinguish a single guard
212
+ * from a route-part map.
213
+ * @param value Candidate source.
165
214
  * @returns True when the value is a TypeSea guard object.
166
215
  */
167
216
  function isGuardValue(value) {
217
+ if (isConstructedGuard(value)) {
218
+ return true;
219
+ }
168
220
  if (!isRecord(value)) {
169
221
  return false;
170
222
  }
171
- const guard = value;
172
- return isSchemaValue(value["schema"]) && typeof guard.check === "function";
223
+ const schema = readOwnDataProperty(value, "schema");
224
+ const check = readOwnDataProperty(value, "check");
225
+ return isSchemaValue(schema) && typeof check === "function";
173
226
  }
174
227
  /**
175
- * @brief read fastify compiler map.
176
- * @details Validates every present route-part source before Fastify starts compiling routes.
177
- * @post No result value is produced; malformed sources throw TypeError.
228
+ * @brief Copy and validate a Fastify route-part source map.
229
+ * @details Validates every present route-part source before Fastify starts
230
+ * compiling routes. The returned table is a frozen null-prototype copy owned by
231
+ * TypeSea.
232
+ * @param source Route-part source table supplied by the user.
233
+ * @returns Frozen null-prototype map containing only own data-property sources.
234
+ * @post Accessor properties are rejected without executing getters.
178
235
  */
179
236
  function readFastifyCompilerMap(source) {
180
- readOptionalFastifyCompilerPart(source, "body");
181
- readOptionalFastifyCompilerPart(source, "querystring");
182
- readOptionalFastifyCompilerPart(source, "params");
183
- readOptionalFastifyCompilerPart(source, "headers");
237
+ /*
238
+ * Null prototype prevents inherited body/querystring/params/headers slots
239
+ * from becoming validator sources during route selection.
240
+ */
241
+ const target = Object.create(null);
242
+ readOptionalFastifyCompilerPart(source, target, "body");
243
+ readOptionalFastifyCompilerPart(source, target, "querystring");
244
+ readOptionalFastifyCompilerPart(source, target, "params");
245
+ readOptionalFastifyCompilerPart(source, target, "headers");
246
+ return Object.freeze(target);
184
247
  }
185
248
  /**
186
- * @brief read optional fastify compiler part.
187
- * @details Checks one optional source-map slot without consulting prototype state.
188
- * @post No result value is produced; malformed present sources throw TypeError.
249
+ * @brief Copy one optional Fastify route-part source.
250
+ * @details Copies one own data-property source without consulting prototype
251
+ * state. Missing parts stay undefined so route selection can fail with the
252
+ * concrete missing part later.
253
+ * @param source User supplied route-part source table.
254
+ * @param target Hardened lookup receiving validated sources.
255
+ * @param part Fastify HTTP part to copy.
256
+ * @post Malformed present sources throw TypeError before the compiler is returned.
189
257
  */
190
- function readOptionalFastifyCompilerPart(source, part) {
191
- if (!Object.prototype.hasOwnProperty.call(source, part)) {
258
+ function readOptionalFastifyCompilerPart(source, target, part) {
259
+ /*
260
+ * getOwnPropertyDescriptor observes own metadata without reading the value
261
+ * through the prototype chain or invoking an accessor getter.
262
+ */
263
+ const descriptor = Object.getOwnPropertyDescriptor(source, part);
264
+ if (descriptor === undefined) {
192
265
  return;
193
266
  }
194
- const partSource = source[part];
267
+ if (!Object.prototype.hasOwnProperty.call(descriptor, "value")) {
268
+ throw new TypeError(`Fastify validator source for ${part} must be a data property`);
269
+ }
270
+ const partSource = descriptor.value;
195
271
  if (partSource === undefined) {
196
272
  throw new TypeError(`Fastify validator source for ${part} must be defined`);
197
273
  }
198
274
  readSyncAdapterSource(partSource, `Fastify validator source for ${part}`);
275
+ target[part] = partSource;
199
276
  }
200
277
  /**
201
- * @brief read fastify route http part.
202
- * @details Converts Fastify's route descriptor slot into TypeSea's closed part union.
278
+ * @brief Normalize Fastify route metadata into a supported HTTP part.
279
+ * @details Converts Fastify's route descriptor slot into TypeSea's closed part
280
+ * union so one validator source is never silently reused for a different part.
281
+ * @param route Fastify validator route descriptor.
203
282
  * @returns Validated Fastify HTTP part.
204
283
  */
205
284
  function readFastifyRouteHttpPart(route) {
@@ -214,7 +293,11 @@ function readFastifyRouteHttpPart(route) {
214
293
  }
215
294
  }
216
295
  /**
217
- * @brief read async adapter source.
296
+ * @brief Validate a source accepted by async-capable adapters.
297
+ * @param source Candidate guard, decoder, or async decoder.
298
+ * @param label Message prefix for TypeError diagnostics.
299
+ * @details Async decoders and sync decoders already prove identity through
300
+ * private registries. Guard-like values still pass through readGuard.
218
301
  */
219
302
  function readAsyncAdapterSource(source, label) {
220
303
  if (isAsyncDecoderValue(source) || isDecoderValue(source)) {
@@ -223,7 +306,11 @@ function readAsyncAdapterSource(source, label) {
223
306
  readGuard(source, label);
224
307
  }
225
308
  /**
226
- * @brief read fastify part.
309
+ * @brief Resolve the Fastify route part used for JSON Schema output.
310
+ * @details Adapter shapes stay local so TypeSea diagnostics can be translated without
311
+ * adding framework dependencies.
312
+ * @param options Optional Fastify route schema options.
313
+ * @returns The selected HTTP part, defaulting to body.
227
314
  */
228
315
  function readFastifyPart(options) {
229
316
  if (options?.part === undefined) {
@@ -240,8 +327,10 @@ function readFastifyPart(options) {
240
327
  }
241
328
  }
242
329
  /**
243
- * @brief read fastify json schema options.
244
- * @details Copies only JSON Schema exporter options out of the adapter options object.
330
+ * @brief Extract JSON Schema exporter options from Fastify options.
331
+ * @details Copies only JSON Schema exporter options out of the adapter options
332
+ * object. The returned object avoids exact-optional undefined fields.
333
+ * @param options Optional Fastify route schema options.
245
334
  * @returns Partial JSON Schema options without exact-optional undefined slots.
246
335
  */
247
336
  function readFastifyJsonSchemaOptions(options) {
@@ -255,7 +344,12 @@ function readFastifyJsonSchemaOptions(options) {
255
344
  return output;
256
345
  }
257
346
  /**
258
- * @brief read react hook form options.
347
+ * @brief Normalize React Hook Form resolver options.
348
+ * @details Adapter shapes stay local so TypeSea diagnostics can be translated without
349
+ * adding framework dependencies.
350
+ * @param options Optional resolver options.
351
+ * @returns Required options object used by the resolver.
352
+ * @throws TypeError when options are not object-like.
259
353
  */
260
354
  function readReactHookFormOptions(options) {
261
355
  if (options === undefined) {
@@ -271,7 +365,12 @@ function readReactHookFormOptions(options) {
271
365
  };
272
366
  }
273
367
  /**
274
- * @brief issues to react hook form errors.
368
+ * @brief Convert TypeSea issues into React Hook Form field errors.
369
+ * @param issues Frozen TypeSea issue vector.
370
+ * @param options Message formatting options.
371
+ * @returns Frozen nested FieldErrors-compatible object.
372
+ * @details React Hook Form resolves nested fields by object traversal, so
373
+ * TypeSea paths are inserted as nested branches rather than flat dotted keys.
275
374
  */
276
375
  function issuesToReactHookFormErrors(issues, options) {
277
376
  const errors = makeReactHookFormErrorBranch();
@@ -285,19 +384,21 @@ function issuesToReactHookFormErrors(issues, options) {
285
384
  return freezeReactHookFormErrors(errors);
286
385
  }
287
386
  /**
288
- * @brief make react hook form error branch.
289
- * @details Allocates one null-prototype object so form field names cannot collide with inherited keys.
387
+ * @brief Allocate one mutable React Hook Form error branch.
388
+ * @details Null prototype branches keep field names such as `constructor` or
389
+ * `__proto__` from colliding with inherited object members.
290
390
  * @returns Mutable branch owned by the caller.
291
391
  */
292
392
  function makeReactHookFormErrorBranch() {
293
393
  return Object.create(null);
294
394
  }
295
395
  /**
296
- * @brief insert react hook form issue.
297
- * @details Inserts one TypeSea issue into a nested React Hook Form error tree.
298
- * @param errors Borrowed output branch that receives the leaf error when absent.
299
- * @param issue Borrowed input issue; its path is converted into string map keys.
300
- * @param options Borrowed input message options used only for new leaf formatting.
396
+ * @brief Insert one TypeSea issue into a nested React Hook Form tree.
397
+ * @details Existing leaf errors are preserved because React Hook Form reports
398
+ * the first error for a field by default.
399
+ * @param errors Mutable root branch receiving the leaf error when absent.
400
+ * @param issue Issue whose path is converted into branch keys.
401
+ * @param options Message options used only when a leaf is created.
301
402
  * @post Existing first errors are preserved to match React Hook Form resolver behavior.
302
403
  */
303
404
  function insertReactHookFormIssue(errors, issue, options) {
@@ -337,7 +438,7 @@ function insertReactHookFormIssue(errors, issue, options) {
337
438
  /**
338
439
  * @brief react hook form path key.
339
440
  * @details Converts one TypeSea path segment into the object key React Hook Form traverses.
340
- * @param segment Borrowed input path segment.
441
+ * @param segment Path segment from a TypeSea issue.
341
442
  * @returns Stable string key for object or array-index lookup.
342
443
  */
343
444
  function reactHookFormPathKey(segment) {
@@ -346,7 +447,7 @@ function reactHookFormPathKey(segment) {
346
447
  /**
347
448
  * @brief freeze react hook form errors.
348
449
  * @details Recursively freezes the null-prototype tree after all issues have been inserted.
349
- * @param errors Borrowed mutable branch that becomes immutable before publication.
450
+ * @param errors Mutable branch that becomes immutable before publication.
350
451
  * @returns Frozen React Hook Form error tree.
351
452
  */
352
453
  function freezeReactHookFormErrors(errors) {
@@ -364,7 +465,7 @@ function freezeReactHookFormErrors(errors) {
364
465
  return Object.freeze(errors);
365
466
  }
366
467
  /**
367
- * @brief is react hook form error branch.
468
+ * @brief Test whether a React Hook Form node is an internal branch.
368
469
  * @details Distinguishes internal branch objects from frozen leaf error objects.
369
470
  * @param value Candidate branch or leaf error value.
370
471
  * @returns True when value is a null-prototype branch object.
@@ -381,16 +482,36 @@ function isReactHookFormErrorBranch(value) {
381
482
  */
382
483
  const rootIssuePath = Object.freeze(["root"]);
383
484
  /**
384
- * @brief is record.
485
+ * @brief Check record.
486
+ * @details This helper keeps a local invariant explicit at the module boundary.
385
487
  */
386
488
  function isRecord(value) {
387
489
  return typeof value === "object" && value !== null && !Array.isArray(value);
388
490
  }
389
491
  /**
390
- * @brief empty errors.
492
+ * @brief Read one own data slot from an adapter input object.
493
+ * @details Adapter shapes stay local so TypeSea diagnostics can be translated without
494
+ * adding framework dependencies.
495
+ * @param value Object being normalized.
496
+ * @param key Field name or symbol.
497
+ * @returns Stored field value, or undefined when absent.
498
+ */
499
+ function readOwnDataProperty(value, key) {
500
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
501
+ if (descriptor === undefined ||
502
+ !Object.prototype.hasOwnProperty.call(descriptor, "value")) {
503
+ return undefined;
504
+ }
505
+ return descriptor.value;
506
+ }
507
+ /**
508
+ * @brief Shared immutable success errors object for React Hook Form.
509
+ * @details Reusing this object avoids allocating a fresh empty tree on every
510
+ * successful resolver call.
391
511
  */
392
512
  const emptyErrors = Object.freeze({});
393
513
  /**
394
- * @brief empty values.
514
+ * @brief Shared immutable values object used when resolver validation fails.
515
+ * @details React Hook Form expects failed resolvers to return no accepted values.
395
516
  */
396
517
  const emptyValues = Object.freeze({});
@@ -1,12 +1,17 @@
1
+ import type { CompileMode } from "../compile/index.js";
1
2
  import type { Guard, Presence } from "../guard/index.js";
2
3
  import type { PathSegment } from "../issue/index.js";
3
4
  import { type Result } from "../result/index.js";
4
5
  /**
5
6
  * @brief aot issue code.
7
+ * @details AOT helpers serialize only portable data because standalone modules cannot close
8
+ * over runtime side tables.
6
9
  */
7
10
  export type AotIssueCode = "unsupported_aot_lazy" | "unsupported_aot_refine" | "unsupported_aot_symbol_literal";
8
11
  /**
9
12
  * @brief aot issue.
13
+ * @details AOT helpers serialize only portable data because standalone modules cannot close
14
+ * over runtime side tables.
10
15
  */
11
16
  export interface AotIssue {
12
17
  readonly path: readonly PathSegment[];
@@ -15,19 +20,30 @@ export interface AotIssue {
15
20
  }
16
21
  /**
17
22
  * @brief aot compile options.
23
+ * @details AOT helpers serialize only portable data because standalone modules cannot close
24
+ * over runtime side tables.
18
25
  */
19
26
  export interface AotCompileOptions {
20
27
  readonly name: string | undefined;
28
+ readonly mode: CompileMode | undefined;
21
29
  }
22
30
  /**
23
- * @brief aot module.
31
+ * @brief Source pair emitted for ahead-of-time validation.
32
+ * @details `source` is the JavaScript module body; `declarationSource` is the
33
+ * companion TypeScript declaration used by package consumers.
24
34
  */
25
35
  export interface AotModule {
26
36
  readonly source: string;
27
37
  readonly declarationSource: string;
28
38
  }
29
39
  /**
30
- * @brief emit aot module.
40
+ * @brief Emit a standalone validator module for a guard schema.
41
+ * @param guard Guard whose schema is exported.
42
+ * @param options Optional function name and compile mode.
43
+ * @returns Result carrying source text, or closed issues for unsupported schema nodes.
44
+ * @details AOT output cannot close over runtime side tables. The schema is
45
+ * scanned before code emission so lazy, refine, and symbol-literal constructs
46
+ * fail as explicit issues instead of producing partially faithful source.
31
47
  */
32
48
  export declare function emitAotModule(guard: Guard<unknown, Presence>, options?: Partial<AotCompileOptions>): Result<AotModule, readonly AotIssue[]>;
33
49
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/aot/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAQ1D;;GAEG;AACH,MAAM,MAAM,YAAY,GACpB,sBAAsB,GACtB,wBAAwB,GACxB,gCAAgC,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AASD;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACpC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAC/B,OAAO,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GACnC,MAAM,CAAC,SAAS,EAAE,SAAS,QAAQ,EAAE,CAAC,CAsBxC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/aot/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAQ1D;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAClB,sBAAsB,GACtB,wBAAwB,GACxB,gCAAgC,CAAC;AAEvC;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,CAAC;CAC1C;AAYD;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACtC;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CACzB,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAC/B,OAAO,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GACrC,MAAM,CAAC,SAAS,EAAE,SAAS,QAAQ,EAAE,CAAC,CAsBxC"}