@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.
- package/CHANGELOG.md +788 -0
- package/LICENSE +21 -0
- package/README.md +541 -0
- package/dist/.build-fingerprint +1 -0
- package/dist/agent-file-refresh-ZEMK33AX.js +38 -0
- package/dist/answer-shape-K67TAAPY.js +33 -0
- package/dist/backend-dir-2U53CIAL.js +39 -0
- package/dist/backend-slot-7QXW2QYC.js +28 -0
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +255 -0
- package/dist/branch-NCRNWQBQ.js +61 -0
- package/dist/branch-commands-ACIRCEQJ.js +79 -0
- package/dist/bundle.d.ts +223 -0
- package/dist/bundle.js +153 -0
- package/dist/capture-WAXPD7DR.js +41 -0
- package/dist/chunk-27GWNP2I.js +23 -0
- package/dist/chunk-2CMJZDCL.js +177 -0
- package/dist/chunk-2EZ3ZJZZ.js +302 -0
- package/dist/chunk-2GNFDZA2.js +390 -0
- package/dist/chunk-2MNLRIOX.js +11 -0
- package/dist/chunk-2TFRR6JV.js +104 -0
- package/dist/chunk-2ZUEE4EK.js +408 -0
- package/dist/chunk-36JUQZVQ.js +22 -0
- package/dist/chunk-3DRXWLJ5.js +83 -0
- package/dist/chunk-3JDU4VRL.js +137 -0
- package/dist/chunk-3KZCLN4Z.js +241 -0
- package/dist/chunk-3LDULPRE.js +168 -0
- package/dist/chunk-3M4LFYNQ.js +111 -0
- package/dist/chunk-3XI5CTUE.js +22 -0
- package/dist/chunk-3YW23UFH.js +50 -0
- package/dist/chunk-45UIT5T2.js +862 -0
- package/dist/chunk-4BW2SG2N.js +46 -0
- package/dist/chunk-4KHEMC32.js +79 -0
- package/dist/chunk-4POWHT2K.js +321 -0
- package/dist/chunk-4Q2GN7NW.js +192 -0
- package/dist/chunk-5A2PLKZB.js +70 -0
- package/dist/chunk-5FBYXK5P.js +159 -0
- package/dist/chunk-5HVXPTU4.js +323 -0
- package/dist/chunk-5QU2P5CA.js +304 -0
- package/dist/chunk-5V5XU32D.js +191 -0
- package/dist/chunk-5ZSO4T2G.js +10 -0
- package/dist/chunk-622HUCZT.js +10 -0
- package/dist/chunk-65HWOMGV.js +177 -0
- package/dist/chunk-6ELFRN3P.js +365 -0
- package/dist/chunk-6HO3NCSJ.js +1055 -0
- package/dist/chunk-6IUMKYWI.js +457 -0
- package/dist/chunk-6KEB3C3U.js +65 -0
- package/dist/chunk-6MR5TI5V.js +987 -0
- package/dist/chunk-6NNTNXN7.js +157 -0
- package/dist/chunk-6PBR37LN.js +97 -0
- package/dist/chunk-6QXLMMT3.js +155 -0
- package/dist/chunk-6ZGJCBZS.js +224 -0
- package/dist/chunk-73IVBKMA.js +250 -0
- package/dist/chunk-7G3CTU7I.js +286 -0
- package/dist/chunk-A3UDOZB6.js +222 -0
- package/dist/chunk-A6E77GDW.js +85 -0
- package/dist/chunk-AHJWCYQO.js +660 -0
- package/dist/chunk-AKNCFVKZ.js +36 -0
- package/dist/chunk-AM4FKL4J.js +237 -0
- package/dist/chunk-AN6BL47T.js +26 -0
- package/dist/chunk-AOSYVMUS.js +147 -0
- package/dist/chunk-APWXY5SL.js +182 -0
- package/dist/chunk-AWEIIR2U.js +218 -0
- package/dist/chunk-AWQ7BQTQ.js +73 -0
- package/dist/chunk-BAUZOWGX.js +393 -0
- package/dist/chunk-BHACRS6R.js +940 -0
- package/dist/chunk-BWPNT55T.js +680 -0
- package/dist/chunk-C6RIMRU4.js +187 -0
- package/dist/chunk-CGVQZXYG.js +263 -0
- package/dist/chunk-CIMQZRRE.js +162 -0
- package/dist/chunk-CJHQKJU4.js +113 -0
- package/dist/chunk-CTMO46PK.js +1897 -0
- package/dist/chunk-D53J55C5.js +106 -0
- package/dist/chunk-D7VGG3WS.js +90 -0
- package/dist/chunk-DAD3ONIS.js +245 -0
- package/dist/chunk-DGWHAVRG.js +162 -0
- package/dist/chunk-DX4QR4B2.js +483 -0
- package/dist/chunk-EHP3WPEG.js +21 -0
- package/dist/chunk-ELP2HMXC.js +432 -0
- package/dist/chunk-ERVIASGL.js +21 -0
- package/dist/chunk-ET4Y4XCB.js +865 -0
- package/dist/chunk-ETO6LGLD.js +4750 -0
- package/dist/chunk-EUUUMY7J.js +24 -0
- package/dist/chunk-FQJ2TTHP.js +218 -0
- package/dist/chunk-FQOF7E2E.js +133 -0
- package/dist/chunk-FWD7AL6N.js +21 -0
- package/dist/chunk-FXFV3KU6.js +138 -0
- package/dist/chunk-FXRQOWTE.js +171 -0
- package/dist/chunk-G554NZNI.js +210 -0
- package/dist/chunk-GSGDWJB5.js +13 -0
- package/dist/chunk-H2V3N23D.js +66 -0
- package/dist/chunk-H5C7MBCR.js +159 -0
- package/dist/chunk-HHN734BU.js +371 -0
- package/dist/chunk-HRVBLCVJ.js +243 -0
- package/dist/chunk-HVRUQXGD.js +1264 -0
- package/dist/chunk-I4F5TCJH.js +130 -0
- package/dist/chunk-IDOTCMDV.js +57 -0
- package/dist/chunk-IGOLHKWF.js +427 -0
- package/dist/chunk-JGE7CAWB.js +148 -0
- package/dist/chunk-JTUKLCXS.js +92 -0
- package/dist/chunk-JZGVVJSI.js +66 -0
- package/dist/chunk-K4WX6UUU.js +923 -0
- package/dist/chunk-K5BBGTYZ.js +217 -0
- package/dist/chunk-K6RXBGUB.js +427 -0
- package/dist/chunk-KTSDSD36.js +165 -0
- package/dist/chunk-L5JYN3NM.js +1038 -0
- package/dist/chunk-LIEOKXKD.js +354 -0
- package/dist/chunk-LLNZGEFK.js +51 -0
- package/dist/chunk-LPECSJ2J.js +55 -0
- package/dist/chunk-LQCMKAJ7.js +413 -0
- package/dist/chunk-LRN4ZJCQ.js +1145 -0
- package/dist/chunk-MJ4ZVHKN.js +17 -0
- package/dist/chunk-MXHSQOC4.js +3061 -0
- package/dist/chunk-N5GKCWE5.js +367 -0
- package/dist/chunk-NA3PXMEF.js +10 -0
- package/dist/chunk-NAQDMEHV.js +76 -0
- package/dist/chunk-NWKXM5RD.js +109 -0
- package/dist/chunk-NZOWWHU5.js +196 -0
- package/dist/chunk-OHX6MIUZ.js +184 -0
- package/dist/chunk-OOXWYAA4.js +15 -0
- package/dist/chunk-OPHB5ORL.js +1990 -0
- package/dist/chunk-OXA6PSZT.js +1725 -0
- package/dist/chunk-P2HAGF6H.js +73 -0
- package/dist/chunk-PTHVMXZI.js +3036 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-Q325JKYB.js +189 -0
- package/dist/chunk-Q7DGTQ5G.js +255 -0
- package/dist/chunk-QCNYHBL7.js +601 -0
- package/dist/chunk-QO6BVGS5.js +145 -0
- package/dist/chunk-QXTKSOFI.js +76 -0
- package/dist/chunk-ROY4YAEQ.js +66 -0
- package/dist/chunk-RTJRZFFY.js +447 -0
- package/dist/chunk-SAVJUS2X.js +128 -0
- package/dist/chunk-SFLHVCKX.js +173 -0
- package/dist/chunk-STSFNCY4.js +127 -0
- package/dist/chunk-SWBF2LTK.js +170 -0
- package/dist/chunk-T5KELPAR.js +109 -0
- package/dist/chunk-TFFGOFVZ.js +1481 -0
- package/dist/chunk-TLHIFK4M.js +256 -0
- package/dist/chunk-TLQE7ZN3.js +156 -0
- package/dist/chunk-TPHWJ7UG.js +1981 -0
- package/dist/chunk-TRJCALW3.js +291 -0
- package/dist/chunk-TTEIYD5P.js +133 -0
- package/dist/chunk-U64O2MXY.js +407 -0
- package/dist/chunk-UCQ2VUTG.js +630 -0
- package/dist/chunk-UTI5G6OJ.js +44 -0
- package/dist/chunk-UVHDMMIP.js +188 -0
- package/dist/chunk-UZ6QQWJT.js +120 -0
- package/dist/chunk-VAX3UZOY.js +686 -0
- package/dist/chunk-W3HBUKFO.js +57 -0
- package/dist/chunk-WKQLGKCL.js +2823 -0
- package/dist/chunk-WQFNASK4.js +560 -0
- package/dist/chunk-WRBKLYSJ.js +224 -0
- package/dist/chunk-WTPZRR4I.js +17 -0
- package/dist/chunk-WZDJ2LLX.js +2385 -0
- package/dist/chunk-X2NL4KUO.js +14 -0
- package/dist/chunk-X4DVXBFY.js +38 -0
- package/dist/chunk-X677DMZM.js +7050 -0
- package/dist/chunk-XBKMWY7F.js +612 -0
- package/dist/chunk-XNCP4KYO.js +78 -0
- package/dist/chunk-XVBGLISP.js +35 -0
- package/dist/chunk-XW6KISBB.js +1192 -0
- package/dist/chunk-YGZHHAAB.js +8156 -0
- package/dist/chunk-YHEFQUQB.js +186 -0
- package/dist/chunk-YLDALTWZ.js +653 -0
- package/dist/chunk-YU4HSQW7.js +229 -0
- package/dist/chunk-ZDPP6RKB.js +27 -0
- package/dist/chunk-ZFDZKNGG.js +194 -0
- package/dist/chunk-ZIY7RNUT.js +49 -0
- package/dist/chunk-ZYJP6BOO.js +30 -0
- package/dist/cli.d.ts +1111 -0
- package/dist/cli.js +165 -0
- package/dist/codegen-command-VR2GWR6C.js +173 -0
- package/dist/codegen.d.ts +115 -0
- package/dist/codegen.js +19 -0
- package/dist/commands-GJMJ4XYZ.js +76 -0
- package/dist/completion-ZQLO6PB6.js +738 -0
- package/dist/config-MBYGCAFK.js +136 -0
- package/dist/deploy-command-JVZPWHMK.js +180 -0
- package/dist/deploy-source-3W45CXMP.js +81 -0
- package/dist/dev-env-sync-HN44K4D5.js +188 -0
- package/dist/diagnostics-UEAAHWVF.js +30 -0
- package/dist/display-name-hint-ABBPVQIR.js +46 -0
- package/dist/emit-CyhBDxli.d.ts +7007 -0
- package/dist/env-example-refresh-ET5HMMDW.js +126 -0
- package/dist/env-pull-command-TNMNB3CV.js +323 -0
- package/dist/env-target-O4HRKTGZ.js +40 -0
- package/dist/env-var-command-ZIRDCAZA.js +427 -0
- package/dist/ephemeral-P7F3PMAD.js +54 -0
- package/dist/ephemeral-command-CLJJKOFT.js +592 -0
- package/dist/ephemeral-state-PYCBSOGX.js +61 -0
- package/dist/file-lock-PT74GWYW.js +10 -0
- package/dist/generate-command-AYEOLA26.js +510 -0
- package/dist/gitignore-3SJ3WNRG.js +51 -0
- package/dist/guards-4EBNCZDC.js +162 -0
- package/dist/hosted-file-PSHJB3HX.js +28 -0
- package/dist/impersonate-command-5JAS3WSV.js +152 -0
- package/dist/import-EQSFU6JC.js +19 -0
- package/dist/index.d.ts +5470 -0
- package/dist/index.js +371 -0
- package/dist/init-command-X2FR4UAK.js +125 -0
- package/dist/init-modules-RY7UHAOL.js +50 -0
- package/dist/init-web-M4YZSZK6.js +42 -0
- package/dist/internal.d.ts +179 -0
- package/dist/internal.js +2634 -0
- package/dist/io-RC56QSN5.js +26 -0
- package/dist/keep-data-merge-7MPLVAVI.js +1119 -0
- package/dist/lambda-config-reconcile-OUZ4OYAB.js +116 -0
- package/dist/landed-753YLJ5H.js +40 -0
- package/dist/landing-record-SU52SKXU.js +61 -0
- package/dist/live-diff-YONW2VI3.js +65 -0
- package/dist/local-engine-choice-CH5X3W7E.js +79 -0
- package/dist/local-engine-command-Z3OL7VOD.js +766 -0
- package/dist/local-engine-config-5U3SC434.js +39 -0
- package/dist/local-engine-deploy-PCQ4SNPB.js +39 -0
- package/dist/local-engine-process-EHTE5LLU.js +63 -0
- package/dist/local-engine-state-A4FTRFAF.js +32 -0
- package/dist/local-engine-update-check-6L645VBL.js +162 -0
- package/dist/lock-MRRHW5GS.js +87 -0
- package/dist/lock-commands-2QG25HL7.js +963 -0
- package/dist/login-command-QPYRWOXZ.js +538 -0
- package/dist/logout-command-WOIQLDP6.js +56 -0
- package/dist/loop-ALIZLOSX.js +191 -0
- package/dist/marketplace-command-K5YL42NO.js +977 -0
- package/dist/marketplace-resolve-LY32JES5.js +40 -0
- package/dist/meta-client-YXGPW53C.js +244 -0
- package/dist/module-manifest-JFGHU2TC.js +38 -0
- package/dist/near-key.d.ts +13 -0
- package/dist/near-key.js +8 -0
- package/dist/node.d.ts +95 -0
- package/dist/node.js +969 -0
- package/dist/operation-outcome-TZSESNC7.js +51 -0
- package/dist/output-target-AL3I44GG.js +47 -0
- package/dist/package-manager-PRAHUSCN.js +34 -0
- package/dist/plan-disclosure-6G4MLZKD.js +114 -0
- package/dist/plugin-contributions-WRNY5ABG.js +28 -0
- package/dist/plugin-prompt-4VA3B4FF.js +20 -0
- package/dist/plugin-questions-JTSYA74Q.js +24 -0
- package/dist/plugin.d.ts +396 -0
- package/dist/plugin.js +1 -0
- package/dist/preflight-command-2T5Z36MI.js +321 -0
- package/dist/profile-command-AH3PIM4X.js +800 -0
- package/dist/profile-pointer-GRWJU3YD.js +31 -0
- package/dist/profile-select-74TRDEPD.js +23 -0
- package/dist/project-dependency-KSH63ODT.js +35 -0
- package/dist/project-sdk-REPPOIBD.js +24 -0
- package/dist/promote-command-PCWT5N6S.js +140 -0
- package/dist/prompt-II3F3LND.js +27 -0
- package/dist/publish-command-TTDUUJI5.js +414 -0
- package/dist/pull-command-VBO7C4S3.js +161 -0
- package/dist/pull-superseded-GJWLG7XO.js +20 -0
- package/dist/release-command-N4ZPKMHR.js +146 -0
- package/dist/release-ns-command-3KFDMZ6G.js +1745 -0
- package/dist/response-HlXahv4K.d.ts +925 -0
- package/dist/retry-command-AS5EVREX.js +34 -0
- package/dist/routes-manifest-SNWUVBT6.js +43 -0
- package/dist/runtime-XETHVF33.js +14 -0
- package/dist/scaffold.d.ts +1911 -0
- package/dist/scaffold.js +107 -0
- package/dist/secrets-file-LVZD6IIM.js +56 -0
- package/dist/secrets-fill-command-TTCPSVXN.js +218 -0
- package/dist/seed-VU7C3QYS.js +46 -0
- package/dist/sent-writes-N7X4OVXT.js +22 -0
- package/dist/source-resolve-S2XA3XZF.js +83 -0
- package/dist/static-host-B2Y6AG3W.js +352 -0
- package/dist/status-command-RUDXTF7I.js +554 -0
- package/dist/store-6VNCD4D7.js +20 -0
- package/dist/store-ARM6VMO5.js +98 -0
- package/dist/store-DuYfzKlW.d.ts +3144 -0
- package/dist/suggest-6FOOYKHG.js +12 -0
- package/dist/sveltekit.d.ts +154 -0
- package/dist/sveltekit.js +109 -0
- package/dist/sync-contributions-UCEROO26.js +415 -0
- package/dist/table-ENAVMITR.js +42 -0
- package/dist/tables-command-GUPXXSB5.js +156 -0
- package/dist/tenant-IIHPOHGP.js +42 -0
- package/dist/tenant-command-D5HGI2X4.js +965 -0
- package/dist/test-command-TIKZMDPZ.js +476 -0
- package/dist/tests-BGGIOK3L.js +26 -0
- package/dist/token-NICJUTMT.js +72 -0
- package/dist/toolchain-hooks-GHKLUJOH.js +96 -0
- package/dist/toolchain-modules-5EAZUONB.js +24 -0
- package/dist/tracked-backend-EIBUMDZA.js +80 -0
- package/dist/update-check-2W2NLDTC.js +136 -0
- package/dist/upgrade-command-QHNFWM7O.js +531 -0
- package/dist/verify-rollout-DRCK5TDD.js +61 -0
- package/dist/whoami-command-STGINTXH.js +51 -0
- package/dist/workspace-2CLHU2LK.js +93 -0
- package/dist/workspace-binding-56PIIPCP.js +54 -0
- package/dist/workspace-command-JEXQETJD.js +535 -0
- package/dist/workspace-env-F2RFMSC5.js +70 -0
- package/dist/workspace-export-OJSH2HIW.js +21 -0
- package/dist/writable-VA7OISSK.js +25 -0
- package/dist/xano-ICFUSPFR.js +42 -0
- package/dist/xanosdk-import-GN42TO2B.js +56 -0
- package/dist/xanosdk-project-S6DXJONQ.js +41 -0
- package/dist/xdo-CxDr2Q1C.d.ts +1371 -0
- package/guides/README.md +33 -0
- package/guides/authoring.md +921 -0
- package/guides/cli.md +401 -0
- package/guides/codegen.md +177 -0
- package/guides/codes.md +404 -0
- package/guides/coverage.md +74 -0
- package/guides/deploying.md +1525 -0
- package/guides/environment.md +400 -0
- package/guides/marketplace.md +415 -0
- package/guides/module-contract.md +558 -0
- package/guides/object-kinds.md +433 -0
- package/guides/project-structure.md +43 -0
- package/guides/scaffold.md +351 -0
- package/guides/typed-frontend.md +242 -0
- package/llms/client.md +63 -0
- package/llms/errors.md +56 -0
- package/llms/fields.md +176 -0
- package/llms/filters.md +183 -0
- package/llms/kinds-agent-mcp.md +30 -0
- package/llms/kinds-core.md +100 -0
- package/llms/kinds-knowledge.md +20 -0
- package/llms/kinds-realtime.md +76 -0
- package/llms/lambda.md +94 -0
- package/llms/legacy.md +44 -0
- package/llms/lock.md +40 -0
- package/llms/object-kinds.md +34 -0
- package/llms/statements-calls.md +62 -0
- package/llms/statements-catalog.md +320 -0
- package/llms/statements-data.md +66 -0
- package/llms/statements-runtime.md +68 -0
- package/llms/tests.md +59 -0
- package/llms/toolchain.md +16 -0
- package/llms/triggers.md +36 -0
- package/llms/values.md +29 -0
- package/llms-full.txt +2085 -0
- package/llms.txt +493 -0
- package/manifest.json +11224 -0
- package/package.json +162 -0
- 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 };
|