@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,4750 @@
1
+ import {
2
+ assertOneName,
3
+ noteRunArgs
4
+ } from "./chunk-ZIY7RNUT.js";
5
+ import {
6
+ WORKSPACE_ENV_FILE,
7
+ classifyEnv,
8
+ declaredEnv,
9
+ defaultWorkspaceEnvPath,
10
+ namesInEnvExample,
11
+ parseEnvFile,
12
+ readWorkspaceEnvFile
13
+ } from "./chunk-DAD3ONIS.js";
14
+ import {
15
+ readTrackedBackend
16
+ } from "./chunk-HHN734BU.js";
17
+ import {
18
+ isCI
19
+ } from "./chunk-Q325JKYB.js";
20
+ import {
21
+ backendSlotForFlag,
22
+ slotValueMissing
23
+ } from "./chunk-STSFNCY4.js";
24
+ import {
25
+ defaultWorkspaceSecretsPath,
26
+ readSecretsFile
27
+ } from "./chunk-I4F5TCJH.js";
28
+ import {
29
+ allLandings,
30
+ getEnvironment,
31
+ readEphemeralState
32
+ } from "./chunk-5QU2P5CA.js";
33
+ import {
34
+ isUnwritableError,
35
+ unwritableError
36
+ } from "./chunk-JZGVVJSI.js";
37
+ import {
38
+ isExpired
39
+ } from "./chunk-7G3CTU7I.js";
40
+ import {
41
+ contextFlags,
42
+ setHintContext
43
+ } from "./chunk-NAQDMEHV.js";
44
+ import {
45
+ shellWord
46
+ } from "./chunk-FWD7AL6N.js";
47
+ import {
48
+ buildSeedContentFiles,
49
+ collectNonPublicSeedValues,
50
+ hostedFileArchivePath,
51
+ hostedFileResolver,
52
+ isMissingFile,
53
+ registerSeedHostedFiles
54
+ } from "./chunk-U64O2MXY.js";
55
+ import {
56
+ projectRootFrom
57
+ } from "./chunk-ROY4YAEQ.js";
58
+ import {
59
+ readLockFile,
60
+ readLockFileReport,
61
+ writeLockFile
62
+ } from "./chunk-P2HAGF6H.js";
63
+ import {
64
+ writeData
65
+ } from "./chunk-AWQ7BQTQ.js";
66
+ import {
67
+ expandHome
68
+ } from "./chunk-EUUUMY7J.js";
69
+ import {
70
+ inCredentialScope,
71
+ lastResolvedAuth,
72
+ pinnedWorkspaceMissed
73
+ } from "./chunk-YLDALTWZ.js";
74
+ import {
75
+ assertValidProfileName
76
+ } from "./chunk-QXTKSOFI.js";
77
+ import {
78
+ readEnvVar
79
+ } from "./chunk-X2NL4KUO.js";
80
+ import {
81
+ bundleCapabilities
82
+ } from "./chunk-JGE7CAWB.js";
83
+ import {
84
+ BARE,
85
+ CliError,
86
+ FLAGS,
87
+ GLOBAL_FLAGS,
88
+ LocalFileNotFoundError,
89
+ REFUSES_EMPTY_DOC_TOKEN,
90
+ REFUSES_EMPTY_ENV,
91
+ UsageError,
92
+ detail,
93
+ displayPath,
94
+ envSetArgumentsRefused,
95
+ extraArguments,
96
+ failureCode,
97
+ flagName,
98
+ flagRefFor,
99
+ flagValues,
100
+ getCommand,
101
+ getSubcommand,
102
+ inJsonDocumentScope,
103
+ info,
104
+ isAuthenticatedCommand,
105
+ isCommand,
106
+ isKindShaped,
107
+ isMachineOutput,
108
+ isUsageError,
109
+ jsonWarning,
110
+ liveSubcommandNames,
111
+ mergeJsonWarnings,
112
+ missingArgument,
113
+ movedVerb,
114
+ noteRunAccepted,
115
+ noteRunWarning,
116
+ pastePath,
117
+ pathsShownFrom,
118
+ relForwardSlash,
119
+ renderGlobalHelp,
120
+ renderHelpFor,
121
+ runAccepted,
122
+ runWarnings,
123
+ selectorSpellings,
124
+ setRunFailureExplainer,
125
+ stdoutStyle,
126
+ success,
127
+ tablesCommand,
128
+ takesProfileFlag,
129
+ terminalText,
130
+ unknownCommand,
131
+ unknownFlag,
132
+ unknownHelpTopic,
133
+ unknownSubcommand,
134
+ warn,
135
+ withCliPrefix,
136
+ writeJson
137
+ } from "./chunk-PTHVMXZI.js";
138
+ import {
139
+ KNOWLEDGE_DIR,
140
+ KNOWLEDGE_FILE,
141
+ emit,
142
+ isOsMetadataFile,
143
+ registerAllKinds,
144
+ serializeBundle
145
+ } from "./chunk-MXHSQOC4.js";
146
+ import {
147
+ Xano,
148
+ checkFilterOperands,
149
+ standaloneDefKind
150
+ } from "./chunk-CTMO46PK.js";
151
+ import {
152
+ knowledgeBodiesAllEmpty
153
+ } from "./chunk-LQCMKAJ7.js";
154
+ import {
155
+ checkDecodeOnlyStatements,
156
+ checkExpressionOperands,
157
+ checkInterpolatedValues,
158
+ checkLiveDatasourceTests,
159
+ checkLoopControl,
160
+ checkNonJsonValues,
161
+ checkNullMatchArgs,
162
+ checkPasswordInputHashing,
163
+ checkPathSegmentCandidates,
164
+ checkRegexOperandOrder,
165
+ checkReservedColumnNames,
166
+ checkReservedInputNames,
167
+ checkRunFamilyHosts,
168
+ checkSafeRefMatchArgs,
169
+ checkSearchOperandFilters,
170
+ checkSeed,
171
+ checkStacks,
172
+ checkSwitchFallthrough,
173
+ checkToThrowScope,
174
+ checkUnboundVarRefs,
175
+ checkZipPasswordKeys,
176
+ isQueryExpressionFilter
177
+ } from "./chunk-YGZHHAAB.js";
178
+ import {
179
+ FILTER_NAMES
180
+ } from "./chunk-6HO3NCSJ.js";
181
+ import {
182
+ isRepresentableName,
183
+ safeNames
184
+ } from "./chunk-GSGDWJB5.js";
185
+ import {
186
+ getKind
187
+ } from "./chunk-4POWHT2K.js";
188
+ import {
189
+ WORKSPACE_SECRETS_FILE,
190
+ documentationScopeFlagLabel,
191
+ documentationScopeLabel
192
+ } from "./chunk-3JDU4VRL.js";
193
+ import {
194
+ suggest
195
+ } from "./chunk-UTI5G6OJ.js";
196
+ import {
197
+ DiagnosticBag,
198
+ DiagnosticError,
199
+ isDiagnosticError,
200
+ setDiagnosticSink
201
+ } from "./chunk-2EZ3ZJZZ.js";
202
+ import {
203
+ WORKSPACE_KEY,
204
+ createLockContext,
205
+ displayLockKey,
206
+ emptyLock,
207
+ fileSpellingNote,
208
+ lockKey,
209
+ mergeObserved,
210
+ serializeLock,
211
+ toolsetKindsFromPayload,
212
+ validateLockModel,
213
+ withoutGuidSources
214
+ } from "./chunk-6MR5TI5V.js";
215
+ import {
216
+ shellQuote
217
+ } from "./chunk-5ZSO4T2G.js";
218
+ import {
219
+ HOSTED_FILE_SCHEME,
220
+ HOSTED_ICON_KINDS,
221
+ uncarriedHostedIcons
222
+ } from "./chunk-XNCP4KYO.js";
223
+ import {
224
+ IDENT,
225
+ installLambdaFreeReads,
226
+ installLambdaSyntaxCheck
227
+ } from "./chunk-OXA6PSZT.js";
228
+ import {
229
+ rawDeriveGuid
230
+ } from "./chunk-NZOWWHU5.js";
231
+ import {
232
+ resetLockOverrides,
233
+ seedLockOverrides
234
+ } from "./chunk-4BW2SG2N.js";
235
+
236
+ // src/emit/cli.ts
237
+ import { pathToFileURL as pathToFileURL2, fileURLToPath as fileURLToPath3 } from "url";
238
+ import { existsSync as existsSync2, mkdirSync, readdirSync as readdirSync2, readFileSync as readFileSync3, realpathSync, statSync as statSync3, writeFileSync } from "fs";
239
+ import { basename, dirname as dirname2, isAbsolute, join as join2, relative as relative3, resolve as resolve2 } from "path";
240
+ import { createRequire as createRequire2 } from "module";
241
+
242
+ // src/emit/authoring-site.ts
243
+ import { dirname, relative, resolve, sep } from "path";
244
+ import { fileURLToPath } from "url";
245
+ var OWN_ROOT = dirname(fileURLToPath(import.meta.url)).replace(/[\\/](src[\\/]emit|dist)$/, "");
246
+ function authorFrame(err, entry) {
247
+ const stack = err instanceof Error ? err.stack ?? "" : "";
248
+ const project = projectRootFrom(dirname(resolve(entry))) + sep;
249
+ let first = true;
250
+ for (const line of stack.split("\n").slice(1)) {
251
+ const frame = /(?:file:\/\/)?((?:\/|[A-Za-z]:[\\/])[^\s()]*?):(\d+):(\d+)\)?\s*$/.exec(line);
252
+ if (!frame) continue;
253
+ let file = frame[1];
254
+ if (line.includes("file://")) {
255
+ try {
256
+ file = fileURLToPath(`file://${file}`);
257
+ } catch {
258
+ continue;
259
+ }
260
+ }
261
+ const top = first;
262
+ first = false;
263
+ if (!file.startsWith(project) || file.includes(`${sep}node_modules${sep}`)) continue;
264
+ if (file.startsWith(OWN_ROOT + sep + "src" + sep) || file.startsWith(OWN_ROOT + sep + "dist" + sep)) continue;
265
+ return { site: `${relative(process.cwd(), file) || file}:${frame[2]}:${frame[3]}`, top };
266
+ }
267
+ return void 0;
268
+ }
269
+ function authorFiles(err) {
270
+ const files = [];
271
+ const stack = err.stack;
272
+ for (const line of (typeof stack === "string" ? stack : "").split("\n").slice(1)) {
273
+ const frame = /(?:file:\/\/)?((?:\/|[A-Za-z]:[\\/])[^\s()]*?):\d+:\d+\)?\s*$/.exec(line);
274
+ if (!frame) continue;
275
+ let file = frame[1];
276
+ if (line.includes("file://")) {
277
+ try {
278
+ file = fileURLToPath(`file://${file}`);
279
+ } catch {
280
+ continue;
281
+ }
282
+ }
283
+ if (file.includes(`${sep}node_modules${sep}`)) continue;
284
+ if (file.startsWith(OWN_ROOT + sep + "src" + sep) || file.startsWith(OWN_ROOT + sep + "dist" + sep)) continue;
285
+ if (!files.includes(file)) files.push(file);
286
+ }
287
+ return files;
288
+ }
289
+ var AUTHORING_STACK_DEPTH = 200;
290
+ async function withAuthoringStacks(load) {
291
+ const limit = Error.stackTraceLimit;
292
+ if (typeof limit === "number" && limit >= AUTHORING_STACK_DEPTH) return load();
293
+ Error.stackTraceLimit = AUTHORING_STACK_DEPTH;
294
+ try {
295
+ return await load();
296
+ } finally {
297
+ Error.stackTraceLimit = limit;
298
+ }
299
+ }
300
+ function asUsage(err) {
301
+ Object.defineProperty(err, "name", { value: "UsageError", configurable: true, writable: true });
302
+ }
303
+ function withAuthoringSite(err, entry) {
304
+ if (!(err instanceof Error) || err.code !== void 0) return err;
305
+ const missing = /does not provide an export named '([^']+)'/.exec(err.message);
306
+ if (err instanceof SyntaxError && missing !== null) {
307
+ asUsage(err);
308
+ return err;
309
+ }
310
+ const frame = authorFrame(err, entry);
311
+ if (frame === void 0) return err;
312
+ if (frame.top || Object.getPrototypeOf(err) === Error.prototype) asUsage(err);
313
+ if (!err.message.includes(frame.site)) err.message = `${err.message}
314
+ (thrown while loading ${frame.site})`;
315
+ return err;
316
+ }
317
+
318
+ // src/emit/compile-checks.ts
319
+ function payloadKeyOf(def) {
320
+ registerAllKinds();
321
+ const kind = standaloneDefKind(def);
322
+ return kind === void 0 ? "function" : getKind(kind).payloadKey;
323
+ }
324
+ function checkCompiledDef(def, artifact, strict, raised = []) {
325
+ const encoded = JSON.parse(artifact);
326
+ const payloadKey = payloadKeyOf(def);
327
+ const sections = { [payloadKey]: [encoded] };
328
+ const tables = payloadKey === "dbo" ? [def] : [];
329
+ const allow = new Set(def.diagnostics?.allow ?? []);
330
+ const bag = new DiagnosticBag(strict);
331
+ bag.accepts = (code, subject) => (subject === encoded || subject === def) && allow.has(code);
332
+ for (const d of raised) bag.warn(d.code, d.message, encoded);
333
+ checkNonJsonValues(sections, bag);
334
+ checkStacks(tables, sections, bag, {}, "authored");
335
+ checkExpressionOperands(sections, bag);
336
+ checkInterpolatedValues(sections, bag);
337
+ checkRegexOperandOrder(sections, bag);
338
+ checkDecodeOnlyStatements(sections, bag);
339
+ checkRunFamilyHosts(sections, bag);
340
+ checkLiveDatasourceTests(sections, bag);
341
+ checkLoopControl(sections, bag);
342
+ checkSwitchFallthrough(sections, bag);
343
+ checkSearchOperandFilters(sections, bag);
344
+ checkFilterOperands(sections, bag);
345
+ checkUnboundVarRefs(sections, bag);
346
+ checkToThrowScope(sections, bag);
347
+ checkPasswordInputHashing(sections, bag);
348
+ checkZipPasswordKeys(sections, bag);
349
+ checkSafeRefMatchArgs(sections, bag);
350
+ checkNullMatchArgs(sections, bag);
351
+ checkPathSegmentCandidates(sections, bag);
352
+ checkSeed(tables, bag);
353
+ checkReservedColumnNames(tables, bag);
354
+ checkReservedInputNames(sections, bag);
355
+ bag.flush();
356
+ }
357
+
358
+ // src/validate/filter-names.ts
359
+ var RESOLVABLE = new Set(FILTER_NAMES);
360
+ var QUERY_EXPRESSION_KEYS = /* @__PURE__ */ new Set(["eval", "search", "sort", "aggregate"]);
361
+ function editDistance(a, b) {
362
+ let prev = Array.from({ length: b.length + 1 }, (_, j) => j);
363
+ for (let i = 1; i <= a.length; i++) {
364
+ const curr = [i];
365
+ for (let j = 1; j <= b.length; j++) {
366
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
367
+ curr[j] = Math.min(prev[j] + 1, curr[j - 1] + 1, prev[j - 1] + cost);
368
+ }
369
+ prev = curr;
370
+ }
371
+ return prev[b.length];
372
+ }
373
+ function suggestFilterNames(name) {
374
+ const AFFIX_MAX = 6;
375
+ const affix = (long, short) => (long.startsWith(short) || long.endsWith(short)) && long.length - short.length <= AFFIX_MAX;
376
+ const substr = FILTER_NAMES.filter(
377
+ (r) => name.length >= r.length ? affix(name, r) : affix(r, name)
378
+ ).sort((a, b) => Math.abs(a.length - name.length) - Math.abs(b.length - name.length));
379
+ if (substr.length) return substr.slice(0, 2);
380
+ const near = (d) => d === 1 || d === 2 && name.length >= 6;
381
+ return FILTER_NAMES.map((r) => ({ r, d: editDistance(name, r) })).filter((x) => near(x.d)).sort((a, b) => a.d - b.d).slice(0, 2).map((x) => x.r);
382
+ }
383
+ var SECTION_KIND = {
384
+ dbo: "table",
385
+ app: "api group",
386
+ toolset: "toolset",
387
+ realtime_server: "realtime server",
388
+ channel: "realtime channel",
389
+ message: "realtime message",
390
+ workflow_test: "workflow test"
391
+ };
392
+ var BRANCH_LABEL = {
393
+ if: "then",
394
+ else: "else",
395
+ elif: "elif"
396
+ };
397
+ var STATEMENT_BRANCH_LABEL = {
398
+ "mvp:try_catch": { if: "try", else: "catch", then: "finally" },
399
+ "mvp:switch": { elif: "cases", else: "default" },
400
+ "mvp:switch_case": { if: "body" }
401
+ };
402
+ function expressionFilterNames(source) {
403
+ const names = [];
404
+ for (let i = 0; i < source.length; i++) {
405
+ const ch = source[i];
406
+ if (ch === '"' || ch === "'") {
407
+ for (i++; i < source.length && source[i] !== ch; i++) if (source[i] === "\\") i++;
408
+ continue;
409
+ }
410
+ if (ch !== "|") continue;
411
+ if (source[i + 1] === "|") {
412
+ i++;
413
+ continue;
414
+ }
415
+ const name = /^\s*([A-Za-z_][A-Za-z0-9_]*)/.exec(source.slice(i + 1));
416
+ if (name) names.push(name[1]);
417
+ }
418
+ return names;
419
+ }
420
+ function findUnresolvableFilters(bundle) {
421
+ const findings = [];
422
+ const seen = /* @__PURE__ */ new Map();
423
+ const walk = (node, owner, path, inQuery = false, parentKey = "", stmt = "") => {
424
+ if (Array.isArray(node)) {
425
+ for (const item of node) walk(item, owner, path, inQuery, parentKey, stmt);
426
+ return;
427
+ }
428
+ if (node === null || typeof node !== "object") return;
429
+ const obj = node;
430
+ const own = typeof obj.name === "string" && "context" in obj ? obj.name : parentKey === "context" ? stmt : "";
431
+ const embedded = obj.tag === "const:expr2" && typeof obj.value === "string" ? expressionFilterNames(obj.value).map((name) => ({ name, expr: true })) : [];
432
+ const filters = Array.isArray(obj.filters) ? [...obj.filters, ...embedded] : embedded;
433
+ if (filters.length > 0) {
434
+ for (const f of filters) {
435
+ const fname = f?.name;
436
+ const resolvable = typeof fname === "string" && (RESOLVABLE.has(fname) || inQuery && isQueryExpressionFilter(fname));
437
+ if (typeof fname === "string" && fname !== "" && !resolvable) {
438
+ const key = `${fname}@${owner}`;
439
+ let found = seen.get(key);
440
+ if (found === void 0) {
441
+ found = { finding: { name: fname, location: owner || "(unknown)", suggestions: suggestFilterNames(fname) }, paths: [] };
442
+ seen.set(key, found);
443
+ findings.push(found.finding);
444
+ }
445
+ if (f.expr) found.finding.inExpression = true;
446
+ if (path !== "" && !found.paths.includes(path)) {
447
+ found.paths.push(path);
448
+ found.finding.location = `${owner || "(unknown)"} at ${found.paths.join(", ")}`;
449
+ }
450
+ }
451
+ }
452
+ }
453
+ for (const [key, value] of Object.entries(obj)) {
454
+ const query = inQuery || QUERY_EXPRESSION_KEYS.has(key);
455
+ if (Array.isArray(value) && (key === "run" || path === "" && (key === "result" || key === "input"))) {
456
+ value.forEach((item, i) => {
457
+ const name = item?.name;
458
+ const at = key === "run" ? `${STATEMENT_BRANCH_LABEL[stmt]?.[parentKey] ?? BRANCH_LABEL[parentKey] ?? "stack"}[${i}]` : `${key === "result" ? "response" : "input"}${typeof name === "string" && name !== "" ? `.${name}` : `[${i}]`}`;
459
+ walk(item, owner, path ? `${path}.${at}` : at, query);
460
+ });
461
+ } else walk(value, owner, path, query, key, own);
462
+ }
463
+ };
464
+ const payload = bundle?.payload;
465
+ if (payload === null || typeof payload !== "object" || Array.isArray(payload)) {
466
+ walk(bundle, "", "");
467
+ return findings;
468
+ }
469
+ for (const [section, entries] of Object.entries(payload)) {
470
+ const kind = SECTION_KIND[section] ?? section;
471
+ for (const entry of Array.isArray(entries) ? entries : [entries]) {
472
+ const name = entry?.name;
473
+ walk(entry, typeof name === "string" && name !== "" ? `${kind} "${name}"` : kind, "");
474
+ }
475
+ }
476
+ return findings;
477
+ }
478
+
479
+ // src/workspace/knowledge.ts
480
+ import { readFileSync, readdirSync, statSync } from "fs";
481
+ import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
482
+ import { join, relative as relative2, sep as sep2 } from "path";
483
+ var MAX_KNOWLEDGE_FILE_BYTES = 1024 * 1024;
484
+ function resolveMarker(ref) {
485
+ const base = /^[a-z][a-z0-9+.-]*:/i.test(ref.base) ? ref.base : pathToFileURL(ref.base).href;
486
+ return fileURLToPath2(new URL(ref.path, base));
487
+ }
488
+ function utf8Text(bytes) {
489
+ if (bytes.includes(0)) return { problem: "nul" };
490
+ try {
491
+ return { text: new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes) };
492
+ } catch {
493
+ return { problem: "encoding" };
494
+ }
495
+ }
496
+ function notTextReason(problem, remedy) {
497
+ return problem === "nul" ? `it contains a NUL byte, so it is binary content, not text. ${remedy}` : `it is not valid UTF-8 (binary, or another encoding). ${remedy} \u2014 or, if it is text, re-save it as UTF-8.`;
498
+ }
499
+ function collectRefFiles(dir, itemName, refsWhere, warnings) {
500
+ const out = [];
501
+ const links = [];
502
+ const walk = (cur) => {
503
+ for (const entry of readdirSync(cur, { withFileTypes: true })) {
504
+ const full = join(cur, entry.name);
505
+ const rel = relative2(dir, full).split(sep2).join("/");
506
+ if (entry.isDirectory()) {
507
+ walk(full);
508
+ continue;
509
+ }
510
+ if (entry.isSymbolicLink()) {
511
+ links.push(rel);
512
+ continue;
513
+ }
514
+ if (!entry.isFile()) continue;
515
+ const bytes = readFileSync(full);
516
+ const decoded = utf8Text(bytes);
517
+ if ("problem" in decoded) {
518
+ if (isOsMetadataFile(rel, true)) continue;
519
+ throw new Error(
520
+ `knowledge "${itemName}": reference file "${rel}" under ${refsWhere} cannot ship \u2014 a reference file ships as text, and ${notTextReason(decoded.problem, "Move it out of the directory")}`
521
+ );
522
+ }
523
+ const content = decoded.text;
524
+ const size = bytes.length;
525
+ if (size > MAX_KNOWLEDGE_FILE_BYTES) {
526
+ throw new Error(
527
+ `knowledge "${itemName}": reference file "${rel}" is ${size} bytes, over the ${MAX_KNOWLEDGE_FILE_BYTES}-byte limit the engine accepts. Split it, or move the bulk of it somewhere the agent fetches at run time.`
528
+ );
529
+ }
530
+ out.push({ path: rel, content, size });
531
+ }
532
+ };
533
+ walk(dir);
534
+ if (links.length > 0) {
535
+ links.sort();
536
+ warnings.push({
537
+ code: "knowledge.refs-symlink-skipped",
538
+ message: `knowledge "${itemName}": ${refsWhere} contains ${links.map((l) => `"${l}"`).join(", ")}, ${links.length === 1 ? "a symbolic link" : "symbolic links"}, which ${links.length === 1 ? "does" : "do"} not ship \u2014 a link is not followed. Copy the file it points at into the directory to ship it.`
539
+ });
540
+ }
541
+ out.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
542
+ return out;
543
+ }
544
+ function resolveKnowledge(defs) {
545
+ const resolved = [];
546
+ for (const def of defs) {
547
+ const bodyRef = def.body[KNOWLEDGE_FILE];
548
+ const where = `knowledgeFile("${bodyRef.path}")`;
549
+ let content;
550
+ try {
551
+ const abs = resolveMarker(bodyRef);
552
+ if (statSync(abs).isDirectory()) {
553
+ throw new Error(
554
+ `knowledge "${def.name}": ${where} points at a DIRECTORY. A body is one markdown file; use \`refs: knowledgeDir(...)\` for a folder of reference files.`
555
+ );
556
+ }
557
+ const decoded = utf8Text(readFileSync(abs));
558
+ if ("problem" in decoded) {
559
+ throw new Error(
560
+ `knowledge "${def.name}": ${where} cannot ship \u2014 a body ships as text, and ` + notTextReason(decoded.problem, "Point the body at a markdown file")
561
+ );
562
+ }
563
+ content = decoded.text;
564
+ } catch (err) {
565
+ if (err instanceof Error && /points at a DIRECTORY|cannot ship — a body ships as text/.test(err.message)) throw err;
566
+ throw new (isMissingFile(err) ? LocalFileNotFoundError : Error)(
567
+ `knowledge "${def.name}": cannot read ${where} \u2014 ${err.message}. The path resolves relative to the module that declares the item (its \`import.meta.url\`).`
568
+ );
569
+ }
570
+ let files = [];
571
+ const warnings = [];
572
+ if (def.refs !== void 0) {
573
+ const refsRef = def.refs[KNOWLEDGE_DIR];
574
+ const refsWhere = `knowledgeDir("${refsRef.path}")`;
575
+ const abs = resolveMarker(refsRef);
576
+ try {
577
+ if (!statSync(abs).isDirectory()) {
578
+ throw new Error(
579
+ `knowledge "${def.name}": ${refsWhere} is not a directory. Reference files are a FOLDER the agent searches; a single file belongs in the body.`
580
+ );
581
+ }
582
+ } catch (err) {
583
+ if (err instanceof Error && /is not a directory/.test(err.message)) throw err;
584
+ throw new (isMissingFile(err) ? LocalFileNotFoundError : Error)(
585
+ `knowledge "${def.name}": cannot read ${refsWhere} \u2014 ${err.message}.`
586
+ );
587
+ }
588
+ files = collectRefFiles(abs, def.name, refsWhere, warnings);
589
+ const own = /* @__PURE__ */ new Map([[resolveMarker(bodyRef), where]]);
590
+ for (const base of [bodyRef.base, refsRef.base]) {
591
+ const module = base.startsWith("file:") ? fileURLToPath2(base) : /^[a-z][a-z0-9+.-]*:/i.test(base) ? void 0 : base;
592
+ if (module !== void 0) own.set(module, "the module that declares it");
593
+ }
594
+ const shipped = files.map((f) => ({
595
+ rel: f.path,
596
+ what: own.get(join(abs, ...f.path.split("/"))) ?? (/\.[cm]?[jt]sx?$/i.test(f.path) ? "a source file" : void 0)
597
+ })).filter((f) => f.what !== void 0);
598
+ if (shipped.length > 0) {
599
+ warnings.push({
600
+ code: "knowledge.refs-include-source",
601
+ message: `knowledge "${def.name}": ${refsWhere} contains ${shipped.map((f) => `"${f.rel}" (${f.what})`).join(", ")}, which ${shipped.length === 1 ? "ships" : "ship"} as ${shipped.length === 1 ? "a reference file" : "reference files"} \u2014 everything under the directory is collected. Move ${shipped.length === 1 ? "it" : "them"} out of it, or point \`refs\` at a subdirectory (\`knowledgeDir("./refs", import.meta.url)\`).`
602
+ });
603
+ }
604
+ }
605
+ resolved.push({ name: def.name, content, files, ...warnings.length > 0 ? { warnings } : {} });
606
+ }
607
+ return resolved;
608
+ }
609
+
610
+ // src/values/lambda-syntax.ts
611
+ import { createRequire } from "module";
612
+
613
+ // src/values/lambda-scope.ts
614
+ var PUNCTUATORS = ["...", "=>", "?.", "??", "&&", "||", "==", "!=", "<=", ">="];
615
+ var ID_AT = new RegExp(`^#?${IDENT}`, "u");
616
+ function tokenize(mask) {
617
+ const out = [];
618
+ let nl = false;
619
+ let i = 0;
620
+ while (i < mask.length) {
621
+ const ch = mask[i];
622
+ if (ch === "\n") {
623
+ nl = true;
624
+ i++;
625
+ continue;
626
+ }
627
+ if (/\s/.test(ch)) {
628
+ i++;
629
+ continue;
630
+ }
631
+ const id = ID_AT.exec(mask.slice(i, i + 256));
632
+ if (id) {
633
+ out.push({ text: id[0], kind: "id", nl });
634
+ i += id[0].length;
635
+ } else if (/[0-9]/.test(ch)) {
636
+ const num = /^[0-9][0-9A-Za-z_.]*/.exec(mask.slice(i, i + 64))[0];
637
+ out.push({ text: num, kind: "num", nl });
638
+ i += num.length;
639
+ } else {
640
+ const multi = PUNCTUATORS.find((p) => mask.startsWith(p, i));
641
+ const text = multi ?? ch;
642
+ out.push({ text, kind: "punc", nl });
643
+ i += text.length;
644
+ }
645
+ nl = false;
646
+ }
647
+ return out;
648
+ }
649
+ var OPEN = { "(": ")", "[": "]", "{": "}" };
650
+ var CLOSE = /* @__PURE__ */ new Set([")", "]", "}"]);
651
+ function matchBrackets(toks) {
652
+ const match = new Array(toks.length).fill(-1);
653
+ const stack = [];
654
+ toks.forEach((t, i) => {
655
+ if (t.kind !== "punc") return;
656
+ if (OPEN[t.text] !== void 0) stack.push(i);
657
+ else if (CLOSE.has(t.text)) {
658
+ const open = stack.pop();
659
+ if (open !== void 0 && OPEN[toks[open].text] === t.text) {
660
+ match[open] = i;
661
+ match[i] = open;
662
+ }
663
+ }
664
+ });
665
+ return match;
666
+ }
667
+ var BLOCK_AFTER_WORD = /* @__PURE__ */ new Set(["else", "do", "try", "finally", "catch"]);
668
+ var KEYWORDS = /* @__PURE__ */ new Set([
669
+ "break",
670
+ "case",
671
+ "catch",
672
+ "class",
673
+ "const",
674
+ "continue",
675
+ "debugger",
676
+ "default",
677
+ "delete",
678
+ "do",
679
+ "else",
680
+ "export",
681
+ "extends",
682
+ "false",
683
+ "finally",
684
+ "for",
685
+ "function",
686
+ "if",
687
+ "import",
688
+ "in",
689
+ "instanceof",
690
+ "let",
691
+ "new",
692
+ "null",
693
+ "of",
694
+ "return",
695
+ "super",
696
+ "switch",
697
+ "this",
698
+ "throw",
699
+ "true",
700
+ "try",
701
+ "typeof",
702
+ "var",
703
+ "void",
704
+ "while",
705
+ "with",
706
+ "yield",
707
+ "await",
708
+ "async",
709
+ "undefined"
710
+ ]);
711
+ var CONTROL = /* @__PURE__ */ new Set(["if", "for", "while", "switch", "catch", "with", "return", "typeof", "await", "yield", "new"]);
712
+ var Analysis = class {
713
+ toks;
714
+ match;
715
+ /** Brace index → true when it opens an object literal (or object pattern) rather than a block. */
716
+ objectBrace = /* @__PURE__ */ new Map();
717
+ /** Token indices that are a binding's own declaration site. */
718
+ declSites = /* @__PURE__ */ new Set();
719
+ scopes = [];
720
+ /** Brace indices that open a class body. */
721
+ classBodies = /* @__PURE__ */ new Set();
722
+ /** [from, to] token ranges that are TypeScript type positions, never value reads. */
723
+ typeRanges = [];
724
+ /** [from, to] ranges of function bodies (parameters included), outermost first. */
725
+ functions = [];
726
+ /** Index of the leading `function` keyword of the analysed function, or -1. */
727
+ header;
728
+ constructor(mask, header) {
729
+ this.toks = tokenize(mask);
730
+ this.header = !header ? -1 : this.t(0) === "function" ? 0 : this.t(0) === "async" && this.t(1) === "function" ? 1 : -1;
731
+ this.match = matchBrackets(this.toks);
732
+ this.functions.push([0, this.toks.length]);
733
+ this.classifyBraces();
734
+ this.collect();
735
+ }
736
+ t(i) {
737
+ return this.toks[i]?.text ?? "";
738
+ }
739
+ classifyBraces() {
740
+ const open = [];
741
+ this.toks.forEach((tok, i) => {
742
+ if (tok.kind !== "punc") return;
743
+ if (CLOSE.has(tok.text)) {
744
+ if (open.length > 0 && this.match[open[open.length - 1]] === i) open.pop();
745
+ return;
746
+ }
747
+ if (tok.text === "(" || tok.text === "[") open.push(i);
748
+ if (tok.text !== "{") return;
749
+ const prev = this.toks[i - 1];
750
+ let object;
751
+ if (prev === void 0) object = false;
752
+ else if (prev.text === ":" && prev.kind === "punc") object = !this.statementColon(i - 1, open[open.length - 1]);
753
+ else if (prev.kind === "punc") object = !["=>", ")", "{", "}", ";"].includes(prev.text);
754
+ else if (prev.kind === "id") object = !BLOCK_AFTER_WORD.has(prev.text) && KEYWORDS.has(prev.text);
755
+ else object = false;
756
+ this.objectBrace.set(i, object);
757
+ open.push(i);
758
+ });
759
+ }
760
+ /**
761
+ * Whether the `:` at `colon` ends a `case …:` / `default:` clause or a
762
+ * statement label — after which `{` opens a block — rather than an object
763
+ * key, a ternary's second branch or a type annotation. `enclosing` is the
764
+ * innermost open bracket. Only a colon sitting directly in a block (or at
765
+ * the top level) can be one; there the statement is read back to its start.
766
+ */
767
+ statementColon(colon, enclosing) {
768
+ if (enclosing !== void 0 && (this.t(enclosing) !== "{" || this.objectBrace.get(enclosing) === true)) return false;
769
+ for (let k = (enclosing ?? 0) - 1; k >= 0 && ![";", "{", "}"].includes(this.t(k)); k--) {
770
+ if (this.t(k) === "class") return false;
771
+ }
772
+ const boundary = (k) => k < 0 || k === enclosing || [";", "{", "}", ":"].includes(this.t(k)) || this.toks[k].kind === "id" && BLOCK_AFTER_WORD.has(this.t(k)) || this.t(k) === ")" && this.match[k] > 0 && ["if", "for", "while", "with"].includes(this.t(this.match[k] - 1));
773
+ if (this.t(colon - 1) === "case") return true;
774
+ if (this.toks[colon - 1]?.kind === "id" && boundary(colon - 2) && this.t(colon - 2) !== "?") {
775
+ return this.t(colon - 1) === "default" || !KEYWORDS.has(this.t(colon - 1));
776
+ }
777
+ let questions = 0;
778
+ let colons = 0;
779
+ for (let k = colon - 1; k > (enclosing ?? -1); k--) {
780
+ const closer = CLOSE.has(this.t(k)) ? this.match[k] : -1;
781
+ if (closer >= 0) {
782
+ k = closer;
783
+ continue;
784
+ }
785
+ const text = this.t(k);
786
+ if (text === "case") return questions === colons;
787
+ if (text === ";" || text === "{" || text === "}") return false;
788
+ if (text === "?") questions++;
789
+ if (text === ":") colons++;
790
+ }
791
+ return false;
792
+ }
793
+ /**
794
+ * Skip forward from `i` to the first token in `stops` at bracket depth 0, a
795
+ * closer of an enclosing bracket, or (with `asi`) a line break that ends the
796
+ * statement (never before the first token). `angles` counts `<`/`>` as brackets, for type annotations.
797
+ */
798
+ skip(i, stops, angles = false, asi = true) {
799
+ let depth = 0;
800
+ let angle = 0;
801
+ const start = i;
802
+ for (; i < this.toks.length; i++) {
803
+ const tok = this.toks[i];
804
+ if (depth === 0 && angle === 0 && stops.includes(tok.text)) return i;
805
+ if (tok.kind === "punc") {
806
+ if (OPEN[tok.text] !== void 0) {
807
+ depth++;
808
+ continue;
809
+ }
810
+ if (CLOSE.has(tok.text)) {
811
+ if (depth === 0) return i;
812
+ depth--;
813
+ continue;
814
+ }
815
+ if (angles && tok.text === "<") angle++;
816
+ if (angles && tok.text === ">" && angle > 0) {
817
+ angle--;
818
+ continue;
819
+ }
820
+ }
821
+ if (depth > 0 || angle > 0) continue;
822
+ if (asi && tok.nl && tok.kind !== "punc" && i !== start) {
823
+ const prev = this.toks[i - 1];
824
+ if (prev && (prev.kind !== "punc" || [")", "]", "}"].includes(prev.text))) return i;
825
+ }
826
+ }
827
+ return i;
828
+ }
829
+ declare(name, site, from, to) {
830
+ this.declSites.add(site);
831
+ this.scopes.push({ name, from, to });
832
+ }
833
+ /** Bind every name in the pattern at `i`; returns the index after it. */
834
+ pattern(i, from, to) {
835
+ const tok = this.toks[i];
836
+ if (tok === void 0) return i;
837
+ if (tok.text === "...") return this.pattern(i + 1, from, to);
838
+ if (tok.kind === "id") {
839
+ if (!KEYWORDS.has(tok.text)) this.declare(tok.text, i, from, to);
840
+ return i + 1;
841
+ }
842
+ if (tok.text === "{" || tok.text === "[") {
843
+ const end = this.match[i];
844
+ if (end < 0) return i + 1;
845
+ if (tok.text === "{") this.objectBrace.set(i, true);
846
+ let j = i + 1;
847
+ while (j < end) {
848
+ if (this.t(j) === ",") {
849
+ j++;
850
+ continue;
851
+ }
852
+ if (tok.text === "{") {
853
+ if (this.t(j) === "...") {
854
+ j = this.pattern(j + 1, from, to);
855
+ } else {
856
+ let key = j;
857
+ if (this.t(j) === "[") key = this.match[j] >= 0 ? this.match[j] : j;
858
+ if (this.t(key + 1) === ":") j = this.pattern(key + 2, from, to);
859
+ else if (this.t(j) === ":") j = this.pattern(j + 1, from, to);
860
+ else j = this.pattern(j, from, to);
861
+ }
862
+ } else {
863
+ j = this.pattern(j, from, to);
864
+ }
865
+ if (this.t(j) === "=") j = this.skip(j + 1, [","], false, false);
866
+ if (j < end && this.t(j) !== ",") j = this.skip(j, [","], false, false);
867
+ }
868
+ return end + 1;
869
+ }
870
+ return i + 1;
871
+ }
872
+ /** A parameter list `(` … `)` at `open`, binding into [from, to]. */
873
+ params(open, from, to) {
874
+ const close = this.match[open];
875
+ let j = open + 1;
876
+ while (j < close) {
877
+ if (this.t(j) === ",") {
878
+ j++;
879
+ continue;
880
+ }
881
+ if (this.t(j) === "this" && this.t(j + 1) === ":") {
882
+ j = this.annotation(j + 2, [","]);
883
+ continue;
884
+ }
885
+ j = this.pattern(j, from, to);
886
+ if (this.t(j) === "?") j++;
887
+ if (this.t(j) === ":") j = this.annotation(j + 1, [",", "="]);
888
+ if (this.t(j) === "=") j = this.skip(j + 1, [","], false, false);
889
+ if (j < close && this.t(j) !== ",") j = this.skip(j, [","], false, false);
890
+ }
891
+ }
892
+ /** Index of the `{` opening a body after `)` at `close`, skipping a return-type annotation. */
893
+ bodyBrace(close) {
894
+ let j = close + 1;
895
+ if (this.t(j) === ":") j = this.annotation(j + 1, ["{", "=>"]);
896
+ return this.t(j) === "{" ? j : -1;
897
+ }
898
+ /** Skip a type annotation starting at `from`, recording it as a type position. */
899
+ annotation(from, stops, asi = false) {
900
+ const end = this.skip(from, stops, true, asi);
901
+ this.typeRanges.push([from, end - 1]);
902
+ return end;
903
+ }
904
+ /** The end of an arrow body starting at `start`. */
905
+ arrowEnd(start) {
906
+ if (this.t(start) === "{" && this.match[start] >= 0) return this.match[start];
907
+ return this.skip(start, [",", ";"]);
908
+ }
909
+ enclosingBlock(i) {
910
+ let best = [0, this.toks.length];
911
+ for (let k = i - 1; k >= 0; k--) {
912
+ if (this.t(k) !== "{" || this.objectBrace.get(k)) continue;
913
+ const close = this.match[k];
914
+ if (close > i) {
915
+ best = [k, close];
916
+ break;
917
+ }
918
+ }
919
+ return best;
920
+ }
921
+ enclosingFunction(i) {
922
+ let best = this.functions[0];
923
+ for (const range of this.functions) {
924
+ if (range[0] <= i && range[1] >= i && range[0] >= best[0]) best = range;
925
+ }
926
+ return best;
927
+ }
928
+ collect() {
929
+ const toks = this.toks;
930
+ for (let i = 0; i < toks.length; i++) {
931
+ const tok = toks[i];
932
+ const prev = this.t(i - 1);
933
+ if (prev === "." || prev === "?.") continue;
934
+ if (tok.text === "(" && this.match[i] > i) {
935
+ const close = this.match[i];
936
+ const before = toks[i - 1];
937
+ let arrow = this.t(close + 1) === "=>" ? close + 1 : -1;
938
+ if (arrow < 0 && this.t(close + 1) === ":") {
939
+ const k = this.skip(close + 2, ["=>", "{", ";", ","], true, false);
940
+ if (this.t(k) === "=>") {
941
+ arrow = k;
942
+ this.typeRanges.push([close + 2, k - 1]);
943
+ }
944
+ }
945
+ if (arrow >= 0) {
946
+ const end = this.arrowEnd(arrow + 1);
947
+ this.functions.push([i, end]);
948
+ this.params(i, i, end);
949
+ continue;
950
+ }
951
+ if (before?.text === "catch") {
952
+ const body = close + 1;
953
+ if (this.t(body) === "{" && this.match[body] > body) this.params(i, i, this.match[body]);
954
+ continue;
955
+ }
956
+ const isFunction = before?.text === "function" || before?.kind === "id" && !CONTROL.has(before.text) && (this.t(i - 2) === "function" || this.t(i - 2) === "*") || // A method: `name(` … `) {` directly inside an object literal or class body.
957
+ before?.kind === "id" && !CONTROL.has(before.text) && !KEYWORDS.has(before.text) && this.bodyBrace(close) >= 0 && [",", "{", "}", ";", "get", "set", "async", "static"].includes(this.t(i - 2));
958
+ if (isFunction) {
959
+ const body = this.bodyBrace(close);
960
+ if (body >= 0 && this.match[body] > body) {
961
+ const end = this.match[body];
962
+ this.functions.push([i, end]);
963
+ this.params(i, i, end);
964
+ }
965
+ }
966
+ continue;
967
+ }
968
+ if (tok.kind !== "id") continue;
969
+ if ((tok.text === "as" || tok.text === "satisfies") && toks[i + 1]?.kind === "id" && i > 0) {
970
+ this.typeRanges.push([i + 1, i + 1]);
971
+ continue;
972
+ }
973
+ if ((tok.text === "type" || tok.text === "interface") && toks[i + 1]?.kind === "id" && !toks[i + 1].nl && ["=", "<", "{", "extends"].includes(this.t(i + 2)) && (i === 0 || tok.nl || [";", "{", "}"].includes(prev))) {
974
+ const end = tok.text === "type" ? this.skip(i + 2, [";"], true) : (() => {
975
+ const brace = this.skip(i + 2, ["{"], true, false);
976
+ return this.match[brace] > brace ? this.match[brace] : brace;
977
+ })();
978
+ this.declSites.add(i + 1);
979
+ this.typeRanges.push([i + 1, end]);
980
+ i = end;
981
+ continue;
982
+ }
983
+ if (tok.text === "class") {
984
+ const brace = this.skip(i + 1, ["{"], true, false);
985
+ if (this.t(brace) === "{") {
986
+ this.classBodies.add(brace);
987
+ this.objectBrace.set(brace, false);
988
+ }
989
+ }
990
+ if (this.t(i + 1) === "=>" && !KEYWORDS.has(tok.text)) {
991
+ const end = this.arrowEnd(i + 2);
992
+ this.functions.push([i, end]);
993
+ this.declare(tok.text, i, i, end);
994
+ continue;
995
+ }
996
+ if (tok.text === "let" || tok.text === "const" || tok.text === "var") {
997
+ let range;
998
+ if (prev === "(" && this.t(i - 2) === "for") {
999
+ const close = this.match[i - 1];
1000
+ const body = close + 1;
1001
+ const end = this.t(body) === "{" && this.match[body] > body ? this.match[body] : this.skip(body, [";"]);
1002
+ range = tok.text === "var" ? this.enclosingFunction(i) : [i, end];
1003
+ } else {
1004
+ range = tok.text === "var" ? this.enclosingFunction(i) : this.enclosingBlock(i);
1005
+ }
1006
+ let j = i + 1;
1007
+ for (; ; ) {
1008
+ j = this.pattern(j, range[0], range[1]);
1009
+ if (this.t(j) === "!") j++;
1010
+ if (this.t(j) === ":") j = this.annotation(j + 1, ["=", ",", ";", "of", "in"], true);
1011
+ if (this.t(j) === "=") j = this.skip(j + 1, [",", ";"]);
1012
+ if (this.t(j) !== ",") break;
1013
+ j++;
1014
+ }
1015
+ continue;
1016
+ }
1017
+ if ((tok.text === "function" || tok.text === "class") && toks[i + 1]?.kind === "id") {
1018
+ const nameAt = i + 1;
1019
+ const [from, to] = tok.text === "function" ? this.enclosingFunction(i) : this.enclosingBlock(i);
1020
+ if (i === this.header) continue;
1021
+ this.declare(this.t(nameAt), nameAt, from, to);
1022
+ }
1023
+ }
1024
+ }
1025
+ /** Whether the identifier at `i` is an object-literal key rather than a read. */
1026
+ isKey(i) {
1027
+ const prev = this.t(i - 1);
1028
+ const next = this.t(i + 1);
1029
+ let opener = -1;
1030
+ if (prev === "{") opener = i - 1;
1031
+ else if (prev === "," || ["get", "set", "async"].includes(prev)) {
1032
+ let depth = 0;
1033
+ for (let k = i - 1; k >= 0; k--) {
1034
+ const t = this.t(k);
1035
+ if (CLOSE.has(t)) depth++;
1036
+ else if (OPEN[t] !== void 0) {
1037
+ if (depth === 0) {
1038
+ opener = k;
1039
+ break;
1040
+ }
1041
+ depth--;
1042
+ }
1043
+ }
1044
+ }
1045
+ if (opener < 0 || this.t(opener) !== "{" || !this.objectBrace.get(opener)) return false;
1046
+ return next === ":" || next === "(";
1047
+ }
1048
+ /** Index of the bracket directly enclosing token `i`, or -1. */
1049
+ opener(i) {
1050
+ for (let k = i - 1; k >= 0; k--) {
1051
+ const m = this.match[k];
1052
+ if (OPEN[this.t(k)] !== void 0 && (m > i || m < 0)) return k;
1053
+ if (CLOSE.has(this.t(k)) && m >= 0) k = m;
1054
+ }
1055
+ return -1;
1056
+ }
1057
+ /** A class member's name: `total = 1`, `total: T`, `total() {}`, `static total`. */
1058
+ isClassMember(i) {
1059
+ if (!this.classBodies.has(this.opener(i))) return false;
1060
+ const prev = this.t(i - 1);
1061
+ const lead = ["{", ";", "}", "static", "readonly", "private", "public", "protected", "declare", "override", "accessor", "async", "get", "set", "*"];
1062
+ if (!lead.includes(prev) && !this.toks[i].nl) return false;
1063
+ const next = this.toks[i + 1];
1064
+ return next === void 0 || next.nl || ["=", ";", ":", "?", "!", "(", "}", "<"].includes(next.text);
1065
+ }
1066
+ /** A statement label (`total: for …`) or a jump to one (`continue total`). */
1067
+ isLabel(i) {
1068
+ const prev = this.t(i - 1);
1069
+ if ((prev === "break" || prev === "continue") && !this.toks[i].nl) return true;
1070
+ if (this.t(i + 1) !== ":") return false;
1071
+ const asi = this.toks[i].nl && this.toks[i - 1]?.kind !== "punc";
1072
+ if (!(i === 0 || asi || [";", "{", "}"].includes(prev))) return false;
1073
+ const open = this.opener(i);
1074
+ return open < 0 || this.t(open) === "{" && !this.objectBrace.get(open) && !this.classBodies.has(open);
1075
+ }
1076
+ /** Whether token `i` sits in a TypeScript type position. */
1077
+ inType(i) {
1078
+ return this.typeRanges.some(([from, to]) => from <= i && i <= to);
1079
+ }
1080
+ /** Whether some declaration of `name` encloses token `i`. */
1081
+ shadowed(name, i) {
1082
+ return this.scopes.some((s) => s.name === name && s.from <= i && i <= s.to);
1083
+ }
1084
+ };
1085
+ function isFreeRead(analysis, i) {
1086
+ const toks = analysis.toks;
1087
+ const tok = toks[i];
1088
+ const prev = toks[i - 1]?.text;
1089
+ if (prev === "." || prev === "?.") return false;
1090
+ if (analysis.header >= 0 && i <= analysis.header + 2) return false;
1091
+ if (analysis.declSites.has(i)) return false;
1092
+ if (analysis.isKey(i)) return false;
1093
+ if (analysis.isClassMember(i) || analysis.isLabel(i) || analysis.inType(i)) return false;
1094
+ return !analysis.shadowed(tok.text, i);
1095
+ }
1096
+ function readsFreeName(mask, name) {
1097
+ const analysis = new Analysis(mask, true);
1098
+ return analysis.toks.some((tok, i) => tok.kind === "id" && tok.text === name && isFreeRead(analysis, i));
1099
+ }
1100
+ function freeReads(mask) {
1101
+ const analysis = new Analysis(mask, false);
1102
+ const seen = /* @__PURE__ */ new Set();
1103
+ analysis.toks.forEach((tok, i) => {
1104
+ if (tok.kind !== "id" || tok.text.startsWith("#") || KEYWORDS.has(tok.text) || seen.has(tok.text)) return;
1105
+ if (isFreeRead(analysis, i)) seen.add(tok.text);
1106
+ });
1107
+ return [...seen];
1108
+ }
1109
+
1110
+ // src/values/lambda-syntax.ts
1111
+ function loadEsbuild() {
1112
+ try {
1113
+ return createRequire(import.meta.url)("esbuild");
1114
+ } catch {
1115
+ return void 0;
1116
+ }
1117
+ }
1118
+ var PREFIX = "async function __xanosdk_lambda() {\n";
1119
+ function installNodeLambdaChecks() {
1120
+ installLambdaFreeReads(freeReads);
1121
+ const esbuild = loadEsbuild();
1122
+ if (esbuild === void 0) return;
1123
+ installLambdaSyntaxCheck((body) => {
1124
+ try {
1125
+ esbuild.transformSync(`${PREFIX}${body}
1126
+ }`, { loader: "ts" });
1127
+ return void 0;
1128
+ } catch (err) {
1129
+ const first = err.errors?.[0];
1130
+ if (first?.location == null || typeof first.text !== "string") return void 0;
1131
+ const lines = body.split("\n");
1132
+ const line = (first.location.line ?? 2) - 1;
1133
+ const past = line > lines.length;
1134
+ return {
1135
+ line: past ? lines.length : Math.max(line, 1),
1136
+ column: past ? (lines[lines.length - 1] ?? "").length + 1 : (first.location.column ?? 0) + 1,
1137
+ message: first.text,
1138
+ lineText: past ? lines[lines.length - 1] ?? "" : first.location.lineText ?? ""
1139
+ };
1140
+ }
1141
+ });
1142
+ }
1143
+
1144
+ // src/emit/bundle-input.ts
1145
+ import { existsSync, readFileSync as readFileSync2, statSync as statSync2 } from "fs";
1146
+ function assertBundleInput(args, target) {
1147
+ if (args.bundle === void 0 && args.file === void 0) throw missingArgument("file", target);
1148
+ if (args.bundle === void 0) return;
1149
+ if (args.file !== void 0) {
1150
+ throw new UsageError(`Pass either an entry <file> or --bundle <path>, not both.`, { hintFor: target });
1151
+ }
1152
+ }
1153
+ function assertEntryFile(args) {
1154
+ if (args.bundle === void 0 && args.file !== void 0) assertEntryExists(args.file);
1155
+ }
1156
+ function assertBundleFile(args, target, consequence) {
1157
+ if (args.bundle === void 0) return;
1158
+ const tail = `${consequence === void 0 ? "" : ` ${consequence}`} Pass the path of a bundle \`xanosdk export <entry> --out <path>\` wrote.`;
1159
+ const typed = args.bundlePositional === true ? `"${args.bundle}"` : `\`--bundle ${args.bundle}\``;
1160
+ if (!existsSync(args.bundle) || !statSync2(args.bundle).isFile()) {
1161
+ const Refusal = existsSync(args.bundle) ? UsageError : LocalFileNotFoundError;
1162
+ throw new Refusal(`${typed} ${existsSync(args.bundle) ? "is not a file" : "does not exist"}.${tail}`, {
1163
+ hintFor: target
1164
+ });
1165
+ }
1166
+ const text = readFileSync2(args.bundle, "utf8");
1167
+ const why = bundleTextProblem(text);
1168
+ if (why !== void 0) throw new UsageError(`${typed} is not a bundle: ${why}.${tail}`, { hintFor: target });
1169
+ const bad = target.command === "workspace" ? [] : bundleEnvNames(text).filter((n) => !isRepresentableName(n));
1170
+ if (bad.length > 0) {
1171
+ const one = bad.length === 1;
1172
+ throw new UsageError(
1173
+ `${typed} sets ${bad.map((n) => `"${safeNames([n])}"`).join(", ")} in its env, which ${one ? "is not a usable env var name" : "are not usable env var names"}. ${envNameRule()} ${consequence === void 0 ? "" : `${consequence} `}Rename ${one ? "it" : "them"} in the source's \`workspaceConfig({ env })\` and \`xano/.env\`, and export the bundle again.`,
1174
+ { hintFor: target }
1175
+ );
1176
+ }
1177
+ const unread = target.command === "workspace" ? void 0 : uncompiledBundleProblem(text);
1178
+ if (unread !== void 0) {
1179
+ throw new UsageError(
1180
+ `${typed} ${unread}, so it would land them empty. It was built in code without the Node compile (\`export()\` / \`emitBundle()\`). ${consequence === void 0 ? "" : `${consequence} `}Write it with \`xanosdk export <entry> --out <path>\` or \`writeBundle(app, path)\` from \`@xano/sdk/node\`, or deploy the entry itself.`,
1181
+ { hintFor: target }
1182
+ );
1183
+ }
1184
+ }
1185
+ function uncompiledBundleProblem(text) {
1186
+ let payload;
1187
+ let knowledgeRead;
1188
+ try {
1189
+ const parsed = JSON.parse(text);
1190
+ payload = parsed.payload ?? {};
1191
+ knowledgeRead = parsed.knowledge_read === true;
1192
+ } catch {
1193
+ return void 0;
1194
+ }
1195
+ const pending = HOSTED_ICON_KINDS.flatMap(
1196
+ (kind) => (Array.isArray(payload[kind]) ? payload[kind] : []).filter((row) => Array.isArray(row?.icons) && row.icons.some((icon) => String(icon?.src).startsWith(`${HOSTED_FILE_SCHEME}pending/`))).map((row) => `${kind} "${String(row.name ?? "")}"`)
1197
+ );
1198
+ if (pending.length > 0) return `has unresolved hostedFile() icons (${pending.join(", ")})`;
1199
+ if (!knowledgeRead && knowledgeBodiesAllEmpty(payload)) {
1200
+ const knowledge = payload.knowledge;
1201
+ const names = knowledge.map((k) => `"${String(k?.name ?? "")}"`).join(", ");
1202
+ return `carries no markdown body for its knowledge (${names})`;
1203
+ }
1204
+ return void 0;
1205
+ }
1206
+ function bundleEnvNames(text) {
1207
+ try {
1208
+ const env = JSON.parse(text).payload?.env;
1209
+ if (!Array.isArray(env)) return [];
1210
+ return env.flatMap((e) => e !== null && typeof e === "object" && typeof e.name === "string" ? [e.name] : []);
1211
+ } catch {
1212
+ return [];
1213
+ }
1214
+ }
1215
+ var BUNDLE_ENVELOPE = [
1216
+ ["app", "string"],
1217
+ ["payload", "object"]
1218
+ ];
1219
+ function bundleTextProblem(text) {
1220
+ let parsed;
1221
+ try {
1222
+ parsed = JSON.parse(text);
1223
+ } catch (err) {
1224
+ return `it is not valid JSON (${err.message})`;
1225
+ }
1226
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return "it is JSON, but not an object";
1227
+ const record = parsed;
1228
+ const missing = BUNDLE_ENVELOPE.filter(([key, type]) => {
1229
+ const value = record[key];
1230
+ return type === "object" ? value === null || typeof value !== "object" || Array.isArray(value) : typeof value !== "string";
1231
+ }).map(([key]) => `\`${key}\``);
1232
+ if (missing.length === 0) return void 0;
1233
+ const list = missing.length === 1 ? missing[0] : `${missing.slice(0, -1).join(", ")} and ${missing.at(-1)}`;
1234
+ return `it is a JSON object with no ${list} (every bundle carries \`app\`, \`version\`, \`type\`, \`payload\` and \`sig\`)`;
1235
+ }
1236
+ function assertValueFiles(args, target) {
1237
+ for (const [flag, path] of [
1238
+ ["--backend-env-file", args.envFile],
1239
+ ["--secrets-file", args.secretsFile]
1240
+ ]) {
1241
+ if (path === void 0) continue;
1242
+ if (existsSync(path) && statSync2(path).isFile()) continue;
1243
+ throw new (existsSync(path) ? UsageError : LocalFileNotFoundError)(
1244
+ `\`${flag} ${path}\` ${existsSync(path) ? "is not a file" : "does not exist"}. Check the path, and make sure the file is present wherever this runs (a CI secret mounted at deploy time, not a file committed to the repo).`,
1245
+ { hintFor: target }
1246
+ );
1247
+ }
1248
+ }
1249
+ function refuseValueFlagsBesideBundle(args, target) {
1250
+ if (args.bundle === void 0) return;
1251
+ refuseCompileValueFlags(
1252
+ args,
1253
+ args.bundle,
1254
+ "it is already compiled, and its env values and documentation tokens are the ones the `xanosdk export` that wrote it resolved. Pass them to that export" + // `preflight` tears its environment down, so there is no afterwards.
1255
+ (target.command === "deploy" && compileValueFlagKinds(args).env ? `, or change an env var on the target afterwards with \`xanosdk env set NAME${args.to === void 0 ? "" : ` --to ${shellQuote(args.to)}`}${contextFlags()}\`.` : "."),
1256
+ target
1257
+ );
1258
+ }
1259
+ function compileValueFlagKinds(args) {
1260
+ return {
1261
+ env: Object.keys(args.envVars).length > 0 || args.envFile !== void 0 || args.allowEmptyEnv.length > 0,
1262
+ docs: Object.keys(args.docTokens).length > 0 || args.secretsFile !== void 0 || args.allowEmptyDocToken.length > 0
1263
+ };
1264
+ }
1265
+ var DOC_TOKEN_REMEDY = "A documentation token is compiled into the bundle \u2014 deploy the project's entry file with `--doc-token` (or its value in `xano/.secrets.json`) to set one.";
1266
+ function compileValueFlagsPassed(args) {
1267
+ return [
1268
+ Object.keys(args.envVars).length > 0 ? "--env-var" : void 0,
1269
+ args.envFile !== void 0 ? "--backend-env-file" : void 0,
1270
+ args.allowEmptyEnv.length > 0 ? "--allow-empty-env" : void 0,
1271
+ args.allowEmptyDocToken.length > 0 ? "--allow-empty-doc-token" : void 0,
1272
+ args.secretsFile !== void 0 ? "--secrets-file" : void 0,
1273
+ Object.keys(args.docTokens).length > 0 ? "--doc-token" : void 0
1274
+ ].filter((f) => f !== void 0);
1275
+ }
1276
+ function refuseCompileValueFlags(args, input, why, target) {
1277
+ const passed = compileValueFlagsPassed(args);
1278
+ if (passed.length === 0) return;
1279
+ const list = passed.length === 1 ? passed[0] : `${passed.slice(0, -1).join(", ")} and ${passed.at(-1)}`;
1280
+ throw new UsageError(
1281
+ `${list} ${passed.length === 1 ? "applies" : "apply"} only when an entry file is compiled, and ${input} is not: ${why}`,
1282
+ { hintFor: target }
1283
+ );
1284
+ }
1285
+ async function loadBundleText(args, target, opts = {}) {
1286
+ assertBundleInput(args, target);
1287
+ assertBundleFile(args, target);
1288
+ assertValueFiles(args, target);
1289
+ if (args.bundle !== void 0) {
1290
+ return { bundle: readFileSync2(args.bundle, "utf8"), source: args.bundle, content: [], files: [], nonPublicSeedValues: [] };
1291
+ }
1292
+ if (args.file !== void 0) {
1293
+ const { bundle, bundleObject, content, files, nonPublicSeedValues, commitLock, classifiedLock, warnLockOrphans, warnOrphansUncommitted } = await compileBundle(args, {
1294
+ seed: opts.withSeed,
1295
+ deferLockWrite: opts.deferLockWrite,
1296
+ deferOrphanWarning: opts.deferOrphanWarning
1297
+ });
1298
+ return {
1299
+ bundle,
1300
+ bundleObject,
1301
+ source: args.file,
1302
+ content,
1303
+ files,
1304
+ nonPublicSeedValues,
1305
+ ...commitLock !== void 0 ? { commitLock } : {},
1306
+ ...classifiedLock !== void 0 ? { classifiedLock } : {},
1307
+ ...warnLockOrphans !== void 0 ? { warnLockOrphans } : {},
1308
+ ...warnOrphansUncommitted !== void 0 ? { warnOrphansUncommitted } : {}
1309
+ };
1310
+ }
1311
+ throw missingArgument("file", target);
1312
+ }
1313
+
1314
+ // src/emit/cli.ts
1315
+ installNodeLambdaChecks();
1316
+ function wholeNumber(raw) {
1317
+ return raw !== void 0 && /^-?\d{1,15}$/.test(raw) ? Number(raw) : void 0;
1318
+ }
1319
+ function parsePort(raw) {
1320
+ const n = wholeNumber(raw);
1321
+ if (n === void 0 || n < 0 || n > 65535) {
1322
+ throw new UsageError(`--port must be an integer 0-65535 (got "${raw ?? ""}").`, { hintFor: { command: "login" } });
1323
+ }
1324
+ return n;
1325
+ }
1326
+ var NOUN_COMMANDS = /* @__PURE__ */ new Set([
1327
+ "profile",
1328
+ "env",
1329
+ "secrets",
1330
+ "ephemeral",
1331
+ "local-engine",
1332
+ "workspace",
1333
+ "marketplace",
1334
+ "test",
1335
+ "release",
1336
+ "tenant"
1337
+ ]);
1338
+ function helpTargetFor(command, subcommand) {
1339
+ if (command === void 0 || !isCommand(command)) return void 0;
1340
+ return subcommand !== void 0 && getSubcommand(command, subcommand) !== void 0 ? { command, subcommand } : { command };
1341
+ }
1342
+ function selectorValueMissing(key, spelling, command, subcommand) {
1343
+ const slot = backendSlotForFlag(command, subcommand, key);
1344
+ if (slot !== void 0) return slotValueMissing(slot);
1345
+ const noun = key === "to" ? "a destination" : key === "from" ? "a source" : "a backend";
1346
+ return new UsageError(`${spelling} expects ${noun}.`, { helpFor: helpTargetFor(command, subcommand) });
1347
+ }
1348
+ function throwValueMissing(spelling, command, subcommand, attachedEmpty = false) {
1349
+ const spec = Object.values(FLAGS).find((f) => f.spec.split(/[\s,=[]+/).includes(spelling))?.spec;
1350
+ const placeholder = spec?.match(/<[^>]*>/)?.[0] ?? "a value";
1351
+ const long = spec?.split(/[\s,=[]+/)[0] ?? spelling;
1352
+ throw new UsageError(
1353
+ // `--config=` WAS the attached form, so pointing at it read as the fix it
1354
+ // already was. It is an empty value, and is said to be one.
1355
+ attachedEmpty ? `\`${spelling}=\` gives \`${spelling}\` an empty value \u2014 it expects ${placeholder}: \`${long}=${placeholder}\`.` : `\`${spelling}\` expects ${placeholder}, and none was given. A value that starts with \`-\` goes attached: \`${long}=${placeholder}\`.`,
1356
+ { helpFor: helpTargetFor(command, subcommand) }
1357
+ );
1358
+ }
1359
+ function expandShortAttached(arg) {
1360
+ const m = /^(-[A-Za-z])=([\s\S]*)$/.exec(arg);
1361
+ if (m === null) return arg;
1362
+ const [, short, value] = m;
1363
+ const spec = Object.values(FLAGS).find((f) => f.spec.split(/[\s,=[]+/).includes(short))?.spec;
1364
+ if (spec === void 0 || !/<[^>]*>/.test(spec)) return arg;
1365
+ return `${spec.split(/[\s,=[]+/)[0]}=${value}`;
1366
+ }
1367
+ var SCOPED_FLAG_SPELLINGS = new Map(
1368
+ Object.keys(FLAGS).filter((key) => !GLOBAL_FLAGS.includes(key)).flatMap(
1369
+ (key) => FLAGS[key].spec.split(/[\s,=[]+/).filter((token) => /^--?[a-z]/.test(token)).map((token) => [token, key])
1370
+ )
1371
+ );
1372
+ function maxPositionals(args) {
1373
+ if (args === void 0) return 0;
1374
+ return args.some((a) => a.variadic === true) ? Number.POSITIVE_INFINITY : args.length;
1375
+ }
1376
+ var RESERVED_OBJECT_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
1377
+ function envNameRule() {
1378
+ return "A name is letters, digits and `_`, and does not start with a digit (e.g. STRIPE_KEY).";
1379
+ }
1380
+ function quotedNames(names) {
1381
+ return names.map((n) => `"${safeNames([n])}"`).join(", ");
1382
+ }
1383
+ function refuseReservedKey(flag, key) {
1384
+ if (!RESERVED_OBJECT_KEYS.has(key)) return;
1385
+ throw new Error(
1386
+ `${flag} KEY cannot be \`${key}\` \u2014 \`__proto__\`, \`constructor\` and \`prototype\` are reserved JavaScript object keys, not names a value can be stored under. Choose another name.`
1387
+ );
1388
+ }
1389
+ function positionalBudget(command, subcommand, positionals) {
1390
+ const spec = getCommand(command);
1391
+ if (spec === void 0) return void 0;
1392
+ if (spec.subcommands === void 0) {
1393
+ return { max: maxPositionals(spec.args), given: positionals, offset: 0, target: { command } };
1394
+ }
1395
+ const offset = command === "lock" ? 1 : 0;
1396
+ const verb = offset === 1 ? positionals[0] : subcommand;
1397
+ if (verb === void 0) return void 0;
1398
+ const sub = getSubcommand(command, verb);
1399
+ if (sub === void 0) return void 0;
1400
+ return {
1401
+ max: maxPositionals(sub.args),
1402
+ given: positionals.slice(offset),
1403
+ offset,
1404
+ target: { command, subcommand: verb }
1405
+ };
1406
+ }
1407
+ var NAMING_FLAGS = [
1408
+ ["to", "`--to`"],
1409
+ ["from", "`--from`"],
1410
+ ["on", "`--on`"],
1411
+ ["release", "`--release`"],
1412
+ ["name", "`--name`"],
1413
+ ["branch", "`--branch`"],
1414
+ ["expectLive", "`--expect-live`"],
1415
+ ["backupBranch", "`--backup-branch`"]
1416
+ ];
1417
+ function assertNamingFlags(args) {
1418
+ for (const [key, flag] of NAMING_FLAGS) {
1419
+ const value = args[key];
1420
+ if (typeof value === "string") assertOneName(value, `the ${flag} value`, { args });
1421
+ }
1422
+ }
1423
+ function parseArgs(argv) {
1424
+ const [command, ...afterCommand] = argv;
1425
+ let subcommand;
1426
+ let rest = afterCommand;
1427
+ if (command !== void 0 && NOUN_COMMANDS.has(command)) {
1428
+ subcommand = afterCommand[0];
1429
+ rest = afterCommand.slice(1);
1430
+ }
1431
+ let out;
1432
+ let lock = false;
1433
+ let lockPath;
1434
+ let noLock = false;
1435
+ let entryPath;
1436
+ let frozenLock = false;
1437
+ let allowLockOrphans = false;
1438
+ let strict = false;
1439
+ let yes = false;
1440
+ let check = false;
1441
+ let bundle;
1442
+ let reset = false;
1443
+ let keepData = false;
1444
+ let on;
1445
+ let kind;
1446
+ let concurrency;
1447
+ let test = false;
1448
+ let expiresHours;
1449
+ let staticDir;
1450
+ let to;
1451
+ let localEngine = false;
1452
+ let localEngineUrl;
1453
+ let engineVersion;
1454
+ let description;
1455
+ let release;
1456
+ let staticHost;
1457
+ let staticRouting;
1458
+ const staticEnv = /* @__PURE__ */ Object.create(null);
1459
+ const envVars = /* @__PURE__ */ Object.create(null);
1460
+ let envFile;
1461
+ const allowEmptyEnv = [];
1462
+ const allowEmptyDocToken = [];
1463
+ const docTokens = /* @__PURE__ */ Object.create(null);
1464
+ let secretsFile;
1465
+ let backendDir;
1466
+ let noSecrets = false;
1467
+ let authHost;
1468
+ let authFile;
1469
+ let all = false;
1470
+ let workspaceId;
1471
+ let profile;
1472
+ let profileSeen = false;
1473
+ let useLocal = false;
1474
+ let paste = false;
1475
+ let allWorkspaces = false;
1476
+ let guest = false;
1477
+ let urlOnly = false;
1478
+ let prompt = false;
1479
+ let port;
1480
+ let scope;
1481
+ let runtime = false;
1482
+ let capture = false;
1483
+ let legacyRuntime = false;
1484
+ let verbose = false;
1485
+ let instance;
1486
+ let format;
1487
+ let formatRaw;
1488
+ let path;
1489
+ let name;
1490
+ let noAgentsMd = false;
1491
+ let aiSeen = false;
1492
+ const marketplace = [];
1493
+ let from;
1494
+ let framework;
1495
+ let theme;
1496
+ let radius;
1497
+ let dark;
1498
+ let font;
1499
+ let fontMono;
1500
+ let fontHeading;
1501
+ let icons;
1502
+ let force = false;
1503
+ let noInstall = false;
1504
+ let skipLiveness = false;
1505
+ let skipRoundtrip = false;
1506
+ let identityOnly = false;
1507
+ let requireMicroservices = false;
1508
+ let report;
1509
+ let noDevEnv = false;
1510
+ let dryRun = false;
1511
+ let prune = false;
1512
+ let resetData = false;
1513
+ let seed = false;
1514
+ let table;
1515
+ let write = false;
1516
+ let seedTableGuids;
1517
+ let replace = false;
1518
+ let branch;
1519
+ let setLive = false;
1520
+ let expectLive;
1521
+ let toProfile;
1522
+ let allowSharedSchemaChanges = false;
1523
+ let allowBranchDeletion = false;
1524
+ let backupBranch;
1525
+ let emit2;
1526
+ let exportName;
1527
+ let json = false;
1528
+ let noRefresh = false;
1529
+ let open = false;
1530
+ const positionals = [];
1531
+ const positionalAt = [];
1532
+ const unknownFlags = [];
1533
+ const deferUnknown = command !== void 0 && (getCommand(command)?.deferUnknownFlags === true || subcommand !== void 0 && getSubcommand(command, subcommand)?.deferUnknownFlags === true);
1534
+ let i = 0;
1535
+ const valueAfter = () => {
1536
+ const next = rest[i + 1];
1537
+ if (next === void 0 || next.startsWith("-") && next !== "-") return void 0;
1538
+ i += 1;
1539
+ return next;
1540
+ };
1541
+ const numberAfter = () => /^-\d/.test(rest[i + 1] ?? "") ? rest[++i] : valueAfter();
1542
+ const requireValue = (spelling) => valueAfter() ?? throwValueMissing(spelling, command, subcommand);
1543
+ const attachedValue = (arg, prefix) => {
1544
+ const value = arg.slice(prefix.length);
1545
+ return value !== "" ? value : throwValueMissing(prefix.slice(0, -1), command, subcommand, true);
1546
+ };
1547
+ const spelled = /* @__PURE__ */ new Map();
1548
+ let optionsEnded = false;
1549
+ for (; i < rest.length; i++) {
1550
+ if (optionsEnded || rest[i] === "--") {
1551
+ if (optionsEnded) {
1552
+ positionals.push(rest[i]);
1553
+ positionalAt.push(i);
1554
+ }
1555
+ optionsEnded = true;
1556
+ continue;
1557
+ }
1558
+ const arg = expandShortAttached(rest[i]);
1559
+ const spelling = arg.split("=", 1)[0];
1560
+ const key = SCOPED_FLAG_SPELLINGS.get(spelling);
1561
+ if (key !== void 0 && !spelled.has(key)) spelled.set(key, spelling);
1562
+ if (arg === "--out" || arg === "-o") {
1563
+ out = requireValue(arg);
1564
+ } else if (arg.startsWith("--out=")) {
1565
+ out = attachedValue(arg, "--out=");
1566
+ } else if (arg === "--export") {
1567
+ exportName = requireValue(arg);
1568
+ } else if (arg.startsWith("--export=")) {
1569
+ exportName = attachedValue(arg, "--export=");
1570
+ } else if (arg === "--emit") {
1571
+ emit2 = requireValue(arg);
1572
+ } else if (arg.startsWith("--emit=")) {
1573
+ emit2 = attachedValue(arg, "--emit=");
1574
+ } else if (arg === "--no-lock") {
1575
+ noLock = true;
1576
+ } else if (arg === "--lock") {
1577
+ lock = true;
1578
+ } else if (arg.startsWith("--lock=")) {
1579
+ lock = true;
1580
+ lockPath = arg.slice("--lock=".length);
1581
+ } else if (arg === "--entry") {
1582
+ entryPath = requireValue(arg);
1583
+ } else if (arg.startsWith("--entry=")) {
1584
+ entryPath = attachedValue(arg, "--entry=");
1585
+ } else if (arg === "--frozen-lock") {
1586
+ frozenLock = true;
1587
+ } else if (arg === "--allow-lock-orphans") {
1588
+ allowLockOrphans = true;
1589
+ } else if (arg === "--strict") {
1590
+ strict = true;
1591
+ } else if (arg === "--yes" || arg === "-y") {
1592
+ yes = true;
1593
+ } else if (arg === "--check") {
1594
+ check = true;
1595
+ } else if (arg === "--bundle") {
1596
+ bundle = requireValue(arg);
1597
+ } else if (arg.startsWith("--bundle=")) {
1598
+ bundle = attachedValue(arg, "--bundle=");
1599
+ } else if (arg === "--reset") {
1600
+ reset = true;
1601
+ } else if (arg === "--keep-data") {
1602
+ keepData = true;
1603
+ } else if (arg === "--env" || arg.startsWith("--env=")) {
1604
+ throw new UsageError(
1605
+ "`--env` was renamed `--on` on `test`; other commands name a backend with `--to`, `--from`, or a positional.",
1606
+ { helpFor: helpTargetFor(command, subcommand) }
1607
+ );
1608
+ } else if (arg === "--on" || arg.startsWith("--on=")) {
1609
+ const value = arg === "--on" ? valueAfter() : arg.slice("--on=".length);
1610
+ if (value === void 0 || value === "") throw selectorValueMissing("on", "--on", command, subcommand);
1611
+ on = value;
1612
+ } else if (arg === "--kind") {
1613
+ kind = parseKind(valueAfter());
1614
+ } else if (arg.startsWith("--kind=")) {
1615
+ kind = parseKind(arg.slice("--kind=".length));
1616
+ } else if (arg === "--concurrency") {
1617
+ concurrency = parseConcurrency(numberAfter());
1618
+ } else if (arg.startsWith("--concurrency=")) {
1619
+ concurrency = parseConcurrency(arg.slice("--concurrency=".length));
1620
+ } else if (arg === "--test") {
1621
+ test = true;
1622
+ } else if (arg === "--expires-hours") {
1623
+ expiresHours = parseExpiresHours(numberAfter());
1624
+ } else if (arg.startsWith("--expires-hours=")) {
1625
+ expiresHours = parseExpiresHours(arg.slice("--expires-hours=".length));
1626
+ } else if (arg === "--static-env" || arg.startsWith("--static-env=")) {
1627
+ const kv = arg === "--static-env" ? valueAfter() : arg.slice("--static-env=".length);
1628
+ const eq = kv?.indexOf("=") ?? -1;
1629
+ if (kv === void 0 || eq <= 0) {
1630
+ throw new Error(`--static-env expects KEY=VALUE (got "${kv ?? ""}").`);
1631
+ }
1632
+ const key2 = kv.slice(0, eq);
1633
+ if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key2)) {
1634
+ throw new Error(
1635
+ `--static-env KEY must be a JavaScript identifier \u2014 letters, digits, \`_\` or \`$\`, not starting with a digit \u2014 because it is served as \`window.<KEY>\` (got ${JSON.stringify(key2)}).`
1636
+ );
1637
+ }
1638
+ refuseReservedKey("--static-env", key2);
1639
+ staticEnv[key2] = kv.slice(eq + 1);
1640
+ } else if (arg === "--env-var" || arg.startsWith("--env-var=")) {
1641
+ const kv = arg === "--env-var" ? valueAfter() : arg.slice("--env-var=".length);
1642
+ const eq = kv?.indexOf("=") ?? -1;
1643
+ if (kv === void 0 || eq <= 0) {
1644
+ const got = eq === 0 ? "an empty name" : `"${kv ?? ""}"`;
1645
+ throw new Error(
1646
+ `--env-var expects KEY=VALUE (got ${got}). It sets a BACKEND workspace variable the engine reads with env("NAME"); for public frontend config use \`deploy --static-env\`, and to choose which backend a command acts on use its selector (\`--to\`, \`--from\`, \`--on\`, or its positional).`
1647
+ );
1648
+ }
1649
+ refuseReservedKey("--env-var", kv.slice(0, eq));
1650
+ if (!isRepresentableName(kv.slice(0, eq))) {
1651
+ throw new Error(`--env-var: ${quotedNames([kv.slice(0, eq)])} is not a usable env var name. ${envNameRule()}`);
1652
+ }
1653
+ if (Object.hasOwn(envVars, kv.slice(0, eq))) {
1654
+ throw new UsageError(
1655
+ `--env-var names ${quotedNames([kv.slice(0, eq)])} more than once. Give each name once \u2014 which of the values was meant cannot be guessed.`,
1656
+ { hintFor: helpTargetFor(command, subcommand) }
1657
+ );
1658
+ }
1659
+ envVars[kv.slice(0, eq)] = kv.slice(eq + 1);
1660
+ } else if (arg === "--env-file" || arg.startsWith("--env-file=")) {
1661
+ throw new UsageError(
1662
+ "`--env-file` was renamed `--backend-env-file`: Node itself claims `--env-file` and loads that file into the CLI's own environment before the CLI runs.",
1663
+ // The message names the replacement; a pointer, not the whole block.
1664
+ { hintFor: helpTargetFor(command, subcommand) }
1665
+ );
1666
+ } else if (arg === "--backend-env-file" || arg.startsWith("--backend-env-file=")) {
1667
+ const value = arg === "--backend-env-file" ? valueAfter() : arg.slice("--backend-env-file=".length);
1668
+ if (value === void 0 || value === "") {
1669
+ throw new Error(
1670
+ "--backend-env-file expects a path (e.g. `--backend-env-file ci.env`). It REPLACES the default xano/.env for this run."
1671
+ );
1672
+ }
1673
+ envFile = value;
1674
+ } else if (arg === "--allow-empty-env" || arg.startsWith("--allow-empty-env=")) {
1675
+ const value = arg.startsWith("--allow-empty-env=") ? arg.slice("--allow-empty-env=".length) : "";
1676
+ const names = value.split(",").map((n) => n.trim()).filter((n) => n !== "");
1677
+ if (names.length === 0) {
1678
+ throw new Error(
1679
+ "--allow-empty-env expects the NAMES it may clear (e.g. `--allow-empty-env=STRIPE_KEY,SENTRY_DSN`). There is deliberately no bare form: it would also clear whatever names the backend gains later."
1680
+ );
1681
+ }
1682
+ allowEmptyEnv.push(...names);
1683
+ } else if (arg === "--allow-empty-doc-token" || arg.startsWith("--allow-empty-doc-token=")) {
1684
+ const value = (arg.startsWith("--allow-empty-doc-token=") ? arg.slice("--allow-empty-doc-token=".length) : "").trim();
1685
+ if (value === "") {
1686
+ throw new Error(
1687
+ '--allow-empty-doc-token expects the SCOPE it may clear \u2014 `workspace`, or an API group\'s name (e.g. `--allow-empty-doc-token="Public API"`). Repeat the flag for more than one. There is deliberately no bare form: it would also clear the gate on whatever doc sites the workspace gains later.'
1688
+ );
1689
+ }
1690
+ allowEmptyDocToken.push(value);
1691
+ } else if (arg === "--doc-token" || arg.startsWith("--doc-token=")) {
1692
+ const pair = arg === "--doc-token" ? valueAfter() : arg.slice("--doc-token=".length);
1693
+ const eq = pair === void 0 ? -1 : pair.indexOf("=");
1694
+ if (pair === void 0 || eq <= 0 || pair.slice(eq + 1) === "") {
1695
+ throw new Error(
1696
+ '--doc-token expects `<scope>=<value>` \u2014 `workspace=\u2026`, or an API group\'s name (e.g. `--doc-token "Public API=sk_\u2026"`). Repeat the flag for more than one. An empty value is refused: to clear a gate on purpose, say so with `--allow-empty-doc-token="<scope>"`. Prefer `--secrets-file <path>` for a real value: one here is visible in shell history, in the process list, and in any CI log that echoes the command.'
1697
+ );
1698
+ }
1699
+ docTokens[pair.slice(0, eq).trim()] = pair.slice(eq + 1);
1700
+ } else if (arg === "--no-secrets") {
1701
+ noSecrets = true;
1702
+ } else if (arg === "--secrets-file" || arg.startsWith("--secrets-file=")) {
1703
+ const value = arg === "--secrets-file" ? valueAfter() : arg.slice("--secrets-file=".length);
1704
+ if (value === void 0 || value === "") {
1705
+ throw new Error("--secrets-file expects a path to a documentation-token file.");
1706
+ }
1707
+ secretsFile = value;
1708
+ } else if (arg === "--backend-dir" || arg.startsWith("--backend-dir=")) {
1709
+ const value = arg === "--backend-dir" ? valueAfter() : arg.slice("--backend-dir=".length);
1710
+ if (value === void 0 || value === "") {
1711
+ throw new Error("--backend-dir expects the path of a backend directory inside this project.");
1712
+ }
1713
+ backendDir = value;
1714
+ } else if (arg === "--to" || arg.startsWith("--to=")) {
1715
+ const value = arg === "--to" ? valueAfter() : arg.slice("--to=".length);
1716
+ if (value === void 0 || value === "") throw selectorValueMissing("to", "--to", command, subcommand);
1717
+ to = value;
1718
+ } else if (arg === "--local-engine" || arg.startsWith("--local-engine=")) {
1719
+ if (command === "env" && (subcommand === "set" || subcommand === "unset")) {
1720
+ throw new UsageError("`--local-engine` here is `--to local-engine`.", {
1721
+ helpFor: helpTargetFor(command, subcommand)
1722
+ });
1723
+ }
1724
+ localEngine = true;
1725
+ if (arg.startsWith("--local-engine=")) {
1726
+ const value = arg.slice("--local-engine=".length);
1727
+ if (value === "") {
1728
+ throw new UsageError(
1729
+ "--local-engine= expects an engine version (v0.1.5), a URL to fetch the engine from, or the path to an engine archive on this machine."
1730
+ );
1731
+ }
1732
+ localEngineUrl = value;
1733
+ } else if (/^https?:\/\//.test(rest[i + 1] ?? "") || /\.(tar\.gz|tgz)$/i.test(rest[i + 1] ?? "") || /^v?\d+\.\d+\.\d+$/.test(rest[i + 1] ?? "")) {
1734
+ localEngineUrl = rest[++i];
1735
+ }
1736
+ } else if (arg === "--description" || arg.startsWith("--description=")) {
1737
+ const value = arg === "--description" ? valueAfter() : arg.slice("--description=".length);
1738
+ if (value === void 0 || value === "") {
1739
+ throw new Error('--description expects text (e.g. `--description "what shipped"`).');
1740
+ }
1741
+ description = value;
1742
+ } else if (arg === "--release" || arg.startsWith("--release=")) {
1743
+ const value = arg === "--release" ? valueAfter() : arg.slice("--release=".length);
1744
+ if (value === void 0 || value === "") {
1745
+ throw new Error("--release expects a release name (`xanosdk release list` shows them).");
1746
+ }
1747
+ release = value;
1748
+ } else if (arg === "--static-host") {
1749
+ staticHost = requireValue(arg);
1750
+ } else if (arg.startsWith("--static-host=")) {
1751
+ staticHost = attachedValue(arg, "--static-host=");
1752
+ } else if (arg === "--static-routing" || arg.startsWith("--static-routing=")) {
1753
+ const v = arg === "--static-routing" ? valueAfter() : arg.slice("--static-routing=".length);
1754
+ if (v !== "spa" && v !== "multipage") {
1755
+ throw new Error(`--static-routing expects "spa" or "multipage" (got "${v ?? ""}").`);
1756
+ }
1757
+ staticRouting = v;
1758
+ } else if (arg === "--static") {
1759
+ staticDir = requireValue(arg);
1760
+ } else if (arg.startsWith("--static=")) {
1761
+ staticDir = attachedValue(arg, "--static=");
1762
+ } else if (arg === "--origin") {
1763
+ authHost = requireValue(arg);
1764
+ } else if (arg.startsWith("--origin=")) {
1765
+ authHost = attachedValue(arg, "--origin=");
1766
+ } else if (arg === "--config") {
1767
+ authFile = expandHome(requireValue(arg));
1768
+ } else if (arg.startsWith("--config=")) {
1769
+ authFile = expandHome(attachedValue(arg, "--config="));
1770
+ } else if (arg === "--local") {
1771
+ useLocal = true;
1772
+ } else if (arg === "--paste") {
1773
+ paste = true;
1774
+ } else if (arg === "--version" || arg.startsWith("--version=")) {
1775
+ const value = arg === "--version" ? valueAfter() : arg.slice("--version=".length);
1776
+ if (value === void 0 || value === "" || value.startsWith("-")) {
1777
+ throw new UsageError(`--version expects an engine version, like \`--version v0.1.5\`.`, {
1778
+ helpFor: helpTargetFor(command, subcommand)
1779
+ });
1780
+ }
1781
+ engineVersion = value;
1782
+ } else if (arg === "--all") {
1783
+ all = true;
1784
+ } else if (arg === "--all-workspaces") {
1785
+ allWorkspaces = true;
1786
+ } else if (arg === "--guest" || arg === "-g") {
1787
+ guest = true;
1788
+ } else if (arg === "--url-only" || arg === "-u") {
1789
+ urlOnly = true;
1790
+ } else if (arg === "--prompt") {
1791
+ prompt = true;
1792
+ } else if (arg === "--port") {
1793
+ port = parsePort(numberAfter());
1794
+ } else if (arg.startsWith("--port=")) {
1795
+ port = parsePort(arg.slice("--port=".length));
1796
+ } else if (arg === "--scope") {
1797
+ scope = requireValue(arg);
1798
+ } else if (arg.startsWith("--scope=")) {
1799
+ scope = attachedValue(arg, "--scope=");
1800
+ } else if (arg === "--runtime") {
1801
+ runtime = true;
1802
+ } else if (arg === "--capture") {
1803
+ capture = true;
1804
+ } else if (arg === "--legacy-runtime") {
1805
+ legacyRuntime = true;
1806
+ } else if (arg === "--verbose") {
1807
+ verbose = true;
1808
+ } else if (arg === "--instance") {
1809
+ instance = requireValue(arg);
1810
+ } else if (arg.startsWith("--instance=")) {
1811
+ instance = attachedValue(arg, "--instance=");
1812
+ } else if (arg === "--workspace-id") {
1813
+ workspaceId = requireValue(arg);
1814
+ } else if (arg.startsWith("--workspace-id=")) {
1815
+ workspaceId = attachedValue(arg, "--workspace-id=");
1816
+ } else if (arg === "--format" || arg.startsWith("--format=")) {
1817
+ const value = arg === "--format" ? valueAfter() : arg.slice("--format=".length);
1818
+ formatRaw = { value };
1819
+ } else if (arg === "--path") {
1820
+ path = requireValue(arg);
1821
+ } else if (arg.startsWith("--path=")) {
1822
+ path = attachedValue(arg, "--path=");
1823
+ } else if (arg === "--report") {
1824
+ report = requireValue(arg);
1825
+ } else if (arg.startsWith("--report=")) {
1826
+ report = attachedValue(arg, "--report=");
1827
+ } else if (arg === "--name") {
1828
+ name = requireValue(arg);
1829
+ } else if (arg.startsWith("--name=")) {
1830
+ name = attachedValue(arg, "--name=");
1831
+ } else if (arg === "--framework") {
1832
+ framework = requireValue(arg);
1833
+ } else if (arg.startsWith("--framework=")) {
1834
+ framework = attachedValue(arg, "--framework=");
1835
+ } else if (arg === "--theme") {
1836
+ theme = requireValue(arg);
1837
+ } else if (arg.startsWith("--theme=")) {
1838
+ theme = attachedValue(arg, "--theme=");
1839
+ } else if (arg === "--radius") {
1840
+ radius = requireValue(arg);
1841
+ } else if (arg.startsWith("--radius=")) {
1842
+ radius = attachedValue(arg, "--radius=");
1843
+ } else if (arg === "--dark") {
1844
+ dark = requireValue(arg);
1845
+ } else if (arg.startsWith("--dark=")) {
1846
+ dark = attachedValue(arg, "--dark=");
1847
+ } else if (arg === "--font-mono") {
1848
+ fontMono = requireValue(arg);
1849
+ } else if (arg.startsWith("--font-mono=")) {
1850
+ fontMono = attachedValue(arg, "--font-mono=");
1851
+ } else if (arg === "--font-heading") {
1852
+ fontHeading = requireValue(arg);
1853
+ } else if (arg.startsWith("--font-heading=")) {
1854
+ fontHeading = attachedValue(arg, "--font-heading=");
1855
+ } else if (arg === "--font") {
1856
+ font = requireValue(arg);
1857
+ } else if (arg.startsWith("--font=")) {
1858
+ font = attachedValue(arg, "--font=");
1859
+ } else if (arg === "--icons") {
1860
+ icons = requireValue(arg);
1861
+ } else if (arg.startsWith("--icons=")) {
1862
+ icons = attachedValue(arg, "--icons=");
1863
+ } else if (arg === "--from" || arg.startsWith("--from=")) {
1864
+ const value = arg === "--from" ? valueAfter() : arg.slice("--from=".length);
1865
+ if (value === void 0 || value === "") throw selectorValueMissing("from", "--from", command, subcommand);
1866
+ from = value;
1867
+ } else if (arg === "--marketplace" || arg.startsWith("--marketplace=")) {
1868
+ const raw = arg === "--marketplace" ? requireValue(arg) : attachedValue(arg, "--marketplace=");
1869
+ for (const p of raw.split(",")) {
1870
+ const pkg = p.trim();
1871
+ if (pkg !== "") marketplace.push(pkg);
1872
+ }
1873
+ } else if (arg === "--no-agents-md") {
1874
+ noAgentsMd = true;
1875
+ } else if (arg === "--ai" || arg.startsWith("--ai=")) {
1876
+ aiSeen = true;
1877
+ const raw = arg === "--ai" ? requireValue(arg) : attachedValue(arg, "--ai=");
1878
+ if (raw.split(",").some((p) => p.trim().toLowerCase() === "none")) noAgentsMd = true;
1879
+ } else if (arg === "--force") {
1880
+ force = true;
1881
+ } else if (arg === "--no-install") {
1882
+ noInstall = true;
1883
+ } else if (arg === "--no-dev-env") {
1884
+ noDevEnv = true;
1885
+ } else if (arg === "--skip-liveness") {
1886
+ skipLiveness = true;
1887
+ } else if (arg === "--skip-roundtrip") {
1888
+ skipRoundtrip = true;
1889
+ } else if (arg === "--identity-only") {
1890
+ identityOnly = true;
1891
+ } else if (arg === "--no-verify") {
1892
+ throw new UsageError(
1893
+ `\`--no-verify\` was split into three flags that each name what they skip: \`--skip-liveness\` (deploy: waiting for the deploy to come up), \`--skip-roundtrip\` (init --from: the offline re-export check), and \`--identity-only\` (lock prune: loading the entry file).`,
1894
+ { helpFor: helpTargetFor(command, subcommand) }
1895
+ );
1896
+ } else if (arg === "--require-microservices") {
1897
+ requireMicroservices = true;
1898
+ } else if (arg === "--dry-run") {
1899
+ dryRun = true;
1900
+ } else if (arg === "--prune") {
1901
+ prune = true;
1902
+ } else if (arg === "--reset-data") {
1903
+ resetData = true;
1904
+ } else if (arg === "--write") {
1905
+ write = true;
1906
+ } else if (arg === "--table" || arg.startsWith("--table=")) {
1907
+ const value = arg.startsWith("--table=") ? arg.slice("--table=".length) : valueAfter();
1908
+ if (value === void 0 || value === "") {
1909
+ throw new UsageError(`\`--table\` needs a table guid. Run \`${tablesCommand("workspace")}\` to list them.`);
1910
+ }
1911
+ table = [...table ?? [], value];
1912
+ } else if (arg === "--seed") {
1913
+ seed = true;
1914
+ } else if (arg.startsWith("--seed=")) {
1915
+ seed = true;
1916
+ seedTableGuids = arg.slice("--seed=".length);
1917
+ } else if (arg === "--replace") {
1918
+ replace = true;
1919
+ } else if (arg === "--branch" || arg.startsWith("--branch=")) {
1920
+ const value = arg === "--branch" ? valueAfter() : arg.slice("--branch=".length);
1921
+ if (value === void 0 || value === "") {
1922
+ throw new Error("--branch expects a branch label (e.g. `--branch staging`).");
1923
+ }
1924
+ branch = value;
1925
+ } else if (arg === "--set-live") {
1926
+ setLive = true;
1927
+ } else if (arg === "--expect-live" || arg.startsWith("--expect-live=")) {
1928
+ const value = arg === "--expect-live" ? valueAfter() : arg.slice("--expect-live=".length);
1929
+ if (value === void 0 || value === "" || value.startsWith("-")) {
1930
+ throw new Error("--expect-live expects the label of the branch you expect to be live (e.g. `--expect-live main`).");
1931
+ }
1932
+ expectLive = value;
1933
+ } else if (arg === "--to-profile" || arg.startsWith("--to-profile=")) {
1934
+ const value = arg === "--to-profile" ? valueAfter() : arg.slice("--to-profile=".length);
1935
+ if (value === void 0 || value === "" || value.startsWith("-")) {
1936
+ throw new Error("--to-profile expects the name of a stored credential profile (e.g. `--to-profile prod`).");
1937
+ }
1938
+ toProfile = value;
1939
+ } else if (arg === "--allow-shared-schema-changes") {
1940
+ allowSharedSchemaChanges = true;
1941
+ } else if (arg === "--allow-branch-deletion") {
1942
+ allowBranchDeletion = true;
1943
+ } else if (arg === "--backup-branch") {
1944
+ backupBranch = true;
1945
+ } else if (arg.startsWith("--backup-branch=")) {
1946
+ const value = arg.slice("--backup-branch=".length);
1947
+ backupBranch = value === "" ? true : value;
1948
+ } else if (arg === "--no-refresh") {
1949
+ noRefresh = true;
1950
+ } else if (arg === "--json") {
1951
+ json = true;
1952
+ } else if (arg === "--open") {
1953
+ open = true;
1954
+ } else if (arg === "--profile" || arg === "-p") {
1955
+ profileSeen = true;
1956
+ profile = valueAfter();
1957
+ } else if (arg.startsWith("--profile=")) {
1958
+ profileSeen = true;
1959
+ profile = arg.slice("--profile=".length);
1960
+ } else if (arg === "--help" || arg === "-h") {
1961
+ continue;
1962
+ } else if (arg.startsWith("-") && arg !== "-") {
1963
+ unknownFlags.push(arg);
1964
+ } else {
1965
+ positionals.push(arg);
1966
+ positionalAt.push(i);
1967
+ }
1968
+ }
1969
+ const secretArgs = command === "env" && subcommand === "set";
1970
+ const moved = movedVerb(command, subcommand, positionals);
1971
+ if (moved !== void 0) throw moved;
1972
+ if (profileSeen && (profile === void 0 || profile === "" || profile.startsWith("-"))) {
1973
+ throw new UsageError(
1974
+ // `login` CREATES the profile it names: "a stored credential profile"
1975
+ // sent its reader to a list that cannot hold it yet (E2E pass 26).
1976
+ command === "login" ? `\`--profile\` needs the name to sign in as, e.g. \`xanosdk login --profile staging\` \u2014 a new name creates that profile, an existing one signs it in again.` : `\`--profile\` needs the name of a stored credential profile, e.g. \`--profile staging\`. Run \`xanosdk profile list\` to see what is signed in.`,
1977
+ { helpFor: helpTargetFor(command, subcommand) }
1978
+ );
1979
+ }
1980
+ if (command === "login" && unknownFlags.some((f) => f === "--token" || f.startsWith("--token="))) {
1981
+ throw new UsageError(
1982
+ `\`xanosdk login\` signs in through the browser and takes no token. Store a meta API token with \`xanosdk profile add <name> --instance <url> --workspace-id <id>\` \u2014 it prompts for the token, or reads it piped on stdin (\`printf %s "$TOKEN" | xanosdk profile add \u2026\`), never from a flag.`,
1983
+ { hintFor: { command: "profile", subcommand: "add" } }
1984
+ );
1985
+ }
1986
+ if (unknownFlags.length > 0 && !deferUnknown) {
1987
+ if (secretArgs) throw envSetArgumentsRefused("flag", unknownFlags);
1988
+ throw unknownFlag(unknownFlags, helpTargetFor(command, subcommand));
1989
+ }
1990
+ const shortUnknown = deferUnknown ? unknownFlags.filter((f) => !f.startsWith("--")) : [];
1991
+ if (shortUnknown.length > 0) throw unknownFlag(shortUnknown, helpTargetFor(command, subcommand));
1992
+ if (formatRaw !== void 0) {
1993
+ const ref = flagRefFor(command, subcommand, "format");
1994
+ const path2 = subcommand === void 0 ? command : `${command} ${subcommand}`;
1995
+ if (ref === void 0) {
1996
+ throw new UsageError(`\`xanosdk ${path2}\` takes no \`--format\` \u2014 it writes one artifact.`, {
1997
+ helpFor: helpTargetFor(command, subcommand)
1998
+ });
1999
+ }
2000
+ format = parseFormat(formatRaw.value);
2001
+ const allowed = flagValues(ref) ?? ["json"];
2002
+ if (!allowed.includes(format)) {
2003
+ const hint = format === "multidoc" ? " (the engine's rendering of a deployed env: `xanosdk ephemeral export --format multidoc`)" : "";
2004
+ throw new UsageError(
2005
+ `\`xanosdk ${path2}\` does not render \`--format ${format}\`${hint}; it takes ${allowed.map((v) => `\`${v}\``).join(", ")}.`,
2006
+ { helpFor: helpTargetFor(command, subcommand) }
2007
+ );
2008
+ }
2009
+ }
2010
+ const refuseUnlessDeclared = (key, spelling, why, suggestion) => {
2011
+ if (command === void 0 || flagRefFor(command, subcommand, key) !== void 0) return;
2012
+ const path2 = subcommand === void 0 ? command : `${command} ${subcommand}`;
2013
+ throw new UsageError(`\`xanosdk ${path2}\` takes no \`${spelling}\` \u2014 ${why}`, {
2014
+ helpFor: helpTargetFor(command, subcommand),
2015
+ ...suggestion === void 0 ? {} : { suggestion }
2016
+ });
2017
+ };
2018
+ if (aiSeen) refuseUnlessDeclared("ai", "--ai", "it only chooses whether `init` writes AGENTS.md.");
2019
+ if (profileSeen && profile !== void 0) {
2020
+ if (command !== void 0 && !isAuthenticatedCommand(command, subcommand)) {
2021
+ const path2 = subcommand === void 0 ? command : `${command} ${subcommand}`;
2022
+ throw new UsageError(
2023
+ `\`xanosdk ${path2}\` takes no \`--profile\` \u2014 it reaches no Xano instance, so there is no credential for a profile to select. The commands that take it are the ones that sign in (\`deploy\`, \`pull\`, \`status\`, \`whoami\`, \`tenant\`, \`release\`, \u2026).`,
2024
+ { hintFor: helpTargetFor(command, subcommand) }
2025
+ );
2026
+ }
2027
+ if (command !== void 0 && !takesProfileFlag(command, subcommand)) {
2028
+ throw new UsageError(
2029
+ `\`xanosdk ${command} ${subcommand}\` takes no \`--profile\` \u2014 the profile it acts on is its <name> argument: \`xanosdk ${command} ${subcommand} <name>\`.`,
2030
+ { hintFor: helpTargetFor(command, subcommand) }
2031
+ );
2032
+ }
2033
+ assertValidProfileName(profile);
2034
+ }
2035
+ if (force) {
2036
+ refuseUnlessDeclared(
2037
+ "force",
2038
+ "--force",
2039
+ command !== void 0 && flagRefFor(command, subcommand, "yes") !== void 0 ? "it asks before it replaces or removes anything, and `--yes` answers that confirmation in advance." : "it overwrites nothing that already exists. A confirmation is answered in advance with `--yes`."
2040
+ );
2041
+ }
2042
+ if (out !== void 0) {
2043
+ refuseUnlessDeclared(
2044
+ "out",
2045
+ "--out",
2046
+ command !== void 0 && flagRefFor(command, subcommand, "path") !== void 0 ? "its output location is `--path` (a file, a directory, or `-` for stdout)." : "it writes no file."
2047
+ );
2048
+ }
2049
+ if (branch !== void 0) {
2050
+ refuseUnlessDeclared(
2051
+ "branch",
2052
+ "--branch",
2053
+ // Tables are the one thing a workspace does not keep per branch, so the
2054
+ // table verbs get the reason that is true of them.
2055
+ command === "workspace" && subcommand === "reset-tables" ? "tables are shared by every branch of a workspace, so a reset reaches all of them and a branch would scope nothing." : "this command does not act on a single workspace branch, so there is nothing for a label to select."
2056
+ );
2057
+ }
2058
+ if (name !== void 0) {
2059
+ refuseUnlessDeclared(
2060
+ "name",
2061
+ "--name",
2062
+ "a name it needs is a positional argument, or part of the backend it names (`--on ephemeral:<name>`, `--to tenant:<name>`)."
2063
+ );
2064
+ }
2065
+ if (on !== void 0) {
2066
+ const own = selectorSpellings(command, subcommand);
2067
+ refuseUnlessDeclared(
2068
+ "on",
2069
+ "--on",
2070
+ "`--on` is `test`'s selector. " + (own.length === 0 ? "This command acts on no backend a selector names." : `This command names its backend with ${own.length === 1 ? own[0] : `${own.slice(0, -1).join(", ")} or ${own.at(-1)}`}` + (/^`--/.test(own[0]) ? `: \`${own[0].slice(1, -1)} ${on}\`.` : ".")),
2071
+ // The flag it names, as `--json`'s `suggestion` (E2E pass 28: only the
2072
+ // message carried it).
2073
+ own.length > 0 && /^`--/.test(own[0]) ? own[0].slice(1, -1) : void 0
2074
+ );
2075
+ }
2076
+ if (localEngine) {
2077
+ refuseUnlessDeclared(
2078
+ "local-engine",
2079
+ "--local-engine",
2080
+ "only `deploy` takes it, because only a deploy downloads, pins and starts an engine. " + // Command-aware: `publish` refuses `--to local-engine` too, so pointing
2081
+ // it there sent the reader from one refusal to the next.
2082
+ (command === "publish" ? "A local engine takes a frontend only through `xanosdk deploy --local-engine --static <dir>`; `publish` publishes to an ephemeral's, a tenant's or your workspace's static host (`--to`)." : "Elsewhere a local engine is a backend: `--to local-engine`, `--from local-engine`, or `local-engine` as the positional.")
2083
+ );
2084
+ }
2085
+ if (guest) {
2086
+ refuseUnlessDeclared(
2087
+ "guest",
2088
+ "--guest",
2089
+ "a guest session is minted only when opening a backend's dashboard (`impersonate`)."
2090
+ );
2091
+ }
2092
+ if (engineVersion !== void 0) {
2093
+ refuseUnlessDeclared(
2094
+ "engine-version",
2095
+ "--version",
2096
+ "it takes no engine version. `xanosdk --version` (as the first argument) prints the CLI's own."
2097
+ );
2098
+ }
2099
+ if (all) {
2100
+ refuseUnlessDeclared(
2101
+ "all",
2102
+ "--all",
2103
+ "it acts on one thing. `xanosdk logout --all` is the one that means every stored profile."
2104
+ );
2105
+ }
2106
+ if (expectLive !== void 0) {
2107
+ const takers = "`xanosdk promote <release> --set-live --expect-live <label>` and `xanosdk workspace branch set-live <branch> --expect-live <label>` are the ones that take it.";
2108
+ refuseUnlessDeclared(
2109
+ "expect-live",
2110
+ "--expect-live",
2111
+ command === "deploy" ? `its \`--set-live\` switches live without checking what is live first. ${takers}` : `it switches no live branch, so there is no switch for the precondition to guard. ${takers}`
2112
+ );
2113
+ }
2114
+ if (toProfile !== void 0) {
2115
+ refuseUnlessDeclared(
2116
+ "to-profile",
2117
+ "--to-profile",
2118
+ "it writes to the workspace its own credential is bound to. `--profile` chooses that credential; `--to-profile` names a second, destination one, and belongs to `xanosdk release transfer`."
2119
+ );
2120
+ }
2121
+ if (workspaceId !== void 0) {
2122
+ refuseUnlessDeclared(
2123
+ "workspace-id",
2124
+ "--workspace-id",
2125
+ "every command acts on the workspace its credential is bound to. `--workspace-id` names the workspace a STORED meta API token addresses, and belongs to `xanosdk profile add`."
2126
+ );
2127
+ }
2128
+ const commandSpec = command === void 0 ? void 0 : getCommand(command);
2129
+ const verb = commandSpec?.subcommands === void 0 ? void 0 : command === "lock" ? positionals[0] : subcommand;
2130
+ const declaring = commandSpec?.subcommands === void 0 ? commandSpec : verb === void 0 ? void 0 : getSubcommand(command, verb);
2131
+ if (declaring !== void 0) {
2132
+ for (const [key, spelling] of spelled) {
2133
+ if (key === "format" || flagRefFor(command, verb, key) !== void 0) continue;
2134
+ const path2 = verb === void 0 ? command : `${command} ${verb}`;
2135
+ throw new UsageError(
2136
+ `\`xanosdk ${path2}\` takes no \`${spelling}\` \u2014 it is not one of this command's flags, so it would change nothing.`,
2137
+ { helpFor: helpTargetFor(command, verb) }
2138
+ );
2139
+ }
2140
+ }
2141
+ if (seedTableGuids !== void 0 && !(command === "release" && subcommand === "create")) {
2142
+ const path2 = subcommand === void 0 ? command : `${command} ${subcommand}`;
2143
+ throw new UsageError(
2144
+ `\`xanosdk ${path2}\` takes the bare \`--seed\`, not \`--seed=<guids>\`. Selecting which tables' rows to carry is \`xanosdk release create <name> --seed=<guids>\`; here \`--seed\` is all-or-nothing.`,
2145
+ { helpFor: helpTargetFor(command, subcommand) }
2146
+ );
2147
+ }
2148
+ if (noLock && lockPath !== void 0) {
2149
+ throw new Error(
2150
+ `\`--no-lock\` and \`--lock=${lockPath}\` ask for opposite things: one builds with no lock at all, the other names the lock file to use. Drop \`--no-lock\` to build against ${lockPath}, or drop \`--lock=\` to build without a lock.`
2151
+ );
2152
+ }
2153
+ if (noLock && lock) {
2154
+ throw new Error(
2155
+ "`--no-lock` and `--lock` are contradictory. The lock is maintained by default, so `--lock` adds nothing \u2014 drop it to keep the lock, or keep `--no-lock` alone to build without one."
2156
+ );
2157
+ }
2158
+ if (noLock && frozenLock) {
2159
+ throw new Error(
2160
+ "`--no-lock` and `--frozen-lock` are contradictory: `--frozen-lock` asserts that the lock is read and honored unchanged, and `--no-lock` reads no lock at all. Use `--frozen-lock` alone in CI."
2161
+ );
2162
+ }
2163
+ const emptyFlagged = Object.keys(envVars).filter((n) => envVars[n] === "" && !allowEmptyEnv.includes(n));
2164
+ if (emptyFlagged.length > 0) {
2165
+ const one = emptyFlagged.length === 1;
2166
+ throw new UsageError(
2167
+ `--env-var gives ${quotedNames(emptyFlagged)} an empty value, which clears what the target holds. Pass \`--allow-empty-env=${emptyFlagged.join(",")}\` if clearing ${one ? "it" : "them"} is meant, or give ${one ? "it a value" : "each a value"}.`,
2168
+ { hintFor: helpTargetFor(command, subcommand) }
2169
+ );
2170
+ }
2171
+ if (command === "export" && check) {
2172
+ const pointless = [
2173
+ ...out !== void 0 ? ["--out"] : [],
2174
+ ...envFile !== void 0 ? ["--backend-env-file"] : [],
2175
+ ...Object.keys(envVars).length > 0 ? ["--env-var"] : [],
2176
+ ...allowEmptyEnv.length > 0 ? ["--allow-empty-env"] : [],
2177
+ ...Object.keys(docTokens).length > 0 ? ["--doc-token"] : [],
2178
+ ...secretsFile !== void 0 ? ["--secrets-file"] : [],
2179
+ ...allowEmptyDocToken.length > 0 ? ["--allow-empty-doc-token"] : []
2180
+ ];
2181
+ if (pointless.length > 0) {
2182
+ throw new UsageError(
2183
+ `\`export --check\` writes no bundle, so ${pointless.map((f) => `\`${f}\``).join(", ")} ${pointless.length === 1 ? "has" : "have"} nothing to act on. Drop ${pointless.length === 1 ? "it" : "them"}, or drop \`--check\` to write the bundle.`,
2184
+ { hintFor: { command: "export" } }
2185
+ );
2186
+ }
2187
+ if (!noLock) frozenLock = true;
2188
+ }
2189
+ if (allowLockOrphans && !frozenLock) {
2190
+ const path2 = subcommand === void 0 ? command : `${command} ${subcommand}`;
2191
+ throw new UsageError(
2192
+ `\`--allow-lock-orphans\` only relaxes \`--frozen-lock\` (or \`export --check\`, which implies it), so on its own it would change nothing. Add \`--frozen-lock\`, or drop the flag.`,
2193
+ { hintFor: path2 === void 0 ? void 0 : { command, ...subcommand ? { subcommand } : {} } }
2194
+ );
2195
+ }
2196
+ if (strict && emit2 === void 0 && (command === "routes" || command === "paths")) {
2197
+ throw new UsageError(
2198
+ `\`${command} --strict\` checks the file \`--emit\` names, so on its own it would change nothing. Add \`--emit <path>\` (e.g. \`--emit xano/routes.gen.ts\`), or drop the flag.`,
2199
+ { hintFor: { command } }
2200
+ );
2201
+ }
2202
+ const budget = command === void 0 ? void 0 : positionalBudget(command, subcommand, positionals);
2203
+ if (budget !== void 0 && budget.given.length > budget.max) {
2204
+ if (secretArgs) throw envSetArgumentsRefused("extra");
2205
+ const longUnknown = deferUnknown ? unknownFlags.filter((f) => f.startsWith("--")) : [];
2206
+ const typo = longUnknown.length > 0 ? unknownFlag(longUnknown, helpTargetFor(command, subcommand)) : void 0;
2207
+ if (typo?.suggestion !== void 0) throw typo;
2208
+ const lockValue = positionals.findIndex((_, n) => rest[(positionalAt[n] ?? 0) - 1] === "--lock");
2209
+ const extras = lockValue >= budget.offset ? [positionals[lockValue]] : budget.given.slice(budget.max);
2210
+ const refused = extraArguments(extras, budget.target, budget.max, lockValue >= budget.offset ? "--lock" : void 0);
2211
+ const backend = extras.length === 1 && extras[0] !== void 0 && isKindShapedOrBare(extras[0]) ? extras[0] : void 0;
2212
+ if (command === "test" && on === void 0 && backend !== void 0) {
2213
+ refused.message += ` The backend is chosen with \`--on\`: \`xanosdk test ${[subcommand, ...budget.given.slice(0, budget.max)].map((t) => shellWord(t)).join(" ")} --on ${shellWord(backend)}\`.`;
2214
+ }
2215
+ throw refused;
2216
+ }
2217
+ let file = positionals[0];
2218
+ let bundlePositional = false;
2219
+ const fileSpec = command === void 0 ? void 0 : subcommand === void 0 ? getCommand(command) : getSubcommand(command, subcommand);
2220
+ const firstArg = fileSpec?.args?.[0];
2221
+ if (file !== void 0 && bundle === void 0 && /\.json$/i.test(file) && firstArg?.path === true && firstArg.satisfiedBy?.includes("bundle") === true && !isKindShaped(file)) {
2222
+ bundle = file;
2223
+ bundlePositional = true;
2224
+ file = void 0;
2225
+ }
2226
+ const parsed = {
2227
+ argv: [...argv],
2228
+ command,
2229
+ subcommand,
2230
+ file,
2231
+ out,
2232
+ positionals,
2233
+ positionalArgv: positionalAt.map((at) => at + (argv.length - rest.length)),
2234
+ lock,
2235
+ lockPath,
2236
+ seedTableGuids,
2237
+ noLock,
2238
+ entryPath,
2239
+ frozenLock,
2240
+ allowLockOrphans,
2241
+ strict,
2242
+ yes,
2243
+ check,
2244
+ bundle,
2245
+ ...bundlePositional ? { bundlePositional } : {},
2246
+ reset,
2247
+ keepData,
2248
+ on,
2249
+ kind,
2250
+ concurrency,
2251
+ test,
2252
+ expiresHours,
2253
+ static: staticDir,
2254
+ staticHost,
2255
+ to,
2256
+ localEngine,
2257
+ localEngineUrl,
2258
+ engineVersion,
2259
+ description,
2260
+ release,
2261
+ staticRouting,
2262
+ staticEnv,
2263
+ envVars,
2264
+ envFile,
2265
+ allowEmptyEnv,
2266
+ allowEmptyDocToken,
2267
+ docTokens,
2268
+ secretsFile,
2269
+ backendDir,
2270
+ noSecrets,
2271
+ authHost,
2272
+ authFile,
2273
+ all,
2274
+ workspaceId,
2275
+ profile,
2276
+ local: useLocal,
2277
+ paste,
2278
+ allWorkspaces,
2279
+ guest,
2280
+ urlOnly,
2281
+ prompt,
2282
+ port,
2283
+ scope,
2284
+ runtime,
2285
+ capture,
2286
+ legacyRuntime,
2287
+ verbose,
2288
+ instance,
2289
+ format,
2290
+ path,
2291
+ name,
2292
+ noAgentsMd,
2293
+ marketplace,
2294
+ from,
2295
+ force,
2296
+ noInstall,
2297
+ framework,
2298
+ theme,
2299
+ radius,
2300
+ dark,
2301
+ font,
2302
+ fontMono,
2303
+ fontHeading,
2304
+ icons,
2305
+ skipLiveness,
2306
+ skipRoundtrip,
2307
+ identityOnly,
2308
+ requireMicroservices,
2309
+ report,
2310
+ noDevEnv,
2311
+ dryRun,
2312
+ prune,
2313
+ resetData,
2314
+ seed,
2315
+ table,
2316
+ write,
2317
+ replace,
2318
+ branch,
2319
+ setLive,
2320
+ expectLive,
2321
+ toProfile,
2322
+ allowSharedSchemaChanges,
2323
+ allowBranchDeletion,
2324
+ backupBranch,
2325
+ emit: emit2,
2326
+ exportName,
2327
+ json,
2328
+ noRefresh,
2329
+ open,
2330
+ unknownFlags
2331
+ };
2332
+ assertNamingFlags(parsed);
2333
+ return parsed;
2334
+ }
2335
+ function onlyFlags(tokens) {
2336
+ for (let i = 0; i < tokens.length; i++) {
2337
+ const t = tokens[i];
2338
+ if (!t.startsWith("-")) return false;
2339
+ if (SEPARATED_VALUE_SPELLINGS.has(t)) i += 1;
2340
+ }
2341
+ return true;
2342
+ }
2343
+ function resolveHelpRequest(argv) {
2344
+ const asVerb = argv[0] === "help";
2345
+ const [first, second, ...after] = argv;
2346
+ if (first !== void 0 && first !== "init" && second === "help" && isCommand(first) && onlyFlags(after) && !existsSync2("help")) {
2347
+ return { command: first };
2348
+ }
2349
+ const [third, ...rest] = after;
2350
+ if (first !== void 0 && second !== void 0 && third === "help" && isCommand(first) && getSubcommand(first, second) !== void 0 && onlyFlags(rest) && !existsSync2("help")) {
2351
+ return { command: first, subcommand: second };
2352
+ }
2353
+ if (!asVerb && !argv.some((a) => a === "--help" || a === "-h")) return void 0;
2354
+ const tokens = (asVerb ? argv.slice(1) : argv).filter((a) => !a.startsWith("-"));
2355
+ const command = tokens[0];
2356
+ if (command === void 0 || !isCommand(command)) {
2357
+ if (command === void 0) return {};
2358
+ if (asVerb) return { unknownTopic: command };
2359
+ return argv[0] === command && /^[a-z][a-z0-9-]*$/.test(command) ? { unknownCommand: command } : {};
2360
+ }
2361
+ const sub = tokens[1];
2362
+ if (sub !== void 0 && getSubcommand(command, sub) !== void 0) return { command, subcommand: sub };
2363
+ const source = asVerb ? argv.slice(1) : argv;
2364
+ if (sub !== void 0 && liveSubcommandNames(command).length > 0 && source[source.indexOf(command) + 1] === sub && /^[a-z][a-z0-9-]*$/.test(sub)) {
2365
+ return { command, unknownSubcommand: sub, positionals: tokens.slice(2) };
2366
+ }
2367
+ return { command };
2368
+ }
2369
+ function parseFormat(raw) {
2370
+ if (raw === "json" || raw === "multidoc") return raw;
2371
+ throw new UsageError(`--format must be "json" or "multidoc" (got "${raw ?? ""}").`);
2372
+ }
2373
+ function parseKind(raw) {
2374
+ if (raw === "unit" || raw === "workflow") return raw;
2375
+ throw new UsageError(`--kind must be "unit" or "workflow" (got "${raw ?? ""}").`);
2376
+ }
2377
+ function parseConcurrency(raw) {
2378
+ const n = wholeNumber(raw);
2379
+ if (n === void 0 || n < 1 || n > 32) {
2380
+ throw new Error(`--concurrency must be a whole number from 1 to 32 (got "${raw ?? ""}").`);
2381
+ }
2382
+ return n;
2383
+ }
2384
+ function parseExpiresHours(raw) {
2385
+ const n = wholeNumber(raw);
2386
+ if (n === void 0 || n < 1 || n > 24) {
2387
+ throw new Error(`--expires-hours must be an integer 1\u201324 (got "${raw ?? ""}").`);
2388
+ }
2389
+ return n;
2390
+ }
2391
+ async function importTsxApi(file) {
2392
+ try {
2393
+ const requireFromEntry = createRequire2(pathToFileURL2(resolve2(file)));
2394
+ const apiPath = requireFromEntry.resolve("tsx/esm/api");
2395
+ return await import(pathToFileURL2(apiPath).href);
2396
+ } catch {
2397
+ return await import("tsx/esm/api");
2398
+ }
2399
+ }
2400
+ async function tryImportTsxApi(file) {
2401
+ try {
2402
+ return await importTsxApi(file);
2403
+ } catch {
2404
+ return void 0;
2405
+ }
2406
+ }
2407
+ function entryIsCommonJs(file) {
2408
+ const path = resolve2(file);
2409
+ if (/\.mts$/.test(path)) return false;
2410
+ if (/\.cts$/.test(path)) return true;
2411
+ let dir = dirname2(path);
2412
+ for (; ; ) {
2413
+ const manifest = join2(dir, "package.json");
2414
+ if (existsSync2(manifest)) {
2415
+ try {
2416
+ const pkg = JSON.parse(readFileSync3(manifest, "utf8"));
2417
+ return pkg.type !== "module";
2418
+ } catch {
2419
+ return false;
2420
+ }
2421
+ }
2422
+ const parent = dirname2(dir);
2423
+ if (parent === dir) return false;
2424
+ dir = parent;
2425
+ }
2426
+ }
2427
+ function commonJsEntryError(file, cause) {
2428
+ return new Error(
2429
+ `Cannot load "${file}": it is being evaluated as CommonJS, but Xano SDK workspace files are ES modules. Add \`"type": "module"\` to the nearest package.json, or rename the entry to \`.mts\`.`,
2430
+ cause !== void 0 ? { cause } : void 0
2431
+ );
2432
+ }
2433
+ function suggestSiblingFile(path) {
2434
+ try {
2435
+ return suggest(basename(path), readdirSync2(dirname2(path)));
2436
+ } catch {
2437
+ return void 0;
2438
+ }
2439
+ }
2440
+ function findEntryInAncestor(file) {
2441
+ if (isAbsolute(file)) return void 0;
2442
+ let dir = dirname2(resolve2(file));
2443
+ for (; ; ) {
2444
+ const parent = dirname2(dir);
2445
+ if (parent === dir) return void 0;
2446
+ dir = parent;
2447
+ if (existsSync2(resolve2(dir, file))) return dir;
2448
+ }
2449
+ }
2450
+ async function loadDefault(file) {
2451
+ return (await loadModule(file)).default;
2452
+ }
2453
+ function noProjectEntryError(file, cause) {
2454
+ const message = cause instanceof Error ? cause.message : String(cause);
2455
+ const code = cause?.code;
2456
+ const exportsMain = code === "ERR_PACKAGE_PATH_NOT_EXPORTED" || /No "exports" main defined/.test(message);
2457
+ const notFound = /Cannot find (module|package) '@xano\/sdk'/.test(message);
2458
+ if (!exportsMain && !notFound) return void 0;
2459
+ if (!/@xano[\\/]sdk/.test(message) || hasPackageJsonAbove(file)) return void 0;
2460
+ return new UsageError(
2461
+ `Cannot load "${file}": there is no package.json above it, so it is not part of a project, and @xano/sdk (an ES module) cannot be resolved from it. Run xanosdk on an entry inside a project (\`xanosdk init\` makes one, and \`xanosdk generate --out <dir>\` can write into it), or add a package.json with \`"type": "module"\` beside the entry, then \`npm i @xano/sdk && npm i -D tsx\`.`
2462
+ );
2463
+ }
2464
+ async function tsxRemedy(file) {
2465
+ const fallback = `Install it in your project (\`npm i -D tsx\`) or precompile the file to .js first.`;
2466
+ for (let dir = dirname2(resolve2(file)); ; dir = dirname2(dir)) {
2467
+ const manifest = join2(dir, "package.json");
2468
+ if (existsSync2(manifest)) {
2469
+ let pkg;
2470
+ try {
2471
+ pkg = JSON.parse(readFileSync3(manifest, "utf8"));
2472
+ } catch {
2473
+ return fallback;
2474
+ }
2475
+ const declared = ["devDependencies", "dependencies"].some(
2476
+ (block) => typeof pkg[block] === "object" && pkg[block] !== null && "tsx" in pkg[block]
2477
+ );
2478
+ if (!declared) return fallback;
2479
+ const { detectPackageManager } = await import("./package-manager-PRAHUSCN.js");
2480
+ const { inProject } = await import("./init-modules-RY7UHAOL.js");
2481
+ return `This project's package.json declares it, but its dependencies are not installed \u2014 run \`${inProject(dir)}${detectPackageManager(dir)} install\` first.`;
2482
+ }
2483
+ if (dirname2(dir) === dir) return fallback;
2484
+ }
2485
+ }
2486
+ function hasPackageJsonAbove(file) {
2487
+ let dir = dirname2(resolve2(file));
2488
+ for (; ; ) {
2489
+ if (existsSync2(join2(dir, "package.json"))) return true;
2490
+ const parent = dirname2(dir);
2491
+ if (parent === dir) return false;
2492
+ dir = parent;
2493
+ }
2494
+ }
2495
+ function assertEntryExists(file) {
2496
+ const path = resolve2(file);
2497
+ if (!existsSync2(path)) {
2498
+ const elsewhere = findEntryInAncestor(file);
2499
+ const where = elsewhere !== void 0 ? `A relative entry resolves against the current directory (${process.cwd()}), and "${file}" does exist under ${elsewhere} \u2014 run xanosdk from there.` : `A relative entry resolves against the current directory (${process.cwd()}).`;
2500
+ throw new LocalFileNotFoundError(
2501
+ `Cannot find entry file "${file}" (resolved to ${path}).` + (isAbsolute(file) ? "" : `
2502
+ ${where}`),
2503
+ { suggestion: suggestSiblingFile(path) }
2504
+ );
2505
+ }
2506
+ }
2507
+ async function loadModule(file) {
2508
+ try {
2509
+ return await withAuthoringStacks(() => loadEntryModule(file));
2510
+ } catch (err) {
2511
+ throw withAuthoringSite(err, file);
2512
+ }
2513
+ }
2514
+ async function loadEntryModule(file) {
2515
+ const path = resolve2(file);
2516
+ assertEntryExists(file);
2517
+ const url = pathToFileURL2(path).href;
2518
+ const isTypeScript = /\.[mc]?ts$/.test(file);
2519
+ if (isTypeScript) {
2520
+ if (entryIsCommonJs(file)) throw commonJsEntryError(file);
2521
+ const tsx = await tryImportTsxApi(file);
2522
+ if (tsx) {
2523
+ const unregister = tsx.register();
2524
+ try {
2525
+ return await import(url);
2526
+ } catch (err) {
2527
+ if (err instanceof Error) void err.stack;
2528
+ throw noProjectEntryError(file, err) ?? err;
2529
+ } finally {
2530
+ unregister();
2531
+ }
2532
+ }
2533
+ }
2534
+ try {
2535
+ return await import(url);
2536
+ } catch (err) {
2537
+ const noProject = noProjectEntryError(file, err);
2538
+ if (noProject !== void 0) throw noProject;
2539
+ if (!isTypeScript) throw err;
2540
+ const code = err?.code;
2541
+ if (code === "ERR_UNKNOWN_FILE_EXTENSION" || code === "ERR_MODULE_NOT_FOUND") {
2542
+ throw new Error(`Loading a TypeScript entry ("${file}") requires \`tsx\`. ${await tsxRemedy(file)}`, { cause: err });
2543
+ }
2544
+ if (err instanceof SyntaxError && /import statement outside a module/.test(err.message)) {
2545
+ throw commonJsEntryError(file, err);
2546
+ }
2547
+ throw err;
2548
+ }
2549
+ }
2550
+ var cachedVersion;
2551
+ function readVersion() {
2552
+ if (cachedVersion !== void 0) return cachedVersion;
2553
+ cachedVersion = resolveVersion();
2554
+ return cachedVersion;
2555
+ }
2556
+ function resolveVersion() {
2557
+ return ownPackage()?.version ?? "unknown";
2558
+ }
2559
+ function ownPackage() {
2560
+ let dir = dirname2(fileURLToPath3(import.meta.url));
2561
+ for (let i = 0; i < 6; i++) {
2562
+ const p = join2(dir, "package.json");
2563
+ if (existsSync2(p)) {
2564
+ try {
2565
+ const pkg = JSON.parse(readFileSync3(p, "utf8"));
2566
+ if (pkg.name === "@xano/sdk" && typeof pkg.version === "string") return { root: dir, version: pkg.version };
2567
+ } catch {
2568
+ }
2569
+ }
2570
+ const up = dirname2(dir);
2571
+ if (up === dir) break;
2572
+ dir = up;
2573
+ }
2574
+ return void 0;
2575
+ }
2576
+ async function emitterFor(file) {
2577
+ let manifestPath;
2578
+ try {
2579
+ manifestPath = createRequire2(pathToFileURL2(resolve2(file))).resolve("@xano/sdk/package.json");
2580
+ } catch {
2581
+ return emit;
2582
+ }
2583
+ const root = realpathSync(dirname2(manifestPath));
2584
+ const own = ownPackage();
2585
+ if (own === void 0 || root === realpathSync(own.root)) return emit;
2586
+ try {
2587
+ const pkg = JSON.parse(readFileSync3(manifestPath, "utf8"));
2588
+ const dot = pkg.exports?.["."];
2589
+ const entry = (typeof dot === "string" ? dot : dot?.import) ?? pkg.main;
2590
+ if (entry === void 0) return emit;
2591
+ const mod = await import(pathToFileURL2(join2(root, entry)).href);
2592
+ return typeof mod.emit === "function" ? mod.emit : emit;
2593
+ } catch {
2594
+ return emit;
2595
+ }
2596
+ }
2597
+ function printHelp() {
2598
+ process.stdout.write(terminalText(withCliPrefix(renderGlobalHelp(stdoutStyle(), readVersion()))));
2599
+ }
2600
+ function isWithin(path, dir) {
2601
+ const rel = relative3(dir, path);
2602
+ return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
2603
+ }
2604
+ function orphanFixUps(key, entryFile, lockPath, kinds, children = [], only) {
2605
+ const shown = displayPath(lockPath);
2606
+ const lockFlag = `--lock=${shellWord(shown)}`;
2607
+ entryFile = pastePath(entryFile);
2608
+ const shownKey = displayLockKey(key, kinds);
2609
+ const pruned = [key, ...children].map((k) => shellWord(displayLockKey(k, kinds))).join(" ");
2610
+ const prune = `xanosdk lock prune ${shellWord(entryFile)} ${pruned} ${lockFlag} --yes`;
2611
+ if (key === WORKSPACE_KEY) return [`deleted? run: ${prune}`];
2612
+ const sep3 = key.indexOf(":");
2613
+ const payloadKey = key.slice(0, sep3);
2614
+ const name = key.slice(sep3 + 1);
2615
+ const kind = shownKey.slice(0, shownKey.indexOf(":"));
2616
+ const newName = only !== void 0 ? shellWord(only) : payloadKey === "query" ? `'<group>|<VERB>|<name>'` : "<new-name>";
2617
+ return [
2618
+ // `--entry` too: the rename replaces the fresh entry this export appended
2619
+ // for the new name, and only the source can tell that from a live object.
2620
+ // The SDK's kind name (`table`, not the lock file's `dbo`): the reader
2621
+ // wrote `table()`, and `lock rename` accepts either spelling.
2622
+ // A placeholder makes it a template, not a command: said so, not "run:".
2623
+ `${only !== void 0 ? "renamed? run:" : `if renamed, put the new ${payloadKey === "query" ? "key" : "name"} in place of ${newName} and run:`} xanosdk lock rename ${kind} ${shellWord(name)} ${newName} ${lockFlag} --entry=${shellWord(entryFile)}` + (children.length === 0 ? "" : ` (it moves ${describeChildren(children)} with it)`),
2624
+ `deleted? run: ${prune}`
2625
+ ];
2626
+ }
2627
+ var COMPOSED_CHILDREN = {
2628
+ app: ["query"],
2629
+ realtime_server: ["channel", "message"],
2630
+ channel: ["message"]
2631
+ };
2632
+ function composedChildren(key, keys) {
2633
+ const sep3 = key.indexOf(":");
2634
+ const kids = COMPOSED_CHILDREN[key.slice(0, sep3)];
2635
+ if (kids === void 0) return [];
2636
+ const name = key.slice(sep3 + 1);
2637
+ return keys.filter((k) => kids.some((c) => k.startsWith(`${c}:${name}|`)));
2638
+ }
2639
+ function orphanFamilies(orphans) {
2640
+ const children = /* @__PURE__ */ new Map();
2641
+ const folded = /* @__PURE__ */ new Set();
2642
+ for (const key of orphans) {
2643
+ const sep3 = key.indexOf(":");
2644
+ const kids = COMPOSED_CHILDREN[key.slice(0, sep3)];
2645
+ if (kids === void 0) continue;
2646
+ const name = key.slice(sep3 + 1);
2647
+ const mine = orphans.filter((k) => kids.some((c) => k.startsWith(`${c}:${name}|`)));
2648
+ if (mine.length === 0) continue;
2649
+ children.set(key, mine);
2650
+ for (const k of mine) folded.add(k);
2651
+ }
2652
+ return { children, folded };
2653
+ }
2654
+ function describeChildren(keys) {
2655
+ const noun = {
2656
+ query: ["query", "queries"],
2657
+ channel: ["channel", "channels"],
2658
+ message: ["message", "messages"]
2659
+ };
2660
+ const parts = [];
2661
+ for (const kind of ["query", "channel", "message"]) {
2662
+ const n = keys.filter((k) => k.startsWith(`${kind}:`)).length;
2663
+ if (n > 0) parts.push(`${n} ${noun[kind][n === 1 ? 0 : 1]}`);
2664
+ }
2665
+ return `its ${parts.join(" and ")}`;
2666
+ }
2667
+ function warnOrphans(orphans, dropped, cededCanonicals, previous, observed, entryFile, lockPath, kinds, pending, accepted = false) {
2668
+ const allFamilies = orphanFamilies(orphans);
2669
+ const allRenames = renameCandidatesFor(orphans, previous, observed, kinds);
2670
+ const adopted = orphans.filter(
2671
+ (k) => k !== WORKSPACE_KEY && previous.objects[k]?.adopted === true && !allFamilies.children.has(k) && !allFamilies.folded.has(k) && allRenames.get(k)?.only === void 0 && (allRenames.get(k)?.hint ?? "") === ""
2672
+ );
2673
+ if (adopted.length > 0) {
2674
+ const shared = [
2675
+ ...new Set(adopted.flatMap((k) => {
2676
+ const only = allRenames.get(k)?.shared;
2677
+ return only === void 0 ? [] : [`${displayLockKey(k, kinds).slice(0, displayLockKey(k, kinds).indexOf(":"))}:${only}`];
2678
+ }))
2679
+ ];
2680
+ warnAdoptedOrphans(adopted, entryFile, lockPath, kinds, accepted, shared);
2681
+ const skip = new Set(adopted);
2682
+ orphans = orphans.filter((k) => !skip.has(k));
2683
+ }
2684
+ const families = adopted.length === 0 ? allFamilies : orphanFamilies(orphans);
2685
+ const renames = adopted.length === 0 ? allRenames : renameCandidatesFor(orphans, previous, observed, kinds);
2686
+ const lastHead = accepted ? void 0 : orphans.filter((k) => k !== WORKSPACE_KEY && !families.folded.has(k)).at(-1);
2687
+ const plain = orphans.filter((k) => {
2688
+ if (k === WORKSPACE_KEY || families.folded.has(k)) return false;
2689
+ const c = renames.get(k);
2690
+ return c.only === void 0 && c.inCode === void 0 && (c.hint === "" || c.candidates !== void 0);
2691
+ });
2692
+ const grouped = new Set(plain.length > ORPHANS_SAID_ONE_BY_ONE ? plain : []);
2693
+ if (grouped.size > 0) {
2694
+ warnPlainOrphans(plain, families.children, orphans, entryFile, lockPath, kinds, accepted, lastHead !== void 0 && grouped.has(lastHead), renames);
2695
+ }
2696
+ for (const key of orphans) {
2697
+ if (grouped.has(key)) continue;
2698
+ if (key === WORKSPACE_KEY) {
2699
+ exportWarn(
2700
+ "lock.orphan",
2701
+ `xano.lock entry "${key}" matched nothing this export (no workspace canonical emitted).`,
2702
+ orphanFixUps(key, entryFile, lockPath, kinds),
2703
+ !accepted
2704
+ );
2705
+ continue;
2706
+ }
2707
+ if (families.folded.has(key)) continue;
2708
+ const children = families.children.get(key) ?? [];
2709
+ const candidates = renames.get(key);
2710
+ const [rename, prune] = orphanFixUps(key, entryFile, lockPath, kinds, children, candidates.only);
2711
+ exportWarn(
2712
+ "lock.orphan",
2713
+ `xano.lock entry "${displayLockKey(key, kinds)}" ` + (children.length === 0 ? "" : `(and ${describeChildren(children)}: ${children.map((k) => displayLockKey(k, kinds)).join(", ")}) `) + `matches no exported object \u2014 if this was a rename, the next sync would delete+create unless the entry moves with it.`,
2714
+ [
2715
+ candidates.inCode !== void 0 ? setGuidFixUp(candidates.inCode) : `${rename}${candidates.hint}`,
2716
+ prune,
2717
+ ...key === lastHead ? [ADOPTED_ORPHANS_NOTE] : []
2718
+ ],
2719
+ // Accepted by `--allow-lock-orphans`: still said, never a `--strict`
2720
+ // failure — an adopted, partly ported workspace could otherwise never
2721
+ // pass the scaffold's `xano:check` (E2E pass 27).
2722
+ !accepted
2723
+ );
2724
+ }
2725
+ const droppedChildren = new Map(dropped.map((k) => [k, composedChildren(k, dropped)]));
2726
+ const droppedFolded = new Set([...droppedChildren.values()].flat());
2727
+ for (const key of dropped) {
2728
+ if (droppedFolded.has(key)) continue;
2729
+ const kids = droppedChildren.get(key) ?? [];
2730
+ const withKids = kids.length === 0 ? "" : ` (and ${describeChildren(kids)} with it)`;
2731
+ const guid = previous.objects[key]?.guid;
2732
+ const liveKey = guid === void 0 ? void 0 : Object.keys(observed).find((k) => observed[k]?.guid === guid);
2733
+ const shownLive = liveKey === void 0 ? void 0 : displayLockKey(liveKey, kinds);
2734
+ const drop = pending ? "Would drop" : "Dropped";
2735
+ exportWarn(
2736
+ "lock.dropped-entry",
2737
+ liveKey !== void 0 && guid !== rawDeriveGuid(liveKey) ? `${drop} lock entry "${displayLockKey(key, kinds)}"${withKids} \u2014 "${shownLive}" now carries its guid, so the rename ${pending ? "keeps" : "kept"} its identity; nothing else to do.` : `${drop} stale lock entry "${displayLockKey(key, kinds)}"${withKids} \u2014 its identity reappeared under ${shownLive === void 0 ? "a live name" : `"${shownLive}"`} (a reverted rename).`
2738
+ );
2739
+ }
2740
+ for (const key of cededCanonicals) {
2741
+ const shown = displayLockKey(key, kinds);
2742
+ const children = composedChildren(key, Object.keys(previous.objects));
2743
+ const candidates = allRenames.get(key);
2744
+ const [rename, prune] = orphanFixUps(key, entryFile, lockPath, kinds, children, candidates?.only);
2745
+ exportWarn(
2746
+ "lock.ceded-canonical",
2747
+ `Lock entry "${shown}" ${pending ? "would keep its guid but cede" : "kept its guid but ceded"} its canonical to a live object that now emits it (an explicit in-code canonical). A rename moves the entry, so the object keeps its identity and its URL:`,
2748
+ [rename, prune]
2749
+ );
2750
+ }
2751
+ }
2752
+ var ORPHANS_SAID_ONE_BY_ONE = 5;
2753
+ function warnPlainOrphans(plain, children, orphans, entryFile, lockPath, kinds, accepted, carriesAdoptedNote, renames) {
2754
+ const SHOWN = 5;
2755
+ const keys = plain.flatMap((k) => [k, ...children.get(k) ?? []]);
2756
+ const newcomers = /* @__PURE__ */ new Map();
2757
+ for (const k of plain) {
2758
+ const c = renames.get(k)?.candidates;
2759
+ if (c === void 0) continue;
2760
+ const names = newcomers.get(c.noun) ?? [];
2761
+ for (const n of c.names) if (!names.includes(n)) names.push(n);
2762
+ newcomers.set(c.noun, names);
2763
+ }
2764
+ const maybe = [...newcomers].map(([noun, names]) => `new ${noun} names this export: ${names.join(", ")}`).join("; ");
2765
+ const shown = keys.map((k) => displayLockKey(k, kinds));
2766
+ const list = (names) => names.map((k) => `"${k}"`).join(", ");
2767
+ const head = (names) => `${keys.length} xano.lock entries match no exported object, and this export ${maybe === "" ? "has no new name for any of them" : "fills in no new name for any of them"}: ${names}. If one was renamed, the next sync would delete+create it unless its entry moves with it.`;
2768
+ const lockFlag = `--lock=${shellWord(displayPath(lockPath))}`;
2769
+ const entry = shellWord(pastePath(entryFile));
2770
+ const listed = new Set(keys);
2771
+ const bare = orphans.every((k) => listed.has(k));
2772
+ const prune = `xanosdk lock prune ${entry}${bare ? "" : ` ${shown.map(shellWord).join(" ")}`} ${lockFlag} --yes`;
2773
+ const remedies = [
2774
+ `if one was renamed${maybe === "" ? "" : ` (${maybe})`}, put its kind and names in place of the placeholders and run: xanosdk lock rename <kind> <old-name> <new-name> ${lockFlag} --entry=${entry}`,
2775
+ `deleted? drop ${bare ? "them all" : "these"}: ${prune}`,
2776
+ ...carriesAdoptedNote && !accepted ? [ADOPTED_ORPHANS_NOTE] : []
2777
+ ];
2778
+ const capped = shown.length <= SHOWN ? list(shown) : `${list(shown.slice(0, SHOWN))}, and ${shown.length - SHOWN} more (\`--json\` lists every one)`;
2779
+ exportWarn("lock.orphan", head(capped), remedies, !accepted, [head(list(shown)), ...remedies].join("\n"));
2780
+ }
2781
+ function warnAdoptedOrphans(adopted, entryFile, lockPath, kinds, accepted, shared = []) {
2782
+ const SHOWN = 5;
2783
+ const shown = adopted.map((k) => displayLockKey(k, kinds));
2784
+ const n = adopted.length;
2785
+ const one = n === 1;
2786
+ const list = (keys) => keys.map((k) => `"${k}"`).join(", ");
2787
+ const head = (keys) => `${n} xano.lock ${one ? "entry" : "entries"} adopted by \`lock import\` ${one ? "matches" : "match"} no exported object: ${keys}. ${one ? "It pins an object" : "They pin objects"} still serving on the backend ${one ? "it was" : "they were"} adopted from \u2014 a part of it this project has not ported \u2014 so a bare \`xanosdk lock prune\` keeps ${one ? "it" : "them"}.`;
2788
+ const lockFlag = `--lock=${shellWord(displayPath(lockPath))}`;
2789
+ const entry = shellWord(pastePath(entryFile));
2790
+ const prune = `xanosdk lock prune ${entry} ${shellWord(shown[0])} ${lockFlag} --yes`;
2791
+ const renameOne = (newcomer) => {
2792
+ const kind = newcomer.slice(0, newcomer.indexOf(":"));
2793
+ const name = newcomer.slice(kind.length + 1);
2794
+ const placeholder = kind === "query" ? `"<group>|<VERB>|<old-name>"` : "<old-name>";
2795
+ return `"${newcomer}" is new this export and could be any one of them renamed, so it is offered to none \u2014 if one is: xanosdk lock rename ${kind} ${placeholder} ${shellWord(name)} ${lockFlag} --entry=${entry}`;
2796
+ };
2797
+ const remedies = [
2798
+ `deleted from that backend? drop it by naming its key: ${prune}` + (one ? "" : " (one key or several)"),
2799
+ ...shared.map(renameOne),
2800
+ // The per-orphan warnings' note, word for word: one answer, one sentence.
2801
+ ...accepted ? [] : [ADOPTED_ORPHANS_NOTE]
2802
+ ];
2803
+ const capped = n <= SHOWN ? list(shown) : `${list(shown.slice(0, SHOWN))}, and ${n - SHOWN} more (\`--json\` lists every one)`;
2804
+ exportWarn("lock.orphan-adopted", head(capped), remedies, !accepted, [head(list(shown)), ...remedies].join("\n"));
2805
+ }
2806
+ var ADOPTED_ORPHANS_NOTE = `Adopted a live workspace and ported only part of it? Those entries pin objects that are still serving, so pruning them would hand the engine back its own objects as strangers. Pass \`--allow-lock-orphans\` to \`--frozen-lock\` or \`export --check\` to accept them there.`;
2807
+ function renameCandidates(key, previous, observed, kinds, landings) {
2808
+ if (key === WORKSPACE_KEY) return { hint: "" };
2809
+ const payloadKey = key.slice(0, key.indexOf(":"));
2810
+ const shown = displayLockKey(key, kinds);
2811
+ const kind = shown.slice(0, shown.indexOf(":"));
2812
+ const orphanName = key.slice(payloadKey.length + 1);
2813
+ const kindKnown = payloadKey !== "toolset" || kinds?.has(orphanName) === true;
2814
+ const sameKind = Object.keys(observed).filter(
2815
+ (k) => k.startsWith(`${payloadKey}:`) && (!kindKnown || displayLockKey(k, kinds).startsWith(`${kind}:`)) && previous.objects[k]?.adopted !== true && // A guid `lock import` took from a live backend stays that object's
2816
+ // after the code declares it — even one its name derives (a backend
2817
+ // deployed from code): offered, the printed rename replaced it (E2E pass 30).
2818
+ previous.objects[k]?.imported !== true
2819
+ );
2820
+ const label = (k) => kindKnown ? k.slice(payloadKey.length + 1) : displayLockKey(k, kinds);
2821
+ const noun = kindKnown ? kind : "agent/mcpServer";
2822
+ const single = (names) => names.length === 1 && kindKnown ? { hint: "", only: names[0] } : void 0;
2823
+ const nameOf = (k) => k.slice(payloadKey.length + 1);
2824
+ const narrowed = (keys) => {
2825
+ const routed = keys.filter((k) => plausibleRename(orphanName, nameOf(k), false));
2826
+ return routed.length === 1 ? routed : routed.filter((k) => plausibleRename(orphanName, nameOf(k), true));
2827
+ };
2828
+ const orphanGuid = previous.objects[key]?.guid;
2829
+ const landed = (k) => landings.some(([, record]) => record[k] !== void 0 && (key in record || record[k].guid !== orphanGuid));
2830
+ const newcomers = likeliestFirst(
2831
+ orphanName,
2832
+ narrowed(sameKind.filter((k) => !(k in previous.objects) && !landed(k))),
2833
+ payloadKey
2834
+ ).map(label);
2835
+ const guessable = (name) => orphanName.split("|").length !== 3 || plausibleRename(orphanName, name, true) || sharesWord(orphanName, name);
2836
+ if (newcomers.length > 0) {
2837
+ const lone = newcomers.length === 1 && guessable(newcomers[0]) ? single(newcomers) : void 0;
2838
+ const seen = lone === void 0 ? void 0 : observed[`${payloadKey}:${lone.only}`];
2839
+ const pinned = typeof seen === "object" ? seen.guid : void 0;
2840
+ const inCode = typeof seen === "object" && seen.guid_source === "code";
2841
+ if (lone !== void 0 && orphanGuid !== void 0 && typeof pinned === "string" && pinned !== orphanGuid && (inCode || pinned !== rawDeriveGuid(`${payloadKey}:${lone.only}`))) {
2842
+ return { hint: "", inCode: { name: lone.only, guid: orphanGuid, pins: pinned } };
2843
+ }
2844
+ return lone ?? { hint: ` (new ${noun} names this export: ${newcomers.join(", ")})`, candidates: { noun, names: newcomers } };
2845
+ }
2846
+ const codePinnedHere = narrowed(
2847
+ sameKind.filter((k) => {
2848
+ const e = previous.objects[k];
2849
+ return e?.guid_source === "code" && e.guid !== orphanGuid && !landed(k);
2850
+ })
2851
+ ).map(label);
2852
+ if (orphanGuid !== void 0 && codePinnedHere.length === 1 && kindKnown && guessable(codePinnedHere[0])) {
2853
+ const pins = previous.objects[`${payloadKey}:${codePinnedHere[0]}`].guid;
2854
+ return { hint: "", inCode: { name: codePinnedHere[0], guid: orphanGuid, pins } };
2855
+ }
2856
+ return { hint: "" };
2857
+ }
2858
+ function sharesWord(a, b) {
2859
+ const words = (n) => (n.split("|").at(-1) ?? "").split(/[^A-Za-z0-9]+|(?<=[a-z0-9])(?=[A-Z])/).map((w) => w.toLowerCase()).filter((w) => w.length >= 3);
2860
+ const mine = new Set(words(a));
2861
+ return words(b).some((w) => mine.has(w));
2862
+ }
2863
+ function plausibleRename(orphanName, name, near) {
2864
+ const split = (n2) => n2.split("|").length === 3 ? n2.split("|") : ["", "", n2];
2865
+ const [og, ov, on] = split(orphanName);
2866
+ const [g, v, n] = split(name);
2867
+ if (g !== og || v !== ov && n !== on) return false;
2868
+ return !near || editDistance2(on, n) <= Math.max(3, Math.ceil(on.length / 2));
2869
+ }
2870
+ function setGuidFixUp(inCode) {
2871
+ return `renamed to "${inCode.name}"? set its def to \`guid: "${inCode.guid}"\` \u2014 its def pins its own guid (${inCode.pins}), which replaces any lock entry, so a \`lock rename\` cannot carry the identity`;
2872
+ }
2873
+ function renameCandidatesFor(orphans, previous, observed, kinds) {
2874
+ const landings = allLandings(process.cwd(), previous);
2875
+ const all = new Map(
2876
+ orphans.map((key) => [key, renameCandidates(key, previous, observed, kinds, landings)])
2877
+ );
2878
+ const target = (key, only) => `${key.slice(0, key.indexOf(":"))}:${only}`;
2879
+ const filled = /* @__PURE__ */ new Map();
2880
+ for (const [key, c] of all) {
2881
+ if (c.only !== void 0) filled.set(target(key, c.only), (filled.get(target(key, c.only)) ?? 0) + 1);
2882
+ }
2883
+ for (const [key, c] of all) {
2884
+ if (c.only === void 0 || filled.get(target(key, c.only)) < 2) continue;
2885
+ if (previous.objects[key]?.adopted === true) {
2886
+ all.set(key, { hint: "", shared: c.only });
2887
+ continue;
2888
+ }
2889
+ const shown = displayLockKey(key, kinds);
2890
+ all.set(key, {
2891
+ hint: ` (its new name may be ${c.only} \u2014 the one candidate for another orphan too, so run the rename only for the entry that was renamed)`,
2892
+ candidates: { noun: shown.slice(0, shown.indexOf(":")), names: [c.only] }
2893
+ });
2894
+ }
2895
+ return all;
2896
+ }
2897
+ function likeliestFirst(orphanName, keys, payloadKey) {
2898
+ const parts = (name) => name.split("|");
2899
+ const [og, ov, on] = parts(orphanName).length === 3 ? parts(orphanName) : ["", "", orphanName];
2900
+ const score = (key) => {
2901
+ const name = key.slice(payloadKey.length + 1);
2902
+ const [g, v, n] = parts(name).length === 3 ? parts(name) : ["", "", name];
2903
+ return (g === og ? 0 : 2e3) + (v === ov ? 0 : 1e3) + editDistance2(on, n);
2904
+ };
2905
+ return keys.map((key, i) => ({ key, i, s: score(key) })).sort((a, b) => a.s - b.s || a.i - b.i).map((e) => e.key);
2906
+ }
2907
+ function editDistance2(a, b) {
2908
+ let prev = Array.from({ length: b.length + 1 }, (_, j) => j);
2909
+ for (let i = 1; i <= a.length; i++) {
2910
+ const row = [i];
2911
+ for (let j = 1; j <= b.length; j++) {
2912
+ row[j] = Math.min(prev[j] + 1, row[j - 1] + 1, prev[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));
2913
+ }
2914
+ prev = row;
2915
+ }
2916
+ return prev[b.length];
2917
+ }
2918
+ var DRIFT = "SDK_DRIFT";
2919
+ var NULL_DEVICE = process.platform === "win32" ? "NUL" : "/dev/null";
2920
+ function frozenChangeMessage(gate, before, after, file, lockPath, def, args, kinds, droppedLandings = []) {
2921
+ const was = before?.objects ?? {};
2922
+ const added = [];
2923
+ const changed = [];
2924
+ const removed = Object.keys(was).filter((k) => !(k in after.objects));
2925
+ let minted = false;
2926
+ for (const [key, entry] of Object.entries(after.objects)) {
2927
+ const prior = was[key];
2928
+ if (prior === void 0) added.push(key);
2929
+ else if (JSON.stringify(prior) !== JSON.stringify(entry)) changed.push(key);
2930
+ if (entry.canonical !== void 0 && entry.canonical !== prior?.canonical && entry.canonical_source === "minted") {
2931
+ minted = true;
2932
+ }
2933
+ }
2934
+ const SHOWN = 5;
2935
+ const list = (label, keys) => keys.length === 0 ? [] : [
2936
+ ` ${label}: ${keys.slice(0, SHOWN).map((k) => JSON.stringify(displayLockKey(k, kinds))).join(", ")}` + (keys.length > SHOWN ? `, and ${keys.length - SHOWN} more` : "")
2937
+ ];
2938
+ const have = availableDocTokenKeys(args, file);
2939
+ const gates = def.documentationTokenNames().filter(
2940
+ (d) => d.gated && d.published && !have.has(d.key) && !Object.hasOwn(args.docTokens, documentationScopeFlagLabel(d.scope))
2941
+ );
2942
+ const one = gates.length === 1;
2943
+ const tokens = gates.length === 0 ? "" : ` It needs the documentation token${one ? "" : "s"} this source gates (${safeNames(gates.map((d) => documentationScopeLabel(d.scope)))}): \`${secretsRemedyFor(file).fill}\` mints ${one ? "one" : "them"} into \`${secretsRemedyFor(file).file}\`, or pass ${gates.map((d) => `\`--doc-token "${documentationScopeFlagLabel(d.scope)}=<value>"\``).join(" ")}.`;
2944
+ const head = before !== void 0 ? `${gate}: this export would change ${displayPath(lockPath)}${fileSpellingNote([...added, ...changed, ...removed])}:` : `${gate}: no xano.lock found at ${displayPath(lockPath)}, and this source has identities to record:`;
2945
+ return [
2946
+ head,
2947
+ ...list("add", added),
2948
+ ...list("change", changed),
2949
+ ...list("remove", removed),
2950
+ ...droppedLandings.length === 0 ? [] : [
2951
+ ` drop: ${droppedLandings.length === 1 ? "an ephemeral's landing record" : `${droppedLandings.length} ephemeral landing records`} (${droppedLandings.slice(0, SHOWN).map((d) => JSON.stringify(d)).join(", ")}${droppedLandings.length > SHOWN ? `, and ${droppedLandings.length - SHOWN} more` : ""}) \u2014 an ephemeral's record now lives in \`.xano/ephemeral.json\`, not the lock`
2952
+ ],
2953
+ // `--out` to the null device: a bare export writes the whole bundle — env
2954
+ // values and documentation tokens in cleartext — to the terminal, when all
2955
+ // the reader needs from it is the lock it records.
2956
+ `Run \`xanosdk export ${shellWord(file)} --out ${NULL_DEVICE}\` locally \u2014 it records the lock and writes the bundle nowhere \u2014 commit the ${before !== void 0 ? "updated " : ""}xano.lock it writes, and retry.${tokens}` + (before === void 0 && args.check ? ` Until then, \`--check --no-lock\` checks everything but the lock.` : "") + (minted ? ` A canonical minted here would be discarded, permanently diverging public URLs.` : "")
2957
+ ].join("\n");
2958
+ }
2959
+ function frozenOrphanError(orphans, entryFile, lockPath, gate, context) {
2960
+ const { previous, observed, kinds } = context;
2961
+ const where = displayPath(lockPath);
2962
+ const many = orphans.length !== 1;
2963
+ const SHOWN = 5;
2964
+ const families = orphanFamilies(orphans);
2965
+ const heads = orphans.filter((k) => !families.folded.has(k));
2966
+ const shown = heads.slice(0, SHOWN);
2967
+ const rest = heads.length - shown.length;
2968
+ const named = (k) => {
2969
+ const children = families.children.get(k) ?? [];
2970
+ return `${JSON.stringify(displayLockKey(k, kinds))}${children.length === 0 ? "" : ` (and ${describeChildren(children)})`}`;
2971
+ };
2972
+ const lines = [
2973
+ `${gate}: ${where} carries ${orphans.length} ${many ? "entries that match" : "entry that matches"} no exported object: ${shown.map(named).join(", ")}${rest > 0 ? `, and ${rest} more` : ""}.`,
2974
+ `A rename done in code lands here \u2014 the old name's entry stays behind while the new name mints a fresh identity, so the next sync DELETES the object and creates another in its place. A deletion lands here too, and once a plain \`xanosdk export\` has written the lock nothing tells the two apart, so the intent has to be declared rather than guessed.`
2975
+ ];
2976
+ const renames = renameCandidatesFor(heads, previous, observed, kinds);
2977
+ const fixUps = heads.map((key) => {
2978
+ const candidates = renames.get(key);
2979
+ const children = families.children.get(key) ?? [];
2980
+ const [first, ...others] = orphanFixUps(key, entryFile, lockPath, kinds, children, candidates.only);
2981
+ const hint = others.length > 0 ? candidates.hint : "";
2982
+ return {
2983
+ key: displayLockKey(key, kinds),
2984
+ ...children.length === 0 ? {} : { children: children.map((k) => displayLockKey(k, kinds)) },
2985
+ remedies: [candidates.inCode !== void 0 ? setGuidFixUp(candidates.inCode) : `${first}${hint}`, ...others]
2986
+ };
2987
+ });
2988
+ for (const { key, remedies } of fixUps.slice(0, SHOWN)) for (const fix of remedies) lines.push(` "${key}" ${fix}`);
2989
+ let pruneAll;
2990
+ if (rest > 0) {
2991
+ lines.push(
2992
+ ` \u2026and ${rest} more (${heads.slice(SHOWN).map(named).join(", ")}), each fixed the same two ways \u2014 \`--json\` lists every entry's commands under \`error.details.orphans\`.`
2993
+ );
2994
+ const plain = heads.filter((k) => {
2995
+ const c = renames.get(k);
2996
+ return k !== WORKSPACE_KEY && previous.objects[k]?.adopted !== true && c.only === void 0 && c.inCode === void 0 && c.hint === "";
2997
+ });
2998
+ if (plain.length > 1) {
2999
+ const keys = plain.flatMap((k) => [k, ...families.children.get(k) ?? []]);
3000
+ const listed = new Set(keys);
3001
+ const bare = orphans.every((k) => listed.has(k));
3002
+ pruneAll = `xanosdk lock prune ${shellWord(pastePath(entryFile))}${bare ? "" : ` ${keys.map((k) => shellWord(displayLockKey(k, kinds))).join(" ")}`} --lock=${shellWord(displayPath(lockPath))} --yes`;
3003
+ lines.push(` Deleted ${bare ? "them all" : `the ${plain.length} with no new name`}? Drop ${bare ? "every one" : "those"} at once: ${pruneAll}`);
3004
+ }
3005
+ }
3006
+ lines.push(
3007
+ `Adopted a live workspace and ported only part of it? Those entries pin objects that are still serving, so pruning them would hand the engine back its own objects as strangers. Pass \`--allow-lock-orphans\` to accept them and keep the rest of this check.`
3008
+ );
3009
+ lines.push(`Then commit the updated ${basename(lockPath)} and retry.`);
3010
+ return new CliError(DRIFT, lines.join("\n"), { details: { orphans: fixUps, ...pruneAll === void 0 ? {} : { pruneAll } } });
3011
+ }
3012
+ function run(argv) {
3013
+ return inJsonDocumentScope(
3014
+ () => inCredentialScope(() => {
3015
+ setRunFailureExplainer(explainRunCredential);
3016
+ return dispatch(argv).catch(async (err) => {
3017
+ await refineGonePullHint(err);
3018
+ throw await explainRunCredential(await nameLookupRerun(unresolvableEnvInstance(err)));
3019
+ }).catch((err) => {
3020
+ throw carryRunWarnings(maskAssignments(err, argv));
3021
+ });
3022
+ })
3023
+ ).finally(() => {
3024
+ setHintContext(void 0);
3025
+ noteRunScope(void 0);
3026
+ runArgs = void 0;
3027
+ noteRunArgs(void 0);
3028
+ offeredPull = void 0;
3029
+ mergeExcusedEnv = void 0;
3030
+ mergeExcusedDocToken = void 0;
3031
+ });
3032
+ }
3033
+ var ASSIGNMENT = /^([A-Za-z_][A-Za-z0-9_]*)=(.+)$/s;
3034
+ function maskAssignments(err, argv) {
3035
+ if (!(err instanceof Error)) return err;
3036
+ const words = [...new Set(argv.filter((a) => !a.startsWith("-") && ASSIGNMENT.test(a)))];
3037
+ if (words.length === 0) return err;
3038
+ const masked = (text) => words.reduce((t, w) => t.split(w).join(`${ASSIGNMENT.exec(w)[1]}=\u2026`), text);
3039
+ err.message = masked(err.message);
3040
+ const suggestion = err.suggestion;
3041
+ if (typeof suggestion === "string") Object.defineProperty(err, "suggestion", { value: masked(suggestion) });
3042
+ const args = runArgs ?? positionalsOf(argv);
3043
+ const positional = args?.positionals.find((p) => ASSIGNMENT.test(p));
3044
+ if (args !== void 0 && positional !== void 0 && flagRefFor(args.command, args.subcommand, "env-var") !== void 0) {
3045
+ const name = ASSIGNMENT.exec(positional)[1];
3046
+ err.message += `
3047
+ Did you mean \`--env-var ${name}=\u2026\`? A backend env var is set with the flag, not as an argument.`;
3048
+ }
3049
+ return err;
3050
+ }
3051
+ function positionalsOf(argv) {
3052
+ const [command, ...rest] = argv;
3053
+ if (command === void 0 || !isCommand(command)) return void 0;
3054
+ const subcommand = NOUN_COMMANDS.has(command) ? rest.shift() : void 0;
3055
+ const positionals = [];
3056
+ for (let i = 0; i < rest.length; i++) {
3057
+ const a = rest[i];
3058
+ if (a === "--") {
3059
+ positionals.push(...rest.slice(i + 1));
3060
+ break;
3061
+ }
3062
+ if (SEPARATED_VALUE_SPELLINGS.has(a)) i += 1;
3063
+ else if (!a.startsWith("-")) positionals.push(a);
3064
+ }
3065
+ return { command, subcommand, positionals };
3066
+ }
3067
+ function carryRunWarnings(err) {
3068
+ if (!(err instanceof Error)) return err;
3069
+ const own = err;
3070
+ const coded = typeof own.code === "string" && own.code.startsWith("SDK_");
3071
+ if (coded && Array.isArray(own.details)) {
3072
+ const pending = own.code === "SDK_EXPORT_INVALID" ? takePendingStrictFindings() : [];
3073
+ const listed = own.details;
3074
+ const joining = pending.filter((p) => !listed.some((d) => d.code === p.code && d.message === p.message));
3075
+ own.details = { diagnostics: [...listed, ...joining], warnings: [] };
3076
+ }
3077
+ let details = coded ? own.details : void 0;
3078
+ if (details !== void 0 && (typeof details !== "object" || details === null || Array.isArray(details))) return err;
3079
+ for (const [key, extra] of [["warnings", runWarnings()], ["accepted", runAccepted()]]) {
3080
+ if (extra.length === 0) continue;
3081
+ const merged = mergeJsonWarnings(details?.[key], extra);
3082
+ if (merged === void 0) continue;
3083
+ if (!coded) own.code = failureCode(err);
3084
+ details = { ...details, [key]: merged };
3085
+ own.details = details;
3086
+ }
3087
+ return err;
3088
+ }
3089
+ var runArgs;
3090
+ async function explainRunCredential(err) {
3091
+ return explainRejectedCredential(await explainUnreachableWorkspace(err));
3092
+ }
3093
+ var unreachableVerdicts = /* @__PURE__ */ new WeakMap();
3094
+ async function explainUnreachableWorkspace(err) {
3095
+ const resolved = lastResolvedAuth();
3096
+ if (!(err instanceof Error) || err instanceof UsageError || resolved === void 0 || !pinnedWorkspaceMissed()) return err;
3097
+ const { auth } = resolved;
3098
+ let verdict = unreachableVerdicts.get(auth);
3099
+ if (verdict === void 0) {
3100
+ verdict = (async () => {
3101
+ const { readReachableWorkspaces, unreachableWorkspaceMessage } = await import("./workspace-binding-56PIIPCP.js");
3102
+ const all = await readReachableWorkspaces(auth, 15e3);
3103
+ if (all === void 0 || all.length === 0 || all.some((w) => w.id === auth.workspaceId)) return void 0;
3104
+ return new UsageError(unreachableWorkspaceMessage(auth, all));
3105
+ })();
3106
+ unreachableVerdicts.set(auth, verdict);
3107
+ }
3108
+ return await verdict ?? err;
3109
+ }
3110
+ async function explainRejectedCredential(err) {
3111
+ const resolved = lastResolvedAuth();
3112
+ if (!(err instanceof Error) || resolved === void 0) return err;
3113
+ const [first = "", ...rest] = err.message.split("\n");
3114
+ if (!/\(401\b[^)]*\)|\banswered (HTTP )?401\b/.test(first) || /\brejected\b/.test(err.message)) return err;
3115
+ const { asRejectedCredential, rejectedRemedy } = await import("./whoami-command-STGINTXH.js");
3116
+ const { auth, args } = resolved;
3117
+ err.message = [first, rejectedRemedy(auth, args), ...rest].join("\n");
3118
+ if (failureCode(err) === "SDK_ERROR") asRejectedCredential(err, auth, args);
3119
+ return err;
3120
+ }
3121
+ function unresolvableEnvInstance(err) {
3122
+ const resolved = lastResolvedAuth();
3123
+ const url = readEnvVar("XANO_INSTANCE_URL");
3124
+ if (!(err instanceof Error) || resolved === void 0 || resolved.auth.profile !== void 0 || url === void 0) return err;
3125
+ let code;
3126
+ for (let e = err, depth = 0; e !== void 0 && e !== null && depth < 5 && typeof code !== "string"; depth++) {
3127
+ code = e.code;
3128
+ e = e.cause;
3129
+ }
3130
+ let host;
3131
+ try {
3132
+ host = new URL(url).host;
3133
+ } catch {
3134
+ return err;
3135
+ }
3136
+ if (code !== "ENOTFOUND" || !err.message.includes(host) || / redirected to /.test(err.message)) return err;
3137
+ return new UsageError(
3138
+ `The host of XANO_INSTANCE_URL (${url}) does not resolve (ENOTFOUND), so nothing was sent. Check the variable \u2014 it is your instance's origin, e.g. https://x8ki-letl-twmt.n7.xano.io.`
3139
+ );
3140
+ }
3141
+ function withoutSecretValue(args) {
3142
+ const at = args.positionalArgv?.[1];
3143
+ if (args.argv === void 0 || at === void 0) return args;
3144
+ return {
3145
+ ...args,
3146
+ argv: args.argv.filter((_, i) => i !== at),
3147
+ positionals: args.positionals.filter((_, i) => i !== 1),
3148
+ positionalArgv: args.positionalArgv.filter((_, i) => i !== 1).map((i) => i > at ? i - 1 : i)
3149
+ };
3150
+ }
3151
+ async function nameLookupRerun(failure) {
3152
+ if (!(failure instanceof Error) || runArgs?.argv === void 0) return failure;
3153
+ const { LookupFailedError, rateLimitedFailure } = await import("./source-resolve-S2XA3XZF.js");
3154
+ const err = rateLimitedFailure(failure);
3155
+ if (!(err instanceof LookupFailedError)) return err;
3156
+ const { retryCommand, withheldNote } = await import("./deploy-command-JVZPWHMK.js");
3157
+ if (runArgs.command === "env" && runArgs.subcommand === "set") {
3158
+ const retry2 = retryCommand(withoutSecretValue(runArgs));
3159
+ return err.withRerun(
3160
+ retry2.command,
3161
+ "",
3162
+ ` It leaves out the value of \`${runArgs.positionals[0] ?? "NAME"}\`: it is not reprinted, so pass it again (or pipe it on stdin).${withheldNote(retry2.withheld)}`
3163
+ );
3164
+ }
3165
+ const retry = retryCommand(runArgs);
3166
+ const token = runArgs.command === "profile" && runArgs.subcommand === "add" ? " with the token on stdin" : "";
3167
+ return err.withRerun(retry.command, token, withheldNote(retry.withheld));
3168
+ }
3169
+ function hoistLeadingGlobalFlags(argv) {
3170
+ const lead = [];
3171
+ let i = 0;
3172
+ while (i < argv.length) {
3173
+ const arg = expandShortAttached(argv[i]);
3174
+ if (arg === "--json" || arg === "--no-refresh" || arg.startsWith("--profile=")) {
3175
+ lead.push(arg);
3176
+ i += 1;
3177
+ } else if (arg === "--profile" || arg === "-p") {
3178
+ const value = argv[i + 1];
3179
+ lead.push(...value === void 0 ? [arg] : [arg, value]);
3180
+ i += value === void 0 ? 1 : 2;
3181
+ } else {
3182
+ break;
3183
+ }
3184
+ }
3185
+ if (lead.length === 0) return { argv: [...argv], command: [...argv] };
3186
+ const rest = argv.slice(i);
3187
+ if (rest.length === 0) {
3188
+ const shown = lead.map(
3189
+ (f, n) => (f === "-p" || f === "--profile") && n === lead.length - 1 ? `${f} <profile>` : f === "--profile=" ? "--profile=<profile>" : f
3190
+ );
3191
+ throw new UsageError(
3192
+ `No command given after \`${lead.join(" ")}\` \u2014 global flags modify a command: \`xanosdk <command> ${shown.join(" ")}\`.`,
3193
+ { helpFor: {} }
3194
+ );
3195
+ }
3196
+ return { argv: [...rest, ...lead], command: rest };
3197
+ }
3198
+ var PATHLESS_VERBS = {
3199
+ ephemeral: /* @__PURE__ */ new Set(["list", "get", "delete"]),
3200
+ tenant: /* @__PURE__ */ new Set(["list", "get", "delete", "details"]),
3201
+ release: /* @__PURE__ */ new Set(["list", "show", "delete"]),
3202
+ "local-engine": /* @__PURE__ */ new Set(["token", "stop"]),
3203
+ test: /* @__PURE__ */ new Set(["list", "run", "run-all"])
3204
+ };
3205
+ var PATHLESS_COMMANDS = /* @__PURE__ */ new Set(["tables", "impersonate"]);
3206
+ function isPathlessRun(args) {
3207
+ const command = args.command ?? "";
3208
+ return PATHLESS_COMMANDS.has(command) || PATHLESS_VERBS[command]?.has(args.subcommand ?? "") === true;
3209
+ }
3210
+ async function atProjectRoot(args, command, positional) {
3211
+ const { enterProjectRoot } = await import("./xanosdk-project-S6DXJONQ.js");
3212
+ const entered = enterProjectRoot(args, process.cwd(), positional);
3213
+ if (entered === void 0) return command(args);
3214
+ if (isPathlessRun(args)) {
3215
+ setHintContext(entered.args);
3216
+ try {
3217
+ return await command(entered.args);
3218
+ } finally {
3219
+ entered.restore();
3220
+ setHintContext(args);
3221
+ }
3222
+ }
3223
+ const note = `Using the project at ${entered.root}; printed paths and commands read from where you typed them.
3224
+ `;
3225
+ const errWrite = process.stderr.write;
3226
+ const outWrite = process.stdout.write;
3227
+ let noted = false;
3228
+ const unwrap = () => {
3229
+ process.stderr.write = errWrite;
3230
+ process.stdout.write = outWrite;
3231
+ };
3232
+ const sayNote = () => {
3233
+ if (noted) return;
3234
+ noted = true;
3235
+ unwrap();
3236
+ errWrite.call(process.stderr, note);
3237
+ };
3238
+ process.stderr.write = function(...rest) {
3239
+ sayNote();
3240
+ return errWrite.apply(process.stderr, rest);
3241
+ };
3242
+ process.stdout.write = function(...rest) {
3243
+ sayNote();
3244
+ return outWrite.apply(process.stdout, rest);
3245
+ };
3246
+ setHintContext(entered.args);
3247
+ try {
3248
+ await command(entered.args);
3249
+ } catch (err) {
3250
+ if (!isUsageError(err)) sayNote();
3251
+ throw err;
3252
+ } finally {
3253
+ if (!noted) unwrap();
3254
+ entered.restore();
3255
+ setHintContext(args);
3256
+ }
3257
+ }
3258
+ function entryPositional(args) {
3259
+ if (args.bundlePositional === true) return "entry";
3260
+ return args.file !== void 0 && !isKindShapedOrBare(args.file) ? "entry" : void 0;
3261
+ }
3262
+ function isKindShapedOrBare(raw) {
3263
+ return isKindShaped(raw) || BARE.includes(raw);
3264
+ }
3265
+ function globalVersionAsked(argv) {
3266
+ const at = globalVersionToken(argv);
3267
+ if (at === void 0) return false;
3268
+ const next = at.own[at.index + 1];
3269
+ return next === void 0 || next.startsWith("-");
3270
+ }
3271
+ function globalVersionMisuse(argv) {
3272
+ const at = globalVersionToken(argv);
3273
+ if (at === void 0) return void 0;
3274
+ const flag = at.own[at.index];
3275
+ const next = at.own[at.index + 1];
3276
+ if (next === void 0 || next.startsWith("-")) return void 0;
3277
+ if (flag === "--version" && /^v?\d/.test(next)) return void 0;
3278
+ const shown = next.includes("=") ? `${flagName(next)}=\u2026` : next;
3279
+ const where = [argv[0], NOUN_COMMANDS.has(argv[0]) ? argv[1] : void 0].filter((t) => t !== void 0).join(" ");
3280
+ return new UsageError(
3281
+ `\`${flag}\` prints the CLI version and takes no argument, so "${shown}" after it was not read. Run \`xanosdk --version\` on its own, or drop \`${flag}\` from \`xanosdk ${where}\`.`,
3282
+ { hintFor: { command: argv[0] } }
3283
+ );
3284
+ }
3285
+ var SEPARATED_VALUE_SPELLINGS = new Set(
3286
+ Object.values(FLAGS).flatMap(({ spec }) => {
3287
+ const m = /^((?:--?[\w-]+)(?:,\s*-[\w-]+)*)\s+\S/.exec(spec);
3288
+ return m === null ? [] : m[1].split(/,\s*/).filter((t) => t !== "--version" && t !== "-v");
3289
+ })
3290
+ );
3291
+ function globalVersionToken(argv) {
3292
+ const [command, ...rest] = argv;
3293
+ if (command === void 0 || !isCommand(command)) return void 0;
3294
+ const verb = NOUN_COMMANDS.has(command) ? rest[0] : void 0;
3295
+ if (command === "env" && verb === "set") return void 0;
3296
+ if (flagRefFor(command, verb, "engine-version") !== void 0) return void 0;
3297
+ const end = rest.indexOf("--");
3298
+ const own = end === -1 ? rest : rest.slice(0, end);
3299
+ for (let i = 0; i < own.length; i++) {
3300
+ const a = own[i];
3301
+ if (a === "--version" || a === "-v") return { own, index: i };
3302
+ if (SEPARATED_VALUE_SPELLINGS.has(a)) i += 1;
3303
+ }
3304
+ return void 0;
3305
+ }
3306
+ async function dispatch(rawArgv) {
3307
+ while (rawArgv[0] === "--") rawArgv = rawArgv.slice(1);
3308
+ const { argv, command: typed } = hoistLeadingGlobalFlags(rawArgv);
3309
+ if (typed[0] === "init") {
3310
+ const web = typed.indexOf("--web", 1);
3311
+ if (web !== -1) {
3312
+ const { runInitWebCommand } = await import("./init-web-M4YZSZK6.js");
3313
+ return runInitWebCommand([...typed.slice(1, web), ...typed.slice(web + 1)]);
3314
+ }
3315
+ }
3316
+ if (globalVersionAsked(argv)) {
3317
+ if (argv.includes("--json")) writeJson({ version: readVersion() });
3318
+ else process.stdout.write(`${readVersion()}
3319
+ `);
3320
+ return;
3321
+ }
3322
+ const helpRequest = resolveHelpRequest(argv);
3323
+ if (helpRequest) {
3324
+ if (helpRequest.unknownTopic !== void 0) throw unknownHelpTopic(helpRequest.unknownTopic);
3325
+ if (helpRequest.unknownCommand !== void 0) throw unknownCommand(helpRequest.unknownCommand, { help: true });
3326
+ if (helpRequest.unknownSubcommand !== void 0 && helpRequest.command !== void 0) {
3327
+ throw unknownSubcommand(helpRequest.command, helpRequest.unknownSubcommand, helpRequest.positionals ?? []);
3328
+ }
3329
+ if (argv.includes("--json")) {
3330
+ const { helpDocument } = await import("./commands-GJMJ4XYZ.js");
3331
+ writeJson({ version: readVersion(), ...helpDocument(helpRequest) });
3332
+ return;
3333
+ }
3334
+ process.stdout.write(terminalText(withCliPrefix(renderHelpFor(helpRequest, stdoutStyle(), readVersion()))));
3335
+ return;
3336
+ }
3337
+ const versionMisuse = globalVersionMisuse(argv);
3338
+ if (versionMisuse !== void 0) throw versionMisuse;
3339
+ let args;
3340
+ try {
3341
+ args = parseArgs(argv);
3342
+ } catch (err) {
3343
+ if (!(err instanceof Error)) throw err;
3344
+ const hintFor = argv[0] === "deploy" && (!isUsageError(err) || err.hintFor === void 0 && err.helpFor === void 0) ? { hintFor: { command: "deploy" } } : void 0;
3345
+ if (isUsageError(err) && hintFor === void 0) throw err;
3346
+ throw new UsageError(err.message, { ...isUsageError(err) && err.suggestion !== void 0 ? { suggestion: err.suggestion } : {}, ...hintFor });
3347
+ }
3348
+ setHintContext(args);
3349
+ runArgs = args;
3350
+ noteRunArgs(args);
3351
+ if (isMachineOutput(args)) (await import("./update-check-2W2NLDTC.js")).routeUpdateNoticeToDocument();
3352
+ const { command } = args;
3353
+ const out = args.out === "-" ? void 0 : args.out;
3354
+ if (command === void 0) {
3355
+ printHelp();
3356
+ return;
3357
+ }
3358
+ if (command === "version" || command === "--version" || command === "-v") {
3359
+ const stray = [args.subcommand, ...args.positionals].find((t) => t !== void 0);
3360
+ if (stray !== void 0) {
3361
+ throw new UsageError(
3362
+ `\`${command}\` prints the CLI version and takes no argument, so "${stray}" after it was not read. Run \`xanosdk --version\` on its own.`,
3363
+ { hintFor: {} }
3364
+ );
3365
+ }
3366
+ if (args.json) writeJson({ version: readVersion() });
3367
+ else process.stdout.write(`${readVersion()}
3368
+ `);
3369
+ return;
3370
+ }
3371
+ if (command === "init") {
3372
+ const { runInitCommand } = await import("./init-command-X2FR4UAK.js");
3373
+ return runInitCommand(args);
3374
+ }
3375
+ if (command === "completion") {
3376
+ const { isCompletionShell, runCompletionCommand, COMPLETION_SHELLS, UNSUPPORTED_SHELLS } = await import("./completion-ZQLO6PB6.js");
3377
+ const shell = args.positionals[0];
3378
+ if (shell === void 0) throw missingArgument("shell", { command: "completion" });
3379
+ if (!isCompletionShell(shell)) {
3380
+ const known = UNSUPPORTED_SHELLS.has(shell.toLowerCase());
3381
+ throw new UsageError(
3382
+ `\`xanosdk completion\`: ${known ? `${shell} is not supported` : `unknown shell "${shell}"`}. Supported: ${COMPLETION_SHELLS.join(", ")}.`,
3383
+ known ? {} : { suggestion: suggest(shell, COMPLETION_SHELLS) }
3384
+ );
3385
+ }
3386
+ if (args.json) {
3387
+ throw new UsageError(
3388
+ "`xanosdk completion` prints a shell script to source, and has no JSON form. Drop `--json`.",
3389
+ { hintFor: { command: "completion" } }
3390
+ );
3391
+ }
3392
+ return runCompletionCommand(shell);
3393
+ }
3394
+ if (command === "upgrade") {
3395
+ const { runUpgradeCommand } = await import("./upgrade-command-QHNFWM7O.js");
3396
+ return runUpgradeCommand(args);
3397
+ }
3398
+ if (command === "lock") {
3399
+ const { runLockCommand } = await import("./lock-commands-2QG25HL7.js");
3400
+ const verb = args.positionals[0];
3401
+ const { isProjectDir } = await import("./xanosdk-project-S6DXJONQ.js");
3402
+ const here = verb !== "prune" && args.lockPath === void 0 && args.entryPath === void 0 && existsSync2("xano.lock") && !isProjectDir(process.cwd()) ? { ...args, lockPath: "xano.lock" } : args;
3403
+ return atProjectRoot(here, runLockCommand, verb === "prune" || verb === "import" ? "verb-path" : void 0);
3404
+ }
3405
+ if (command === "login") {
3406
+ const { runLoginCommand } = await import("./login-command-QPYRWOXZ.js");
3407
+ return runLoginCommand(args);
3408
+ }
3409
+ if (command === "logout") {
3410
+ const { runLogoutCommand } = await import("./logout-command-WOIQLDP6.js");
3411
+ return runLogoutCommand(args);
3412
+ }
3413
+ if (command === "deploy") {
3414
+ const { runDeployCommand } = await import("./deploy-command-JVZPWHMK.js");
3415
+ return atProjectRoot(args, runDeployCommand, entryPositional(args));
3416
+ }
3417
+ if (command === "ephemeral") {
3418
+ const { runEphemeralCommand } = await import("./ephemeral-command-CLJJKOFT.js");
3419
+ return atProjectRoot(args, runEphemeralCommand);
3420
+ }
3421
+ if (command === "local-engine") {
3422
+ const { runLocalEngineCommand } = await import("./local-engine-command-Z3OL7VOD.js");
3423
+ const project = ["token", "stop", "update"].includes(args.subcommand ?? "");
3424
+ return project ? atProjectRoot(args, runLocalEngineCommand) : runLocalEngineCommand(args);
3425
+ }
3426
+ if (command === "env") {
3427
+ if (args.subcommand === "set" || args.subcommand === "unset") {
3428
+ const { runEnvVarCommand } = await import("./env-var-command-ZIRDCAZA.js");
3429
+ return atProjectRoot(args, (a) => runEnvVarCommand(a, args.subcommand));
3430
+ }
3431
+ if (args.subcommand !== "pull") throw unknownSubcommand("env", args.subcommand);
3432
+ const { runEnvPullCommand } = await import("./env-pull-command-TNMNB3CV.js");
3433
+ return atProjectRoot(args, runEnvPullCommand);
3434
+ }
3435
+ if (command === "secrets") {
3436
+ if (args.subcommand !== "fill") throw unknownSubcommand("secrets", args.subcommand);
3437
+ const { runSecretsFillCommand } = await import("./secrets-fill-command-TTCPSVXN.js");
3438
+ return atProjectRoot(args, runSecretsFillCommand, entryPositional(args));
3439
+ }
3440
+ if (command === "release") {
3441
+ const { runReleaseCommand: runReleaseNs } = await import("./release-ns-command-3KFDMZ6G.js");
3442
+ return atProjectRoot(args, runReleaseNs);
3443
+ }
3444
+ if (command === "pull") {
3445
+ const { runPullCommand } = await import("./pull-command-VBO7C4S3.js");
3446
+ const first = args.positionals[0];
3447
+ const file = first !== void 0 && !isKindShaped(first) && (/\.json$/i.test(first) || /[\\/]/.test(first));
3448
+ return file ? runPullCommand(args) : atProjectRoot(args, runPullCommand);
3449
+ }
3450
+ if (command === "generate") {
3451
+ const { runGenerateCommand } = await import("./generate-command-AYEOLA26.js");
3452
+ return runGenerateCommand(args);
3453
+ }
3454
+ if (command === "tables") {
3455
+ const { runTablesCommand } = await import("./tables-command-GUPXXSB5.js");
3456
+ return atProjectRoot(args, runTablesCommand);
3457
+ }
3458
+ if (command === "impersonate") {
3459
+ const { runImpersonateCommand } = await import("./impersonate-command-5JAS3WSV.js");
3460
+ return atProjectRoot(args, runImpersonateCommand);
3461
+ }
3462
+ if (command === "promote") {
3463
+ const { runPromoteCommand } = await import("./promote-command-PCWT5N6S.js");
3464
+ return atProjectRoot(args, runPromoteCommand);
3465
+ }
3466
+ if (command === "publish") {
3467
+ const { runPublishCommand } = await import("./publish-command-TTDUUJI5.js");
3468
+ return atProjectRoot(args, runPublishCommand, "path");
3469
+ }
3470
+ if (command === "tenant") {
3471
+ const { runTenantCommand } = await import("./tenant-command-D5HGI2X4.js");
3472
+ return atProjectRoot(args, runTenantCommand);
3473
+ }
3474
+ if (command === "test") {
3475
+ const { runTestCommand } = await import("./test-command-TIKZMDPZ.js");
3476
+ return atProjectRoot(args, runTestCommand);
3477
+ }
3478
+ if (command === "workspace") {
3479
+ const { runWorkspaceCommand } = await import("./workspace-command-JEXQETJD.js");
3480
+ return runWorkspaceCommand(args);
3481
+ }
3482
+ if (command === "status") {
3483
+ const { runStatusCommand } = await import("./status-command-RUDXTF7I.js");
3484
+ return runStatusCommand(args);
3485
+ }
3486
+ if (command === "whoami") {
3487
+ const { runWhoamiCommand } = await import("./whoami-command-STGINTXH.js");
3488
+ return runWhoamiCommand(args);
3489
+ }
3490
+ if (command === "profile") {
3491
+ const { runProfileCommand } = await import("./profile-command-AH3PIM4X.js");
3492
+ return runProfileCommand(args);
3493
+ }
3494
+ if (command === "marketplace") {
3495
+ if (!["list", "search", "details", "install", "reinstall", "remove"].includes(args.subcommand ?? "")) {
3496
+ throw unknownSubcommand("marketplace", args.subcommand);
3497
+ }
3498
+ const marketplace = await import("./marketplace-command-K5YL42NO.js");
3499
+ const { withCatalogueRerun } = await import("./marketplace-resolve-LY32JES5.js");
3500
+ try {
3501
+ if (args.subcommand === "list") return await marketplace.runMarketplaceListCommand(args);
3502
+ if (args.subcommand === "search") return await marketplace.runMarketplaceSearchCommand(args);
3503
+ if (args.subcommand === "details") return await marketplace.runMarketplaceDetailsCommand(args);
3504
+ if (args.subcommand === "reinstall") return await atProjectRoot(args, marketplace.runMarketplaceReinstallCommand);
3505
+ if (args.subcommand === "remove") return await atProjectRoot(args, marketplace.runMarketplaceRemoveCommand);
3506
+ return await atProjectRoot(args, marketplace.runMarketplaceInstallCommand);
3507
+ } catch (err) {
3508
+ throw await withCatalogueRerun(err, args, `marketplace ${args.subcommand}`);
3509
+ }
3510
+ }
3511
+ if (command === "preflight") {
3512
+ const { runPreflightCommand } = await import("./preflight-command-2T5Z36MI.js");
3513
+ return runPreflightCommand(args);
3514
+ }
3515
+ if (command !== "compile" && command !== "export" && command !== "paths" && command !== "routes") {
3516
+ throw unknownCommand(command);
3517
+ }
3518
+ if (!args.file) {
3519
+ throw missingArgument("file", { command });
3520
+ }
3521
+ if (command === "compile") {
3522
+ return runCompile(args);
3523
+ }
3524
+ if (command === "paths" || command === "routes") {
3525
+ return runPaths(args);
3526
+ }
3527
+ const { discoverToolchainPlugins } = await import("./toolchain-modules-5EAZUONB.js");
3528
+ const toolchain = await discoverToolchainPlugins(process.cwd(), {
3529
+ frozen: args.frozenLock === true || args.check === true
3530
+ });
3531
+ if (out && !args.check) {
3532
+ const { assertWritableTarget } = await import("./output-target-AL3I44GG.js");
3533
+ assertWritableTarget(out, "--out");
3534
+ }
3535
+ const { bundle: json, bundleObject, omittedSeedTables, lock: lockOutcome, declaredEnvNames } = await compileBundle(args);
3536
+ if (omittedSeedTables.length > 0 && !args.check) {
3537
+ const names = omittedSeedTables.map((n) => `"${n}"`).join(", ");
3538
+ info(
3539
+ `Exported bundle omits seed rows for ${countOf(omittedSeedTables.length, "table")}: ${names}. Seed is applied only by \`xanosdk deploy <entry>\` \u2014 deploying this bundle via \`--bundle\` ships schema without seed data.`
3540
+ );
3541
+ }
3542
+ const { hostedIconOwners } = await import("./hosted-file-PSHJB3HX.js");
3543
+ const hostedOwners = hostedIconOwners(bundleObject.payload ?? {});
3544
+ if (hostedOwners.length > 0 && !args.check) {
3545
+ warn(
3546
+ `Exported bundle names hostedFile() icons whose files it does not carry: ${hostedOwners.join(", ")}. Deploying it with \`--bundle\` is refused; \`xanosdk deploy ${shellWord(pastePath(args.file))}\` ships the files.`,
3547
+ "export.hosted-files-omitted"
3548
+ );
3549
+ }
3550
+ const { runBundleHooks } = await import("./toolchain-hooks-GHKLUJOH.js");
3551
+ await runBundleHooks(
3552
+ toolchain.loaded,
3553
+ {
3554
+ bundle: bundleObject,
3555
+ entry: args.file,
3556
+ cwd: process.cwd(),
3557
+ command: "export",
3558
+ frozen: args.frozenLock === true || args.check === true,
3559
+ sdkVersion: readVersion()
3560
+ },
3561
+ ""
3562
+ );
3563
+ const { refreshEnvExample, bundleEnvNames: bundleEnvNames2 } = await import("./env-example-refresh-ET5HMMDW.js");
3564
+ const { backendDirFor } = await import("./backend-dir-2U53CIAL.js");
3565
+ const declaredSet = new Set(declaredEnvNames);
3566
+ const templateDir = backendDirFor(args.file);
3567
+ const ownsTemplate = isWithin(resolve2(args.file), templateDir) && (dirname2(resolve2(args.file)) === templateDir || !existsSync2(join2(templateDir, "index.ts")));
3568
+ const templateEnv = Object.fromEntries(
3569
+ Object.entries(bundleEnvNames2(bundleObject)).filter(([name]) => declaredSet.has(name))
3570
+ );
3571
+ const { skewedProjectSdk, skewNote, installedCliCommand } = await import("./project-sdk-REPPOIBD.js");
3572
+ const projectSdk = skewedProjectSdk(dirname2(resolve2(args.file)), readVersion());
3573
+ const regenerate = projectSdk === void 0 ? `xanosdk export ${shellWord(pastePath(args.file))} --out ${NULL_DEVICE}` : installedCliCommand(projectSdk.root, (path) => `export ${path(args.file)} --out ${NULL_DEVICE}`);
3574
+ if (args.check) {
3575
+ const staleEnvExample = ownsTemplate ? refreshEnvExample(templateDir, templateEnv, { write: false }) : void 0;
3576
+ if (staleEnvExample !== void 0) {
3577
+ const listed = new Set(
3578
+ [...readFileSync3(staleEnvExample, "utf8").matchAll(/^# ([^\s=`]+)=/gm)].map((m) => m[1])
3579
+ );
3580
+ const quoted = (names) => names.map((n) => `\`${n}\``).join(", ");
3581
+ const missing = Object.keys(templateEnv).filter((n) => !listed.has(n));
3582
+ const extra = [...listed].filter((n) => !(n in templateEnv));
3583
+ const drift = [
3584
+ missing.length > 0 ? `omits ${quoted(missing)}, which this source declares` : "",
3585
+ extra.length > 0 ? `still lists ${quoted(extra)}, which this source no longer declares` : ""
3586
+ ].filter(Boolean);
3587
+ if (drift.length === 0 && projectSdk !== void 0) {
3588
+ info(skewNote(displayPath(staleEnvExample), readVersion(), projectSdk.version, regenerate));
3589
+ } else {
3590
+ throw new CliError(
3591
+ DRIFT,
3592
+ `--check: ${displayPath(staleEnvExample)} ${drift.length > 0 ? drift.join(", and ") : `lists the env names this source declares, but in other words than @xano/sdk ${readVersion()} renders the template`}. Run \`${regenerate}\` locally \u2014 it rewrites the template (names only, never a value) and writes the bundle nowhere \u2014 then commit it and retry.`
3593
+ );
3594
+ }
3595
+ }
3596
+ const lockPath = resolveLockPath(args, args.file);
3597
+ const lock = !args.noLock && existsSync2(lockPath) ? { path: displayPath(lockPath), changed: false } : null;
3598
+ if (isMachineOutput(args)) writeJson({ checked: resolve2(args.file), lock, written: false });
3599
+ else {
3600
+ success(
3601
+ `Checked ${args.file}: ` + (args.noLock ? `it compiles and every guard, toolchain check and .env.example passes; no xano.lock yet, so identities were not checked \u2014 \`${regenerate}\` records one to commit.` : lock === null ? "nothing to record in xano.lock." : "xano.lock is up to date.") + ` Nothing was written.`
3602
+ );
3603
+ }
3604
+ return;
3605
+ }
3606
+ const hadEnvExample = existsSync2(join2(templateDir, ".env.example"));
3607
+ const held = ownsTemplate && projectSdk !== void 0 ? refreshEnvExample(templateDir, templateEnv, { write: false }) : void 0;
3608
+ if (held !== void 0) {
3609
+ warn(skewNote(displayPath(held), readVersion(), projectSdk.version, regenerate), "export.env-example-cli-skew");
3610
+ }
3611
+ let refreshed;
3612
+ try {
3613
+ refreshed = ownsTemplate && projectSdk === void 0 ? refreshEnvExample(templateDir, templateEnv) : void 0;
3614
+ } catch (err) {
3615
+ if (isUnwritableError(err)) throw unwritableError(join2(templateDir, ".env.example"));
3616
+ throw err;
3617
+ }
3618
+ if (refreshed !== void 0) {
3619
+ info(`${hadEnvExample ? "Updated" : "Wrote"} ${displayPath(refreshed)} to list the env names this source declares.`);
3620
+ }
3621
+ if (out) {
3622
+ const { secretsCarriedBy } = await import("./live-diff-YONW2VI3.js");
3623
+ const { writeExportFile } = await import("./output-target-AL3I44GG.js");
3624
+ const written = lockOutcome?.changed ? `Only ${lockOutcome.path} was written` : void 0;
3625
+ writeExportFile(out, json + "\n", secretsCarriedBy(bundleObject), "--out", written);
3626
+ reportWrote(args, out, lockOutcome);
3627
+ } else {
3628
+ process.stdout.write(json + "\n");
3629
+ const { secretsCarriedBy } = await import("./live-diff-YONW2VI3.js");
3630
+ const { secretsPhrase } = await import("./output-target-AL3I44GG.js");
3631
+ const secrets = secretsCarriedBy(bundleObject);
3632
+ if (secrets.length > 0) {
3633
+ warn(
3634
+ `The export carries ${secretsPhrase(secrets)} in cleartext \u2014 written to stdout, where no file permission protects it; do not commit or log it.`,
3635
+ "secrets.cleartext-stdout"
3636
+ );
3637
+ }
3638
+ }
3639
+ }
3640
+ function reportWrote(args, out, lock) {
3641
+ if (isMachineOutput(args)) {
3642
+ writeJson({ out: resolve2(out), written: true, ...lock === void 0 ? {} : { lock } });
3643
+ } else success(`Wrote ${out}`);
3644
+ }
3645
+ async function refreshAgentGuidance(args) {
3646
+ if (args.noRefresh) return;
3647
+ if (args.check || args.frozenLock || args.dryRun) return;
3648
+ try {
3649
+ const { installedSdk, skewedProjectSdk, skewNote, installedCliCommand } = await import("./project-sdk-REPPOIBD.js");
3650
+ const entryProject = args.file === void 0 ? void 0 : installedSdk(dirname2(resolve2(args.file)))?.root;
3651
+ const projectDir = existsSync2(join2(process.cwd(), "AGENTS.md")) || entryProject === void 0 ? process.cwd() : entryProject;
3652
+ const projectSdk = skewedProjectSdk(projectDir, readVersion());
3653
+ const { refreshAgentFiles } = await import("./agent-file-refresh-ZEMK33AX.js");
3654
+ if (projectSdk !== void 0) {
3655
+ const stale = refreshAgentFiles({ projectDir, sdkVersion: readVersion(), write: false });
3656
+ const file = args.file;
3657
+ const command = installedCliCommand(
3658
+ projectSdk.root,
3659
+ (path) => `export${file === void 0 ? "" : ` ${path(file)}`} --out ${NULL_DEVICE}`
3660
+ );
3661
+ for (const path of stale) info(skewNote(displayPath(join2(projectDir, path)), readVersion(), projectSdk.version, command));
3662
+ return;
3663
+ }
3664
+ const refreshed = refreshAgentFiles({
3665
+ projectDir,
3666
+ sdkVersion: readVersion()
3667
+ });
3668
+ for (const path of refreshed) {
3669
+ process.stderr.write(`Refreshed ${displayPath(join2(projectDir, path))} for @xano/sdk ${readVersion()}.
3670
+ `);
3671
+ }
3672
+ } catch {
3673
+ }
3674
+ }
3675
+ function nearestLockPath(file) {
3676
+ const start = dirname2(resolve2(file));
3677
+ let dir = start;
3678
+ for (; ; ) {
3679
+ const candidate = join2(dir, "xano.lock");
3680
+ if (existsSync2(candidate)) return candidate;
3681
+ if (existsSync2(join2(dir, "package.json"))) return join2(start, "xano.lock");
3682
+ const parent = dirname2(dir);
3683
+ if (parent === dir) return join2(start, "xano.lock");
3684
+ dir = parent;
3685
+ }
3686
+ }
3687
+ function missingLockDir(args) {
3688
+ if (args.lockPath === void 0) return void 0;
3689
+ const dir = dirname2(resolve2(args.lockPath));
3690
+ if (existsSync2(dir)) return void 0;
3691
+ return `\`--lock=${args.lockPath}\`: ${displayPath(dir)}/ doesn't exist \u2014 create it, or pass a \`--lock\` path in an existing directory.`;
3692
+ }
3693
+ function resolveLockPath(args, file) {
3694
+ return args.lockPath !== void 0 ? resolve2(args.lockPath) : join2(dirname2(resolve2(file)), "xano.lock");
3695
+ }
3696
+ function isParseableLock(lockPath) {
3697
+ try {
3698
+ readLockFile(lockPath);
3699
+ return true;
3700
+ } catch {
3701
+ return false;
3702
+ }
3703
+ }
3704
+ function noteUnlockedBuild() {
3705
+ info("Building without an identity lock (`--no-lock`).");
3706
+ detail("Identities derive from names, so renaming an object becomes delete-and-create on sync.");
3707
+ detail(
3708
+ "Public URLs not pinned in code are left for the instance to invent, and this project will not learn them; a `canonical` written on a def still applies."
3709
+ );
3710
+ detail(
3711
+ "`xanosdk deploy --to <backend> --prune` needs the lock to know what this project owns there, so it is unavailable except onto an ephemeral, whose landing record is kept in .xano/ephemeral.json instead."
3712
+ );
3713
+ }
3714
+ function adoptBeforeFirstLock(lockPath, args) {
3715
+ const deploying = args?.command === "deploy";
3716
+ if (deploying && (args.localEngine || args.to === void 0 || args.to.startsWith("local-engine"))) return void 0;
3717
+ const importLine = `\`xanosdk lock import live.json --lock=${shellWord(displayPath(lockPath))} --yes\``;
3718
+ const ending = "so the lock adopts the URLs it already serves instead of values it will not accept.";
3719
+ const target = deploying ? args.to : "workspace";
3720
+ const colon = target.indexOf(":");
3721
+ const kind = colon === -1 ? target : target.slice(0, colon);
3722
+ const name = colon === -1 ? void 0 : target.slice(colon + 1);
3723
+ if (kind === "ephemeral") {
3724
+ return `Deploying to an ephemeral that already holds objects? Adopt what it serves first \u2014 \`xanosdk ephemeral export${name === void 0 || name === "" ? "" : ` ${shellWord(name)}`} --path live.json${contextFlags()}\`, then ${importLine} \u2014 ${ending}`;
3725
+ }
3726
+ if (kind === "tenant") return void 0;
3727
+ return `Deploying to a workspace that already exists? Adopt what it serves first \u2014 \`xanosdk workspace export --path live.json${contextFlags()}\`, then ${importLine} \u2014 ${ending}`;
3728
+ }
3729
+ function noteLockCreated(lockPath, args, opts = {}) {
3730
+ info(`Wrote ${displayPath(lockPath)} \u2014 commit it.`);
3731
+ detail("It pins this project's object identities and public URLs: renames stay renames, and the");
3732
+ detail("URLs stay yours. A later deploy honors what it records.");
3733
+ const adopt = opts.adopt === false ? void 0 : adoptBeforeFirstLock(lockPath, args);
3734
+ if (adopt !== void 0) detail(adopt);
3735
+ if (isCI()) {
3736
+ warn(
3737
+ "This lock was created in CI, which means the repository does not have one.",
3738
+ "lock.created-in-ci",
3739
+ [
3740
+ "It is discarded with the checkout and re-minted next run, so the identities it froze",
3741
+ "do not survive. Commit the lock, or add `--frozen-lock` to fail instead."
3742
+ ]
3743
+ );
3744
+ }
3745
+ }
3746
+ function commandLabel(args) {
3747
+ return [args.command ?? "export", args.subcommand].filter((p) => p !== void 0).join(" ");
3748
+ }
3749
+ function describeDefaultExport(def) {
3750
+ if (def === void 0) return "no default export";
3751
+ if (def === null) return "null";
3752
+ if (Array.isArray(def)) return "an array (export one def, not a list)";
3753
+ if (typeof def !== "object") return `a ${typeof def}`;
3754
+ return "an object with no `name`";
3755
+ }
3756
+ async function runCompile(args) {
3757
+ const file = args.file;
3758
+ if (existsSync2(file) && statSync3(file).isDirectory()) {
3759
+ const example = readdirSync2(file).filter((n) => /\.[mc]?ts$/.test(n) && !n.endsWith(".d.ts")).sort()[0] ?? "<def>.ts";
3760
+ throw new UsageError(
3761
+ `compile: "${file}" is a directory. \`compile\` takes one module that exports a single def \u2014 \`xanosdk compile ${shellWord(join2(file, example))}\`; for a whole workspace, \`xanosdk export <entry>\`.`,
3762
+ { hintFor: { command: "compile" } }
3763
+ );
3764
+ }
3765
+ const lockPath = args.lockPath !== void 0 ? resolve2(args.lockPath) : nearestLockPath(file);
3766
+ if (args.lockPath !== void 0 && !existsSync2(lockPath)) {
3767
+ throw new UsageError(
3768
+ `compile: no lock file at ${displayPath(lockPath)}. \`compile\` reads the lock and never writes one \u2014 point \`--lock\` at the xano.lock \`xanosdk export\` wrote, or drop it to use the nearest one.`,
3769
+ { hintFor: { command: "compile" } }
3770
+ );
3771
+ }
3772
+ resetLockOverrides();
3773
+ if (existsSync2(lockPath)) {
3774
+ seedLockOverrides(readLockFile(lockPath));
3775
+ }
3776
+ const mod = await loadModule(file);
3777
+ const namedDefs = () => Object.entries(mod).filter(
3778
+ ([key, value]) => key !== "default" && value !== null && typeof value === "object" && !Xano.isXano(value) && typeof value.name === "string"
3779
+ );
3780
+ if (args.exportName !== void 0 && !Object.hasOwn(mod, args.exportName)) {
3781
+ const names = namedDefs().map(([key]) => `\`${key}\``);
3782
+ throw new UsageError(
3783
+ `Module "${file}" has no export \`${args.exportName}\`.` + (names.length > 0 ? ` Its named defs: ${names.join(", ")}.` : ""),
3784
+ { hintFor: { command: "compile" } }
3785
+ );
3786
+ }
3787
+ let def = args.exportName !== void 0 ? mod[args.exportName] : mod.default;
3788
+ if (def === void 0 && args.exportName === void 0) {
3789
+ const named = namedDefs();
3790
+ if (named.length === 1) {
3791
+ def = named[0][1];
3792
+ info(`Compiling the named export \`${named[0][0]}\` (the module has no default export).`);
3793
+ } else if (named.length > 1) {
3794
+ throw new UsageError(
3795
+ `Module "${file}" has no default export and ${named.length} named defs \u2014 ${named.map(([key]) => `\`${key}\``).join(", ")} \u2014 so \`compile\`, which takes one def, cannot tell which to compile. Name one: \`xanosdk compile ${shellWord(file)} --export ${named[0][0]}\`, or export the workspace with \`xanosdk export\`.`,
3796
+ { hintFor: { command: "compile" } }
3797
+ );
3798
+ }
3799
+ }
3800
+ if (Xano.isXano(def)) {
3801
+ throw new UsageError(
3802
+ `Module "${file}" default-exports a workspace \u2014 use \`xanosdk export\` (or \`xanosdk routes\`) for a workspace entry. \`compile\` takes a single object def (a query, function, table, \u2026) and prints its JSON artifact.`,
3803
+ { hintFor: { command: "compile" } }
3804
+ );
3805
+ }
3806
+ if (!def || typeof def !== "object" || typeof def.name !== "string") {
3807
+ throw new UsageError(
3808
+ `Module "${file}" must default-export a single object def (a query, function, table, \u2026) \u2014 one object with a \`name\`. Got: ${describeDefaultExport(def)}.`,
3809
+ { hintFor: { command: "compile" } }
3810
+ );
3811
+ }
3812
+ const one = def;
3813
+ const encode = await emitterFor(file);
3814
+ if (encode === emit && standaloneDefKind(one) === void 0) throw unplaceableDef(file, one.name);
3815
+ const raised = [];
3816
+ const previousSink = setDiagnosticSink((d) => raised.push(d));
3817
+ const docTokens = /* @__PURE__ */ Object.create(null);
3818
+ for (const [key, entry] of Object.entries(readSecretsFile(join2(dirname2(lockPath), ".secrets.json"))?.documentationTokens ?? {})) {
3819
+ docTokens[key] = entry.value;
3820
+ }
3821
+ let artifact;
3822
+ try {
3823
+ artifact = withPinnedGuid(encode(one, { hostedFiles: hostedFileResolver(), documentationTokens: docTokens }), one);
3824
+ } catch (err) {
3825
+ if (encode !== emit && err instanceof Error && /cannot tell what kind of def/.test(err.message)) {
3826
+ throw unplaceableDef(file, one.name);
3827
+ }
3828
+ throw err;
3829
+ } finally {
3830
+ setDiagnosticSink(previousSink);
3831
+ }
3832
+ if (standaloneDefKind(one) === "knowledge") artifact = withKnowledgeContent(artifact, one, raised);
3833
+ const parsedArtifact = JSON.parse(artifact);
3834
+ const gate = one.documentation;
3835
+ if (standaloneDefKind(one) === "api_group" && gate?.require_token === true && parsedArtifact.documentation === void 0) {
3836
+ raised.push({
3837
+ severity: "warning",
3838
+ code: "doc-token.unsupplied",
3839
+ message: `API group "${one.name}" declares a documentation gate and no token was found for it in \`${displayPath(join2(dirname2(lockPath), ".secrets.json"))}\`, so this artifact carries no \`documentation\` block \u2014 the bytes an export would write CLEAR the group's gate. \`xanosdk pull\` stores the token there.`
3840
+ });
3841
+ }
3842
+ checkCompiledDef(one, artifact, args.strict === true, raised);
3843
+ if (args.out && args.out !== "-") {
3844
+ mkdirSync(dirname2(resolve2(args.out)), { recursive: true });
3845
+ writeFileSync(args.out, artifact + "\n", "utf8");
3846
+ reportWrote(args, args.out);
3847
+ } else {
3848
+ writeData(process.stdout, artifact + "\n");
3849
+ }
3850
+ }
3851
+ function withKnowledgeContent(artifact, def, raised) {
3852
+ const [resolved] = resolveKnowledge([def]);
3853
+ if (resolved === void 0) return artifact;
3854
+ for (const w of resolved.warnings ?? []) raised.push({ severity: "warning", code: w.code, message: w.message });
3855
+ return JSON.stringify({ ...JSON.parse(artifact), content: resolved.content }, null, 2);
3856
+ }
3857
+ function unplaceableDef(file, name) {
3858
+ return new UsageError(
3859
+ `Module "${file}" exports "${name}", which nothing marks as a kind of def \u2014 no factory brand, no \`verb\`, \`schema\` or group key \u2014 so \`compile\` cannot tell which encoder to use. Build it with its factory (\`defineFunction({...})\`, \`table({...})\`, \`task({...})\`, \u2026) rather than as an object literal or a spread copy.`,
3860
+ { hintFor: { command: "compile" } }
3861
+ );
3862
+ }
3863
+ function withPinnedGuid(artifact, def) {
3864
+ if (typeof def.guid !== "string" || def.guid === "") return artifact;
3865
+ const parsed = JSON.parse(artifact);
3866
+ if (parsed.guid !== void 0) return artifact;
3867
+ return JSON.stringify({ ...parsed, guid: def.guid }, null, 2);
3868
+ }
3869
+ async function runPaths(args) {
3870
+ const file = args.file;
3871
+ if (args.emit === "-" && args.strict) {
3872
+ throw new UsageError(
3873
+ "`--strict` checks a committed route manifest, and `--emit -` writes to stdout \u2014 name the file it should check: `--emit <path> --strict`.",
3874
+ { hintFor: { command: "routes" } }
3875
+ );
3876
+ }
3877
+ const lockPath = resolveLockPath(args, file);
3878
+ resetLockOverrides();
3879
+ const lockModel = existsSync2(lockPath) ? readLockFile(lockPath) : void 0;
3880
+ const def = await loadDefault(file);
3881
+ if (!Xano.isXano(def)) {
3882
+ throw new UsageError(
3883
+ `Module "${file}" must default-export a Xano registry for \`${commandLabel(args)}\` \u2014 \`export default workspace("\u2026")\u2026\`. Got: ${describeDefaultExport(def)}.`
3884
+ );
3885
+ }
3886
+ const outerSink = setDiagnosticSink((d) => {
3887
+ if (d.code !== "microservice.early-surface") outerSink(d);
3888
+ });
3889
+ let bundle;
3890
+ try {
3891
+ bundle = def.export({ strict: args.strict, documentationTokens: checkStandInTokens(def).values });
3892
+ } finally {
3893
+ setDiagnosticSink(outerSink);
3894
+ }
3895
+ const payload = bundle.payload;
3896
+ const { planRouteManifest } = await import("./routes-manifest-SNWUVBT6.js");
3897
+ const plan = planRouteManifest(payload, (kind, name) => lockModel?.objects[lockKey(kind, name)]?.canonical);
3898
+ const queryCount = plan.rows.length;
3899
+ const realtimeCount = plan.servers.length + plan.unresolvedServers.length;
3900
+ const machine = isMachineOutput(args);
3901
+ const emptiedManifest = args.emit !== void 0 && queryCount === 0 && realtimeCount === 0 && existsSync2(args.emit);
3902
+ if (queryCount === 0 && !(args.emit !== void 0 && realtimeCount > 0) && !emptiedManifest) {
3903
+ info("No API queries registered in this workspace.");
3904
+ if (machine && args.emit !== "-") writeJson(args.emit !== void 0 ? { emit: resolve2(args.emit), written: false, routes: 0, channels: 0 } : { routes: [] });
3905
+ return;
3906
+ }
3907
+ const unresolved = plan.unresolved;
3908
+ const resolved = plan.resolved;
3909
+ if (args.emit !== void 0) {
3910
+ const unresolvedServers = plan.unresolvedServers.map((name) => ({ name }));
3911
+ const describableServers = plan.servers;
3912
+ const channelRows = plan.channels;
3913
+ if (unresolvedServers.length > 0) {
3914
+ warn(
3915
+ `${args.emit}: leaving out ${countOf(unresolvedServers.length, "realtime server")} \u2014 ${unresolvedServers.map((s) => `"${s.name}"`).join(", ")} \u2014 whose canonical URL token resolves nowhere, along with their channels. Set an explicit \`realtimeServer({ canonical })\`, or run \`xanosdk export ${shellWord(file)} --out ${NULL_DEVICE}\` once (it mints a unique canonical and freezes it in xano.lock, and writes the bundle nowhere), then re-run to include them.`,
3916
+ "routes.realtime-unresolved"
3917
+ );
3918
+ }
3919
+ if (unresolved.length > 0) {
3920
+ const { unresolvedCanonicalMessage } = await import("./routes-manifest-SNWUVBT6.js");
3921
+ const why = `${args.emit} was not written: ${unresolvedCanonicalMessage(unresolved, shellWord(file))}`;
3922
+ if (args.strict) throw new Error(`--strict: ${why}`);
3923
+ warn(why, "routes.not-written");
3924
+ if (machine && args.emit !== "-") writeJson({ emit: resolve2(args.emit), written: false, routes: 0, channels: 0 });
3925
+ return;
3926
+ }
3927
+ if (resolved.length === 0 && describableServers.length === 0 && !emptiedManifest) {
3928
+ info(`Nothing to write to ${args.emit} yet.`);
3929
+ if (machine && args.emit !== "-") writeJson({ emit: resolve2(args.emit), written: false, routes: 0, channels: 0 });
3930
+ return;
3931
+ }
3932
+ const { renderPlannedManifest, renderRouteManifest } = await import("./routes-manifest-SNWUVBT6.js");
3933
+ const source = emptiedManifest ? renderRouteManifest([]) : renderPlannedManifest(plan);
3934
+ const routeCount = resolved.length === 1 ? "1 route" : `${resolved.length} routes`;
3935
+ const channelCount = channelRows.length === 1 ? "1 channel" : `${channelRows.length} channels`;
3936
+ const count = describableServers.length > 0 ? `${routeCount}, ${channelCount}` : routeCount;
3937
+ if (args.emit === "-") {
3938
+ writeData(process.stdout, source);
3939
+ return;
3940
+ }
3941
+ const { installedSdk, skewedProjectSdk, skewNote, installedCliCommand } = await import("./project-sdk-REPPOIBD.js");
3942
+ const emitDir = dirname2(resolve2(args.emit));
3943
+ const projectSdk = skewedProjectSdk(installedSdk(emitDir) !== void 0 ? emitDir : dirname2(resolve2(file)), readVersion());
3944
+ if (projectSdk !== void 0 && existsSync2(args.emit) && readFileSync3(args.emit, "utf8") !== source) {
3945
+ const emit2 = args.emit;
3946
+ const installed = installedCliCommand(
3947
+ projectSdk.root,
3948
+ (path) => `routes ${path(file)} --emit ${path(emit2)}${args.strict ? " --strict" : ""}`
3949
+ );
3950
+ if (args.strict) {
3951
+ throw new CliError(
3952
+ DRIFT,
3953
+ `--strict: ${displayPath(emit2)} differs from what this CLI (@xano/sdk ${readVersion()}) renders, and the project has ${projectSdk.version} installed, whose wording the table follows \u2014 so this CLI cannot tell a stale table from a current one. Run \`${installed}\` to check it with the installed CLI.`
3954
+ );
3955
+ }
3956
+ warn(skewNote(emit2, readVersion(), projectSdk.version, installed), "routes.cli-skew");
3957
+ if (machine) writeJson({ emit: resolve2(emit2), written: false, routes: resolved.length, channels: 0 });
3958
+ return;
3959
+ }
3960
+ if (args.strict) {
3961
+ const current = existsSync2(args.emit) ? readFileSync3(args.emit, "utf8") : void 0;
3962
+ if (current !== source) {
3963
+ throw new CliError(
3964
+ DRIFT,
3965
+ `--strict: ${args.emit} is ${current === void 0 ? "missing" : "out of date"}. Run ${routesRegenerateCommand(file, args.emit)} and commit the result \u2014 a stale route manifest keeps compiling while the endpoints have moved.`
3966
+ );
3967
+ }
3968
+ info(`${args.emit} is up to date (${count}).`);
3969
+ }
3970
+ let written = false;
3971
+ if (!args.strict) {
3972
+ const current = existsSync2(args.emit) ? readFileSync3(args.emit, "utf8") : void 0;
3973
+ if (current === source) {
3974
+ info(`${args.emit} is already up to date (${count}).`);
3975
+ } else {
3976
+ try {
3977
+ mkdirSync(dirname2(resolve2(args.emit)), { recursive: true });
3978
+ writeFileSync(args.emit, source, "utf8");
3979
+ } catch (err) {
3980
+ if (isUnwritableError(err)) throw unwritableError(args.emit, "pass `--emit` a path you can write");
3981
+ throw err;
3982
+ }
3983
+ written = true;
3984
+ info(`Wrote ${args.emit} (${count}).`);
3985
+ }
3986
+ }
3987
+ if (machine) {
3988
+ writeJson({
3989
+ emit: resolve2(args.emit),
3990
+ written,
3991
+ routes: resolved.length,
3992
+ channels: describableServers.length > 0 ? channelRows.length : 0
3993
+ });
3994
+ }
3995
+ } else if (machine) {
3996
+ if (unresolved.length === 0) {
3997
+ writeJson({
3998
+ routes: resolved.map((r) => ({
3999
+ verb: r.verb,
4000
+ path: `/api:${r.canonical}/${r.name}`,
4001
+ ref: `api:${r.canonical}/${r.name}`
4002
+ }))
4003
+ });
4004
+ }
4005
+ } else {
4006
+ const verbWidth = Math.max(0, ...resolved.map((r) => r.verb.length));
4007
+ for (const r of resolved) {
4008
+ const path = `/api:${r.canonical}/${r.name}`;
4009
+ process.stdout.write(`${r.verb.padEnd(verbWidth)} ${path} api:${r.canonical}/${r.name}
4010
+ `);
4011
+ }
4012
+ }
4013
+ if (unresolved.length > 0) {
4014
+ const { unresolvedCanonicalMessage } = await import("./routes-manifest-SNWUVBT6.js");
4015
+ throw new UsageError(`${commandLabel(args)}: ${unresolvedCanonicalMessage(unresolved, shellWord(file))}`);
4016
+ }
4017
+ }
4018
+ async function refreshRouteManifest(entry, emit2) {
4019
+ resetLockOverrides();
4020
+ const lockPath = join2(dirname2(resolve2(entry)), "xano.lock");
4021
+ const lockModel = existsSync2(lockPath) ? readLockFile(lockPath) : void 0;
4022
+ const def = await loadDefault(entry);
4023
+ if (!Xano.isXano(def)) return { manifest: "absent", lockOrphans: 0 };
4024
+ const previousSink = setDiagnosticSink(() => {
4025
+ });
4026
+ let payload;
4027
+ try {
4028
+ payload = def.export({ documentationTokens: checkStandInTokens(def).values }).payload;
4029
+ } finally {
4030
+ setDiagnosticSink(previousSink);
4031
+ }
4032
+ const { pulledIdentities } = await import("./pull-command-VBO7C4S3.js");
4033
+ const live = pulledIdentities(payload);
4034
+ const lockOrphans = lockModel === void 0 ? 0 : Object.keys(lockModel.objects).filter((k) => k !== WORKSPACE_KEY && !live.has(k)).length;
4035
+ if (!existsSync2(emit2)) return { manifest: "absent", lockOrphans };
4036
+ const { planRouteManifest, renderPlannedManifest, renderRouteManifest } = await import("./routes-manifest-SNWUVBT6.js");
4037
+ const plan = planRouteManifest(payload, (kind, name) => lockModel?.objects[lockKey(kind, name)]?.canonical);
4038
+ if (plan.unresolved.length > 0) return { manifest: "skipped", lockOrphans };
4039
+ const source = renderPlannedManifest(plan) ?? (plan.resolved.length === 0 && plan.servers.length === 0 ? renderRouteManifest([]) : void 0);
4040
+ if (source === void 0) return { manifest: "skipped", lockOrphans };
4041
+ if (readFileSync3(emit2, "utf8") === source) return { manifest: "unchanged", lockOrphans };
4042
+ try {
4043
+ writeFileSync(emit2, source, "utf8");
4044
+ } catch (err) {
4045
+ if (isUnwritableError(err)) throw unwritableError(emit2);
4046
+ throw err;
4047
+ }
4048
+ return { manifest: "written", lockOrphans };
4049
+ }
4050
+ function routesRegenerateCommand(file, emit2) {
4051
+ try {
4052
+ const pkg = JSON.parse(readFileSync3(join2(process.cwd(), "package.json"), "utf8"));
4053
+ const script = pkg.scripts?.["xano:routes"];
4054
+ if (typeof script === "string" && script.includes(`--emit ${emit2}`)) return "`npm run xano:routes`";
4055
+ } catch {
4056
+ }
4057
+ return `\`xanosdk routes ${shellWord(file)} --emit ${shellWord(emit2)}\``;
4058
+ }
4059
+ async function exportBundleJson(args) {
4060
+ return (await compileBundle(args)).bundle;
4061
+ }
4062
+ async function compileBundle(args, opts = {}) {
4063
+ const file = args.file;
4064
+ const lockPath = resolveLockPath(args, file);
4065
+ const lockExists = existsSync2(lockPath);
4066
+ resetLockOverrides();
4067
+ let lockCtx;
4068
+ let originalSerialized;
4069
+ let droppedLandings = [];
4070
+ strictFindings = args.strict ? [] : void 0;
4071
+ exportFindings = [];
4072
+ let lockReport = null;
4073
+ let commitLock;
4074
+ let deferredOrphans;
4075
+ let uncommittedOrphans;
4076
+ let classifiedLock;
4077
+ if (args.noLock) {
4078
+ if (lockExists && isParseableLock(lockPath)) {
4079
+ if (args.command === "export" && args.check) {
4080
+ throw new UsageError(
4081
+ `\`--no-lock\` refused: ${displayPath(lockPath)} exists, and a check without it would skip the identities it pins. Drop \`--no-lock\`: \`xanosdk export ${shellWord(pastePath(args.file ?? ""))} --check\` checks them too.`
4082
+ );
4083
+ }
4084
+ throw new UsageError(
4085
+ `\`--no-lock\` refused: ${displayPath(lockPath)} exists and pins this project's identities.
4086
+ Building without it derives guids from names instead, so every object the lock pins under a different guid is deleted and recreated by whatever this bundle is released to.
4087
+ Drop \`--no-lock\` to build against the lock, or delete the lock first if you really mean to abandon those identities.`
4088
+ );
4089
+ }
4090
+ assertEntryExists(file);
4091
+ if (!(args.command === "export" && args.check)) noteUnlockedBuild();
4092
+ } else {
4093
+ const loaded = lockExists ? readLockFileReport(lockPath) : { lock: emptyLock(), droppedLandings: [] };
4094
+ const lockModel = loaded.lock;
4095
+ droppedLandings = loaded.droppedLandings;
4096
+ if (lockExists) originalSerialized = serializeLock(lockModel);
4097
+ seedLockOverrides(lockModel);
4098
+ lockCtx = createLockContext(lockModel);
4099
+ }
4100
+ const buildWarnings = [];
4101
+ const previousSink = setDiagnosticSink((diagnostic) => {
4102
+ if (diagnostic.severity === "warning") buildWarnings.push(diagnostic);
4103
+ if (!(args.strict && diagnostic.severity === "warning")) {
4104
+ previousSink(diagnostic);
4105
+ if (diagnostic.severity === "warning") noteRunWarning(diagnostic.code, diagnostic.message, diagnostic.subject);
4106
+ }
4107
+ });
4108
+ const checkOnly = args.command === "export" && args.check;
4109
+ const accepted = [];
4110
+ let def;
4111
+ let bundle;
4112
+ let libraryRefusal;
4113
+ const hostedFiles = hostedFileResolver();
4114
+ let exportForChecks;
4115
+ try {
4116
+ const loaded = await loadDefault(file);
4117
+ if (!Xano.isXano(loaded)) {
4118
+ throw new UsageError(
4119
+ `Module "${file}" must default-export a Xano registry for \`${commandLabel(args)}\` \u2014 \`export default workspace("\u2026")\u2026\`. Got: ${describeDefaultExport(loaded)}.`
4120
+ );
4121
+ }
4122
+ def = loaded;
4123
+ if (opts.seed) await registerSeedHostedFiles(loaded.tables(), hostedFiles, loaded.workspaceSettings().use_xdo === true);
4124
+ const resolvedKnowledge = resolveKnowledge(def.knowledge());
4125
+ const envOverrides = checkOnly ? {} : resolveWorkspaceEnv(args, file, def.workspaceSettings());
4126
+ const docTokens = checkOnly ? checkStandInTokens(def) : resolveDocumentationTokens(args, file, def);
4127
+ const exportOptions = {
4128
+ knowledge: resolvedKnowledge,
4129
+ ...Object.keys(envOverrides).length > 0 ? { envOverrides } : {},
4130
+ documentationTokens: docTokens.values,
4131
+ allowEmptyDocToken: docTokens.allowEmpty,
4132
+ secretsRemedy: secretsRemedyFor(file)
4133
+ };
4134
+ const built = def;
4135
+ exportForChecks = () => built.export({ ...exportOptions, hostedFiles: hostedFileResolver() });
4136
+ bundle = def.export({ ...lockCtx ? { lock: lockCtx } : {}, strict: args.strict, ...exportOptions, hostedFiles, accepted });
4137
+ } catch (err) {
4138
+ if (!(args.strict && isDiagnosticError(err))) throw err;
4139
+ libraryRefusal = err;
4140
+ } finally {
4141
+ setDiagnosticSink(previousSink);
4142
+ noteRunAccepted(accepted);
4143
+ }
4144
+ checkFilterNames(bundle ?? quietly(exportForChecks));
4145
+ const library = [...buildWarnings, ...libraryRefusal?.details ?? []];
4146
+ if (args.strict && library.some((d) => d.severity === "warning")) failStrictFindings(args, library);
4147
+ if (libraryRefusal !== void 0) throw libraryRefusal;
4148
+ failStrictFindings(args);
4149
+ if (bundle === void 0 || def === void 0) throw new Error("unreachable: no bundle and no refusal");
4150
+ const literalIcons = uncarriedHostedIcons(
4151
+ bundle.payload ?? {},
4152
+ new Set(hostedFiles.files().map((f) => f.canonical))
4153
+ );
4154
+ if (literalIcons.length > 0) {
4155
+ throw new UsageError(
4156
+ `${countOf(literalIcons.length, "icon")} name${literalIcons.length === 1 ? "s" : ""} a hosted file by a literal \`xanosdk-file://\` src, which carries no bytes \u2014 a bundle's placeholder copied into source:
4157
+ ` + literalIcons.map((i) => ` ${i.owner} \`icons[${i.index}]\`: save the image as ${i.name} beside its module and write \`src: hostedFile("./${i.name}", import.meta.url)\``).join("\n")
4158
+ );
4159
+ }
4160
+ if (lockCtx) {
4161
+ const { lock: merged, orphans, dropped, cededCanonicals } = mergeObserved(
4162
+ lockCtx.lock,
4163
+ lockCtx.observed,
4164
+ // A gate that never writes keeps the `lock import` provenance note: its
4165
+ // clearing is not drift. A writing export clears it for what it declares.
4166
+ {
4167
+ keepAdopted: args.frozenLock === true || args.lockReadOnly === true,
4168
+ landedGuids: new Set(allLandings(process.cwd(), lockCtx.lock).flatMap(([, record]) => Object.values(record).map((e) => e.guid)))
4169
+ }
4170
+ );
4171
+ validateLockModel(merged, displayPath(lockPath), lockCtx.observed);
4172
+ classifiedLock = merged;
4173
+ const gate = checkOnly ? "export --check" : "--frozen-lock";
4174
+ const kinds = toolsetKindsFromPayload(bundle.payload, lockCtx.lock.objects);
4175
+ if (args.frozenLock && !args.allowLockOrphans && orphans.length > 0) {
4176
+ throw frozenOrphanError(orphans, file, lockPath, gate, { previous: lockCtx.lock, observed: lockCtx.observed, kinds });
4177
+ }
4178
+ const changed = originalSerialized === void 0 ? Object.keys(merged.objects).length > 0 : serializeLock(merged) !== originalSerialized || droppedLandings.length > 0;
4179
+ const identitiesChanged = changed && (originalSerialized === void 0 || droppedLandings.length > 0 || serializeLock(withoutGuidSources(merged)) !== serializeLock(withoutGuidSources(lockCtx.lock)));
4180
+ if (args.frozenLock && identitiesChanged) {
4181
+ throw new CliError(
4182
+ DRIFT,
4183
+ frozenChangeMessage(gate, lockExists ? lockCtx.lock : void 0, merged, file, lockPath, def, args, kinds, droppedLandings)
4184
+ );
4185
+ }
4186
+ if (args.strict && args.lockReadOnly !== true) {
4187
+ warnOrphans(orphans, dropped, cededCanonicals, lockCtx.lock, lockCtx.observed, file, lockPath, kinds, args.frozenLock || args.dryRun === true, args.allowLockOrphans);
4188
+ failStrictFindings(args);
4189
+ }
4190
+ const skipWrite = args.lockReadOnly === true || args.frozenLock || !lockExists && Object.keys(merged.objects).length === 0;
4191
+ const observedLock = lockCtx.lock;
4192
+ const observed = lockCtx.observed;
4193
+ const repinned = lockCtx.repinned ?? [];
4194
+ const dryRun = args.dryRun === true;
4195
+ let orphansWarned = false;
4196
+ const warnLockOrphans = (pruned) => {
4197
+ if (orphansWarned || args.strict || args.lockReadOnly === true && !dryRun) return;
4198
+ orphansWarned = true;
4199
+ const unexplained = pruned === void 0 ? orphans : orphans.filter((key) => !pruned.has(key));
4200
+ const ceded = pruned === void 0 ? cededCanonicals : cededCanonicals.filter((key) => !pruned.has(key));
4201
+ warnOrphans(unexplained, dropped, ceded, observedLock, observed, file, lockPath, kinds, dryRun || skipWrite, args.allowLockOrphans);
4202
+ };
4203
+ const writeLock = (commitOpts) => {
4204
+ try {
4205
+ if (!skipWrite) writeLockFile(lockPath, merged);
4206
+ } catch (err) {
4207
+ const noDir = missingLockDir(args);
4208
+ if (noDir !== void 0) throw new UsageError(noDir);
4209
+ const reason = err instanceof Error ? err.message : String(err);
4210
+ const remedy = lockExists ? "Point at a writable location with `--lock=<path>`, or make the directory writable." : "Build without a lock with `--no-lock` (identities then derive from names), or make the directory writable.";
4211
+ const message = `Could not write ${displayPath(lockPath)}: ${reason}
4212
+ ${remedy}`;
4213
+ throw isUnwritableError(err) ? new UsageError(message) : new Error(message);
4214
+ }
4215
+ if (!lockExists && !skipWrite) {
4216
+ noteLockCreated(lockPath, commitOpts?.to === void 0 ? args : { ...args, to: commitOpts.to }, {
4217
+ adopt: commitOpts?.nothingToAdopt !== true
4218
+ });
4219
+ } else if (lockExists && !skipWrite && changed) info(`Updated ${displayPath(lockPath)} \u2014 commit it.`);
4220
+ if (!skipWrite) {
4221
+ for (const r of repinned) {
4222
+ const shown = displayLockKey(r.key, kinds);
4223
+ if (!r.key.startsWith("dbo:")) {
4224
+ detail(`${shown} now pins ${r.to}, the guid its def declares (the lock had ${r.from}).`);
4225
+ continue;
4226
+ }
4227
+ const name = r.key.slice("dbo:".length);
4228
+ if (merged.objects[r.key]?.replaced?.includes(r.from) !== true) {
4229
+ detail(`${shown} now pins ${r.to}, the guid its def declares (the lock had ${r.from}).`);
4230
+ continue;
4231
+ }
4232
+ warn(
4233
+ `${shown} now pins ${r.to}, the guid its def declares \u2014 the lock had ${r.from}. An environment holding the table under ${r.from} would drop it with its rows at the next merge, so xano.lock keeps ${r.from} as \`replaced\` and a keep-data deploy there refuses until you choose. If it is the same table, set its def to \`guid: "${r.from}"\`.`,
4234
+ "lock.repinned-table",
4235
+ [
4236
+ `if the old table is not wanted: xanosdk lock prune --identity-only ${shellWord(`table:${name}`)} --lock=${shellWord(displayPath(lockPath))} --yes \u2014 then, where an environment holds it, rename the def to "${name}_tmp" and deploy, then back to "${name}" and deploy again: a merge cannot replace a table with another of its own name, so the first drops the old table with its rows and the second renames the new one`
4237
+ ]
4238
+ );
4239
+ }
4240
+ }
4241
+ if (opts.deferOrphanWarning !== true) warnLockOrphans(commitOpts?.pruned);
4242
+ };
4243
+ if (opts.deferOrphanWarning === true) deferredOrphans = warnLockOrphans;
4244
+ lockReport = !lockExists && Object.keys(merged.objects).length === 0 ? null : { path: displayPath(lockPath), changed: !skipWrite && changed };
4245
+ if (opts.deferLockWrite === true && !skipWrite) {
4246
+ commitLock = writeLock;
4247
+ if (opts.deferOrphanWarning !== true) uncommittedOrphans = () => warnLockOrphans();
4248
+ if (dryRun && opts.deferOrphanWarning !== true) warnLockOrphans();
4249
+ } else writeLock();
4250
+ }
4251
+ reportCapabilities(bundle);
4252
+ const files = hostedFiles.files().map((f) => ({ name: hostedFileArchivePath(f), content: f.bytes }));
4253
+ const resolvedContent = await buildSeedContentFiles(
4254
+ def.tables(),
4255
+ opts.seed ? hostedFiles : hostedFileResolver(),
4256
+ def.workspaceSettings().use_xdo === true
4257
+ );
4258
+ const content = opts.seed ? resolvedContent : [];
4259
+ const nonPublicSeedValues = opts.seed ? await collectNonPublicSeedValues(def.tables()) : [];
4260
+ const omittedSeedTables = opts.seed ? [] : def.tables().filter((t) => t.seed !== void 0 && !(Array.isArray(t.seed) && t.seed.length === 0)).map((t) => t.name);
4261
+ await refreshAgentGuidance(args);
4262
+ return {
4263
+ bundle: serializeBundle(bundle),
4264
+ bundleObject: bundle,
4265
+ content,
4266
+ files,
4267
+ omittedSeedTables,
4268
+ nonPublicSeedValues,
4269
+ lock: lockReport,
4270
+ declaredEnvNames: declaredEnv(def.workspaceSettings()).map((e) => e.name),
4271
+ warnings: [
4272
+ ...buildWarnings.map(jsonWarning),
4273
+ ...exportFindings
4274
+ ],
4275
+ ...classifiedLock !== void 0 ? { classifiedLock } : {},
4276
+ ...commitLock !== void 0 ? { commitLock } : {},
4277
+ ...deferredOrphans !== void 0 ? { warnLockOrphans: deferredOrphans } : {},
4278
+ ...uncommittedOrphans !== void 0 ? { warnOrphansUncommitted: uncommittedOrphans } : {}
4279
+ };
4280
+ }
4281
+ function projectRelative(path, entryFile, fallback) {
4282
+ if (pathsShownFrom() !== void 0) return displayPath(path);
4283
+ return relForwardSlash(process.cwd(), path) || relForwardSlash(projectRootFrom(dirname2(resolve2(entryFile))), path) || fallback;
4284
+ }
4285
+ function secretsRemedyFor(entryFile) {
4286
+ const path = defaultWorkspaceSecretsPath(entryFile);
4287
+ const fill = `xanosdk secrets fill ${shellWord(entryFile)}`;
4288
+ const dir = dirname2(path);
4289
+ return {
4290
+ file: projectRelative(path, entryFile, WORKSPACE_SECRETS_FILE),
4291
+ fill: existsSync2(dir) ? fill : `mkdir ${shellWord(displayPath(dir))} && ${fill}`
4292
+ };
4293
+ }
4294
+ function resolveWorkspaceEnv(args, file, settings) {
4295
+ const declared = declaredEnv(settings);
4296
+ const declaredNames = declared.map((e) => e.name);
4297
+ const declaredValues = Object.fromEntries(declared.map((e) => [e.name, e.value]));
4298
+ const explicit = args.envFile !== void 0 ? resolve2(args.envFile) : void 0;
4299
+ const defaultPath = defaultWorkspaceEnvPath(file);
4300
+ const defaultLabel = projectRelative(defaultPath, file, WORKSPACE_ENV_FILE);
4301
+ const fileValues = explicit !== void 0 ? parseEnvFile(explicit) : readWorkspaceEnvFile(defaultPath);
4302
+ const badDeclared = declaredNames.filter((n) => !isRepresentableName(n));
4303
+ if (badDeclared.length > 0) {
4304
+ const one = badDeclared.length === 1;
4305
+ throw new UsageError(
4306
+ `\`workspaceConfig({ env })\` declares ${quotedNames(badDeclared)}, which ${one ? "is not a usable env var name" : "are not usable env var names"}. ${envNameRule()} Rename ${one ? "it" : "them"} there, and in every \`env("\u2026")\` that reads ${one ? "it" : "them"}.`
4307
+ );
4308
+ }
4309
+ const badInFile = Object.keys(fileValues ?? {}).filter((n) => !isRepresentableName(n));
4310
+ if (badInFile.length > 0) {
4311
+ const one = badInFile.length === 1;
4312
+ const where = explicit !== void 0 ? displayPath(explicit) : defaultLabel;
4313
+ throw new UsageError(
4314
+ `\`${where}\` sets ${quotedNames(badInFile)}, which ${one ? "is not a usable env var name" : "are not usable env var names"}. ${envNameRule()} Rename ${one ? "it" : "them"} in the file.`
4315
+ );
4316
+ }
4317
+ const resolution = classifyEnv({
4318
+ fileValues: fileValues ?? {},
4319
+ flagValues: args.envVars,
4320
+ declaredNames,
4321
+ declaredValues
4322
+ });
4323
+ const source = explicit !== void 0 ? displayPath(explicit) : fileValues !== void 0 ? defaultLabel : void 0;
4324
+ const allowed = new Set(args.allowEmptyEnv);
4325
+ const undeclared = [...allowed].filter((n) => !declaredNames.includes(n) && args.envVars[n] !== "");
4326
+ if (undeclared.length > 0) {
4327
+ throw new UsageError(
4328
+ `--allow-empty-env: ${safeNames(undeclared)} ${undeclared.length === 1 ? "is" : "are"} not declared.` + (declaredNames.length === 0 ? ` This workspace declares no env vars \u2014 a name is declared in \`workspaceConfig({ env })\`.` : ` Declared: ${safeNames(declaredNames)}.`)
4329
+ );
4330
+ }
4331
+ const unsupplied = resolution.clearing.filter((n) => !allowed.has(n));
4332
+ const refuses = REFUSES_EMPTY_ENV.has(args.command ?? "");
4333
+ const flagged = Object.keys(args.envVars).length;
4334
+ const comparesOnly = args.command === "workspace" && args.subcommand === "diff";
4335
+ const cutsRelease = args.command === "release" && args.subcommand === "create";
4336
+ const merges = refuses && args.command === "deploy" && args.keepData && !args.reset && args.to === void 0;
4337
+ const toMerge = refuses && args.command === "deploy" && args.to !== void 0 && !args.replace;
4338
+ reportWorkspaceEnv({
4339
+ declaredNames,
4340
+ resolution,
4341
+ source,
4342
+ flagged,
4343
+ allowed,
4344
+ refuses,
4345
+ defaultLabel,
4346
+ comparesOnly,
4347
+ cutsRelease,
4348
+ merges: merges ? "`--keep-data`" : toMerge ? "`--to`" : void 0
4349
+ });
4350
+ const examplePath = `${defaultPath}.example`;
4351
+ const exampleLacks = existsSync2(examplePath) ? unsupplied.filter((n) => !namesInEnvExample(examplePath).includes(n)) : void 0;
4352
+ const dryRun = args.dryRun === true;
4353
+ const refusal = (replaceWhy) => unsuppliedEnvError(unsupplied, source ?? defaultLabel, source !== void 0, exampleLacks, {
4354
+ ...replaceWhy !== void 0 ? { replaceWhy } : {},
4355
+ mode: replaceWhy === void 0 && toMerge ? "merge" : "replace",
4356
+ dryRun
4357
+ });
4358
+ mergeExcusedEnv = merges && unsupplied.length > 0 ? refusal : void 0;
4359
+ if (refuses && !merges && unsupplied.length > 0) {
4360
+ if (dryRun) warn(refusal(), "workspace-env.unsupplied");
4361
+ else throw new Error(refusal());
4362
+ }
4363
+ return resolution.values;
4364
+ }
4365
+ function resolveDocumentationTokens(args, file, def) {
4366
+ const declared = def.documentationTokenNames();
4367
+ const byLabel = /* @__PURE__ */ new Map();
4368
+ for (const d of declared) {
4369
+ const label = documentationScopeFlagLabel(d.scope);
4370
+ byLabel.set(label, [...byLabel.get(label) ?? [], d]);
4371
+ }
4372
+ const keyFor = (label, flag) => {
4373
+ const reserved = declared.find((d) => d.scope.kind === "workspace");
4374
+ if (label === "workspace" && reserved !== void 0) return reserved.key;
4375
+ const matches = (byLabel.get(label) ?? []).filter((d) => d.scope.kind === "api_group");
4376
+ if (matches.length === 1) return matches[0].key;
4377
+ const known = [...byLabel.keys()];
4378
+ if (matches.length === 0) {
4379
+ throw new UsageError(
4380
+ `${flag}: no documentation gate is declared for ${JSON.stringify(label)}.` + (known.length === 0 ? ` This workspace declares none \u2014 a gate is \`documentation: { require_token: true }\`.` : ` Declared: ${safeNames(known)}.`)
4381
+ );
4382
+ }
4383
+ throw new Error(
4384
+ `${flag}: ${matches.length} API groups are named ${JSON.stringify(label)}, so that name does not say which one you mean. Rename one of them, or pull again so the group you want carries its own entry in \`${projectRelative(defaultWorkspaceSecretsPath(file), file, WORKSPACE_SECRETS_FILE)}\`.` + (label === "workspace" ? ` (\`workspace\` addresses the WORKSPACE's own gate, which this source does not declare \u2014 a group of that name cannot take the label.)` : "")
4385
+ );
4386
+ };
4387
+ const values = /* @__PURE__ */ Object.create(null);
4388
+ const secretsPath = args.secretsFile !== void 0 ? resolve2(args.secretsFile) : defaultWorkspaceSecretsPath(file);
4389
+ const stored = readSecretsFile(secretsPath, args.secretsFile !== void 0 ? "--secrets-file" : void 0);
4390
+ const source = args.secretsFile !== void 0 ? displayPath(secretsPath) : projectRelative(secretsPath, file, WORKSPACE_SECRETS_FILE);
4391
+ for (const [key, entry] of Object.entries(stored?.documentationTokens ?? {})) {
4392
+ values[key] = entry.value;
4393
+ }
4394
+ for (const [label, value] of Object.entries(args.docTokens)) {
4395
+ values[keyFor(label, "--doc-token")] = value;
4396
+ }
4397
+ const allowEmpty = new Set(args.allowEmptyDocToken.map((l) => keyFor(l, "--allow-empty-doc-token")));
4398
+ const declaredKeys = new Set(declared.map((d) => d.key));
4399
+ const supplied = declared.filter((d) => Object.hasOwn(values, d.key));
4400
+ const cleared = declared.filter((d) => !Object.hasOwn(values, d.key) && allowEmpty.has(d.key));
4401
+ const unsupplied = declared.filter(
4402
+ (d) => d.gated && !Object.hasOwn(values, d.key) && !allowEmpty.has(d.key)
4403
+ );
4404
+ if (supplied.length > 0 || declared.some((d) => d.gated)) {
4405
+ const flagKeys = new Set(Object.keys(args.docTokens).map((label) => keyFor(label, "--doc-token")));
4406
+ const fromFlag = supplied.filter((d) => flagKeys.has(d.key)).length;
4407
+ const toResolve = declared.filter((d) => d.gated || Object.hasOwn(values, d.key));
4408
+ info(
4409
+ `Documentation tokens: ${supplied.length} of ${countOf(toResolve.length, "scope")} resolved` + suppliedFrom(supplied.length - fromFlag, source, fromFlag, "--doc-token", " from")
4410
+ );
4411
+ }
4412
+ const orphans = Object.entries(stored?.documentationTokens ?? {}).filter(([key]) => !declaredKeys.has(key)).map(([, entry]) => entry.label);
4413
+ if (orphans.length > 0) {
4414
+ exportWarn(
4415
+ "doc-token.orphan",
4416
+ `Documentation tokens: \`${source}\` holds ${orphans.length} entr${orphans.length === 1 ? "y" : "ies"} no scope in this source claims \u2014 ${safeNames(orphans)}. Nothing is sent for ${orphans.length === 1 ? "it" : "them"}, and nothing is deleted. ` + // A lock keeps a renamed group's identity, so there the cause is a
4417
+ // group removed, or its gate dropped from the source.
4418
+ (existsSync2(join2(dirname2(secretsPath), "xano.lock")) ? `Usually an API group that was removed, or whose \`documentation\` gate was dropped; ` : `Usually a renamed API group in a project with no lock; `) + // Only a decoded project has a pull that rebuilds the file.
4419
+ (existsSync2(join2(dirname2(secretsPath), ".xanosdk-codegen.json")) ? `pull again to rebuild the file.` : `move the token to the group's new entry, or delete ${orphans.length === 1 ? "the entry" : "them"} from \`${source}\`.`)
4420
+ );
4421
+ }
4422
+ const refuses = REFUSES_EMPTY_DOC_TOKEN.has(args.command ?? "");
4423
+ const workspaceKept = refuses ? docMergeOf(args) : void 0;
4424
+ const clearedWs = workspaceKept === void 0 ? [] : cleared.filter((d) => d.scope.kind === "workspace");
4425
+ const clearedApplied = cleared.filter((d) => !clearedWs.includes(d));
4426
+ if (clearedApplied.length > 0) {
4427
+ exportWarn(
4428
+ "doc-token.cleared",
4429
+ `Documentation tokens: ${safeNames(clearedApplied.map((d) => documentationScopeFlagLabel(d.scope)))} will be sent EMPTY (--allow-empty-doc-token). Whatever gate the target holds for ${clearedApplied.length === 1 ? "that doc site" : "those doc sites"} is cleared, and its docs become publicly readable.`
4430
+ );
4431
+ }
4432
+ if (clearedWs.length > 0) {
4433
+ exportWarn(
4434
+ "doc-token.cleared",
4435
+ `Documentation tokens: workspace \u2014 --allow-empty-doc-token is not applied: a merge leaves the workspace's documentation gate as it is.` + (workspaceKept === "keep-data" ? ` If \`--keep-data\` cannot keep this environment and the deploy replaces it instead, the gate is cleared and its docs become publicly readable.` : "")
4436
+ );
4437
+ }
4438
+ const unsuppliedWs = workspaceKept === void 0 ? [] : unsupplied.filter((d) => d.scope.kind === "workspace");
4439
+ mergeExcusedDocToken = workspaceKept === "keep-data" && unsuppliedWs.length > 0 ? (why) => `${why}, so the deploy replaces it \u2014 which writes the workspace's documentation block.
4440
+ ${unsuppliedDocTokenError(unsuppliedWs, secretsRemedyFor(file))}` : void 0;
4441
+ if (unsuppliedWs.length > 0) {
4442
+ exportWarn(
4443
+ "doc-token.unsupplied",
4444
+ `Documentation tokens: the workspace declares a gate and no token was supplied \u2014 a merge does not write the workspace's \`documentation\` block, so the live gate stays as it is.`
4445
+ );
4446
+ }
4447
+ const applied = unsupplied.filter((d) => !unsuppliedWs.includes(d));
4448
+ if (applied.length > 0) {
4449
+ if (refuses) throw new Error(unsuppliedDocTokenError(applied, secretsRemedyFor(file)));
4450
+ const ws = applied.filter((d) => d.scope.kind === "workspace");
4451
+ const groups = applied.filter((d) => d.scope.kind === "api_group" && !d.published);
4452
+ if (ws.length > 0) {
4453
+ exportWarn(
4454
+ "doc-token.unsupplied",
4455
+ `Documentation tokens: the workspace declares a gate and no token was supplied; no \`documentation\` key is emitted, so this bundle leaves the workspace's gate as it is rather than clearing it \u2014 and cannot restore it either.`
4456
+ );
4457
+ }
4458
+ if (groups.length > 0) {
4459
+ exportWarn(
4460
+ "doc-token.unsupplied",
4461
+ `Documentation tokens: ${countOf(groups.length, "API group")} ${groups.length === 1 ? "declares" : "declare"} a gate with no token (${safeNames(groups.map((d) => documentationScopeFlagLabel(d.scope)))}). Unlike the workspace's, a group's \`documentation\` key is written as the engine default when it is absent, so these bytes CLEAR that group's gate on import. ${groups.length === 1 ? "That group does" : "Those groups do"} not publish docs (\`swagger\` is off), so nothing is exposed \u2014 turn it on and the export fails until the value is supplied.`
4462
+ );
4463
+ }
4464
+ }
4465
+ return { values, allowEmpty };
4466
+ }
4467
+ function availableDocTokenKeys(args, file) {
4468
+ const keys = /* @__PURE__ */ new Set();
4469
+ try {
4470
+ const secretsPath = args.secretsFile !== void 0 ? resolve2(args.secretsFile) : defaultWorkspaceSecretsPath(file);
4471
+ const stored = readSecretsFile(secretsPath, void 0);
4472
+ for (const key of Object.keys(stored?.documentationTokens ?? {})) keys.add(key);
4473
+ } catch {
4474
+ }
4475
+ return keys;
4476
+ }
4477
+ function checkStandInTokens(def) {
4478
+ const values = /* @__PURE__ */ Object.create(null);
4479
+ for (const declared of def.documentationTokenNames()) values[declared.key] = "xanosdk-check";
4480
+ return { values, allowEmpty: /* @__PURE__ */ new Set() };
4481
+ }
4482
+ function docMergeOf(args) {
4483
+ if (args.command !== "deploy" || args.localEngine) return void 0;
4484
+ if (args.to !== void 0) return args.replace || args.to.startsWith("local-engine") ? void 0 : "to";
4485
+ return args.keepData && !args.reset ? "keep-data" : void 0;
4486
+ }
4487
+ function unsuppliedDocTokenError(unsupplied, remedy) {
4488
+ const one = unsupplied.length === 1;
4489
+ const labels = unsupplied.map((d) => documentationScopeFlagLabel(d.scope));
4490
+ const scopes = unsupplied.map((d) => documentationScopeLabel(d.scope));
4491
+ return `Refusing to deploy: ${unsupplied.length} declared documentation gate${one ? "" : "s"} ${one ? "has" : "have"} no token \u2014 ${safeNames(scopes)}.
4492
+ Deploying without ${one ? "it" : "them"} would leave ${one ? "that" : "those"} doc site${one ? "" : "s"} without the gate this source describes \u2014 and \`--allow-empty-doc-token\` would actively clear whatever gate the target holds, making every endpoint, input and response shape in ${one ? "it" : "them"} publicly readable.
4493
+ Run \`${remedy.fill}\` to mint ${one ? "a token" : "tokens"} into \`${remedy.file}\`, pass ${one ? "it" : "them"} with ${labels.map((l) => `\`--doc-token "${l}=<value>"\``).join(" ")}, point at a mounted file with \`--secrets-file <path>\`, or \u2014 if opening ${one ? "that doc site" : "those doc sites"} is what you meant \u2014 ${labels.map((l) => `\`--allow-empty-doc-token="${l}"\``).join(" ")}.
4494
+ Do not put the token back into \`documentation: { token }\` \u2014 a value there is committed to the repo, which is what \`${remedy.file}\` replaces, and the export refuses it.`;
4495
+ }
4496
+ var runScope;
4497
+ function noteRunScope(scope) {
4498
+ runScope = scope === void 0 ? void 0 : { workspaceId: scope.workspaceId, instance: scope.instance, profile: scope.profile };
4499
+ }
4500
+ function trackedBackend(cwd = process.cwd(), scope = runScope) {
4501
+ try {
4502
+ const kind = readTrackedBackend({ cwd, scope }).kind;
4503
+ if (kind !== "ephemeral" || scope === void 0) return { kind };
4504
+ const record = getEnvironment(readEphemeralState(cwd), scope);
4505
+ return record === void 0 ? { kind } : { kind, ephemeral: { name: record.name, expired: isExpired(record.expires_at) } };
4506
+ } catch {
4507
+ return { kind: null };
4508
+ }
4509
+ }
4510
+ var offeredPull;
4511
+ var mergeExcusedEnv;
4512
+ var mergeExcusedDocToken;
4513
+ function docTokenRefusalIfReplaced(replaceWhy) {
4514
+ return mergeExcusedDocToken?.(replaceWhy);
4515
+ }
4516
+ function envRefusalIfReplaced(replaceWhy) {
4517
+ return mergeExcusedEnv?.(replaceWhy);
4518
+ }
4519
+ function fillFrom(source, exampleLacks, one = false) {
4520
+ const tracked = trackedBackend();
4521
+ const expired = tracked.ephemeral?.expired === true;
4522
+ const pull = `run \`xanosdk env pull${contextFlags()}\` to fetch ${one ? "it" : "them"} from the backend this project deployed`;
4523
+ const copy = exampleLacks === void 0 ? void 0 : exampleLacks.length === 0 ? `copy \`${source}.example\` to start` : `copy \`${source}.example\` to start and add ${exampleLacks.join(", ")}, which it does not list`;
4524
+ const ways = [
4525
+ ...copy !== void 0 ? [copy] : [],
4526
+ ...tracked.kind !== null && !expired ? [pull] : []
4527
+ ];
4528
+ offeredPull = tracked.ephemeral !== void 0 && !expired ? { name: tracked.ephemeral.name, clause: pull } : void 0;
4529
+ return ways.length === 0 ? "" : ` (${ways.join(", or ")})`;
4530
+ }
4531
+ function expiredPullNote() {
4532
+ const tracked = trackedBackend();
4533
+ return tracked.ephemeral?.expired === true ? `
4534
+ ${pullGone(tracked.ephemeral.name, "has expired")}` : "";
4535
+ }
4536
+ function pullGone(name, how) {
4537
+ return `The ephemeral this project deployed (${name}) ${how}, so there is no backend to pull the values from.`;
4538
+ }
4539
+ var DO_NOT_COMMIT = "\nDo not put the value back into `workspaceConfig({ env })`";
4540
+ async function refineGonePullHint(err) {
4541
+ const offer = offeredPull;
4542
+ offeredPull = void 0;
4543
+ const auth = lastResolvedAuth()?.auth;
4544
+ if (offer === void 0 || auth === void 0 || !(err instanceof Error) || !err.message.includes(offer.clause)) return;
4545
+ let gone;
4546
+ try {
4547
+ const { lookupEphemeral } = await import("./source-resolve-S2XA3XZF.js");
4548
+ gone = await lookupEphemeral(auth, offer.name) === null;
4549
+ } catch {
4550
+ return;
4551
+ }
4552
+ if (!gone) return;
4553
+ const taken = err.message.includes(`, or ${offer.clause})`) ? err.message.replace(`, or ${offer.clause})`, ")") : err.message.replace(` (${offer.clause})`, "");
4554
+ err.message = taken.replace(DO_NOT_COMMIT, `
4555
+ ${pullGone(offer.name, "is gone")}${DO_NOT_COMMIT}`);
4556
+ }
4557
+ function unsuppliedEnvError(unsupplied, source, found, exampleLacks, opts) {
4558
+ const one = unsupplied.length === 1;
4559
+ const { replaceWhy } = opts;
4560
+ const merge = opts.mode === "merge" && replaceWhy === void 0;
4561
+ return (opts.dryRun ? "Dry run \u2014 the deploy would refuse: " : "Refusing to deploy: ") + `${unsupplied.length} declared env variable${one ? "" : "s"} ${one ? "has" : "have"} no value \u2014 ${unsupplied.join(", ")}.
4562
+ ` + (merge ? `A \`--to\` deploy merges the env add-only: where the target holds ${one ? "that name" : "those names"}, the live value is kept, and where it does not, ${one ? "it" : "each"} would be created there with no value.
4563
+ ` : (replaceWhy !== void 0 ? `${replaceWhy}: this deploy REPLACES` : "A deploy REPLACES") + ` the backend's env set, so sending this bundle would clear ${one ? "that value" : "those values"} in the target.
4564
+ `) + // `source` is the RESOLVED default even when no file was found, so the way
4565
+ // out names the directory this project actually uses. Naming the `xano/`
4566
+ // constant here told a project whose backend is a sibling to put its values
4567
+ // in a directory that is not its backend — the fatal message contradicting
4568
+ // the info line printed one moment earlier.
4569
+ (found ? `Add ${one ? "it" : "them"} to \`${source}\`, ` : `Put the value${one ? "" : "s"} in \`${source}\`` + fillFrom(source, exampleLacks, one) + `, `) + `pass ${one ? "it" : "them"} with \`--env-var NAME=value\`, or \u2014 if ${merge ? "sending" : "clearing"} ${one ? "it" : "them"}${merge ? " empty" : ""} is what you meant \u2014 \`--allow-empty-env=${unsupplied.join(",")}\`.` + (found ? "" : expiredPullNote()) + // The one thing the ways out do not say. For a project scaffolded without
4570
+ // `AGENTS.md`, this message is the ONLY text in the loop, and the tempting
4571
+ // repair is the exact habit `xano/.env` exists to break.
4572
+ `${DO_NOT_COMMIT} \u2014 a value there is committed to the repo, which is what ${source} replaces.`;
4573
+ }
4574
+ function suppliedFrom(fromFile, file, fromFlag, flag, flagOnly) {
4575
+ if (fromFile > 0 && fromFlag > 0) return ` \u2014 ${fromFile} from \`${file}\`, ${fromFlag} from ${flag}.`;
4576
+ if (fromFile > 0) return ` from \`${file}\`.`;
4577
+ if (fromFlag > 0) return `${flagOnly} ${flag}.`;
4578
+ return ".";
4579
+ }
4580
+ function reportWorkspaceEnv(r) {
4581
+ const sent = Object.keys(r.resolution.values).length;
4582
+ const cleared = r.resolution.clearing.filter((n) => r.allowed.has(n));
4583
+ const unsupplied = r.resolution.clearing.filter((n) => !r.allowed.has(n));
4584
+ if (r.declaredNames.length === 0 && sent === 0) {
4585
+ info("Workspace env: no env vars are declared and none were supplied.");
4586
+ } else if (sent > 0) {
4587
+ info(
4588
+ `Workspace env: ${countOf(sent, "value")}` + suppliedFrom(sent - r.flagged, r.source ?? r.defaultLabel, r.flagged, "--env-var", " supplied with")
4589
+ );
4590
+ } else if (r.source !== void 0) {
4591
+ info(`Workspace env: 0 values from \`${r.source}\`.`);
4592
+ } else {
4593
+ const empty = r.resolution.clearing.length;
4594
+ info(
4595
+ `Workspace env: no \`${r.defaultLabel}\` found` + (empty === 0 ? r.declaredNames.length === 1 ? `; the 1 declared value comes from the source.` : `; the ${r.declaredNames.length} declared values come from the source.` : empty === 1 ? `; 1 declared name has no value.` : `; ${empty} declared names have no value.`)
4596
+ );
4597
+ }
4598
+ if (cleared.length > 0) {
4599
+ const those = cleared.length === 1 ? "that name" : "those names";
4600
+ warn(
4601
+ r.comparesOnly === true ? `Workspace env: ${cleared.join(", ")} ${cleared.length === 1 ? "is" : "are"} compared as EMPTY (--allow-empty-env).` : r.merges !== void 0 ? `Workspace env: ${cleared.join(", ")} will be sent EMPTY (--allow-empty-env). A ${r.merges} merge keeps whatever the target holds for ${those}, and adds ${cleared.length === 1 ? "it" : "them"} empty where it holds none.` : `Workspace env: ${cleared.join(", ")} will be sent EMPTY (--allow-empty-env). Whatever the target holds for ${those} is cleared.`,
4602
+ "workspace-env.compared-empty"
4603
+ );
4604
+ }
4605
+ if (unsupplied.length > 0 && r.merges === "`--keep-data`") {
4606
+ const one = unsupplied.length === 1;
4607
+ info(
4608
+ `Workspace env: ${unsupplied.join(", ")} ${one ? "has" : "have"} no value. A \`--keep-data\` merge keeps whatever the target holds for ${one ? "it" : "them"}, and adds ${one ? "it" : "them"} empty where it holds none.`
4609
+ );
4610
+ }
4611
+ if (unsupplied.length > 0 && !r.refuses && r.merges === void 0) {
4612
+ exportWarn(
4613
+ "workspace-env.unsupplied",
4614
+ r.comparesOnly === true ? `Workspace env: ${unsupplied.length === 1 ? `1 declared name is unsupplied (${unsupplied[0]})` : `${unsupplied.length} declared names are unsupplied (${unsupplied.join(", ")})`}, so this project's side of the comparison holds no value for ${unsupplied.length === 1 ? "it" : "them"}.` : r.cutsRelease === true ? `Workspace env: ${unsupplied.length === 1 ? `1 declared name is unsupplied (${unsupplied[0]})` : `${unsupplied.length} declared names are unsupplied (${unsupplied.join(", ")})`}. A release carries no env values, so this changes nothing it carries: set ${unsupplied.length === 1 ? "it" : "them"} on each destination it lands on with \`xanosdk env set\`.` : (unsupplied.length === 1 ? `Workspace env: 1 declared name is unsupplied (${unsupplied[0]}); this bundle will clear it if it is imported.` : `Workspace env: ${unsupplied.length} declared names are unsupplied (${unsupplied.join(", ")}); this bundle will clear them if it is imported.`) + ` Put the value${unsupplied.length === 1 ? "" : "s"} in \`${r.source ?? r.defaultLabel}\`, pass \`--env-var NAME=value\`, or \u2014 if empty is meant \u2014 \`--allow-empty-env=${unsupplied.join(",")}\`.`
4615
+ );
4616
+ }
4617
+ if (r.resolution.additions.length > 0) {
4618
+ const added = r.resolution.additions;
4619
+ exportWarn(
4620
+ "workspace-env.undeclared",
4621
+ `Workspace env: ${added.join(", ")} ${added.length === 1 ? "is" : "are"} not declared in \`workspaceConfig({ env })\` and ${r.comparesOnly === true ? `${added.length === 1 ? "is" : "are"} supplied only by this project's env values (a deploy would add ${added.length === 1 ? "it" : "them"})` : "will be ADDED"}. Declare the name there with an empty value so the stack's \`env()\` reads stay checkable; if this is a typo, this is the only place you will see it.`
4622
+ );
4623
+ }
4624
+ }
4625
+ function reportCapabilities(bundle) {
4626
+ const needs = bundleCapabilities(bundle);
4627
+ if (needs.length === 0) return;
4628
+ info(`This bundle needs ${needs.length} instance capabilit${needs.length === 1 ? "y" : "ies"}:`);
4629
+ for (const need of needs) {
4630
+ const where = need.objects.length ? ` (e.g. ${need.objects[0]}${need.objects.length > 1 ? ` +${need.objects.length - 1} more` : ""})` : "";
4631
+ detail(`${need.label} \u2014 ${need.effect}${where}`);
4632
+ }
4633
+ detail("Check these against the plan of anything you promote to; the deploy cannot.");
4634
+ }
4635
+ var strictFindings;
4636
+ var exportFindings = [];
4637
+ function countOf(n, noun) {
4638
+ return `${n} ${noun}${n === 1 ? "" : "s"}`;
4639
+ }
4640
+ function exportWarn(code, message, remedies = [], strict = true, machine) {
4641
+ const full = [message, ...remedies].join("\n");
4642
+ if (strict && strictFindings !== void 0) {
4643
+ strictFindings.push({ code, message: full });
4644
+ noteRunWarning(code, machine ?? full);
4645
+ } else {
4646
+ warn(message, code, remedies, machine);
4647
+ }
4648
+ exportFindings.push({ code, message: machine ?? full });
4649
+ }
4650
+ function failStrictFindings(args, library = []) {
4651
+ if (library.length > 0) throw strictRefusal(args, library);
4652
+ if (!args.strict || strictFindings === void 0 || strictFindings.length === 0) return;
4653
+ throw strictRefusal(args, []);
4654
+ }
4655
+ function strictRefusal(args, library) {
4656
+ const all = [];
4657
+ for (const d of [...library, ...takePendingStrictFindings()]) {
4658
+ if (!all.some((a) => a.code === d.code && a.message === d.message)) all.push(d);
4659
+ }
4660
+ const n = all.length;
4661
+ const hard = all.filter((d) => d.severity === "error").length;
4662
+ const why = hard === 0 ? "" : ` \u2014 ${countOf(hard, "error")}, and ${countOf(n - hard, "warning")} that --strict makes errors`;
4663
+ const remedy = hard === 0 ? `Resolve ${n === 1 ? "it" : "them"}, or run without --strict to proceed with ${n === 1 ? "it" : "them"}.` : "Resolve them.";
4664
+ return new DiagnosticError(
4665
+ `\`${commandLabel(args)}\` stopped: ${countOf(n, "finding")} ${n === 1 ? "fails" : "fail"} --strict${why}
4666
+ ` + // A finding's remedies are its later lines: each on its own line under it.
4667
+ all.map((d, i) => ` ${i + 1}. ${d.message.split("\n").join("\n ")}`).join("\n") + `
4668
+ ${remedy}`,
4669
+ all
4670
+ );
4671
+ }
4672
+ function quietly(fn) {
4673
+ if (fn === void 0) return void 0;
4674
+ const previous = setDiagnosticSink(() => {
4675
+ });
4676
+ try {
4677
+ return fn();
4678
+ } catch {
4679
+ return void 0;
4680
+ } finally {
4681
+ setDiagnosticSink(previous);
4682
+ }
4683
+ }
4684
+ function takePendingStrictFindings() {
4685
+ const pending = strictFindings ?? [];
4686
+ if (strictFindings !== void 0) strictFindings = [];
4687
+ return pending.map(({ code, message }) => ({ severity: "warning", code, message }));
4688
+ }
4689
+ function checkFilterNames(bundle) {
4690
+ for (const f of findUnresolvableFilters(bundle)) {
4691
+ const hint = f.suggestions.length ? ` \u2014 did you mean ${f.suggestions.map((s) => `\`${s}\``).join(" or ")}?` : "";
4692
+ exportWarn(
4693
+ "filter.unresolvable",
4694
+ `Filter "${f.name}" (in ${f.location}) is not engine-resolvable and will 500 at runtime${hint}`,
4695
+ [
4696
+ f.inExpression ? "Replace it with a resolvable name (see `fl.*` / llms.txt) where it is piped: the `filter()` inside the `obj()` member, or the `|name` in the `c.expression` source." : "Replace it with a resolvable name (see `fl.*` / llms.txt) or drop the raw `filter()` call."
4697
+ ]
4698
+ );
4699
+ }
4700
+ }
4701
+
4702
+ export {
4703
+ readsFreeName,
4704
+ authorFiles,
4705
+ resolveKnowledge,
4706
+ assertBundleInput,
4707
+ assertEntryFile,
4708
+ assertBundleFile,
4709
+ assertValueFiles,
4710
+ refuseValueFlagsBesideBundle,
4711
+ compileValueFlagKinds,
4712
+ DOC_TOKEN_REMEDY,
4713
+ refuseCompileValueFlags,
4714
+ loadBundleText,
4715
+ expandShortAttached,
4716
+ envNameRule,
4717
+ parseArgs,
4718
+ resolveHelpRequest,
4719
+ loadDefault,
4720
+ tsxRemedy,
4721
+ assertEntryExists,
4722
+ loadModule,
4723
+ readVersion,
4724
+ emitterFor,
4725
+ printHelp,
4726
+ orphanFixUps,
4727
+ composedChildren,
4728
+ setGuidFixUp,
4729
+ renameCandidatesFor,
4730
+ run,
4731
+ maskAssignments,
4732
+ carryRunWarnings,
4733
+ withoutSecretValue,
4734
+ isPathlessRun,
4735
+ globalVersionAsked,
4736
+ globalVersionMisuse,
4737
+ refreshAgentGuidance,
4738
+ nearestLockPath,
4739
+ missingLockDir,
4740
+ resolveLockPath,
4741
+ noteLockCreated,
4742
+ refreshRouteManifest,
4743
+ exportBundleJson,
4744
+ compileBundle,
4745
+ checkStandInTokens,
4746
+ noteRunScope,
4747
+ docTokenRefusalIfReplaced,
4748
+ envRefusalIfReplaced
4749
+ };
4750
+ //# sourceMappingURL=chunk-ETO6LGLD.js.map