@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/guides/cli.md
ADDED
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
# CLI
|
|
2
|
+
|
|
3
|
+
Every `xanosdk` command, shell completion, and what the CLI prints when something fails.
|
|
4
|
+
|
|
5
|
+
The examples spell the bare `xanosdk` of a global install (`npm i -g @xano/sdk`). In a project
|
|
6
|
+
with `@xano/sdk` installed, run them as `npx xanosdk …`; anywhere else, `npx @xano/sdk …` (see
|
|
7
|
+
[Commands the CLI prints](#commands-the-cli-prints)).
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
xanosdk init my-app # scaffold a full project (frontend/ + xano/)
|
|
11
|
+
xanosdk init my-app --framework svelte # SvelteKit instead of the default React
|
|
12
|
+
xanosdk init my-app --no-agents-md --no-install # skip AGENTS.md and npm install
|
|
13
|
+
xanosdk init my-app --theme zinc-blue --dark toggle --icons tabler # the look
|
|
14
|
+
xanosdk init my-app --marketplace @xano-sdk/auth,@xano-sdk/vector # install add-ons AND register them
|
|
15
|
+
|
|
16
|
+
xanosdk marketplace list # every published add-on (no login needed)
|
|
17
|
+
xanosdk marketplace search auth # narrow by keyword
|
|
18
|
+
xanosdk marketplace details @xano-sdk/auth # what it installs + the registration to copy
|
|
19
|
+
xanosdk marketplace details @xano-sdk/auth --prompt # …as a prompt for a coding agent
|
|
20
|
+
xanosdk marketplace install @xano-sdk/auth # add an add-on to the project you're in (and configure it)
|
|
21
|
+
xanosdk marketplace reinstall <toolchain-package> # re-ask a toolchain module its questions
|
|
22
|
+
xanosdk marketplace remove <toolchain-package> # uninstall it and drop what it contributed
|
|
23
|
+
|
|
24
|
+
xanosdk export ./xano/index.ts # bundle to stdout
|
|
25
|
+
xanosdk export ./xano/index.ts --out ws.json
|
|
26
|
+
xanosdk compile ./xano/functions/get-user.ts # a single function's JSON
|
|
27
|
+
xanosdk routes ./xano/index.ts # each query's verb + resolved api:<canonical>/<name> (`paths` is an alias)
|
|
28
|
+
|
|
29
|
+
xanosdk export ./xano/index.ts --strict # CI: fail the build on any warning, don't just print it
|
|
30
|
+
xanosdk export ./xano/index.ts --no-lock # build with no xano.lock (one is written by default; refused once one exists)
|
|
31
|
+
xanosdk export ./xano/index.ts --frozen-lock # CI guard: fail if the export would change the lock, or if the lock carries an entry no object matches
|
|
32
|
+
xanosdk export ./xano/index.ts --check --strict # the same guard, writing nothing (no bundle, no lock) — needs no .env or .secrets.json; the scaffold's xano:check
|
|
33
|
+
xanosdk lock rename --entry=xano/index.ts table users members # move a lock entry after renaming in code
|
|
34
|
+
xanosdk lock prune ./xano/index.ts --yes # drop lock entries nothing exports anymore
|
|
35
|
+
xanosdk lock prune --identity-only --entry=xano/index.ts --yes dbo:notes # …or drop named keys without running the workspace
|
|
36
|
+
xanosdk lock import live-export.json --entry=xano/index.ts --yes # seed the lock from a live engine export
|
|
37
|
+
|
|
38
|
+
xanosdk login # OAuth sign-in (once) — pick the instance + workspace at consent
|
|
39
|
+
xanosdk login --paste # …when the browser can't reach this machine's 127.0.0.1 (remote shell, container, Codespace)
|
|
40
|
+
xanosdk login --scope "<list>" # request these OAuth scopes instead of the built-in set
|
|
41
|
+
xanosdk login --profile staging # sign in as a second named credential, leaving the others alone
|
|
42
|
+
xanosdk <command> --profile staging # act as that profile for one run (-p is the short form)
|
|
43
|
+
xanosdk workspace details # which instance/workspace am I bound to, and via which credential?
|
|
44
|
+
xanosdk deploy ./xano/index.ts # compile + import into a live ephemeral (the dev loop) → URL
|
|
45
|
+
xanosdk deploy ./xano/index.ts --static ./frontend/dist # also deploy a static frontend (onto the ephemeral)
|
|
46
|
+
xanosdk deploy ./xano/index.ts --static ./frontend/dist --static-env PK=pk_live_1 # + extra public config
|
|
47
|
+
xanosdk deploy --bundle ws.json # deploy an already-exported bundle
|
|
48
|
+
xanosdk deploy ./xano/index.ts --open # …and open the deployed URL in your browser
|
|
49
|
+
xanosdk deploy ./xano/index.ts --expires-hours 8 # the ephemeral's TTL when this deploy creates it: 1–24 hours (default: 1)
|
|
50
|
+
xanosdk deploy ./xano/index.ts --keep-data --static ./frontend/dist --static-host docs # publish to a named static host — merge only: a replace deletes it, and a deploy creates only `default` (create `docs` in the dashboard first)
|
|
51
|
+
xanosdk deploy ./xano/index.ts --static ./frontend/dist --static-routing spa # override URL resolution, spa|multipage (inferred from the bundle; rarely needed)
|
|
52
|
+
xanosdk deploy ./xano/index.ts --keep-data # redeploy but keep table rows (merge instead of replace; seeds aren't re-written)
|
|
53
|
+
xanosdk env set STRIPE_KEY --to workspace --yes # set ONE env var on a running backend, value piped on stdin (no deploy; never printed)
|
|
54
|
+
xanosdk env unset STRIPE_KEY --to local-engine # clear one (--to workspace|ephemeral[:<name>]|local-engine[:<name>]|tenant:<name>, default: last deployed)
|
|
55
|
+
xanosdk publish ./frontend/dist # publish a built frontend alone — no compile, no backend import (default: last deployed)
|
|
56
|
+
xanosdk publish ./frontend/dist --to ephemeral # …after a local-engine deploy: publish does not reach a local engine
|
|
57
|
+
xanosdk deploy ./xano/index.ts --local-engine --static ./frontend/dist # the engine serves the build at http://<prefix>.localhost:<port>
|
|
58
|
+
xanosdk publish ./frontend/dist --to workspace --branch v2 --yes # …onto the workspace, refused unless branch v2 is live
|
|
59
|
+
xanosdk deploy ./xano/index.ts --local-engine # deploy to a local engine on this machine instead of an ephemeral (runs the version pinned in package.json)
|
|
60
|
+
xanosdk deploy ./xano/index.ts --local-engine=~/Downloads/engine.tar.gz # override: run this archive, URL or version (v0.1.8), never touching the pin
|
|
61
|
+
XANOSDK_LOCAL_ENGINE_OVERRIDE=v0.1.8 npm run xano:deploy:local-engine # the same override for every deploy in the shell
|
|
62
|
+
xanosdk local-engine list # local engines on this machine, marking the ones xanosdk started
|
|
63
|
+
xanosdk local-engine token # print its meta API bearer: XANO_META_TOKEN=$(xanosdk local-engine token)
|
|
64
|
+
xanosdk local-engine stop <name> # stop one (--all: every one xanosdk started, and what a crashed one left running)
|
|
65
|
+
xanosdk local-engine update # move this project's pinned engine to the latest (--version <v>: that one) and restart it — commit package.json
|
|
66
|
+
xanosdk local-engine cache list # each cached engine version, its size, and the engines running on it
|
|
67
|
+
xanosdk local-engine cache clear # remove every cached engine and its unpacked runtime (--version <v>: just that one); running ones are stopped first
|
|
68
|
+
xanosdk ephemeral list # list your ephemeral environments (--all-workspaces spans every workspace; --json: { ephemerals: [...] })
|
|
69
|
+
xanosdk ephemeral get <name> # base URL, state, and expiry for one (<name> = the tenant name, e.g. ewap-8wz9-9e13, NOT the display name — `ephemeral list` shows it in bold)
|
|
70
|
+
xanosdk ephemeral delete <name> --yes # destroy one
|
|
71
|
+
xanosdk tables # the last-deployed backend's tables: id, guid, name (for release create --seed)
|
|
72
|
+
xanosdk tables tenant:acme # …or name one
|
|
73
|
+
xanosdk test run-all # run the tests the last-deployed backend carries (exits 5 on a failure)
|
|
74
|
+
xanosdk test run-all --on local-engine # …or name one (--on ephemeral:<name>|tenant:<name>|workspace)
|
|
75
|
+
xanosdk test list # list the tests a backend carries, without running any
|
|
76
|
+
xanosdk test run-all --kind unit # only one family (unit|workflow; default: both) — also on test list
|
|
77
|
+
xanosdk test run-all --concurrency 4 # run 4 at once (default: 1); tests share the backend's database, so only when yours don't share state
|
|
78
|
+
xanosdk impersonate # open what this project last deployed to in the builder (--guest = read-only; --url-only prints the URL; the URL is a session — treat it as a credential)
|
|
79
|
+
xanosdk impersonate ephemeral:<tenant> # …or name one: local-engine[:<name>] or tenant:<name> (open your workspace from the Xano dashboard)
|
|
80
|
+
xanosdk deploy ./xano/index.ts --test # THE RELEASE FLOW, step 1: stand it up and run its tests
|
|
81
|
+
xanosdk release create v1 # …2: cut a release from the ephemeral this project last deployed to (after a local-engine deploy: --from ephemeral)
|
|
82
|
+
xanosdk release create v1 --from ephemeral:e4f2-9ab1 --description "what shipped" # …from a named source
|
|
83
|
+
xanosdk release create v1 --from workspace --branch staging # …or from a branch of your workspace (default: what it serves)
|
|
84
|
+
xanosdk release list # every release in this workspace, newest first, a description cut to one line (--json: { releases: [...] }, each with the origin show names)
|
|
85
|
+
xanosdk release show v1 # one release: when it was cut, from what (a cut from an environment records it in the description), what it carries
|
|
86
|
+
# --json origin: {kind:"branch",label} | {kind:"environment",name,type} | {kind:"copy",source:{host,workspaceId,release},from?:<branch or environment>} (transferred in) | null
|
|
87
|
+
xanosdk release export v1 # download it as a XanoScript multidoc (workspace block named "v1")
|
|
88
|
+
xanosdk release delete v1 --yes # remove one (a tenant may be running it — there is no undo)
|
|
89
|
+
xanosdk release transfer v1 --to-profile prod # copy a release to another workspace/instance, checked by content hash
|
|
90
|
+
xanosdk promote v1 # …3: land it in your workspace, as a new branch
|
|
91
|
+
xanosdk promote v1 --branch staging # …on a named branch instead of one named after the release (a taken label exits 2, SDK_BRANCH_TAKEN)
|
|
92
|
+
# (a label is letters, digits, _ . - and starts with a letter, digit or _; surrounding spaces are trimmed)
|
|
93
|
+
xanosdk tenant list # every tenant under this workspace (--json: { tenants: [...] })
|
|
94
|
+
xanosdk tenant get acme # base URL and state for one
|
|
95
|
+
xanosdk tenant deploy acme v1 # …or 3: land it on a customer tenant instead
|
|
96
|
+
xanosdk tenant delete acme --yes # destroy one (by its NAME — a display name fails with exit 8 and names the tenant it belongs to)
|
|
97
|
+
xanosdk pull release:v1 # refresh xano/ from a release: rewrites decoded files, keeps and names files you added, lists and confirms (also workspace, ephemeral[:<name>], local-engine, tenant:<name>)
|
|
98
|
+
xanosdk pull release:v1 --yes # …skip the confirmation and the dirty-tree refusal (CI)
|
|
99
|
+
xanosdk pull workspace --backend-dir ./backend # …when this project keeps its backend somewhere other than xano/ and nothing on disk says so (also on env pull)
|
|
100
|
+
xanosdk generate release:v1 --out ./backend # write ONLY the decoded xano/ tree, no project around it (any source above, or a bundle path; --force replaces the files an earlier generate wrote, asks first when that loses your edits (--yes answers), and keeps and lists any others)
|
|
101
|
+
xanosdk deploy ./xano/index.ts --to workspace --dry-run # ALTERNATIVE to the release flow: preview a merge of the local build
|
|
102
|
+
xanosdk deploy ./xano/index.ts --to workspace # …send it: add + update, never delete, never touch table data. Leaves no release to re-land
|
|
103
|
+
xanosdk deploy ./xano/index.ts --to workspace --prune # …also delete objects this project LANDED here and no longer defines (per xano.lock's `landed` record; commit it)
|
|
104
|
+
xanosdk deploy ./xano/index.ts --to workspace --branch staging # …land on a NEW branch instead of live (created; an existing label is refused, exit 2; stages LOGIC only — schema and workspace settings are shared, so not applied from a branch)
|
|
105
|
+
xanosdk deploy ./xano/index.ts --to workspace --branch staging --set-live # …and set it live the moment the import succeeds
|
|
106
|
+
xanosdk deploy ./xano/index.ts --to tenant:acme # …or merge into a customer tenant
|
|
107
|
+
xanosdk ephemeral export <name> # export a DEPLOYED ephemeral as a JSON bundle → .xano/exports/<name>.json
|
|
108
|
+
xanosdk ephemeral export <name> --format multidoc --name backend # …or as XanoScript → .xano/exports/backend.xs (--path picks elsewhere; a secret-bearing file git would commit is added to .gitignore)
|
|
109
|
+
xanosdk ephemeral export <name> --format multidoc --path - # …stream the multidoc to stdout (deploy first)
|
|
110
|
+
|
|
111
|
+
xanosdk workspace details # which workspace your token is scoped to (instance, id, name)
|
|
112
|
+
xanosdk workspace export --path ws.json # your REAL workspace as a JSON bundle (`--path -` streams to stdout)
|
|
113
|
+
xanosdk workspace diff ./xano/index.ts --branch staging # did my release land? which objects on the branch differ from your compile, are missing, or are unexpected (default: live); exits 2 when anything declared differs or is missing
|
|
114
|
+
xanosdk workspace branch list # its branches, and which one is live
|
|
115
|
+
xanosdk workspace branch set-live staging # promote a branch (also the way back after --backup-branch)
|
|
116
|
+
xanosdk workspace branch delete staging --yes # remove a non-live branch (a label padded with spaces is found by the trimmed one; one not there exits 0, alreadyGone; the live branch exits 2, SDK_BRANCH_LIVE)
|
|
117
|
+
xanosdk init my-app --from workspace # …or as a runnable project (the pull direction)
|
|
118
|
+
xanosdk init my-app --from ephemeral:<tenant> # same, from an ephemeral (the env is named inside the flag)
|
|
119
|
+
xanosdk init my-app --from ./ws.json # …or from a bundle already on disk (offline, no auth)
|
|
120
|
+
|
|
121
|
+
xanosdk status # who am I, which workspace, and the env this project last deployed to
|
|
122
|
+
xanosdk whoami # print the scoped user + instance base URL (pretty on a TTY, JSON when piped)
|
|
123
|
+
xanosdk profile list # every stored credential profile, with the default and the active one marked
|
|
124
|
+
xanosdk profile show [name] # what one profile addresses — never its token
|
|
125
|
+
xanosdk profile use <name> # pin THIS PROJECT to a profile (writes a committed xano.profile.json)
|
|
126
|
+
xanosdk profile set-default <name> # set the profile THIS MACHINE falls back to
|
|
127
|
+
xanosdk profile add <name> --instance <url> --workspace-id <n> # store a meta API token (prompts, or reads it piped on stdin; checked before storing)
|
|
128
|
+
xanosdk profile delete <name> # revoke that session and remove the profile (xano.profile.json is kept, as logout keeps it)
|
|
129
|
+
xanosdk logout # revoke the active profile and remove it (--all for every profile)
|
|
130
|
+
# Both ask first (--yes off a terminal) when the profile is the one xano.profile.json pins, or the default while others stay.
|
|
131
|
+
xanosdk version # print the installed @xano/sdk version
|
|
132
|
+
xanosdk upgrade --check # is a newer @xano/sdk published? exits 7 if so, 0 if current
|
|
133
|
+
xanosdk upgrade # install it: globally (npm i -g) for a global CLI; in a project, into the block that lists it (--save-prod or --save-dev)
|
|
134
|
+
xanosdk help # grouped command reference (also the no-arg default)
|
|
135
|
+
xanosdk <command> --help # that command's usage, subcommands, and flags (`xanosdk deploy --help`)
|
|
136
|
+
xanosdk <noun> <verb> --help # scoped to one verb (`xanosdk workspace export --help`)
|
|
137
|
+
xanosdk <command> --json # force JSON on stdout (otherwise: whenever stdout isn't a terminal)
|
|
138
|
+
xanosdk <command> --no-refresh # don't refresh the managed block in AGENTS.md (a build that writes nothing outside its output)
|
|
139
|
+
xanosdk completion zsh # shell completion script (also bash, fish) — see below
|
|
140
|
+
|
|
141
|
+
xanosdk preflight ./xano/index.ts # import into a live instance, diff each object back (needs auth + a throwaway tenant)
|
|
142
|
+
xanosdk preflight ./xano/index.ts --runtime # also run each deployed function on the engine
|
|
143
|
+
xanosdk preflight ./xano/index.ts --capture # write the fetched JSON as fixture candidates
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
The `marketplace` family has a guide of its own: [The marketplace](marketplace.md) for what
|
|
147
|
+
each verb does to a project, and [The module contract](module-contract.md) for writing an
|
|
148
|
+
add-on.
|
|
149
|
+
|
|
150
|
+
## Naming a backend
|
|
151
|
+
|
|
152
|
+
Every command that reads, writes or opens a running backend names it with one grammar:
|
|
153
|
+
|
|
154
|
+
| Spelling | What it is |
|
|
155
|
+
|---|---|
|
|
156
|
+
| `workspace` | Your real workspace — the one your login is scoped to |
|
|
157
|
+
| `ephemeral` / `ephemeral:<name>` | The ephemeral this project deployed to, or a named one — by its name (`e4f2-9ab1`, from `xanosdk ephemeral list`), not its display name |
|
|
158
|
+
| `local-engine` / `local-engine:<name>` | The engine this project deployed to, or a named one from `xanosdk local-engine list`. Needs no Xano account |
|
|
159
|
+
| `tenant:<name>` | A tenant on your instance |
|
|
160
|
+
| `release:<name>` | A stored release — where a command reads one (`deploy`, `pull`, `generate`, `init --from`) |
|
|
161
|
+
| a bundle path | Where a command takes a file (`deploy`, `generate`, `init --from`) |
|
|
162
|
+
|
|
163
|
+
The flag follows what the command does with it: **reads take `--from`** (`env pull`, `release
|
|
164
|
+
create`, `init`), **writes take `--to`** (`env set`, `env unset`, `publish`, `deploy`), `test`
|
|
165
|
+
takes **`--on`**, and a command whose subject IS the backend takes it positionally (`deploy`,
|
|
166
|
+
`pull`, `generate`, `tables`, `impersonate`).
|
|
167
|
+
|
|
168
|
+
**Leave it off and a command follows the backend this project last deployed to** — recorded
|
|
169
|
+
in `.xano/deployed.json` by an ephemeral or local-engine deploy, and never by a deploy to your
|
|
170
|
+
workspace or a tenant, so a bare command cannot reach something real unasked. With no record,
|
|
171
|
+
it falls back to the ephemeral recorded under your current credential, then to the engine
|
|
172
|
+
recorded for this directory, and otherwise refuses naming the flag, `xanosdk deploy` and
|
|
173
|
+
`xanosdk deploy --local-engine`.
|
|
174
|
+
`deploy` is the exception: bare, it compiles the project and stands it up on an ephemeral
|
|
175
|
+
unless `--to` or `--local-engine` says otherwise, so it writes that record rather than
|
|
176
|
+
reading it. `generate` and `init --from` need a backend named.
|
|
177
|
+
|
|
178
|
+
A command that cannot serve a backend refuses it, whether you typed it or it came from the
|
|
179
|
+
record, with the reason and the spellings it does take: `publish` refuses a local engine (no
|
|
180
|
+
static host — pass `--to ephemeral`), and so does `release create` (the cut runs on the
|
|
181
|
+
instance — pass `--from ephemeral`). A write to your workspace or a tenant confirms first,
|
|
182
|
+
or needs `--yes` off a terminal; an ephemeral or local engine never asks.
|
|
183
|
+
|
|
184
|
+
## Bundle key names vs. the names everything else uses
|
|
185
|
+
|
|
186
|
+
A bundle's `payload` arrays are keyed by the engine's **storage** name, which for five kinds
|
|
187
|
+
is not the name the SDK, the CLI, or a release plan uses for the same thing. Scripting against
|
|
188
|
+
a bundle means translating:
|
|
189
|
+
|
|
190
|
+
| You author / the plan reports | `payload` array |
|
|
191
|
+
|---|---|
|
|
192
|
+
| `table` | `payload.dbo` |
|
|
193
|
+
| `api_group` | `payload.app` |
|
|
194
|
+
| `agent` | `payload.toolset` |
|
|
195
|
+
| `mcp_server` | `payload.toolset` |
|
|
196
|
+
| `toolset` | `payload.tool` |
|
|
197
|
+
| `realtime_channel` | `payload.channel` |
|
|
198
|
+
| `realtime_message` | `payload.message` |
|
|
199
|
+
|
|
200
|
+
Everything else (`query`, `function`, `task`, `trigger`, `middleware`, `microservice`,
|
|
201
|
+
`addon`, `workflow_test`, `workspace`) is keyed the same on both sides.
|
|
202
|
+
|
|
203
|
+
Two traps worth naming. A release plan reports operations as `{"type": "table", …}` while the
|
|
204
|
+
bundle it came from stores that object under `payload.dbo` — so a table that released
|
|
205
|
+
correctly looks *missing* if you go looking for `payload.table`. And `agent` and `mcp_server`
|
|
206
|
+
both land in `payload.toolset`, while the kind actually named `toolset` lands in
|
|
207
|
+
`payload.tool`; matching on the word alone will pick the wrong array.
|
|
208
|
+
|
|
209
|
+
This is also the format `xanosdk lock import` reads, so both directions are user-facing.
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
**Build warnings, and `--strict`.** `export`/`deploy` print a warning (a `!` line) for the
|
|
213
|
+
shapes that ship clean and then do the wrong thing — a `bulk.update` zero-filling the columns
|
|
214
|
+
an item omits, an `ignoreEmpty` on an operand that's already empty, a `ref()` no `as` binds,
|
|
215
|
+
a filter name the engine can't resolve, a `s.switch` case that falls through into the next
|
|
216
|
+
one, a request-time timestamp filter on a `where` operand. Each stays a warning because each
|
|
217
|
+
has a legitimate use. Nothing fails on a message nobody reads, though, so pass `--strict` in CI and in
|
|
218
|
+
unattended agent builds: every warning becomes a hard failure and the exit code carries it —
|
|
219
|
+
the CLI's own too (an unsupplied documentation token or env name, a `xano.lock` entry that
|
|
220
|
+
matches no object), and a db step bound to no table (`table: null`), which a pulled tree may
|
|
221
|
+
carry and which does nothing when run. When a shape is meant — a fixture that pins a hazard on
|
|
222
|
+
purpose — `diagnostics: { allow: ["<code>"] }` on that def accepts that warning for it alone, and
|
|
223
|
+
`--strict` still fails everything else. Every def kind takes it, and it takes any warning code the
|
|
224
|
+
def raised (never an error); the advisory warnings name the form in their own message. Some lines are deliberately
|
|
225
|
+
exempt, because each describes a choice you made rather than a defect in the build: a `--no-lock`
|
|
226
|
+
build says so as information, and a bundle written to stdout that carries env values or a
|
|
227
|
+
documentation token says so on stderr — `--strict` passes both.
|
|
228
|
+
The programmatic equivalents are `emitBundle(app, { strict: true })` and
|
|
229
|
+
`app.export({ strict: true })`. The bundle bytes are identical either way.
|
|
230
|
+
|
|
231
|
+
**Warnings under `--json`.** Every `!` line a run prints on stderr is also in the `--json`
|
|
232
|
+
document it writes, on every command, as `warnings: [{ code, message }]`, and a failure
|
|
233
|
+
document carries the same list as `error.details.warnings`. `code` is stable and dotted, so
|
|
234
|
+
match on it rather than on the sentence. A build diagnostic keeps its own code
|
|
235
|
+
(`stack.env-undeclared`), and the export's own warnings take theirs (`workspace-env.undeclared`,
|
|
236
|
+
`workspace-env.unsupplied`, `lock.orphan`, `lock.dropped-entry`, `lock.ceded-canonical`,
|
|
237
|
+
`filter.unresolvable`, `doc-token.orphan`, `doc-token.cleared`, `doc-token.unsupplied`) — these, and only these, are
|
|
238
|
+
what `--strict` fails on. Every other code is a NOTICE about this run, and `--strict` passes it:
|
|
239
|
+
`secrets.cleartext-export`, `credential.readable-file`, `credential.unpinned-profile`,
|
|
240
|
+
`credential.shadowed-global`, `credential.env-overrides-pin`, `profile.local-shadows-pin`, `static-env.secret-like`, `publish.unbuilt-source`, and a code
|
|
241
|
+
dotted by area on each other line — among them `deploy.tenant-write`, `deploy.destructive`,
|
|
242
|
+
`plan.nothing-matched`, `plan.workspace-rename`, `plan.column-drop`, `release.no-env`,
|
|
243
|
+
`release.drift`, `promote.server-release`, `promote.seed-rows`, `pull.no-git`,
|
|
244
|
+
`pull.kept-files`, `pull.unverified`, `tenant.not-found`,
|
|
245
|
+
`release.not-found`. `message` is the line stderr printed, with any fix-up commands printed
|
|
246
|
+
under it (a lock orphan's `lock rename` / `lock prune`) appended one per line.
|
|
247
|
+
An export that fails its checks — `--strict` promoting a warning included, whichever
|
|
248
|
+
layer raised it — is `SDK_EXPORT_INVALID`, with its checks in `error.details.diagnostics` as
|
|
249
|
+
`{ severity, code, message }` and every warning the run printed beside them in
|
|
250
|
+
`error.details.warnings`.
|
|
251
|
+
|
|
252
|
+
**Naming the backend under `--json`.** Every document that names a backend — a write's
|
|
253
|
+
`destination`, a read's `kind`/`name` (`tables`, `test`), `status`, `ephemeral get`,
|
|
254
|
+
`workspace details`, `impersonate`, and each `tenant list`/`ephemeral list` row — also carries
|
|
255
|
+
`selector`, the spelling the next command's backend slot takes (`"ephemeral:e4f2-9ab1"`,
|
|
256
|
+
`"tenant:acme"`, `"local-engine:<name>"`, `"workspace"`; `ephemeral get|delete|export` and
|
|
257
|
+
`tenant get|deploy|delete` take it as well as the bare name), and `workspaceId`, the numeric workspace it acts on (for an ephemeral or tenant,
|
|
258
|
+
the workspace it lives under). The fields each command already had stay. `export --out --json`
|
|
259
|
+
carries `written: true`, as `export --check` carries `written: false`. `help --json` lists each
|
|
260
|
+
flag as `{ flag, summary, name, short?, arg?, values?, examples?, description }` — `flag` the spec
|
|
261
|
+
string, `values` its whole closed set, `examples` a few values of a flag that takes others too
|
|
262
|
+
(`--to tenant:<name>`, `--theme <url>`).
|
|
263
|
+
|
|
264
|
+
## Shell completion
|
|
265
|
+
|
|
266
|
+
`xanosdk completion <bash|zsh|fish>` prints a completion script covering every command, verb, flag,
|
|
267
|
+
and closed value set (`--on workspace|ephemeral|local-engine`, `--format json|multidoc`, `--icons lucide|tabler|phosphor`).
|
|
268
|
+
A flag's value completes as what it takes: its closed set, file names for a path (`--config`,
|
|
269
|
+
`--secrets-file`), directories for a directory (`--backend-dir`), stored profile names for
|
|
270
|
+
`--profile`/`--to-profile`, and nothing for a free-form value (`--name`, `--expires-hours`).
|
|
271
|
+
`xanosdk help <Tab>` completes command names, then verbs.
|
|
272
|
+
It is generated from the CLI's own command table, so it never drifts from what the CLI accepts — but it
|
|
273
|
+
is baked at generation time, so re-run it after upgrading.
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
# zsh
|
|
277
|
+
xanosdk completion zsh > "${fpath[1]}/_xanosdk" # then restart your shell
|
|
278
|
+
|
|
279
|
+
# bash
|
|
280
|
+
xanosdk completion bash > ~/.xanosdk-completion.bash
|
|
281
|
+
echo 'source ~/.xanosdk-completion.bash' >> ~/.bashrc
|
|
282
|
+
|
|
283
|
+
# fish
|
|
284
|
+
xanosdk completion fish > ~/.config/fish/completions/xanosdk.fish
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
After a command succeeds the CLI checks npm (at most once an hour, cached in
|
|
288
|
+
`~/.xanosdk/update-check.json`) and prints a one-line nudge to **stderr** when a newer
|
|
289
|
+
`@xano/sdk` is published — never to stdout, so piped bundles stay clean. The suggested
|
|
290
|
+
command adapts to how you installed it: `npm i -g @xano/sdk@latest` for a global install,
|
|
291
|
+
`xanosdk upgrade` when it's a project dependency (it keeps the SDK in the `package.json` block
|
|
292
|
+
that lists it and restores the scaffolded range, which a raw `npm i` would not). The check is best-effort and bounded (a slow or offline
|
|
293
|
+
registry never delays a command), and stays silent under CI or when stderr isn't a terminal.
|
|
294
|
+
Opt out with `XANOSDK_NO_UPDATE_CHECK=1` (or the conventional `NO_UPDATE_NOTIFIER=1`).
|
|
295
|
+
|
|
296
|
+
`xanosdk upgrade` is the same question asked on purpose, and it answers under all the
|
|
297
|
+
conditions the nudge stays quiet for — CI, a piped stderr, the opt-out variables — reading the
|
|
298
|
+
registry live rather than serving the hourly cache. `--check` reports without installing and
|
|
299
|
+
exits **7** when a newer version is published, **0** when you are current or ahead of the
|
|
300
|
+
latest published version (a local build; `status: "ahead"`, and a bare `upgrade` installs
|
|
301
|
+
nothing), so a pipeline can branch on it:
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
xanosdk upgrade --check || echo "an upgrade is waiting"
|
|
305
|
+
xanosdk upgrade --check | jq -r .latest # piped stdout is JSON already
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
A registry it cannot reach is an error (exit 1), never a quiet "you are up to date". Without
|
|
309
|
+
`--check` it installs the exact version the check found (never npm's `latest` tag, which npm
|
|
310
|
+
resolves from a cache that lags a fresh release) and reports the version it actually installed
|
|
311
|
+
as `installed`. The install matches how this CLI is installed (`npm i -g` for a global one; for a
|
|
312
|
+
project, `--save-prod` when `@xano/sdk` is in `dependencies`, as a scaffold puts it, else
|
|
313
|
+
`--save-dev`) — and for a project-local install it
|
|
314
|
+
then restores the `@xano/sdk` range your project was scaffolded with (npm rewrites it to a
|
|
315
|
+
caret) and restamps the managed block in your
|
|
316
|
+
agent files so the guidance matches the version you now have. Set `XANOSDK_INSTALL_MODE` to
|
|
317
|
+
`global` or `local` to override the detection. Run through `npx` (or `pnpm dlx`, `yarn dlx`, `bunx`)
|
|
318
|
+
outside a project, it installs nothing (`status: "not-installed"`): that copy is temporary,
|
|
319
|
+
and `npx @xano/sdk@latest` already runs the newest release.
|
|
320
|
+
|
|
321
|
+
## Checking what an installed SDK can do
|
|
322
|
+
|
|
323
|
+
A tool that drives the CLI, such as an editor extension or a CI step, should check that the
|
|
324
|
+
installed SDK has the commands it needs before it starts. **The compatibility contract is the
|
|
325
|
+
installed version plus the `cli` array in its `manifest.json`.** There is no capability
|
|
326
|
+
endpoint and no protocol number. The manifest is a file inside the package, so reading it
|
|
327
|
+
needs no sign-in and no network. It comes from the same registry that parses the
|
|
328
|
+
command line, so it cannot list a command the CLI does not accept.
|
|
329
|
+
|
|
330
|
+
Each `cli` entry carries a `command` (`"promote"`, `"release create"`, `"publish"`) and its
|
|
331
|
+
`flags`. Check for the commands and flags you will actually run:
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
M=node_modules/@xano/sdk/manifest.json
|
|
335
|
+
jq -r .version "$M" # e.g. 1.0.3
|
|
336
|
+
jq -e '.cli[] | select(.command=="promote")' "$M" >/dev/null # exit 0: present
|
|
337
|
+
jq -e '.cli[] | select(.command=="publish") | .flags[]
|
|
338
|
+
| select(.flag | startswith("--release"))' "$M" >/dev/null # a flag, not just the command
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
```ts
|
|
342
|
+
import manifest from "@xano/sdk/manifest.json" with { type: "json" };
|
|
343
|
+
const has = (cmd: string) => manifest.cli.some((c) => c.command === cmd);
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Read the manifest from the install whose `xanosdk` you will run: a project dependency and a
|
|
347
|
+
global install can be different versions.
|
|
348
|
+
|
|
349
|
+
- **Check each operation, not the whole feature.** A backend-only promotion needs `promote`,
|
|
350
|
+
and it should not be refused because `publish` is missing. Gate each command on its own entry.
|
|
351
|
+
- **When something is missing, name the command.** `This workflow needs \`xanosdk publish\`,
|
|
352
|
+
which the installed @xano/sdk (1.0.x) does not have. Run \`xanosdk upgrade\`.` is accurate. "This SDK has
|
|
353
|
+
no release support" is not, when `release create` and `promote` are right there.
|
|
354
|
+
- **The manifest describes the package, not the target.** Whether a particular workspace or
|
|
355
|
+
instance will accept an operation is decided when the command runs. The command's own
|
|
356
|
+
failure is the answer to that, not a check you make in advance.
|
|
357
|
+
|
|
358
|
+
## Commands the CLI prints
|
|
359
|
+
|
|
360
|
+
Every command the CLI prints for you to run next (a remedy, a rerun, a hint, `--help`) is spelled
|
|
361
|
+
for where it runs, in the text and in `--json` fields such as `rerun` alike: plain `xanosdk …` from a
|
|
362
|
+
global install; otherwise `npx xanosdk …` in a project with `@xano/sdk` installed, and
|
|
363
|
+
`npx @xano/sdk …` anywhere else (a `cd <dir> && …` is spelled for `<dir>`). Paths in it read from
|
|
364
|
+
where you typed — under `npm run`, the directory you ran npm in. Files it writes to disk (a
|
|
365
|
+
scaffold's README, `AGENTS.md`, `.env.example`) always say `npx xanosdk …`.
|
|
366
|
+
|
|
367
|
+
## When something fails
|
|
368
|
+
|
|
369
|
+
Failures are written for the person reading the terminal. A request the instance refused
|
|
370
|
+
prints the server's own sentence on one line (`deploy failed (403 Forbidden): Access denied
|
|
371
|
+
for this workspace.`) rather than the whole JSON envelope; a request that never arrived names
|
|
372
|
+
what it could not reach and why (`workspace list could not reach https://…: fetch failed
|
|
373
|
+
(ECONNRESET)`), and a request that timed out says so separately, because "slow" and
|
|
374
|
+
"unreachable" call for different next steps. Set `XANOSDK_DEBUG=1` to append the untouched
|
|
375
|
+
response body underneath — nothing is discarded, only folded away.
|
|
376
|
+
|
|
377
|
+
A malformed invocation fails before any work happens: a missing or misspelled entry file, an
|
|
378
|
+
argument the command has nowhere to put (`xanosdk export --lock xano.lock` — that flag takes
|
|
379
|
+
its value attached, as `--lock=xano.lock`), or a missing credential, each answered with the
|
|
380
|
+
command's usage block instead of a stack trace. `deploy` and `release` check that you are
|
|
381
|
+
signed in *before* compiling, so a lapsed session costs you a message, not a build.
|
|
382
|
+
|
|
383
|
+
Emitters that write to disk (and the programmatic CLI) are Node-only — import them from
|
|
384
|
+
`@xano/sdk/node`. The string emitters (`emit`, `emitBundle`) stay on the browser-safe
|
|
385
|
+
`@xano/sdk` entry.
|
|
386
|
+
|
|
387
|
+
```ts
|
|
388
|
+
import { emitBundle } from "@xano/sdk"; // pure string — browser-safe
|
|
389
|
+
import { writeBundle } from "@xano/sdk/node"; // writes a file — Node only
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
**Four entry points, and only the first is the authoring API.** `@xano/sdk` is what you
|
|
393
|
+
define a workspace with; `@xano/sdk/node` adds the filesystem half; `@xano/sdk/codegen`
|
|
394
|
+
is what a generated tree imports; and `@xano/sdk/internal` holds the compiler machinery —
|
|
395
|
+
the per-kind encoders, the kind and statement registries, the bundle serializer, the
|
|
396
|
+
`xano.lock` model. Nothing on `/internal` is needed to author anything, and it is kept off
|
|
397
|
+
the root so an agent scanning the package's exports sees the surface rather than the guts.
|
|
398
|
+
|
|
399
|
+
`emit`, `emitBundle` and the `@xano/sdk/node` writers run the same build-time checks, including seed validation of a literal
|
|
400
|
+
`seed: [...]` array. A **deferred** seed (a thunk, or `seedFile()`) needs an await or the
|
|
401
|
+
filesystem, so it is materialised and checked only by `xanosdk export` / `xanosdk deploy`.
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Pulling an existing workspace
|
|
2
|
+
|
|
3
|
+
What `xanosdk init --from` writes, how faithful the pull is, and how to read its report.
|
|
4
|
+
|
|
5
|
+
## Running it
|
|
6
|
+
|
|
7
|
+
A pull is `init` with `xano/` filled from an existing backend instead of the empty starter,
|
|
8
|
+
so it is the scaffold command with one extra flag:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
xanosdk init my-app --from workspace # your real workspace (the one your login is scoped to)
|
|
12
|
+
xanosdk init my-app --from ephemeral:my-env # a named ephemeral environment
|
|
13
|
+
xanosdk init my-app --from local-engine:<name> # a running local engine (`local-engine list`) — no login
|
|
14
|
+
xanosdk init my-app --from ./ws.json # a bundle already on disk — offline, no login
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`--from` takes any backend in [the CLI's one grammar](cli.md#naming-a-backend) —
|
|
18
|
+
`workspace`, `ephemeral[:<name>]`, `local-engine[:<name>]`, `tenant:<name>`, `release:<name>` —
|
|
19
|
+
or a bundle path. Unlike most commands it has no default: a pull names its source.
|
|
20
|
+
|
|
21
|
+
Everything else about the project is unchanged: `--framework`, the theme flags, `--no-agents-md` and
|
|
22
|
+
`--web` mean the same thing here as they do without `--from`. The three flags that describe
|
|
23
|
+
the pull itself — `--report`, `--skip-roundtrip` and `--branch` — are refused without it rather
|
|
24
|
+
than silently ignored.
|
|
25
|
+
|
|
26
|
+
### Just the tree: `generate`
|
|
27
|
+
|
|
28
|
+
`xanosdk generate <source>` writes the same decoded tree `init --from` puts in `xano/`, and nothing
|
|
29
|
+
else — no `package.json`, no frontend, no round-trip check. Use it to drop a backend into a repo
|
|
30
|
+
that already has its own shell, or to read one.
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
xanosdk generate workspace # → ./xano
|
|
34
|
+
xanosdk generate release:v1 --out ./backend # a stored release
|
|
35
|
+
xanosdk generate ephemeral:my-env # also tenant:<name>, local-engine[:<name>]
|
|
36
|
+
xanosdk generate ./ws.json # a bundle on disk — offline, no login
|
|
37
|
+
xanosdk generate workspace --branch staging # --branch applies to `workspace` only
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The output directory must be new, empty, or a tree an earlier decode wrote — `generate` and
|
|
41
|
+
`init --from` both leave `.xanosdk-codegen.json` in it, and that marker is the proof. Replacing a tree
|
|
42
|
+
needs `--force`, and keeps its `.env` and `.secrets.json`; a non-empty directory
|
|
43
|
+
without the marker, or the working directory itself, is refused even with `--force`. Env var names
|
|
44
|
+
land in `.env.example`; the values a bundle carries land in the tree's `.env` — owner-only and
|
|
45
|
+
gitignored, as `init --from` writes them — unless `--no-secrets` declines them, and an existing
|
|
46
|
+
`.env` is kept. `--json` names them under `env` (names only). `xano.lock` is reconciled the way `pull` does it:
|
|
47
|
+
an entry survives only when the source still carries an object with that name and identity, so
|
|
48
|
+
generating a different backend into a tree cannot carry its old identities forward.
|
|
49
|
+
|
|
50
|
+
### Pulling a branch
|
|
51
|
+
|
|
52
|
+
`--branch <label>` reads that branch instead of the live one:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
xanosdk init review-staging --from workspace --branch staging
|
|
56
|
+
xanosdk pull workspace --branch staging # refresh that tree from the same branch
|
|
57
|
+
xanosdk workspace export --branch staging --path - # the raw bundle, same selector
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Only logic differs. Tables and microservices are shared by every branch, so the schema in the
|
|
61
|
+
tree is the same one live has — a branch pull changes the APIs, functions and tasks around it.
|
|
62
|
+
|
|
63
|
+
Three things are refused rather than quietly worked around, because each would otherwise hand
|
|
64
|
+
back a plausible tree built from something other than what was asked for:
|
|
65
|
+
|
|
66
|
+
- **A label the workspace does not have**, answered with the labels it does have.
|
|
67
|
+
- **An instance too old to honor the selector.** Such an instance accepts the branch, ignores
|
|
68
|
+
it, and returns the live branch with a success status — so the SDK asks it about a branch
|
|
69
|
+
that cannot exist first, and refuses to read at all if it gets an archive back instead of a
|
|
70
|
+
refusal.
|
|
71
|
+
- **`--branch` on a source with no branches to choose between** — an ephemeral carries the
|
|
72
|
+
logic it was deployed with, and a bundle file is one archive already exported from one
|
|
73
|
+
branch. Re-export, or deploy from the branch you want, instead.
|
|
74
|
+
|
|
75
|
+
## The generated tree
|
|
76
|
+
|
|
77
|
+
Inside, `xano/` is shaped the way the workspace is: one directory per kind, with each
|
|
78
|
+
object under its parent — queries under the API group that owns them, triggers under
|
|
79
|
+
what they fire on. Each table gets its own `table/<name>.ts`, settings sit in `xano/workspace.ts`,
|
|
80
|
+
`_shared.ts` holds anything else referenced from more than one file, and `xano/README.md`
|
|
81
|
+
lists anything that did not translate cleanly.
|
|
82
|
+
Object identities (`guid`) are preserved, so cross-references stay intact. A statement
|
|
83
|
+
this SDK does not model yet round-trips verbatim rather than breaking the pull.
|
|
84
|
+
|
|
85
|
+
Pulled objects are authored the same way you would write them by hand — `table({...})`,
|
|
86
|
+
`query({...})`, `defineFunction({...})` — so the generated tree keeps its types. A pulled
|
|
87
|
+
table's columns still check on `fieldName`/`output`/`sortBy`, `InferInput<typeof q>` still
|
|
88
|
+
resolves a pulled query's payload, and a pulled agent still types `s.ai.agent.run`.
|
|
89
|
+
|
|
90
|
+
A pull states what the source workspace actually holds and leaves out what the SDK would
|
|
91
|
+
put back anyway. A table's `primary(id)` / `created_at` / `gin(xdo)` indexes are the
|
|
92
|
+
engine's standard set, so only the indexes someone created are listed. A trigger comes back
|
|
93
|
+
through the factory that built it (`tableTrigger`, `realtimeTrigger`, …) rather than a bare
|
|
94
|
+
`satisfies TriggerDef`, which keeps its typed stack handle; the two realtime types that bind
|
|
95
|
+
a def handle are the exception, since a stored trigger carries two guids with no way to know
|
|
96
|
+
they agree. And two objects that reference each other — a pair of tables joined both ways,
|
|
97
|
+
two functions that call each other — can't both be declared first, so the second reference
|
|
98
|
+
is a `{name, guid}` const hoisted to the top of the file (`const OrdersRef = {…}`) instead of
|
|
99
|
+
an import that would close a cycle. Only the guid is ever read, so it binds exactly.
|
|
100
|
+
|
|
101
|
+
`xano/README.md` also lists objects that were **already empty in the source** — an
|
|
102
|
+
endpoint someone created and never filled in pulls as a def with no `stack`, which looks
|
|
103
|
+
identical to a decode that gave up. The report is what tells the two apart.
|
|
104
|
+
|
|
105
|
+
A few options exist only so a pull can be *faithful*, and reading them in generated code
|
|
106
|
+
is the only time you should see them: `table: null` / `fn: null` (a statement whose target
|
|
107
|
+
was deleted or never bound), `merge` / `hidden` on a field, `paging: { enabled }` on a
|
|
108
|
+
query, `c.blank(tag)` (the editor's unconfigured value box — **not** a zero or an
|
|
109
|
+
empty collection; the engine reads `""` and `"0"` differently, so tidying one into the
|
|
110
|
+
other changes what the workspace stores), and `c.null("const:obj")` (the object-typed null
|
|
111
|
+
a `db.*` statement's `@meta` slot carries — different stored bytes from `c.obj(null)`,
|
|
112
|
+
which is the blank object, though both evaluate to null). They describe what the source workspace actually
|
|
113
|
+
stored — a pulled `table: null` is a defect to fix upstream, not a shape to copy — and
|
|
114
|
+
each carries that warning at the call site. A blank binding also reports, because a
|
|
115
|
+
statement wired to a table or function that no longer exists is worth seeing even though
|
|
116
|
+
it round-trips exactly.
|
|
117
|
+
|
|
118
|
+
## Verification, and the decode report
|
|
119
|
+
|
|
120
|
+
Then it checks its own work: the project it just wrote is loaded, exported, and diffed
|
|
121
|
+
against the workspace it came from. A mismatch names the object and fails the command
|
|
122
|
+
(`--skip-roundtrip` opts out). So "it compiled" and "it means the same thing" are separate
|
|
123
|
+
claims, and you get both.
|
|
124
|
+
|
|
125
|
+
A tree that passes gets its `xano/xano.lock` from that same export, so the lock is committed
|
|
126
|
+
with the first commit rather than written by the first deploy. As with a plain `init`, the
|
|
127
|
+
project is pinned in `xano.profile.json` to the profile the pull ran under. Under `--json` the
|
|
128
|
+
command answers with the project — `dir`, `name`, `pinnedProfile`, `lock`, `verified` — and
|
|
129
|
+
the findings under `report`.
|
|
130
|
+
|
|
131
|
+
The findings above are printed either way. Verification runs after decoding is finished,
|
|
132
|
+
so whether it passes, disagrees, or cannot run at all, the report describing the decode is
|
|
133
|
+
rendered first — and a tree that was written but does not re-export exits **2**, distinct
|
|
134
|
+
from the **1** you get when nothing was written at all. A tree that fails verification is
|
|
135
|
+
reported as unverified rather than ready, and the deploy next steps are withheld: the check
|
|
136
|
+
exists precisely because re-exporting that tree does not reproduce the workspace it came
|
|
137
|
+
from.
|
|
138
|
+
|
|
139
|
+
**A source that carries one object twice.** An export can repeat a stored object — the same
|
|
140
|
+
guid appearing on several records, differing only in generated editor ids. Those are merged
|
|
141
|
+
into one definition keeping the original guid, and the merge is reported as a notice, so a
|
|
142
|
+
tree holding fewer objects than the archive has records is explained rather than merely
|
|
143
|
+
smaller. Records that share a guid but genuinely differ are refused before anything is
|
|
144
|
+
written (exit **1**), naming both records and the fields they disagree on: one guid cannot
|
|
145
|
+
describe two objects, and renaming one or pinning a fresh guid would repoint every
|
|
146
|
+
reference that resolves through it.
|
|
147
|
+
|
|
148
|
+
**Reading the report.** It opens with a headline (`27 distinct issues across 424 findings;
|
|
149
|
+
3 need your attention`) and splits into three sections, most actionable first: *problems in
|
|
150
|
+
your workspace*, *things Xano SDK could not model*, and the things stated only so the output
|
|
151
|
+
is not ambiguous. That split is the question a reader actually has — a `raw()` passthrough
|
|
152
|
+
is ours to close, a lambda reading an unbound name is theirs to fix, and an empty object is
|
|
153
|
+
neither. Findings that repeat the same sentence across objects collapse to one line with a
|
|
154
|
+
count and a collapsed object list, and each names the generated file it landed in.
|
|
155
|
+
`--report full` prints every site instead; `--report json` prints the findings as data (piped
|
|
156
|
+
or under `--json`, as the `report` field of the command's one JSON document), and the same data is written into `xano/.xanosdk-codegen.json` on every pull, so parity is
|
|
157
|
+
trackable release over release and gateable in CI without scraping output.
|
|
158
|
+
|
|
159
|
+
Re-pulling is a real workflow: a second `init --from` into the same directory refreshes
|
|
160
|
+
`xano/` and leaves the rest of the project — your `package.json`, your `frontend/` —
|
|
161
|
+
exactly as you left it. No `--force` needed, because the tree carries a marker saying it
|
|
162
|
+
was decoded. It and `xanosdk pull` share one planner: before any write it lists the files it
|
|
163
|
+
will delete and the files it will rewrite — telling a file you edited since the last decode
|
|
164
|
+
from one only the source changed — refuses a `xano/` git reports as dirty, and asks; without
|
|
165
|
+
a terminal, `--yes` answers. It removes only files the previous decode wrote; one you added
|
|
166
|
+
beside them is kept and named. `xano.lock` is reconciled against the source (dropped entries
|
|
167
|
+
are listed), then updated from the new tree, so `export --check` passes after it. `--force`
|
|
168
|
+
over a `xano/` no decode wrote follows the same rules.
|
|
169
|
+
|
|
170
|
+
> ⚠️ **`xano/` is your source once pulled — commit it.** A refresh overwrites the files it
|
|
171
|
+
> decodes, so commit before one (a directory that isn't a previous pull still needs `--force`).
|
|
172
|
+
> It carries schema only — no table rows or stored files.
|
|
173
|
+
> `xanosdk deploy` sends it to a disposable ephemeral environment as a *full replace*;
|
|
174
|
+
> `xanosdk promote <release>` or `xanosdk deploy --to workspace` merges it into your real
|
|
175
|
+
> workspace. Workspace env vars are declared by name only — their values never enter the tree.
|
|
176
|
+
|
|
177
|
+
---
|