@shapecraft/core 1.0.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 (584) hide show
  1. package/dist/cjs/common/array.d.ts +3 -0
  2. package/dist/cjs/common/array.d.ts.map +1 -0
  3. package/dist/cjs/common/array.js +17 -0
  4. package/dist/cjs/common/array.js.map +1 -0
  5. package/dist/cjs/common/index.d.ts +6 -0
  6. package/dist/cjs/common/index.d.ts.map +1 -0
  7. package/dist/cjs/common/index.js +22 -0
  8. package/dist/cjs/common/index.js.map +1 -0
  9. package/dist/cjs/common/is.d.ts +5 -0
  10. package/dist/cjs/common/is.d.ts.map +1 -0
  11. package/dist/cjs/common/is.js +36 -0
  12. package/dist/cjs/common/is.js.map +1 -0
  13. package/dist/cjs/common/object.d.ts +4 -0
  14. package/dist/cjs/common/object.d.ts.map +1 -0
  15. package/dist/cjs/common/object.js +20 -0
  16. package/dist/cjs/common/object.js.map +1 -0
  17. package/dist/cjs/common/phantom.d.ts +2 -0
  18. package/dist/cjs/common/phantom.d.ts.map +1 -0
  19. package/dist/cjs/common/phantom.js +3 -0
  20. package/dist/cjs/common/phantom.js.map +1 -0
  21. package/dist/cjs/common/result.d.ts +22 -0
  22. package/dist/cjs/common/result.d.ts.map +1 -0
  23. package/dist/cjs/common/result.js +28 -0
  24. package/dist/cjs/common/result.js.map +1 -0
  25. package/dist/cjs/common/string.d.ts +3 -0
  26. package/dist/cjs/common/string.d.ts.map +1 -0
  27. package/dist/cjs/common/string.js +33 -0
  28. package/dist/cjs/common/string.js.map +1 -0
  29. package/dist/cjs/common/types.d.ts +14 -0
  30. package/dist/cjs/common/types.d.ts.map +1 -0
  31. package/dist/cjs/common/types.js +3 -0
  32. package/dist/cjs/common/types.js.map +1 -0
  33. package/dist/cjs/index.d.ts +2 -0
  34. package/dist/cjs/index.d.ts.map +1 -0
  35. package/dist/cjs/index.js +18 -0
  36. package/dist/cjs/index.js.map +1 -0
  37. package/dist/cjs/shape/annotate.d.ts +57 -0
  38. package/dist/cjs/shape/annotate.d.ts.map +1 -0
  39. package/dist/cjs/shape/annotate.js +37 -0
  40. package/dist/cjs/shape/annotate.js.map +1 -0
  41. package/dist/cjs/shape/annotation.d.ts +39 -0
  42. package/dist/cjs/shape/annotation.d.ts.map +1 -0
  43. package/dist/cjs/shape/annotation.js +3 -0
  44. package/dist/cjs/shape/annotation.js.map +1 -0
  45. package/dist/cjs/shape/base.d.ts +33 -0
  46. package/dist/cjs/shape/base.d.ts.map +1 -0
  47. package/dist/cjs/shape/base.js +26 -0
  48. package/dist/cjs/shape/base.js.map +1 -0
  49. package/dist/cjs/shape/builder.d.ts +168 -0
  50. package/dist/cjs/shape/builder.d.ts.map +1 -0
  51. package/dist/cjs/shape/builder.js +156 -0
  52. package/dist/cjs/shape/builder.js.map +1 -0
  53. package/dist/cjs/shape/error.d.ts +5 -0
  54. package/dist/cjs/shape/error.d.ts.map +1 -0
  55. package/dist/cjs/shape/error.js +3 -0
  56. package/dist/cjs/shape/error.js.map +1 -0
  57. package/dist/cjs/shape/index.d.ts +4 -0
  58. package/dist/cjs/shape/index.d.ts.map +1 -0
  59. package/dist/cjs/shape/index.js +20 -0
  60. package/dist/cjs/shape/index.js.map +1 -0
  61. package/dist/cjs/shape/number.d.ts +8 -0
  62. package/dist/cjs/shape/number.d.ts.map +1 -0
  63. package/dist/cjs/shape/number.js +123 -0
  64. package/dist/cjs/shape/number.js.map +1 -0
  65. package/dist/cjs/shape/shape.d.ts +150 -0
  66. package/dist/cjs/shape/shape.d.ts.map +1 -0
  67. package/dist/cjs/shape/shape.js +158 -0
  68. package/dist/cjs/shape/shape.js.map +1 -0
  69. package/dist/cjs/shape/tags.d.ts +4 -0
  70. package/dist/cjs/shape/tags.d.ts.map +1 -0
  71. package/dist/cjs/shape/tags.js +3 -0
  72. package/dist/cjs/shape/tags.js.map +1 -0
  73. package/dist/cjs/shape/transforms/index.d.ts +4 -0
  74. package/dist/cjs/shape/transforms/index.d.ts.map +1 -0
  75. package/dist/cjs/shape/transforms/index.js +20 -0
  76. package/dist/cjs/shape/transforms/index.js.map +1 -0
  77. package/dist/cjs/shape/transforms/json-schema/index.d.ts +3 -0
  78. package/dist/cjs/shape/transforms/json-schema/index.d.ts.map +1 -0
  79. package/dist/cjs/shape/transforms/json-schema/index.js +19 -0
  80. package/dist/cjs/shape/transforms/json-schema/index.js.map +1 -0
  81. package/dist/cjs/shape/transforms/json-schema/transform.d.ts +5 -0
  82. package/dist/cjs/shape/transforms/json-schema/transform.d.ts.map +1 -0
  83. package/dist/cjs/shape/transforms/json-schema/transform.js +739 -0
  84. package/dist/cjs/shape/transforms/json-schema/transform.js.map +1 -0
  85. package/dist/cjs/shape/transforms/json-schema/types.d.ts +87 -0
  86. package/dist/cjs/shape/transforms/json-schema/types.d.ts.map +1 -0
  87. package/dist/cjs/shape/transforms/json-schema/types.js +3 -0
  88. package/dist/cjs/shape/transforms/json-schema/types.js.map +1 -0
  89. package/dist/cjs/shape/transforms/sql/dialects/dialect.d.ts +51 -0
  90. package/dist/cjs/shape/transforms/sql/dialects/dialect.d.ts.map +1 -0
  91. package/dist/cjs/shape/transforms/sql/dialects/dialect.js +8 -0
  92. package/dist/cjs/shape/transforms/sql/dialects/dialect.js.map +1 -0
  93. package/dist/cjs/shape/transforms/sql/dialects/index.d.ts +7 -0
  94. package/dist/cjs/shape/transforms/sql/dialects/index.d.ts.map +1 -0
  95. package/dist/cjs/shape/transforms/sql/dialects/index.js +19 -0
  96. package/dist/cjs/shape/transforms/sql/dialects/index.js.map +1 -0
  97. package/dist/cjs/shape/transforms/sql/dialects/postgres.d.ts +8 -0
  98. package/dist/cjs/shape/transforms/sql/dialects/postgres.d.ts.map +1 -0
  99. package/dist/cjs/shape/transforms/sql/dialects/postgres.js +374 -0
  100. package/dist/cjs/shape/transforms/sql/dialects/postgres.js.map +1 -0
  101. package/dist/cjs/shape/transforms/sql/dialects/sqlite.d.ts +3 -0
  102. package/dist/cjs/shape/transforms/sql/dialects/sqlite.d.ts.map +1 -0
  103. package/dist/cjs/shape/transforms/sql/dialects/sqlite.js +318 -0
  104. package/dist/cjs/shape/transforms/sql/dialects/sqlite.js.map +1 -0
  105. package/dist/cjs/shape/transforms/sql/from-sql.d.ts +5 -0
  106. package/dist/cjs/shape/transforms/sql/from-sql.d.ts.map +1 -0
  107. package/dist/cjs/shape/transforms/sql/from-sql.js +201 -0
  108. package/dist/cjs/shape/transforms/sql/from-sql.js.map +1 -0
  109. package/dist/cjs/shape/transforms/sql/index.d.ts +4 -0
  110. package/dist/cjs/shape/transforms/sql/index.d.ts.map +1 -0
  111. package/dist/cjs/shape/transforms/sql/index.js +20 -0
  112. package/dist/cjs/shape/transforms/sql/index.js.map +1 -0
  113. package/dist/cjs/shape/transforms/sql/options.d.ts +6 -0
  114. package/dist/cjs/shape/transforms/sql/options.d.ts.map +1 -0
  115. package/dist/cjs/shape/transforms/sql/options.js +6 -0
  116. package/dist/cjs/shape/transforms/sql/options.js.map +1 -0
  117. package/dist/cjs/shape/transforms/sql/parser/check-decoder.d.ts +25 -0
  118. package/dist/cjs/shape/transforms/sql/parser/check-decoder.d.ts.map +1 -0
  119. package/dist/cjs/shape/transforms/sql/parser/check-decoder.js +417 -0
  120. package/dist/cjs/shape/transforms/sql/parser/check-decoder.js.map +1 -0
  121. package/dist/cjs/shape/transforms/sql/parser/create-domain.d.ts +11 -0
  122. package/dist/cjs/shape/transforms/sql/parser/create-domain.d.ts.map +1 -0
  123. package/dist/cjs/shape/transforms/sql/parser/create-domain.js +95 -0
  124. package/dist/cjs/shape/transforms/sql/parser/create-domain.js.map +1 -0
  125. package/dist/cjs/shape/transforms/sql/parser/create-table.d.ts +28 -0
  126. package/dist/cjs/shape/transforms/sql/parser/create-table.d.ts.map +1 -0
  127. package/dist/cjs/shape/transforms/sql/parser/create-table.js +744 -0
  128. package/dist/cjs/shape/transforms/sql/parser/create-table.js.map +1 -0
  129. package/dist/cjs/shape/transforms/sql/parser/create-type.d.ts +23 -0
  130. package/dist/cjs/shape/transforms/sql/parser/create-type.d.ts.map +1 -0
  131. package/dist/cjs/shape/transforms/sql/parser/create-type.js +76 -0
  132. package/dist/cjs/shape/transforms/sql/parser/create-type.js.map +1 -0
  133. package/dist/cjs/shape/transforms/sql/parser/cursor.d.ts +32 -0
  134. package/dist/cjs/shape/transforms/sql/parser/cursor.d.ts.map +1 -0
  135. package/dist/cjs/shape/transforms/sql/parser/cursor.js +168 -0
  136. package/dist/cjs/shape/transforms/sql/parser/cursor.js.map +1 -0
  137. package/dist/cjs/shape/transforms/sql/parser/default-decoder.d.ts +10 -0
  138. package/dist/cjs/shape/transforms/sql/parser/default-decoder.d.ts.map +1 -0
  139. package/dist/cjs/shape/transforms/sql/parser/default-decoder.js +125 -0
  140. package/dist/cjs/shape/transforms/sql/parser/default-decoder.js.map +1 -0
  141. package/dist/cjs/shape/transforms/sql/parser/lexer.d.ts +14 -0
  142. package/dist/cjs/shape/transforms/sql/parser/lexer.d.ts.map +1 -0
  143. package/dist/cjs/shape/transforms/sql/parser/lexer.js +259 -0
  144. package/dist/cjs/shape/transforms/sql/parser/lexer.js.map +1 -0
  145. package/dist/cjs/shape/transforms/sql/parser/pg-types.d.ts +21 -0
  146. package/dist/cjs/shape/transforms/sql/parser/pg-types.d.ts.map +1 -0
  147. package/dist/cjs/shape/transforms/sql/parser/pg-types.js +213 -0
  148. package/dist/cjs/shape/transforms/sql/parser/pg-types.js.map +1 -0
  149. package/dist/cjs/shape/transforms/sql/parser/sqlite-types.d.ts +8 -0
  150. package/dist/cjs/shape/transforms/sql/parser/sqlite-types.d.ts.map +1 -0
  151. package/dist/cjs/shape/transforms/sql/parser/sqlite-types.js +93 -0
  152. package/dist/cjs/shape/transforms/sql/parser/sqlite-types.js.map +1 -0
  153. package/dist/cjs/shape/transforms/sql/parser/statements.d.ts +9 -0
  154. package/dist/cjs/shape/transforms/sql/parser/statements.d.ts.map +1 -0
  155. package/dist/cjs/shape/transforms/sql/parser/statements.js +158 -0
  156. package/dist/cjs/shape/transforms/sql/parser/statements.js.map +1 -0
  157. package/dist/cjs/shape/transforms/sql/parser/type-spec.d.ts +12 -0
  158. package/dist/cjs/shape/transforms/sql/parser/type-spec.d.ts.map +1 -0
  159. package/dist/cjs/shape/transforms/sql/parser/type-spec.js +136 -0
  160. package/dist/cjs/shape/transforms/sql/parser/type-spec.js.map +1 -0
  161. package/dist/cjs/shape/transforms/sql/transform.d.ts +5 -0
  162. package/dist/cjs/shape/transforms/sql/transform.d.ts.map +1 -0
  163. package/dist/cjs/shape/transforms/sql/transform.js +262 -0
  164. package/dist/cjs/shape/transforms/sql/transform.js.map +1 -0
  165. package/dist/cjs/shape/transforms/typescript/index.d.ts +2 -0
  166. package/dist/cjs/shape/transforms/typescript/index.d.ts.map +1 -0
  167. package/dist/cjs/shape/transforms/typescript/index.js +18 -0
  168. package/dist/cjs/shape/transforms/typescript/index.js.map +1 -0
  169. package/dist/cjs/shape/transforms/typescript/transform.d.ts +3 -0
  170. package/dist/cjs/shape/transforms/typescript/transform.d.ts.map +1 -0
  171. package/dist/cjs/shape/transforms/typescript/transform.js +190 -0
  172. package/dist/cjs/shape/transforms/typescript/transform.js.map +1 -0
  173. package/dist/cjs/shape/validate.d.ts +7 -0
  174. package/dist/cjs/shape/validate.d.ts.map +1 -0
  175. package/dist/cjs/shape/validate.js +360 -0
  176. package/dist/cjs/shape/validate.js.map +1 -0
  177. package/dist/esm/common/array.d.ts +3 -0
  178. package/dist/esm/common/array.d.ts.map +1 -0
  179. package/dist/esm/common/array.js +12 -0
  180. package/dist/esm/common/array.js.map +1 -0
  181. package/dist/esm/common/index.d.ts +6 -0
  182. package/dist/esm/common/index.d.ts.map +1 -0
  183. package/dist/esm/common/index.js +6 -0
  184. package/dist/esm/common/index.js.map +1 -0
  185. package/dist/esm/common/is.d.ts +5 -0
  186. package/dist/esm/common/is.d.ts.map +1 -0
  187. package/dist/esm/common/is.js +29 -0
  188. package/dist/esm/common/is.js.map +1 -0
  189. package/dist/esm/common/object.d.ts +4 -0
  190. package/dist/esm/common/object.d.ts.map +1 -0
  191. package/dist/esm/common/object.js +15 -0
  192. package/dist/esm/common/object.js.map +1 -0
  193. package/dist/esm/common/phantom.d.ts +2 -0
  194. package/dist/esm/common/phantom.d.ts.map +1 -0
  195. package/dist/esm/common/phantom.js +2 -0
  196. package/dist/esm/common/phantom.js.map +1 -0
  197. package/dist/esm/common/result.d.ts +22 -0
  198. package/dist/esm/common/result.d.ts.map +1 -0
  199. package/dist/esm/common/result.js +25 -0
  200. package/dist/esm/common/result.js.map +1 -0
  201. package/dist/esm/common/string.d.ts +3 -0
  202. package/dist/esm/common/string.d.ts.map +1 -0
  203. package/dist/esm/common/string.js +28 -0
  204. package/dist/esm/common/string.js.map +1 -0
  205. package/dist/esm/common/types.d.ts +14 -0
  206. package/dist/esm/common/types.d.ts.map +1 -0
  207. package/dist/esm/common/types.js +2 -0
  208. package/dist/esm/common/types.js.map +1 -0
  209. package/dist/esm/index.d.ts +2 -0
  210. package/dist/esm/index.d.ts.map +1 -0
  211. package/dist/esm/index.js +2 -0
  212. package/dist/esm/index.js.map +1 -0
  213. package/dist/esm/shape/annotate.d.ts +57 -0
  214. package/dist/esm/shape/annotate.d.ts.map +1 -0
  215. package/dist/esm/shape/annotate.js +34 -0
  216. package/dist/esm/shape/annotate.js.map +1 -0
  217. package/dist/esm/shape/annotation.d.ts +39 -0
  218. package/dist/esm/shape/annotation.d.ts.map +1 -0
  219. package/dist/esm/shape/annotation.js +2 -0
  220. package/dist/esm/shape/annotation.js.map +1 -0
  221. package/dist/esm/shape/base.d.ts +33 -0
  222. package/dist/esm/shape/base.d.ts.map +1 -0
  223. package/dist/esm/shape/base.js +20 -0
  224. package/dist/esm/shape/base.js.map +1 -0
  225. package/dist/esm/shape/builder.d.ts +168 -0
  226. package/dist/esm/shape/builder.d.ts.map +1 -0
  227. package/dist/esm/shape/builder.js +146 -0
  228. package/dist/esm/shape/builder.js.map +1 -0
  229. package/dist/esm/shape/error.d.ts +5 -0
  230. package/dist/esm/shape/error.d.ts.map +1 -0
  231. package/dist/esm/shape/error.js +2 -0
  232. package/dist/esm/shape/error.js.map +1 -0
  233. package/dist/esm/shape/index.d.ts +4 -0
  234. package/dist/esm/shape/index.d.ts.map +1 -0
  235. package/dist/esm/shape/index.js +4 -0
  236. package/dist/esm/shape/index.js.map +1 -0
  237. package/dist/esm/shape/number.d.ts +8 -0
  238. package/dist/esm/shape/number.d.ts.map +1 -0
  239. package/dist/esm/shape/number.js +114 -0
  240. package/dist/esm/shape/number.js.map +1 -0
  241. package/dist/esm/shape/shape.d.ts +150 -0
  242. package/dist/esm/shape/shape.d.ts.map +1 -0
  243. package/dist/esm/shape/shape.js +121 -0
  244. package/dist/esm/shape/shape.js.map +1 -0
  245. package/dist/esm/shape/tags.d.ts +4 -0
  246. package/dist/esm/shape/tags.d.ts.map +1 -0
  247. package/dist/esm/shape/tags.js +2 -0
  248. package/dist/esm/shape/tags.js.map +1 -0
  249. package/dist/esm/shape/transforms/index.d.ts +4 -0
  250. package/dist/esm/shape/transforms/index.d.ts.map +1 -0
  251. package/dist/esm/shape/transforms/index.js +4 -0
  252. package/dist/esm/shape/transforms/index.js.map +1 -0
  253. package/dist/esm/shape/transforms/json-schema/index.d.ts +3 -0
  254. package/dist/esm/shape/transforms/json-schema/index.d.ts.map +1 -0
  255. package/dist/esm/shape/transforms/json-schema/index.js +3 -0
  256. package/dist/esm/shape/transforms/json-schema/index.js.map +1 -0
  257. package/dist/esm/shape/transforms/json-schema/transform.d.ts +5 -0
  258. package/dist/esm/shape/transforms/json-schema/transform.d.ts.map +1 -0
  259. package/dist/esm/shape/transforms/json-schema/transform.js +734 -0
  260. package/dist/esm/shape/transforms/json-schema/transform.js.map +1 -0
  261. package/dist/esm/shape/transforms/json-schema/types.d.ts +87 -0
  262. package/dist/esm/shape/transforms/json-schema/types.d.ts.map +1 -0
  263. package/dist/esm/shape/transforms/json-schema/types.js +2 -0
  264. package/dist/esm/shape/transforms/json-schema/types.js.map +1 -0
  265. package/dist/esm/shape/transforms/sql/dialects/dialect.d.ts +51 -0
  266. package/dist/esm/shape/transforms/sql/dialects/dialect.d.ts.map +1 -0
  267. package/dist/esm/shape/transforms/sql/dialects/dialect.js +3 -0
  268. package/dist/esm/shape/transforms/sql/dialects/dialect.js.map +1 -0
  269. package/dist/esm/shape/transforms/sql/dialects/index.d.ts +7 -0
  270. package/dist/esm/shape/transforms/sql/dialects/index.d.ts.map +1 -0
  271. package/dist/esm/shape/transforms/sql/dialects/index.js +12 -0
  272. package/dist/esm/shape/transforms/sql/dialects/index.js.map +1 -0
  273. package/dist/esm/shape/transforms/sql/dialects/postgres.d.ts +8 -0
  274. package/dist/esm/shape/transforms/sql/dialects/postgres.d.ts.map +1 -0
  275. package/dist/esm/shape/transforms/sql/dialects/postgres.js +370 -0
  276. package/dist/esm/shape/transforms/sql/dialects/postgres.js.map +1 -0
  277. package/dist/esm/shape/transforms/sql/dialects/sqlite.d.ts +3 -0
  278. package/dist/esm/shape/transforms/sql/dialects/sqlite.d.ts.map +1 -0
  279. package/dist/esm/shape/transforms/sql/dialects/sqlite.js +315 -0
  280. package/dist/esm/shape/transforms/sql/dialects/sqlite.js.map +1 -0
  281. package/dist/esm/shape/transforms/sql/from-sql.d.ts +5 -0
  282. package/dist/esm/shape/transforms/sql/from-sql.d.ts.map +1 -0
  283. package/dist/esm/shape/transforms/sql/from-sql.js +197 -0
  284. package/dist/esm/shape/transforms/sql/from-sql.js.map +1 -0
  285. package/dist/esm/shape/transforms/sql/index.d.ts +4 -0
  286. package/dist/esm/shape/transforms/sql/index.d.ts.map +1 -0
  287. package/dist/esm/shape/transforms/sql/index.js +4 -0
  288. package/dist/esm/shape/transforms/sql/index.js.map +1 -0
  289. package/dist/esm/shape/transforms/sql/options.d.ts +6 -0
  290. package/dist/esm/shape/transforms/sql/options.d.ts.map +1 -0
  291. package/dist/esm/shape/transforms/sql/options.js +2 -0
  292. package/dist/esm/shape/transforms/sql/options.js.map +1 -0
  293. package/dist/esm/shape/transforms/sql/parser/check-decoder.d.ts +25 -0
  294. package/dist/esm/shape/transforms/sql/parser/check-decoder.d.ts.map +1 -0
  295. package/dist/esm/shape/transforms/sql/parser/check-decoder.js +412 -0
  296. package/dist/esm/shape/transforms/sql/parser/check-decoder.js.map +1 -0
  297. package/dist/esm/shape/transforms/sql/parser/create-domain.d.ts +11 -0
  298. package/dist/esm/shape/transforms/sql/parser/create-domain.d.ts.map +1 -0
  299. package/dist/esm/shape/transforms/sql/parser/create-domain.js +91 -0
  300. package/dist/esm/shape/transforms/sql/parser/create-domain.js.map +1 -0
  301. package/dist/esm/shape/transforms/sql/parser/create-table.d.ts +28 -0
  302. package/dist/esm/shape/transforms/sql/parser/create-table.d.ts.map +1 -0
  303. package/dist/esm/shape/transforms/sql/parser/create-table.js +740 -0
  304. package/dist/esm/shape/transforms/sql/parser/create-table.js.map +1 -0
  305. package/dist/esm/shape/transforms/sql/parser/create-type.d.ts +23 -0
  306. package/dist/esm/shape/transforms/sql/parser/create-type.d.ts.map +1 -0
  307. package/dist/esm/shape/transforms/sql/parser/create-type.js +72 -0
  308. package/dist/esm/shape/transforms/sql/parser/create-type.js.map +1 -0
  309. package/dist/esm/shape/transforms/sql/parser/cursor.d.ts +32 -0
  310. package/dist/esm/shape/transforms/sql/parser/cursor.d.ts.map +1 -0
  311. package/dist/esm/shape/transforms/sql/parser/cursor.js +163 -0
  312. package/dist/esm/shape/transforms/sql/parser/cursor.js.map +1 -0
  313. package/dist/esm/shape/transforms/sql/parser/default-decoder.d.ts +10 -0
  314. package/dist/esm/shape/transforms/sql/parser/default-decoder.d.ts.map +1 -0
  315. package/dist/esm/shape/transforms/sql/parser/default-decoder.js +121 -0
  316. package/dist/esm/shape/transforms/sql/parser/default-decoder.js.map +1 -0
  317. package/dist/esm/shape/transforms/sql/parser/lexer.d.ts +14 -0
  318. package/dist/esm/shape/transforms/sql/parser/lexer.d.ts.map +1 -0
  319. package/dist/esm/shape/transforms/sql/parser/lexer.js +253 -0
  320. package/dist/esm/shape/transforms/sql/parser/lexer.js.map +1 -0
  321. package/dist/esm/shape/transforms/sql/parser/pg-types.d.ts +21 -0
  322. package/dist/esm/shape/transforms/sql/parser/pg-types.d.ts.map +1 -0
  323. package/dist/esm/shape/transforms/sql/parser/pg-types.js +208 -0
  324. package/dist/esm/shape/transforms/sql/parser/pg-types.js.map +1 -0
  325. package/dist/esm/shape/transforms/sql/parser/sqlite-types.d.ts +8 -0
  326. package/dist/esm/shape/transforms/sql/parser/sqlite-types.d.ts.map +1 -0
  327. package/dist/esm/shape/transforms/sql/parser/sqlite-types.js +89 -0
  328. package/dist/esm/shape/transforms/sql/parser/sqlite-types.js.map +1 -0
  329. package/dist/esm/shape/transforms/sql/parser/statements.d.ts +9 -0
  330. package/dist/esm/shape/transforms/sql/parser/statements.d.ts.map +1 -0
  331. package/dist/esm/shape/transforms/sql/parser/statements.js +153 -0
  332. package/dist/esm/shape/transforms/sql/parser/statements.js.map +1 -0
  333. package/dist/esm/shape/transforms/sql/parser/type-spec.d.ts +12 -0
  334. package/dist/esm/shape/transforms/sql/parser/type-spec.d.ts.map +1 -0
  335. package/dist/esm/shape/transforms/sql/parser/type-spec.js +130 -0
  336. package/dist/esm/shape/transforms/sql/parser/type-spec.js.map +1 -0
  337. package/dist/esm/shape/transforms/sql/transform.d.ts +5 -0
  338. package/dist/esm/shape/transforms/sql/transform.d.ts.map +1 -0
  339. package/dist/esm/shape/transforms/sql/transform.js +258 -0
  340. package/dist/esm/shape/transforms/sql/transform.js.map +1 -0
  341. package/dist/esm/shape/transforms/typescript/index.d.ts +2 -0
  342. package/dist/esm/shape/transforms/typescript/index.d.ts.map +1 -0
  343. package/dist/esm/shape/transforms/typescript/index.js +2 -0
  344. package/dist/esm/shape/transforms/typescript/index.js.map +1 -0
  345. package/dist/esm/shape/transforms/typescript/transform.d.ts +3 -0
  346. package/dist/esm/shape/transforms/typescript/transform.d.ts.map +1 -0
  347. package/dist/esm/shape/transforms/typescript/transform.js +186 -0
  348. package/dist/esm/shape/transforms/typescript/transform.js.map +1 -0
  349. package/dist/esm/shape/validate.d.ts +7 -0
  350. package/dist/esm/shape/validate.d.ts.map +1 -0
  351. package/dist/esm/shape/validate.js +355 -0
  352. package/dist/esm/shape/validate.js.map +1 -0
  353. package/dist/esm/src/common/array.d.ts +3 -0
  354. package/dist/esm/src/common/array.d.ts.map +1 -0
  355. package/dist/esm/src/common/array.js +12 -0
  356. package/dist/esm/src/common/array.js.map +1 -0
  357. package/dist/esm/src/common/index.d.ts +6 -0
  358. package/dist/esm/src/common/index.d.ts.map +1 -0
  359. package/dist/esm/src/common/index.js +6 -0
  360. package/dist/esm/src/common/index.js.map +1 -0
  361. package/dist/esm/src/common/is.d.ts +5 -0
  362. package/dist/esm/src/common/is.d.ts.map +1 -0
  363. package/dist/esm/src/common/is.js +29 -0
  364. package/dist/esm/src/common/is.js.map +1 -0
  365. package/dist/esm/src/common/object.d.ts +4 -0
  366. package/dist/esm/src/common/object.d.ts.map +1 -0
  367. package/dist/esm/src/common/object.js +15 -0
  368. package/dist/esm/src/common/object.js.map +1 -0
  369. package/dist/esm/src/common/phantom.d.ts +2 -0
  370. package/dist/esm/src/common/phantom.d.ts.map +1 -0
  371. package/dist/esm/src/common/phantom.js +2 -0
  372. package/dist/esm/src/common/phantom.js.map +1 -0
  373. package/dist/esm/src/common/result.d.ts +22 -0
  374. package/dist/esm/src/common/result.d.ts.map +1 -0
  375. package/dist/esm/src/common/result.js +25 -0
  376. package/dist/esm/src/common/result.js.map +1 -0
  377. package/dist/esm/src/common/string.d.ts +3 -0
  378. package/dist/esm/src/common/string.d.ts.map +1 -0
  379. package/dist/esm/src/common/string.js +28 -0
  380. package/dist/esm/src/common/string.js.map +1 -0
  381. package/dist/esm/src/common/types.d.ts +14 -0
  382. package/dist/esm/src/common/types.d.ts.map +1 -0
  383. package/dist/esm/src/common/types.js +2 -0
  384. package/dist/esm/src/common/types.js.map +1 -0
  385. package/dist/esm/src/index.d.ts +2 -0
  386. package/dist/esm/src/index.d.ts.map +1 -0
  387. package/dist/esm/src/index.js +2 -0
  388. package/dist/esm/src/index.js.map +1 -0
  389. package/dist/esm/src/shape/annotate.d.ts +57 -0
  390. package/dist/esm/src/shape/annotate.d.ts.map +1 -0
  391. package/dist/esm/src/shape/annotate.js +34 -0
  392. package/dist/esm/src/shape/annotate.js.map +1 -0
  393. package/dist/esm/src/shape/annotation.d.ts +39 -0
  394. package/dist/esm/src/shape/annotation.d.ts.map +1 -0
  395. package/dist/esm/src/shape/annotation.js +2 -0
  396. package/dist/esm/src/shape/annotation.js.map +1 -0
  397. package/dist/esm/src/shape/base.d.ts +33 -0
  398. package/dist/esm/src/shape/base.d.ts.map +1 -0
  399. package/dist/esm/src/shape/base.js +20 -0
  400. package/dist/esm/src/shape/base.js.map +1 -0
  401. package/dist/esm/src/shape/builder.d.ts +168 -0
  402. package/dist/esm/src/shape/builder.d.ts.map +1 -0
  403. package/dist/esm/src/shape/builder.js +146 -0
  404. package/dist/esm/src/shape/builder.js.map +1 -0
  405. package/dist/esm/src/shape/error.d.ts +5 -0
  406. package/dist/esm/src/shape/error.d.ts.map +1 -0
  407. package/dist/esm/src/shape/error.js +2 -0
  408. package/dist/esm/src/shape/error.js.map +1 -0
  409. package/dist/esm/src/shape/index.d.ts +4 -0
  410. package/dist/esm/src/shape/index.d.ts.map +1 -0
  411. package/dist/esm/src/shape/index.js +4 -0
  412. package/dist/esm/src/shape/index.js.map +1 -0
  413. package/dist/esm/src/shape/number.d.ts +8 -0
  414. package/dist/esm/src/shape/number.d.ts.map +1 -0
  415. package/dist/esm/src/shape/number.js +114 -0
  416. package/dist/esm/src/shape/number.js.map +1 -0
  417. package/dist/esm/src/shape/shape.d.ts +150 -0
  418. package/dist/esm/src/shape/shape.d.ts.map +1 -0
  419. package/dist/esm/src/shape/shape.js +121 -0
  420. package/dist/esm/src/shape/shape.js.map +1 -0
  421. package/dist/esm/src/shape/tags.d.ts +4 -0
  422. package/dist/esm/src/shape/tags.d.ts.map +1 -0
  423. package/dist/esm/src/shape/tags.js +2 -0
  424. package/dist/esm/src/shape/tags.js.map +1 -0
  425. package/dist/esm/src/shape/transforms/index.d.ts +4 -0
  426. package/dist/esm/src/shape/transforms/index.d.ts.map +1 -0
  427. package/dist/esm/src/shape/transforms/index.js +4 -0
  428. package/dist/esm/src/shape/transforms/index.js.map +1 -0
  429. package/dist/esm/src/shape/transforms/json-schema/index.d.ts +3 -0
  430. package/dist/esm/src/shape/transforms/json-schema/index.d.ts.map +1 -0
  431. package/dist/esm/src/shape/transforms/json-schema/index.js +3 -0
  432. package/dist/esm/src/shape/transforms/json-schema/index.js.map +1 -0
  433. package/dist/esm/src/shape/transforms/json-schema/transform.d.ts +5 -0
  434. package/dist/esm/src/shape/transforms/json-schema/transform.d.ts.map +1 -0
  435. package/dist/esm/src/shape/transforms/json-schema/transform.js +734 -0
  436. package/dist/esm/src/shape/transforms/json-schema/transform.js.map +1 -0
  437. package/dist/esm/src/shape/transforms/json-schema/types.d.ts +87 -0
  438. package/dist/esm/src/shape/transforms/json-schema/types.d.ts.map +1 -0
  439. package/dist/esm/src/shape/transforms/json-schema/types.js +2 -0
  440. package/dist/esm/src/shape/transforms/json-schema/types.js.map +1 -0
  441. package/dist/esm/src/shape/transforms/sql/dialects/dialect.d.ts +51 -0
  442. package/dist/esm/src/shape/transforms/sql/dialects/dialect.d.ts.map +1 -0
  443. package/dist/esm/src/shape/transforms/sql/dialects/dialect.js +3 -0
  444. package/dist/esm/src/shape/transforms/sql/dialects/dialect.js.map +1 -0
  445. package/dist/esm/src/shape/transforms/sql/dialects/index.d.ts +7 -0
  446. package/dist/esm/src/shape/transforms/sql/dialects/index.d.ts.map +1 -0
  447. package/dist/esm/src/shape/transforms/sql/dialects/index.js +12 -0
  448. package/dist/esm/src/shape/transforms/sql/dialects/index.js.map +1 -0
  449. package/dist/esm/src/shape/transforms/sql/dialects/postgres.d.ts +8 -0
  450. package/dist/esm/src/shape/transforms/sql/dialects/postgres.d.ts.map +1 -0
  451. package/dist/esm/src/shape/transforms/sql/dialects/postgres.js +370 -0
  452. package/dist/esm/src/shape/transforms/sql/dialects/postgres.js.map +1 -0
  453. package/dist/esm/src/shape/transforms/sql/dialects/sqlite.d.ts +3 -0
  454. package/dist/esm/src/shape/transforms/sql/dialects/sqlite.d.ts.map +1 -0
  455. package/dist/esm/src/shape/transforms/sql/dialects/sqlite.js +315 -0
  456. package/dist/esm/src/shape/transforms/sql/dialects/sqlite.js.map +1 -0
  457. package/dist/esm/src/shape/transforms/sql/from-sql.d.ts +5 -0
  458. package/dist/esm/src/shape/transforms/sql/from-sql.d.ts.map +1 -0
  459. package/dist/esm/src/shape/transforms/sql/from-sql.js +197 -0
  460. package/dist/esm/src/shape/transforms/sql/from-sql.js.map +1 -0
  461. package/dist/esm/src/shape/transforms/sql/index.d.ts +4 -0
  462. package/dist/esm/src/shape/transforms/sql/index.d.ts.map +1 -0
  463. package/dist/esm/src/shape/transforms/sql/index.js +4 -0
  464. package/dist/esm/src/shape/transforms/sql/index.js.map +1 -0
  465. package/dist/esm/src/shape/transforms/sql/options.d.ts +6 -0
  466. package/dist/esm/src/shape/transforms/sql/options.d.ts.map +1 -0
  467. package/dist/esm/src/shape/transforms/sql/options.js +2 -0
  468. package/dist/esm/src/shape/transforms/sql/options.js.map +1 -0
  469. package/dist/esm/src/shape/transforms/sql/parser/check-decoder.d.ts +25 -0
  470. package/dist/esm/src/shape/transforms/sql/parser/check-decoder.d.ts.map +1 -0
  471. package/dist/esm/src/shape/transforms/sql/parser/check-decoder.js +412 -0
  472. package/dist/esm/src/shape/transforms/sql/parser/check-decoder.js.map +1 -0
  473. package/dist/esm/src/shape/transforms/sql/parser/create-domain.d.ts +11 -0
  474. package/dist/esm/src/shape/transforms/sql/parser/create-domain.d.ts.map +1 -0
  475. package/dist/esm/src/shape/transforms/sql/parser/create-domain.js +91 -0
  476. package/dist/esm/src/shape/transforms/sql/parser/create-domain.js.map +1 -0
  477. package/dist/esm/src/shape/transforms/sql/parser/create-table.d.ts +28 -0
  478. package/dist/esm/src/shape/transforms/sql/parser/create-table.d.ts.map +1 -0
  479. package/dist/esm/src/shape/transforms/sql/parser/create-table.js +740 -0
  480. package/dist/esm/src/shape/transforms/sql/parser/create-table.js.map +1 -0
  481. package/dist/esm/src/shape/transforms/sql/parser/create-type.d.ts +23 -0
  482. package/dist/esm/src/shape/transforms/sql/parser/create-type.d.ts.map +1 -0
  483. package/dist/esm/src/shape/transforms/sql/parser/create-type.js +72 -0
  484. package/dist/esm/src/shape/transforms/sql/parser/create-type.js.map +1 -0
  485. package/dist/esm/src/shape/transforms/sql/parser/cursor.d.ts +32 -0
  486. package/dist/esm/src/shape/transforms/sql/parser/cursor.d.ts.map +1 -0
  487. package/dist/esm/src/shape/transforms/sql/parser/cursor.js +163 -0
  488. package/dist/esm/src/shape/transforms/sql/parser/cursor.js.map +1 -0
  489. package/dist/esm/src/shape/transforms/sql/parser/default-decoder.d.ts +10 -0
  490. package/dist/esm/src/shape/transforms/sql/parser/default-decoder.d.ts.map +1 -0
  491. package/dist/esm/src/shape/transforms/sql/parser/default-decoder.js +121 -0
  492. package/dist/esm/src/shape/transforms/sql/parser/default-decoder.js.map +1 -0
  493. package/dist/esm/src/shape/transforms/sql/parser/lexer.d.ts +14 -0
  494. package/dist/esm/src/shape/transforms/sql/parser/lexer.d.ts.map +1 -0
  495. package/dist/esm/src/shape/transforms/sql/parser/lexer.js +253 -0
  496. package/dist/esm/src/shape/transforms/sql/parser/lexer.js.map +1 -0
  497. package/dist/esm/src/shape/transforms/sql/parser/pg-types.d.ts +21 -0
  498. package/dist/esm/src/shape/transforms/sql/parser/pg-types.d.ts.map +1 -0
  499. package/dist/esm/src/shape/transforms/sql/parser/pg-types.js +208 -0
  500. package/dist/esm/src/shape/transforms/sql/parser/pg-types.js.map +1 -0
  501. package/dist/esm/src/shape/transforms/sql/parser/sqlite-types.d.ts +8 -0
  502. package/dist/esm/src/shape/transforms/sql/parser/sqlite-types.d.ts.map +1 -0
  503. package/dist/esm/src/shape/transforms/sql/parser/sqlite-types.js +89 -0
  504. package/dist/esm/src/shape/transforms/sql/parser/sqlite-types.js.map +1 -0
  505. package/dist/esm/src/shape/transforms/sql/parser/statements.d.ts +9 -0
  506. package/dist/esm/src/shape/transforms/sql/parser/statements.d.ts.map +1 -0
  507. package/dist/esm/src/shape/transforms/sql/parser/statements.js +153 -0
  508. package/dist/esm/src/shape/transforms/sql/parser/statements.js.map +1 -0
  509. package/dist/esm/src/shape/transforms/sql/parser/type-spec.d.ts +12 -0
  510. package/dist/esm/src/shape/transforms/sql/parser/type-spec.d.ts.map +1 -0
  511. package/dist/esm/src/shape/transforms/sql/parser/type-spec.js +130 -0
  512. package/dist/esm/src/shape/transforms/sql/parser/type-spec.js.map +1 -0
  513. package/dist/esm/src/shape/transforms/sql/transform.d.ts +5 -0
  514. package/dist/esm/src/shape/transforms/sql/transform.d.ts.map +1 -0
  515. package/dist/esm/src/shape/transforms/sql/transform.js +258 -0
  516. package/dist/esm/src/shape/transforms/sql/transform.js.map +1 -0
  517. package/dist/esm/src/shape/transforms/typescript/index.d.ts +2 -0
  518. package/dist/esm/src/shape/transforms/typescript/index.d.ts.map +1 -0
  519. package/dist/esm/src/shape/transforms/typescript/index.js +2 -0
  520. package/dist/esm/src/shape/transforms/typescript/index.js.map +1 -0
  521. package/dist/esm/src/shape/transforms/typescript/transform.d.ts +3 -0
  522. package/dist/esm/src/shape/transforms/typescript/transform.d.ts.map +1 -0
  523. package/dist/esm/src/shape/transforms/typescript/transform.js +186 -0
  524. package/dist/esm/src/shape/transforms/typescript/transform.js.map +1 -0
  525. package/dist/esm/src/shape/validate.d.ts +7 -0
  526. package/dist/esm/src/shape/validate.d.ts.map +1 -0
  527. package/dist/esm/src/shape/validate.js +355 -0
  528. package/dist/esm/src/shape/validate.js.map +1 -0
  529. package/package.json +40 -0
  530. package/src/common/array.test.ts +19 -0
  531. package/src/common/array.ts +15 -0
  532. package/src/common/index.ts +5 -0
  533. package/src/common/is.ts +23 -0
  534. package/src/common/object.ts +35 -0
  535. package/src/common/phantom.ts +1 -0
  536. package/src/common/result.ts +43 -0
  537. package/src/common/string.ts +28 -0
  538. package/src/common/types.ts +34 -0
  539. package/src/index.ts +1 -0
  540. package/src/shape/annotate.ts +139 -0
  541. package/src/shape/annotation.ts +47 -0
  542. package/src/shape/base.ts +71 -0
  543. package/src/shape/builder.test.ts +728 -0
  544. package/src/shape/builder.ts +475 -0
  545. package/src/shape/error.ts +4 -0
  546. package/src/shape/index.ts +3 -0
  547. package/src/shape/number.ts +118 -0
  548. package/src/shape/shape.test.ts +792 -0
  549. package/src/shape/shape.ts +377 -0
  550. package/src/shape/tags.ts +14 -0
  551. package/src/shape/transforms/index.ts +3 -0
  552. package/src/shape/transforms/json-schema/index.ts +2 -0
  553. package/src/shape/transforms/json-schema/transform.test.ts +850 -0
  554. package/src/shape/transforms/json-schema/transform.ts +882 -0
  555. package/src/shape/transforms/json-schema/types.ts +132 -0
  556. package/src/shape/transforms/sql/dialects/dialect.ts +89 -0
  557. package/src/shape/transforms/sql/dialects/index.ts +14 -0
  558. package/src/shape/transforms/sql/dialects/postgres.ts +392 -0
  559. package/src/shape/transforms/sql/dialects/sqlite.ts +333 -0
  560. package/src/shape/transforms/sql/from-sql.test.ts +704 -0
  561. package/src/shape/transforms/sql/from-sql.ts +210 -0
  562. package/src/shape/transforms/sql/index.ts +3 -0
  563. package/src/shape/transforms/sql/options.ts +6 -0
  564. package/src/shape/transforms/sql/parser/check-decoder.ts +457 -0
  565. package/src/shape/transforms/sql/parser/create-domain.ts +105 -0
  566. package/src/shape/transforms/sql/parser/create-table.ts +809 -0
  567. package/src/shape/transforms/sql/parser/create-type.ts +91 -0
  568. package/src/shape/transforms/sql/parser/cursor.ts +179 -0
  569. package/src/shape/transforms/sql/parser/default-decoder.ts +129 -0
  570. package/src/shape/transforms/sql/parser/lexer.ts +289 -0
  571. package/src/shape/transforms/sql/parser/pg-types.ts +247 -0
  572. package/src/shape/transforms/sql/parser/sqlite-types.ts +103 -0
  573. package/src/shape/transforms/sql/parser/statements.ts +127 -0
  574. package/src/shape/transforms/sql/parser/type-spec.ts +159 -0
  575. package/src/shape/transforms/sql/transform.sqlite.test.ts +448 -0
  576. package/src/shape/transforms/sql/transform.test.ts +880 -0
  577. package/src/shape/transforms/sql/transform.ts +295 -0
  578. package/src/shape/transforms/typescript/index.ts +1 -0
  579. package/src/shape/transforms/typescript/transform.ts +211 -0
  580. package/src/shape/tuple.test.ts +171 -0
  581. package/src/shape/validate.ts +413 -0
  582. package/tsconfig.cjs.json +11 -0
  583. package/tsconfig.esm.json +10 -0
  584. package/tsconfig.json +23 -0
@@ -0,0 +1,792 @@
1
+ import { describe, expect } from "vitest";
2
+ import { NumberTag } from "./tags";
3
+ import { annotate, shapes } from "./shape";
4
+
5
+ function expectToBe<Input, Value extends Input>(
6
+ input: Input,
7
+ value: Value,
8
+ ): asserts input is Value {
9
+ return expect(input).toBe(value);
10
+ }
11
+
12
+ describe("shapes.auto", (it) => {
13
+ it("returns the correct shape for numbers", () => {
14
+ const samples: Array<{ value: number; tag: NumberTag }> = [
15
+ { value: 0, tag: "uint8" },
16
+ { value: 0.5, tag: "float32" },
17
+ { value: -0.5, tag: "float32" },
18
+ { value: 0xffffffff, tag: "uint32" },
19
+ { value: -0xffffffff, tag: "int64" },
20
+ { value: 0xfffffffff, tag: "uint64" },
21
+ { value: -0xfffffffff, tag: "int64" },
22
+ ];
23
+
24
+ samples.forEach((sample) => {
25
+ const shape = shapes.auto(sample.value);
26
+ expectToBe(shape.type, "number");
27
+ expectToBe(shape.tag, sample.tag);
28
+ });
29
+ });
30
+
31
+ it("returns nil for null input", () => {
32
+ const shape = shapes.auto(null);
33
+ expectToBe(shape.type, "nil");
34
+ });
35
+
36
+ it("returns undefined-shape for undefined input", () => {
37
+ const shape = shapes.auto(undefined);
38
+ expectToBe(shape.type, "undefined");
39
+ });
40
+
41
+ it("returns string shape for string input", () => {
42
+ const shape = shapes.auto("hello");
43
+ expectToBe(shape.type, "string");
44
+ });
45
+
46
+ it("returns boolean shape for boolean input", () => {
47
+ const shape = shapes.auto(true);
48
+ expectToBe(shape.type, "boolean");
49
+ });
50
+
51
+ it("returns date shape for Date input", () => {
52
+ const shape = shapes.auto(new Date());
53
+ expectToBe(shape.type, "date");
54
+ });
55
+
56
+ it("returns binary shape for Uint8Array input", () => {
57
+ const shape = shapes.auto(new Uint8Array([1, 2, 3]));
58
+ expectToBe(shape.type, "binary");
59
+ });
60
+
61
+ it("returns unknown shape for unsupported input (e.g. functions)", () => {
62
+ const shape = shapes.auto(() => {});
63
+ expectToBe(shape.type, "unknown");
64
+ });
65
+
66
+ it("returns an array of inferred numeric tag for homogenous number arrays", () => {
67
+ const shape = shapes.auto([1, 2, 3]);
68
+ expectToBe(shape.type, "array");
69
+ if (shape.input.type !== "number") {
70
+ throw new Error("expected array item to be a number shape");
71
+ }
72
+ expectToBe(shape.input.tag, "uint8");
73
+ });
74
+
75
+ it("widens the numeric tag across a homogenous number array", () => {
76
+ const shape = shapes.auto([1, 0xffff, 0.5]);
77
+ expectToBe(shape.type, "array");
78
+ if (shape.input.type !== "number") {
79
+ throw new Error("expected array item to be a number shape");
80
+ }
81
+ expectToBe(shape.input.tag, "float64");
82
+ });
83
+
84
+ it("infers item shape from a single-element array", () => {
85
+ const shape = shapes.auto(["only"]);
86
+ expectToBe(shape.type, "array");
87
+ expectToBe(shape.input.type, "string");
88
+ });
89
+
90
+ it("returns array<union> for heterogeneous arrays with multiple elements", () => {
91
+ const shape = shapes.auto(["a", 1]);
92
+ expectToBe(shape.type, "array");
93
+ expectToBe(shape.input.type, "union");
94
+ });
95
+
96
+ it("returns a mapping shape for plain objects", () => {
97
+ const shape = shapes.auto({ a: 1, b: "two", c: true });
98
+ expectToBe(shape.type, "mapping");
99
+ expect(Object.keys(shape.input).sort()).toEqual(["a", "b", "c"]);
100
+ expectToBe(shape.input.a!.type, "number");
101
+ expectToBe(shape.input.b!.type, "string");
102
+ expectToBe(shape.input.c!.type, "boolean");
103
+ });
104
+
105
+ it("recurses into nested objects and arrays", () => {
106
+ const shape = shapes.auto({ nested: { count: 5 }, tags: ["x"] });
107
+ expectToBe(shape.type, "mapping");
108
+ const nested = shape.input.nested!;
109
+ expectToBe(nested.type, "mapping");
110
+ if (nested.type !== "mapping") return;
111
+ expectToBe(nested.input.count!.type, "number");
112
+ const tags = shape.input.tags!;
113
+ expectToBe(tags.type, "array");
114
+ if (tags.type !== "array") return;
115
+ expectToBe(tags.input.type, "string");
116
+ });
117
+
118
+ it("produces literal number shapes when literalNumbers is true", () => {
119
+ const shape = shapes.auto(42, { literalNumbers: true });
120
+ expectToBe(shape.type, "number");
121
+ if (shape.type !== "number") return;
122
+ expect((shape as any).literal).toBe(true);
123
+ expect(shape.input).toBe(42);
124
+ });
125
+
126
+ it("produces literal string shapes when literalStrings is true", () => {
127
+ const shape = shapes.auto("hi", { literalStrings: true });
128
+ expectToBe(shape.type, "string");
129
+ if (shape.type !== "string") return;
130
+ expect((shape as any).literal).toBe(true);
131
+ expect(shape.input).toBe("hi");
132
+ });
133
+
134
+ it("produces literal boolean shapes when literalBooleans is true", () => {
135
+ const shape = shapes.auto(false, { literalBooleans: true });
136
+ expectToBe(shape.type, "boolean");
137
+ if (shape.type !== "boolean") return;
138
+ expect((shape as any).literal).toBe(true);
139
+ expect(shape.input).toBe(false);
140
+ });
141
+
142
+ it("does not produce literals by default", () => {
143
+ const shape = shapes.auto(7);
144
+ expect((shape as any).literal).toBeUndefined();
145
+ });
146
+ });
147
+
148
+ describe("scalar shape constructors", (it) => {
149
+ it("builds primitive shapes with the correct type tag", () => {
150
+ expectToBe(shapes.string().type, "string");
151
+ expectToBe(shapes.boolean().type, "boolean");
152
+ expectToBe(shapes.notDefined().type, "undefined");
153
+ expectToBe(shapes.date().type, "date");
154
+ expectToBe(shapes.nil().type, "nil");
155
+ expectToBe(shapes.unknown().type, "unknown");
156
+ expectToBe(shapes.binary().type, "binary");
157
+ });
158
+
159
+ it("marks shapes as shape values with empty default annotations", () => {
160
+ const s = shapes.string();
161
+ expect(s._shape).toBe(true);
162
+ expect(s.anno).toEqual({});
163
+ });
164
+
165
+ it("attaches the matching number tag for each numeric constructor", () => {
166
+ expectToBe(shapes.number().tag, "number");
167
+ expectToBe(shapes.int().tag, "int");
168
+ expectToBe(shapes.int8().tag, "int8");
169
+ expectToBe(shapes.uint8().tag, "uint8");
170
+ expectToBe(shapes.int16().tag, "int16");
171
+ expectToBe(shapes.uint16().tag, "uint16");
172
+ expectToBe(shapes.int32().tag, "int32");
173
+ expectToBe(shapes.uint32().tag, "uint32");
174
+ expectToBe(shapes.int64().tag, "int64");
175
+ expectToBe(shapes.uint64().tag, "uint64");
176
+ expectToBe(shapes.float().tag, "float");
177
+ expectToBe(shapes.float32().tag, "float32");
178
+ expectToBe(shapes.float64().tag, "float64");
179
+ });
180
+ });
181
+
182
+ describe("shapes.literal", (it) => {
183
+ it("creates a literal string shape carrying its input value", () => {
184
+ const s = shapes.literal("foo");
185
+ expectToBe(s.type, "string");
186
+ if (s.type !== "string") return;
187
+ expect(s.literal).toBe(true);
188
+ expect(s.input).toBe("foo");
189
+ });
190
+
191
+ it("creates a literal number shape carrying its input value", () => {
192
+ const s = shapes.literal(123);
193
+ expectToBe(s.type, "number");
194
+ if (s.type !== "number") return;
195
+ expect(s.literal).toBe(true);
196
+ expect(s.input).toBe(123);
197
+ });
198
+
199
+ it("creates a literal boolean shape carrying its input value", () => {
200
+ const s = shapes.literal(true);
201
+ expectToBe(s.type, "boolean");
202
+ if (s.type !== "boolean") return;
203
+ expect(s.literal).toBe(true);
204
+ expect(s.input).toBe(true);
205
+ });
206
+
207
+ it("throws when given a non-literal-eligible value", () => {
208
+ expect(() => shapes.literal(null as any)).toThrow();
209
+ });
210
+ });
211
+
212
+ describe("container shape constructors", (it) => {
213
+ it("array stores the item shape on input", () => {
214
+ const item = shapes.string();
215
+ const s = shapes.array(item);
216
+ expectToBe(s.type, "array");
217
+ expect(s.input).toBe(item);
218
+ });
219
+
220
+ it("mapping stores the record of shapes on input", () => {
221
+ const rec = { a: shapes.number(), b: shapes.string() };
222
+ const s = shapes.mapping(rec);
223
+ expectToBe(s.type, "mapping");
224
+ expect(s.input).toBe(rec);
225
+ });
226
+
227
+ it("record stores its key/value shapes as a tuple on input", () => {
228
+ const k = shapes.string();
229
+ const v = shapes.number();
230
+ const s = shapes.record(k, v);
231
+ expectToBe(s.type, "record");
232
+ expect(s.input[0]).toBe(k);
233
+ expect(s.input[1]).toBe(v);
234
+ });
235
+
236
+ it("vector defaults its format to a generic number shape", () => {
237
+ const s = shapes.vector(3);
238
+ expectToBe(s.type, "vector");
239
+ expect(s.input.dims).toBe(3);
240
+ expectToBe(s.input.format.type, "number");
241
+ expectToBe(s.input.format.tag, "number");
242
+ });
243
+
244
+ it("vector accepts an explicit numeric format", () => {
245
+ const s = shapes.vector(4, shapes.float32());
246
+ expect(s.input.dims).toBe(4);
247
+ expectToBe(s.input.format.tag, "float32");
248
+ });
249
+ });
250
+
251
+ describe("shapes.union", (it) => {
252
+ it("accepts variadic arguments", () => {
253
+ const a = shapes.string();
254
+ const b = shapes.number();
255
+ const s = shapes.union(a, b);
256
+ expectToBe(s.type, "union");
257
+ expect(s.input).toEqual([a, b]);
258
+ });
259
+
260
+ it("accepts a single array of shapes", () => {
261
+ const a = shapes.string();
262
+ const b = shapes.number();
263
+ const s = shapes.union([a, b]);
264
+ expectToBe(s.type, "union");
265
+ expect(s.input).toEqual([a, b]);
266
+ });
267
+ });
268
+
269
+ describe("annotate", (it) => {
270
+ it("annotate.as merges annotations without mutating the source", () => {
271
+ const original = shapes.number();
272
+ const annotated = annotate.as(original, { min: 0, max: 10 });
273
+ expect(annotated.anno).toEqual({ min: 0, max: 10 });
274
+ expect(original.anno).toEqual({});
275
+ expect(annotated).not.toBe(original);
276
+ });
277
+
278
+ it("annotate.as preserves prior annotations when merging", () => {
279
+ const base = annotate.as(shapes.number(), { min: 0 });
280
+ const merged = annotate.as(base, { max: 5 });
281
+ expect(merged.anno).toEqual({ min: 0, max: 5 });
282
+ });
283
+
284
+ it("annotate.as overrides overlapping annotation fields", () => {
285
+ const base = annotate.as(shapes.number(), { min: 0 });
286
+ const merged = annotate.as(base, { min: 10 });
287
+ expectToBe(merged.anno.min, 10);
288
+ });
289
+
290
+ it("annotate.optional sets optional=true", () => {
291
+ const s = annotate.optional(shapes.string());
292
+ expect(s.anno.optional).toBe(true);
293
+ });
294
+
295
+ it("annotate preserves the underlying shape type and input", () => {
296
+ const inner = shapes.string();
297
+ const arr = shapes.array(inner);
298
+ const annotated = annotate.optional(arr);
299
+ expectToBe(annotated.type, "array");
300
+ expect(annotated.input).toBe(inner);
301
+ });
302
+ });
303
+
304
+ describe("shapes.validate — scalars", (it) => {
305
+ it("returns no errors when a string matches a string shape", () => {
306
+ expect(shapes.validate(shapes.string(), "hello")).toEqual([]);
307
+ });
308
+
309
+ it("flags a non-string against a string shape", () => {
310
+ const errors = shapes.validate(shapes.string(), 42);
311
+ expect(errors).toHaveLength(1);
312
+ expect(errors[0]!.path).toEqual([]);
313
+ expect(errors[0]!.message).toMatch(/string/);
314
+ });
315
+
316
+ it("returns no errors when a boolean matches a boolean shape", () => {
317
+ expect(shapes.validate(shapes.boolean(), true)).toEqual([]);
318
+ expect(shapes.validate(shapes.boolean(), false)).toEqual([]);
319
+ });
320
+
321
+ it("flags a non-boolean against a boolean shape", () => {
322
+ const errors = shapes.validate(shapes.boolean(), "true");
323
+ expect(errors).toHaveLength(1);
324
+ expect(errors[0]!.message).toMatch(/boolean/);
325
+ });
326
+
327
+ it("returns no errors when null matches a nil shape", () => {
328
+ expect(shapes.validate(shapes.nil(), null)).toEqual([]);
329
+ });
330
+
331
+ it("flags a non-null value against a nil shape", () => {
332
+ const errors = shapes.validate(shapes.nil(), 0);
333
+ expect(errors).toHaveLength(1);
334
+ expect(errors[0]!.message).toMatch(/nil/);
335
+ });
336
+
337
+ it("returns no errors when undefined matches an undefined shape", () => {
338
+ expect(shapes.validate(shapes.notDefined(), undefined)).toEqual([]);
339
+ });
340
+
341
+ it("flags a defined value against an undefined shape", () => {
342
+ const errors = shapes.validate(shapes.notDefined(), null);
343
+ expect(errors).toHaveLength(1);
344
+ });
345
+
346
+ it("returns no errors when a Date matches a date shape", () => {
347
+ expect(shapes.validate(shapes.date(), new Date())).toEqual([]);
348
+ });
349
+
350
+ it("flags a non-Date against a date shape", () => {
351
+ const errors = shapes.validate(shapes.date(), "2026-01-01");
352
+ expect(errors).toHaveLength(1);
353
+ expect(errors[0]!.message).toMatch(/date/);
354
+ });
355
+
356
+ it("accepts any value against an unknown shape", () => {
357
+ expect(shapes.validate(shapes.unknown(), 1)).toEqual([]);
358
+ expect(shapes.validate(shapes.unknown(), "x")).toEqual([]);
359
+ expect(shapes.validate(shapes.unknown(), null)).toEqual([]);
360
+ expect(shapes.validate(shapes.unknown(), { a: 1 })).toEqual([]);
361
+ });
362
+ });
363
+
364
+ describe("shapes.validate — numbers", (it) => {
365
+ it("returns no errors when a number matches a generic number shape", () => {
366
+ expect(shapes.validate(shapes.number(), 42)).toEqual([]);
367
+ expect(shapes.validate(shapes.number(), -1.5)).toEqual([]);
368
+ });
369
+
370
+ it("flags a non-number against a number shape", () => {
371
+ const errors = shapes.validate(shapes.number(), "42");
372
+ expect(errors).toHaveLength(1);
373
+ expect(errors[0]!.message).toMatch(/number/);
374
+ });
375
+
376
+ it("accepts a value that fits the requested integer tag", () => {
377
+ expect(shapes.validate(shapes.uint8(), 200)).toEqual([]);
378
+ expect(shapes.validate(shapes.int16(), -1000)).toEqual([]);
379
+ });
380
+
381
+ it("rejects a value that exceeds the requested integer tag's range", () => {
382
+ const errors = shapes.validate(shapes.uint8(), 0xffff);
383
+ expect(errors).toHaveLength(1);
384
+ expect(errors[0]!.message).toMatch(/format/);
385
+ });
386
+
387
+ it("rejects a float when an integer tag is required", () => {
388
+ const errors = shapes.validate(shapes.uint8(), 0.5);
389
+ expect(errors).toHaveLength(1);
390
+ expect(errors[0]!.message).toMatch(/format/);
391
+ });
392
+
393
+ it("accepts an int that fits inside a float32 tag", () => {
394
+ // int tags cannot be cast to float tags directly per numberTagCanBeCastedTo,
395
+ // so a uint8 input should fail against float32.
396
+ const errors = shapes.validate(shapes.float32(), 1);
397
+ expect(errors).toHaveLength(1);
398
+ });
399
+
400
+ it("accepts a float that fits inside float32", () => {
401
+ expect(shapes.validate(shapes.float32(), 0.5)).toEqual([]);
402
+ });
403
+ });
404
+
405
+ describe("shapes.validate — literals", (it) => {
406
+ it("accepts the matching literal string", () => {
407
+ expect(shapes.validate(shapes.literal("foo"), "foo")).toEqual([]);
408
+ });
409
+
410
+ it("rejects a non-matching literal string", () => {
411
+ const errors = shapes.validate(shapes.literal("foo"), "bar");
412
+ expect(errors).toHaveLength(1);
413
+ expect(errors[0]!.message).toMatch(/literal/);
414
+ });
415
+
416
+ it("accepts the matching literal number", () => {
417
+ expect(shapes.validate(shapes.literal(7), 7)).toEqual([]);
418
+ });
419
+
420
+ it("rejects a non-matching literal number", () => {
421
+ const errors = shapes.validate(shapes.literal(7), 8);
422
+ expect(errors).toHaveLength(1);
423
+ expect(errors[0]!.message).toMatch(/literal/);
424
+ });
425
+
426
+ it("accepts the matching literal boolean", () => {
427
+ expect(shapes.validate(shapes.literal(true), true)).toEqual([]);
428
+ });
429
+
430
+ it("rejects a non-matching literal boolean", () => {
431
+ const errors = shapes.validate(shapes.literal(true), false);
432
+ expect(errors).toHaveLength(1);
433
+ expect(errors[0]!.message).toMatch(/literal/);
434
+ });
435
+ });
436
+
437
+ describe("shapes.validate — binary", (it) => {
438
+ it("accepts a Uint8Array against a binary shape", () => {
439
+ expect(shapes.validate(shapes.binary(), new Uint8Array([1, 2, 3]))).toEqual(
440
+ [],
441
+ );
442
+ });
443
+
444
+ it("accepts an array of uint8-fitting numbers against a binary shape", () => {
445
+ expect(shapes.validate(shapes.binary(), [0, 127, 255])).toEqual([]);
446
+ });
447
+
448
+ it("rejects an array containing a non-uint8 value against a binary shape", () => {
449
+ const errors = shapes.validate(shapes.binary(), [0, 256]);
450
+ expect(errors.length).toBeGreaterThan(0);
451
+ expect(errors[0]!.path).toEqual([1]);
452
+ });
453
+
454
+ it("rejects a non-array, non-Uint8Array against a binary shape", () => {
455
+ const errors = shapes.validate(shapes.binary(), "not binary");
456
+ expect(errors).toHaveLength(1);
457
+ expect(errors[0]!.message).toMatch(/binary/);
458
+ });
459
+ });
460
+
461
+ describe("shapes.validate — array", (it) => {
462
+ it("accepts an array whose items all match the item shape", () => {
463
+ expect(shapes.validate(shapes.array(shapes.string()), ["a", "b"])).toEqual(
464
+ [],
465
+ );
466
+ });
467
+
468
+ it("accepts an empty array regardless of item shape", () => {
469
+ expect(shapes.validate(shapes.array(shapes.string()), [])).toEqual([]);
470
+ });
471
+
472
+ it("rejects a non-array input", () => {
473
+ const errors = shapes.validate(shapes.array(shapes.string()), "abc");
474
+ expect(errors).toHaveLength(1);
475
+ expect(errors[0]!.message).toMatch(/array/);
476
+ });
477
+
478
+ it("reports the index of an invalid item in the path", () => {
479
+ const errors = shapes.validate(shapes.array(shapes.string()), [
480
+ "a",
481
+ 1,
482
+ "c",
483
+ ]);
484
+ expect(errors.length).toBeGreaterThan(0);
485
+ expect(errors[0]!.path).toEqual([1]);
486
+ });
487
+ });
488
+
489
+ describe("shapes.validate — vector", (it) => {
490
+ it("accepts an array whose length matches dims and items fit the format", () => {
491
+ expect(
492
+ shapes.validate(shapes.vector(3, shapes.uint8()), [1, 2, 3]),
493
+ ).toEqual([]);
494
+ });
495
+
496
+ it("rejects a non-array input", () => {
497
+ const errors = shapes.validate(shapes.vector(3), "nope");
498
+ expect(errors).toHaveLength(1);
499
+ expect(errors[0]!.message).toMatch(/vector/);
500
+ });
501
+
502
+ it("rejects a length mismatch", () => {
503
+ const errors = shapes.validate(shapes.vector(3), [1, 2]);
504
+ expect(errors).toHaveLength(1);
505
+ expect(errors[0]!.message).toMatch(/dimensions/);
506
+ });
507
+
508
+ it("reports the index of a format-mismatched item", () => {
509
+ const errors = shapes.validate(
510
+ shapes.vector(3, shapes.uint8()),
511
+ [1, 999, 3],
512
+ );
513
+ expect(errors.length).toBeGreaterThan(0);
514
+ expect(errors[0]!.path).toEqual([1]);
515
+ });
516
+ });
517
+
518
+ describe("shapes.validate — mapping", (it) => {
519
+ it("accepts an object where every required key validates", () => {
520
+ const shape = shapes.mapping({
521
+ a: shapes.string(),
522
+ b: shapes.number(),
523
+ });
524
+ expect(shapes.validate(shape, { a: "x", b: 1 })).toEqual([]);
525
+ });
526
+
527
+ it("rejects a non-object input", () => {
528
+ const shape = shapes.mapping({ a: shapes.string() });
529
+ const errors = shapes.validate(shape, "not an object");
530
+ expect(errors).toHaveLength(1);
531
+ expect(errors[0]!.message).toMatch(/mapping/);
532
+ });
533
+
534
+ it("rejects null against a mapping shape", () => {
535
+ const shape = shapes.mapping({ a: shapes.string() });
536
+ const errors = shapes.validate(shape, null);
537
+ expect(errors).toHaveLength(1);
538
+ expect(errors[0]!.message).toMatch(/mapping/);
539
+ });
540
+
541
+ it("reports a missing required key with the key in the path", () => {
542
+ const shape = shapes.mapping({
543
+ a: shapes.string(),
544
+ b: shapes.number(),
545
+ });
546
+ const errors = shapes.validate(shape, { a: "x" });
547
+ expect(errors).toHaveLength(1);
548
+ expect(errors[0]!.path).toEqual(["b"]);
549
+ expect(errors[0]!.message).toMatch(/Missing required key/);
550
+ });
551
+
552
+ it("allows a missing optional key", () => {
553
+ const shape = shapes.mapping({
554
+ a: shapes.string(),
555
+ b: annotate.optional(shapes.number()),
556
+ });
557
+ expect(shapes.validate(shape, { a: "x" })).toEqual([]);
558
+ });
559
+
560
+ it("reports value-shape errors with the key in the path", () => {
561
+ const shape = shapes.mapping({
562
+ a: shapes.string(),
563
+ b: shapes.number(),
564
+ });
565
+ const errors = shapes.validate(shape, { a: "x", b: "not a number" });
566
+ expect(errors).toHaveLength(1);
567
+ expect(errors[0]!.path).toEqual(["b"]);
568
+ });
569
+
570
+ it("walks the path into nested mappings", () => {
571
+ const shape = shapes.mapping({
572
+ outer: shapes.mapping({
573
+ inner: shapes.number(),
574
+ }) as unknown as shapes.Shape,
575
+ });
576
+ const errors = shapes.validate(shape, { outer: { inner: "oops" } });
577
+ expect(errors).toHaveLength(1);
578
+ expect(errors[0]!.path).toEqual(["outer", "inner"]);
579
+ });
580
+ });
581
+
582
+ describe("shapes.validate — record", (it) => {
583
+ it("accepts an object whose keys and values all validate", () => {
584
+ const shape = shapes.record(shapes.string(), shapes.number());
585
+ expect(shapes.validate(shape, { a: 1, b: 2 })).toEqual([]);
586
+ });
587
+
588
+ it("rejects a non-object input", () => {
589
+ const shape = shapes.record(shapes.string(), shapes.number());
590
+ const errors = shapes.validate(shape, 1);
591
+ expect(errors).toHaveLength(1);
592
+ expect(errors[0]!.message).toMatch(/record/);
593
+ });
594
+
595
+ it("rejects null against a record shape", () => {
596
+ const shape = shapes.record(shapes.string(), shapes.number());
597
+ const errors = shapes.validate(shape, null);
598
+ expect(errors).toHaveLength(1);
599
+ });
600
+
601
+ it("reports a value-shape error with the key in the path", () => {
602
+ const shape = shapes.record(shapes.string(), shapes.number());
603
+ const errors = shapes.validate(shape, { a: 1, b: "no" });
604
+ expect(errors.length).toBeGreaterThan(0);
605
+ expect(errors[0]!.path).toEqual(["b"]);
606
+ });
607
+
608
+ it("accepts an empty object", () => {
609
+ const shape = shapes.record(shapes.string(), shapes.number());
610
+ expect(shapes.validate(shape, {})).toEqual([]);
611
+ });
612
+ });
613
+
614
+ describe("shapes.validate — union", (it) => {
615
+ it("accepts a value matching any variant", () => {
616
+ const shape = shapes.union(shapes.string(), shapes.number());
617
+ expect(shapes.validate(shape, "hi")).toEqual([]);
618
+ expect(shapes.validate(shape, 1)).toEqual([]);
619
+ });
620
+
621
+ it("rejects a value matching no variant and collects errors from each", () => {
622
+ const shape = shapes.union(shapes.string(), shapes.number());
623
+ const errors = shapes.validate(shape, true);
624
+ expect(errors.length).toBeGreaterThanOrEqual(2);
625
+ });
626
+ });
627
+
628
+ describe("shapes.validate — min/max", (it) => {
629
+ it("accepts a number within [min, max]", () => {
630
+ const shape = annotate.as(shapes.number(), { min: 0, max: 10 });
631
+ expect(shapes.validate(shape, 0)).toEqual([]);
632
+ expect(shapes.validate(shape, 5)).toEqual([]);
633
+ expect(shapes.validate(shape, 10)).toEqual([]);
634
+ });
635
+
636
+ it("rejects a number below min", () => {
637
+ const shape = annotate.as(shapes.number(), { min: 0 });
638
+ const errors = shapes.validate(shape, -1);
639
+ expect(errors).toHaveLength(1);
640
+ expect(errors[0]!.message).toMatch(/>= 0/);
641
+ });
642
+
643
+ it("rejects a number above max", () => {
644
+ const shape = annotate.as(shapes.number(), { max: 10 });
645
+ const errors = shapes.validate(shape, 11);
646
+ expect(errors).toHaveLength(1);
647
+ expect(errors[0]!.message).toMatch(/<= 10/);
648
+ });
649
+
650
+ it("checks the number format before applying bounds", () => {
651
+ // "foo" fails the type check first; bounds should not run on a non-number
652
+ const shape = annotate.as(shapes.number(), { min: 0, max: 10 });
653
+ const errors = shapes.validate(shape, "foo");
654
+ expect(errors).toHaveLength(1);
655
+ expect(errors[0]!.message).toMatch(/number/);
656
+ });
657
+
658
+ it("accepts a string whose length is within [min, max]", () => {
659
+ const shape = annotate.as(shapes.string(), { min: 2, max: 4 });
660
+ expect(shapes.validate(shape, "ab")).toEqual([]);
661
+ expect(shapes.validate(shape, "abc")).toEqual([]);
662
+ expect(shapes.validate(shape, "abcd")).toEqual([]);
663
+ });
664
+
665
+ it("rejects a string shorter than min", () => {
666
+ const shape = annotate.as(shapes.string(), { min: 2 });
667
+ const errors = shapes.validate(shape, "a");
668
+ expect(errors).toHaveLength(1);
669
+ expect(errors[0]!.message).toMatch(/string length/);
670
+ expect(errors[0]!.message).toMatch(/>= 2/);
671
+ });
672
+
673
+ it("rejects a string longer than max", () => {
674
+ const shape = annotate.as(shapes.string(), { max: 3 });
675
+ const errors = shapes.validate(shape, "abcd");
676
+ expect(errors).toHaveLength(1);
677
+ expect(errors[0]!.message).toMatch(/string length/);
678
+ expect(errors[0]!.message).toMatch(/<= 3/);
679
+ });
680
+
681
+ it("accepts an array whose length is within [min, max]", () => {
682
+ const shape = annotate.as(shapes.array(shapes.number()), {
683
+ min: 1,
684
+ max: 3,
685
+ });
686
+ expect(shapes.validate(shape, [1])).toEqual([]);
687
+ expect(shapes.validate(shape, [1, 2])).toEqual([]);
688
+ expect(shapes.validate(shape, [1, 2, 3])).toEqual([]);
689
+ });
690
+
691
+ it("rejects an array shorter than min", () => {
692
+ const shape = annotate.as(shapes.array(shapes.number()), { min: 2 });
693
+ const errors = shapes.validate(shape, [1]);
694
+ expect(errors).toHaveLength(1);
695
+ expect(errors[0]!.message).toMatch(/array length/);
696
+ expect(errors[0]!.message).toMatch(/>= 2/);
697
+ });
698
+
699
+ it("rejects an array longer than max", () => {
700
+ const shape = annotate.as(shapes.array(shapes.number()), { max: 2 });
701
+ const errors = shapes.validate(shape, [1, 2, 3]);
702
+ expect(errors).toHaveLength(1);
703
+ expect(errors[0]!.message).toMatch(/array length/);
704
+ expect(errors[0]!.message).toMatch(/<= 2/);
705
+ });
706
+
707
+ it("reports bounds errors at the shape's path inside a nested mapping", () => {
708
+ const shape = shapes.mapping({
709
+ name: annotate.as(shapes.string(), { min: 3 }),
710
+ });
711
+ const errors = shapes.validate(shape, { name: "no" });
712
+ expect(errors).toHaveLength(1);
713
+ expect(errors[0]!.path).toEqual(["name"]);
714
+ });
715
+
716
+ it("ignores min/max on shapes where they don't apply (e.g. boolean)", () => {
717
+ const shape = annotate.as(shapes.boolean(), { min: 100, max: 200 });
718
+ expect(shapes.validate(shape, true)).toEqual([]);
719
+ });
720
+ });
721
+
722
+ describe("shapes.validate — pattern", (it) => {
723
+ it("accepts a string matching a RegExp pattern", () => {
724
+ const shape = annotate.pattern(shapes.string(), /^[a-z]+$/);
725
+ expect(shapes.validate(shape, "abc")).toEqual([]);
726
+ });
727
+
728
+ it("rejects a string not matching a RegExp pattern", () => {
729
+ const shape = annotate.pattern(shapes.string(), /^[a-z]+$/);
730
+ const errors = shapes.validate(shape, "abc123");
731
+ expect(errors).toHaveLength(1);
732
+ expect(errors[0]!.message).toMatch(/pattern/);
733
+ });
734
+
735
+ it("accepts a string matching a string-source pattern", () => {
736
+ const shape = annotate.pattern(shapes.string(), "^[A-Z]{3}$");
737
+ expect(shapes.validate(shape, "USD")).toEqual([]);
738
+ });
739
+
740
+ it("rejects a string not matching a string-source pattern", () => {
741
+ const shape = annotate.pattern(shapes.string(), "^[A-Z]{3}$");
742
+ const errors = shapes.validate(shape, "usd");
743
+ expect(errors).toHaveLength(1);
744
+ expect(errors[0]!.message).toMatch(/pattern/);
745
+ });
746
+
747
+ it("checks type before pattern", () => {
748
+ const shape = annotate.pattern(shapes.string(), /^[a-z]+$/);
749
+ const errors = shapes.validate(shape, 5);
750
+ expect(errors).toHaveLength(1);
751
+ expect(errors[0]!.message).toMatch(/string/);
752
+ });
753
+
754
+ it("reports pattern errors at the shape's path inside a nested mapping", () => {
755
+ const shape = shapes.mapping({
756
+ slug: annotate.pattern(shapes.string(), /^[a-z-]+$/),
757
+ });
758
+ const errors = shapes.validate(shape, { slug: "Bad Slug" });
759
+ expect(errors).toHaveLength(1);
760
+ expect(errors[0]!.path).toEqual(["slug"]);
761
+ });
762
+
763
+ it("composes with min/max — bounds error takes precedence", () => {
764
+ const shape = annotate.as(shapes.string(), {
765
+ min: 3,
766
+ pattern: /^[a-z]+$/,
767
+ });
768
+ const errors = shapes.validate(shape, "a");
769
+ expect(errors).toHaveLength(1);
770
+ expect(errors[0]!.message).toMatch(/string length/);
771
+ });
772
+ });
773
+
774
+ describe("shapes.validate — paths", (it) => {
775
+ it("uses [] as the path for a top-level scalar mismatch", () => {
776
+ const errors = shapes.validate(shapes.string(), 1);
777
+ expect(errors[0]!.path).toEqual([]);
778
+ });
779
+
780
+ it("threads indices and keys through nested arrays and mappings", () => {
781
+ const shape = shapes.mapping({
782
+ items: shapes.array(
783
+ shapes.mapping({ name: shapes.string() }) as unknown as shapes.Shape,
784
+ ),
785
+ });
786
+ const errors = shapes.validate(shape, {
787
+ items: [{ name: "ok" }, { name: 5 }],
788
+ });
789
+ expect(errors).toHaveLength(1);
790
+ expect(errors[0]!.path).toEqual(["items", 1, "name"]);
791
+ });
792
+ });