@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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Xano, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# Xano SDK
|
|
4
|
+
|
|
5
|
+
### The official TypeScript SDK for [Xano](https://xano.com).
|
|
6
|
+
|
|
7
|
+
**Write your app in TypeScript — the database, the APIs, even AI agents. Or let an
|
|
8
|
+
AI write it for you. Then run one command and it's live on Xano's cloud, with its own
|
|
9
|
+
URL. No servers, no setup, no config. That's it.**
|
|
10
|
+
|
|
11
|
+
[](https://www.npmjs.com/package/@xano/sdk)
|
|
12
|
+
[](https://nodejs.org)
|
|
13
|
+
[](LICENSE)
|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx @xano/sdk login # 1. sign in (opens your browser)
|
|
19
|
+
npx @xano/sdk init my-app && cd my-app # 2. scaffold your backend + frontend
|
|
20
|
+
npm run build # 3. build your frontend → frontend/dist
|
|
21
|
+
npx xanosdk deploy ./xano/index.ts --static ./frontend/dist # 4. deploy both → live URLs
|
|
22
|
+
# Outside a project: npx @xano/sdk <cmd>. Inside one, npx xanosdk <cmd> runs its own install.
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
→ Deploying ./xano/index.ts → new ephemeral "my-app"
|
|
27
|
+
✓ Ephemeral e4f2-9ab1 deployed
|
|
28
|
+
! New ephemeral URL:
|
|
29
|
+
https://e4f2-9ab1.xano.io ← backend, live
|
|
30
|
+
Expires in 1h 0m
|
|
31
|
+
✓ Static host deployed
|
|
32
|
+
https://my-app.xano.io ← frontend, live
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
<div align="center">
|
|
36
|
+
|
|
37
|
+
**From an empty folder to a live full-stack app.** `init` sets up your project — a
|
|
38
|
+
TypeScript backend and a React or Svelte frontend. `npm run build` builds your frontend, then
|
|
39
|
+
`deploy` puts both online and hands you a live URL. Change your code — yourself or with
|
|
40
|
+
an AI — and deploy again; your app updates in seconds. No servers to set up, nothing to
|
|
41
|
+
configure, no glue code between your backend and your frontend.
|
|
42
|
+
|
|
43
|
+
[Why](#why-xano-sdk) ·
|
|
44
|
+
[Quickstart](#quickstart) ·
|
|
45
|
+
[The model](#the-model) ·
|
|
46
|
+
[Deploying](#deploying) ·
|
|
47
|
+
[Type-safe frontend](#a-type-safe-frontend-for-free) ·
|
|
48
|
+
[Reference](#reference)
|
|
49
|
+
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Why Xano SDK
|
|
55
|
+
|
|
56
|
+
Xano gives you a genuinely scalable backend — Postgres, serverless functions, background
|
|
57
|
+
tasks, realtime, MCP servers (tools, prompts and resources), AI agents — without you
|
|
58
|
+
running a single server. Xano SDK is Xano's **officially supported** TypeScript SDK, and it
|
|
59
|
+
gives you that backend **as code you own**:
|
|
60
|
+
|
|
61
|
+
- **📦 TypeScript is the source of truth.** Your whole workspace — tables, indexes, API
|
|
62
|
+
endpoints, functions, triggers, tasks, middleware, AI toolsets — is typed TS in your repo.
|
|
63
|
+
Version it, review it in PRs, diff it, roll it back. No more clicking through a dashboard
|
|
64
|
+
and hoping prod matches staging.
|
|
65
|
+
|
|
66
|
+
- **🚀 Deploy is built in.** `xanosdk deploy` compiles your code and ships it to a live Xano
|
|
67
|
+
environment over an authenticated connection, then prints its URL. Backend **and** static
|
|
68
|
+
frontend in one command — no export/import dance, no upload script to maintain.
|
|
69
|
+
|
|
70
|
+
- **⚡ Fast, safe iteration.** Ephemeral environments are disposable and auto-expiring, so
|
|
71
|
+
you rebuild as often as you like. Deploys are identity-stable: re-running never duplicates
|
|
72
|
+
objects, and every build writes a `xano.lock` you commit, so renames stay renames instead
|
|
73
|
+
of delete-and-recreate and your public URLs stay yours.
|
|
74
|
+
|
|
75
|
+
- **🧩 The types flow to your frontend.** `import type` a `query()` def for its typed request
|
|
76
|
+
and response, and read its path and verb from `xano/routes.gen.ts` — plain data the scaffold
|
|
77
|
+
regenerates before every dev, build and typecheck. Rename a column and every consumer lights up red.
|
|
78
|
+
|
|
79
|
+
- **🤖 AI-first by design.** A deterministic, fully-typed authoring surface: an agent (or
|
|
80
|
+
you) emits well-typed TS that always compiles to a valid, importable workspace. It ships
|
|
81
|
+
with machine-readable grounding an agent reads instead of your source — see
|
|
82
|
+
[Coverage & agent grounding](https://github.com/xanots/sdk/blob/main/guides/coverage.md).
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Quickstart
|
|
87
|
+
|
|
88
|
+
The four commands at the top of this page are the whole loop. Here they are one at a time.
|
|
89
|
+
|
|
90
|
+
**1. Sign in.** OAuth in your browser — no API keys to copy around. The CLI refreshes tokens
|
|
91
|
+
for you, and the target instance comes from your token rather than a flag.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
npx @xano/sdk login
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
> On a remote shell, container, or Codespace — anywhere your browser can't reach this machine's `127.0.0.1` — add `--paste`. It prints the URL for you to open anywhere,
|
|
98
|
+
> and you paste the redirect back. No browser at all (CI, a headless agent)? Create a token in your instance's settings under **Metadata API & MCP Server**, then pipe it
|
|
99
|
+
> to `npx @xano/sdk profile add <name> --instance <url> --workspace-id <n>`. See [Signing in & deploying](https://github.com/xanots/sdk/blob/main/guides/deploying.md).
|
|
100
|
+
|
|
101
|
+
**2. Scaffold.** `init` writes a complete project: a Vite frontend under `frontend/` (React
|
|
102
|
+
19 + shadcn/ui by default, or SvelteKit with `--framework svelte`), a Xano SDK backend under
|
|
103
|
+
`xano/`, and the `xano:export` / `xano:deploy` scripts already wired.
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
npx @xano/sdk init my-app && cd my-app
|
|
107
|
+
npm run dev # the frontend runs immediately
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
In a terminal it asks one question — the framework — with a default. `AGENTS.md`, the
|
|
111
|
+
agent brief every coding agent reads, is written without asking; `--no-agents-md` skips it. The theme is a flag, not a question: it is shadcn's own, a base color plus an
|
|
112
|
+
optional accent, rendered into the token stylesheet with a complete dark palette either way.
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
npx @xano/sdk init my-app --theme zinc-blue --dark toggle
|
|
116
|
+
npx @xano/sdk init my-app --theme https://ui.shadcn.com/r/themes/slate.json # or any registry theme
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The starter backend is empty but already compiles and deploys — grow it from the walkthrough
|
|
120
|
+
in `xano/EXAMPLE.md`. For the flags, the two presets, theming, and add-ons, see
|
|
121
|
+
[The scaffolded project](https://github.com/xanots/sdk/blob/main/guides/scaffold.md).
|
|
122
|
+
|
|
123
|
+
Prefer to see the theme before you commit to it? `--web` picks the framework, the palette,
|
|
124
|
+
the typefaces and the add-ons in a browser, against a live preview, and hands the result
|
|
125
|
+
back to `init` here in your terminal.
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npx @xano/sdk init my-app --web
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
It is a nicer way to arrive at the flags above, not a second scaffolder — it prints the
|
|
132
|
+
equivalent `init` command when it is done, so the project stays reproducible from a script.
|
|
133
|
+
The configurator is downloaded on demand, so `--web` needs the registry before it can
|
|
134
|
+
start; `init` reaches out only to install the new project's dependencies, which
|
|
135
|
+
`--no-install` skips.
|
|
136
|
+
|
|
137
|
+
**3. Build the frontend.**
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
npm run build # → frontend/dist
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**4. Deploy both.** One authenticated call ships your database schema, your APIs, your
|
|
144
|
+
functions and triggers, **and** your compiled web app.
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
npx xanosdk deploy ./xano/index.ts --static ./frontend/dist
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
→ Deploying ./xano/index.ts → new ephemeral "my-app"
|
|
152
|
+
✓ Ephemeral e4f2-9ab1 deployed
|
|
153
|
+
! New ephemeral URL:
|
|
154
|
+
https://e4f2-9ab1.xano.io ← backend, live
|
|
155
|
+
Expires in 1h 0m
|
|
156
|
+
✓ Config injected into 1 document: window.XANO_HOST ← backend URL, wired in
|
|
157
|
+
✓ Static host deployed
|
|
158
|
+
https://my-app.xano.io ← frontend, live
|
|
159
|
+
✓ Frontend is live ← edge confirmed serving THIS build
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
That's the dev loop. Change your code and run step 4 again; the environment refreshes in
|
|
163
|
+
seconds. The deploy bakes the backend URL into your build as `window.XANO_HOST`, so the
|
|
164
|
+
frontend never needs to know it ahead of time — read it with a build-time fallback:
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
const HOST = (typeof window !== "undefined" && window.XANO_HOST) || import.meta.env.VITE_XANO_HOST;
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
> Deploying again keeps the **backend** URL; the **frontend** one changes, because a deploy
|
|
171
|
+
> is a full replace and clears the environment's static hosting along with its workspace.
|
|
172
|
+
> Hand out the URL from the latest run. [Signing in & deploying](https://github.com/xanots/sdk/blob/main/guides/deploying.md) covers
|
|
173
|
+
> the injection rules, serving stored files, and headless CI runs.
|
|
174
|
+
|
|
175
|
+
**Prefer to wire it by hand?** Skip `init` — `npm init -y && npm pkg set type=module && npm install -D @xano/sdk`, then `npx xanosdk upgrade`
|
|
176
|
+
(it rewrites npm's caret to the range `init` writes). Write your workspace in `xano/index.ts`; steps 1 and 4
|
|
177
|
+
are unchanged. `type=module` matters: Xano SDK defs are ESM-only, and `npm init` writes `"type": "commonjs"`. A TypeScript entry wants
|
|
178
|
+
[`tsx`](https://tsx.is) (`npm i -D tsx`), which the CLI picks up — Node's type stripping does not remap a workspace's `./x.js` imports.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## The model
|
|
183
|
+
|
|
184
|
+
You author declarative def-objects, register them on one `Xano` instance, and Xano SDK
|
|
185
|
+
compiles the whole thing into Xano's importable bundle.
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
import { workspace, table, query, apiGroup, f, s, ref, c, expr, col } from "@xano/sdk";
|
|
189
|
+
|
|
190
|
+
// A database table — `id` + `created_at` auto-inject, so declare only your own columns.
|
|
191
|
+
const user = table({
|
|
192
|
+
name: "user",
|
|
193
|
+
auth: true,
|
|
194
|
+
schema: {
|
|
195
|
+
email: f.email({ required: true, methods: ["trim", "lower"] }),
|
|
196
|
+
name: f.text(),
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
export const post = table({
|
|
201
|
+
name: "post",
|
|
202
|
+
schema: {
|
|
203
|
+
title: f.text({ required: true }),
|
|
204
|
+
body: f.text(),
|
|
205
|
+
published: f.bool({ default: false }),
|
|
206
|
+
author: f.tableRef(user), // a real foreign key, type-checked
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// A public API group + endpoint. This query def is also the contract your frontend imports.
|
|
211
|
+
const blog = apiGroup({ name: "blog", canonical: "blog" });
|
|
212
|
+
|
|
213
|
+
const listPosts = query({
|
|
214
|
+
verb: "GET",
|
|
215
|
+
apiGroup: blog,
|
|
216
|
+
name: "list_posts",
|
|
217
|
+
stack: [
|
|
218
|
+
s.db.query({ table: post, where: expr(col("published"), "=", c.bool(true)), as: "rows" }),
|
|
219
|
+
],
|
|
220
|
+
response: ref("rows"),
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
export default workspace("blog")
|
|
224
|
+
.registerApiGroups([blog])
|
|
225
|
+
.registerTables([user, post])
|
|
226
|
+
.registerQueries([listPosts]);
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Tab-complete `s.` to discover the entire statement catalog — `s.db.*`, `s.math.*`,
|
|
230
|
+
`s.array.*`, `s.text.*`, `s.storage.*`, `s.api.*`, `s.cloud.*`, control flow, AI agent runs,
|
|
231
|
+
and more. **All 218 engine statement surfaces are authorable** — every field name matches
|
|
232
|
+
the Xano engine, and the emitted shape is checked against bytes a real engine stored. Where
|
|
233
|
+
a surface has no stored instance behind it yet, it is built from the engine's own schema;
|
|
234
|
+
[Coverage](https://github.com/xanots/sdk/blob/main/guides/coverage.md) says which is which.
|
|
235
|
+
|
|
236
|
+
Give a table a `seed` array and those rows ship into the database on deploy, so a fresh
|
|
237
|
+
environment comes up with its lookup tables and fixtures already in place. A file column or an
|
|
238
|
+
MCP icon takes `hostedFile("./logo.png", import.meta.url)`: the file ships with the deploy.
|
|
239
|
+
|
|
240
|
+
Your workspace's own AI agents are configured the same way. `knowledge()` is the markdown
|
|
241
|
+
they read before they act — standing instructions, a skill, or reference docs — and the body
|
|
242
|
+
is a real `.md` file in your repo rather than a string in a def:
|
|
243
|
+
|
|
244
|
+
```ts
|
|
245
|
+
knowledge({
|
|
246
|
+
name: "deploy-runbook",
|
|
247
|
+
description: "How this workspace ships: environments, gates, and rollback.",
|
|
248
|
+
body: knowledgeFile("./deploy-runbook.md", import.meta.url),
|
|
249
|
+
refs: knowledgeDir("./deploy-runbook", import.meta.url),
|
|
250
|
+
});
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
So the instructions your agents follow are reviewed in a diff, versioned with the code they
|
|
254
|
+
describe, and redeployed with it — instead of living in a console where nothing tracks them.
|
|
255
|
+
|
|
256
|
+
Tables, fields,
|
|
257
|
+
statements, values, inputs, and middleware are all in the
|
|
258
|
+
[Authoring reference](https://github.com/xanots/sdk/blob/main/guides/authoring.md); every kind you can author is in
|
|
259
|
+
[Object kinds](https://github.com/xanots/sdk/blob/main/guides/object-kinds.md).
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Deploying
|
|
264
|
+
|
|
265
|
+
A deploy targets a **disposable ephemeral**. Reaching anything real goes through a **release** — the stored record
|
|
266
|
+
that this code came up and answered: `deploy --test`, then `release create v1`, then `promote v1`.
|
|
267
|
+
|
|
268
|
+
| Command | Where it goes |
|
|
269
|
+
|---|---|
|
|
270
|
+
| `xanosdk deploy` | A disposable **ephemeral** — create-or-refreshed each run, auto-expiring, with its own URL. The default; needs no flag. |
|
|
271
|
+
| `xanosdk deploy --local-engine` | A **local engine** on this machine — no network round-trip per deploy, nothing to configure, and no Xano account needed. The first run downloads the engine and pins its version in `package.json` so every checkout runs the same one; `xanosdk local-engine update` moves the pin ([details](guides/deploying.md#deploying-to-a-local-engine)). |
|
|
272
|
+
| `xanosdk promote <release>` | Your **main Xano instance** workspace — the production target. Lands a release on a branch named for it, reads the branch back, and fails naming anything the release declared that did not arrive. `--set-live` serves it once that check passes. Tables are shared by every branch, so its table changes reach live as it lands — one that alters a table is refused without `--allow-shared-schema-changes`. |
|
|
273
|
+
| `xanosdk tenant deploy <tenant> <release>` | A **customer tenant** — the same release, on someone else's deployment. It **replaces** what the tenant serves: anything the release does not carry is removed. Static hosting is kept. |
|
|
274
|
+
| `xanosdk release transfer <release> --to-profile <profile>` | **Another workspace or instance** — copies the stored release, checked by content hash, to `promote` there. |
|
|
275
|
+
| `xanosdk deploy --to <dest>` | The **escape hatch**: merges a local build straight into `workspace` or `tenant:<name>`, skipping the release record. |
|
|
276
|
+
| `xanosdk publish <dir>` | **Just the frontend**: an already-built directory onto the ephemeral you last deployed to (default), `workspace`, or `tenant:<name>` static host — after a local-engine deploy, `--to ephemeral`, as a local engine has none. No compile, no backend import — the retry when a frontend fails after its backend landed, and `npm run xano:deploy:frontend` in a scaffold. |
|
|
277
|
+
|
|
278
|
+
Every `deploy` is a **full replace** of the disposable environment unless [`--keep-data`](guides/deploying.md#keeping-your-data-between-deploys) merges, keeping its rows.
|
|
279
|
+
Promoting is the opposite by design: it changes what your code defines and keeps every row — so an unchanged
|
|
280
|
+
project is a no-op. But tables have no branch: a change that alters one reaches live as it lands, so it is refused without `--allow-shared-schema-changes`. A tenant deploy then serves
|
|
281
|
+
exactly the release, and a `--seed` release REPLACES its seeded tables' rows, named with counts first ([details](guides/deploying.md#what-a-landing-does-to-tables)).
|
|
282
|
+
|
|
283
|
+
Going the other way — from a backend you did not author — is `xanosdk pull release:v1`, which **rewrites** the decoded files in `xano/` — it keeps files you added, and lists and confirms first.
|
|
284
|
+
|
|
285
|
+
**The alternative.** `deploy --to workspace` merges your local build straight in, skipping the release record. Reach
|
|
286
|
+
for it to delete objects, or for the plan preview a release cannot run (`--dry-run`, `--prune`; `--yes` skips the
|
|
287
|
+
prompt for CI, never the preview). It leaves nothing to re-land — prefer a release for anything you may repeat.
|
|
288
|
+
|
|
289
|
+
A release name is **refused** rather than resolved when it already exists, and so is a public URL something else
|
|
290
|
+
already holds. Nothing is written, the message names what holds it, and the exit code is `2`. `--yes` does not
|
|
291
|
+
waive it: a taken identity is not a question about whether you meant it.
|
|
292
|
+
|
|
293
|
+
**Scripting a landing:** `release create`, `promote` and `tenant deploy --json` print one result, failures included; `completed: unknown` exits `9` —
|
|
294
|
+
run its `resolveWith` before retrying ([details](guides/deploying.md#reading-the-result---json-and-exit-codes)).
|
|
295
|
+
|
|
296
|
+
> ⚠️ A deploy is a full replace of the target environment, **including its table records**, before importing. The
|
|
297
|
+
> blast radius is your own disposable ephemeral — but anything you only ever created by hand in it is gone. That
|
|
298
|
+
> is exactly why reaching production goes through a release.
|
|
299
|
+
|
|
300
|
+
**Deploying to a branch.** With one workspace, a deploy and production are the same thing.
|
|
301
|
+
`--branch <label>` lands it on a non-live branch instead, `--set-live` promotes it, and
|
|
302
|
+
`--backup-branch` snapshots live's logic, not its shared tables, for a one-`set-live` rollback — see
|
|
303
|
+
[the deploying guide](guides/deploying.md). The flag reads too: `init --from workspace --branch
|
|
304
|
+
<label>` pulls that branch rather than live, so reviewing one as TypeScript costs no cutover.
|
|
305
|
+
|
|
306
|
+
> ⚠️ **A branch stages your logic, not your database.** Tables and microservices are shared by
|
|
307
|
+
> every branch, so a schema change reaches production whichever branch you target. A branch
|
|
308
|
+
> release carrying one is refused unless you pass `--allow-shared-schema-changes`. Seeded
|
|
309
|
+
> **rows** are shared too, so reference data has an order: rows first (`workspace
|
|
310
|
+
> reset-tables`), then the logic reading them — the guide has the recipe.
|
|
311
|
+
|
|
312
|
+
> ⚠️ **`--replace` clears by workspace, not by branch.** It deletes every non-live branch and
|
|
313
|
+
> the saved versions that would restore one — not recoverable. Refused unless you pass
|
|
314
|
+
> `--allow-branch-deletion`, which `--yes` does not cover; the guide has the recipe.
|
|
315
|
+
|
|
316
|
+
`xanosdk status` answers where you stand in one read — who you are signed in as, which
|
|
317
|
+
credential profile that came from, which instance and workspace it is bound to, and the
|
|
318
|
+
backend this project last deployed to — an ephemeral or a local engine — including whether it is still alive and when it
|
|
319
|
+
expires. More than one account or instance is `xanosdk login --profile <name>`, then
|
|
320
|
+
`--profile <name>` on any command. `xanosdk init` commits a `xano.profile.json` pinning the
|
|
321
|
+
repository to one credential (`xanosdk profile use <name>` repoints it), and nothing ambient
|
|
322
|
+
outranks that pin: a `$XANO_PROFILE` in a shell rc cannot retarget a pinned project, only
|
|
323
|
+
`--profile` can. The tracked environment is per profile, so a redeploy under another credential
|
|
324
|
+
cannot refresh the wrong tenant, and every writing command names its target before writing.
|
|
325
|
+
|
|
326
|
+
**Your dev server follows the deploy.** In a scaffolded project, a deploy that publishes no static site writes the backend
|
|
327
|
+
URL into the project's gitignored `.env.local` as `VITE_XANO_HOST`, in a marked block that leaves your own values alone and
|
|
328
|
+
is replaced rather than repeated next time. **Restart the dev server to pick it up.** `--no-dev-env` turns it off, and so
|
|
329
|
+
do `--static <dir>` and a site an earlier deploy published there that still serves — a frontend reads the URL at runtime. A `.env.local` your repo does not ignore is
|
|
330
|
+
reported, never written.
|
|
331
|
+
|
|
332
|
+
Every flag, the `--prune` rules, the identity model, and headless CI runs are in
|
|
333
|
+
[Signing in & deploying](https://github.com/xanots/sdk/blob/main/guides/deploying.md). Every operation names a backend one way — `workspace`, `ephemeral[:<name>]`, `local-engine[:<name>]`, `tenant:<name>`, `release:<name>` — and a bare one follows the ephemeral or local engine you last deployed to, never your workspace ([the grammar](guides/cli.md#naming-a-backend)).
|
|
334
|
+
Environment management is `xanosdk ephemeral <list|get|delete|export>`; `xanosdk tables [backend]` lists guids and `xanosdk impersonate [backend]` opens one in the builder.
|
|
335
|
+
|
|
336
|
+
### Testing
|
|
337
|
+
|
|
338
|
+
The tests you author — a `tests` entry on a query, function, or middleware, or a standalone
|
|
339
|
+
`workflowTest()` — run against a deployed environment:
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
npx xanosdk test run-all # the ephemeral or local engine you last deployed to
|
|
343
|
+
npx xanosdk test run-all --on ephemeral:e4f2-9ab1 # or one by its name, not its display name (also local-engine, tenant:<name>)
|
|
344
|
+
npx xanosdk test run-all --on workspace # or your real workspace
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
A test's `datasource` defaults to `""` — an empty database, so `table({ seed })` rows are
|
|
348
|
+
not visible. On an ephemeral, set `datasource: "live"` to read them: there it holds only
|
|
349
|
+
your seed fixtures (plus any rows a `--keep-data` deploy kept). That value is **stored on the test**, so clear it before you release —
|
|
350
|
+
a non-empty datasource is cloned before every run, and against your real workspace that is
|
|
351
|
+
the production database.
|
|
352
|
+
|
|
353
|
+
`xanosdk test list` shows what is there without running it, and `xanosdk test run "<name>"`
|
|
354
|
+
runs one. A failing suite exits **5**, distinct from a crash, so CI can tell the two apart.
|
|
355
|
+
To deploy and prove it in one step, `xanosdk deploy ./xano/index.ts --test` — a failing test
|
|
356
|
+
exits 5 **without** retracting the deploy, so the environment is live either way.
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## A type-safe frontend, for free
|
|
361
|
+
|
|
362
|
+
Because your API is a typed def, the code that *calls* it reuses that def instead of
|
|
363
|
+
re-typing URLs and request bodies. Paths come from a generated route manifest, types
|
|
364
|
+
straight from the defs:
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
npx xanosdk routes ./xano/index.ts --emit xano/routes.gen.ts # scaffolds run this before dev/build/typecheck
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
```ts
|
|
371
|
+
import { ROUTES, routePath } from "../xano/routes.gen.js"; // plain data, imports nothing
|
|
372
|
+
import type { post } from "../xano/index.js"; // the model above
|
|
373
|
+
import type { InferRow } from "@xano/sdk";
|
|
374
|
+
|
|
375
|
+
const BASE = window.XANO_HOST ?? import.meta.env.VITE_XANO_HOST; // deploy injects it; .env.local in dev
|
|
376
|
+
|
|
377
|
+
type Post = InferRow<typeof post>; // { id: number; created_at: number; title: string; … }
|
|
378
|
+
|
|
379
|
+
async function fetchPosts(): Promise<Post[]> {
|
|
380
|
+
const res = await fetch(BASE + routePath("GET list_posts"), { method: ROUTES["GET list_posts"].verb });
|
|
381
|
+
return res.json(); // typed end to end
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
- **`routePath("GET blog/{slug}", { slug })`** → the endpoint path, resolved from your code
|
|
386
|
+
(or the frozen `xano.lock`). Keys are `"<VERB> <name>"`, so verb-differentiated siblings
|
|
387
|
+
coexist (a pair two api groups share is keyed `"<group>:<VERB> <name>"`), and the keys and their `{param}` names are checked at compile time: a backend
|
|
388
|
+
rename is a compile error rather than a 404.
|
|
389
|
+
- **`ROUTES[key].verb`** → the HTTP method, as a literal.
|
|
390
|
+
- **`InferInput<typeof someQuery>`** → the request-payload type, derived from a query's
|
|
391
|
+
`input` map at compile time. Required inputs are required keys, enums literal unions, and
|
|
392
|
+
a nullable field (explicit or by type default) adds `| null`. **No codegen, always in sync.**
|
|
393
|
+
- **`InferRow<typeof post>`** → the table's row type. Rename or retype a column and every
|
|
394
|
+
consumer breaks at compile time — exactly where you want it.
|
|
395
|
+
- **`InferResponse<typeof someQuery>`** → the endpoint's **response** type, closing the round
|
|
396
|
+
trip. It auto-derives the common shapes with no codegen, mirroring the static walk the
|
|
397
|
+
engine itself does, and degrades to `unknown` in exactly the cases the engine cannot
|
|
398
|
+
resolve either — declare `responseShape` there. A `db.get` row types as `Row | null`
|
|
399
|
+
until `guard.found("row")` asserts it exists (404 otherwise), which narrows it to `Row`.
|
|
400
|
+
|
|
401
|
+
Import defs into a frontend with `import type` only. A def imported as a value, for its
|
|
402
|
+
`getPath()`/`verb`, runs its factory calls at module load and carries the SDK runtime and
|
|
403
|
+
the backend graph it references into the bundle. The measured bundle
|
|
404
|
+
numbers, the full response-inference rules, endpoint-name constraints, and the realtime
|
|
405
|
+
helpers are in
|
|
406
|
+
[The typed frontend surface](https://github.com/xanots/sdk/blob/main/guides/typed-frontend.md).
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
## Already have a Xano workspace?
|
|
411
|
+
|
|
412
|
+
`--from` runs the loop the other way: it reads a workspace and writes it back out as
|
|
413
|
+
readable Xano SDK source — real `s.db.query(...)`, `f.email()`, typed defs — not a JSON dump.
|
|
414
|
+
And not a loose pile of files either: it is the same runnable project `xanosdk init`
|
|
415
|
+
scaffolds, with the pulled workspace filling `xano/` instead of the starter. So a pull
|
|
416
|
+
deploys:
|
|
417
|
+
|
|
418
|
+
```bash
|
|
419
|
+
npx @xano/sdk init my-app --from workspace # your real workspace (the one your login is scoped to)
|
|
420
|
+
cd my-app
|
|
421
|
+
npm run build
|
|
422
|
+
npm run xano:deploy # → a live ephemeral URL
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
The other sources are the same flag with a different value — `--from ephemeral:<name>`, `--from local-engine:<name>`,
|
|
426
|
+
and `--from ./ws.json` for a bundle already on disk (offline, no login). Everything else about the project is unchanged, so `--theme`, `--no-agents-md` and `--web`
|
|
427
|
+
compose with a pull exactly as they do with a starter. For just the `xano/` tree with no project around it, `xanosdk generate <source> [--out <dir>]` also reads `release:<name>` and `tenant:<name>`.
|
|
428
|
+
|
|
429
|
+
Object identities are preserved, so cross-references stay intact, and a statement this SDK
|
|
430
|
+
does not model yet round-trips verbatim rather than breaking the pull. Then it checks its own
|
|
431
|
+
work: the tree it just wrote is loaded, exported, and diffed against the workspace it came
|
|
432
|
+
from, so "it compiled" and "it means the same thing" are separate claims and you get both.
|
|
433
|
+
|
|
434
|
+
> ⚠️ **After a pull, `xano/` is your source** — edit it and commit it. A later `pull` replaces
|
|
435
|
+
> only what a decode wrote: it refuses a dirty tree, asks before discarding your edits, and keeps
|
|
436
|
+
> files no decode wrote. It carries schema only — no table rows or stored files — and deploying
|
|
437
|
+
> it is a *full replace* of the target, so try a change on a disposable ephemeral first.
|
|
438
|
+
|
|
439
|
+
A pull carries env var **names**, never values: the config declares each name with an empty
|
|
440
|
+
placeholder and the values stay in the workspace (`init --from ./ws.json` on a bundle that
|
|
441
|
+
carries values writes them to `xano/.env` for you). They belong in `xano/.env` — gitignored,
|
|
442
|
+
preserved across a pull, and read with no flag by every command that compiles a bundle. Copy
|
|
443
|
+
`xano/.env.example` and fill it in, or run `npx xanosdk env pull` to fetch them from a running
|
|
444
|
+
backend; `npx xanosdk env set NAME` / `env unset NAME` change one live value without a deploy.
|
|
445
|
+
Because a deploy *replaces* the backend's env set, a declared name with no value refuses the
|
|
446
|
+
deploy rather than clearing the live one; CI mounts its own file and passes `--backend-env-file <path>`. The token gating a **hosted doc site** is a secret too, and goes in a second
|
|
447
|
+
ignored file. The source declares only the gate — `documentation: { require_token: true }` on the
|
|
448
|
+
workspace config or an `apiGroup`, and a literal `token` fails the export. `npx xanosdk pull` writes
|
|
449
|
+
the value to `xano/.secrets.json` and every build reads it back; `npx xanosdk secrets fill` mints one
|
|
450
|
+
for a gate you declared yourself, which has none to pull. Omitting the workspace's block leaves the
|
|
451
|
+
target's alone, but an API group's is always sent, so omitting *that* one clears its gate — the
|
|
452
|
+
export fails when a group publishes docs and declares a gate with no token. A merge (`deploy --to
|
|
453
|
+
workspace`) never writes the workspace's block and says so; `--replace` does.
|
|
454
|
+
|
|
455
|
+
What the generated tree looks like, how faithful the pull is, and how to read its report are
|
|
456
|
+
in [Pulling an existing workspace](https://github.com/xanots/sdk/blob/main/guides/codegen.md).
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
## Reference
|
|
461
|
+
|
|
462
|
+
Every kind, statement, filter, and field type is typed, so your editor's autocomplete is
|
|
463
|
+
the fastest lookup — tab-complete `s.`, `f.`, `c.`, `fl.`, `input.`. For the written
|
|
464
|
+
reference, the guides carry the shape of a project and the behavior that will bite you:
|
|
465
|
+
|
|
466
|
+
| Guide | What's in it |
|
|
467
|
+
|---|---|
|
|
468
|
+
| [Project structure](https://github.com/xanots/sdk/blob/main/guides/project-structure.md) | How a `xano/` project is laid out, and why registration is explicit |
|
|
469
|
+
| [The scaffolded project](https://github.com/xanots/sdk/blob/main/guides/scaffold.md) | What `xanosdk init` writes, the two frontend presets, theming, add-ons, SvelteKit rules |
|
|
470
|
+
| [The marketplace](https://github.com/xanots/sdk/blob/main/guides/marketplace.md) | Finding add-ons, the two kinds of module, and the install/reinstall/remove lifecycle |
|
|
471
|
+
| [The module contract](https://github.com/xanots/sdk/blob/main/guides/module-contract.md) | Building an add-on: the manifest fields, the plugin types, every hook, and what is refused |
|
|
472
|
+
| [Object kinds](https://github.com/xanots/sdk/blob/main/guides/object-kinds.md) | Every authorable kind, and splitting a workspace across microservices |
|
|
473
|
+
| [Authoring reference](https://github.com/xanots/sdk/blob/main/guides/authoring.md) | Tables and fields, statements, values, inputs, middleware, seed data |
|
|
474
|
+
| [CLI](https://github.com/xanots/sdk/blob/main/guides/cli.md) | Every command, shell completion, and what failures look like |
|
|
475
|
+
| [Warning and error codes](https://github.com/xanots/sdk/blob/main/guides/codes.md) | Every code the CLI and the build emit, with what it means |
|
|
476
|
+
| [Signing in & deploying](https://github.com/xanots/sdk/blob/main/guides/deploying.md) | Auth, ephemerals, `--static`, releasing to production, `xanosdk preflight` |
|
|
477
|
+
| [Environment & identity](https://github.com/xanots/sdk/blob/main/guides/environment.md) | Every environment variable, and how `xano.lock` pins identity |
|
|
478
|
+
| [The typed frontend surface](https://github.com/xanots/sdk/blob/main/guides/typed-frontend.md) | Path resolution, input/response inference, bundle cost, the route manifest |
|
|
479
|
+
| [Pulling an existing workspace](https://github.com/xanots/sdk/blob/main/guides/codegen.md) | What `xanosdk init --from` writes, how faithful it is, and how to read its report |
|
|
480
|
+
| [Coverage & agent grounding](https://github.com/xanots/sdk/blob/main/guides/coverage.md) | What is covered, what is out of scope, and the files agents read |
|
|
481
|
+
|
|
482
|
+
### Reading a compiled bundle
|
|
483
|
+
|
|
484
|
+
`@xano/sdk` writes a bundle; `@xano/sdk/bundle` reads one back. It is the surface for
|
|
485
|
+
tools that take compiled JSON as input — a graph view, a diff, a linter, a docs generator —
|
|
486
|
+
so none of them has to reverse-engineer the storage shape and then go quietly wrong when the
|
|
487
|
+
engine grows a new one.
|
|
488
|
+
|
|
489
|
+
```ts
|
|
490
|
+
import { readFile } from "node:fs/promises";
|
|
491
|
+
import { statementCatalog, walk } from "@xano/sdk/bundle";
|
|
492
|
+
|
|
493
|
+
const bundle = JSON.parse(await readFile("bundle.json", "utf8"));
|
|
494
|
+
const catalog = statementCatalog();
|
|
495
|
+
|
|
496
|
+
for (const { raw, path, depth } of walk(bundle.payload.query[0].run)) {
|
|
497
|
+
console.log(`${" ".repeat(depth)}${path} ${catalog.get(raw.name)?.sPath ?? raw.name}`);
|
|
498
|
+
}
|
|
499
|
+
// 0 db.query
|
|
500
|
+
// 1 conditional
|
|
501
|
+
// 1.if.0 db.add
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
- **`walk(run)`** → every statement in the tree, each with a `path` and a `depth`. The path
|
|
505
|
+
format (`2.if.0`) is the shared address: a lint finding, a review comment and a runtime
|
|
506
|
+
error written by three different tools all name the same node.
|
|
507
|
+
- **`subStacks(raw)`** → the nested stacks a statement carries, keyed by where they are
|
|
508
|
+
stored and labelled by what they mean — a try/catch and a conditional share the same three
|
|
509
|
+
storage keys. Found by shape, so a nesting form added later is still walked.
|
|
510
|
+
- **`statementCatalog()`** → the stored `mvp:*` name to its authoring path, minus the
|
|
511
|
+
namespace (`mvp:dbo_view` → `db.query`, the `sPath` you write after `s.`) — which is
|
|
512
|
+
the point: the stored name is often not the one you'd guess.
|
|
513
|
+
- **`structuralHash(raw)`** → a diff key for a statement and everything under it, with
|
|
514
|
+
engine-filled operands excluded — so adding a column to a table leaves `db.edit` /
|
|
515
|
+
`db.add_or_edit` unchanged. A `db.add` writes every column, so its hash does change.
|
|
516
|
+
- **`tableRefOf(column)` / `linkedTableOf(column)`** → the table a column points at.
|
|
517
|
+
- **`normalize(value)`** → the normalizer `xanosdk preflight` compares with, for diffing a
|
|
518
|
+
stored workspace against a compiled one.
|
|
519
|
+
|
|
520
|
+
Everything on the entry is pure — no filesystem, network, or Node built-ins — so it runs anywhere.
|
|
521
|
+
|
|
522
|
+
The package also ships two machine-readable descriptions of the same surface, generated from the SDK's
|
|
523
|
+
own sources so they cannot drift from it: `llms.txt` (the router — the mental model and the gotchas, plus a
|
|
524
|
+
map of the `llms/*.md` topic files) and `manifest.json` (per-entry detail: field schemas, filter arguments,
|
|
525
|
+
stored names; its `cli` array plus `version` is the [compatibility contract](https://github.com/xanots/sdk/blob/main/guides/cli.md#checking-what-an-installed-sdk-can-do) for tools that drive the CLI).
|
|
526
|
+
|
|
527
|
+
---
|
|
528
|
+
|
|
529
|
+
<div align="center">
|
|
530
|
+
|
|
531
|
+
**Write TypeScript. Run `xanosdk deploy`. See it live.**
|
|
532
|
+
|
|
533
|
+
[npm](https://www.npmjs.com/package/@xano/sdk) ·
|
|
534
|
+
[GitHub](https://github.com/xanots/sdk) ·
|
|
535
|
+
[Issues](https://github.com/xanots/sdk/issues) ·
|
|
536
|
+
[Changelog](CHANGELOG.md) ·
|
|
537
|
+
[`llms.txt`](llms.txt) — the agent-facing router, mapping the `llms/` topic files
|
|
538
|
+
|
|
539
|
+
Xano SDK is the official TypeScript SDK for [Xano](https://xano.com). MIT licensed.
|
|
540
|
+
|
|
541
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3add8b1a9765d984d1dba690507b52c785fb78991ea8b102e5e6b63cedb0fbdb
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CI_ENV_VARS,
|
|
3
|
+
codingAgentDetected,
|
|
4
|
+
isCI,
|
|
5
|
+
refreshAgentFiles
|
|
6
|
+
} from "./chunk-Q325JKYB.js";
|
|
7
|
+
import "./chunk-AHJWCYQO.js";
|
|
8
|
+
import "./chunk-DX4QR4B2.js";
|
|
9
|
+
import "./chunk-6QXLMMT3.js";
|
|
10
|
+
import "./chunk-ZFDZKNGG.js";
|
|
11
|
+
import "./chunk-FWD7AL6N.js";
|
|
12
|
+
import "./chunk-2GNFDZA2.js";
|
|
13
|
+
import "./chunk-JTUKLCXS.js";
|
|
14
|
+
import "./chunk-4KHEMC32.js";
|
|
15
|
+
import "./chunk-WRBKLYSJ.js";
|
|
16
|
+
import "./chunk-3LDULPRE.js";
|
|
17
|
+
import "./chunk-YLDALTWZ.js";
|
|
18
|
+
import "./chunk-LLNZGEFK.js";
|
|
19
|
+
import "./chunk-QXTKSOFI.js";
|
|
20
|
+
import "./chunk-X2NL4KUO.js";
|
|
21
|
+
import "./chunk-OPHB5ORL.js";
|
|
22
|
+
import "./chunk-UCQ2VUTG.js";
|
|
23
|
+
import "./chunk-DGWHAVRG.js";
|
|
24
|
+
import "./chunk-PTHVMXZI.js";
|
|
25
|
+
import "./chunk-UTI5G6OJ.js";
|
|
26
|
+
import "./chunk-2EZ3ZJZZ.js";
|
|
27
|
+
import "./chunk-5ZSO4T2G.js";
|
|
28
|
+
import "./chunk-TFFGOFVZ.js";
|
|
29
|
+
import "./chunk-OHX6MIUZ.js";
|
|
30
|
+
import "./chunk-36JUQZVQ.js";
|
|
31
|
+
import "./chunk-PZ5AY32C.js";
|
|
32
|
+
export {
|
|
33
|
+
CI_ENV_VARS,
|
|
34
|
+
codingAgentDetected,
|
|
35
|
+
isCI,
|
|
36
|
+
refreshAgentFiles
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=agent-file-refresh-ZEMK33AX.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {
|
|
2
|
+
deleteAnswer,
|
|
3
|
+
hasString,
|
|
4
|
+
isRecord,
|
|
5
|
+
listAnswer,
|
|
6
|
+
multidocAnswer,
|
|
7
|
+
notTheAnswer,
|
|
8
|
+
parseAnswer,
|
|
9
|
+
recordAnswer,
|
|
10
|
+
writeTransportFailure
|
|
11
|
+
} from "./chunk-6PBR37LN.js";
|
|
12
|
+
import "./chunk-YLDALTWZ.js";
|
|
13
|
+
import "./chunk-QXTKSOFI.js";
|
|
14
|
+
import "./chunk-X2NL4KUO.js";
|
|
15
|
+
import "./chunk-PTHVMXZI.js";
|
|
16
|
+
import "./chunk-UTI5G6OJ.js";
|
|
17
|
+
import "./chunk-2EZ3ZJZZ.js";
|
|
18
|
+
import "./chunk-5ZSO4T2G.js";
|
|
19
|
+
import "./chunk-TFFGOFVZ.js";
|
|
20
|
+
import "./chunk-36JUQZVQ.js";
|
|
21
|
+
import "./chunk-PZ5AY32C.js";
|
|
22
|
+
export {
|
|
23
|
+
deleteAnswer,
|
|
24
|
+
hasString,
|
|
25
|
+
isRecord,
|
|
26
|
+
listAnswer,
|
|
27
|
+
multidocAnswer,
|
|
28
|
+
notTheAnswer,
|
|
29
|
+
parseAnswer,
|
|
30
|
+
recordAnswer,
|
|
31
|
+
writeTransportFailure
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=answer-shape-K67TAAPY.js.map
|