@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,1371 @@
1
+ /**
2
+ * GENERATED by `npm run codegen:query-filters` — do not edit.
3
+ *
4
+ * `qf.*` — the filters a **db-query expression** resolves. They compile into the
5
+ * SQL statement the database runs, which is why they are a different registry
6
+ * from `fl.*` (the runtime value pipeline) and why a name from one does not
7
+ * resolve in the other.
8
+ *
9
+ * Reach them from a query's own expression surfaces — `eval`, `sort`, `where`:
10
+ *
11
+ * ```ts
12
+ * s.db.query({
13
+ * table: chunk,
14
+ * eval: [{ name: "embedding", as: "distance", filters: [qf.vector_cos_distance(inp("q"))] }],
15
+ * sort: [{ sortBy: "distance", dir: "asc" }], // nearest first
16
+ * })
17
+ * ```
18
+ *
19
+ * Each factory returns the same `{ name, arg }` step the raw form builds, so the
20
+ * emitted bytes are identical — what changes is that the name, the argument
21
+ * COUNT and (where the engine enumerates it) the argument's accepted spellings
22
+ * are checked where you write them instead of at request time.
23
+ *
24
+ * Signatures come from the engine's filter/aggregate classes, which enforce an
25
+ * exact argument count. Where a class and the YAML catalog disagree the class
26
+ * wins: the per-part timestamp extractors (`qf.epochms_month`, …) take a
27
+ * timezone the catalog does not mention, and `qf.round`'s precision is required.
28
+ */
29
+
30
+ /** A bare JS literal a query filter argument accepts in place of a {@link Value}. */
31
+ type Scalar = string | number | boolean;
32
+ /**
33
+ * One step of a query-expression pipeline — structurally the `DbEvalFilter` an
34
+ * `eval`/`sort`/`where` takes. The phantom name parameter keeps the emitted
35
+ * step traceable to the factory that built it.
36
+ */
37
+ interface QueryFilter<N extends string = string> {
38
+ readonly name: N;
39
+ readonly arg?: Value[];
40
+ }
41
+ /** Every name `qf` offers. */
42
+ declare const QUERY_FILTER_NAMES: readonly string[];
43
+ /**
44
+ * The subset that are AGGREGATES — computed by the database over a grouped
45
+ * result, so they belong in an aggregate query's `eval`/`group` and nowhere
46
+ * else.
47
+ */
48
+ declare const QUERY_AGGREGATE_NAMES: readonly string[];
49
+ /**
50
+ * The TypeScript type each name's declared result reads as — what an aggregate
51
+ * `eval`/`group` alias types to when this is its last step. A `json`
52
+ * result is absent (not statically known).
53
+ */
54
+ interface QueryFilterResults {
55
+ add: number;
56
+ array_length: number;
57
+ at_timezone: number;
58
+ avg: number;
59
+ between_filter: boolean;
60
+ ceil: number;
61
+ concat: string;
62
+ count: number;
63
+ count_distinct: number;
64
+ covers: boolean;
65
+ distance: number;
66
+ div: number;
67
+ epochms_add_day: number;
68
+ epochms_add_hour: number;
69
+ epochms_add_minute: number;
70
+ epochms_add_month: number;
71
+ epochms_add_sec: number;
72
+ epochms_add_year: number;
73
+ epochms_day: number;
74
+ epochms_dow: number;
75
+ epochms_doy: number;
76
+ epochms_epoch_day: number;
77
+ epochms_epoch_hour: number;
78
+ epochms_epoch_minute: number;
79
+ epochms_epoch_sec: number;
80
+ epochms_hour: number;
81
+ epochms_minute: number;
82
+ epochms_month: number;
83
+ epochms_sub_day: number;
84
+ epochms_sub_hour: number;
85
+ epochms_sub_minute: number;
86
+ epochms_sub_month: number;
87
+ epochms_sub_sec: number;
88
+ epochms_sub_year: number;
89
+ epochms_week: number;
90
+ epochms_year: number;
91
+ floor: number;
92
+ length: number;
93
+ lower: string;
94
+ max: number;
95
+ max_timestamp: number;
96
+ median: number;
97
+ min: number;
98
+ min_timestamp: number;
99
+ mul: number;
100
+ round: number;
101
+ search_rank: number;
102
+ sub: number;
103
+ substr: string;
104
+ sum: number;
105
+ time: number;
106
+ to_decimal: number;
107
+ to_int: number;
108
+ to_text: string;
109
+ to_timestamp: number;
110
+ unaccent: string;
111
+ upper: string;
112
+ vector_cos_distance: number;
113
+ vector_cos_similarity: number;
114
+ vector_hamming_distance: number;
115
+ vector_inner_product: number;
116
+ vector_jaccard_distance: number;
117
+ vector_l1_distance: number;
118
+ vector_l2_distance: number;
119
+ vector_negative_inner_product: number;
120
+ within: boolean;
121
+ }
122
+ /** The engine's declared shape for each name, for the manifest and the docs. */
123
+ declare const QUERY_FILTER_SPECS: Readonly<Record<string, {
124
+ kind: string;
125
+ args: {
126
+ name: string;
127
+ type: string;
128
+ enum?: readonly string[];
129
+ }[];
130
+ arity: number;
131
+ result?: string;
132
+ entry?: readonly string[];
133
+ }>>;
134
+ declare const qf: {
135
+ readonly add: (value: Scalar | Value) => QueryFilter<"add">;
136
+ readonly array_length: () => QueryFilter<"array_length">;
137
+ readonly at_timezone: (value: Scalar | Value) => QueryFilter<"at_timezone">;
138
+ readonly avg: () => QueryFilter<"avg">;
139
+ readonly between_filter: (left: Scalar | Value, right: Scalar | Value) => QueryFilter<"between_filter">;
140
+ readonly ceil: () => QueryFilter<"ceil">;
141
+ readonly coalesce: (value: Scalar | Value) => QueryFilter<"coalesce">;
142
+ readonly concat: (value: Scalar | Value) => QueryFilter<"concat">;
143
+ readonly count: () => QueryFilter<"count">;
144
+ readonly count_distinct: () => QueryFilter<"count_distinct">;
145
+ readonly covers: (point: Scalar | Value) => QueryFilter<"covers">;
146
+ readonly distance: (point: Scalar | Value) => QueryFilter<"distance">;
147
+ readonly div: (value: Scalar | Value) => QueryFilter<"div">;
148
+ readonly epochms_add_day: (amount: Scalar | Value) => QueryFilter<"epochms_add_day">;
149
+ readonly epochms_add_hour: (amount: Scalar | Value) => QueryFilter<"epochms_add_hour">;
150
+ readonly epochms_add_minute: (amount: Scalar | Value) => QueryFilter<"epochms_add_minute">;
151
+ readonly epochms_add_month: (amount: Scalar | Value) => QueryFilter<"epochms_add_month">;
152
+ readonly epochms_add_sec: (amount: Scalar | Value) => QueryFilter<"epochms_add_sec">;
153
+ readonly epochms_add_year: (amount: Scalar | Value) => QueryFilter<"epochms_add_year">;
154
+ readonly epochms_day: (timezone: Scalar | Value) => QueryFilter<"epochms_day">;
155
+ readonly epochms_dow: (timezone: Scalar | Value) => QueryFilter<"epochms_dow">;
156
+ readonly epochms_doy: (timezone: Scalar | Value) => QueryFilter<"epochms_doy">;
157
+ readonly epochms_epoch_day: () => QueryFilter<"epochms_epoch_day">;
158
+ readonly epochms_epoch_hour: () => QueryFilter<"epochms_epoch_hour">;
159
+ readonly epochms_epoch_minute: () => QueryFilter<"epochms_epoch_minute">;
160
+ readonly epochms_epoch_sec: () => QueryFilter<"epochms_epoch_sec">;
161
+ readonly epochms_hour: (timezone: Scalar | Value) => QueryFilter<"epochms_hour">;
162
+ readonly epochms_minute: (timezone: Scalar | Value) => QueryFilter<"epochms_minute">;
163
+ readonly epochms_month: (timezone: Scalar | Value) => QueryFilter<"epochms_month">;
164
+ readonly epochms_sub_day: (amount: Scalar | Value) => QueryFilter<"epochms_sub_day">;
165
+ readonly epochms_sub_hour: (amount: Scalar | Value) => QueryFilter<"epochms_sub_hour">;
166
+ readonly epochms_sub_minute: (amount: Scalar | Value) => QueryFilter<"epochms_sub_minute">;
167
+ readonly epochms_sub_month: (amount: Scalar | Value) => QueryFilter<"epochms_sub_month">;
168
+ readonly epochms_sub_sec: (amount: Scalar | Value) => QueryFilter<"epochms_sub_sec">;
169
+ readonly epochms_sub_year: (amount: Scalar | Value) => QueryFilter<"epochms_sub_year">;
170
+ readonly epochms_week: (timezone: Scalar | Value) => QueryFilter<"epochms_week">;
171
+ readonly epochms_year: (timezone: Scalar | Value) => QueryFilter<"epochms_year">;
172
+ readonly floor: () => QueryFilter<"floor">;
173
+ readonly length: () => QueryFilter<"length">;
174
+ readonly lower: () => QueryFilter<"lower">;
175
+ readonly max: () => QueryFilter<"max">;
176
+ readonly max_timestamp: () => QueryFilter<"max_timestamp">;
177
+ readonly median: () => QueryFilter<"median">;
178
+ readonly min: () => QueryFilter<"min">;
179
+ readonly min_timestamp: () => QueryFilter<"min_timestamp">;
180
+ readonly mul: (value: Scalar | Value) => QueryFilter<"mul">;
181
+ readonly round: (precision: Scalar | Value) => QueryFilter<"round">;
182
+ readonly search_rank: (q: Scalar | Value) => QueryFilter<"search_rank">;
183
+ readonly sub: (value: Scalar | Value) => QueryFilter<"sub">;
184
+ readonly substr: (start: Scalar | Value, length: Scalar | Value) => QueryFilter<"substr">;
185
+ readonly sum: () => QueryFilter<"sum">;
186
+ readonly time: (option: "century" | "day" | "decade" | "dow" | "doy" | "epoch" | "hour" | "isodow" | "isoyear" | "microseconds" | "millennium" | "milliseconds" | "minute" | "month" | "quarter" | "second" | "timezone" | "timezone_hour" | "timezone_minute" | "week" | "year" | Value) => QueryFilter<"time">;
187
+ readonly to_decimal: () => QueryFilter<"to_decimal">;
188
+ readonly to_distinct_list: () => QueryFilter<"to_distinct_list">;
189
+ readonly to_distinct_list_asc: () => QueryFilter<"to_distinct_list_asc">;
190
+ readonly to_distinct_list_desc: () => QueryFilter<"to_distinct_list_desc">;
191
+ readonly to_int: () => QueryFilter<"to_int">;
192
+ readonly to_list: () => QueryFilter<"to_list">;
193
+ readonly to_list_asc: () => QueryFilter<"to_list_asc">;
194
+ readonly to_list_desc: () => QueryFilter<"to_list_desc">;
195
+ readonly to_text: () => QueryFilter<"to_text">;
196
+ readonly to_timestamp: () => QueryFilter<"to_timestamp">;
197
+ readonly unaccent: () => QueryFilter<"unaccent">;
198
+ readonly upper: () => QueryFilter<"upper">;
199
+ readonly vector_cos_distance: (vector: Scalar | Value) => QueryFilter<"vector_cos_distance">;
200
+ readonly vector_cos_similarity: (vector: Scalar | Value) => QueryFilter<"vector_cos_similarity">;
201
+ readonly vector_hamming_distance: (vector: Scalar | Value) => QueryFilter<"vector_hamming_distance">;
202
+ readonly vector_inner_product: (vector: Scalar | Value) => QueryFilter<"vector_inner_product">;
203
+ readonly vector_jaccard_distance: (vector: Scalar | Value) => QueryFilter<"vector_jaccard_distance">;
204
+ readonly vector_l1_distance: (vector: Scalar | Value) => QueryFilter<"vector_l1_distance">;
205
+ readonly vector_l2_distance: (vector: Scalar | Value) => QueryFilter<"vector_l2_distance">;
206
+ readonly vector_negative_inner_product: (vector: Scalar | Value) => QueryFilter<"vector_negative_inner_product">;
207
+ readonly within: (point: Scalar | Value, radius: Scalar | Value) => QueryFilter<"within">;
208
+ };
209
+
210
+ /**
211
+ * The shared tagged-value primitive. Every place a function references
212
+ * data — input bindings, statement context, response — uses this `{value, tag,
213
+ * filters}` shape. Built and tested once here, reused everywhere.
214
+ */
215
+
216
+ /** A Xano SDK authored value is just the stored tagged-value shape. */
217
+ type Value = TaggedValue;
218
+ /**
219
+ * A {@link Value} that also carries, **at the type level only**, the name of the
220
+ * stack variable it references (`ref("user")` → `RefValue<"user">`). The `__ref`
221
+ * carrier is phantom — never present at runtime — and required (not optional) so
222
+ * `InferResponse`'s trace matches only real refs, never a plain `Value`.
223
+ * Because it is a subtype of `Value`, every existing `ref(...)` use — filter
224
+ * args, `db.query` `where`, response fields — keeps type-checking unchanged.
225
+ */
226
+ type RefValue<Name extends string = string> = Value & {
227
+ readonly __ref: Name;
228
+ };
229
+ /**
230
+ * An `auth(path)` read, carrying its path at the type level only (phantom
231
+ * `__auth`) so `InferResponse` types it from a query's auth table row.
232
+ */
233
+ type AuthValue<Path extends string = string> = Value & {
234
+ readonly __auth: Path;
235
+ };
236
+ /**
237
+ * A {@link Value} whose tag has no object-literal form, so `obj()` refuses it
238
+ * as a member — at the type level through this phantom `__notObjMember` carrier
239
+ * (never present at runtime), and at runtime by the tag. Bind it with
240
+ * `s.set_var` first and `ref()` the variable.
241
+ */
242
+ type NotObjMember<Tag extends string> = Value & {
243
+ readonly __notObjMember: Tag;
244
+ };
245
+ /**
246
+ * A `caught(path)` read, carrying its path at the type level only (phantom
247
+ * `__caught`) so `InferResponse` types it: `code`, `message` and `name` are
248
+ * strings, `result` is whatever payload was attached.
249
+ */
250
+ type CaughtValue<Path extends string = string> = NotObjMember<"trycatch"> & {
251
+ readonly __caught: Path;
252
+ };
253
+ /** What `caught(path)` reads, at the type level. */
254
+ type CaughtShape<Path extends string> = Path extends "code" | "message" | "name" ? string : Path extends "" ? {
255
+ code: string;
256
+ message: string;
257
+ name: string;
258
+ result: unknown;
259
+ } : unknown;
260
+ /**
261
+ * A {@link Value} that carries, at the type level only, the input it reads
262
+ * (`inp("email")` → `InpValue<"email">`), so `InferResponse` types it from the
263
+ * def's declared `input` instead of `unknown`. Phantom, like `__ref`.
264
+ */
265
+ type InpValue<Name extends string = string> = Value & {
266
+ readonly __inp: Name;
267
+ };
268
+ /**
269
+ * A {@link Value} that has had a filter chain attached (`withFilters(...)`).
270
+ * The `__filtered` carrier is phantom (type-only). A filter can reshape the
271
+ * value arbitrarily at runtime — turn an object into a scalar, add or drop keys
272
+ * — with no static signal, so `InferResponse` treats a filtered response value
273
+ * as `unknown` (the honest floor, matching how the Xano engine degrades a
274
+ * filtered result to `json`). Overriding via `responseShape` remains available.
275
+ */
276
+ type FilteredValue<Base = unknown, Chain extends readonly unknown[] = readonly unknown[]> = Value & {
277
+ readonly __filtered: true;
278
+ /** Phantom: the value the chain was applied to, so its type can be folded. */
279
+ readonly __base?: Base;
280
+ /** Phantom: the flattened filter chain, in application order. */
281
+ readonly __chain?: Chain;
282
+ };
283
+ /**
284
+ * A {@link Value} built by {@link c.regex} — a PCRE pattern the engine can
285
+ * actually run, delimiter-wrapped (`/…/flags`).
286
+ *
287
+ * The `__regex` carrier is phantom (type-only). It exists so a helper that takes
288
+ * a pattern can SAY so in its signature (`function match(p: RegexValue)`) and so
289
+ * an editor's hover distinguishes a pattern from the text beside it.
290
+ *
291
+ * It is deliberately NOT used to restrict `s.expect.to_match` or the `fl.regex_*`
292
+ * pattern slot. A nominal restriction there
293
+ * would have to reject `Value`, and `inp()`, `env()`, `auth()` and `sys.*` all
294
+ * return exactly `Value` — the same type `c.text` does — so it would reject every
295
+ * DYNAMIC pattern along with the broken constant ones. The enforcement is instead
296
+ * a build-time refusal that inspects the value it was actually given
297
+ * ({@link assertRegexPattern}), which fires on the bare constant and stays silent
298
+ * on a reference it cannot see through.
299
+ */
300
+ type RegexValue = Value & {
301
+ readonly __regex: true;
302
+ };
303
+ /** Flatten one level of `withFilters`'s spread-or-array argument list. */
304
+ type FlattenFilters<Fs extends readonly unknown[]> = Fs extends readonly [
305
+ infer Head,
306
+ ...infer Tail
307
+ ] ? Head extends readonly unknown[] ? [...Head, ...FlattenFilters<Tail>] : [Head, ...FlattenFilters<Tail>] : [];
308
+ /**
309
+ * A {@link Value} produced by {@link col} (or a filter chain built from one). The
310
+ * `__col` carrier is phantom (type-only). It exists so a `col()` reference can be
311
+ * *statically rejected* where it would silently fail at runtime: inside a
312
+ * `db.edit`/`db.add` `row`, `{tag:"col"}` does not resolve to the row's stored
313
+ * value — it evaluates to `null`, so a following `fl.add(1)` computes `null + 1`
314
+ * and the engine aborts ("Numbers are required for mathematical operations").
315
+ * `col()` is only meaningful in a `db.query` `where`/view expression.
316
+ */
317
+ type ColValue = Value & {
318
+ readonly __col: true;
319
+ };
320
+ /**
321
+ * The error branch surfaced when a tagged {@link Value} is nested inside a
322
+ * `c.obj`/`c.array` literal. The long message is the *property key*
323
+ * so TypeScript prints it verbatim in the "property … is missing" diagnostic; a
324
+ * `Value` has no such key, so intersecting it here makes the offending position
325
+ * fail to type-check. The runtime guard ({@link assertPlainJson}) carries the
326
+ * same guidance for JS/`any`-typed callers the type can't reach.
327
+ */
328
+ type TaggedValueNotAllowed = {
329
+ "❌ c.obj/c.array take plain JSON only — a tagged value (inp/ref/auth/col/c.*) can't be nested. For a computed object response use a record of values: `response: { key: value }` (not c.obj).": never;
330
+ };
331
+ /**
332
+ * Recursively reject any nested {@link Value} in a plain-JSON literal `T`. A
333
+ * member assignable to `Value` maps to {@link TaggedValueNotAllowed}; plain JSON
334
+ * (primitives, arrays, objects) passes through unchanged. Used intersected with
335
+ * a naked `T` (`o: T & RejectValues<T>`) so `T` stays inferrable while the
336
+ * rejection rides along. Structural `extends Value` detection — not a `JsonLiteral`
337
+ * constraint — so it survives a future `TaggedValue` interface→alias refactor.
338
+ */
339
+ type RejectValues<T> = T extends Value ? TaggedValueNotAllowed : T extends NotJson ? NotPlainJson : T extends readonly (infer E)[] ? readonly RejectValues<E>[] : T extends object ? {
340
+ [K in keyof T]: RejectValues<T[K]>;
341
+ } : T;
342
+ /**
343
+ * JS values `JSON.stringify` cannot carry faithfully: a function or symbol
344
+ * vanishes (or reads `null` in a list), a bigint throws, a `Date` becomes a
345
+ * string and a `Map`/`Set` becomes `{}`. Each is refused at the type level
346
+ * here and at runtime by {@link assertPlainJson}.
347
+ */
348
+ type NotJson = ((...args: never[]) => unknown) | bigint | symbol | Date | RegExp | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown> | WeakMap<object, unknown> | WeakSet<object> | Promise<unknown>;
349
+ /** `c.obj([…])` — a list handed to the record constructor. Printed verbatim, like {@link TaggedValueNotAllowed}. */
350
+ type ListNotAllowed = {
351
+ "❌ c.obj takes a { key: value } record — a list is c.array([ … ]).": never;
352
+ };
353
+ /** `c.obj`'s top-level rejection of a list; a record (or anything else) passes. */
354
+ type RejectList<T> = T extends readonly unknown[] ? ListNotAllowed : unknown;
355
+ /** The error branch for a {@link NotJson} member — printed verbatim, like {@link TaggedValueNotAllowed}. */
356
+ type NotPlainJson = {
357
+ "❌ c.obj/c.array take plain JSON only — no functions, Dates, Maps/Sets, class instances, bigint or symbol values. Convert first: a Date to date.toISOString(), a Map to Object.fromEntries(map).": never;
358
+ };
359
+ /**
360
+ * Tags {@link c.blank} can spell — the constant tags with no exact blank form of
361
+ * their own.
362
+ *
363
+ * Derived by exclusion from {@link TAGS} rather than listed, so a constant tag
364
+ * added to the catalog is blank-spellable without a second edit here. The two
365
+ * carve-outs are the tags that already round-trip a blank exactly: `const` via
366
+ * `c.text("")`, and `const:obj` via `c.obj(null)`.
367
+ *
368
+ * Reference tags are excluded by construction: a blank `var`/`input`/`col` is an
369
+ * unbound reference, not an empty value, and the two want different fixes.
370
+ */
371
+ type BlankTag = Exclude<Extract<Tag, `const${string}`>, "const" | "const:obj">;
372
+ /**
373
+ * Tags {@link c.null} can spell — the two the engine stores a `"null"` value
374
+ * under. `const:null` is the plain one; `const:obj` is the object-typed null a
375
+ * `db.*` statement's `@meta` slot carries.
376
+ *
377
+ * Listed rather than derived: a `"null"` value under any OTHER constant tag is
378
+ * unobserved, and inventing spellings for it would offer an authoring form for
379
+ * bytes no engine writes.
380
+ */
381
+ type NullTag = "const:null" | "const:obj";
382
+ /**
383
+ * A constant {@link Value} that also remembers the JavaScript type it resolves
384
+ * to at runtime.
385
+ *
386
+ * Phantom and optional, so a `ConstValue<T>` IS a `Value` everywhere one is
387
+ * expected and a plain `Value` is still assignable back — nothing about the
388
+ * encoding changes, and no existing call site moves. What it buys is one thing:
389
+ * `s.set_var("n", c.int(1))` can brand its binding, so a `ref("n")` in the
390
+ * response resolves to `number` instead of bottoming out at `unknown`.
391
+ *
392
+ * Deliberately NOT carried by every constructor. `c.blank()` is the editor's
393
+ * unconfigured value box and `c.expression()` is unparsed source — neither has a
394
+ * type anything here could honestly claim, so both stay bare and keep the
395
+ * `unknown` floor.
396
+ */
397
+ type ConstValue<T> = Value & {
398
+ readonly __const?: T;
399
+ };
400
+ /** Constant constructors. Values always serialize as strings (per fixture). */
401
+ declare const c: {
402
+ /**
403
+ * Plain string constant → `tag:"const"`.
404
+ *
405
+ * `null` is accepted alongside a string because the engine stores both: 47
406
+ * values in the sweep are a bare `const` holding `null` rather than `""`,
407
+ * mostly ignored statement-input entries the engine never reads. They are
408
+ * distinct bytes — `normalize` keeps them apart, unlike the `const:obj` blanks
409
+ * it does canonicalize — so a pull has to be able to spell the null form, and
410
+ * `c.text(null)` did not type-check.
411
+ *
412
+ * Write `c.text("")` for an empty string. The null form is here so a pulled
413
+ * workspace round-trips, not to be authored.
414
+ */
415
+ text<const S extends string | null>(s: S): ConstValue<S>;
416
+ /**
417
+ * Integer constant → `tag:"const:int"`, value stringified (e.g. `"123"`).
418
+ *
419
+ * Pass a **string** or `bigint` for an integer outside JavaScript's safe
420
+ * range: `c.int("9223372036854775807")` is exact, where the number literal
421
+ * for it silently rounds. The engine's integers are signed 64-bit and it
422
+ * clamps a value past that range with no error, so the export warns on one
423
+ * (`value.int-out-of-range`); the string form still stores the digits as
424
+ * written, which a pulled workspace relies on.
425
+ *
426
+ * A `number` that is not an integer, or is past `Number.MAX_SAFE_INTEGER`,
427
+ * **throws**: by the time such a literal reaches here its precision is already
428
+ * gone, so encoding it would write a value the caller did not type. The throw
429
+ * names the string form.
430
+ */
431
+ int(n: number | bigint | string): ConstValue<number>;
432
+ /**
433
+ * Decimal constant → `tag:"const:decimal"`.
434
+ *
435
+ * Pass a **string** to preserve a stored spelling a number literal cannot
436
+ * reproduce — `c.decimal("10.00")` keeps its trailing zeros, where
437
+ * `c.decimal(10)` writes `"10"`. The engine stores decimals as strings either
438
+ * way, so this is exactness rather than a workaround; prefer the number form
439
+ * whenever it reproduces the value you want.
440
+ */
441
+ decimal(n: number | string): ConstValue<number>;
442
+ /**
443
+ * The editor's **unconfigured value box** — a value cell added and never
444
+ * filled in, stored as `{value: "", tag}`.
445
+ *
446
+ * This is not a zero, an empty string, or an empty collection. The engine
447
+ * reads `""` and `"0"` differently, so `c.blank("const:int")` and `c.int(0)`
448
+ * are different stored values and the SDK will not canonicalize one into the
449
+ * other. It exists because 13 real values in the survey corpus are in this
450
+ * state and had no authoring form, so a pull emitted them as annotated
451
+ * literals with a warning attached — describing a workspace that was fine.
452
+ *
453
+ * Constant tags only. A blank `var` or `input` is an unbound REFERENCE, which
454
+ * is a different defect with a different fix, and is deliberately not
455
+ * spellable here. `const` and `const:obj` are excluded too: they already have
456
+ * exact blank forms in `c.text("")` and `c.obj(null)`, and a second spelling
457
+ * for the same bytes is how two constructors start disagreeing.
458
+ */
459
+ blank(tag: BlankTag): Value;
460
+ /** Boolean constant → `"true"`/`"false"` with `tag:"const:bool"`. */
461
+ bool<const B extends boolean>(b: B): ConstValue<B>;
462
+ /**
463
+ * Null constant → value `"null"` (per engine fixture).
464
+ *
465
+ * Bare `c.null()` is the plain `const:null`. Pass a tag for the **object-typed
466
+ * null** the engine writes into a `db.*` statement's `@meta` slot —
467
+ * `c.null("const:obj")` → `{tag:"const:obj", value:"null"}`, 16 of them across
468
+ * eight ordinary queries in the survey corpus, which had no spelling and came
469
+ * back as `rawValue`.
470
+ *
471
+ * ⚠ Not the same bytes as `c.obj(null)`, which is the BLANK object
472
+ * (`value: ""`). Both evaluate to null — the engine JSON-decodes the stored
473
+ * string and `""` and `"null"` both decode to it — but they are two stored
474
+ * spellings, and the SDK writes back the one it was given rather than
475
+ * re-pointing a pulled workspace at the other.
476
+ */
477
+ null(tag?: NullTag): ConstValue<null>;
478
+ /**
479
+ * Build a **regex pattern value** for the pattern-piped regex filters
480
+ * (`fl.regex_test`/`regex_match`/`regex_replace`/…). Xano runs PHP `preg_*`, so
481
+ * the pattern MUST be delimiter-wrapped — a bare `c.text("^…$")` is an invalid
482
+ * PCRE and the filter then matches *nothing* for every input, so a precondition
483
+ * built on it silently rejects all values. This wraps the raw
484
+ * pattern in `/…/`, escapes any interior `/`, and appends `flags`, so the result
485
+ * is always valid; `withFilters` rejects a bare `c.text` pattern and points here.
486
+ *
487
+ * Pass a JS `RegExp` (source + flags used directly, minus JS-only `g`/`y`/`d`):
488
+ * `c.regex(/^[^@\s]+@[^@\s]+\.[^@\s]+$/i)`, or a raw body + optional PCRE flags:
489
+ * `c.regex("^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$", "i")`. The pattern is the piped
490
+ * value; the filter's `subject` arg is the text tested against it.
491
+ */
492
+ regex(pattern: string | RegExp, flags?: string): RegexValue;
493
+ /**
494
+ * Current time as an **epoch-milliseconds** value — the engine's native
495
+ * `const:epochms` constant. Xano has no `$now` *setting*, so this lives on
496
+ * `c.*` (a current-time literal) rather than {@link sys} (which emits
497
+ * `setting("$…")` and would reference a dead `$now` var).
498
+ *
499
+ * Emits `{tag:"const:epochms", value:"now"}` — an UNFILTERED value, valid
500
+ * inline as a `where`/`cmp` operand. The equivalent `text("now") |to_epoch_ms`
501
+ * chain evaluates to the same epoch-ms number on a live engine, and both
502
+ * persist verbatim, but the native tag is what the editor writes and needs no
503
+ * filter to get there. Chain math onto it as usual:
504
+ * `withFilters(c.now(), fl.epochms_add_ms(c.int(-maxAgeMs)))`.
505
+ *
506
+ * Inside an `obj()` the tag is flattened into an expression string, where the
507
+ * identifier `now` alone is the STRING "now" — so `obj()` writes the
508
+ * `now|to_epochms` coercion that restores this tag's meaning. A `c.now()` used
509
+ * as a FILTER ARGUMENT there is refused: the coercion cannot be written in
510
+ * that position. Hoist it with `s.set_var` and `ref()` it.
511
+ */
512
+ now(): ConstValue<number>;
513
+ /**
514
+ * Object constant → JSON-string value with `tag:"const:obj"`. Takes **plain
515
+ * JSON literals only**: nesting a tagged value (`inp`/`ref`/`auth`/`c.*`) is a
516
+ * compile error and throws at runtime — it would serialize as internal
517
+ * representation the engine can't decode. For a computed/multi-key object
518
+ * response use a record of values (`response: { key: value }`), not `c.obj`.
519
+ *
520
+ * Called with no argument it is the **empty object**, `{}` — the same default
521
+ * the editor gives a new object variable, and the only empty form current
522
+ * editors write.
523
+ *
524
+ * Called with an explicit `null` it is the **blank** form (stored `value: ""`),
525
+ * which the engine evaluates to `null` rather than `{}` — it JSON-decodes the
526
+ * stored string, and decoding `""` yields null. That is a real difference in
527
+ * what the statement sees, so the two are separate spellings rather than one
528
+ * "empty object": `c.obj()` is `{}`, `c.obj(null)` is null.
529
+ *
530
+ * ⚠ **Prefer `c.obj()`.** The blank form is legacy — no current editor path
531
+ * writes it — and it exists here so a pulled workspace round-trips to the
532
+ * same bytes instead of being quietly re-pointed at `{}`.
533
+ *
534
+ * A **populated** object is stored the way the editor stores one: an empty
535
+ * `{}` base carrying one `set` filter per key. It is NOT a
536
+ * populated JSON string — that form fails the request at runtime, see
537
+ * {@link objSetFilters}.
538
+ *
539
+ * ⚠ **Zero-based numeric keys come back as a LIST**, not an object:
540
+ * `c.obj({ "0": "a" })` evaluates to `["a"]`. That is the engine's data model
541
+ * — a numeric key IS an index there, and the same object decoded from JSON
542
+ * anywhere else behaves identically — not something this encoding introduces.
543
+ * A non-zero-based numeric key (`{ "2": … }`) survives as a key. Live-verified.
544
+ * `export()` warns `value.obj-zero-based-numeric-keys` on the def that carries one.
545
+ */
546
+ obj<const T>(o?: (T & RejectValues<T> & RejectList<T>) | null): ConstValue<T>;
547
+ /**
548
+ * Array constant → JSON-string value with `tag:"const:array"`. Takes **plain
549
+ * JSON literals only** — like {@link obj}, a nested tagged value is a compile
550
+ * error and throws at runtime.
551
+ */
552
+ array<const T extends readonly unknown[]>(a: T & RejectValues<T>): ConstValue<T>;
553
+ /**
554
+ * A **Xano Expression Engine** expression, passed through verbatim →
555
+ * `tag:"const:expr2"`. The string IS the expression, exactly as it would be
556
+ * typed into the expression editor:
557
+ *
558
+ * c.expression('"Hello, " ~ $input.name')
559
+ * c.expression("$var.price * $var.qty")
560
+ * c.expression("{ id: $var.user.id, tier: $var.plan }")
561
+ *
562
+ * ⚠️ **THE STRING IS NOT VALIDATED.** Xano SDK does not parse it, does not
563
+ * type-check it, and cannot tell a working expression from a typo — the whole
564
+ * string is handed to the engine as-is. Nothing here participates in
565
+ * `InferResponse`, so a var referenced inside it is invisible to the type
566
+ * system, and a rename that updates every typed `ref()` will NOT update this.
567
+ * A malformed expression surfaces at RUNTIME, and one that is merely wrong
568
+ * (`$var.tota1`) surfaces as a wrong answer, not an error. Play at your own
569
+ * risk until validation exists.
570
+ *
571
+ * Prefer the typed surfaces whenever they cover the case: `ref`/`inp`/`col`
572
+ * for references, `withFilters(..., fl.*)` for transforms, {@link obj} for a
573
+ * dynamic object (it BUILDS a checked expression for you). Reach for this only
574
+ * for expression-engine syntax the typed surfaces cannot express — string
575
+ * concatenation with `~`, inline arithmetic, conditionals.
576
+ *
577
+ * NOT the `expr()` condition builder. `expr(col("id"), "=", inp("id"))` builds
578
+ * a comparison for a `where`; this builds a VALUE from raw expression source.
579
+ */
580
+ expression(source: string): Value;
581
+ /**
582
+ * The **older** expression form → `tag:"const:expr"`, kept because real
583
+ * workspaces still hold values stored that way and codegen has to bring them
584
+ * back as something readable. New code wants {@link expression}, which is what
585
+ * the expression editor writes today.
586
+ *
587
+ * ⚠️ Unvalidated passthrough, exactly like {@link expression} — see the
588
+ * warning there. This one additionally uses the older syntax generation, so an
589
+ * expression copied out of the current editor may not mean the same thing
590
+ * here.
591
+ */
592
+ expressionLegacy(source: string): Value;
593
+ };
594
+ /** Options for {@link ref}. */
595
+ interface RefOptions {
596
+ /**
597
+ * Null-safe nested access (opt-in). A dotted `ref("owner.user_id")` normally
598
+ * compiles to the raw var path `$owner.user_id`, which the engine resolves in
599
+ * a single lookup — so when the base var `owner` is null (e.g. a `db.get` that
600
+ * matched no row), it raises a runtime `ERROR_FATAL` "Unable to locate var"
601
+ * (HTTP 500) instead of yielding null.
602
+ *
603
+ * With `safe: true` the path compiles through the `get` filter
604
+ * (`$owner|get:"user_id"`), which walks the remaining path and resolves to
605
+ * null when the base is null — so an ownership/existence guard evaluates to
606
+ * `false` cleanly rather than throwing. Has no effect on a plain, dot-free name
607
+ * (a bare var already resolves to null without error).
608
+ */
609
+ safe?: boolean;
610
+ }
611
+ /**
612
+ * Reference a **stack variable** — the `as:` output of an earlier statement:
613
+ * `{tag:"var", value}`. e.g. `dbGet({ ..., as: "user" })` then `ref("user")`.
614
+ *
615
+ * Pass `{ safe: true }` to make a *nested* path null-safe: `ref("owner.user_id",
616
+ * { safe: true })` resolves to null instead of 500ing when the base `owner` is
617
+ * null — the intent-revealing opt-in for drilling into a `db.get`
618
+ * result that may not exist.
619
+ *
620
+ * Picking a reference helper (these are easy to mix up):
621
+ * - {@link ref} — a stack variable (`as:` output). **Not** a foreign key — that's
622
+ * the field constructor `f.tableRef`.
623
+ * - {@link inp} — an endpoint/function `input`.
624
+ * - {@link col} — a table column (in a `db.query` `where`/view comparison).
625
+ * - {@link auth} — the authenticated caller (`auth("id")`).
626
+ * - `c.*` — a literal constant (`c.int(1)`, `c.text("x")`).
627
+ */
628
+ declare function ref<const Name extends string>(name: Name, opts?: RefOptions): RefValue<Name>;
629
+ /**
630
+ * The second parameter every non-`ref` reference creator declares, so that
631
+ * passing `{ safe: true }` to one is a COMPILE error whose expected type is the
632
+ * explanation.
633
+ *
634
+ * `safe` was silently dropped before this: the creators took one parameter, so
635
+ * JavaScript discarded the extra argument and TypeScript never saw it. An
636
+ * author who wrote `inp("owner.id", { safe: true })` believed they had a
637
+ * null-safe drill and still got a 500 on a null base.
638
+ */
639
+ type SafeIsRefOnly = "`safe` is only valid on ref()";
640
+ /**
641
+ * Reference a function/endpoint **input**: `{tag:"input", value}`. See {@link ref} for the full picker.
642
+ * `inp("")` is the whole input object (`$input`).
643
+ */
644
+ declare function inp<const Name extends string>(name: Name, opts?: SafeIsRefOnly): InpValue<Name>;
645
+ /**
646
+ * Reference a table **column**: `{tag:"col", value}` (used in `db.query` `where` +
647
+ * table views). See {@link ref} for the full picker. The return is branded
648
+ * {@link ColValue} so it is a *compile error* to pass `col()` into a `db.edit`/
649
+ * `db.add` `row` — where it would resolve to `null` at runtime. Outside a
650
+ * `db.*` statement's where/sort/eval (a condition, a `set_var`, a response) the
651
+ * engine reads it as the column's NAME, so export refuses it there.
652
+ */
653
+ declare function col(name: string, opts?: SafeIsRefOnly): ColValue;
654
+ /**
655
+ * Reference the authenticated identity (`{tag:"auth", value}`). Pass a path to
656
+ * drill into the auth record — `auth("id")` is the authenticated row id
657
+ * (Xano's `$auth.id`); bare `auth()` is the whole record. Use it to bind the
658
+ * caller into a row write on an authenticated endpoint (one whose `auth` names
659
+ * an auth table), e.g.
660
+ * `s.db.add({ table: post, row: { author_id: auth("id") } })`.
661
+ */
662
+ declare function auth<const P extends string = "">(path?: P, opts?: SafeIsRefOnly): AuthValue<P>;
663
+ /**
664
+ * Reference the RESPONSE of the object under test (`{tag:"response", value}`) —
665
+ * the subject nearly every unit-test assertion is written against.
666
+ *
667
+ * Bare `resp()` is the whole response (stored as the literal `"response"`, which
668
+ * is what the editor writes); a path drills into it, `resp("id")` →
669
+ * `"response.id"`. A segment that is not a bare identifier takes the engine's
670
+ * bracket escape, so `resp("user-data")` → `response["user-data"]`.
671
+ *
672
+ * Meaningful only inside a `tests` entry's `expect` list. It is NOT a stack
673
+ * variable: a running stack has no response yet, which is why `ref` cannot
674
+ * spell this and why the engine gives it its own tag.
675
+ */
676
+ declare function resp(path?: string, opts?: SafeIsRefOnly): NotObjMember<"response">;
677
+ /**
678
+ * The four fields the engine binds in a `s.try_catch` catch arm. Read straight
679
+ * off the engine's own catch-variable map, which sets exactly these.
680
+ */
681
+ type CaughtField = "code" | "message" | "name" | "result";
682
+ /**
683
+ * Read the caught error inside a {@link s.try_catch} **catch** arm
684
+ * (`{tag:"trycatch", value}` — XanoScript's `$trycatch.*`).
685
+ *
686
+ * Only valid inside the catch arm; the engine binds these for that scope alone
687
+ * and they read empty anywhere else. The four fields are all the engine sets:
688
+ * - `name` — the error name/type (for a thrown error statement, its message)
689
+ * - `message` — the human-readable message (`"Throw Error Statement"` for a throw)
690
+ * - `code` — the mapped HTTP-ish error code
691
+ * - `result` — the error payload, when one was attached
692
+ *
693
+ * e.g. `s.try_catch({ try: [...], catch: [s.debug_log(caught("message"))] })`.
694
+ * Bare `caught()` is the whole error record.
695
+ */
696
+ declare function caught<const P extends CaughtField | "" = "">(path?: P, opts?: SafeIsRefOnly): CaughtValue<P>;
697
+ /**
698
+ * The toolset-scoped bindings, as the engine sets them.
699
+ *
700
+ * Both statements that populate the namespace write exactly two members —
701
+ * `token` (the calling URL's token, null when the call carried none) and
702
+ * `params` (the URL's parameters, an empty object when there were none). A
703
+ * dotted `params.<key>` reads one parameter: the lookup walks the stored map,
704
+ * so a path into `params` resolves the same way `ref("a.b")` does.
705
+ *
706
+ * Closed at the root deliberately — a name outside it resolves to empty rather
707
+ * than raising, so a typo would read as a silent null at runtime.
708
+ */
709
+ type ToolsetPath = "token" | "params" | `params.${string}`;
710
+ /**
711
+ * Read a **toolset-scoped binding** inside an agent/MCP tool
712
+ * (`{tag:"toolset", value}`) — the token and URL parameters the toolset was
713
+ * called with, alongside {@link ref}/{@link inp}/{@link env}/{@link auth}.
714
+ *
715
+ * - `toolset("token")` — the token on the calling URL, null when absent.
716
+ * - `toolset("params")` — the URL parameters as an object.
717
+ * - `toolset("params.tenant")` — one parameter out of that object.
718
+ *
719
+ * Only bound while a tool runs under its toolset; anywhere else it reads empty.
720
+ */
721
+ declare function toolset(path: ToolsetPath, opts?: SafeIsRefOnly): NotObjMember<"toolset">;
722
+ /**
723
+ * Read a **workspace environment variable** — the ones set via `workspaceConfig({ env })`
724
+ * or the workspace dashboard, e.g. `env("STRIPE_KEY")` → `$env.STRIPE_KEY`.
725
+ *
726
+ * Under the hood a workspace env var is a `{tag:"setting", value:"NAME"}` (the plain,
727
+ * non-`$` name) — `$env.NAME` in XanoScript is sugar for that setting. This is the SAME
728
+ * tag the built-in request/system vars use; those just carry a `$`-prefixed name
729
+ * (`$env.$remote_ip`). So `env("remote_ip")` reads a *user* var literally named
730
+ * `remote_ip` (usually unset → null), NOT the caller IP — use {@link sys} (`sys.remoteIp()`)
731
+ * or {@link setting} with the exact `$`-prefixed name for the built-ins.
732
+ *
733
+ * (`$env.NAME` is a setting, not the raw `tag:"env"` form — which does not resolve
734
+ * workspace vars — so this reads them as settings, matching the platform.)
735
+ */
736
+ declare function env(name: string, opts?: SafeIsRefOnly): Value;
737
+ /**
738
+ * Reference a workspace setting by raw name (`{tag:"setting", value}`). The built-in
739
+ * request/system variables are settings with a **`$`-prefixed** name — `setting("$remote_ip")`,
740
+ * `setting("$datasource")`, etc. Prefer the typed {@link sys} accessors, which spell the
741
+ * names for you and avoid the `$`-prefix footgun; drop to `setting()` only for a name `sys`
742
+ * doesn't cover.
743
+ */
744
+ declare function setting(name: string, opts?: SafeIsRefOnly): Value;
745
+ /**
746
+ * Built-in **system / request-context variables**. In XanoScript these are written
747
+ * `$env.$remote_ip`, `$env.$datasource`, … — note the second `$`: they are *settings*
748
+ * (`{tag:"setting", value:"$remote_ip"}`), distinct from the user-defined env vars that
749
+ * {@link env} reaches. Reaching for `env("remote_ip")` silently reads the wrong thing;
750
+ * these accessors emit the correct `setting("$…")` form so you never type the `$` prefix.
751
+ *
752
+ * The one that matters most: a **public** endpoint has no caller identity, so `auth("id")`
753
+ * does not resolve there — the
754
+ * request FAILS with a 403 rather than degrading to one shared bucket, so key a rate limit
755
+ * off {@link sys.remoteIp} instead —
756
+ * `withFilters(c.text("rl:apply:"), fl.concat(sys.remoteIp()))`.
757
+ *
758
+ * Mirrors the full workspace "environment" panel; every accessor returns a {@link Value}.
759
+ */
760
+ declare const sys: {
761
+ /** Client IP address (`$remote_ip`, text). Best public-endpoint rate-limit key. */
762
+ remoteIp: () => Value;
763
+ /** HTTP method of the request — `GET`, `POST`, … (`$request_method`, text). */
764
+ requestMethod: () => Value;
765
+ /** Full request URI/path (`$request_uri`, text). */
766
+ requestUri: () => Value;
767
+ /** Raw query-string portion of the URL (`$request_querystring`, text). */
768
+ requestQueryString: () => Value;
769
+ /** Request headers as an object/map (`$http_headers`, object). */
770
+ /**
771
+ * The request's headers, keyed Title-Cased whatever the client sent — a
772
+ * client's `x-sync-secret` is read as `X-Sync-Secret`, so read that spelling.
773
+ * `s.api.call` sends header names the same way.
774
+ */
775
+ httpHeaders: () => Value;
776
+ /** The caller's `Authorization` bearer token, if present (`$request_auth_token`, text). */
777
+ requestAuthToken: () => Value;
778
+ /** API base URL for the request (`$api_baseurl`, text). */
779
+ apiBaseUrl: () => Value;
780
+ /** Active data source name — e.g. `live` or a branch source (`$datasource`, text). */
781
+ datasource: () => Value;
782
+ /** Active branch name (`$branch`, text). */
783
+ branch: () => Value;
784
+ /** Tenant identifier for multi-tenant instances (`$tenant`, text). */
785
+ tenant: () => Value;
786
+ /** Current release number (`$release`, int). */
787
+ release: () => Value;
788
+ /** Platform identifier (`$platform`, int). */
789
+ platform: () => Value;
790
+ /** `true` when the request is running under the debugger (`$debugger`, bool). */
791
+ isDebugger: () => Value;
792
+ };
793
+ /**
794
+ * Reference a column of the **parent statement's output row** (`{tag:"output",
795
+ * value}`) — the `$output.<col>` reference an addon input binds to. Only
796
+ * meaningful inside an addon spec's `input` map (see `s.db.query`'s `addon`
797
+ * arg), where the engine resolves it against each row the parent query returns,
798
+ * e.g. `addon: [{ addon: transactions, as: "items._txns",
799
+ * input: { user_id: out("id") } }]`.
800
+ */
801
+ declare function out(name: string, opts?: SafeIsRefOnly): NotObjMember<"output">;
802
+ /**
803
+ * Build a `mvp_filter` chain entry: `{name, disabled:false, arg}`.
804
+ *
805
+ * Generic in the name so a literal call carries it at the type level
806
+ * (`filter("upper")` is a `FilterXdo<"upper">`), which is what lets a chain's
807
+ * result type be folded. A `string` name — the escape-hatch spelling, and what a
808
+ * decoded workspace passes — widens to `FilterXdo<string>` and folds to
809
+ * `unknown`, exactly as before.
810
+ */
811
+ declare function filter<const N extends string>(name: N, ...args: (Value | undefined)[]): FilterXdo<N>;
812
+ /**
813
+ * One chain member {@link withFilters} takes: an `fl.*` filter, or a `qf.*`
814
+ * step for an operand a db query compiles to SQL — `where: expr(col("at"), ">",
815
+ * withFilters(c.now(), qf.epochms_sub_day(7)))`. A `qf` step carries no
816
+ * `disabled`, and a zero-argument one no `arg`; it is appended as it came, the
817
+ * bytes a query's `eval` stores for the same step.
818
+ */
819
+ type ChainFilter = FilterXdo | QueryFilter;
820
+ /**
821
+ * Attach a filter chain to a value, returning a new value. Pass filters spread
822
+ * (the canonical form, `withFilters(v, fl.trim(), fl.lower())`); the array form
823
+ * (`withFilters(v, [fl.trim(), fl.lower()])`) is also accepted — both are flattened.
824
+ * A db-query operand also takes `qf.*` steps (see {@link ChainFilter}).
825
+ */
826
+ declare function withFilters<V extends Value, const Fs extends readonly (ChainFilter | ChainFilter[])[]>(value: V, ...filters: Fs): FilteredValue<V, FlattenFilters<Fs>> & (V extends ColValue ? {
827
+ readonly __col: true;
828
+ } : unknown);
829
+
830
+ /**
831
+ * Unit-test ASSERTIONS — the `expect[]` list on a saved `test`.
832
+ *
833
+ * ## Not to be confused with `s.expect.*`
834
+ *
835
+ * Xano overloads the word, and so does this SDK, because both surfaces are
836
+ * really called `expect` in the product:
837
+ *
838
+ * - `expect.*` (this module) builds a `{type, vars[]}` **assertion record**
839
+ * stored on a `tests` entry of a query/function/middleware. It is data, not a
840
+ * step, and it only ever appears inside `tests: [{ expect: [...] }]`.
841
+ * - `s.expect.*` builds an assertion **statement** that runs inside a
842
+ * `workflowTest()` stack. It is a stack item like any other.
843
+ *
844
+ * They are not interchangeable and the type system enforces it: these return
845
+ * {@link TestExpect}, those return `Statement`.
846
+ *
847
+ * ## The subject comes first
848
+ *
849
+ * Every matcher takes its subject as the first argument — almost always
850
+ * {@link resp}. Argument ORDER is the assertion's meaning:
851
+ * `expect.to_contain(resp("tags"), c.text("new"))` asserts the response's tags
852
+ * contain `"new"`, not the reverse.
853
+ */
854
+
855
+ /** The stored matcher names, in the engine's own order. */
856
+ declare const TEST_EXPECT_TYPES: readonly ["to_be_defined", "to_be_empty", "to_be_false", "to_be_greater_than", "to_be_in_the_future", "to_be_in_the_past", "to_be_less_than", "to_be_null", "to_be_true", "to_be_within", "to_contain", "to_end_with", "to_equal", "to_match", "to_not_be_defined", "to_not_be_null", "to_not_equal", "to_start_with", "to_throw"];
857
+ /** One of the 19 stored matcher names. */
858
+ type TestExpectType = (typeof TEST_EXPECT_TYPES)[number];
859
+ /** A stored assertion — `{type, vars[]}`, the `mvp_test_expect` shape. */
860
+ interface TestExpect {
861
+ type: TestExpectType;
862
+ vars: Value[];
863
+ }
864
+ /**
865
+ * Unit-test assertions, for the `expect` list of a `tests` entry.
866
+ *
867
+ * See the module header for why this is NOT `s.expect.*`.
868
+ *
869
+ * ```ts
870
+ * query({
871
+ * name: "score",
872
+ * verb: "POST",
873
+ * input: { score: input.int() },
874
+ * tests: [
875
+ * {
876
+ * name: "adds one",
877
+ * input: { score: c.int(1) },
878
+ * expect: [expect.to_equal(resp(), c.int(2))],
879
+ * },
880
+ * ],
881
+ * stack: [s.set_var("x1", c.expression("$input.score + 1"))],
882
+ * response: ref("x1"),
883
+ * });
884
+ * ```
885
+ */
886
+ declare const expect: {
887
+ /** The subject is set (not undefined). */
888
+ readonly to_be_defined: (subject: Value) => TestExpect;
889
+ /** The subject is undefined. */
890
+ readonly to_not_be_defined: (subject: Value) => TestExpect;
891
+ /** The subject is empty — `""`, `[]`, `{}`, `0`, or null. */
892
+ readonly to_be_empty: (subject: Value) => TestExpect;
893
+ /** The subject is `null`. */
894
+ readonly to_be_null: (subject: Value) => TestExpect;
895
+ /** The subject is not `null`. */
896
+ readonly to_not_be_null: (subject: Value) => TestExpect;
897
+ /** The subject is boolean true. */
898
+ readonly to_be_true: (subject: Value) => TestExpect;
899
+ /** The subject is boolean false. */
900
+ readonly to_be_false: (subject: Value) => TestExpect;
901
+ /** The subject is a timestamp later than now. */
902
+ readonly to_be_in_the_future: (subject: Value) => TestExpect;
903
+ /** The subject is a timestamp earlier than now. */
904
+ readonly to_be_in_the_past: (subject: Value) => TestExpect;
905
+ /** `subject === value`. */
906
+ readonly to_equal: (subject: Value, value: Value) => TestExpect;
907
+ /** `subject !== value`. */
908
+ readonly to_not_equal: (subject: Value, value: Value) => TestExpect;
909
+ /** `subject > value`, both read as numbers. */
910
+ readonly to_be_greater_than: (subject: Value, value: Value) => TestExpect;
911
+ /** `subject < value`, both read as numbers. */
912
+ readonly to_be_less_than: (subject: Value, value: Value) => TestExpect;
913
+ /** A list subject contains the item; a text subject contains the substring. */
914
+ readonly to_contain: (subject: Value, item: Value) => TestExpect;
915
+ /** The subject, as text, starts with `prefix`. */
916
+ readonly to_start_with: (subject: Value, prefix: Value) => TestExpect;
917
+ /** The subject, as text, ends with `suffix`. */
918
+ readonly to_end_with: (subject: Value, suffix: Value) => TestExpect;
919
+ /**
920
+ * The subject matches a regular expression. `pattern` is a PCRE pattern
921
+ * INCLUDING its delimiters — build it with `c.regex(...)` rather than by hand;
922
+ * a bare `"^a"` is not a runnable pattern and the engine's match silently
923
+ * fails rather than erroring.
924
+ */
925
+ readonly to_match: (subject: Value, pattern: Value) => TestExpect;
926
+ /**
927
+ * `min < subject < max`, both bounds EXCLUSIVE and all three read as numbers.
928
+ * A subject equal to either bound fails.
929
+ */
930
+ readonly to_be_within: (subject: Value, min: Value, max: Value) => TestExpect;
931
+ /**
932
+ * The run raised an error. Pass `exception` to require that text to appear in
933
+ * the error message (a case-insensitive substring, not an exact match);
934
+ * omit it to accept ANY error.
935
+ *
936
+ * Unlike every other matcher this one takes no subject: the thing under
937
+ * assertion is the run's failure, and the engine stores the response slot as
938
+ * a fixed first var. That is what the editor writes, and it is preserved so
939
+ * an authored test and a pulled one are the same bytes.
940
+ */
941
+ readonly to_throw: (exception?: Value) => TestExpect;
942
+ };
943
+
944
+ /**
945
+ * The lean statement-input entry — `{name, tag, value, filters}` — shared by
946
+ * every call site that emits the *lean* input form (no rich
947
+ * `ignore`/`expand`/`children`):
948
+ *
949
+ * - addon `input[]` bindings ({@link ../statements/special/addon-encode.ts}),
950
+ * - the lean db family (`db.add_or_edit` / the bulk ops in
951
+ * {@link ../statements/special/db.ts}),
952
+ * - lean spec-driven statements ({@link ../statements/schema-dsl/interpret.ts}).
953
+ *
954
+ * One builder so the shape lives in exactly one place. (JSON key order is not
955
+ * significant to the engine parser, which reads by field name.)
956
+ */
957
+
958
+ /** A lean input binding — `{name, tag, value, filters}`, no `ignore/expand/children`. */
959
+ interface LeanInput {
960
+ name: string;
961
+ tag: string;
962
+ value: string;
963
+ filters: unknown[];
964
+ }
965
+
966
+ interface TestDef {
967
+ /**
968
+ * The test's display name, unique within the object. It is also the key a
969
+ * statement's `mock` map uses to name this test, which is why a duplicate is
970
+ * refused rather than merged.
971
+ */
972
+ name: string;
973
+ /**
974
+ * Explicit stored `id` (this test's identity). Defaults to one derived from
975
+ * the owning object and the test name; set it to keep identity across a
976
+ * rename. A pulled test always carries the id Xano minted for it.
977
+ */
978
+ id?: string;
979
+ description?: string;
980
+ /**
981
+ * Datasource to run against. `""` (the default) means an EMPTY datasource —
982
+ * the recommended default for isolated runs. Any other value names a datasource
983
+ * the engine **clones** before the test runs; `"live"` warns at encode time to
984
+ * prevent cloning large production databases, but in ephemeral test environments
985
+ * `datasource: "live"` is safe and allows running tests against `table({ seed })` rows.
986
+ */
987
+ datasource?: string;
988
+ /**
989
+ * The inputs to call the object with, by input name — the same tagged values
990
+ * used everywhere else (`c.*`, `ref`, …), not plain JS scalars.
991
+ */
992
+ input?: Record<string, Value>;
993
+ /**
994
+ * The assertions, built with the top-level `expect.*` helpers — NOT
995
+ * `s.expect.*`, which builds workflow-test statements. See
996
+ * {@link ../values/expect.js}.
997
+ */
998
+ expect?: TestExpect[];
999
+ /**
1000
+ * An auth token to run the test as an authenticated caller.
1001
+ *
1002
+ * Accepted so an authored test can supply one, but note that a pull does NOT
1003
+ * bring it back: a token is an expiring credential rather than authored
1004
+ * configuration, so `codegen` reports a stored one as a deliberate omission
1005
+ * instead of writing it into a committed tree.
1006
+ */
1007
+ token?: string;
1008
+ }
1009
+ /** The stored `mvp_test` shape. */
1010
+ interface TestXdo {
1011
+ datasource: string;
1012
+ description: string;
1013
+ expect: TestExpect[];
1014
+ id: string;
1015
+ input: LeanInput[];
1016
+ name: string;
1017
+ /**
1018
+ * Always emitted, blank when unset. The stored schema marks it optional, but a
1019
+ * live round trip shows the engine persists `""` regardless — omitting it read
1020
+ * as a failed round trip on every test.
1021
+ */
1022
+ token: string;
1023
+ }
1024
+ /**
1025
+ * Declare a saved unit test. Sugar for a plain object literal — use it for the
1026
+ * inferred type and the doc hover; `tests: [{ … }]` is equally valid.
1027
+ */
1028
+ declare function test(def: TestDef): TestDef;
1029
+
1030
+ /**
1031
+ * TypeScript mirror of Xano's stored `mvp_function` JSON contract (the
1032
+ * importable `xdo` subset, flattened — no `xdo` wrapper).
1033
+ *
1034
+ * Field shapes are taken from the real Xano engine's persisted function shape.
1035
+ *
1036
+ * The SDK emits only authored fields. Server/auto-generated keys (`id`,
1037
+ * `created_at`, `_xsid`, `@guid`, `@index`, `guid`, `_draft`, `stack_id`, …)
1038
+ * are generated by the engine on import and are NEVER emitted here; the test
1039
+ * normalizer strips them from the fixture before comparison.
1040
+ */
1041
+ /**
1042
+ * Xano tagged-value tags (verified against the Xano engine). The runtime
1043
+ * `TAGS` tuple is the single source of truth; the `Tag` type is derived from it
1044
+ * so the manifest can enumerate the tag catalog without drifting from the type.
1045
+ */
1046
+
1047
+ declare const TAGS: readonly ["const", "const:int", "const:decimal", "const:bool", "const:array", "const:obj", "const:null", "const:epochms", "const:expr", "const:expr2", "const:encoded", "var", "input", "auth", "env", "setting", "col", "output", "response", "trycatch", "toolset"];
1048
+ type Tag = (typeof TAGS)[number];
1049
+ /**
1050
+ * A filter in a `mvp_filter` chain: `{name, disabled, arg}`.
1051
+ *
1052
+ * `N` is a **phantom** carrier for the filter's name, set by the `fl.*` factories
1053
+ * (`fl.upper()` is a `FilterXdo<"upper">`) and never present at runtime — `name`
1054
+ * already holds it. It exists so a chain's RESULT type can be folded statically:
1055
+ * knowing a chain is `["trim", "upper"]` rather than `string[]` is what lets
1056
+ * `withFilters`/`asFilters` report `string` instead of `unknown`.
1057
+ *
1058
+ * It defaults to `string`, so every existing `FilterXdo` position — stored
1059
+ * envelopes, decoder output, the `filter()` escape hatch — keeps working
1060
+ * unchanged and simply folds to `unknown`, the honest floor for a chain whose
1061
+ * names are not statically known.
1062
+ */
1063
+ interface FilterXdo<N extends string = string> {
1064
+ name: string;
1065
+ /**
1066
+ * Whether the engine skips this filter. OPTIONAL because the engine stores it
1067
+ * both ways: `filter()` and every `fl.*` constructor write it, but a filter
1068
+ * persisted by an older editor may carry no `disabled` key at all.
1069
+ *
1070
+ * Required here until now, which made a pulled workspace fail its own
1071
+ * type-check: codegen emits a stored filter verbatim when no `fl.*` form
1072
+ * reproduces it, and a verbatim emit of a filter stored without the key does
1073
+ * not have it. Writing `disabled: false` in would have been the
1074
+ * other repair, and it is the wrong one — it ADDS a key the engine did not
1075
+ * store, so the re-encode would no longer match the stored bytes and the value
1076
+ * would degrade further rather than round-trip.
1077
+ *
1078
+ * Read it as `filter.disabled ?? false`.
1079
+ */
1080
+ disabled?: boolean;
1081
+ arg: TaggedValue[];
1082
+ /** Phantom: the filter's name at the type level. Never present at runtime. */
1083
+ readonly __filter?: N;
1084
+ }
1085
+ /** The core tagged value: `{value, tag, filters}`. Values serialize as strings. */
1086
+ interface TaggedValue {
1087
+ value: string;
1088
+ tag: Tag;
1089
+ filters: FilterXdo[];
1090
+ }
1091
+ /**
1092
+ * An input/column "method" (e.g. `trim`, or `min:8`). `arg` holds the filter's
1093
+ * literal arguments as scalars (`["8"]`); the persisted corpus is numeric/string
1094
+ * inconsistent on them (`[8]` vs `["10"]`), the same artifact class as
1095
+ * `const:int` tagged values — the normalizer coerces both to strings.
1096
+ */
1097
+ interface MethodXdo {
1098
+ name: string;
1099
+ disabled: boolean;
1100
+ arg: Array<string | number>;
1101
+ }
1102
+ /**
1103
+ * A field-bearing entry — the shape shared by function/query inputs and table
1104
+ * columns. In the persisted form the two are byte-identical: both use
1105
+ * `customize:{}`, numeric `market_item` ids, an `_xsid` placeholder, and a
1106
+ * present `description`. (The older parser generation emitted `customize:""` /
1107
+ * string ids for inputs; the live `mvp_query`/`mvp_dbo` rows show they converge.)
1108
+ */
1109
+ /**
1110
+ * A field's array length bounds, as PERSISTED.
1111
+ *
1112
+ * Both members are `json`-typed in the engine rather than numeric — the editor
1113
+ * declares them that way and every consumer reads them through a coercion
1114
+ * (`+list.max`) — so a set bound arrives as `5` or as `"5"`, and an UNSET one as
1115
+ * whichever empty the editor serialized: `""` on 8,814 fields in the sweep, `{}`
1116
+ * on two. All four spellings are real bytes, so the type admits them rather than
1117
+ * asserting a tidiness the engine does not have.
1118
+ */
1119
+ type ListBoundsXdo = {
1120
+ min?: string | number | Record<string, never>;
1121
+ max?: string | number | Record<string, never>;
1122
+ };
1123
+ interface FieldXdo {
1124
+ name: string;
1125
+ type: string;
1126
+ _xsid: string;
1127
+ description?: string;
1128
+ nullable: boolean;
1129
+ /**
1130
+ * Absent for types that persist no default (`uuid`) — the engine drops the
1131
+ * key rather than storing it empty, and the two are different stored bytes.
1132
+ */
1133
+ default?: string;
1134
+ merge: boolean;
1135
+ hidden: unknown[];
1136
+ override: unknown[];
1137
+ customize: string | Record<string, unknown>;
1138
+ required: boolean;
1139
+ values: unknown[];
1140
+ mode: string;
1141
+ format: string;
1142
+ sensitive: boolean;
1143
+ list: ListBoundsXdo;
1144
+ vector: {
1145
+ size: number;
1146
+ };
1147
+ access: string;
1148
+ style: {
1149
+ type: string;
1150
+ };
1151
+ children: unknown[];
1152
+ methods: MethodXdo[];
1153
+ market_item: {
1154
+ id: string | number;
1155
+ version: string | number;
1156
+ guid: string;
1157
+ };
1158
+ is_settings_registry: boolean;
1159
+ }
1160
+ /**
1161
+ * A single function/query input (`input[]` entry). Shares the persisted field
1162
+ * shape with table columns ({@link FieldXdo}) — `customize:{}`, numeric
1163
+ * `market_item` ids, `_xsid` present.
1164
+ */
1165
+ interface InputXdo {
1166
+ name: string;
1167
+ type: string;
1168
+ _xsid: string;
1169
+ description: string;
1170
+ nullable: boolean;
1171
+ /** `null` on the one input the platform stores a null default for: an MCP trigger's `auth`. */
1172
+ default: string | null;
1173
+ merge: boolean;
1174
+ hidden: unknown[];
1175
+ override: unknown[];
1176
+ customize: string | Record<string, unknown>;
1177
+ required: boolean;
1178
+ values: unknown[];
1179
+ mode: string;
1180
+ format: string;
1181
+ sensitive: boolean;
1182
+ list: ListBoundsXdo;
1183
+ vector: {
1184
+ size: number;
1185
+ };
1186
+ access: string;
1187
+ style: {
1188
+ type: string;
1189
+ };
1190
+ children: unknown[];
1191
+ methods: MethodXdo[];
1192
+ market_item: {
1193
+ id: string | number;
1194
+ version: string | number;
1195
+ guid: string;
1196
+ };
1197
+ is_settings_registry: boolean;
1198
+ }
1199
+ /** A response item (`result[]` entry). The persisted form always carries `_xsid` and `disabled`. */
1200
+ interface ResultItemXdo {
1201
+ filters: FilterXdo[];
1202
+ name: string;
1203
+ tag: Tag;
1204
+ value: string;
1205
+ _xsid: string;
1206
+ disabled: boolean;
1207
+ }
1208
+ /**
1209
+ * A stack statement (`run[]` entry). The persisted form is a **uniform** 12-key
1210
+ * envelope, identical across every statement type (confirmed against live
1211
+ * `mvp_query`/`mvp_tool`): every member is always present, with empty defaults.
1212
+ * `context` varies per statement (set_var carries a TaggedValue; conditional
1213
+ * carries nested runs — see below).
1214
+ */
1215
+ interface StackItemXdo {
1216
+ as: string;
1217
+ name: string;
1218
+ _xsid: string;
1219
+ addon: unknown[];
1220
+ input: unknown[];
1221
+ mocks: unknown;
1222
+ output: unknown;
1223
+ context: unknown;
1224
+ runtime: unknown;
1225
+ disabled: boolean;
1226
+ description: string;
1227
+ settings_registry: unknown[] | null;
1228
+ }
1229
+ /**
1230
+ * A statement `input[]` argument binding — a named tagged value, distinct from
1231
+ * the rich `InputXdo` field shape. Lean form is `{name,value,tag,filters}`;
1232
+ * "full" statements (api_request, db ops, file ops) add `ignore/expand/children`.
1233
+ */
1234
+ interface StatementInputXdo {
1235
+ name: string;
1236
+ value: string;
1237
+ tag: Tag;
1238
+ filters: FilterXdo[];
1239
+ ignore?: boolean;
1240
+ expand?: boolean;
1241
+ children?: unknown[];
1242
+ }
1243
+ /** A single binary comparison operand inside a conditional expression. */
1244
+ interface ExprOperand {
1245
+ operand: string;
1246
+ tag: Tag;
1247
+ filters: FilterXdo[];
1248
+ ignore_empty?: boolean;
1249
+ }
1250
+ /** One `statement`-type entry in a conditional's `expr.expression[]`. */
1251
+ interface ExprStatement {
1252
+ type: "statement";
1253
+ or: boolean;
1254
+ group: {
1255
+ expression: unknown[];
1256
+ };
1257
+ statement: {
1258
+ op: string;
1259
+ left: ExprOperand;
1260
+ right: ExprOperand;
1261
+ };
1262
+ }
1263
+ /** A `{type:"group"}` entry — a nested AND/OR subtree of expression nodes. */
1264
+ interface ExprGroup {
1265
+ type: "group";
1266
+ or: boolean;
1267
+ group: {
1268
+ expression: ExprNode[];
1269
+ };
1270
+ }
1271
+ /** One node in an expression tree: a comparison statement or a nested group. */
1272
+ type ExprNode = ExprStatement | ExprGroup;
1273
+ /** `context` for a `mvp:conditional` statement. */
1274
+ interface ConditionalContext {
1275
+ expr: {
1276
+ expression: ExprNode[];
1277
+ };
1278
+ if: {
1279
+ run: StackItemXdo[];
1280
+ };
1281
+ /**
1282
+ * The elif stack — a `run[]` of `mvp:conditional_elif` statements, each its own
1283
+ * `{ expr, if:{run} }` branch (mirrors how `mvp:switch` stacks `switch_case`).
1284
+ * The engine always persists this key, `{run:[]}` when there are no elif
1285
+ * branches (verified against a live conditional capture).
1286
+ */
1287
+ elif: {
1288
+ run: StackItemXdo[];
1289
+ };
1290
+ else: {
1291
+ run: StackItemXdo[];
1292
+ };
1293
+ }
1294
+ /** `context` for a `mvp:conditional_elif` statement — one leaf branch of a conditional's elif stack. */
1295
+ interface ConditionalElifContext {
1296
+ expr: {
1297
+ expression: ExprNode[];
1298
+ };
1299
+ if: {
1300
+ run: StackItemXdo[];
1301
+ };
1302
+ }
1303
+ interface CacheXdo {
1304
+ active: boolean;
1305
+ ttl: number;
1306
+ input: boolean;
1307
+ auth: boolean;
1308
+ datasource: boolean;
1309
+ ip: boolean;
1310
+ headers: unknown[];
1311
+ env: unknown[];
1312
+ }
1313
+ interface HistoryXdo {
1314
+ inherit: boolean;
1315
+ enabled: boolean;
1316
+ limit: number;
1317
+ }
1318
+ interface MiddlewareXdo {
1319
+ pre_customize: boolean;
1320
+ post_customize: boolean;
1321
+ pre: unknown[];
1322
+ post: unknown[];
1323
+ }
1324
+ /** The flattened authored function envelope the SDK emits. */
1325
+ interface FunctionXdo {
1326
+ name: string;
1327
+ description: string;
1328
+ docs: string;
1329
+ workspace: {
1330
+ id: number;
1331
+ };
1332
+ branch: {
1333
+ id: number;
1334
+ };
1335
+ cache: CacheXdo;
1336
+ history: HistoryXdo;
1337
+ middleware: MiddlewareXdo;
1338
+ tag: unknown[];
1339
+ input: InputXdo[];
1340
+ result: ResultItemXdo[];
1341
+ run: StackItemXdo[];
1342
+ test: TestXdo[];
1343
+ market_item: {
1344
+ id: number;
1345
+ version: number;
1346
+ guid: string;
1347
+ };
1348
+ shared_workspace: {
1349
+ is_shared: boolean;
1350
+ };
1351
+ }
1352
+ /**
1353
+ * The persisted row: authored envelope plus the server columns the engine
1354
+ * adds on import. Used ONLY by the test normalizer — the SDK never emits these.
1355
+ */
1356
+ type PersistedFunctionRow = FunctionXdo & {
1357
+ id: number;
1358
+ created_at: string;
1359
+ updated_at: string;
1360
+ deleted_at?: string;
1361
+ guid: string;
1362
+ _draft?: boolean;
1363
+ _xsid?: string;
1364
+ market_item?: {
1365
+ id: number;
1366
+ version: number;
1367
+ guid: string;
1368
+ };
1369
+ };
1370
+
1371
+ export { setting as $, type AuthValue as A, auth as B, type CacheXdo as C, c as D, type ExprGroup as E, type FieldXdo as F, caught as G, type HistoryXdo as H, type InpValue as I, col as J, env as K, type ListBoundsXdo as L, type MethodXdo as M, type NotObjMember as N, expect as O, type PersistedFunctionRow as P, QUERY_AGGREGATE_NAMES as Q, type RefValue as R, type StackItemXdo as S, TAGS as T, filter as U, type Value as V, inp as W, out as X, qf as Y, ref as Z, resp as _, type CaughtField as a, sys as a0, test as a1, toolset as a2, withFilters as a3, type CaughtShape as a4, type CaughtValue as b, type ConditionalContext as c, type ConditionalElifContext as d, type ConstValue as e, type ExprNode as f, type ExprOperand as g, type ExprStatement as h, type FilterXdo as i, type FilteredValue as j, type FunctionXdo as k, type InputXdo as l, QUERY_FILTER_NAMES as m, QUERY_FILTER_SPECS as n, type QueryFilter as o, type QueryFilterResults as p, type RegexValue as q, type ResultItemXdo as r, type StatementInputXdo as s, TEST_EXPECT_TYPES as t, type Tag as u, type TaggedValue as v, type TestDef as w, type TestExpect as x, type TestExpectType as y, type TestXdo as z };