@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,1981 @@
1
+ import {
2
+ readPathEnvVar
3
+ } from "./chunk-EUUUMY7J.js";
4
+ import {
5
+ FIELD_METHODS
6
+ } from "./chunk-3YW23UFH.js";
7
+ import {
8
+ obj
9
+ } from "./chunk-K5BBGTYZ.js";
10
+ import {
11
+ FILTER_NAMES,
12
+ FILTER_REQUIRED_ARGS,
13
+ fl
14
+ } from "./chunk-6HO3NCSJ.js";
15
+ import {
16
+ WORKSPACE_SECRETS_FILE
17
+ } from "./chunk-3JDU4VRL.js";
18
+ import {
19
+ linkedTableOf,
20
+ tableRefOf
21
+ } from "./chunk-EHP3WPEG.js";
22
+ import {
23
+ clearLocalDboRefs,
24
+ hasNoListBounds,
25
+ isDeadResultItem,
26
+ isEmptyCustomize,
27
+ normalize
28
+ } from "./chunk-L5JYN3NM.js";
29
+ import {
30
+ f,
31
+ input
32
+ } from "./chunk-N5GKCWE5.js";
33
+ import {
34
+ TAGS,
35
+ auth,
36
+ c,
37
+ caught,
38
+ col,
39
+ env,
40
+ inp,
41
+ isTaggedValue,
42
+ isToolsetPath,
43
+ out,
44
+ ref,
45
+ resp,
46
+ setting,
47
+ sys,
48
+ toolset,
49
+ withFilters
50
+ } from "./chunk-OXA6PSZT.js";
51
+ import {
52
+ REFERENCEABLE_KIND_PAYLOAD_KEYS
53
+ } from "./chunk-NZOWWHU5.js";
54
+ import {
55
+ CATALOG_BY_TYPE,
56
+ COLUMN_CONTEXT,
57
+ INPUT_CONTEXT,
58
+ defaultNullable,
59
+ encodeField,
60
+ parseMethod
61
+ } from "./chunk-TTEIYD5P.js";
62
+
63
+ // src/codegen/report.ts
64
+ var AUDIENCE_ORDER = [
65
+ ["workspace", "Problems in your workspace"],
66
+ ["modelling", "Things Xano SDK could not model"],
67
+ ["informational", "Stated so the output is not ambiguous"]
68
+ ];
69
+ var CATEGORY_LABELS = [
70
+ ["verify-mismatch", "Round-trip mismatches", "error", "modelling"],
71
+ ["duplicate-source-guid", "Objects sharing one guid in the source", "error", "workspace"],
72
+ ["unresolved-ref", "References that could not be resolved", "error", "workspace"],
73
+ ["workspace-defect", "Defects in the source workspace", "warning", "workspace"],
74
+ ["decode-only", "Statements the engine writes but will not import", "warning", "workspace"],
75
+ ["blank-binding", "Bindings that are blank upstream", "warning", "workspace"],
76
+ ["name-bound-ref", "References stored by name, not by guid", "warning", "workspace"],
77
+ ["ambiguous-condition", "Conditions that mix AND and OR at one level", "warning", "workspace"],
78
+ ["raw-fallback", "Statements emitted as raw() passthroughs", "warning", "modelling"],
79
+ ["unsupported-section", "Unsupported payload sections", "warning", "modelling"],
80
+ ["file-not-recovered", "Files referenced but not recovered", "warning", "modelling"],
81
+ ["value-fallback", "Values emitted as annotated literals", "warning", "modelling"],
82
+ ["modernized", "Updated to the current form (evaluates differently)", "warning", "modelling"],
83
+ ["path-param-bound", "Unbound {param} segments given an input", "warning", "modelling"],
84
+ ["superseded", "Retired statement versions, carried verbatim", "notice", "informational"],
85
+ ["expected-omission", "Deliberately not carried into the tree", "notice", "informational"],
86
+ ["empty-source", "Objects that were already empty in the source", "notice", "informational"],
87
+ ["unconfigured-stub", "Statements that were never configured", "notice", "informational"],
88
+ ["unportable-id", "Internal ids that are not portable identity", "notice", "informational"],
89
+ ["consolidated-duplicate", "Repeated source records merged by guid", "notice", "informational"],
90
+ ["instance-owned", "Instance state, deliberately not carried as source", "notice", "informational"]
91
+ ];
92
+ var COALESCE_BY_OBJECT = /* @__PURE__ */ new Set(["blank-binding"]);
93
+ var SEVERITY_LABEL = {
94
+ error: "ERROR",
95
+ warning: "WARN",
96
+ notice: "note"
97
+ };
98
+ function location(entry) {
99
+ return entry.path ? `${entry.object} \u2192 ${entry.path}` : entry.object;
100
+ }
101
+ function coalesceByObject(entries) {
102
+ const byObject = /* @__PURE__ */ new Map();
103
+ for (const entry of entries) {
104
+ const found = byObject.get(entry.object);
105
+ if (found) found.push(entry);
106
+ else byObject.set(entry.object, [entry]);
107
+ }
108
+ return [...byObject].map(([object, group]) => {
109
+ if (group.length === 1) return group[0];
110
+ const subjects = [...new Set(group.map((e) => e.subject).filter((s) => s !== void 0))];
111
+ const named = subjects.length > 0 ? `${subjects.join(", ")} \u2014 ` : "";
112
+ return {
113
+ category: group[0].category,
114
+ object,
115
+ detail: `${named}${group.length} references in this object are blank upstream, recovered as \`null\`. The targets were deleted, or the bindings were never made. Fix them upstream, or bind them in the generated source.`
116
+ };
117
+ });
118
+ }
119
+ function groupByCause(entries) {
120
+ const byDetail = /* @__PURE__ */ new Map();
121
+ for (const entry of entries) {
122
+ const found = byDetail.get(entry.detail);
123
+ if (found) found.push(entry);
124
+ else byDetail.set(entry.detail, [entry]);
125
+ }
126
+ return [...byDetail].map(([detail, group]) => ({
127
+ detail,
128
+ count: group.length,
129
+ objects: [...new Set(group.map((e) => e.object))],
130
+ entries: group
131
+ }));
132
+ }
133
+ var OBJECTS_SHOWN = 4;
134
+ function collapseObjects(objects) {
135
+ if (objects.length <= OBJECTS_SHOWN) return objects.join(", ");
136
+ const shown = objects.slice(0, OBJECTS_SHOWN).join(", ");
137
+ return `${shown} and ${objects.length - OBJECTS_SHOWN} more`;
138
+ }
139
+ var DecodeReport = class {
140
+ #entries = [];
141
+ /** Object label → the generated file it was written to. See {@link locate}. */
142
+ #files = /* @__PURE__ */ new Map();
143
+ /** Record a problem. */
144
+ add(entry) {
145
+ const key2 = JSON.stringify([entry.category, entry.object, entry.path, entry.detail, entry.subject]);
146
+ if (this.#seen.has(key2)) return;
147
+ this.#seen.add(key2);
148
+ this.#entries.push(entry);
149
+ }
150
+ #seen = /* @__PURE__ */ new Set();
151
+ /**
152
+ * Record which generated file an object was written to.
153
+ *
154
+ * A finding is keyed by the object it happened in (`query:dbo_direct_query`),
155
+ * but the fix happens in the file the object was written to — and assembly
156
+ * knows that path, because it just chose it. Recording it here is what lets
157
+ * every finding name a file the reader can open.
158
+ *
159
+ * The path only; there is no line. A finding's `path` (`stack[5]`) is a
160
+ * position in the STORED object, and mapping one to a line in the emitted
161
+ * source would mean the printer carrying positions through every expression it
162
+ * builds. The file is the part that makes a finding findable.
163
+ */
164
+ locate(object, file) {
165
+ this.#files.set(object, file);
166
+ }
167
+ /** The generated file an object was written to, when assembly recorded one. */
168
+ #fileFor(object) {
169
+ return this.#files.get(object);
170
+ }
171
+ /** The generated file the object labelled `object` (`query:pick`) was written to, when assembly recorded one. */
172
+ fileOf(object) {
173
+ return this.#fileFor(object);
174
+ }
175
+ /** A position in the entry log, for {@link rewind}. */
176
+ mark() {
177
+ return this.#entries.length;
178
+ }
179
+ /**
180
+ * Drop every entry recorded since `mark`. Used to discard a speculative decode
181
+ * attempt, so the report describes what was emitted rather than what was tried.
182
+ */
183
+ rewind(mark) {
184
+ this.#entries.length = mark;
185
+ }
186
+ /** Every entry, in the order it was recorded. */
187
+ get entries() {
188
+ return this.#entries;
189
+ }
190
+ /** Group and count. The one computation every rendering reads. */
191
+ summarize() {
192
+ const byCategory = [];
193
+ const bySeverity = { error: 0, warning: 0, notice: 0 };
194
+ const byAudience = {
195
+ workspace: 0,
196
+ modelling: 0,
197
+ informational: 0
198
+ };
199
+ let total = 0;
200
+ let distinctCauses = 0;
201
+ for (const [category, label, severity, audience] of CATEGORY_LABELS) {
202
+ const found = this.#entries.filter((e) => e.category === category);
203
+ if (found.length === 0) continue;
204
+ const entries = COALESCE_BY_OBJECT.has(category) ? coalesceByObject(found) : found;
205
+ const causes = groupByCause(entries);
206
+ byCategory.push({
207
+ category,
208
+ label,
209
+ severity,
210
+ audience,
211
+ count: entries.length,
212
+ entries,
213
+ causes
214
+ });
215
+ bySeverity[severity] += entries.length;
216
+ byAudience[audience] += entries.length;
217
+ distinctCauses += causes.length;
218
+ total += entries.length;
219
+ }
220
+ return { total, bySeverity, byAudience, distinctCauses, byCategory };
221
+ }
222
+ /**
223
+ * The headline, or an empty string when there is nothing to say.
224
+ *
225
+ * Answers the two questions a reader has before they start reading: how much
226
+ * of this is repetition, and how much of it is theirs to fix.
227
+ */
228
+ headline() {
229
+ const summary = this.summarize();
230
+ if (summary.total === 0) return "";
231
+ const causes = `${summary.distinctCauses} distinct issue${summary.distinctCauses === 1 ? "" : "s"}`;
232
+ const findings = `${summary.total} finding${summary.total === 1 ? "" : "s"}`;
233
+ const mine = summary.byAudience.workspace;
234
+ const errors = summary.byCategory.filter((g) => g.severity === "error" && g.audience !== "workspace").reduce((n, g) => n + g.count, 0);
235
+ const errorClause = (more) => `${errors}${more} ${errors === 1 ? "is an error" : "are errors"}`;
236
+ const warnings = summary.byCategory.filter((g) => g.severity === "warning" && g.audience !== "workspace").reduce((n, g) => n + g.count, 0);
237
+ const attention = mine === 0 ? errors === 0 ? warnings === 0 ? "none need your attention" : `${warnings} ${warnings === 1 ? "is a warning" : "are warnings"}` : errorClause("") : `${mine} need${mine === 1 ? "s" : ""} your attention` + (errors === 0 ? "" : `; ${errorClause(" more")}`);
238
+ return `${causes} across ${findings}; ${attention}`;
239
+ }
240
+ /** The findings as data — the shape `--report json` and the manifest carry. */
241
+ toJson() {
242
+ const summary = this.summarize();
243
+ return {
244
+ headline: this.headline(),
245
+ total: summary.total,
246
+ bySeverity: summary.bySeverity,
247
+ byAudience: summary.byAudience,
248
+ findings: summary.byCategory.flatMap(
249
+ (group) => group.entries.map((entry) => ({
250
+ category: group.category,
251
+ severity: group.severity,
252
+ audience: group.audience,
253
+ object: entry.object,
254
+ ...entry.path === void 0 ? {} : { path: entry.path },
255
+ ...this.#fileFor(entry.object) === void 0 ? {} : { file: this.#fileFor(entry.object) },
256
+ detail: entry.detail
257
+ }))
258
+ )
259
+ };
260
+ }
261
+ /** The generated README's report section. Empty string when there is nothing to say. */
262
+ renderMarkdown() {
263
+ const summary = this.summarize();
264
+ if (summary.total === 0) return "";
265
+ const lines = ["## What did not round-trip cleanly", "", this.headline(), ""];
266
+ for (const [audience, heading] of AUDIENCE_ORDER) {
267
+ const groups = summary.byCategory.filter((g) => g.audience === audience);
268
+ if (groups.length === 0) continue;
269
+ lines.push(`### ${heading}`, "");
270
+ for (const group of groups) {
271
+ lines.push(
272
+ `#### ${SEVERITY_LABEL[group.severity]} ${group.label} [${group.category}=${group.count}]`,
273
+ ""
274
+ );
275
+ for (const entry of group.entries) {
276
+ lines.push(`- \`${this.#locationOf(entry)}\` \u2014 ${entry.detail}`);
277
+ }
278
+ lines.push("");
279
+ }
280
+ }
281
+ return lines.join("\n");
282
+ }
283
+ /**
284
+ * The CLI summary. Empty string when there is nothing to say.
285
+ *
286
+ * Grouped by root cause by default: a cause that repeats across objects gets
287
+ * one line carrying its count and a collapsed object list, because 58 lines
288
+ * saying one sentence about 58 tools is not 58 times the signal. `full: true`
289
+ * restores the per-entry form for anyone who wants every site; `categories`
290
+ * limits it to those categories.
291
+ */
292
+ renderCli(opts = {}) {
293
+ const summary = this.summarize();
294
+ if (summary.total === 0) return "";
295
+ const lines = [];
296
+ for (const [audience, heading] of AUDIENCE_ORDER) {
297
+ const groups = summary.byCategory.filter(
298
+ (g) => g.audience === audience && (opts.categories === void 0 || opts.categories.includes(g.category))
299
+ );
300
+ if (groups.length === 0) continue;
301
+ lines.push(` ${heading}`);
302
+ for (const group of groups) {
303
+ lines.push(
304
+ ` ${SEVERITY_LABEL[group.severity]} ${group.label} [${group.category}=${group.count}]`
305
+ );
306
+ if (opts.full === true) {
307
+ for (const entry of group.entries) {
308
+ lines.push(` ${this.#locationOf(entry, opts.fileBase)} \u2014 ${entry.detail}`);
309
+ }
310
+ continue;
311
+ }
312
+ for (const cause of group.causes) {
313
+ if (cause.count === 1) {
314
+ lines.push(` ${this.#locationOf(cause.entries[0], opts.fileBase)} \u2014 ${cause.detail}`);
315
+ continue;
316
+ }
317
+ lines.push(` \xD7${cause.count} \u2014 ${cause.detail}`);
318
+ const sites = cause.objects.length === cause.count ? cause.objects.map((o) => this.#label(o, opts.fileBase)) : cause.entries.map((e) => this.#locationOf(e, opts.fileBase));
319
+ lines.push(` in ${collapseObjects(sites)}`);
320
+ }
321
+ }
322
+ }
323
+ return lines.join("\n");
324
+ }
325
+ /**
326
+ * `object → path (file)`, with the file only when assembly recorded one.
327
+ *
328
+ * `base` is what the reader's paths are relative TO. The README sits inside
329
+ * the generated tree, so it prints the bare path; the CLI is read from the
330
+ * project root, so it prints the tree directory too and the path is one a
331
+ * terminal can open.
332
+ */
333
+ #locationOf(entry, base) {
334
+ const file = this.#fileFor(entry.object);
335
+ return file === void 0 ? location(entry) : `${location(entry)} (${base ?? ""}${file})`;
336
+ }
337
+ /** An object with its file appended, for the collapsed list on a grouped line. */
338
+ #label(object, base) {
339
+ const file = this.#fileFor(object);
340
+ return file === void 0 ? object : `${object} (${base ?? ""}${file})`;
341
+ }
342
+ };
343
+
344
+ // src/codegen/prove-diff.ts
345
+ import { appendFileSync } from "fs";
346
+ var MAX_PATHS = 40;
347
+ var MAX_DEPTH = 12;
348
+ var MAX_PREVIEW = 60;
349
+ function sink() {
350
+ return readPathEnvVar("XANOSDK_PROVE_DIFF");
351
+ }
352
+ function preview(v) {
353
+ const json = JSON.stringify(v) ?? "undefined";
354
+ return json.length > MAX_PREVIEW ? `${json.slice(0, MAX_PREVIEW)}\u2026` : json;
355
+ }
356
+ function walk(encoded, stored, path, out2, depth) {
357
+ if (out2.length >= MAX_PATHS || depth > MAX_DEPTH) return;
358
+ const bothObjects = encoded !== null && stored !== null && typeof encoded === "object" && typeof stored === "object";
359
+ if (!bothObjects) {
360
+ if (JSON.stringify(encoded) !== JSON.stringify(stored)) {
361
+ out2.push(`${path}: encoded=${preview(encoded)} stored=${preview(stored)}`);
362
+ }
363
+ return;
364
+ }
365
+ const encodedIsArray = Array.isArray(encoded);
366
+ if (encodedIsArray !== Array.isArray(stored)) {
367
+ out2.push(
368
+ `${path}: shape encoded=${encodedIsArray ? "array" : "object"} stored=${Array.isArray(stored) ? "array" : "object"}`
369
+ );
370
+ return;
371
+ }
372
+ if (encodedIsArray) {
373
+ const a2 = encoded;
374
+ const b2 = stored;
375
+ if (a2.length !== b2.length) out2.push(`${path}: length encoded=${a2.length} stored=${b2.length}`);
376
+ for (let i = 0; i < Math.min(a2.length, b2.length); i++) {
377
+ walk(a2[i], b2[i], `${path}[]`, out2, depth + 1);
378
+ }
379
+ return;
380
+ }
381
+ const a = encoded;
382
+ const b = stored;
383
+ for (const key2 of /* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)])) {
384
+ if (out2.length >= MAX_PATHS) return;
385
+ if (!(key2 in a)) out2.push(`${path}.${key2}: MISSING from encoded (stored=${preview(b[key2])})`);
386
+ else if (!(key2 in b)) out2.push(`${path}.${key2}: EXTRA in encoded (${preview(a[key2])})`);
387
+ else walk(a[key2], b[key2], `${path}.${key2}`, out2, depth + 1);
388
+ }
389
+ }
390
+ function diffKeyPaths(encoded, stored) {
391
+ const out2 = [];
392
+ walk(encoded, stored, "", out2, 0);
393
+ return out2;
394
+ }
395
+ var NOTE_PATHS = 3;
396
+ function recordProveDecline(arm, name, encoded, stored) {
397
+ const diffs = diffKeyPaths(encoded, stored);
398
+ if (diffs.length > 0) {
399
+ const shown = diffs.slice(0, NOTE_PATHS).join("; ");
400
+ const rest = diffs.length - NOTE_PATHS;
401
+ noteDecline(
402
+ `the re-encode disagrees with the stored bytes at ${shown}` + (rest > 0 ? ` (and ${rest} more)` : "")
403
+ );
404
+ }
405
+ const file = sink();
406
+ if (file === void 0 || file === "") return;
407
+ appendFileSync(file, `${JSON.stringify({ arm, name, diffs })}
408
+ `);
409
+ }
410
+ function recordProveAbort(arm, name, why) {
411
+ const file = sink();
412
+ if (file === void 0 || file === "") return;
413
+ appendFileSync(file, `${JSON.stringify({ arm, name, diffs: [`ABORT: ${why}`] })}
414
+ `);
415
+ }
416
+ var currentName = void 0;
417
+ function withDeclineContext(name, body) {
418
+ const previous = currentName;
419
+ currentName = name;
420
+ try {
421
+ return body();
422
+ } finally {
423
+ currentName = previous;
424
+ }
425
+ }
426
+ var pendingNote;
427
+ function noteDecline(why, category) {
428
+ pendingNote ??= category === void 0 ? { why } : { why, category };
429
+ return null;
430
+ }
431
+ function takePendingDecline() {
432
+ const note = pendingNote;
433
+ pendingNote = void 0;
434
+ return note;
435
+ }
436
+ function declineHere(where, category) {
437
+ noteDecline(where, category);
438
+ const file = sink();
439
+ if (file === void 0 || file === "") return null;
440
+ appendFileSync(
441
+ file,
442
+ `${JSON.stringify({ arm: "guard", name: currentName, diffs: [`GUARD: ${where}`] })}
443
+ `
444
+ );
445
+ return null;
446
+ }
447
+
448
+ // src/codegen/context.ts
449
+ var SDK_MODULE = "@xano/sdk";
450
+ var CODEGEN_MODULE = "@xano/sdk/codegen";
451
+ function moduleOrder(a, b) {
452
+ const relative = (m) => m.startsWith(".") ? 1 : 0;
453
+ return relative(a) - relative(b) || (a < b ? -1 : a > b ? 1 : 0);
454
+ }
455
+ var ImportCollector = class {
456
+ #value = /* @__PURE__ */ new Map();
457
+ #type = /* @__PURE__ */ new Map();
458
+ /** Record a value import. Returns the symbol so callers can use it inline. */
459
+ use(module, symbol) {
460
+ let symbols = this.#value.get(module);
461
+ if (!symbols) this.#value.set(module, symbols = /* @__PURE__ */ new Set());
462
+ symbols.add(symbol);
463
+ return symbol;
464
+ }
465
+ /** Record a type-only import. Returns the symbol. */
466
+ useType(module, symbol) {
467
+ let symbols = this.#type.get(module);
468
+ if (!symbols) this.#type.set(module, symbols = /* @__PURE__ */ new Set());
469
+ symbols.add(symbol);
470
+ return symbol;
471
+ }
472
+ /** Fold this collector's symbols into another (used to commit an attempt). */
473
+ mergeInto(target) {
474
+ for (const [module, symbols] of this.#value) {
475
+ for (const symbol of symbols) target.use(module, symbol);
476
+ }
477
+ for (const [module, symbols] of this.#type) {
478
+ for (const symbol of symbols) target.useType(module, symbol);
479
+ }
480
+ }
481
+ /** The file's import block, deduplicated and deterministically ordered. */
482
+ toStatements() {
483
+ const out2 = [];
484
+ for (const module of [...this.#value.keys()].sort(moduleOrder)) {
485
+ out2.push({ kind: "import", module, symbols: [...this.#value.get(module)].sort() });
486
+ }
487
+ for (const module of [...this.#type.keys()].sort(moduleOrder)) {
488
+ out2.push({
489
+ kind: "import",
490
+ module,
491
+ symbols: [...this.#type.get(module)].sort(),
492
+ typeOnly: true
493
+ });
494
+ }
495
+ return out2;
496
+ }
497
+ };
498
+ var BUNDLE_SCOPE = "(bundle)";
499
+ var DecodeContext = class {
500
+ report = new DecodeReport();
501
+ /**
502
+ * Where the decode's caller writes the documentation-token sidecar, as the
503
+ * report names it — `xano/.secrets.json` for a project, `<out>/.secrets.json`
504
+ * for `generate --out`. Only the caller knows the directory.
505
+ */
506
+ secretsFile = WORKSPACE_SECRETS_FILE;
507
+ /**
508
+ * Whether the caller writes that sidecar at all. `--no-secrets` does not, and
509
+ * the report has to say so rather than promise a file and a restored gate.
510
+ */
511
+ writesSecrets = true;
512
+ /** The barrel's `workspace("…")` name when the payload carries no workspace object. */
513
+ fallbackWorkspaceName = "workspace";
514
+ /** The import block of the file currently being generated. */
515
+ imports = new ImportCollector();
516
+ #object = BUNDLE_SCOPE;
517
+ #path = [];
518
+ /**
519
+ * Test id → name for the object currently being decoded, so a statement's
520
+ * stored `mocks` (keyed by id) can be written back as the `mock` map an
521
+ * author reads (keyed by name). Ambient rather than threaded because a mock
522
+ * can sit on a statement nested arbitrarily deep inside the stack.
523
+ */
524
+ #testNames = /* @__PURE__ */ new Map();
525
+ /** Start a fresh import block. Called once per generated file. */
526
+ beginFile() {
527
+ this.imports = new ImportCollector();
528
+ return this.imports;
529
+ }
530
+ /** Record a symbol the current file imports. Returns the symbol. */
531
+ use(module, symbol) {
532
+ return this.imports.use(module, symbol);
533
+ }
534
+ /**
535
+ * Run a decode attempt whose result may be discarded.
536
+ *
537
+ * Dispatch tries several forms and keeps the first that provably re-encodes,
538
+ * so a losing attempt must leave nothing behind — an unused import in a
539
+ * generated file is dead weight at best, and a report entry describing an
540
+ * attempt that was thrown away is simply false. Imports and problems are
541
+ * buffered and merged only when `fn` returns a result.
542
+ */
543
+ speculate(fn) {
544
+ const outerImports = this.imports;
545
+ const mark = this.report.mark();
546
+ this.imports = new ImportCollector();
547
+ let result = null;
548
+ try {
549
+ result = fn();
550
+ return result;
551
+ } finally {
552
+ const attempted = this.imports;
553
+ this.imports = outerImports;
554
+ if (result === null) this.report.rewind(mark);
555
+ else attempted.mergeInto(this.imports);
556
+ }
557
+ }
558
+ /** Record a type-only symbol the current file imports. Returns the symbol. */
559
+ useType(module, symbol) {
560
+ return this.imports.useType(module, symbol);
561
+ }
562
+ /** Run `fn` with report entries attributed to `label` (e.g. `function:signup`). */
563
+ inObject(label, fn) {
564
+ const previousObject = this.#object;
565
+ const previousPath = this.#path;
566
+ this.#object = label;
567
+ this.#path = [];
568
+ try {
569
+ return fn();
570
+ } finally {
571
+ this.#object = previousObject;
572
+ this.#path = previousPath;
573
+ }
574
+ }
575
+ /** Run `fn` with this object's test id→name map in force. */
576
+ withTests(names, fn) {
577
+ const previous = this.#testNames;
578
+ this.#testNames = names;
579
+ try {
580
+ return fn();
581
+ } finally {
582
+ this.#testNames = previous;
583
+ }
584
+ }
585
+ /** The name of the test this id belongs to, if the current object declares it. */
586
+ testName(id2) {
587
+ return this.#testNames.get(id2);
588
+ }
589
+ /** The inverse: test name → id, for proving a decoded mock map re-encodes. */
590
+ testIds() {
591
+ return new Map([...this.#testNames].map(([id2, name]) => [name, id2]));
592
+ }
593
+ /** Run `fn` with `segment` appended to the reported path (e.g. `stack[2]`). */
594
+ at(segment, fn) {
595
+ this.#path.push(segment);
596
+ try {
597
+ return fn();
598
+ } finally {
599
+ this.#path.pop();
600
+ }
601
+ }
602
+ /**
603
+ * Record why this decode declined; last writer wins.
604
+ *
605
+ * Reserved for declines with a KNOWN, stable cause. A decoder that declined
606
+ * because something surprised it should stay silent rather than guess.
607
+ *
608
+ * The note itself lives in `prove-diff`, because the other writer — a guard
609
+ * several frames down inside a shared helper — has no context to reach. See
610
+ * {@link noteDecline} for why there is exactly one store.
611
+ */
612
+ declined(why, category) {
613
+ return noteDecline(why, category);
614
+ }
615
+ /** Read and clear the pending decline note. */
616
+ takeDeclineNote() {
617
+ return takePendingDecline();
618
+ }
619
+ /**
620
+ * Record a problem at the current object/path scope.
621
+ *
622
+ * `subject` names what the entry is about in a word or two, for the categories
623
+ * the report coalesces per object. Optional everywhere else and ignored there.
624
+ */
625
+ problem(category, detail, subject) {
626
+ this.report.add({
627
+ category,
628
+ object: this.#object,
629
+ ...this.#path.length > 0 ? { path: this.#path.join(".") } : {},
630
+ detail,
631
+ ...subject !== void 0 ? { subject } : {}
632
+ });
633
+ }
634
+ };
635
+
636
+ // src/codegen/print.ts
637
+ function id(text) {
638
+ return { kind: "id", text };
639
+ }
640
+ function lit(value) {
641
+ return { kind: "literal", value };
642
+ }
643
+ function call(callee, ...args) {
644
+ return { kind: "call", callee, args };
645
+ }
646
+ function obj2(entries) {
647
+ return { kind: "object", entries };
648
+ }
649
+ function arr(items) {
650
+ return { kind: "array", items };
651
+ }
652
+ function spread(base, entries) {
653
+ return { kind: "spread", base, entries };
654
+ }
655
+ function arrow(params, body) {
656
+ return { kind: "arrow", params, body };
657
+ }
658
+ var IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
659
+ var INDENT = " ";
660
+ function key(name) {
661
+ if (name === "__proto__") return `[${JSON.stringify(name)}]`;
662
+ return IDENTIFIER.test(name) ? name : JSON.stringify(name);
663
+ }
664
+ function fromData(value) {
665
+ if (Array.isArray(value)) return arr(value.map(fromData));
666
+ if (value !== null && typeof value === "object") {
667
+ return obj2(Object.entries(value).map(([k, v]) => [k, fromData(v)]));
668
+ }
669
+ return { kind: "id", text: JSON.stringify(value) ?? "undefined" };
670
+ }
671
+ function printExpr(node, depth = 0) {
672
+ const pad = INDENT.repeat(depth);
673
+ const inner = INDENT.repeat(depth + 1);
674
+ switch (node.kind) {
675
+ case "id":
676
+ return node.text;
677
+ case "literal":
678
+ return printExpr(fromData(node.value), depth);
679
+ case "array": {
680
+ if (node.items.length === 0) return "[]";
681
+ const items = node.items.map((item) => `${inner}${printExpr(item, depth + 1)},`);
682
+ return `[
683
+ ${items.join("\n")}
684
+ ${pad}]`;
685
+ }
686
+ case "object": {
687
+ if (node.entries.length === 0) return "{}";
688
+ const entries = node.entries.map(
689
+ ([k, v]) => `${inner}${key(k)}: ${printExpr(v, depth + 1)},`
690
+ );
691
+ return `{
692
+ ${entries.join("\n")}
693
+ ${pad}}`;
694
+ }
695
+ case "spread": {
696
+ const lines = [`${inner}...${printExpr(node.base, depth + 1)},`];
697
+ for (const [k, v] of node.entries) lines.push(`${inner}${key(k)}: ${printExpr(v, depth + 1)},`);
698
+ return `{
699
+ ${lines.join("\n")}
700
+ ${pad}}`;
701
+ }
702
+ case "arrow": {
703
+ const body = printExpr(node.body, depth);
704
+ const params = [...node.params];
705
+ while (params.length > 0 && !new RegExp(`(^|[^\\w$.])${params[params.length - 1].replace(/\$/g, "\\$")}\\b`).test(body)) {
706
+ params.pop();
707
+ }
708
+ return `(${params.join(", ")}) => ${body.startsWith("{") ? `(${body})` : body}`;
709
+ }
710
+ case "call": {
711
+ if (node.args.length === 0) return `${node.callee}()`;
712
+ return `${node.callee}(${node.args.map((a) => printExpr(a, depth)).join(", ")})`;
713
+ }
714
+ }
715
+ }
716
+ function printModule(stmts) {
717
+ const lines = [];
718
+ for (const stmt of stmts) {
719
+ switch (stmt.kind) {
720
+ case "blank":
721
+ lines.push("");
722
+ break;
723
+ case "comment":
724
+ for (const line of stmt.text.split("\n")) lines.push(line === "" ? "//" : `// ${line}`);
725
+ break;
726
+ case "import": {
727
+ const kw = stmt.typeOnly ? "import type" : "import";
728
+ const symbols = [...stmt.symbols].sort().join(", ");
729
+ lines.push(`${kw} { ${symbols} } from ${JSON.stringify(stmt.module)};`);
730
+ break;
731
+ }
732
+ case "const":
733
+ lines.push(
734
+ `${stmt.exported ? "export " : ""}const ${stmt.name} = ${printExpr(stmt.value)};`
735
+ );
736
+ break;
737
+ case "exportDefault":
738
+ lines.push(`export default ${printExpr(stmt.value)};`);
739
+ break;
740
+ case "exportNamed": {
741
+ if (stmt.symbols.length === 0) break;
742
+ const symbols = [...stmt.symbols].sort();
743
+ const single = `export { ${symbols.join(", ")} };`;
744
+ if (single.length <= 100) lines.push(single);
745
+ else lines.push("export {", ...symbols.map((s) => ` ${s},`), "};");
746
+ break;
747
+ }
748
+ }
749
+ }
750
+ return `${lines.join("\n")}
751
+ `;
752
+ }
753
+
754
+ // src/codegen/ref-index.ts
755
+ var KINDS_BY_PAYLOAD_KEY = (() => {
756
+ const out2 = /* @__PURE__ */ new Map();
757
+ for (const [kind, payloadKey] of Object.entries(REFERENCEABLE_KIND_PAYLOAD_KEYS)) {
758
+ const kinds = out2.get(payloadKey) ?? [];
759
+ kinds.push(kind);
760
+ out2.set(payloadKey, kinds);
761
+ }
762
+ return out2;
763
+ })();
764
+ function discriminate(payloadKey, object) {
765
+ const candidates = KINDS_BY_PAYLOAD_KEY.get(payloadKey);
766
+ if (!candidates || candidates.length === 0) return null;
767
+ if (candidates.length === 1) return candidates[0];
768
+ const type = object.type;
769
+ if (type === "mcp") return "mcp_server";
770
+ if (type === "agent") return "agent";
771
+ return null;
772
+ }
773
+ var RefIndex = class _RefIndex {
774
+ #byGuid = /* @__PURE__ */ new Map();
775
+ /**
776
+ * Walk every payload array once, keying each object by its stored guid.
777
+ *
778
+ * An object with no usable guid is reported rather than assigned a derived one:
779
+ * a derived guid would look correct and quietly point somewhere else.
780
+ */
781
+ static fromPayload(payload, ctx) {
782
+ const index = new _RefIndex();
783
+ for (const payloadKey of KINDS_BY_PAYLOAD_KEY.keys()) {
784
+ const section = payload[payloadKey];
785
+ if (!Array.isArray(section)) continue;
786
+ section.forEach((entry, position) => {
787
+ if (entry === null || typeof entry !== "object") return;
788
+ const object = entry;
789
+ const name = typeof object.name === "string" ? object.name : "";
790
+ const kind = discriminate(payloadKey, object);
791
+ const guid = object.guid;
792
+ if (typeof guid !== "string" || guid === "") {
793
+ ctx.problem(
794
+ "unresolved-ref",
795
+ `${payloadKey}[${position}]${name ? ` "${name}"` : ""} has no stored guid; references to it cannot resolve`
796
+ );
797
+ return;
798
+ }
799
+ if (kind === null) {
800
+ ctx.problem(
801
+ "unresolved-ref",
802
+ `${payloadKey} "${name}" (guid ${guid}) has no recognizable kind; its stored \`type\` is ${JSON.stringify(object.type)}`
803
+ );
804
+ return;
805
+ }
806
+ index.#byGuid.set(guid, {
807
+ guid,
808
+ payloadKey,
809
+ kind,
810
+ name,
811
+ position,
812
+ ...payloadKey === "dbo" && Array.isArray(object.schema) ? { schema: object.schema } : {},
813
+ ...payloadKey === "microservice" ? { ports: servicePorts(object) } : {}
814
+ });
815
+ });
816
+ }
817
+ return index;
818
+ }
819
+ /** The object a guid names, or undefined when the bundle does not contain it. */
820
+ lookup(guid) {
821
+ return this.#byGuid.get(guid);
822
+ }
823
+ /** Every indexed object, in payload-walk order. */
824
+ all() {
825
+ return [...this.#byGuid.values()];
826
+ }
827
+ /**
828
+ * The ONE object of `kind` named `name` — for the references the engine
829
+ * resolves by name (a microservice request's `host`). Undefined when none or
830
+ * several match: a guess would repoint the reference.
831
+ */
832
+ byName(kind, name) {
833
+ const found = this.all().filter((o) => o.kind === kind && o.name === name);
834
+ return found.length === 1 ? found[0] : void 0;
835
+ }
836
+ };
837
+ function servicePorts(object) {
838
+ const seen = /* @__PURE__ */ new Set();
839
+ const containers = object.deployment?.containers;
840
+ for (const container of Array.isArray(containers) ? containers : []) {
841
+ const ports = container?.ports;
842
+ for (const port of Array.isArray(ports) ? ports : []) {
843
+ const servicePort = port?.servicePort;
844
+ if (typeof servicePort === "string" && servicePort !== "") seen.add(servicePort);
845
+ }
846
+ }
847
+ return [...seen];
848
+ }
849
+ function microserviceHost(refs, stored) {
850
+ const input2 = stored?.input;
851
+ const entry = (Array.isArray(input2) ? input2 : []).find((e) => e?.name === "host");
852
+ if (entry?.tag !== "const" || typeof entry.value !== "string" || entry.ignore === true) return void 0;
853
+ if (Array.isArray(entry.filters) && entry.filters.length > 0) return void 0;
854
+ const colon = entry.value.indexOf(":");
855
+ const name = colon === -1 ? entry.value : entry.value.slice(0, colon);
856
+ const port = colon === -1 ? void 0 : entry.value.slice(colon + 1);
857
+ const target = name === "" ? void 0 : refs.byName("microservice", name);
858
+ if (!target) return void 0;
859
+ const ports = target.ports ?? [];
860
+ if (port === void 0 ? ports.length !== 0 : port === "" || ports.length > 0 && !ports.includes(port)) return void 0;
861
+ return { target, port };
862
+ }
863
+ function isReferenceId(v) {
864
+ return typeof v === "string" || typeof v === "number" && Number.isFinite(v);
865
+ }
866
+ function isUnboundId(v) {
867
+ return v === "" || v === 0;
868
+ }
869
+ function isBoundNumericId(v) {
870
+ return typeof v === "number" && !isUnboundId(v);
871
+ }
872
+ function resolveReference(ctx, index, guid, options = {}) {
873
+ const target = index.lookup(guid);
874
+ if (!target) {
875
+ ctx.problem(
876
+ guid === "0" ? "unportable-id" : "unresolved-ref",
877
+ guid === "0" ? "a reference stored as `guid 0` \u2014 an internal row id rather than portable identity, so it cannot resolve to an object in any bundle and is carried verbatim" : `guid ${guid} is not present in this bundle`
878
+ );
879
+ return options.unresolved === "object-ref" ? obj2([
880
+ ["name", lit("")],
881
+ ["guid", lit(guid)]
882
+ ]) : lit(guid);
883
+ }
884
+ const symbol = options.symbolFor?.(target) ?? null;
885
+ if (symbol !== null) return id(symbol);
886
+ return obj2([
887
+ ["name", lit(target.name)],
888
+ ["guid", lit(target.guid)]
889
+ ]);
890
+ }
891
+
892
+ // src/codegen/obj-expr.ts
893
+ var IDENT = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
894
+ var REFERENCE = /^\$(input|var|auth|db)((?:\.[A-Za-z0-9_$]+)*)$/;
895
+ var SETTING = /^\$env\.(\$?[A-Za-z0-9_]+)$/;
896
+ var SYS_BY_NAME = new Map(
897
+ Object.entries(sys).map(([accessor, make]) => [make().value, accessor])
898
+ );
899
+ var Cursor = class {
900
+ #text;
901
+ #at = 0;
902
+ constructor(text) {
903
+ this.#text = text;
904
+ }
905
+ get done() {
906
+ return this.#at >= this.#text.length;
907
+ }
908
+ skipSpace() {
909
+ while (this.#at < this.#text.length && /\s/.test(this.#text[this.#at])) this.#at++;
910
+ }
911
+ /** Consume `token` if it is next, after whitespace. */
912
+ eat(token) {
913
+ this.skipSpace();
914
+ if (!this.#text.startsWith(token, this.#at)) return false;
915
+ this.#at += token.length;
916
+ return true;
917
+ }
918
+ peek() {
919
+ this.skipSpace();
920
+ return this.#text[this.#at];
921
+ }
922
+ /** Consume while `re` matches, returning the run (possibly empty). */
923
+ take(re) {
924
+ this.skipSpace();
925
+ const start = this.#at;
926
+ while (this.#at < this.#text.length && re.test(this.#text[this.#at])) this.#at++;
927
+ return this.#text.slice(start, this.#at);
928
+ }
929
+ /**
930
+ * Consume a JSON double-quoted string, honouring escapes. Returns null when
931
+ * the next token is not a well-formed string.
932
+ */
933
+ takeString() {
934
+ this.skipSpace();
935
+ if (this.#text[this.#at] !== '"') return null;
936
+ let i = this.#at + 1;
937
+ let out2 = "";
938
+ while (i < this.#text.length) {
939
+ const ch = this.#text[i];
940
+ if (ch === "\\") {
941
+ const next = this.#text[i + 1];
942
+ if (next === void 0) return null;
943
+ const decoded = tryJsonParse(`"\\${next}"`);
944
+ if (next === "u") {
945
+ const seq = this.#text.slice(i, i + 6);
946
+ const hex = tryJsonParse(`"${seq}"`);
947
+ if (typeof hex !== "string") return null;
948
+ out2 += hex;
949
+ i += 6;
950
+ continue;
951
+ }
952
+ if (typeof decoded !== "string") return null;
953
+ out2 += decoded;
954
+ i += 2;
955
+ continue;
956
+ }
957
+ if (ch === '"') {
958
+ this.#at = i + 1;
959
+ return out2;
960
+ }
961
+ out2 += ch;
962
+ i++;
963
+ }
964
+ return null;
965
+ }
966
+ };
967
+ function tryJsonParse(text) {
968
+ try {
969
+ return JSON.parse(text);
970
+ } catch {
971
+ return void 0;
972
+ }
973
+ }
974
+ function parseReference(token) {
975
+ const m = REFERENCE.exec(token);
976
+ if (!m) return null;
977
+ const root = m[1];
978
+ const path = m[2].replace(/^\./, "");
979
+ switch (root) {
980
+ case "input":
981
+ return path === "" ? null : { expr: call("inp", lit(path)), built: inp(path), symbols: ["inp"] };
982
+ case "var":
983
+ return path === "" ? null : { expr: call("ref", lit(path)), built: ref(path), symbols: ["ref"] };
984
+ case "db":
985
+ return path === "" ? null : { expr: call("col", lit(path)), built: col(path), symbols: ["col"] };
986
+ case "auth":
987
+ return path === "" ? { expr: call("auth"), built: auth(), symbols: ["auth"] } : { expr: call("auth", lit(path)), built: auth(path), symbols: ["auth"] };
988
+ default:
989
+ return null;
990
+ }
991
+ }
992
+ function parseMember(cur) {
993
+ if (cur.eat("(")) {
994
+ const inner = parseMember(cur);
995
+ return inner && cur.eat(")") ? inner : null;
996
+ }
997
+ const atom = parseAtom(cur);
998
+ if (!atom) return null;
999
+ if (cur.peek() !== "|") return atom;
1000
+ const lifted = liftToValue(atom);
1001
+ if (!lifted) return null;
1002
+ const expr = lifted.expr;
1003
+ let built = lifted.built;
1004
+ const symbols = [...lifted.symbols];
1005
+ const filterExprs = [];
1006
+ let absorbNowCoercion = built.tag === "const:epochms" && built.value === "now";
1007
+ while (cur.eat("|")) {
1008
+ const name = cur.take(/[A-Za-z0-9_]/);
1009
+ if (name === "" || !FILTER_NAMES.includes(name)) return null;
1010
+ const factory = fl[name];
1011
+ if (typeof factory !== "function") return null;
1012
+ const argExprs = [];
1013
+ const argBuilt = [];
1014
+ while (cur.eat(":")) {
1015
+ const arg = parseAtom(cur);
1016
+ if (!arg) return null;
1017
+ if (arg.built !== null && typeof arg.built === "object" && !isTaggedValue(arg.built)) {
1018
+ return null;
1019
+ }
1020
+ argExprs.push(arg.expr);
1021
+ argBuilt.push(arg.built);
1022
+ symbols.push(...arg.symbols);
1023
+ }
1024
+ let filterValue;
1025
+ try {
1026
+ filterValue = factory(...argBuilt);
1027
+ } catch {
1028
+ return null;
1029
+ }
1030
+ if (absorbNowCoercion && name === "to_epochms" && argBuilt.length === 0) {
1031
+ absorbNowCoercion = false;
1032
+ continue;
1033
+ }
1034
+ absorbNowCoercion = false;
1035
+ built = withFilters(built, filterValue);
1036
+ filterExprs.push(call(`fl.${name}`, ...argExprs));
1037
+ }
1038
+ if (filterExprs.length === 0) return { expr, built, symbols };
1039
+ return {
1040
+ expr: call("withFilters", expr, ...filterExprs),
1041
+ built,
1042
+ symbols: [...symbols, "withFilters", "fl"]
1043
+ };
1044
+ }
1045
+ function liftToValue(parsed) {
1046
+ const m = parsed.built;
1047
+ if (isTaggedValue(m)) return { expr: parsed.expr, built: m, symbols: parsed.symbols };
1048
+ if (typeof m === "string") return { expr: call("c.text", lit(m)), built: c.text(m), symbols: ["c"] };
1049
+ if (typeof m === "number") {
1050
+ return Number.isInteger(m) ? { expr: call("c.int", lit(m)), built: c.int(m), symbols: ["c"] } : { expr: call("c.decimal", lit(m)), built: c.decimal(m), symbols: ["c"] };
1051
+ }
1052
+ if (typeof m === "boolean") return { expr: call("c.bool", lit(m)), built: c.bool(m), symbols: ["c"] };
1053
+ return null;
1054
+ }
1055
+ function parseAtom(cur) {
1056
+ const next = cur.peek();
1057
+ if (next === void 0) return null;
1058
+ if (next === "{") return parseRecord(cur);
1059
+ if (next === "[") {
1060
+ if (!cur.eat("[")) return null;
1061
+ const exprs = [];
1062
+ const built = [];
1063
+ const symbols = [];
1064
+ if (cur.eat("]")) return { expr: arr([]), built: [], symbols: [] };
1065
+ for (; ; ) {
1066
+ const member = parseMember(cur);
1067
+ if (!member) return null;
1068
+ exprs.push(member.expr);
1069
+ built.push(member.built);
1070
+ symbols.push(...member.symbols);
1071
+ if (cur.eat(",")) continue;
1072
+ if (cur.eat("]")) break;
1073
+ return null;
1074
+ }
1075
+ return { expr: arr(exprs), built, symbols };
1076
+ }
1077
+ if (next === '"') {
1078
+ const text = cur.takeString();
1079
+ return text === null ? null : { expr: lit(text), built: text, symbols: [] };
1080
+ }
1081
+ const token = cur.take(/[A-Za-z0-9_$.\-+]/);
1082
+ if (token === "") return null;
1083
+ const reference = parseReference(token);
1084
+ if (reference) return reference;
1085
+ if (token === "now") return { expr: call("c.now"), built: c.now(), symbols: ["c"] };
1086
+ const settingMatch = SETTING.exec(token);
1087
+ if (settingMatch) {
1088
+ const name = settingMatch[1];
1089
+ const accessor = SYS_BY_NAME.get(name);
1090
+ if (accessor) {
1091
+ return { expr: call(`sys.${accessor}`), built: setting(name), symbols: ["sys"] };
1092
+ }
1093
+ return name.startsWith("$") ? { expr: call("setting", lit(name)), built: setting(name), symbols: ["setting"] } : { expr: call("env", lit(name)), built: env(name), symbols: ["env"] };
1094
+ }
1095
+ if (token === "true" || token === "false") {
1096
+ const value = token === "true";
1097
+ return { expr: lit(value), built: value, symbols: [] };
1098
+ }
1099
+ if (token === "null") return { expr: call("c.null"), built: c.null(), symbols: ["c"] };
1100
+ if (/^-?\d+(\.\d+)?$/.test(token)) {
1101
+ const n = Number(token);
1102
+ return Number.isFinite(n) && String(n) === token ? { expr: lit(n), built: n, symbols: [] } : null;
1103
+ }
1104
+ return null;
1105
+ }
1106
+ function parseRecord(cur) {
1107
+ if (!cur.eat("{")) return null;
1108
+ const entries = [];
1109
+ const built = {};
1110
+ const symbols = [];
1111
+ if (cur.eat("}")) return { expr: obj2([]), built, symbols };
1112
+ for (; ; ) {
1113
+ const key2 = cur.take(/[A-Za-z0-9_$]/);
1114
+ if (key2 === "" || !IDENT.test(key2)) return null;
1115
+ if (!cur.eat(":")) return null;
1116
+ const member = parseMember(cur);
1117
+ if (!member) return null;
1118
+ if (Object.hasOwn(built, key2)) return null;
1119
+ entries.push([key2, member.expr]);
1120
+ Object.defineProperty(built, key2, { value: member.built, enumerable: true, writable: true, configurable: true });
1121
+ symbols.push(...member.symbols);
1122
+ if (cur.eat(",")) continue;
1123
+ if (cur.eat("}")) break;
1124
+ return null;
1125
+ }
1126
+ return { expr: obj2(entries), built, symbols };
1127
+ }
1128
+ function parseObjExpr(value) {
1129
+ const cur = new Cursor(value);
1130
+ if (cur.peek() !== "{") return null;
1131
+ const parsed = parseRecord(cur);
1132
+ if (!parsed) return null;
1133
+ cur.skipSpace();
1134
+ if (!cur.done) return null;
1135
+ return {
1136
+ expr: call("obj", parsed.expr),
1137
+ built: parsed.built,
1138
+ symbols: ["obj", ...parsed.symbols]
1139
+ };
1140
+ }
1141
+
1142
+ // src/codegen/value.ts
1143
+ function deepEqual(a, b) {
1144
+ if (a === b) return true;
1145
+ if (Array.isArray(a) || Array.isArray(b)) {
1146
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
1147
+ return a.every((item, i) => deepEqual(item, b[i]));
1148
+ }
1149
+ if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
1150
+ const ak = Object.keys(a);
1151
+ const bk = Object.keys(b);
1152
+ if (ak.length !== bk.length) return false;
1153
+ return ak.every(
1154
+ (k) => Object.hasOwn(b, k) && deepEqual(a[k], b[k])
1155
+ );
1156
+ }
1157
+ function attempt(fn) {
1158
+ try {
1159
+ return fn();
1160
+ } catch {
1161
+ return null;
1162
+ }
1163
+ }
1164
+ function sameValue(a, b) {
1165
+ return deepEqual(normalize(a), normalize(b));
1166
+ }
1167
+ var REGEX_PATTERN_FILTERS = /* @__PURE__ */ new Set([
1168
+ "regex_test",
1169
+ "regex_match",
1170
+ "regex_match_all",
1171
+ "regex_matches",
1172
+ "regex_replace",
1173
+ "regex_get_all_matches",
1174
+ "regex_get_first_match"
1175
+ ]);
1176
+ function isBlankObject(value) {
1177
+ return value === "" || value === null;
1178
+ }
1179
+ function splitSlashRegex(value) {
1180
+ const m = /^\/(.*)\/([a-zA-Z]*)$/s.exec(value);
1181
+ return m ? { body: m[1], flags: m[2] } : null;
1182
+ }
1183
+ function encodedTextOf(value) {
1184
+ const m = /^\(("(?:[^"\\]|\\.)*")\)$/s.exec(value);
1185
+ if (m === null) return void 0;
1186
+ try {
1187
+ const text = JSON.parse(m[1]);
1188
+ return typeof text === "string" ? text : void 0;
1189
+ } catch {
1190
+ return void 0;
1191
+ }
1192
+ }
1193
+ function isBlankTag(tag) {
1194
+ return tag.startsWith("const") && tag !== "const" && tag !== "const:obj";
1195
+ }
1196
+ function decodeBase(v, regexPiped) {
1197
+ const bare = { value: v.value, tag: v.tag, filters: [] };
1198
+ const propose = (expr, built, ...symbols) => built && sameValue(built, bare) ? { expr, value: built, symbols } : null;
1199
+ const blankTag = v.value === "" && isBlankTag(v.tag) ? v.tag : null;
1200
+ if (blankTag) {
1201
+ return propose(call("c.blank", lit(blankTag)), attempt(() => c.blank(blankTag)), "c");
1202
+ }
1203
+ switch (v.tag) {
1204
+ case "const": {
1205
+ if (regexPiped) {
1206
+ const parts = splitSlashRegex(v.value);
1207
+ if (parts) {
1208
+ const args = parts.flags ? [lit(parts.body), lit(parts.flags)] : [lit(parts.body)];
1209
+ const built = attempt(() => c.regex(parts.body, parts.flags));
1210
+ const candidate = propose(call("c.regex", ...args), built, "c");
1211
+ if (candidate) return candidate;
1212
+ }
1213
+ return null;
1214
+ }
1215
+ return propose(call("c.text", lit(v.value)), attempt(() => c.text(v.value)), "c");
1216
+ }
1217
+ case "const:encoded": {
1218
+ const text = encodedTextOf(v.value);
1219
+ if (text === void 0 || regexPiped) return null;
1220
+ return propose(call("c.text", lit(text)), attempt(() => c.text(text)), "c");
1221
+ }
1222
+ case "const:int": {
1223
+ const n = Number(v.value);
1224
+ if (Number.isSafeInteger(n)) {
1225
+ const asNumber = propose(call("c.int", lit(n)), attempt(() => c.int(n)), "c");
1226
+ if (asNumber) return asNumber;
1227
+ }
1228
+ return propose(call("c.int", lit(v.value)), attempt(() => c.int(v.value)), "c");
1229
+ }
1230
+ case "const:decimal": {
1231
+ const n = Number(v.value);
1232
+ if (!Number.isFinite(n)) return null;
1233
+ const asNumber = propose(call("c.decimal", lit(n)), c.decimal(n), "c");
1234
+ if (asNumber) return asNumber;
1235
+ return propose(call("c.decimal", lit(v.value)), c.decimal(v.value), "c");
1236
+ }
1237
+ case "const:bool": {
1238
+ const b = v.value === "true";
1239
+ return propose(call("c.bool", lit(b)), c.bool(b), "c");
1240
+ }
1241
+ case "const:null":
1242
+ return propose(call("c.null"), c.null(), "c");
1243
+ // The engine's native current-time constant. `c.now()` is the only authoring
1244
+ // form, and it only reproduces `value:"now"` — every occurrence in a real
1245
+ // workspace is exactly that, and any other value falls through to `rawValue`
1246
+ // rather than being decoded as a "now" it is not.
1247
+ case "const:epochms":
1248
+ return propose(call("c.now"), c.now(), "c");
1249
+ case "const:array":
1250
+ case "const:obj": {
1251
+ if (v.tag === "const:obj" && isBlankObject(v.value)) {
1252
+ return propose(call("c.obj", lit(null)), attempt(() => c.obj(null)), "c");
1253
+ }
1254
+ if (v.tag === "const:obj" && v.value === "null") {
1255
+ const objNull = "const:obj";
1256
+ return propose(call("c.null", lit(objNull)), attempt(() => c.null(objNull)), "c");
1257
+ }
1258
+ const parsed = attempt(() => JSON.parse(v.value));
1259
+ if (parsed === null && v.value !== "null") return null;
1260
+ const isArray = Array.isArray(parsed);
1261
+ if (isArray !== (v.tag === "const:array")) return null;
1262
+ const built = attempt(
1263
+ () => isArray ? c.array(parsed) : c.obj(parsed)
1264
+ );
1265
+ return propose(call(isArray ? "c.array" : "c.obj", lit(parsed)), built, "c");
1266
+ }
1267
+ case "var":
1268
+ return propose(call("ref", lit(v.value)), attempt(() => ref(v.value)), "ref");
1269
+ case "input":
1270
+ return propose(call("inp", lit(v.value)), inp(v.value), "inp");
1271
+ case "auth":
1272
+ return propose(call("auth", lit(v.value)), auth(v.value), "auth");
1273
+ case "col":
1274
+ return propose(call("col", lit(v.value)), col(v.value), "col");
1275
+ case "trycatch":
1276
+ return propose(call("caught", lit(v.value)), caught(v.value), "caught");
1277
+ case "output":
1278
+ return propose(call("out", lit(v.value)), out(v.value), "out");
1279
+ case "response": {
1280
+ const path = parseRespPath(v.value);
1281
+ if (path === null) return null;
1282
+ return propose(
1283
+ path === "" ? call("resp") : call("resp", lit(path)),
1284
+ attempt(() => resp(path)),
1285
+ "resp"
1286
+ );
1287
+ }
1288
+ case "setting": {
1289
+ const isEnvVar = !v.value.startsWith("$");
1290
+ return isEnvVar ? propose(call("env", lit(v.value)), attempt(() => env(v.value)), "env") : propose(call("setting", lit(v.value)), attempt(() => setting(v.value)), "setting");
1291
+ }
1292
+ // The older expression form. `obj()` always emits `const:expr2`, so no
1293
+ // object-building path can reproduce this tag — but `c.expressionLegacy` carries
1294
+ // the source verbatim, which is both exact and readable.
1295
+ case "const:expr":
1296
+ return propose(call("c.expressionLegacy", lit(v.value)), attempt(() => c.expressionLegacy(v.value)), "c");
1297
+ case "const:expr2": {
1298
+ const parsed = parseObjExpr(v.value);
1299
+ if (parsed) {
1300
+ const built = attempt(() => obj(parsed.built));
1301
+ const candidate = propose(parsed.expr, built, ...parsed.symbols);
1302
+ if (candidate) return candidate;
1303
+ }
1304
+ return propose(call("c.expression", lit(v.value)), attempt(() => c.expression(v.value)), "c");
1305
+ }
1306
+ // A toolset-scoped binding. Guarded on the accepted path set rather than
1307
+ // decoded for any value: the authoring type is a closed union, and emitting
1308
+ // a call it rejects would leave the pulled tree failing its own type-check.
1309
+ // An unrecognised name keeps its `rawValue` — exact, and honest about being
1310
+ // a name the SDK does not model.
1311
+ case "toolset":
1312
+ return isToolsetPath(v.value) ? propose(call("toolset", lit(v.value)), toolset(v.value), "toolset") : null;
1313
+ default:
1314
+ return null;
1315
+ }
1316
+ }
1317
+ function filterCallee(name) {
1318
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? `fl.${name}` : `fl[${JSON.stringify(name)}]`;
1319
+ }
1320
+ function literalFilter(stored) {
1321
+ return {
1322
+ expr: lit(stored),
1323
+ value: { value: "", tag: "const", filters: [] },
1324
+ symbols: []
1325
+ };
1326
+ }
1327
+ function decodeFilter(stored) {
1328
+ const known = FILTER_NAMES.includes(stored.name);
1329
+ if (!known || (stored.disabled ?? false) !== false || !Array.isArray(stored.arg)) {
1330
+ return literalFilter(stored);
1331
+ }
1332
+ if (stored.arg.length < ((Object.hasOwn(FILTER_REQUIRED_ARGS, stored.name) ? FILTER_REQUIRED_ARGS[stored.name] : void 0) ?? 0)) {
1333
+ return literalFilter(stored);
1334
+ }
1335
+ if (stored.arg.some((arg) => arg === null || typeof arg !== "object")) return null;
1336
+ const args = [];
1337
+ const symbols = /* @__PURE__ */ new Set(["fl"]);
1338
+ const built = [];
1339
+ for (const arg of stored.arg) {
1340
+ const candidate = decodeValueCandidate(arg);
1341
+ if (!candidate) return literalFilter(stored);
1342
+ args.push(candidate.expr);
1343
+ built.push(candidate.value);
1344
+ for (const symbol of candidate.symbols) symbols.add(symbol);
1345
+ }
1346
+ const factory = fl[stored.name];
1347
+ const encoded = factory ? attempt(() => factory(...built)) : null;
1348
+ if (!encoded || !sameValue(encoded, stored)) return literalFilter(stored);
1349
+ return {
1350
+ expr: call(filterCallee(stored.name), ...args),
1351
+ // A filter is not a value; the caller only reads `expr`/`symbols` here.
1352
+ value: { value: "", tag: "const", filters: [] },
1353
+ symbols: [...symbols]
1354
+ };
1355
+ }
1356
+ function decodeFilterChain(filters) {
1357
+ const exprs = [];
1358
+ const symbols = /* @__PURE__ */ new Set();
1359
+ for (const stored of filters) {
1360
+ const decoded = decodeFilter(stored);
1361
+ if (!decoded) {
1362
+ exprs.push(lit(stored));
1363
+ continue;
1364
+ }
1365
+ exprs.push(decoded.expr);
1366
+ for (const symbol of decoded.symbols) symbols.add(symbol);
1367
+ }
1368
+ return { exprs, symbols: [...symbols] };
1369
+ }
1370
+ function decodeObjSetChain(filters) {
1371
+ const out2 = /* @__PURE__ */ Object.create(null);
1372
+ for (const f2 of filters) {
1373
+ if (f2.name !== "set" || f2.disabled || f2.arg.length !== 2) return null;
1374
+ const [path, member] = f2.arg;
1375
+ if (path.tag !== "const" || (path.filters?.length ?? 0) > 0) return null;
1376
+ const decoded = decodeObjMember(member);
1377
+ if (!decoded) return null;
1378
+ const key2 = parseSetPath(path.value);
1379
+ if (key2 === "__proto__") return null;
1380
+ out2[key2] = decoded.value;
1381
+ }
1382
+ return { ...out2 };
1383
+ }
1384
+ function parseSetPath(stored) {
1385
+ const bracketed = /^\["(.*)"\]$/s.exec(stored);
1386
+ return bracketed ? bracketed[1].replace(/\\(["\\])/g, "$1") : stored;
1387
+ }
1388
+ function parseRespPath(stored) {
1389
+ if (stored === "response") return "";
1390
+ if (!stored.startsWith("response")) return null;
1391
+ let rest = stored.slice("response".length);
1392
+ const segments = [];
1393
+ while (rest.length > 0) {
1394
+ const bare = /^\.([A-Za-z_][A-Za-z0-9_]*)/.exec(rest);
1395
+ if (bare) {
1396
+ segments.push(bare[1]);
1397
+ rest = rest.slice(bare[0].length);
1398
+ continue;
1399
+ }
1400
+ const bracketed = /^\["((?:[^"\\]|\\.)*)"\]/s.exec(rest);
1401
+ if (bracketed) {
1402
+ segments.push(bracketed[1].replace(/\\(["\\])/g, "$1"));
1403
+ rest = rest.slice(bracketed[0].length);
1404
+ continue;
1405
+ }
1406
+ return null;
1407
+ }
1408
+ return segments.join(".");
1409
+ }
1410
+ function decodeObjMember(m) {
1411
+ const filters = Array.isArray(m.filters) ? m.filters : [];
1412
+ if (m.tag === "const:obj" && m.value === "{}") {
1413
+ const nested = decodeObjSetChain(filters);
1414
+ return nested ? { value: nested } : null;
1415
+ }
1416
+ if (filters.length > 0) return null;
1417
+ switch (m.tag) {
1418
+ case "const":
1419
+ return { value: m.value };
1420
+ case "const:null":
1421
+ return { value: null };
1422
+ case "const:bool":
1423
+ return { value: m.value === "true" };
1424
+ case "const:int":
1425
+ case "const:decimal":
1426
+ return { value: Number(m.value) };
1427
+ case "const:array":
1428
+ return attempt(() => ({ value: JSON.parse(m.value) }));
1429
+ default:
1430
+ return null;
1431
+ }
1432
+ }
1433
+ function decodeValueCandidate(v, regexSlot = false) {
1434
+ if (v === null || typeof v !== "object") return null;
1435
+ const filters = Array.isArray(v.filters) ? v.filters : [];
1436
+ if (v.tag === "const:obj" && v.value === "{}" && filters.length > 0) {
1437
+ const record = decodeObjSetChain(filters);
1438
+ const built2 = record ? attempt(() => c.obj(record)) : null;
1439
+ if (built2 && record && sameValue(built2, v)) {
1440
+ return { expr: call("c.obj", lit(record)), value: built2, symbols: ["c"] };
1441
+ }
1442
+ }
1443
+ const base = decodeBase(
1444
+ v,
1445
+ regexSlot || filters.some((filter) => REGEX_PATTERN_FILTERS.has(filter.name))
1446
+ );
1447
+ if (!base) return null;
1448
+ if (filters.length === 0) return base;
1449
+ const symbols = /* @__PURE__ */ new Set([...base.symbols, "withFilters"]);
1450
+ const filterExprs = [];
1451
+ const builtFilters = [];
1452
+ for (const stored of filters) {
1453
+ const decoded = decodeFilter(stored);
1454
+ if (!decoded) return null;
1455
+ filterExprs.push(decoded.expr);
1456
+ builtFilters.push(stored);
1457
+ for (const symbol of decoded.symbols) symbols.add(symbol);
1458
+ }
1459
+ const built = attempt(() => withFilters(base.value, ...builtFilters));
1460
+ if (!built || !sameValue(built, v)) return null;
1461
+ return {
1462
+ expr: call("withFilters", base.expr, ...filterExprs),
1463
+ value: built,
1464
+ symbols: [...symbols]
1465
+ };
1466
+ }
1467
+ function fallbackExpr(v) {
1468
+ const entries = [
1469
+ ["value", lit(v.value)],
1470
+ ["tag", lit(v.tag)]
1471
+ ];
1472
+ if (Array.isArray(v.filters) && v.filters.length > 0) entries.push(["filters", lit(v.filters)]);
1473
+ return call("rawValue", obj2(entries));
1474
+ }
1475
+ function decodeValue(ctx, v, opts = {}) {
1476
+ const candidate = decodeValueCandidate(v, opts.regexPattern === true);
1477
+ if (candidate) {
1478
+ for (const symbol of candidate.symbols) ctx.use(SDK_MODULE, symbol);
1479
+ return candidate.expr;
1480
+ }
1481
+ ctx.use(CODEGEN_MODULE, "rawValue");
1482
+ ctx.problem("value-fallback", describeFallback(v));
1483
+ return fallbackExpr(v);
1484
+ }
1485
+ function describeFallback(v) {
1486
+ const hole = nonValueFilterArg(v);
1487
+ if (hole !== void 0) {
1488
+ return `filter \`${hole.filter}\` stores argument ${hole.index + 1} as ${hole.stored} rather than a value \u2014 the shape an earlier SDK wrote for a trigger input accessor (\`t.action\`) passed as a filter argument, which lost the value it named. Carried verbatim so the bytes do not change; put back the value that was meant (e.g. \`inp("action")\`)`;
1489
+ }
1490
+ if (!TAGS.includes(v.tag)) {
1491
+ return `unknown tag ${v.tag} has no idiomatic form; emitted verbatim`;
1492
+ }
1493
+ if (v.value === "") {
1494
+ return `a blank ${v.tag} \u2014 a reference that names nothing, so there is no target to resolve and no \`${v.tag}\` constructor call that would mean this. Carried verbatim so it keeps meaning exactly what it stores; bind it upstream to give it one`;
1495
+ }
1496
+ return `tag ${v.tag} stores ${JSON.stringify(v.value)}, which no \`c.*\` constructor reproduces exactly; emitted verbatim`;
1497
+ }
1498
+ function nonValueFilterArg(v) {
1499
+ const stack = [v];
1500
+ while (stack.length > 0) {
1501
+ const node = stack.pop();
1502
+ if (node === null || typeof node !== "object" || !Array.isArray(node.filters)) continue;
1503
+ for (const f2 of node.filters) {
1504
+ if (f2 === null || typeof f2 !== "object" || !Array.isArray(f2.arg)) continue;
1505
+ const index = f2.arg.findIndex((a) => a === null || typeof a !== "object");
1506
+ if (index !== -1) return { filter: String(f2.name), index, stored: describeStored(f2.arg[index]) };
1507
+ stack.push(...f2.arg);
1508
+ }
1509
+ }
1510
+ return void 0;
1511
+ }
1512
+ function describeStored(v) {
1513
+ if (v === void 0) return "absent";
1514
+ if (v === null) return "null";
1515
+ if (Array.isArray(v)) return "an array";
1516
+ if (typeof v === "object") return "an object with no `tag`";
1517
+ return `a ${typeof v}`;
1518
+ }
1519
+ function readValueOrBare(ctx, stored) {
1520
+ if (typeof stored === "string" || typeof stored === "number" || typeof stored === "boolean") {
1521
+ return { runtime: stored, expr: lit(stored) };
1522
+ }
1523
+ if (stored === null || typeof stored !== "object") return null;
1524
+ const block = stored;
1525
+ if (typeof block.tag !== "string" || block.value === void 0) return null;
1526
+ const value = {
1527
+ value: block.value,
1528
+ tag: block.tag,
1529
+ filters: Array.isArray(block.filters) ? block.filters : []
1530
+ };
1531
+ return { runtime: value, expr: decodeValue(ctx, value) };
1532
+ }
1533
+
1534
+ // src/codegen/field.ts
1535
+ var INPUT_ONLY_BY_TYPE = { file: "file" };
1536
+ var ENCODER_FIXED = [
1537
+ // `merge` and `hidden` are NOT here: they are authorable field options, which
1538
+ // is what lets a merged/hidden field come back as a readable catalog call.
1539
+ // Together they would be the largest single cause of `rawField()`.
1540
+ ["override", []],
1541
+ ["is_settings_registry", false]
1542
+ ];
1543
+ function sameField(a, b) {
1544
+ return deepEqual2(normalize(a), normalize(b));
1545
+ }
1546
+ function differingKeys(encoded, stored) {
1547
+ const a = normalize(encoded);
1548
+ const b = normalize(stored);
1549
+ if (a === null || b === null || typeof a !== "object" || typeof b !== "object") return [];
1550
+ const keys = /* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)]);
1551
+ return [...keys].filter((key2) => !deepEqual2(a[key2], b[key2])).sort();
1552
+ }
1553
+ function describeDiff(encoded, stored) {
1554
+ const keys = differingKeys(encoded, stored);
1555
+ return keys.length === 0 ? "differs structurally" : `differs at ${keys.join(", ")}`;
1556
+ }
1557
+ function deepEqual2(a, b) {
1558
+ if (a === b) return true;
1559
+ if (Array.isArray(a) || Array.isArray(b)) {
1560
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
1561
+ return a.every((item, i) => deepEqual2(item, b[i]));
1562
+ }
1563
+ if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
1564
+ const ak = Object.keys(a);
1565
+ const bk = Object.keys(b);
1566
+ if (ak.length !== bk.length) return false;
1567
+ return ak.every(
1568
+ (k) => Object.hasOwn(b, k) && deepEqual2(a[k], b[k])
1569
+ );
1570
+ }
1571
+ function unrepresentableKeys(stored) {
1572
+ const record = stored;
1573
+ const fixed = [...ENCODER_FIXED];
1574
+ return fixed.filter(
1575
+ ([key2, value]) => Object.hasOwn(record, key2) && !deepEqual2(normalize({ [key2]: record[key2] }), normalize({ [key2]: value }))
1576
+ ).map(([key2]) => key2);
1577
+ }
1578
+ function colonForm(name, args) {
1579
+ if (name.includes(":")) return null;
1580
+ if (args.length === 0) return name;
1581
+ if (!args.every((a) => typeof a === "number" || typeof a === "string")) return null;
1582
+ const candidate = [name, ...args].join(":");
1583
+ const { name: reName, arg: recovered } = parseMethod(candidate);
1584
+ if (reName !== name || recovered.length !== args.length) return null;
1585
+ return recovered.every((value, i) => value === args[i]) ? candidate : null;
1586
+ }
1587
+ var ENUMERATED_METHODS = new Set(
1588
+ Object.values(FIELD_METHODS).flatMap((methods) => Object.keys(methods))
1589
+ );
1590
+ function recoverMethods(stored) {
1591
+ const out2 = [];
1592
+ for (const method of stored) {
1593
+ if ((method.disabled ?? false) !== false) return null;
1594
+ const args = method.arg ?? [];
1595
+ const shorthand = ENUMERATED_METHODS.has(method.name) ? colonForm(method.name, args) : null;
1596
+ out2.push(shorthand ?? { name: method.name, arg: [...args] });
1597
+ }
1598
+ return out2;
1599
+ }
1600
+ function recoverCustomize(stored) {
1601
+ if (isEmptyCustomize(stored)) return null;
1602
+ if (stored === null || typeof stored !== "object" || Array.isArray(stored)) return void 0;
1603
+ const out2 = {};
1604
+ for (const [name, value] of Object.entries(stored)) {
1605
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
1606
+ const node = value;
1607
+ const known = /* @__PURE__ */ new Set(["hidden", "default", "methods", "required", "customize"]);
1608
+ if (Object.keys(node).some((key2) => !known.has(key2))) return void 0;
1609
+ const methods = recoverMethods(node.methods ?? []);
1610
+ if (methods === null) return void 0;
1611
+ const nested = recoverCustomize(node.customize);
1612
+ if (nested === void 0) return void 0;
1613
+ const recovered = {};
1614
+ if (node.hidden === true) recovered.hidden = true;
1615
+ if (node.required === true) recovered.required = true;
1616
+ if (node.default !== void 0 && node.default !== "") {
1617
+ recovered.default = node.default;
1618
+ }
1619
+ if (methods.length > 0) recovered.methods = methods;
1620
+ if (nested !== null) recovered.customize = nested;
1621
+ out2[name] = recovered;
1622
+ }
1623
+ return out2;
1624
+ }
1625
+ function recoverOptions(stored, context, elide = true) {
1626
+ const options = {};
1627
+ const values = Array.isArray(stored.values) ? stored.values : [];
1628
+ const list = stored.list ?? { min: "", max: "" };
1629
+ const vector = stored.vector ?? { size: 3 };
1630
+ const style = stored.style ?? { type: "single" };
1631
+ const access = stored.access ?? "public";
1632
+ const format = stored.format ?? "";
1633
+ const mode = stored.mode ?? "";
1634
+ const fallbackDefault = stored.default ?? "";
1635
+ if (stored.merge === true || !elide) options.merge = stored.merge === true;
1636
+ const hidden = Array.isArray(stored.hidden) ? stored.hidden : [];
1637
+ if (hidden.length > 0 || !elide) options.hidden = [...hidden];
1638
+ const nullable = stored.nullable ?? false;
1639
+ if (nullable !== defaultNullable(String(stored.type ?? ""), context) || !elide) options.nullable = nullable;
1640
+ if (stored.required || !elide) options.required = stored.required ?? false;
1641
+ if (stored.sensitive || !elide) options.sensitive = stored.sensitive ?? false;
1642
+ if (!Object.hasOwn(stored, "default")) options.noDefault = true;
1643
+ else if (fallbackDefault !== "" || !elide) options.default = fallbackDefault;
1644
+ if (mode !== "" || !elide) options.mode = mode;
1645
+ if (format !== "" || !elide) options.format = format;
1646
+ if (access !== "public" || !elide) options.access = access;
1647
+ if (values.length > 0) options.values = [...values];
1648
+ if (!hasNoListBounds(list)) options.list = { ...list };
1649
+ if (!deepEqual2(vector, { size: 3 })) options.vector = { ...vector };
1650
+ if (style.type === "list") options.array = true;
1651
+ else if (!deepEqual2(style, { type: "single" })) {
1652
+ options.style = { type: style.type };
1653
+ }
1654
+ if (context.includeDescription && stored.description !== void 0 && stored.description !== "") {
1655
+ options.description = stored.description;
1656
+ }
1657
+ const methods = recoverMethods(stored.methods ?? []);
1658
+ if (methods === null) return null;
1659
+ if (methods.length > 0) options.methods = methods;
1660
+ const customize = recoverCustomize(stored.customize);
1661
+ if (customize === void 0) return null;
1662
+ if (customize !== null) options.customize = customize;
1663
+ const children = [];
1664
+ for (const child of storedChildren(stored)) {
1665
+ const childOptions = recoverOptions(child, context);
1666
+ if (childOptions === null) return null;
1667
+ children.push({ name: child.name, type: child.type, ...childOptions });
1668
+ }
1669
+ if (children.length > 0) options.children = children;
1670
+ return options;
1671
+ }
1672
+ function storedChildren(stored) {
1673
+ return stored.children ?? [];
1674
+ }
1675
+ function unbindLocalCustomizeRefs(stored) {
1676
+ const customize = stored.customize;
1677
+ if (customize === null || typeof customize !== "object") return { field: stored, unbound: [] };
1678
+ const cleared = /* @__PURE__ */ new Set();
1679
+ const rewritten = clearLocalDboRefs(customize, cleared);
1680
+ if (cleared.size === 0) return { field: stored, unbound: [] };
1681
+ return { field: { ...stored, customize: rewritten }, unbound: [...cleared].sort() };
1682
+ }
1683
+ function optionsExpr(options, omit = []) {
1684
+ const entries = [];
1685
+ for (const [key2, value] of Object.entries(options)) {
1686
+ if (omit.includes(key2)) continue;
1687
+ entries.push([key2, lit(value)]);
1688
+ }
1689
+ return obj2(entries);
1690
+ }
1691
+ function decodeField(ctx, refs, stored, surface, resolve = {}) {
1692
+ const context = surface === "input" ? INPUT_CONTEXT : COLUMN_CONTEXT;
1693
+ const { field: stored_, unbound } = unbindLocalCustomizeRefs(stored);
1694
+ if (unbound.length > 0) {
1695
+ ctx.problem(
1696
+ "unportable-id",
1697
+ `field "${stored.name}" references ${unbound.join(", ")} inside \`customize\` by LOCAL row id rather than by guid \u2014 an internal id is not portable identity, so it is recovered as unbound (\`dbo=\`). A re-deploy will not re-link it, including back into the workspace it came from`
1698
+ );
1699
+ }
1700
+ stored = stored_;
1701
+ if (stored.name === "" && (stored.type === "" || stored.type === void 0)) {
1702
+ ctx.problem(
1703
+ "workspace-defect",
1704
+ `an ${surface === "input" ? "input" : "column"} has no name and no type \u2014 an editor row that was added and never filled in. Nothing can bind to it (there is no name to bind), and the engine reads no type for it. Remove it upstream, or give it a name and a type. It is carried into the tree as stored so the pull still describes the workspace`,
1705
+ "unnamed, untyped"
1706
+ );
1707
+ }
1708
+ const options = recoverOptions(stored, context);
1709
+ const missing = unrepresentableKeys(stored);
1710
+ if (missing.length > 0) {
1711
+ ctx.use(CODEGEN_MODULE, "rawField");
1712
+ ctx.problem(
1713
+ "value-fallback",
1714
+ `field "${stored.name}" stores ${missing.join(", ")} in a shape no authoring surface can produce; emitted verbatim via rawField()`
1715
+ );
1716
+ return { idiomatic: false, expr: call("rawField", lit(stored)) };
1717
+ }
1718
+ const descriptorLiteral = () => {
1719
+ const descriptor = obj2([
1720
+ ["type", lit(stored.type)],
1721
+ ["options", options === null ? lit({}) : optionsExpr(options)]
1722
+ ]);
1723
+ if (options !== null && sameField(encodeField(stored.name, stored.type, options, context), stored)) {
1724
+ return { idiomatic: false, expr: descriptor };
1725
+ }
1726
+ ctx.use(CODEGEN_MODULE, "rawField");
1727
+ return { idiomatic: false, expr: call("rawField", lit(stored)) };
1728
+ };
1729
+ const literalBecause = (why) => {
1730
+ if (missing.length === 0) {
1731
+ ctx.problem(
1732
+ "value-fallback",
1733
+ `field "${stored.name}" (${stored.type}) emitted as a descriptor literal: ${why}`
1734
+ );
1735
+ }
1736
+ return descriptorLiteral();
1737
+ };
1738
+ if (options === null) {
1739
+ return literalBecause("its options could not be recovered from the stored shape");
1740
+ }
1741
+ const reEncoded = encodeField(stored.name, stored.type, options, context);
1742
+ if (!sameField(reEncoded, stored)) {
1743
+ return literalBecause(`re-encoding the recovered options ${describeDiff(reEncoded, stored)}`);
1744
+ }
1745
+ const ns = ctx.use(SDK_MODULE, surface);
1746
+ const opts = options;
1747
+ let lastRejection = "no catalog form was attempted";
1748
+ const proven = (expr, build) => {
1749
+ let built;
1750
+ try {
1751
+ built = build();
1752
+ } catch (err) {
1753
+ lastRejection = `the catalog constructor threw (${err instanceof Error ? err.message : String(err)})`;
1754
+ return null;
1755
+ }
1756
+ const encoded = encodeField(stored.name, built.type, built.options, context);
1757
+ if (sameField(encoded, stored)) return { idiomatic: true, expr: asInputList(expr) };
1758
+ lastRejection = `the catalog call ${describeDiff(encoded, stored)}`;
1759
+ return null;
1760
+ };
1761
+ const asInputList = (expr) => {
1762
+ if (surface !== "input" || opts.array !== true || expr.kind !== "call") return expr;
1763
+ const last = expr.args[expr.args.length - 1];
1764
+ if (last?.kind !== "object") return expr;
1765
+ const entries = last.entries.filter(([key2]) => key2 !== "array");
1766
+ const args = [...expr.args.slice(0, -1), ...entries.length > 0 ? [obj2(entries)] : []];
1767
+ return call(`${ns}.list`, call(expr.callee, ...args));
1768
+ };
1769
+ const catalog = surface === "input" ? input : f;
1770
+ if (stored.type === "enum") {
1771
+ lastRejection = `its default ${JSON.stringify(opts.default)} is not one of its values, which the \`enum\` constructor refuses`;
1772
+ }
1773
+ const dbLinkGuid = linkedTableOf(stored);
1774
+ if (dbLinkGuid !== null && surface === "input") {
1775
+ const rest = { ...opts };
1776
+ delete rest.merge;
1777
+ const restExpr = optionsExpr(rest);
1778
+ const args = [
1779
+ resolveReference(ctx, refs, dbLinkGuid, { ...resolve, unresolved: "object-ref" })
1780
+ ];
1781
+ if (restExpr.kind === "object" && restExpr.entries.length > 0) args.push(restExpr);
1782
+ const decoded = proven(
1783
+ call(`${ns}.dbLink`, ...args),
1784
+ () => input.dbLink({ name: "", guid: dbLinkGuid }, rest)
1785
+ );
1786
+ if (decoded) return decoded;
1787
+ }
1788
+ const refGuid = tableRefOf(stored);
1789
+ if (refGuid !== null) {
1790
+ const withoutRef = { ...opts, methods: opts.methods.slice(0, -1) };
1791
+ if (withoutRef.methods.length === 0) delete withoutRef.methods;
1792
+ const entries = stored.type === "uuid" ? [["type", lit("uuid")]] : [];
1793
+ for (const [key2, value] of Object.entries(withoutRef)) entries.push([key2, lit(value)]);
1794
+ const args = [
1795
+ resolveReference(ctx, refs, refGuid, { ...resolve, unresolved: "object-ref" })
1796
+ ];
1797
+ const tail = { ...stored.type === "uuid" ? { type: "uuid" } : {}, ...withoutRef };
1798
+ if (entries.length > 0) args.push(obj2(entries));
1799
+ const decoded = proven(
1800
+ call(`${ns}.tableRef`, ...args),
1801
+ () => f.tableRef({ name: "", guid: refGuid }, tail)
1802
+ );
1803
+ if (decoded) return decoded;
1804
+ } else if (stored.type === "enum" && // A stored default outside the values does not type-check as `f.enum(…)`
1805
+ // (`EnumDefault`); the descriptor literal below still carries it.
1806
+ (opts.default === void 0 || opts.default === "" || (opts.values ?? []).some((v) => String(v) === String(opts.default)))) {
1807
+ const rest = optionsExpr(opts, ["values"]);
1808
+ const args = [lit(opts.values ?? [])];
1809
+ if (rest.kind === "object" && rest.entries.length > 0) args.push(rest);
1810
+ const { values, ...restOpts } = opts;
1811
+ const decoded = proven(
1812
+ call(`${ns}.enum`, ...args),
1813
+ () => catalog.enum(
1814
+ values ?? [],
1815
+ restOpts
1816
+ )
1817
+ );
1818
+ if (decoded) return decoded;
1819
+ } else if (stored.type === "vector") {
1820
+ const rest = optionsExpr(opts, ["vector"]);
1821
+ const args = [lit(opts.vector?.size ?? 3)];
1822
+ if (rest.kind === "object" && rest.entries.length > 0) args.push(rest);
1823
+ const { vector, ...restOpts } = opts;
1824
+ const decoded = proven(
1825
+ call(`${ns}.vector`, ...args),
1826
+ () => catalog.vector(
1827
+ vector?.size ?? 3,
1828
+ restOpts
1829
+ )
1830
+ );
1831
+ if (decoded) return decoded;
1832
+ } else if (stored.type === "obj") {
1833
+ const rest = optionsExpr(opts, ["children"]);
1834
+ const children = storedChildren(stored);
1835
+ const args = [
1836
+ obj2(children.map((child) => [child.name, decodeField(ctx, refs, child, surface, resolve).expr]))
1837
+ ];
1838
+ if (rest.kind === "object" && rest.entries.length > 0) args.push(rest);
1839
+ const { children: childOpts, ...restOpts } = opts;
1840
+ const decoded = proven(
1841
+ call(`${ns}.object`, ...args),
1842
+ () => catalog.object(
1843
+ Object.fromEntries(
1844
+ (childOpts ?? []).map(({ name, type, ...rest2 }) => [name, { type, options: rest2 }])
1845
+ ),
1846
+ restOpts
1847
+ )
1848
+ );
1849
+ if (decoded) return decoded;
1850
+ } else {
1851
+ const accessor = (Object.hasOwn(CATALOG_BY_TYPE, stored.type) ? CATALOG_BY_TYPE[stored.type] : void 0) ?? (surface === "input" ? Object.hasOwn(INPUT_ONLY_BY_TYPE, stored.type) ? INPUT_ONLY_BY_TYPE[stored.type] : void 0 : void 0);
1852
+ if (accessor !== void 0) {
1853
+ const [head, leaf] = accessor.split(".");
1854
+ const factory = leaf === void 0 ? catalog[head] : catalog[head][leaf];
1855
+ const candidates = [opts];
1856
+ const bare = (() => {
1857
+ try {
1858
+ return factory({}).options;
1859
+ } catch {
1860
+ return null;
1861
+ }
1862
+ })();
1863
+ if (bare) {
1864
+ const lean = Object.fromEntries(
1865
+ Object.entries(opts).filter(([key2, value]) => !deepEqual2(value, bare[key2]))
1866
+ );
1867
+ if (Object.keys(lean).length < Object.keys(opts).length) candidates.unshift(lean);
1868
+ const full = recoverOptions(stored, context, false);
1869
+ if (full) {
1870
+ const restated = Object.fromEntries(
1871
+ Object.keys(bare).filter((key2) => Object.hasOwn(full, key2)).map((key2) => [key2, full[key2]])
1872
+ );
1873
+ candidates.push({ ...opts, ...restated });
1874
+ }
1875
+ }
1876
+ for (const candidate of candidates) {
1877
+ const rest = optionsExpr(candidate);
1878
+ const args = rest.kind === "object" && rest.entries.length > 0 ? [rest] : [];
1879
+ const decoded = proven(call(`${ns}.${accessor}`, ...args), () => factory(candidate));
1880
+ if (decoded) return decoded;
1881
+ }
1882
+ }
1883
+ }
1884
+ ctx.problem(
1885
+ "value-fallback",
1886
+ `field "${stored.name}" (${stored.type}) emitted as a descriptor literal: ${lastRejection}`
1887
+ );
1888
+ return descriptorLiteral();
1889
+ }
1890
+ function decodeFieldMap(ctx, refs, fields, surface, resolve = {}) {
1891
+ return obj2(
1892
+ fields.map((field) => [
1893
+ field.name,
1894
+ ctx.at(
1895
+ `${surface === "input" ? "input" : "schema"}.${field.name}`,
1896
+ () => decodeField(ctx, refs, field, surface, resolve).expr
1897
+ )
1898
+ ])
1899
+ );
1900
+ }
1901
+ var ARRAY_INDEX_KEY = /^(?:0|[1-9][0-9]{0,9})$/;
1902
+ function decodeTableSchema(ctx, refs, fields, resolve = {}) {
1903
+ if (!fields.some((field) => ARRAY_INDEX_KEY.test(field.name) && Number(field.name) < 2 ** 32 - 1)) {
1904
+ return decodeFieldMap(ctx, refs, fields, "f", resolve);
1905
+ }
1906
+ return arr(
1907
+ fields.map(
1908
+ (field) => spread(
1909
+ ctx.at(`schema.${field.name}`, () => decodeField(ctx, refs, field, "f", resolve).expr),
1910
+ [["name", lit(field.name)]]
1911
+ )
1912
+ )
1913
+ );
1914
+ }
1915
+ function decodeResponse(ctx, stored) {
1916
+ if (stored.length === 0) return void 0;
1917
+ const asValue = (item) => ({
1918
+ value: item.value,
1919
+ tag: item.tag,
1920
+ filters: item.filters ?? []
1921
+ });
1922
+ const live = stored.filter((item) => !isDeadResultItem(item, stored.length));
1923
+ if (live.length < stored.length) {
1924
+ const dropped = stored.length - live.length;
1925
+ ctx.problem(
1926
+ "expected-omission",
1927
+ `${dropped} response item${dropped === 1 ? " is" : "s are"} skipped by the engine \u2014 ${dropped === 1 ? "it sets" : "they set"} \`disabled\`, or ${dropped === 1 ? "names" : "name"} nothing to key the response by \u2014 so ${dropped === 1 ? "it contributes" : "they contribute"} no value and ${dropped === 1 ? "is" : "are"} not carried across`
1928
+ );
1929
+ }
1930
+ if (live.length === 0) return void 0;
1931
+ if (live.length === 1 && live[0].name === "") return decodeValue(ctx, asValue(live[0]));
1932
+ const names = live.map((item) => item.name);
1933
+ if (new Set(names).size !== names.length || names.some((name) => name === "")) {
1934
+ ctx.use(CODEGEN_MODULE, "rawResponse");
1935
+ ctx.problem(
1936
+ "raw-fallback",
1937
+ `the response has ${live.length} live items whose names do not key it (blank or repeated), which the record form cannot carry; emitted verbatim via rawResponse()`
1938
+ );
1939
+ return call("rawResponse", lit(stored));
1940
+ }
1941
+ return obj2(
1942
+ live.map((item) => [item.name, ctx.at(`response.${item.name}`, () => decodeValue(ctx, asValue(item)))])
1943
+ );
1944
+ }
1945
+
1946
+ export {
1947
+ diffKeyPaths,
1948
+ recordProveDecline,
1949
+ recordProveAbort,
1950
+ withDeclineContext,
1951
+ declineHere,
1952
+ SDK_MODULE,
1953
+ CODEGEN_MODULE,
1954
+ DecodeContext,
1955
+ id,
1956
+ lit,
1957
+ call,
1958
+ obj2 as obj,
1959
+ arr,
1960
+ spread,
1961
+ arrow,
1962
+ printExpr,
1963
+ printModule,
1964
+ RefIndex,
1965
+ microserviceHost,
1966
+ isReferenceId,
1967
+ isUnboundId,
1968
+ isBoundNumericId,
1969
+ resolveReference,
1970
+ decodeFilterChain,
1971
+ decodeValue,
1972
+ describeStored,
1973
+ readValueOrBare,
1974
+ deepEqual2 as deepEqual,
1975
+ recoverOptions,
1976
+ decodeField,
1977
+ decodeFieldMap,
1978
+ decodeTableSchema,
1979
+ decodeResponse
1980
+ };
1981
+ //# sourceMappingURL=chunk-TPHWJ7UG.js.map