@xano/sdk 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 (336) hide show
  1. package/CHANGELOG.md +788 -0
  2. package/LICENSE +21 -0
  3. package/README.md +541 -0
  4. package/dist/.build-fingerprint +1 -0
  5. package/dist/agent-file-refresh-ZEMK33AX.js +38 -0
  6. package/dist/answer-shape-K67TAAPY.js +33 -0
  7. package/dist/backend-dir-2U53CIAL.js +39 -0
  8. package/dist/backend-slot-7QXW2QYC.js +28 -0
  9. package/dist/bin.d.ts +1 -0
  10. package/dist/bin.js +255 -0
  11. package/dist/branch-NCRNWQBQ.js +61 -0
  12. package/dist/branch-commands-ACIRCEQJ.js +79 -0
  13. package/dist/bundle.d.ts +223 -0
  14. package/dist/bundle.js +153 -0
  15. package/dist/capture-WAXPD7DR.js +41 -0
  16. package/dist/chunk-27GWNP2I.js +23 -0
  17. package/dist/chunk-2CMJZDCL.js +177 -0
  18. package/dist/chunk-2EZ3ZJZZ.js +302 -0
  19. package/dist/chunk-2GNFDZA2.js +390 -0
  20. package/dist/chunk-2MNLRIOX.js +11 -0
  21. package/dist/chunk-2TFRR6JV.js +104 -0
  22. package/dist/chunk-2ZUEE4EK.js +408 -0
  23. package/dist/chunk-36JUQZVQ.js +22 -0
  24. package/dist/chunk-3DRXWLJ5.js +83 -0
  25. package/dist/chunk-3JDU4VRL.js +137 -0
  26. package/dist/chunk-3KZCLN4Z.js +241 -0
  27. package/dist/chunk-3LDULPRE.js +168 -0
  28. package/dist/chunk-3M4LFYNQ.js +111 -0
  29. package/dist/chunk-3XI5CTUE.js +22 -0
  30. package/dist/chunk-3YW23UFH.js +50 -0
  31. package/dist/chunk-45UIT5T2.js +862 -0
  32. package/dist/chunk-4BW2SG2N.js +46 -0
  33. package/dist/chunk-4KHEMC32.js +79 -0
  34. package/dist/chunk-4POWHT2K.js +321 -0
  35. package/dist/chunk-4Q2GN7NW.js +192 -0
  36. package/dist/chunk-5A2PLKZB.js +70 -0
  37. package/dist/chunk-5FBYXK5P.js +159 -0
  38. package/dist/chunk-5HVXPTU4.js +323 -0
  39. package/dist/chunk-5QU2P5CA.js +304 -0
  40. package/dist/chunk-5V5XU32D.js +191 -0
  41. package/dist/chunk-5ZSO4T2G.js +10 -0
  42. package/dist/chunk-622HUCZT.js +10 -0
  43. package/dist/chunk-65HWOMGV.js +177 -0
  44. package/dist/chunk-6ELFRN3P.js +365 -0
  45. package/dist/chunk-6HO3NCSJ.js +1055 -0
  46. package/dist/chunk-6IUMKYWI.js +457 -0
  47. package/dist/chunk-6KEB3C3U.js +65 -0
  48. package/dist/chunk-6MR5TI5V.js +987 -0
  49. package/dist/chunk-6NNTNXN7.js +157 -0
  50. package/dist/chunk-6PBR37LN.js +97 -0
  51. package/dist/chunk-6QXLMMT3.js +155 -0
  52. package/dist/chunk-6ZGJCBZS.js +224 -0
  53. package/dist/chunk-73IVBKMA.js +250 -0
  54. package/dist/chunk-7G3CTU7I.js +286 -0
  55. package/dist/chunk-A3UDOZB6.js +222 -0
  56. package/dist/chunk-A6E77GDW.js +85 -0
  57. package/dist/chunk-AHJWCYQO.js +660 -0
  58. package/dist/chunk-AKNCFVKZ.js +36 -0
  59. package/dist/chunk-AM4FKL4J.js +237 -0
  60. package/dist/chunk-AN6BL47T.js +26 -0
  61. package/dist/chunk-AOSYVMUS.js +147 -0
  62. package/dist/chunk-APWXY5SL.js +182 -0
  63. package/dist/chunk-AWEIIR2U.js +218 -0
  64. package/dist/chunk-AWQ7BQTQ.js +73 -0
  65. package/dist/chunk-BAUZOWGX.js +393 -0
  66. package/dist/chunk-BHACRS6R.js +940 -0
  67. package/dist/chunk-BWPNT55T.js +680 -0
  68. package/dist/chunk-C6RIMRU4.js +187 -0
  69. package/dist/chunk-CGVQZXYG.js +263 -0
  70. package/dist/chunk-CIMQZRRE.js +162 -0
  71. package/dist/chunk-CJHQKJU4.js +113 -0
  72. package/dist/chunk-CTMO46PK.js +1897 -0
  73. package/dist/chunk-D53J55C5.js +106 -0
  74. package/dist/chunk-D7VGG3WS.js +90 -0
  75. package/dist/chunk-DAD3ONIS.js +245 -0
  76. package/dist/chunk-DGWHAVRG.js +162 -0
  77. package/dist/chunk-DX4QR4B2.js +483 -0
  78. package/dist/chunk-EHP3WPEG.js +21 -0
  79. package/dist/chunk-ELP2HMXC.js +432 -0
  80. package/dist/chunk-ERVIASGL.js +21 -0
  81. package/dist/chunk-ET4Y4XCB.js +865 -0
  82. package/dist/chunk-ETO6LGLD.js +4750 -0
  83. package/dist/chunk-EUUUMY7J.js +24 -0
  84. package/dist/chunk-FQJ2TTHP.js +218 -0
  85. package/dist/chunk-FQOF7E2E.js +133 -0
  86. package/dist/chunk-FWD7AL6N.js +21 -0
  87. package/dist/chunk-FXFV3KU6.js +138 -0
  88. package/dist/chunk-FXRQOWTE.js +171 -0
  89. package/dist/chunk-G554NZNI.js +210 -0
  90. package/dist/chunk-GSGDWJB5.js +13 -0
  91. package/dist/chunk-H2V3N23D.js +66 -0
  92. package/dist/chunk-H5C7MBCR.js +159 -0
  93. package/dist/chunk-HHN734BU.js +371 -0
  94. package/dist/chunk-HRVBLCVJ.js +243 -0
  95. package/dist/chunk-HVRUQXGD.js +1264 -0
  96. package/dist/chunk-I4F5TCJH.js +130 -0
  97. package/dist/chunk-IDOTCMDV.js +57 -0
  98. package/dist/chunk-IGOLHKWF.js +427 -0
  99. package/dist/chunk-JGE7CAWB.js +148 -0
  100. package/dist/chunk-JTUKLCXS.js +92 -0
  101. package/dist/chunk-JZGVVJSI.js +66 -0
  102. package/dist/chunk-K4WX6UUU.js +923 -0
  103. package/dist/chunk-K5BBGTYZ.js +217 -0
  104. package/dist/chunk-K6RXBGUB.js +427 -0
  105. package/dist/chunk-KTSDSD36.js +165 -0
  106. package/dist/chunk-L5JYN3NM.js +1038 -0
  107. package/dist/chunk-LIEOKXKD.js +354 -0
  108. package/dist/chunk-LLNZGEFK.js +51 -0
  109. package/dist/chunk-LPECSJ2J.js +55 -0
  110. package/dist/chunk-LQCMKAJ7.js +413 -0
  111. package/dist/chunk-LRN4ZJCQ.js +1145 -0
  112. package/dist/chunk-MJ4ZVHKN.js +17 -0
  113. package/dist/chunk-MXHSQOC4.js +3061 -0
  114. package/dist/chunk-N5GKCWE5.js +367 -0
  115. package/dist/chunk-NA3PXMEF.js +10 -0
  116. package/dist/chunk-NAQDMEHV.js +76 -0
  117. package/dist/chunk-NWKXM5RD.js +109 -0
  118. package/dist/chunk-NZOWWHU5.js +196 -0
  119. package/dist/chunk-OHX6MIUZ.js +184 -0
  120. package/dist/chunk-OOXWYAA4.js +15 -0
  121. package/dist/chunk-OPHB5ORL.js +1990 -0
  122. package/dist/chunk-OXA6PSZT.js +1725 -0
  123. package/dist/chunk-P2HAGF6H.js +73 -0
  124. package/dist/chunk-PTHVMXZI.js +3036 -0
  125. package/dist/chunk-PZ5AY32C.js +10 -0
  126. package/dist/chunk-Q325JKYB.js +189 -0
  127. package/dist/chunk-Q7DGTQ5G.js +255 -0
  128. package/dist/chunk-QCNYHBL7.js +601 -0
  129. package/dist/chunk-QO6BVGS5.js +145 -0
  130. package/dist/chunk-QXTKSOFI.js +76 -0
  131. package/dist/chunk-ROY4YAEQ.js +66 -0
  132. package/dist/chunk-RTJRZFFY.js +447 -0
  133. package/dist/chunk-SAVJUS2X.js +128 -0
  134. package/dist/chunk-SFLHVCKX.js +173 -0
  135. package/dist/chunk-STSFNCY4.js +127 -0
  136. package/dist/chunk-SWBF2LTK.js +170 -0
  137. package/dist/chunk-T5KELPAR.js +109 -0
  138. package/dist/chunk-TFFGOFVZ.js +1481 -0
  139. package/dist/chunk-TLHIFK4M.js +256 -0
  140. package/dist/chunk-TLQE7ZN3.js +156 -0
  141. package/dist/chunk-TPHWJ7UG.js +1981 -0
  142. package/dist/chunk-TRJCALW3.js +291 -0
  143. package/dist/chunk-TTEIYD5P.js +133 -0
  144. package/dist/chunk-U64O2MXY.js +407 -0
  145. package/dist/chunk-UCQ2VUTG.js +630 -0
  146. package/dist/chunk-UTI5G6OJ.js +44 -0
  147. package/dist/chunk-UVHDMMIP.js +188 -0
  148. package/dist/chunk-UZ6QQWJT.js +120 -0
  149. package/dist/chunk-VAX3UZOY.js +686 -0
  150. package/dist/chunk-W3HBUKFO.js +57 -0
  151. package/dist/chunk-WKQLGKCL.js +2823 -0
  152. package/dist/chunk-WQFNASK4.js +560 -0
  153. package/dist/chunk-WRBKLYSJ.js +224 -0
  154. package/dist/chunk-WTPZRR4I.js +17 -0
  155. package/dist/chunk-WZDJ2LLX.js +2385 -0
  156. package/dist/chunk-X2NL4KUO.js +14 -0
  157. package/dist/chunk-X4DVXBFY.js +38 -0
  158. package/dist/chunk-X677DMZM.js +7050 -0
  159. package/dist/chunk-XBKMWY7F.js +612 -0
  160. package/dist/chunk-XNCP4KYO.js +78 -0
  161. package/dist/chunk-XVBGLISP.js +35 -0
  162. package/dist/chunk-XW6KISBB.js +1192 -0
  163. package/dist/chunk-YGZHHAAB.js +8156 -0
  164. package/dist/chunk-YHEFQUQB.js +186 -0
  165. package/dist/chunk-YLDALTWZ.js +653 -0
  166. package/dist/chunk-YU4HSQW7.js +229 -0
  167. package/dist/chunk-ZDPP6RKB.js +27 -0
  168. package/dist/chunk-ZFDZKNGG.js +194 -0
  169. package/dist/chunk-ZIY7RNUT.js +49 -0
  170. package/dist/chunk-ZYJP6BOO.js +30 -0
  171. package/dist/cli.d.ts +1111 -0
  172. package/dist/cli.js +165 -0
  173. package/dist/codegen-command-VR2GWR6C.js +173 -0
  174. package/dist/codegen.d.ts +115 -0
  175. package/dist/codegen.js +19 -0
  176. package/dist/commands-GJMJ4XYZ.js +76 -0
  177. package/dist/completion-ZQLO6PB6.js +738 -0
  178. package/dist/config-MBYGCAFK.js +136 -0
  179. package/dist/deploy-command-JVZPWHMK.js +180 -0
  180. package/dist/deploy-source-3W45CXMP.js +81 -0
  181. package/dist/dev-env-sync-HN44K4D5.js +188 -0
  182. package/dist/diagnostics-UEAAHWVF.js +30 -0
  183. package/dist/display-name-hint-ABBPVQIR.js +46 -0
  184. package/dist/emit-CyhBDxli.d.ts +7007 -0
  185. package/dist/env-example-refresh-ET5HMMDW.js +126 -0
  186. package/dist/env-pull-command-TNMNB3CV.js +323 -0
  187. package/dist/env-target-O4HRKTGZ.js +40 -0
  188. package/dist/env-var-command-ZIRDCAZA.js +427 -0
  189. package/dist/ephemeral-P7F3PMAD.js +54 -0
  190. package/dist/ephemeral-command-CLJJKOFT.js +592 -0
  191. package/dist/ephemeral-state-PYCBSOGX.js +61 -0
  192. package/dist/file-lock-PT74GWYW.js +10 -0
  193. package/dist/generate-command-AYEOLA26.js +510 -0
  194. package/dist/gitignore-3SJ3WNRG.js +51 -0
  195. package/dist/guards-4EBNCZDC.js +162 -0
  196. package/dist/hosted-file-PSHJB3HX.js +28 -0
  197. package/dist/impersonate-command-5JAS3WSV.js +152 -0
  198. package/dist/import-EQSFU6JC.js +19 -0
  199. package/dist/index.d.ts +5470 -0
  200. package/dist/index.js +371 -0
  201. package/dist/init-command-X2FR4UAK.js +125 -0
  202. package/dist/init-modules-RY7UHAOL.js +50 -0
  203. package/dist/init-web-M4YZSZK6.js +42 -0
  204. package/dist/internal.d.ts +179 -0
  205. package/dist/internal.js +2634 -0
  206. package/dist/io-RC56QSN5.js +26 -0
  207. package/dist/keep-data-merge-7MPLVAVI.js +1119 -0
  208. package/dist/lambda-config-reconcile-OUZ4OYAB.js +116 -0
  209. package/dist/landed-753YLJ5H.js +40 -0
  210. package/dist/landing-record-SU52SKXU.js +61 -0
  211. package/dist/live-diff-YONW2VI3.js +65 -0
  212. package/dist/local-engine-choice-CH5X3W7E.js +79 -0
  213. package/dist/local-engine-command-Z3OL7VOD.js +766 -0
  214. package/dist/local-engine-config-5U3SC434.js +39 -0
  215. package/dist/local-engine-deploy-PCQ4SNPB.js +39 -0
  216. package/dist/local-engine-process-EHTE5LLU.js +63 -0
  217. package/dist/local-engine-state-A4FTRFAF.js +32 -0
  218. package/dist/local-engine-update-check-6L645VBL.js +162 -0
  219. package/dist/lock-MRRHW5GS.js +87 -0
  220. package/dist/lock-commands-2QG25HL7.js +963 -0
  221. package/dist/login-command-QPYRWOXZ.js +538 -0
  222. package/dist/logout-command-WOIQLDP6.js +56 -0
  223. package/dist/loop-ALIZLOSX.js +191 -0
  224. package/dist/marketplace-command-K5YL42NO.js +977 -0
  225. package/dist/marketplace-resolve-LY32JES5.js +40 -0
  226. package/dist/meta-client-YXGPW53C.js +244 -0
  227. package/dist/module-manifest-JFGHU2TC.js +38 -0
  228. package/dist/near-key.d.ts +13 -0
  229. package/dist/near-key.js +8 -0
  230. package/dist/node.d.ts +95 -0
  231. package/dist/node.js +969 -0
  232. package/dist/operation-outcome-TZSESNC7.js +51 -0
  233. package/dist/output-target-AL3I44GG.js +47 -0
  234. package/dist/package-manager-PRAHUSCN.js +34 -0
  235. package/dist/plan-disclosure-6G4MLZKD.js +114 -0
  236. package/dist/plugin-contributions-WRNY5ABG.js +28 -0
  237. package/dist/plugin-prompt-4VA3B4FF.js +20 -0
  238. package/dist/plugin-questions-JTSYA74Q.js +24 -0
  239. package/dist/plugin.d.ts +396 -0
  240. package/dist/plugin.js +1 -0
  241. package/dist/preflight-command-2T5Z36MI.js +321 -0
  242. package/dist/profile-command-AH3PIM4X.js +800 -0
  243. package/dist/profile-pointer-GRWJU3YD.js +31 -0
  244. package/dist/profile-select-74TRDEPD.js +23 -0
  245. package/dist/project-dependency-KSH63ODT.js +35 -0
  246. package/dist/project-sdk-REPPOIBD.js +24 -0
  247. package/dist/promote-command-PCWT5N6S.js +140 -0
  248. package/dist/prompt-II3F3LND.js +27 -0
  249. package/dist/publish-command-TTDUUJI5.js +414 -0
  250. package/dist/pull-command-VBO7C4S3.js +161 -0
  251. package/dist/pull-superseded-GJWLG7XO.js +20 -0
  252. package/dist/release-command-N4ZPKMHR.js +146 -0
  253. package/dist/release-ns-command-3KFDMZ6G.js +1745 -0
  254. package/dist/response-HlXahv4K.d.ts +925 -0
  255. package/dist/retry-command-AS5EVREX.js +34 -0
  256. package/dist/routes-manifest-SNWUVBT6.js +43 -0
  257. package/dist/runtime-XETHVF33.js +14 -0
  258. package/dist/scaffold.d.ts +1911 -0
  259. package/dist/scaffold.js +107 -0
  260. package/dist/secrets-file-LVZD6IIM.js +56 -0
  261. package/dist/secrets-fill-command-TTCPSVXN.js +218 -0
  262. package/dist/seed-VU7C3QYS.js +46 -0
  263. package/dist/sent-writes-N7X4OVXT.js +22 -0
  264. package/dist/source-resolve-S2XA3XZF.js +83 -0
  265. package/dist/static-host-B2Y6AG3W.js +352 -0
  266. package/dist/status-command-RUDXTF7I.js +554 -0
  267. package/dist/store-6VNCD4D7.js +20 -0
  268. package/dist/store-ARM6VMO5.js +98 -0
  269. package/dist/store-DuYfzKlW.d.ts +3144 -0
  270. package/dist/suggest-6FOOYKHG.js +12 -0
  271. package/dist/sveltekit.d.ts +154 -0
  272. package/dist/sveltekit.js +109 -0
  273. package/dist/sync-contributions-UCEROO26.js +415 -0
  274. package/dist/table-ENAVMITR.js +42 -0
  275. package/dist/tables-command-GUPXXSB5.js +156 -0
  276. package/dist/tenant-IIHPOHGP.js +42 -0
  277. package/dist/tenant-command-D5HGI2X4.js +965 -0
  278. package/dist/test-command-TIKZMDPZ.js +476 -0
  279. package/dist/tests-BGGIOK3L.js +26 -0
  280. package/dist/token-NICJUTMT.js +72 -0
  281. package/dist/toolchain-hooks-GHKLUJOH.js +96 -0
  282. package/dist/toolchain-modules-5EAZUONB.js +24 -0
  283. package/dist/tracked-backend-EIBUMDZA.js +80 -0
  284. package/dist/update-check-2W2NLDTC.js +136 -0
  285. package/dist/upgrade-command-QHNFWM7O.js +531 -0
  286. package/dist/verify-rollout-DRCK5TDD.js +61 -0
  287. package/dist/whoami-command-STGINTXH.js +51 -0
  288. package/dist/workspace-2CLHU2LK.js +93 -0
  289. package/dist/workspace-binding-56PIIPCP.js +54 -0
  290. package/dist/workspace-command-JEXQETJD.js +535 -0
  291. package/dist/workspace-env-F2RFMSC5.js +70 -0
  292. package/dist/workspace-export-OJSH2HIW.js +21 -0
  293. package/dist/writable-VA7OISSK.js +25 -0
  294. package/dist/xano-ICFUSPFR.js +42 -0
  295. package/dist/xanosdk-import-GN42TO2B.js +56 -0
  296. package/dist/xanosdk-project-S6DXJONQ.js +41 -0
  297. package/dist/xdo-CxDr2Q1C.d.ts +1371 -0
  298. package/guides/README.md +33 -0
  299. package/guides/authoring.md +921 -0
  300. package/guides/cli.md +401 -0
  301. package/guides/codegen.md +177 -0
  302. package/guides/codes.md +404 -0
  303. package/guides/coverage.md +74 -0
  304. package/guides/deploying.md +1525 -0
  305. package/guides/environment.md +400 -0
  306. package/guides/marketplace.md +415 -0
  307. package/guides/module-contract.md +558 -0
  308. package/guides/object-kinds.md +433 -0
  309. package/guides/project-structure.md +43 -0
  310. package/guides/scaffold.md +351 -0
  311. package/guides/typed-frontend.md +242 -0
  312. package/llms/client.md +63 -0
  313. package/llms/errors.md +56 -0
  314. package/llms/fields.md +176 -0
  315. package/llms/filters.md +183 -0
  316. package/llms/kinds-agent-mcp.md +30 -0
  317. package/llms/kinds-core.md +100 -0
  318. package/llms/kinds-knowledge.md +20 -0
  319. package/llms/kinds-realtime.md +76 -0
  320. package/llms/lambda.md +94 -0
  321. package/llms/legacy.md +44 -0
  322. package/llms/lock.md +40 -0
  323. package/llms/object-kinds.md +34 -0
  324. package/llms/statements-calls.md +62 -0
  325. package/llms/statements-catalog.md +320 -0
  326. package/llms/statements-data.md +66 -0
  327. package/llms/statements-runtime.md +68 -0
  328. package/llms/tests.md +59 -0
  329. package/llms/toolchain.md +16 -0
  330. package/llms/triggers.md +36 -0
  331. package/llms/values.md +29 -0
  332. package/llms-full.txt +2085 -0
  333. package/llms.txt +493 -0
  334. package/manifest.json +11224 -0
  335. package/package.json +162 -0
  336. package/types/lambda-globals.d.ts +129 -0
@@ -0,0 +1,1264 @@
1
+ import {
2
+ brandDef
3
+ } from "./chunk-ERVIASGL.js";
4
+ import {
5
+ encodeTags,
6
+ registerKind
7
+ } from "./chunk-4POWHT2K.js";
8
+ import {
9
+ nearestKey
10
+ } from "./chunk-WTPZRR4I.js";
11
+ import {
12
+ DiagnosticError,
13
+ numberedList,
14
+ problemCount
15
+ } from "./chunk-2EZ3ZJZZ.js";
16
+ import {
17
+ isHostedFile
18
+ } from "./chunk-XNCP4KYO.js";
19
+ import {
20
+ annotate,
21
+ encodeStatement,
22
+ registerStatement
23
+ } from "./chunk-YU4HSQW7.js";
24
+ import {
25
+ COLUMN_CONTEXT,
26
+ COLUMN_NULLABLE_TYPES,
27
+ authoredFieldType,
28
+ encodeField,
29
+ isListColumn
30
+ } from "./chunk-TTEIYD5P.js";
31
+ import {
32
+ argsOrEmpty,
33
+ assertArg,
34
+ assertStatements,
35
+ describeEntry,
36
+ isTaggedArg
37
+ } from "./chunk-CIMQZRRE.js";
38
+
39
+ // src/util/known-keys.ts
40
+ function assertKnownKeys(where, v, known) {
41
+ if (typeof v !== "object" || v === null || Array.isArray(v)) return;
42
+ for (const key of Object.keys(v)) {
43
+ if (known.includes(key)) continue;
44
+ const near = nearestKey(key, known);
45
+ throw new Error(
46
+ `${where}: unknown key "${key}" \u2014 ${near ? `did you mean "${near}"? It` : "it"} would be dropped on emit; expected one of: ${known.join(", ")}.`
47
+ );
48
+ }
49
+ }
50
+
51
+ // src/statements/expression.ts
52
+ var SUPPORTED_OPS = ["=", "!=", "===", "!==", ">", "<", ">=", "<="];
53
+ var OP_ALIASES = { "==": "=" };
54
+ function expr(left, op, right) {
55
+ const normalized = OP_ALIASES[op] ?? op;
56
+ if (!SUPPORTED_OPS.includes(normalized)) {
57
+ throw new Error(
58
+ `expr(): Unsupported conditional operator ${typeof op === "string" ? `"${op}"` : describeEntry(op)}. Supported: ${SUPPORTED_OPS.join(", ")} (also ==, a synonym for =)`
59
+ );
60
+ }
61
+ assertOperand("expr", "left", left);
62
+ assertOperand("expr", "right", right);
63
+ return { left, op: normalized, right };
64
+ }
65
+ function assertOperand(helper, side, v) {
66
+ if (isTaggedArg(v)) return;
67
+ throw new Error(
68
+ `${helper}(): the ${side} operand must be a value (\`c.*\`, \`ref()\`, \`inp()\`, \`col()\`, \u2026) \u2014 got ${describeEntry(v)}.`
69
+ );
70
+ }
71
+ var SEARCH_OPS = /* @__PURE__ */ new Set([
72
+ "=",
73
+ "==",
74
+ "!=",
75
+ "===",
76
+ "!==",
77
+ "<",
78
+ "<=",
79
+ ">",
80
+ ">=",
81
+ "in",
82
+ "not in",
83
+ "like",
84
+ "not like",
85
+ "ilike",
86
+ "not ilike",
87
+ "~",
88
+ "!~",
89
+ "between",
90
+ "not between",
91
+ "@>",
92
+ "contains",
93
+ "not contains",
94
+ "includes",
95
+ "not includes",
96
+ "overlaps",
97
+ "not overlaps",
98
+ "search"
99
+ ]);
100
+ function isSearchOp(op) {
101
+ return typeof op === "string" && SEARCH_OPS.has(op);
102
+ }
103
+ function cmp(left, op, right, opts) {
104
+ if (!SEARCH_OPS.has(op)) {
105
+ throw new Error(
106
+ `cmp(): unsupported operator ${typeof op === "string" ? `"${op}"` : describeEntry(op)}. Supported: ${[...SEARCH_OPS].join(", ")}.`
107
+ );
108
+ }
109
+ assertOperand("cmp", "left", left);
110
+ assertOperand("cmp", "right", right);
111
+ return { left, op, right, ignoreEmpty: opts?.ignoreEmpty };
112
+ }
113
+ function assertChildren(helper, children) {
114
+ children.forEach((child, i) => {
115
+ if (typeof child === "object" && child !== null && !Array.isArray(child)) return;
116
+ if (isTaggedArg(child)) return;
117
+ throw new Error(
118
+ `${helper}(): argument ${i + 1} must be a condition (\`cmp()\`, \`expr()\`, \`and()\`/\`or()\`) \u2014 got ${describeEntry(child)}.`
119
+ );
120
+ });
121
+ }
122
+ function and(...children) {
123
+ assertChildren("and", children);
124
+ return { or: false, children };
125
+ }
126
+ function or(...children) {
127
+ assertChildren("or", children);
128
+ return { or: true, children };
129
+ }
130
+ function mixed(first, ...rest) {
131
+ if (rest.length === 0) {
132
+ throw new Error(
133
+ "mixed(): needs at least two terms \u2014 a single term has no join to mix. Pass the node on its own, or use and()/or() for a uniform container."
134
+ );
135
+ }
136
+ for (const term of rest) {
137
+ if (typeof term !== "object" || term === null || Array.isArray(term)) {
138
+ throw new Error(
139
+ `mixed(): every term after the first is exactly one of \`{ and: node }\` or \`{ or: node }\` \u2014 got ${describeEntry(term)}.`
140
+ );
141
+ }
142
+ const keys = Object.keys(term).filter((k) => term[k] !== void 0);
143
+ if (keys.length !== 1 || keys[0] !== "and" && keys[0] !== "or") {
144
+ throw new Error(
145
+ `mixed(): every term after the first is exactly one of \`{ and: node }\` or \`{ or: node }\` \u2014 got ${JSON.stringify(keys)}.`
146
+ );
147
+ }
148
+ }
149
+ return { mixed: [first, ...rest] };
150
+ }
151
+ function isValue(w) {
152
+ return typeof w === "object" && w !== null && !Array.isArray(w) && "tag" in w && "value" in w;
153
+ }
154
+ function isGroup(w) {
155
+ return typeof w === "object" && w !== null && !Array.isArray(w) && "children" in w;
156
+ }
157
+ function isMixed(w) {
158
+ return typeof w === "object" && w !== null && !Array.isArray(w) && "mixed" in w;
159
+ }
160
+ function containerTerms(node) {
161
+ if (isMixed(node)) {
162
+ return node.mixed.map(
163
+ (term, i) => i === 0 ? { or: false, node: term } : { or: "or" in term, node: "or" in term ? term.or : term.and }
164
+ );
165
+ }
166
+ return node.children.map((child, i) => ({ or: node.or && i > 0, node: child }));
167
+ }
168
+ function isCmpNode(w) {
169
+ return typeof w === "object" && w !== null && !Array.isArray(w) && "op" in w && "left" in w;
170
+ }
171
+ function toOperand(v) {
172
+ return { operand: v.value, tag: v.tag, filters: v.filters };
173
+ }
174
+ function toStatementNode(node, or2) {
175
+ const right = toOperand(node.right);
176
+ if (node.ignoreEmpty) right.ignore_empty = true;
177
+ return {
178
+ type: "statement",
179
+ or: or2,
180
+ group: { expression: [] },
181
+ statement: { op: node.op, left: toOperand(node.left), right }
182
+ };
183
+ }
184
+ function encodeContainer(children, joinOr) {
185
+ return encodeTerms(children.map((child, i) => ({ or: joinOr && i > 0, node: child })));
186
+ }
187
+ function encodeTerms(terms) {
188
+ return terms.map(({ or: or2, node }) => {
189
+ if (isGroup(node) || isMixed(node)) {
190
+ const group = {
191
+ type: "group",
192
+ or: or2,
193
+ group: { expression: encodeTerms(containerTerms(node)) }
194
+ };
195
+ return group;
196
+ }
197
+ return toStatementNode(node, or2);
198
+ });
199
+ }
200
+ var MAX_EXPRESSION_DEPTH = 128;
201
+ function assertExpressionDepth(nodes) {
202
+ const stack = nodes.map((node) => ({ node, depth: 1 }));
203
+ while (stack.length > 0) {
204
+ const { node, depth } = stack.pop();
205
+ if (!isGroup(node) && !isMixed(node)) continue;
206
+ if (depth > MAX_EXPRESSION_DEPTH) {
207
+ throw new Error(
208
+ `condition: expression containers are nested ${depth} levels deep, past the supported limit of ${MAX_EXPRESSION_DEPTH}. Nesting costs quadratic bytes \u2014 every level re-wraps everything below it \u2014 so a deep chain exports megabytes and eventually cannot be walked at all. This is almost always a rule set folded one term at a time (\`rules.reduce((acc, r) => and(acc, r))\`); pass the terms as SIBLINGS of one container instead (\`and(...rules)\` \u2014 flat, linear, unlimited in count), or balance the tree so its depth is logarithmic. Mixing joins? Group each run: \`and(or(...anyOf), ...allOf)\`.`
209
+ );
210
+ }
211
+ for (const term of containerTerms(node)) stack.push({ node: term.node, depth: depth + 1 });
212
+ }
213
+ }
214
+ function encodeExpression(input) {
215
+ const nodes = Array.isArray(input) ? input : [input];
216
+ assertExpressionDepth(nodes);
217
+ const only = nodes.length === 1 ? nodes[0] : void 0;
218
+ if (only !== void 0 && isGroup(only) && only.or) {
219
+ return { expression: encodeContainer(only.children, true) };
220
+ }
221
+ if (only !== void 0 && isMixed(only)) {
222
+ return { expression: encodeTerms(containerTerms(only)) };
223
+ }
224
+ return { expression: encodeContainer(nodes, false) };
225
+ }
226
+ var RUNTIME_OPS = new Set(SUPPORTED_OPS);
227
+ function isRuntimeConditionOp(op) {
228
+ return typeof op === "string" && (RUNTIME_OPS.has(op) || Object.hasOwn(OP_ALIASES, op));
229
+ }
230
+ var CONDITION_HINTS = {
231
+ in: "`cond.in(value, list)`",
232
+ "not in": "`cond.notIn(value, list)`",
233
+ contains: "`cond.contains(text, needle)`",
234
+ "not contains": "`cond.notContains(text, needle)`",
235
+ includes: "`cond.contains(text, needle)`",
236
+ like: "`cond.contains(text, needle)` (or `cond.startsWith`/`cond.endsWith`)",
237
+ ilike: "`cond.icontains(text, needle)`",
238
+ between: "`cond.between(value, lo, hi)`"
239
+ };
240
+ function assertRuntimeOps(node, surface) {
241
+ if (isGroup(node) || isMixed(node)) {
242
+ for (const term of containerTerms(node)) assertRuntimeOps(term.node, surface);
243
+ return;
244
+ }
245
+ if (!isCmpNode(node)) {
246
+ throw new Error(
247
+ `${surface}: a condition must be a comparison (\`expr(left, "=", right)\`, \`cond.*\`) or an and()/or() group \u2014 got ${describeEntry(node)}.` + (isValue(node) ? ` To test a value, compare it: \`expr(value, "=", c.bool(true))\`.` : "")
248
+ );
249
+ }
250
+ const op = node.op;
251
+ if (isRuntimeConditionOp(op)) return;
252
+ throw new Error(
253
+ `${surface}: operator "${op}" is a database-search operator and cannot be evaluated in a condition \u2014 the request fails at runtime with \`Invalid op: ${op}\`. A condition evaluates ${SUPPORTED_OPS.join(", ")} (and \`==\`). Keep "${op}" for a db.query/bulk/addon \`where\`, a table view filter, or a database trigger \`search\`. In a condition, reach for \`cond.*\`, which builds the filter-then-compare form that DOES run here \u2014 ${(Object.hasOwn(CONDITION_HINTS, op) ? CONDITION_HINTS[op] : void 0) ?? "`cond.in` / `contains` / `startsWith` / `endsWith` / `empty` / `between` / `isNull`"}.`
254
+ );
255
+ }
256
+ function encodeRuntimeCondition(input, surface) {
257
+ const nodes = Array.isArray(input) ? input : [input];
258
+ assertExpressionDepth(nodes);
259
+ for (const node of nodes) assertRuntimeOps(node, surface);
260
+ return encodeExpression(input);
261
+ }
262
+ function encodeComparison(when) {
263
+ return encodeExpression(when);
264
+ }
265
+
266
+ // src/statements/conditional.ts
267
+ var CONDITIONAL = "mvp:conditional";
268
+ var CONDITIONAL_ELIF = "mvp:conditional_elif";
269
+ var ELIF_KEYS = /* @__PURE__ */ Object.keys({ when: 1, then: 1, disabled: 1, description: 1, mock: 1 });
270
+ function conditionalElif(args, where = "then") {
271
+ args = argsOrEmpty(args);
272
+ assertKnownKeys(`Statement "s.conditional"${where === "then" ? "" : `: argument "${where.replace(/\.then$/, "")}"`}`, args, ELIF_KEYS);
273
+ const label = where === "then" ? "when" : where.replace(/\.then$/, ".when");
274
+ assertArg("s.conditional", label, args.when);
275
+ assertStatements("s.conditional", where, args.then);
276
+ const context = {
277
+ expr: encodeRuntimeCondition(args.when, "s.conditional elif `when`"),
278
+ if: { run: args.then.map(encodeStatement) }
279
+ };
280
+ return annotate({ name: CONDITIONAL_ELIF, context, input: [] }, args);
281
+ }
282
+ var CONDITIONAL_KEYS = /* @__PURE__ */ Object.keys({ when: 1, then: 1, elif: 1, else: 1, disabled: 1, description: 1, mock: 1 });
283
+ function conditional(args) {
284
+ args = argsOrEmpty(args);
285
+ assertKnownKeys(`Statement "s.conditional"`, args, CONDITIONAL_KEYS);
286
+ assertArg("s.conditional", "when", args.when);
287
+ assertStatements("s.conditional", "then", args.then);
288
+ if (args.elif !== void 0 && args.elif !== null && !Array.isArray(args.elif)) {
289
+ throw new Error(
290
+ `Statement "s.conditional": argument "elif" must be an array of { when, then } branches \u2014 got ${describeEntry(args.elif)}.`
291
+ );
292
+ }
293
+ if (args.else !== void 0 && args.else !== null) assertStatements("s.conditional", "else", args.else);
294
+ const context = {
295
+ expr: encodeRuntimeCondition(args.when, "s.conditional `when`"),
296
+ if: { run: args.then.map(encodeStatement) },
297
+ elif: {
298
+ run: (args.elif ?? []).map((e, i) => {
299
+ if (e === null || typeof e !== "object") {
300
+ throw new Error(
301
+ `Statement "s.conditional": argument "elif[${i}]" must be a { when, then } branch \u2014 got ${describeEntry(e)}.`
302
+ );
303
+ }
304
+ return encodeStatement(conditionalElif(e, `elif[${i}].then`));
305
+ })
306
+ },
307
+ else: { run: (args.else ?? []).map(encodeStatement) }
308
+ };
309
+ return annotate({ name: CONDITIONAL, context, input: [] }, args);
310
+ }
311
+ registerStatement(CONDITIONAL, conditional);
312
+ registerStatement(CONDITIONAL_ELIF, conditionalElif);
313
+
314
+ // src/kinds/table.ts
315
+ var SCALAR_FAMILY = {
316
+ bool: "bool",
317
+ int: "int",
318
+ epochms: "epochms",
319
+ decimal: "decimal",
320
+ text: "text",
321
+ uuid: "text",
322
+ email: "text",
323
+ password: "text",
324
+ enum: "enum"
325
+ };
326
+ function normalizeIndexType(type) {
327
+ return type === "unique" ? "btree|unique" : type;
328
+ }
329
+ var PRIORITY_OPS = ["A", "B", "C", "D"];
330
+ var SEED_FILE = /* @__PURE__ */ Symbol.for("xanosdk.seed.file");
331
+ function seedFile(path, base) {
332
+ return { [SEED_FILE]: { path, base: typeof base === "string" ? base : base.href } };
333
+ }
334
+ function isSeedFileSource(source) {
335
+ return typeof source === "object" && source !== null && SEED_FILE in source;
336
+ }
337
+ function toColumns(schema) {
338
+ if (Array.isArray(schema)) {
339
+ return schema.map((c) => {
340
+ if (!("options" in c) || c.options === null || typeof c.options !== "object") return c;
341
+ const { name, type, options } = c;
342
+ return { name, type, ...options };
343
+ });
344
+ }
345
+ return Object.entries(schema).map(([name, d]) => ({ name, type: d.type, ...d.options }));
346
+ }
347
+ function systemColumns(idType = "int") {
348
+ return [
349
+ // A uuid primary key persists NO `default` key — the engine stores it that
350
+ // way because the value is engine-generated. An `int` key and an ordinary
351
+ // (non-key) uuid column both carry `default: ""`, so this is specific to the
352
+ // uuid key. See {@link FieldOptions.noDefault}.
353
+ // `nullable` is pinned on both, not left to the per-type default: a uuid
354
+ // column is nullable by default (see COLUMN_NULLABLE_BY_DEFAULT), but a PRIMARY KEY
355
+ // never is, and every captured `id`/`created_at` stores `nullable: false`.
356
+ {
357
+ name: "id",
358
+ type: idType,
359
+ required: true,
360
+ nullable: false,
361
+ ...idType === "uuid" ? { noDefault: true } : {}
362
+ },
363
+ { name: "created_at", type: "epochms", default: "now", access: "private", nullable: false }
364
+ ];
365
+ }
366
+ function tableColumns(def) {
367
+ const cols = toColumns(def.schema);
368
+ if (def.system === false) return cols.map((col) => primaryKeyColumn(def.name, col));
369
+ const present = new Set(cols.map((col) => col.name));
370
+ const missing = systemColumns(def.idType).filter((sc) => !present.has(sc.name));
371
+ return [...missing, ...cols.map((col) => primaryKeyColumn(def.name, col))];
372
+ }
373
+ function primaryKeyColumn(table2, col) {
374
+ if (col.name !== "id") return col;
375
+ if (col.type !== "int" && col.type !== "uuid") {
376
+ throw new Error(
377
+ `${table2 === void 0 ? "" : `table "${table2}", `}column "id" (${authoredFieldType(col.type)}): \`id\` is the table's primary key, which is an int or a uuid \u2014 any other type fails the deploy. Declare \`id: f.int()\` or \`id: f.uuid()\`, or leave it out (\`idType: "uuid"\` picks a uuid key).`
378
+ );
379
+ }
380
+ return { ...col, ...systemColumns(col.type)[0] };
381
+ }
382
+ function systemIndexes(useXdo = false) {
383
+ return [
384
+ { type: "primary", fields: [{ name: "id" }] },
385
+ ...useXdo ? [{ type: "gin", fields: [{ name: "xdo", op: "jsonb_path_op" }] }] : [],
386
+ { type: "btree", fields: [{ name: "created_at", op: "desc" }] }
387
+ ];
388
+ }
389
+ function indexSignature(def) {
390
+ return `${normalizeIndexType(def.type)}|${def.fields.map((field) => field.name).join(",")}`;
391
+ }
392
+ function tableIndexes(def) {
393
+ const declared = def.index ?? [];
394
+ if (def.system === false) return declared;
395
+ const present = new Set(declared.map(indexSignature));
396
+ const missing = systemIndexes(def.useXdo).filter((idx) => !present.has(indexSignature(idx)));
397
+ return [...missing, ...declared];
398
+ }
399
+ var SYSTEM_COLUMN_NAMES = systemColumns().map((col) => col.name);
400
+ function elideSystemIndexes(index, useXdo) {
401
+ const system = systemIndexes(useXdo);
402
+ const encoded = (list) => JSON.stringify(list.map(encodeIndex));
403
+ const target = encoded(index);
404
+ for (const subset of subsetsLargestFirst(system.length)) {
405
+ const pending = /* @__PURE__ */ new Map();
406
+ for (const position of subset) {
407
+ const signature = indexSignature(system[position]);
408
+ pending.set(signature, (pending.get(signature) ?? 0) + 1);
409
+ }
410
+ const kept = index.filter((entry) => {
411
+ const remaining = pending.get(indexSignature(entry)) ?? 0;
412
+ if (remaining === 0) return true;
413
+ pending.set(indexSignature(entry), remaining - 1);
414
+ return false;
415
+ });
416
+ if (kept.length === index.length) continue;
417
+ if (encoded(tableIndexes({ index: kept, useXdo })) === target) return kept;
418
+ }
419
+ return null;
420
+ }
421
+ function subsetsLargestFirst(n) {
422
+ const all = [];
423
+ for (let mask = 1; mask < 1 << n; mask += 1) {
424
+ const members = [];
425
+ for (let bit = 0; bit < n; bit += 1) if (mask & 1 << bit) members.push(bit);
426
+ all.push(members);
427
+ }
428
+ return all.sort((a, b) => b.length - a.length || a[0] - b[0]);
429
+ }
430
+ function encodeIndex(def) {
431
+ return {
432
+ name: def.name ?? "",
433
+ // A search index with no language fails the deploy (measured: SQL 42602);
434
+ // the engine's own default is english.
435
+ lang: def.lang || (normalizeIndexType(def.type) === "search" ? "english" : ""),
436
+ type: normalizeIndexType(def.type),
437
+ fields: def.fields.map((field) => ({ name: field.name, op: searchOp(def, field) })),
438
+ market_item: { id: 0, version: 0, guid: "" }
439
+ };
440
+ }
441
+ function searchOp(def, field) {
442
+ if (field.priority === void 0) return field.op ?? "";
443
+ if (field.op !== void 0) {
444
+ throw new Error(
445
+ `table index field "${field.name}": \`op\` and \`priority\` are two spellings of the same stored value (priority 1-4 is op "A"-"D"). Supplying both has no correct reading \u2014 drop one.`
446
+ );
447
+ }
448
+ if (normalizeIndexType(def.type) !== "search") {
449
+ throw new Error(
450
+ `table index field "${field.name}": \`priority\` is a SEARCH index's per-column weight, and this index is "${def.type}". On any other index the operator slot means something else entirely (sort direction, a pgvector distance op), so a priority written here would be stored as a letter the index does not understand. Use \`op\`.`
451
+ );
452
+ }
453
+ return PRIORITY_OPS[field.priority - 1];
454
+ }
455
+ function encodeView(def) {
456
+ return {
457
+ alias: def.alias ?? "",
458
+ hiddenCols: def.hide ?? [],
459
+ id: def.id,
460
+ name: def.name,
461
+ q: def.q ?? "",
462
+ expression: def.where ? encodeComparison(def.where).expression : [],
463
+ sort: (def.sort ?? []).map((s) => ({ name: s.name, order: s.order }))
464
+ };
465
+ }
466
+ function encodeColumn(def) {
467
+ const { name, type, ...options } = def;
468
+ return encodeField(name, type, options, COLUMN_CONTEXT);
469
+ }
470
+ function assertBmpColumnDefault(tableName, col) {
471
+ if (col.default === void 0) return;
472
+ for (const ch of String(col.default)) {
473
+ const cp = ch.codePointAt(0);
474
+ if (cp > 65535) {
475
+ const u = `U+${cp.toString(16).toUpperCase().padStart(4, "0")}`;
476
+ throw new Error(
477
+ `table "${tableName}", column "${col.name}": \`default\` contains a 4-byte character (${JSON.stringify(ch)}, ${u}). The engine mangles such characters into an invalid UTF-8 sequence in the column default, failing at deploy with Postgres 22021 (invalid byte sequence for encoding "UTF8"). Use a default within the Basic Multilingual Plane (accents, most CJK, and \u20AC are fine), or move the value onto an endpoint input (\`input.text({ default })\`), applied at runtime bind.`
478
+ );
479
+ }
480
+ }
481
+ }
482
+ function assertColumnDefaultQuote(tableName, col, useXdo) {
483
+ const family = Object.hasOwn(SCALAR_FAMILY, col.type) ? SCALAR_FAMILY[col.type] : void 0;
484
+ if (useXdo || isListColumn(col) || family !== "text" && family !== "enum") return;
485
+ if (typeof col.default !== "string" || !col.default.includes("'")) return;
486
+ throw new Error(
487
+ `table "${tableName}", column "${col.name}" (${authoredFieldType(col.type)}): \`default\` ${JSON.stringify(col.default)} contains an apostrophe, which a table that keeps its fields as columns cannot take in a default \u2014 the deploy fails with an SQL syntax error. Use a typographic apostrophe (\u2019), set the value at insert instead of as the default, or give the table \`useXdo: true\`.`
488
+ );
489
+ }
490
+ function assertIndexColumns(def) {
491
+ const known = tableColumns(def).map((col) => col.name);
492
+ const set = /* @__PURE__ */ new Set([...known, "xdo"]);
493
+ for (const index of def.index ?? []) {
494
+ for (const field of index.fields) {
495
+ if (set.has(field.name)) continue;
496
+ const column = field.name.slice(0, field.name.indexOf("."));
497
+ if (column !== "" && set.has(column)) continue;
498
+ const signature = `${normalizeIndexType(index.type)}(${index.fields.map((f) => f.name).join(", ")})`;
499
+ throw new Error(
500
+ `table "${def.name}", index "${signature}": unknown column "${field.name}" (not in table schema). Known columns: ${known.join(", ")}. An index over a column that does not exist exports cleanly and fails at deploy with an engine error that names neither.`
501
+ );
502
+ }
503
+ }
504
+ }
505
+ function assertIndexFieldTypes(def) {
506
+ const columns = new Map(tableColumns(def).map((col) => [col.name, col]));
507
+ for (const index of def.index ?? []) {
508
+ const type = normalizeIndexType(index.type);
509
+ const at = `table "${def.name}", index "${type}(${index.fields.map((f) => f.name).join(", ")})"`;
510
+ if ((type === "hash" || type === "vector") && index.fields.length !== 1) {
511
+ throw new Error(`${at}: a ${type} index covers exactly one column \u2014 the deploy fails on ${index.fields.length}. Declare one index per column.`);
512
+ }
513
+ const ops = INDEX_OPS[type];
514
+ const xdo = def.useXdo === true;
515
+ const plainIndex = type === "btree" || type === "btree|unique" || type === "hash";
516
+ for (const field of index.fields) {
517
+ const col = columns.get(field.name);
518
+ const column = col?.type;
519
+ const list = col !== void 0 && isListColumn(col);
520
+ const shown = column === void 0 ? "" : `${authoredFieldType(column)}${list ? " list" : ""}`;
521
+ if (column?.startsWith("blob") === true) {
522
+ throw new Error(`${at}: "${field.name}" is ${shown}, and a file column cannot be indexed \u2014 the deploy fails with "Complex schema is not supported.". Index a column that holds the value you match on.`);
523
+ }
524
+ if (xdo && plainIndex && column === "vector") {
525
+ throw new Error(`${at}: "${field.name}" is ${shown}, and on a \`useXdo: true\` table a ${type === "btree|unique" ? "unique" : type} index cannot cover a vector column \u2014 the deploy fails with an SQL syntax error. Use a vector index.`);
526
+ }
527
+ if (xdo && plainIndex && list && column !== void 0 && !XDO_LIST_INDEXABLE.has(column)) {
528
+ throw new Error(`${at}: "${field.name}" is ${shown}, and on a \`useXdo: true\` table a ${type === "btree|unique" ? "unique" : type} index over a list of anything but text or json deploys, then fails inserts with an SQL error. Drop the index, or keep the table's fields as columns (\`useXdo: false\`).`);
529
+ }
530
+ if (type === "vector" && column !== void 0 && column !== "vector") {
531
+ throw new Error(`${at}: "${field.name}" is ${shown}, and a vector index needs an \`f.vector(size)\` column \u2014 the deploy fails with "Malformed vector index".`);
532
+ }
533
+ if (type === "vector" && (field.op === void 0 || field.op === "")) {
534
+ throw new Error(`${at}: a vector index needs the distance \`op\` its queries use on "${field.name}" (${(INDEX_OPS.vector ?? []).map((o) => JSON.stringify(o)).join(", ")}) \u2014 the deploy fails with "Malformed vector index" without one.`);
535
+ }
536
+ if (type === "gist" && column !== void 0 && !column.startsWith("geo_")) {
537
+ throw new Error(`${at}: "${field.name}" is ${shown}, and a gist (spatial) index needs a geo column (\`f.geo.point()\`, \u2026) \u2014 the deploy fails on any other.`);
538
+ }
539
+ if (column === void 0 || field.name === "xdo") {
540
+ } else if (type === "gin" && (column !== "json" && column !== "obj" && !list || xdo && list)) {
541
+ throw new Error(
542
+ xdo && list ? `${at}: "${field.name}" is ${shown}, and on a \`useXdo: true\` table a gin index needs a json or object column \u2014 the deploy fails on a list. Keep the table's fields as columns (\`useXdo: false\`) to gin-index a list.` : `${at}: "${field.name}" is ${shown}, and a gin index needs a json, object or list column \u2014 the deploy fails on any other. Use a \`search\` index for text, or \`btree\`.`
543
+ );
544
+ } else if (type === "gin" && field.op !== void 0 && GIN_OPS[field.op] !== void 0 && !GIN_OPS[field.op](list)) {
545
+ throw new Error(`${at}: op ${JSON.stringify(field.op)} on "${field.name}" (${shown}) is for ${list ? "a json or object" : "a list"} column \u2014 the deploy fails. Use ${list ? '"array_ops"' : '"jsonb_ops" or "jsonb_path_ops"'}, or no op.`);
546
+ } else if (type === "search" && (list ? !(xdo && SEARCHABLE.has(column)) : !SEARCHABLE.has(column))) {
547
+ throw new Error(`${at}: "${field.name}" is ${shown}, and a search index needs a text, email, password or enum column \u2014 the deploy fails on any other.`);
548
+ } else if (type === "hash" && (column === "vector" || column.startsWith("geo_"))) {
549
+ throw new Error(`${at}: "${field.name}" is ${shown}, and a hash index cannot cover a ${column === "vector" ? "vector" : "geo"} column \u2014 the deploy fails. Use a ${column === "vector" ? "vector" : "gist"} index.`);
550
+ }
551
+ if (ops !== void 0 && field.op !== void 0 && field.op !== "" && !ops.includes(field.op)) {
552
+ throw new Error(`${at}: op ${JSON.stringify(field.op)} on "${field.name}" is not one a ${type} index takes (${ops.map((o) => JSON.stringify(o)).join(", ")}).`);
553
+ }
554
+ }
555
+ }
556
+ }
557
+ function calendarDate(text) {
558
+ const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(text);
559
+ if (m === null || m[1] === "0000") return false;
560
+ const day = /* @__PURE__ */ new Date(0);
561
+ day.setUTCFullYear(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
562
+ return day.getUTCMonth() === Number(m[2]) - 1 && day.getUTCDate() === Number(m[3]);
563
+ }
564
+ var SEARCHABLE = /* @__PURE__ */ new Set(["text", "email", "password", "enum"]);
565
+ var XDO_LIST_INDEXABLE = /* @__PURE__ */ new Set([...SEARCHABLE, "json"]);
566
+ var INDEX_OPS = {
567
+ btree: ["asc", "desc"],
568
+ "btree|unique": ["asc", "desc"],
569
+ gin: ["jsonb_path_op", "jsonb_ops", "jsonb_path_ops", "array_ops"],
570
+ vector: ["vector_cosine_ops", "vector_ip_ops", "vector_l1_ops", "vector_l2_ops"]
571
+ };
572
+ var GIN_OPS = {
573
+ jsonb_ops: (list) => !list,
574
+ jsonb_path_ops: (list) => !list,
575
+ array_ops: (list) => list
576
+ };
577
+ function assertColumnDefaultFits(tableName, col, useXdo) {
578
+ const value = col.default;
579
+ if (value === void 0 || value === null || value === "" || typeof value === "object" || isListColumn(col)) return;
580
+ const text = String(value);
581
+ const shown = typeof value === "number" ? text : JSON.stringify(value);
582
+ const family = col.type === "date" ? "date" : Object.hasOwn(SCALAR_FAMILY, col.type) ? SCALAR_FAMILY[col.type] : void 0;
583
+ let want;
584
+ switch (family) {
585
+ case "int":
586
+ if (!/^-?\d+$/.test(text) || BigInt(text) > 2n ** 63n - 1n || BigInt(text) < -(2n ** 63n)) want = "a whole number (64-bit)";
587
+ break;
588
+ case "decimal":
589
+ if (typeof value === "boolean" || !/^\s*[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?\s*$/.test(text)) want = "a number";
590
+ else if (!decimalDefaultInRange(text, useXdo)) {
591
+ throw new Error(
592
+ `table "${tableName}", column "${col.name}" (decimal): \`default\` ${shown} is out of range \u2014 ` + (useXdo ? "a JSON-storage table holds a decimal as a JSON number, and this one is past what a number can hold" : "a normalized table holds a decimal in 14 digits, 5 of them after the point, so it must stay below 1000000000 once rounded to 5 places") + ` \u2014 the table deploys, then every insert that leaves the column unset fails with an SQL error. Use a smaller default.`
593
+ );
594
+ }
595
+ break;
596
+ case "bool":
597
+ if (!/^(true|false|t|f|yes|no|on|off|1|0)$/i.test(text)) want = "true or false";
598
+ break;
599
+ case "epochms":
600
+ if (text !== "now" && !/^-?\d+$/.test(text)) {
601
+ const ms = /\d{4}-\d{2}-\d{2}/.test(text) ? Date.parse(text) : NaN;
602
+ want = `"now" (the insert time) or epoch milliseconds` + (Number.isFinite(ms) ? ` \u2014 ${JSON.stringify(text)} is \`default: ${ms}\`` : "");
603
+ }
604
+ break;
605
+ case "date":
606
+ if (text !== "now" && !calendarDate(text)) want = `"now" (the insert date) or a real calendar date ("2026-01-31")`;
607
+ break;
608
+ }
609
+ if (want === void 0) return;
610
+ const consequence = !useXdo ? "the database takes the default as written, so the table fails to deploy" : family === "date" ? "a JSON-storage table deploys, then every insert that leaves the column unset is refused or stores a rolled-over day" : "a JSON-storage table deploys, then every insert that leaves the column unset is refused";
611
+ throw new Error(
612
+ `table "${tableName}", column "${col.name}" (${authoredFieldType(col.type)}): \`default\` ${shown} does not fit \u2014 ${consequence}. Use ${want}.`
613
+ );
614
+ }
615
+ function decimalDefaultInRange(text, useXdo) {
616
+ if (useXdo) return Number.isFinite(Number(text));
617
+ const m = /^\s*[+-]?(\d*)\.?(\d*)(?:[eE]([+-]?\d+))?\s*$/.exec(text);
618
+ const digits = (m[1] + m[2]).replace(/^0+/, "");
619
+ if (digits === "") return true;
620
+ const shift = Number(m[3] ?? "0") - m[2].length + 6;
621
+ const limit = 999999999999995n;
622
+ if (shift >= 0) return digits.length + shift <= 15 && BigInt(digits) * 10n ** BigInt(shift) < limit;
623
+ if (-shift > digits.length) return true;
624
+ return BigInt(digits) < limit * 10n ** BigInt(-shift);
625
+ }
626
+ function assertOwnPrimaryKey(def) {
627
+ if (def.system !== false) return;
628
+ const hasId = tableColumns(def).some((col) => col.name === "id");
629
+ const hasPrimary = (def.index ?? []).some((index) => index.type === "primary" && index.fields.length === 1 && index.fields[0].name === "id");
630
+ if (hasId && hasPrimary) return;
631
+ const missing = [hasId ? void 0 : "an `id` column (`id: f.int()` or `id: f.uuid()`)", hasPrimary ? void 0 : '`{ type: "primary", fields: [{ name: "id" }] }` in `index`'].filter((m) => m !== void 0).join(" and ");
632
+ throw new Error(
633
+ `table "${def.name}": a \`system: false\` table still needs an \`id\` primary key \u2014 the deploy fails without it. Declare ${missing}, or drop \`system: false\` to have both added (with \`created_at\`).`
634
+ );
635
+ }
636
+ function encodeTable(def) {
637
+ if (!def.name) throw new Error("table: `name` is required.");
638
+ assertIndexShape(def);
639
+ for (const col of tableColumns(def)) {
640
+ assertBmpColumnDefault(def.name, col);
641
+ assertColumnDefaultFits(def.name, col, def.useXdo === true);
642
+ assertColumnDefaultQuote(def.name, col, def.useXdo === true);
643
+ }
644
+ assertIndexColumns(def);
645
+ assertIndexFieldTypes(def);
646
+ assertOwnPrimaryKey(def);
647
+ return {
648
+ name: def.name,
649
+ description: def.description ?? "",
650
+ docs: def.docs ?? "",
651
+ auth: def.auth ?? false,
652
+ install: def.install ?? false,
653
+ schema: tableColumns(def).map(encodeColumn),
654
+ index: tableIndexes(def).map(encodeIndex),
655
+ autocomplete: (def.autocomplete ?? []).map((name) => ({ name })),
656
+ external: def.external ?? { source: "", id: "" },
657
+ views: (def.views ?? []).map(encodeView),
658
+ tag: encodeTags(def.tags),
659
+ // A table has no `as` — it returns nothing (it's a datastore, not a stack
660
+ // statement); confirmed 0/16 live `mvp_dbo` rows carry one. (Older golden
661
+ // export fixtures store `as:<name>`, a stale generation — see normalize.ts.)
662
+ // `sql_name` is the engine's physical table name; persisted as "" (the
663
+ // engine derives the real name) — confirmed against live `mvp_dbo`.
664
+ sql_name: "",
665
+ use_xdo: def.useXdo ?? false,
666
+ market_item: { id: 0, version: 0, guid: "" }
667
+ };
668
+ }
669
+ var tableKind = {
670
+ name: "table",
671
+ payloadKey: "dbo",
672
+ encode: encodeTable
673
+ };
674
+ registerKind(tableKind);
675
+ function table(def) {
676
+ if (def !== null && typeof def === "object") {
677
+ assertIndexShape(def);
678
+ assertColumnNames(def);
679
+ }
680
+ return brandDef(def, "table");
681
+ }
682
+ var COLUMN_NAME = /^(?![-@])(?![0-9]+$)(?![_-]+$)[A-Za-z0-9_:@!-]+(?<!-)$/;
683
+ var COLUMN_NAME_BYTES = 63;
684
+ var COLUMN_NAME_UNUSABLE = "table.column-name-unusable";
685
+ function unusableColumnName(name) {
686
+ const bytes = new TextEncoder().encode(name).length;
687
+ if (bytes > COLUMN_NAME_BYTES && COLUMN_NAME.test(name)) {
688
+ return `is ${bytes} bytes and the database keeps only the first ${COLUMN_NAME_BYTES}, so it deploys but every read returns it empty`;
689
+ }
690
+ if (COLUMN_NAME.test(name)) return void 0;
691
+ if (/[^\x21-\x7e]|[.$]/.test(name) || name === "") return "cannot be deployed";
692
+ if (/^[A-Za-z0-9_:@!?-]+$/.test(name) && (name.includes("?") || /^[0-9]+$/.test(name) || /^[_-]+$/.test(name))) {
693
+ return "deploys, but every insert into the table fails (seed rows included)";
694
+ }
695
+ if (/^@[A-Za-z0-9_:@!-]*$/.test(name) && !name.endsWith("-")) return "deploys, but every filter on it fails";
696
+ return "is outside the column-name rule";
697
+ }
698
+ function unusableColumns(schema) {
699
+ const names = Array.isArray(schema) ? schema.map((c) => c !== null && typeof c === "object" ? c.name : void 0) : schema !== null && typeof schema === "object" ? Object.keys(schema) : [];
700
+ const out = [];
701
+ for (const name of names) {
702
+ if (typeof name !== "string") continue;
703
+ const why = unusableColumnName(name);
704
+ if (why !== void 0) out.push({ name, why });
705
+ }
706
+ return out;
707
+ }
708
+ function assertColumnNames(def) {
709
+ const schema = def.schema;
710
+ const names = Array.isArray(schema) ? schema.map((c) => c !== null && typeof c === "object" ? c.name : void 0) : schema !== null && typeof schema === "object" ? Object.keys(schema) : [];
711
+ const seen = /* @__PURE__ */ new Map();
712
+ const at = /* @__PURE__ */ new Map();
713
+ for (const [i, name2] of names.entries()) {
714
+ if (typeof name2 !== "string") continue;
715
+ if (at.has(name2)) {
716
+ throw new Error(
717
+ `table "${String(def.name)}": schema[${at.get(name2)}] and schema[${i}] are both named ${JSON.stringify(name2)} \u2014 the database keeps one column per name, so the table deploys with one of them. Rename or drop one.`
718
+ );
719
+ }
720
+ at.set(name2, i);
721
+ const head = new TextDecoder().decode(new TextEncoder().encode(name2).slice(0, COLUMN_NAME_BYTES));
722
+ const other = seen.get(head);
723
+ if (other !== void 0) {
724
+ throw new Error(
725
+ `table "${String(def.name)}": the column names ${JSON.stringify(other)} and ${JSON.stringify(name2)} share their first ${COLUMN_NAME_BYTES} bytes, which is all of a column name the database keeps \u2014 the deploy fails on a duplicate column. Shorten one of them.`
726
+ );
727
+ }
728
+ seen.set(head, name2);
729
+ }
730
+ if (def.diagnostics?.allow?.includes(COLUMN_NAME_UNUSABLE)) return;
731
+ const bad = unusableColumns(schema)[0];
732
+ if (bad === void 0) return;
733
+ const { name, why } = bad;
734
+ let fixed = name.trim().replace(/[^A-Za-z0-9_:@!-]+/g, "_").replace(/^[-@_]+|[-_]+$/g, "");
735
+ if (/^[0-9]+$/.test(fixed)) fixed = `col_${fixed}`;
736
+ if (new TextEncoder().encode(fixed).length > COLUMN_NAME_BYTES) fixed = fixed.slice(0, COLUMN_NAME_BYTES).replace(/[-_]+$/, "");
737
+ throw new Error(
738
+ `table "${String(def.name)}": the column name ${JSON.stringify(name)} ${why} \u2014 a column name is ASCII letters, digits, \`_\`, \`-\`, \`:\`, \`@\` and \`!\`, does not start or end with \`-\` or start with \`@\`, is not all digits or all \`_\`/\`-\`, and is at most ${COLUMN_NAME_BYTES} bytes.` + (fixed !== "" && fixed !== name && unusableColumnName(fixed) === void 0 ? ` Rename it, e.g. ${JSON.stringify(fixed)}.` : " Rename it.")
739
+ );
740
+ }
741
+ var INDEX_TYPES = /* @__PURE__ */ new Set(["primary", "btree", "hash", "gin", "gist", "search", "vector"]);
742
+ function assertIndexShape(def) {
743
+ if (def.index === void 0) return;
744
+ const where = `table "${String(def.name)}"`;
745
+ if (!Array.isArray(def.index)) {
746
+ throw new Error(`${where}: \`index\` must be a list of { type, fields } entries \u2014 got ${typeof def.index}.`);
747
+ }
748
+ def.index.forEach((index, i) => {
749
+ const at = `${where}, index[${i}]`;
750
+ if (index === null || typeof index !== "object") throw new Error(`${at} must be a { type, fields } entry \u2014 got ${String(index)}.`);
751
+ if (typeof index.type !== "string") throw new Error(`${at}: \`type\` must be the index type ("btree", "unique", "search", \u2026).`);
752
+ const base = normalizeIndexType(index.type).split("|")[0];
753
+ if (!INDEX_TYPES.has(base)) {
754
+ const hint = base === "spatial" ? " A spatial index is `gist`." : base === "fulltext" || base === "text" ? " A full-text index is `search`." : "";
755
+ throw new Error(
756
+ `${at}: ${JSON.stringify(index.type)} is not an index type the engine builds \u2014 the deploy fails with "Invalid index type.", naming no table. Use one of ${[...INDEX_TYPES].filter((t) => t !== "primary").map((t) => `"${t}"`).join(", ")}, "unique".${hint}`
757
+ );
758
+ }
759
+ if (!Array.isArray(index.fields) || index.fields.length === 0) {
760
+ throw new Error(`${at}: \`fields\` must be a non-empty list of the indexed columns, e.g. \`fields: [{ name: "email" }]\`.`);
761
+ }
762
+ index.fields.forEach((field, j) => {
763
+ if (field === null || typeof field !== "object" || typeof field.name !== "string") {
764
+ throw new Error(
765
+ `${at}: fields[${j}] must be { name: "<column>" } \u2014 got ${JSON.stringify(field) ?? String(field)}.` + (typeof field === "string" ? ` Write \`{ name: ${JSON.stringify(field)} }\`.` : "")
766
+ );
767
+ }
768
+ });
769
+ });
770
+ }
771
+
772
+ // src/fields/email-address.ts
773
+ function emailAddress(value) {
774
+ let start = 0;
775
+ let end = value.length;
776
+ while (start < end && TRIMMED.includes(value[start])) start++;
777
+ while (end > start && TRIMMED.includes(value[end - 1])) end--;
778
+ const text = value.slice(start, end);
779
+ if (text === "") return true;
780
+ const bytes = String.fromCharCode(...new TextEncoder().encode(text));
781
+ return bytes.length <= 320 && EMAIL_ADDRESS.test(bytes);
782
+ }
783
+ var TRIMMED = " \n\r\0\v";
784
+ var EMAIL_ADDRESS = (() => {
785
+ const atom = "[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+";
786
+ const quoted = "\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|\\x5C[\\x00-\\x7F])*\\x22";
787
+ const word = `(?:${atom}|${quoted})`;
788
+ const char = "(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?|\\x22?[^\\x5C\\x22]\\x22?)";
789
+ const octet = "(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])";
790
+ const ipv4 = `${octet}(?:\\.${octet}){3}`;
791
+ const h = "[a-f0-9]{1,4}";
792
+ const domain = "(?!.*[^.]{64,})(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\\.){1,126}(?:[a-z][a-z0-9]*|xn--[a-z0-9]+)(?:-+[a-z0-9]+)*";
793
+ const v6 = `IPv6:(?:${h}(?::${h}){7}|(?!(?:.*[a-f0-9][:\\]]){7,})(?:${h}(?::${h}){0,5})?::(?:${h}(?::${h}){0,5})?)`;
794
+ const v6v4 = `(?:IPv6:(?:${h}(?::${h}){5}:|(?!(?:.*[a-f0-9]:){5,})(?:${h}(?::${h}){0,3})?::(?:${h}(?::${h}){0,3}:)?))?${ipv4}`;
795
+ return new RegExp(`^(?!${char}{255,})(?!${char}{65,}@)${word}(?:\\.${word})*@(?:${domain}|\\[(?:${v6}|${v6v4})\\])$`, "i");
796
+ })();
797
+
798
+ // src/workspace/seed-coerce.ts
799
+ function coerceScalarValue(label, column, type, value, values, scalar) {
800
+ if (value === null) return null;
801
+ if (isHostedFile(value)) {
802
+ if (type.startsWith("blob")) return value;
803
+ throw new Error(
804
+ `${label}, column "${column}" (${authoredFieldType(type)}): hostedFile() goes in a file column (image, video, audio or attachment), not a ${authoredFieldType(type)} column. Fix the seed value or the column type.`
805
+ );
806
+ }
807
+ if (scalar !== void 0 && type === "uuid" && !(typeof value === "string" && UUID.test(value))) {
808
+ throw located(label, column, type, value, 'a uuid ("0b2d382e-dd81-4d56-a291-ecf899ca1d33")');
809
+ }
810
+ if (scalar !== void 0 && type === "email" && !(typeof value === "string" && emailAddress(value))) {
811
+ throw located(label, column, type, value, 'an email address ("ada@example.com")');
812
+ }
813
+ if (scalar !== void 0 && type === "vector") {
814
+ const size = scalar.vectorSize ?? 3;
815
+ if (!(Array.isArray(value) && value.length === size && value.every((n) => typeof n === "number" && Number.isFinite(n)))) {
816
+ throw located(label, column, type, value, `an array of exactly ${size} numbers (the column's size)`);
817
+ }
818
+ return value;
819
+ }
820
+ if (scalar !== void 0 && Object.hasOwn(GEO_TYPE, type)) {
821
+ const problem = geoProblem(GEO_TYPE[type], value);
822
+ if (problem !== void 0) throw located(label, column, type, value, problem);
823
+ return value;
824
+ }
825
+ if (scalar !== void 0 && type === "date") {
826
+ if (typeof value === "number" && Number.isFinite(value) || value instanceof Date && Number.isFinite(value.getTime())) {
827
+ return value;
828
+ }
829
+ if (typeof value === "string" && isCalendarDate(value)) return value;
830
+ throw located(label, column, type, value, 'a real calendar date ("2026-01-31"), or epoch milliseconds');
831
+ }
832
+ switch (Object.hasOwn(SCALAR_FAMILY, type) ? SCALAR_FAMILY[type] : void 0) {
833
+ case "int":
834
+ return wholeNumber(label, column, type, value);
835
+ case "decimal": {
836
+ let n;
837
+ if (typeof value === "number" && Number.isFinite(value)) n = value;
838
+ else if (typeof value === "bigint") n = Number(value);
839
+ else if (typeof value === "string" && value.trim() !== "" && Number.isFinite(Number(value))) n = Number(value);
840
+ if (n === void 0) throw located(label, column, type, value, "a number");
841
+ if (scalar?.useXdo === false && Math.abs(Math.round(n * 1e5) / 1e5) >= FIXED_DECIMAL_LIMIT) {
842
+ throw new SeedCellError(
843
+ (where, shown) => `${where}, column "${column}" (decimal): ${shown} is out of range \u2014 a decimal on a table without \`useXdo: true\` (its own, or the workspace's) holds under 1000000000 (9 digits left of the point), and the deploy fails on a larger one. Store it in an \`f.int\`, or give the table \`useXdo: true\`.`,
844
+ label,
845
+ value
846
+ );
847
+ }
848
+ return n;
849
+ }
850
+ case "epochms": {
851
+ if (typeof value === "number" && Number.isFinite(value)) return value;
852
+ if (value instanceof Date && Number.isFinite(value.getTime())) return value.getTime();
853
+ if (typeof value === "string") {
854
+ const ms = isoInstant(value);
855
+ if (ms !== void 0) return ms;
856
+ }
857
+ throw located(
858
+ label,
859
+ column,
860
+ type,
861
+ value,
862
+ 'epoch ms, a Date, or ISO 8601 with Z or an offset ("2026-01-31T10:00:00Z"; a bare "2026-01-31" is midnight UTC) \u2014 a date-time without a zone reads differently per machine, so add Z or an offset'
863
+ );
864
+ }
865
+ case "bool": {
866
+ if (typeof value === "boolean") return value;
867
+ if (value === "true" || value === 1) return true;
868
+ if (value === "false" || value === 0) return false;
869
+ throw located(label, column, type, value, "a boolean");
870
+ }
871
+ case "text": {
872
+ if (typeof value === "string") return value;
873
+ throw located(label, column, type, value, "a string");
874
+ }
875
+ case "enum": {
876
+ if (!values || values.length === 0) return value;
877
+ if (values.includes(value)) return value;
878
+ if (typeof value === "number" && !Number.isFinite(value)) throw located(label, column, type, value, "one of its values");
879
+ const allowed = values.map((v) => JSON.stringify(v)).join(", ");
880
+ throw new SeedCellError(
881
+ (where, shown) => `${where}, column "${column}" (enum): ${shown} is not one of its declared values (${allowed}). Fix the seed value or add it to the column's enum.`,
882
+ label,
883
+ value
884
+ );
885
+ }
886
+ default:
887
+ assertJsonCarryable(label, column, type, value);
888
+ return value;
889
+ }
890
+ }
891
+ function assertJsonCarryable(label, column, type, value) {
892
+ const seen = /* @__PURE__ */ new Set();
893
+ const walk = (node, path) => {
894
+ if (typeof node === "number") {
895
+ if (Number.isFinite(node)) return;
896
+ throw jsonRefusal(
897
+ label,
898
+ column,
899
+ type,
900
+ path,
901
+ `${node}, which is not a storable number`,
902
+ "JSON has no NaN or Infinity, so it would ship as `null` and the column would import empty"
903
+ );
904
+ }
905
+ if (typeof node === "bigint") {
906
+ throw jsonRefusal(
907
+ label,
908
+ column,
909
+ type,
910
+ path,
911
+ "a BigInt",
912
+ "JSON cannot carry one \u2014 convert it to a number or a string first"
913
+ );
914
+ }
915
+ if (typeof node === "function" || typeof node === "symbol") {
916
+ throw jsonRefusal(
917
+ label,
918
+ column,
919
+ type,
920
+ path,
921
+ `a ${typeof node}`,
922
+ "JSON drops it, so the key would vanish from the imported row"
923
+ );
924
+ }
925
+ if (node === null || typeof node !== "object") return;
926
+ if (seen.has(node)) {
927
+ throw jsonRefusal(
928
+ label,
929
+ column,
930
+ type,
931
+ path,
932
+ "a circular reference",
933
+ "JSON cannot carry one \u2014 the archive would fail to serialize"
934
+ );
935
+ }
936
+ seen.add(node);
937
+ if (Array.isArray(node)) {
938
+ node.forEach((el, i) => walk(el, `${path}[${i}]`));
939
+ } else {
940
+ for (const [key, member] of Object.entries(node)) walk(member, `${path}.${key}`);
941
+ }
942
+ seen.delete(node);
943
+ };
944
+ walk(value, `"${column}"`);
945
+ }
946
+ function jsonRefusal(label, column, type, path, got, why) {
947
+ return new Error(
948
+ `${label}, column "${column}" (${authoredFieldType(type)}): ${path} is ${got}. ${why}. Seed rows are carried to the engine as JSON \u2014 fix the value or the column type.`
949
+ );
950
+ }
951
+ function coerceColumnValue(label, col, value, useXdo) {
952
+ if (value === null) return null;
953
+ if (isListColumn(col)) {
954
+ if (!Array.isArray(value)) throw located(label, col.name, `${authoredFieldType(col.type)}[]`, value, "an array");
955
+ return value.map(
956
+ (el, j) => coerceScalarValue(label, `${col.name}[${j}]`, col.type, el, col.values)
957
+ );
958
+ }
959
+ return coerceScalarValue(label, col.name, col.type, value, col.values, { useXdo, vectorSize: col.vector?.size });
960
+ }
961
+ function unsafeIntRemedy(n) {
962
+ const reads = BigInt(n).toString();
963
+ return `a whole number within \xB19007199254740991 \u2014 past that a JS number cannot hold every whole number, so this one reads as ${reads}, which may not be the digits written; write the digits meant as a digit string or a BigInt \u2014 as it reads now, "${reads}" or ${reads}n \u2014 and in a seedFile quote it in the JSON`;
964
+ }
965
+ var INT64_MIN = -(2n ** 63n);
966
+ var INT64_MAX = 2n ** 63n - 1n;
967
+ function wholeNumber(label, column, type, value) {
968
+ let big;
969
+ if (typeof value === "bigint") big = value;
970
+ else if (typeof value === "string" && /^\s*[+-]?\d+\s*$/.test(value)) big = BigInt(value.trim());
971
+ else {
972
+ const n2 = typeof value === "number" ? value : typeof value === "string" && value.trim() !== "" ? Number(value) : NaN;
973
+ if (Number.isFinite(n2) && !Number.isInteger(n2)) {
974
+ throw located(label, column, type, value, "a whole number (an int column drops the fraction)");
975
+ }
976
+ if (Number.isInteger(n2)) {
977
+ if (!Number.isSafeInteger(n2) && Math.abs(n2) <= 2 ** 63) {
978
+ throw located(label, column, type, value, unsafeIntRemedy(n2));
979
+ }
980
+ big = BigInt(n2);
981
+ }
982
+ }
983
+ if (big === void 0) throw located(label, column, type, value, "a number");
984
+ if (big < INT64_MIN || big > INT64_MAX) {
985
+ throw located(label, column, type, value, "a whole number within int64 (\xB19223372036854775807)");
986
+ }
987
+ const n = Number(big);
988
+ return Number.isSafeInteger(n) ? n : big.toString();
989
+ }
990
+ function isoInstant(value) {
991
+ const m = /^(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d+))?)?([Zz]|[+-]\d{2}(?::?\d{2})?))?$/.exec(value);
992
+ if (m === null) return void 0;
993
+ const [y, mo, d, h = 0, mi = 0, sec = 0] = [m[1], m[2], m[3], m[4], m[5], m[6]].map((v) => v === void 0 ? void 0 : Number(v));
994
+ if (!isCalendarDate(`${m[1]}-${m[2]}-${m[3]}`) || h > 23 || mi > 59 || sec > 59) return void 0;
995
+ let offset = 0;
996
+ const zone = /^([+-])(\d{2}):?(\d{2})?$/.exec(m[8] ?? "");
997
+ if (zone !== null) {
998
+ const [oh, om] = [Number(zone[2]), Number(zone[3] ?? 0)];
999
+ if (oh > 23 || om > 59) return void 0;
1000
+ offset = (zone[1] === "-" ? -1 : 1) * (oh * 60 + om) * 6e4;
1001
+ }
1002
+ const at = new Date(Date.UTC(2e3, mo - 1, d, h, mi, sec, Number((m[7] ?? "").padEnd(3, "0").slice(0, 3))));
1003
+ at.setUTCFullYear(y);
1004
+ return at.getTime() - offset;
1005
+ }
1006
+ var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1007
+ function isUuid(value) {
1008
+ return UUID.test(value);
1009
+ }
1010
+ var GEO_TYPE = {
1011
+ geo_point: "point",
1012
+ geo_multipoint: "points",
1013
+ geo_linestring: "path",
1014
+ geo_multilinestring: "paths",
1015
+ geo_polygon: "poly",
1016
+ geo_multipolygon: "polys"
1017
+ };
1018
+ function geoProblem(name, value) {
1019
+ if (typeof value === "string") return void 0;
1020
+ const position = (p) => typeof p === "object" && p !== null && Number.isFinite(p.lng) && Number.isFinite(p.lat);
1021
+ const positions = (d) => Array.isArray(d) && d.every(position);
1022
+ const v = value;
1023
+ const data = typeof v === "object" && v !== null && !Array.isArray(v) && v.type === name ? v.data : void 0;
1024
+ const fits = name === "point" ? position(data) : name === "paths" || name === "polys" ? Array.isArray(data) && data.every(positions) : positions(data);
1025
+ if (fits) return void 0;
1026
+ const shape = name === "point" ? "{ lng, lat }" : name === "paths" || name === "polys" ? "[[{ lng, lat }, \u2026], \u2026]" : "[{ lng, lat }, \u2026]";
1027
+ return `{ type: "${name}", data: ${shape} } (not GeoJSON)`;
1028
+ }
1029
+ var FIXED_DECIMAL_LIMIT = 1e9;
1030
+ function isCalendarDate(value) {
1031
+ const m = /^(\d{4})-(\d{1,2})-(\d{1,2})(?:[T ].*)?$/.exec(value);
1032
+ if (m === null) return false;
1033
+ const [y, mo, d] = [Number(m[1]), Number(m[2]), Number(m[3])];
1034
+ const day = new Date(Date.UTC(y, mo - 1, d));
1035
+ return mo >= 1 && mo <= 12 && day.getUTCMonth() === mo - 1 && day.getUTCDate() === d;
1036
+ }
1037
+ function located(label, column, type, value, expected) {
1038
+ const got = value instanceof Date ? "Date" : Array.isArray(value) ? "array" : typeof value;
1039
+ const nonFinite = typeof value === "number" && !Number.isFinite(value);
1040
+ return new SeedCellError(
1041
+ (where, shown) => `${where}, column "${column}" (${authoredFieldType(type)}): ` + (nonFinite ? `${String(value)} is not a storable number. ` : `expected ${expected}, got ${got} (${shown}). `) + `Fix the seed value or the column type.`,
1042
+ label,
1043
+ value
1044
+ );
1045
+ }
1046
+ var SeedCellError = class extends Error {
1047
+ constructor(render, where, value) {
1048
+ super(render(where, shownValue(value)));
1049
+ this.render = render;
1050
+ this.value = value;
1051
+ }
1052
+ render;
1053
+ value;
1054
+ };
1055
+ var SHOWN_MAX = 80;
1056
+ function shownValue(value) {
1057
+ const json = typeof value === "bigint" ? `${value}n` : JSON.stringify(value) ?? String(value);
1058
+ return json.length > SHOWN_MAX ? `${json.slice(0, SHOWN_MAX - 1)}\u2026` : json;
1059
+ }
1060
+ var GROUP_SAMPLE = 5;
1061
+ function groupRowProblems(tableName, problems) {
1062
+ const groups = /* @__PURE__ */ new Map();
1063
+ for (const p of problems) {
1064
+ const key = p.render("\0", "\0");
1065
+ const list = groups.get(key);
1066
+ if (list === void 0) groups.set(key, [p]);
1067
+ else list.push(p);
1068
+ }
1069
+ return [...groups.values()].map((list) => {
1070
+ const first = list[0];
1071
+ if (list.length === 1) return first.render(`table "${tableName}", seed row ${first.row}`, shownValue(first.value));
1072
+ const rows = list.slice(0, GROUP_SAMPLE).map((p) => p.row).join(", ") + (list.length > GROUP_SAMPLE ? ", \u2026" : "");
1073
+ const distinct = [...new Set(list.map((p) => shownValue(p.value)))];
1074
+ const shown = distinct.slice(0, GROUP_SAMPLE).join(", ") + (distinct.length > GROUP_SAMPLE ? `, \u2026 (${distinct.length} distinct)` : "");
1075
+ return first.render(`table "${tableName}", ${list.length} seed rows (${rows})`, shown);
1076
+ });
1077
+ }
1078
+ function coerceSeedRowValues(tableName, columns, rows, opts = {}) {
1079
+ const colByName = new Map(columns.map((c) => [c.name, c]));
1080
+ const mustSupply = columns.filter(mustSupplyInSeed);
1081
+ const problems = [];
1082
+ const out = rows.map((row, i) => {
1083
+ const label = `table "${tableName}", seed row ${i}`;
1084
+ const say = (render) => {
1085
+ problems.push({ row: i, render });
1086
+ };
1087
+ const coerced = /* @__PURE__ */ Object.create(null);
1088
+ if (row === null || typeof row !== "object" || Array.isArray(row)) {
1089
+ const got = Array.isArray(row) ? "array" : typeof row;
1090
+ say((where) => `${where}: expected a row object, got ${got}.`);
1091
+ return coerced;
1092
+ }
1093
+ for (const [key, value] of Object.entries(row)) {
1094
+ if (value === void 0) continue;
1095
+ const col = colByName.get(key);
1096
+ if (col === void 0) {
1097
+ const known = columns.map((c) => c.name).join(", ");
1098
+ problems.push({
1099
+ row: i,
1100
+ render: (where, shown) => `${where}: unknown column ${shown} (not in table schema). Known columns: ${known}.`,
1101
+ value: key
1102
+ });
1103
+ continue;
1104
+ }
1105
+ if (value === null && !acceptsSeedNull(col)) {
1106
+ say(
1107
+ (where) => `${where}, column "${key}" (${authoredFieldType(col.type)}): null in a column that is not nullable. The engine does not store it as null \u2014 a date fails the deploy, int/decimal/timestamp store 0, text "", bool false. Give the column \`nullable: true\`, or the row a value.`
1108
+ );
1109
+ continue;
1110
+ }
1111
+ try {
1112
+ coerced[key] = coerceColumnValue(label, col, value, opts.useXdo === true);
1113
+ } catch (err) {
1114
+ if (err instanceof SeedCellError) problems.push({ row: i, render: err.render, value: err.value });
1115
+ else {
1116
+ const message = err.message;
1117
+ const rest = message.startsWith(label) ? message.slice(label.length) : null;
1118
+ say((where) => rest === null ? message : where + rest);
1119
+ }
1120
+ }
1121
+ }
1122
+ const missing = mustSupply.filter((c) => row[c.name] === void 0).map((c) => `"${c.name}"`);
1123
+ if (missing.length > 0) {
1124
+ say(
1125
+ (where) => `${where}: missing required column${missing.length === 1 ? "" : "s"} ${missing.join(", ")}. Supply ${missing.length === 1 ? "it" : "them"} on every row, or give the column a \`default\` (or \`nullable: true\`).`
1126
+ );
1127
+ }
1128
+ return coerced;
1129
+ });
1130
+ problems.push(...partlySetDates(columns, rows));
1131
+ if (problems.length > 0) throw seedError(groupRowProblems(tableName, problems), tableName);
1132
+ return out;
1133
+ }
1134
+ function partlySetDates(columns, rows) {
1135
+ const out = [];
1136
+ for (const col of columns) {
1137
+ if (col.type !== "date" || isListColumn(col) || acceptsSeedNull(col) || col.default !== void 0 || mustSupplyInSeed(col)) continue;
1138
+ const isSet = (row) => row !== null && typeof row === "object" && row[col.name] !== void 0;
1139
+ const set = rows.filter(isSet).length;
1140
+ if (set === 0 || set === rows.length) continue;
1141
+ rows.forEach((row, i) => {
1142
+ if (isSet(row)) return;
1143
+ out.push({
1144
+ row: i,
1145
+ render: (where) => `${where}: leaves out date column "${col.name}", which ${set} other seed row${set === 1 ? " sets" : "s set"} \u2014 the deploy fails on a date column set on some rows and not others. Set it on every row or none, or give the column a \`default\` or \`nullable: true\`.`
1146
+ });
1147
+ });
1148
+ }
1149
+ return out;
1150
+ }
1151
+ var NULLABLE_BY_DEFAULT = new Set(COLUMN_NULLABLE_TYPES);
1152
+ function acceptsSeedNull(col) {
1153
+ if (col.type === "json" || isListColumn(col)) return true;
1154
+ return col.nullable === true || col.nullable === void 0 && NULLABLE_BY_DEFAULT.has(col.type);
1155
+ }
1156
+ function mustSupplyInSeed(col) {
1157
+ if (col.required !== true || col.default !== void 0) return false;
1158
+ if (col.name === "id" || col.name === "created_at" || col.type === "json") return false;
1159
+ return col.nullable === false || col.nullable === void 0 && !NULLABLE_BY_DEFAULT.has(col.type);
1160
+ }
1161
+ function seedError(problems, table2) {
1162
+ const listed = problems.slice(0, SEED_PROBLEMS_LISTED);
1163
+ const rest = problems.length - listed.length;
1164
+ const details = listed.map((message) => ({ severity: "error", code: "seed.invalid", message }));
1165
+ if (rest > 0) {
1166
+ details.push({
1167
+ severity: "error",
1168
+ code: "seed.invalid",
1169
+ message: `\u2026 and ${rest} more seed problem${rest === 1 ? "" : "s"}${table2 === void 0 ? "" : ` in table "${table2}"`}, not listed \u2014 fix these and export again to see them.`,
1170
+ unlisted: rest
1171
+ });
1172
+ }
1173
+ return seedFailure(details);
1174
+ }
1175
+ function seedFailure(details) {
1176
+ const total = problemCount(details);
1177
+ return new DiagnosticError(
1178
+ details.length === 1 ? `xanosdk: ${details[0].message}` : `xanosdk: ${total} seed problems.
1179
+ ${numberedList(details)}`,
1180
+ details
1181
+ );
1182
+ }
1183
+ var SEED_PROBLEMS_LISTED = 20;
1184
+ function assertSeedIds(tableName, columns, rows) {
1185
+ const idType = columns.find((c) => c.name === "id")?.type;
1186
+ if (idType !== "int" && idType !== "uuid") return false;
1187
+ const withId = rows.filter((r) => r.id !== void 0).length;
1188
+ if (withId === rows.length) return false;
1189
+ if (withId !== 0) {
1190
+ const fill = idType === "int" ? "auto-numbered 1..N" : "assigned a generated uuid";
1191
+ throw new Error(
1192
+ `table "${tableName}": ${withId} of ${rows.length} seed rows set \`id\` and the rest omit it. The engine preserves seed ids and won't auto-fill a missing one, so a mix collides on the primary key. Provide \`id\` for every seed row, or none (they'll be ${fill}).`
1193
+ );
1194
+ }
1195
+ return true;
1196
+ }
1197
+ function assertSeedUnique(tableName, indexes, rows) {
1198
+ for (const index of indexes) {
1199
+ const type = normalizeIndexType(index.type);
1200
+ if (type !== "primary" && !type.split("|").includes("unique")) continue;
1201
+ const names = index.fields.map((f) => f.name);
1202
+ if (names.length === 0 || names.some((n) => n.includes("."))) continue;
1203
+ const seen = /* @__PURE__ */ new Map();
1204
+ rows.forEach((row, i) => {
1205
+ const values = names.map((n) => row[n]);
1206
+ if (values.some((v) => v === null || v === void 0)) return;
1207
+ const key = JSON.stringify(values);
1208
+ const first = seen.get(key);
1209
+ if (first === void 0) {
1210
+ seen.set(key, i);
1211
+ return;
1212
+ }
1213
+ const shown = names.length === 1 ? `${names[0]} = ${JSON.stringify(values[0])}` : `(${names.join(", ")}) = (${values.map((v) => JSON.stringify(v)).join(", ")})`;
1214
+ throw new Error(
1215
+ `table "${tableName}": seed rows ${first} and ${i} both have ${shown}, which the ${type === "primary" ? "primary key" : `unique index on (${names.join(", ")})`} allows once \u2014 the import fails on the duplicate. Make the values distinct, or drop one row.`
1216
+ );
1217
+ });
1218
+ }
1219
+ }
1220
+ function isNonPublicColumn(col) {
1221
+ return col.access === "internal" || col.sensitive === true || col.type === "password";
1222
+ }
1223
+
1224
+ export {
1225
+ assertKnownKeys,
1226
+ expr,
1227
+ isSearchOp,
1228
+ cmp,
1229
+ and,
1230
+ or,
1231
+ mixed,
1232
+ isValue,
1233
+ isGroup,
1234
+ isMixed,
1235
+ isCmpNode,
1236
+ encodeExpression,
1237
+ isRuntimeConditionOp,
1238
+ encodeRuntimeCondition,
1239
+ conditional,
1240
+ SCALAR_FAMILY,
1241
+ SEED_FILE,
1242
+ seedFile,
1243
+ isSeedFileSource,
1244
+ tableColumns,
1245
+ tableIndexes,
1246
+ SYSTEM_COLUMN_NAMES,
1247
+ elideSystemIndexes,
1248
+ encodeIndex,
1249
+ encodeView,
1250
+ encodeColumn,
1251
+ encodeTable,
1252
+ tableKind,
1253
+ table,
1254
+ COLUMN_NAME_UNUSABLE,
1255
+ unusableColumns,
1256
+ emailAddress,
1257
+ isUuid,
1258
+ coerceSeedRowValues,
1259
+ seedFailure,
1260
+ assertSeedIds,
1261
+ assertSeedUnique,
1262
+ isNonPublicColumn
1263
+ };
1264
+ //# sourceMappingURL=chunk-HVRUQXGD.js.map