@xano/sdk 1.0.5 → 1.0.7
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 +35 -5
- package/README.md +56 -20
- package/dist/.build-fingerprint +1 -1
- package/dist/{agent-file-refresh-KVLR7M5Y.js → agent-file-refresh-DGGSRPJ4.js} +15 -14
- package/dist/agent-skill-command-37DFYS7Q.js +414 -0
- package/dist/{answer-shape-XGR2DGWY.js → answer-shape-RBFDCNZ7.js} +5 -5
- package/dist/{backend-dir-IE4RMUFH.js → backend-dir-KDD43X7K.js} +16 -15
- package/dist/{backend-slot-6HBWG5FN.js → backend-slot-TBOVZXDE.js} +4 -4
- package/dist/bin.js +63 -61
- package/dist/{branch-T2APKPVG.js → branch-7PIKNUD7.js} +12 -11
- package/dist/{branch-commands-HXXTCSOO.js → branch-commands-EGY7ZEZE.js} +32 -32
- package/dist/bundle.js +9 -39
- package/dist/{capture-HBXFXZEW.js → capture-GW5KNKMB.js} +3 -3
- package/dist/{chunk-3BJYQGAZ.js → chunk-26LHXLD3.js} +2 -2
- package/dist/{chunk-N6BWB35H.js → chunk-2ACWDSAQ.js} +3 -3
- package/dist/{chunk-XIABDKFQ.js → chunk-2SD4LA22.js} +2 -2
- package/dist/{chunk-K6PRKPFX.js → chunk-2XWVZRL6.js} +7 -7
- package/dist/{chunk-ES5A66IH.js → chunk-2YER2J47.js} +13 -13
- package/dist/{chunk-G57RYMKB.js → chunk-3FRGNBOC.js} +2 -2
- package/dist/{chunk-BMCZQZMI.js → chunk-46PATL23.js} +13 -9
- package/dist/{chunk-MYLPOVX6.js → chunk-47XT6WQL.js} +8 -8
- package/dist/{chunk-AWQ7BQTQ.js → chunk-4GPIOIAC.js} +6 -1
- package/dist/{chunk-7GX445AE.js → chunk-4XHAT7C5.js} +2 -2
- package/dist/{chunk-QOLOQ35F.js → chunk-567KK6XF.js} +8 -8
- package/dist/{chunk-57HMNJGB.js → chunk-5GIOCDUM.js} +893 -922
- package/dist/{chunk-OKNE3TWU.js → chunk-5KJBWIDZ.js} +83 -5
- package/dist/{chunk-SRX6B544.js → chunk-5QMJOE2K.js} +5 -5
- package/dist/{chunk-AGD7F7YI.js → chunk-5SCPRXFB.js} +4 -4
- package/dist/{chunk-SNGFEESM.js → chunk-5ZG7V2VW.js} +3 -3
- package/dist/{chunk-XJU6UAFV.js → chunk-7FIMUFBP.js} +2 -2
- package/dist/{chunk-AESE434J.js → chunk-7M6JP3FS.js} +2 -2
- package/dist/{chunk-K6CB5TKM.js → chunk-7REDHC4N.js} +2 -2
- package/dist/chunk-7VR4IO5B.js +44 -0
- package/dist/{chunk-57B56I4B.js → chunk-7XXWKTCE.js} +65 -41
- package/dist/{chunk-PL7AIAWS.js → chunk-A4R5CAY4.js} +4 -111
- package/dist/{chunk-QZTJ2556.js → chunk-AKERAUNH.js} +4 -4
- package/dist/{chunk-JZWUAEMO.js → chunk-ARWMVNDJ.js} +6 -3
- package/dist/{chunk-WYS6XVZ3.js → chunk-AVS4WPPY.js} +2 -2
- package/dist/{chunk-KUU7T4ZE.js → chunk-B2URJBC4.js} +18 -18
- package/dist/chunk-B3P25SDP.js +78 -0
- package/dist/chunk-BRANWM4U.js +853 -0
- package/dist/{chunk-BBPAXOU6.js → chunk-BSVQEKHO.js} +6 -6
- package/dist/{chunk-3WHWOKU4.js → chunk-BZ6WTG3E.js} +4 -4
- package/dist/{chunk-XNZURZ7T.js → chunk-CH23ONYG.js} +77 -6
- package/dist/{chunk-SQPIECXD.js → chunk-CJDPSCMX.js} +45 -5
- package/dist/{chunk-M7GJ6YUF.js → chunk-CNZASQPL.js} +16 -2
- package/dist/{chunk-44CWK6YC.js → chunk-CPN6WSBH.js} +4 -4
- package/dist/{chunk-L3BDO2BI.js → chunk-CT3J5JRZ.js} +7 -7
- package/dist/{chunk-3HOGFGKG.js → chunk-D3KEPRRN.js} +2 -2
- package/dist/{chunk-OGUMHW2X.js → chunk-D5OZRJ3T.js} +7 -7
- package/dist/{chunk-S5KQIFKJ.js → chunk-DG3APBUJ.js} +208 -112
- package/dist/chunk-DIWF7L33.js +995 -0
- package/dist/{chunk-WRBKLYSJ.js → chunk-DNBP4GJN.js} +4 -3
- package/dist/{chunk-LZDA6SVD.js → chunk-DXZTL7NA.js} +141 -91
- package/dist/{chunk-XMDDBEEM.js → chunk-E763QI3G.js} +2 -2
- package/dist/{chunk-3VX7VAQT.js → chunk-EF4MHLEW.js} +26 -9
- package/dist/{chunk-AGSCOISO.js → chunk-ELPQTDW6.js} +108 -100
- package/dist/{chunk-Q22BMRPF.js → chunk-EPFDY5JU.js} +2 -2
- package/dist/{chunk-7DBM6XHR.js → chunk-EU32BC5B.js} +8 -8
- package/dist/{chunk-Y76ERHLK.js → chunk-FDTET7FZ.js} +6 -6
- package/dist/{chunk-Z3SNX45M.js → chunk-FENA7K7C.js} +3 -3
- package/dist/{chunk-WOGJB2F6.js → chunk-FNLTFOUD.js} +4 -9
- package/dist/{chunk-FV55SRQU.js → chunk-FQ53GTII.js} +9 -9
- package/dist/{chunk-DEVGLLNZ.js → chunk-GHMLRFRX.js} +8 -8
- package/dist/{chunk-GMVW6ZZK.js → chunk-H2K4GFUS.js} +4 -4
- package/dist/{chunk-NUU76247.js → chunk-HTQWAQRW.js} +3 -3
- package/dist/{chunk-ROY4YAEQ.js → chunk-HU7F56VF.js} +22 -2
- package/dist/{chunk-RXCT3OCU.js → chunk-HZ6ADG3O.js} +47 -8
- package/dist/{chunk-Z2BRSQ6M.js → chunk-I6XRUU6U.js} +91 -64
- package/dist/chunk-IPNN2KRW.js +257 -0
- package/dist/{chunk-SF2B7MZK.js → chunk-IYXL5NYU.js} +259 -31
- package/dist/chunk-JI3BLXWQ.js +107 -0
- package/dist/{chunk-4DJTQ6W4.js → chunk-JIKGT7DO.js} +2 -1
- package/dist/{chunk-OVV2HXJ6.js → chunk-JOOKM7AH.js} +2 -2
- package/dist/{chunk-65SW2BA5.js → chunk-JOWY6HFL.js} +3 -3
- package/dist/{chunk-I5VEROXW.js → chunk-JX6N73H3.js} +2 -2
- package/dist/{chunk-5D6DGF3W.js → chunk-L472YIGG.js} +8 -8
- package/dist/{chunk-HLQH3AXB.js → chunk-L6HZ67P6.js} +2 -2
- package/dist/{chunk-TM5LRSBB.js → chunk-LBJA7IEM.js} +370 -45
- package/dist/chunk-LCOCRJ4K.js +116 -0
- package/dist/{chunk-DGWHAVRG.js → chunk-LJM5CIY4.js} +16 -1
- package/dist/{chunk-5RLAF6RL.js → chunk-M2C54ZBC.js} +4 -4
- package/dist/{chunk-U6DR6464.js → chunk-M3NEK3LT.js} +4 -4
- package/dist/{chunk-5XVBT6CQ.js → chunk-MBL7CXJ7.js} +2 -2
- package/dist/{chunk-5YBNXNKU.js → chunk-MFWF2NZJ.js} +12 -5
- package/dist/{chunk-TEBS7FE6.js → chunk-MYZRMSPM.js} +2 -2
- package/dist/{chunk-YSLMMR2U.js → chunk-N3YFCFCO.js} +14 -14
- package/dist/{chunk-OJPZEUPH.js → chunk-NDJAKSE7.js} +11 -8
- package/dist/{chunk-PIPIA7K7.js → chunk-NV37YGOV.js} +7 -7
- package/dist/{chunk-ZHGWR45B.js → chunk-O56DQKPL.js} +9 -9
- package/dist/{chunk-4QBGE3EO.js → chunk-ORGNLQN6.js} +6 -6
- package/dist/{chunk-NNB7VUCH.js → chunk-PEIBGH2V.js} +55 -31
- package/dist/{chunk-UJ6ZZJDD.js → chunk-PEX4QZVI.js} +2 -2
- package/dist/{chunk-LLS2WO2K.js → chunk-PV25BDCH.js} +5 -5
- package/dist/{chunk-F3557PVM.js → chunk-PY722CHR.js} +2 -2
- package/dist/{chunk-4GDEEY2U.js → chunk-QGIZLFAS.js} +4 -4
- package/dist/{chunk-YI76TURL.js → chunk-QRQ54LUI.js} +16 -14
- package/dist/{chunk-JQOX6HW4.js → chunk-RBU2YX22.js} +3 -3
- package/dist/{chunk-4NEBBKOP.js → chunk-RRMH7WMY.js} +7 -7
- package/dist/{chunk-HOOOOJJP.js → chunk-S46ODQRA.js} +2 -2
- package/dist/{chunk-37FBPMNE.js → chunk-S56YBYMN.js} +5 -2
- package/dist/{chunk-4QFBEKXI.js → chunk-SDGV76HF.js} +2 -2
- package/dist/{chunk-CV54PASI.js → chunk-SGK3PTTM.js} +312 -132
- package/dist/{chunk-S5TEJIGP.js → chunk-SKEG3V2V.js} +2 -2
- package/dist/{chunk-VZ22VUAS.js → chunk-SLGJIWCY.js} +3 -3
- package/dist/{chunk-JSEVKRVJ.js → chunk-T4LJ5UR2.js} +29 -7
- package/dist/{chunk-JXKO6JT7.js → chunk-TWVUYS63.js} +24 -24
- package/dist/{chunk-UIEFE6FU.js → chunk-U5M7T6CI.js} +7 -7
- package/dist/{chunk-Z4VN347O.js → chunk-UYFUIHH3.js} +2 -2
- package/dist/{chunk-Y6NO3DLQ.js → chunk-V7MBRUK6.js} +3 -3
- package/dist/chunk-VAGSKUWC.js +67 -0
- package/dist/{chunk-A4NNCI4O.js → chunk-VIJ5D3RC.js} +3 -3
- package/dist/{chunk-3IYVHVM6.js → chunk-VJFMUJWZ.js} +4 -4
- package/dist/{chunk-V4IBHDIY.js → chunk-VNDR2T35.js} +7 -7
- package/dist/chunk-WAVNUTMT.js +9 -0
- package/dist/{chunk-KQLACS4Q.js → chunk-WNCW2RNB.js} +4 -4
- package/dist/chunk-WUEPP5HD.js +111 -0
- package/dist/{chunk-IV446ZLJ.js → chunk-Y453TW6J.js} +2 -2
- package/dist/{local-engine-command-73NHWD6V.js → chunk-YCUDOF6Q.js} +22 -76
- package/dist/{chunk-CJ76PSJT.js → chunk-YH2JVJAO.js} +12 -12
- package/dist/{chunk-GPI3OWRE.js → chunk-YHB34BN6.js} +2 -1
- package/dist/{chunk-AMBEITWL.js → chunk-ZGLNHA7T.js} +7 -7
- package/dist/{chunk-NGAODDLX.js → chunk-ZJOAWRED.js} +8 -8
- package/dist/{chunk-TUEFTRC2.js → chunk-ZXRDD3Q2.js} +50 -27
- package/dist/cli.d.ts +40 -11
- package/dist/cli.js +60 -56
- package/dist/{codegen-command-L2OO6OTE.js → codegen-command-T7TC7PQO.js} +79 -72
- package/dist/codegen.d.ts +2 -2
- package/dist/codegen.js +2 -2
- package/dist/{commands-2E4JB3DB.js → commands-JDENTDJS.js} +3 -3
- package/dist/{completion-LPJIH5VQ.js → completion-YFD5OVJW.js} +9 -5
- package/dist/{config-QDCRKEWD.js → config-YJFUTRJW.js} +8 -8
- package/dist/{deploy-command-HJZNYCUY.js → deploy-command-OEVEE6UG.js} +65 -63
- package/dist/deploy-source-HYVZEYXV.js +83 -0
- package/dist/{dev-env-sync-GZ4QQJGV.js → dev-env-sync-EFDCJ6KU.js} +63 -61
- package/dist/{diagnostics-LSMGB4TY.js → diagnostics-OMN5Y2AH.js} +2 -2
- package/dist/{display-name-hint-AHCNH6TF.js → display-name-hint-SW3GB3V7.js} +14 -13
- package/dist/{emit-DqG6qddr.d.ts → emit-Dov_92kn.d.ts} +66 -20
- package/dist/env-example-refresh-WNSOH534.js +134 -0
- package/dist/{env-pull-command-Z4RLVEGJ.js → env-pull-command-UYEXMQ3P.js} +53 -52
- package/dist/{env-target-ZHQUS5BO.js → env-target-JBSLBKNX.js} +15 -14
- package/dist/{env-var-command-FKQ4VVQ6.js → env-var-command-BJNRAXNV.js} +51 -49
- package/dist/{ephemeral-L4KUOGEU.js → ephemeral-CEOGMIEA.js} +11 -10
- package/dist/{ephemeral-command-GRPFI3TD.js → ephemeral-command-IPSGBCS5.js} +70 -69
- package/dist/{ephemeral-state-VLYU2BXR.js → ephemeral-state-MTBASPRS.js} +13 -12
- package/dist/{generate-command-XNODJFDQ.js → generate-command-XQXODBS6.js} +96 -86
- package/dist/{gitignore-VWRSZX5F.js → gitignore-RUVCIZO4.js} +21 -20
- package/dist/{guards-OPSGB6LG.js → guards-KYEOCVHN.js} +6 -6
- package/dist/{impersonate-command-AEKIZHHK.js → impersonate-command-MA27O7S5.js} +46 -44
- package/dist/{import-PHSSFFLA.js → import-XKRFHABE.js} +5 -5
- package/dist/index.d.ts +14 -20
- package/dist/index.js +13 -13
- package/dist/init-command-6RDTCMAB.js +143 -0
- package/dist/{init-modules-SGSX7XEY.js → init-modules-DHTBOCQT.js} +10 -9
- package/dist/{init-web-6HX3YLQP.js → init-web-ELBXSXDL.js} +3 -3
- package/dist/internal.d.ts +5 -5
- package/dist/internal.js +47 -20
- package/dist/{io-TAF4WXYQ.js → io-PGTCBSIQ.js} +6 -4
- package/dist/{keep-data-merge-GUGF7MVZ.js → keep-data-merge-TDJOIAVT.js} +33 -34
- package/dist/{lambda-config-reconcile-65U6I4KU.js → lambda-config-reconcile-47X5C2E4.js} +6 -5
- package/dist/{landed-QA6PRTV2.js → landed-F7PCHGCK.js} +3 -3
- package/dist/{landing-record-FCAWLCZU.js → landing-record-TPPYFQAS.js} +26 -25
- package/dist/{live-diff-IM4W3ELT.js → live-diff-5E2BQWQ7.js} +9 -8
- package/dist/local-engine-choice-S6VHPJRU.js +81 -0
- package/dist/local-engine-command-4EZCGZ6M.js +85 -0
- package/dist/{local-engine-config-W3KB7RWM.js → local-engine-config-2EBL3QKA.js} +3 -2
- package/dist/{local-engine-deploy-Y4OAWL7K.js → local-engine-deploy-FOPNWU7X.js} +18 -16
- package/dist/local-engine-lookup-GM3E3NPP.js +43 -0
- package/dist/local-engine-mcp-bridge-QKZHUGW3.js +423 -0
- package/dist/local-engine-mcp-command-BFQVLXZC.js +181 -0
- package/dist/{local-engine-process-6YPJHKYM.js → local-engine-process-XUQPQENQ.js} +12 -9
- package/dist/{local-engine-state-OCW5YDD7.js → local-engine-state-JQPKGB65.js} +4 -3
- package/dist/{local-engine-update-check-X7TZGRFL.js → local-engine-update-check-S7UF6ZF5.js} +7 -6
- package/dist/{lock-WXXC3QHL.js → lock-HDCHD2ON.js} +4 -2
- package/dist/{lock-commands-PKDBNRSD.js → lock-commands-HJ6Y5QVS.js} +66 -64
- package/dist/{login-command-V4U4FA5G.js → login-command-JO55NZAS.js} +34 -33
- package/dist/{logout-command-TV3P545Z.js → logout-command-MPRIRSJA.js} +18 -17
- package/dist/{loop-VKHGQ6MP.js → loop-SUB6C2LK.js} +8 -9
- package/dist/{marketplace-command-LEFOAEAV.js → marketplace-command-BM6G257N.js} +90 -54
- package/dist/{marketplace-resolve-ME7O7JBJ.js → marketplace-resolve-AWH3RG57.js} +7 -6
- package/dist/{meta-client-TEEECA5W.js → meta-client-AOSWODQQ.js} +16 -15
- package/dist/{module-manifest-7YLGIRCY.js → module-manifest-GXI46PEF.js} +7 -4
- package/dist/node.d.ts +5 -5
- package/dist/node.js +68 -67
- package/dist/operation-outcome-4UKPXTNC.js +53 -0
- package/dist/{output-target-5FWX3NGZ.js → output-target-RAZ4KN5J.js} +22 -21
- package/dist/{package-manager-PRAHUSCN.js → package-manager-K762W7XT.js} +2 -2
- package/dist/{plan-disclosure-QGL5UYQR.js → plan-disclosure-JR52DWXN.js} +21 -21
- package/dist/{plugin-contributions-GNFTWDEB.js → plugin-contributions-E6XHLQWK.js} +6 -6
- package/dist/{plugin-prompt-VEQGMZ4T.js → plugin-prompt-IODX5EU6.js} +5 -5
- package/dist/{plugin-questions-BGRL23GO.js → plugin-questions-AAAJ7POP.js} +4 -4
- package/dist/plugin.d.ts +254 -10
- package/dist/{preflight-command-VKJKXRRI.js → preflight-command-7GKJBWOQ.js} +71 -70
- package/dist/{profile-command-P7A3BH26.js → profile-command-CM6J7E2M.js} +35 -34
- package/dist/{profile-pointer-HG7IXE4I.js → profile-pointer-KTYXL6FU.js} +5 -4
- package/dist/{project-dependency-Z4CKOCJI.js → project-dependency-OQ5575QQ.js} +11 -8
- package/dist/{project-sdk-JWZWGXXR.js → project-sdk-2ESHHZVL.js} +4 -4
- package/dist/promote-command-BDRPG6UU.js +147 -0
- package/dist/{prompt-SURZOUUW.js → prompt-MQPGU4ZI.js} +4 -4
- package/dist/{publish-command-HGAB3H4A.js → publish-command-IEMYZ7LF.js} +69 -67
- package/dist/pull-command-S5E2ABZ4.js +169 -0
- package/dist/{pull-superseded-TOT5S4QU.js → pull-superseded-E34BZVLH.js} +4 -4
- package/dist/{raw-where-EoWl5fqY.d.ts → raw-where-ZMLND6AG.d.ts} +20 -3
- package/dist/release-command-7F5TBKO2.js +151 -0
- package/dist/{release-ns-command-WOQE2BDQ.js → release-ns-command-EK2ZQ4CC.js} +101 -100
- package/dist/{retry-command-JRGMZZAC.js → retry-command-GL5HCMVB.js} +10 -9
- package/dist/{routes-manifest-URFMAWJE.js → routes-manifest-YR4ZIMLM.js} +15 -7
- package/dist/routes-manifest-file-LCIKPDAG.js +41 -0
- package/dist/scaffold.js +4 -4
- package/dist/secrets-IV4N5HYI.js +20 -0
- package/dist/{secrets-file-YWZWVJ52.js → secrets-file-LXREYU3M.js} +21 -20
- package/dist/{secrets-fill-command-HIHK3VH2.js → secrets-fill-command-QHZS3KWM.js} +64 -62
- package/dist/{seed-24DTEY5S.js → seed-FRKMDN2Z.js} +9 -9
- package/dist/{source-resolve-OWD3MIEO.js → source-resolve-BBHYTOXI.js} +26 -24
- package/dist/{static-host-UIR2OLPQ.js → static-host-7LC7OZR4.js} +5 -5
- package/dist/{status-command-JKTHH5QE.js → status-command-TY253MJT.js} +54 -52
- package/dist/{store-zxw2go0f.d.ts → store-Boba9OOh.d.ts} +2 -2
- package/dist/{store-5YAQS6KU.js → store-VJ3OS6VO.js} +8 -7
- package/dist/sync-baseline-DOV5AGIO.js +36 -0
- package/dist/{sync-contributions-RBB6JVOL.js → sync-contributions-63542VE4.js} +20 -12
- package/dist/sync-record-RGHK7EAL.js +43 -0
- package/dist/{table-MQFVYA4K.js → table-OAYGFGEN.js} +8 -8
- package/dist/{tables-command-5Q4BSUNO.js → tables-command-PZIVDAH3.js} +45 -43
- package/dist/{tenant-Q3LPVSSM.js → tenant-Y3II4VY3.js} +12 -11
- package/dist/{tenant-command-BFVU2PEX.js → tenant-command-G6XON7CF.js} +113 -107
- package/dist/{test-command-F4VUU4QR.js → test-command-3FZOX7O3.js} +44 -42
- package/dist/{tests-5ZSDFVIJ.js → tests-KF6N6BZ7.js} +6 -6
- package/dist/{token-TERSTNU4.js → token-DJJUW5HY.js} +14 -13
- package/dist/toolchain-hooks-7PWCFLSU.js +46 -0
- package/dist/{toolchain-modules-FD5ANV2U.js → toolchain-modules-OTNSKK52.js} +8 -5
- package/dist/toolchain-peers-KQ7TQ2AR.js +28 -0
- package/dist/tracked-backend-AJCGTO5Y.js +82 -0
- package/dist/{update-check-O4C2LCZH.js → update-check-4E5L6GAW.js} +61 -59
- package/dist/{upgrade-command-NVFWLMTA.js → upgrade-command-BXMSQN4C.js} +68 -64
- package/dist/{whoami-command-YKNTISIV.js → whoami-command-NLCCIEUM.js} +17 -16
- package/dist/{workspace-GGVGE2S5.js → workspace-PNMJOXE4.js} +5 -5
- package/dist/{workspace-binding-OS4ZOX4S.js → workspace-binding-J5GWDFRI.js} +16 -15
- package/dist/{workspace-command-GTUNVN7K.js → workspace-command-MHIIY352.js} +125 -93
- package/dist/{workspace-env-467C5KHM.js → workspace-env-LLRWCHSA.js} +17 -16
- package/dist/{workspace-export-3XTVGQVM.js → workspace-export-BIKAYHWJ.js} +5 -5
- package/dist/{writable-7SSWUQJ3.js → writable-UOTO4WWC.js} +4 -4
- package/dist/{xano-6RS5XQZE.js → xano-LCI7VWPS.js} +8 -8
- package/dist/{xanosdk-import-E3WSIYUE.js → xanosdk-import-S7A3CVBN.js} +8 -8
- package/dist/{xanosdk-project-KH5TZ2KI.js → xanosdk-project-J4VCFRHP.js} +18 -17
- package/guides/README.md +2 -2
- package/guides/cli.md +73 -4
- package/guides/codegen.md +23 -5
- package/guides/codes.md +8 -2
- package/guides/coverage.md +5 -0
- package/guides/deploying.md +80 -0
- package/guides/marketplace.md +21 -0
- package/guides/module-contract.md +80 -4
- package/guides/scaffold.md +61 -10
- package/guides/typed-frontend.md +37 -0
- package/llms/client.md +11 -1
- package/llms/filters.md +4 -0
- package/llms/kinds-core.md +1 -1
- package/llms/statements-data.md +3 -2
- package/llms/toolchain.md +12 -0
- package/llms-full.txt +34 -7
- package/llms.txt +3 -3
- package/manifest.json +63 -5
- package/package.json +5 -2
- package/skills/xano-backend/SKILL.md +119 -0
- package/dist/chunk-F6IKWAIU.js +0 -664
- package/dist/chunk-M6ZFSTIZ.js +0 -630
- package/dist/chunk-MEIJDRHU.js +0 -243
- package/dist/deploy-source-5COWTBOC.js +0 -81
- package/dist/env-example-refresh-DWQIOQYR.js +0 -127
- package/dist/init-command-TI3HCKXZ.js +0 -126
- package/dist/local-engine-choice-FPJAZSSD.js +0 -79
- package/dist/operation-outcome-GNDD35WL.js +0 -51
- package/dist/promote-command-KHTIK44I.js +0 -141
- package/dist/pull-command-EUEWBRXZ.js +0 -162
- package/dist/release-command-WOVQAMUY.js +0 -147
- package/dist/toolchain-hooks-QVUZ6HZ4.js +0 -96
- package/dist/tracked-backend-B4HTME4S.js +0 -80
package/guides/README.md
CHANGED
|
@@ -6,13 +6,13 @@ typed, so your editor's autocomplete is usually the faster lookup — tab-comple
|
|
|
6
6
|
|
|
7
7
|
| Guide | What's in it |
|
|
8
8
|
|---|---|
|
|
9
|
-
| [The scaffolded project](scaffold.md) | What `xanosdk init` writes, the two frontend presets, add-ons, SvelteKit rules |
|
|
9
|
+
| [The scaffolded project](scaffold.md) | What `xanosdk init` writes, the two frontend presets, no frontend, existing apps, add-ons, SvelteKit rules |
|
|
10
10
|
| [Project structure](project-structure.md) | How a `xano/` project is laid out, and why registration is explicit |
|
|
11
11
|
| [The marketplace](marketplace.md) | Finding add-ons, the two kinds of module, and the install/reinstall/remove lifecycle |
|
|
12
12
|
| [The module contract](module-contract.md) | Building an add-on: the manifest fields, the plugin types, every hook, and what is refused |
|
|
13
13
|
| [Object kinds](object-kinds.md) | Every authorable kind, and splitting a workspace across microservices |
|
|
14
14
|
| [Authoring reference](authoring.md) | Tables and fields, statements, values, inputs, middleware, request history |
|
|
15
|
-
| [CLI](cli.md) | Every command, shell completion, and what failures look like |
|
|
15
|
+
| [CLI](cli.md) | Every command, the agent skill, shell completion, and what failures look like |
|
|
16
16
|
| [Warning and error codes](codes.md) | Every code the CLI and the build emit, with what it means (generated) |
|
|
17
17
|
| [Signing in & deploying](deploying.md) | Auth, ephemerals, `--static`, releasing to production, `xanosdk preflight` |
|
|
18
18
|
| [Environment & identity](environment.md) | Every environment variable, and how `xano.lock` pins identity |
|
package/guides/cli.md
CHANGED
|
@@ -9,6 +9,8 @@ with `@xano/sdk` installed, run them as `npx xanosdk …`; anywhere else, `npx @
|
|
|
9
9
|
```bash
|
|
10
10
|
xanosdk init my-app # scaffold a full project (frontend/ + xano/)
|
|
11
11
|
xanosdk init my-app --framework svelte # SvelteKit instead of the default React
|
|
12
|
+
xanosdk init my-api --framework none # a new project with the backend only (no frontend/)
|
|
13
|
+
xanosdk init # inside an existing app: add xano/ and the xano:* scripts, no frontend (lists clashes and writes nothing; --force overwrites)
|
|
12
14
|
xanosdk init my-app --no-agents-md --no-install # skip AGENTS.md and npm install
|
|
13
15
|
xanosdk init my-app --theme zinc-blue --dark toggle --icons tabler # the look
|
|
14
16
|
xanosdk init my-app --marketplace @xano-sdk/auth,@xano-sdk/vector # install add-ons AND register them
|
|
@@ -62,6 +64,8 @@ xanosdk deploy ./xano/index.ts --local=~/Downloads/engine.tar.gz # override: r
|
|
|
62
64
|
XANOSDK_ENGINE_OVERRIDE=v0.1.8 npm run xano:deploy # the same override for every deploy in the shell
|
|
63
65
|
xanosdk local list # Xano Engines on this machine, marking the ones xanosdk started
|
|
64
66
|
xanosdk local token # print its meta API bearer: XANO_META_TOKEN=$(xanosdk local token)
|
|
67
|
+
xanosdk local mcp # how a coding agent connects to its MCP server (url, command, config); never the bearer
|
|
68
|
+
xanosdk local mcp --stdio # the bridge an agent's .mcp.json launches: follows restarts, brings the current bearer
|
|
65
69
|
xanosdk local stop <name> # stop one (--all: every one xanosdk started, and what a crashed one left running)
|
|
66
70
|
xanosdk local update # move this project's pinned engine to the latest (--version <v>: that one) and restart it — commit package.json
|
|
67
71
|
xanosdk local cache list # each cached engine version, its size, and the engines running on it
|
|
@@ -112,7 +116,7 @@ xanosdk ephemeral export <name> --format multidoc --path - # …stream
|
|
|
112
116
|
|
|
113
117
|
xanosdk workspace details # which workspace your token is scoped to (instance, id, name)
|
|
114
118
|
xanosdk workspace export --path ws.json # your REAL workspace as a JSON bundle (`--path -` streams to stdout)
|
|
115
|
-
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
|
|
119
|
+
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), and which side changed each since the last sync (`changedThere`/`changedHere`/`changedBoth`); exits 2 when anything declared differs or is missing
|
|
116
120
|
xanosdk workspace branch list # its branches, and which one is live
|
|
117
121
|
xanosdk workspace branch set-live staging # promote a branch (also the way back after --backup-branch)
|
|
118
122
|
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)
|
|
@@ -133,11 +137,14 @@ xanosdk logout # revoke the active profile and remo
|
|
|
133
137
|
xanosdk version # print the installed @xano/sdk version
|
|
134
138
|
xanosdk upgrade --check # is a newer @xano/sdk published? exits 7 if so, 0 if current
|
|
135
139
|
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)
|
|
140
|
+
xanosdk agent-skill install # put the xano-backend skill into each coding agent detected on this machine (--agent <id> to pick)
|
|
141
|
+
xanosdk agent-skill status # each copy: current, stale, edited or absent
|
|
142
|
+
xanosdk agent-skill uninstall # remove the copies install wrote (an edited copy is kept)
|
|
136
143
|
xanosdk help # grouped command reference (also the no-arg default)
|
|
137
144
|
xanosdk <command> --help # that command's usage, subcommands, and flags (`xanosdk deploy --help`)
|
|
138
145
|
xanosdk <noun> <verb> --help # scoped to one verb (`xanosdk workspace export --help`)
|
|
139
146
|
xanosdk <command> --json # force JSON on stdout (otherwise: whenever stdout isn't a terminal)
|
|
140
|
-
xanosdk <command> --no-refresh # don't refresh the managed
|
|
147
|
+
xanosdk <command> --no-refresh # don't refresh the managed blocks in AGENTS.md and the README (a build that writes nothing outside its output)
|
|
141
148
|
xanosdk completion zsh # shell completion script (also bash, fish) — see below
|
|
142
149
|
|
|
143
150
|
xanosdk preflight ./xano/index.ts # import into a live instance, diff each object back (needs auth + a throwaway tenant)
|
|
@@ -314,12 +321,74 @@ as `installed`. The install matches how this CLI is installed (`npm i -g` for a
|
|
|
314
321
|
project, `--save-prod` when `@xano/sdk` is in `dependencies`, as a scaffold puts it, else
|
|
315
322
|
`--save-dev`) — and for a project-local install it
|
|
316
323
|
then restores the `@xano/sdk` range your project was scaffolded with (npm rewrites it to a
|
|
317
|
-
caret) and restamps the managed
|
|
318
|
-
|
|
324
|
+
caret) and restamps the managed blocks in your
|
|
325
|
+
`AGENTS.md` and README so what they say matches the version you now have. Set `XANOSDK_INSTALL_MODE` to
|
|
319
326
|
`global` or `local` to override the detection. Run through `npx` (or `pnpm dlx`, `yarn dlx`, `bunx`)
|
|
320
327
|
outside a project, it installs nothing (`status: "not-installed"`): that copy is temporary,
|
|
321
328
|
and `npx @xano/sdk@latest` already runs the newest release.
|
|
322
329
|
|
|
330
|
+
## Adding the backend to an existing app
|
|
331
|
+
|
|
332
|
+
`init` decides what to write from its target directory. An empty or missing directory is a
|
|
333
|
+
**new** project: a full app, `react` unless `--framework` says otherwise, with a framework
|
|
334
|
+
prompt on a terminal whose choices include "No frontend" (`--framework none`, the backend
|
|
335
|
+
alone). Any other directory is an **existing** project: `init` writes `xano/` and merges the
|
|
336
|
+
`xano:*` scripts and the backend's dependencies into its `package.json`, with no prompt and no
|
|
337
|
+
frontend. [The scaffolded project](scaffold.md#no-frontend-and-existing-apps) lists exactly
|
|
338
|
+
what each mode writes and merges.
|
|
339
|
+
|
|
340
|
+
Each of these is a **clash**: an existing `xano/`, any other file `init` would write that is
|
|
341
|
+
already there, and a `xano:*` script the project defines with another command. `init` lists
|
|
342
|
+
every clash and writes nothing. `--force` lists what it would overwrite and asks first
|
|
343
|
+
(`--yes` answers without a terminal).
|
|
344
|
+
|
|
345
|
+
`--framework react` or `--framework svelte` is refused in an existing project, and the
|
|
346
|
+
frontend-only flags (`--theme`, `--radius`, `--dark`, `--font`, `--font-mono`,
|
|
347
|
+
`--font-heading`, `--icons`) are refused wherever no frontend is written, rather than
|
|
348
|
+
silently ignored. `init --from` follows the same two modes
|
|
349
|
+
([Pulling an existing workspace](codegen.md#running-it)).
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
xanosdk init --json # inside the app; then run the command in `next`
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
`init --json` reports `mode` (`new` or `existing`), `files` (every file it wrote or merged
|
|
356
|
+
into, relative to the project) and `next` (the command to run next: the install when one is
|
|
357
|
+
still needed, then `xano:deploy`).
|
|
358
|
+
|
|
359
|
+
## The agent skill
|
|
360
|
+
|
|
361
|
+
`xano-backend` is an agent skill for coding agents such as Claude Code, Codex and Cursor: it
|
|
362
|
+
tells the agent when to set up a Xano backend and hands it to `init`, then to the project's
|
|
363
|
+
`AGENTS.md` and `llms.txt`. It is not a `knowledge()` def; those are docs your workspace's own
|
|
364
|
+
AI agents read. The package ships it at `skills/xano-backend/SKILL.md`.
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
xanosdk agent-skill install # every coding agent detected on this machine
|
|
368
|
+
xanosdk agent-skill install --agent claude-code # …or name one (repeatable)
|
|
369
|
+
xanosdk agent-skill install --dry-run # report what would change, write nothing
|
|
370
|
+
xanosdk agent-skill status --json # each copy, as data
|
|
371
|
+
xanosdk agent-skill uninstall
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
It writes at most two copies. Claude Code reads `~/.claude/skills/xano-backend/SKILL.md`
|
|
375
|
+
(under `$CLAUDE_CONFIG_DIR` when that is set). Codex, Cursor, Copilot, Gemini CLI, Amp and
|
|
376
|
+
OpenCode read the shared `~/.agents/skills/xano-backend/SKILL.md`. An agent is detected by its
|
|
377
|
+
home config directory; `--agent` takes `claude-code`, `agents` (the shared directory),
|
|
378
|
+
`codex`, `cursor`, `copilot`, `gemini`, `amp` or `opencode` instead. When no agent is detected
|
|
379
|
+
and none is named, `install` refuses.
|
|
380
|
+
|
|
381
|
+
Each copy carries the SDK version and a digest. `status` reports a copy as **current**,
|
|
382
|
+
**stale** (an older version, unedited), **edited** (changed since it was installed) or
|
|
383
|
+
**absent**. `install` writes a missing or stale copy and leaves a current one unchanged; it
|
|
384
|
+
leaves an edited copy alone unless `--force`. `uninstall` removes only unedited copies. A
|
|
385
|
+
symlinked skill directory belongs to another installer, and neither command touches it.
|
|
386
|
+
Nothing prompts, so both run unattended; `--json` reports one entry per target.
|
|
387
|
+
|
|
388
|
+
The skill also installs without the CLI, from the public repository:
|
|
389
|
+
`npx skills add xano-sdk/sdk`, or in Claude Code `/plugin marketplace add xano-sdk/sdk`
|
|
390
|
+
followed by `/plugin install xano@xano-sdk`.
|
|
391
|
+
|
|
323
392
|
## Checking what an installed SDK can do
|
|
324
393
|
|
|
325
394
|
A tool that drives the CLI, such as an editor extension or a CI step, should check that the
|
package/guides/codegen.md
CHANGED
|
@@ -18,10 +18,27 @@ xanosdk init my-app --from ./ws.json # a bundle already on disk — off
|
|
|
18
18
|
`workspace`, `ephemeral[:<name>]`, `local[:<name>]`, `tenant:<name>`, `release:<name>` —
|
|
19
19
|
or a bundle path. Unlike most commands it has no default: a pull names its source.
|
|
20
20
|
|
|
21
|
-
Everything else about the project is unchanged: `--framework`,
|
|
22
|
-
`--web` mean the same thing here as they do without `--from`.
|
|
23
|
-
the pull itself — `--report`, `--skip-roundtrip` and `--branch` —
|
|
24
|
-
than silently ignored.
|
|
21
|
+
Everything else about the project is unchanged: `--framework` (`react`, `svelte` or `none`), the
|
|
22
|
+
theme flags, `--no-agents-md` and `--web` mean the same thing here as they do without `--from`.
|
|
23
|
+
The three flags that describe the pull itself — `--report`, `--skip-roundtrip` and `--branch` —
|
|
24
|
+
are refused without it rather than silently ignored.
|
|
25
|
+
|
|
26
|
+
The target directory decides what is written around `xano/`, as it does for a plain
|
|
27
|
+
[`init`](scaffold.md#no-frontend-and-existing-apps):
|
|
28
|
+
|
|
29
|
+
- **Empty or missing:** a new project, with the frontend `--framework` names (`none` for the
|
|
30
|
+
backend alone).
|
|
31
|
+
- **A previous pull** (`xano/.xanosdk-codegen.json` is there): `xano/` is refreshed in place —
|
|
32
|
+
see [Verification, and the decode report](#verification-and-the-decode-report) below.
|
|
33
|
+
- **Anything else:** an existing app, which gets the backend only. The decoded `xano/` is
|
|
34
|
+
written, and the `xano:*` scripts and the backend's dependencies are merged into its
|
|
35
|
+
`package.json`. An existing `xano/`, a file the pull would write, or a `xano:*` script with
|
|
36
|
+
another command is a clash: all of them are listed and nothing is read or written unless
|
|
37
|
+
`--force`. `--framework react|svelte` and the frontend-only flags are refused.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
cd my-existing-app && npx @xano/sdk init --from workspace # add the pulled backend to this app
|
|
41
|
+
```
|
|
25
42
|
|
|
26
43
|
### Just the tree: `generate`
|
|
27
44
|
|
|
@@ -168,7 +185,8 @@ are listed), then updated from the new tree, so `export --check` passes after it
|
|
|
168
185
|
over a `xano/` no decode wrote follows the same rules.
|
|
169
186
|
|
|
170
187
|
> ⚠️ **`xano/` is your source once pulled — commit it.** A refresh overwrites the files it
|
|
171
|
-
> decodes, so commit before one (
|
|
188
|
+
> decodes, so commit before one (an existing `xano/` that isn't a previous pull is a clash, and
|
|
189
|
+
> needs `--force`).
|
|
172
190
|
> It carries schema only — no table rows or stored files.
|
|
173
191
|
> `xanosdk deploy` sends it to the Xano Engine on this machine (`--ephemeral`: a disposable
|
|
174
192
|
> ephemeral environment) as a *full replace*;
|
package/guides/codes.md
CHANGED
|
@@ -35,7 +35,7 @@ Printed as `! …` on stderr, and as `{ code, message }` in a `--json` document'
|
|
|
35
35
|
|
|
36
36
|
| Code | Meaning |
|
|
37
37
|
|---|---|
|
|
38
|
-
| `agents.refresh-failed` | A managed
|
|
38
|
+
| `agents.refresh-failed` | A managed block (AGENTS.md, the README's Built-with footer) could not be refreshed; the compile itself went on. |
|
|
39
39
|
| `agents.symlink` | … is a symlink — left it and its target untouched. |
|
|
40
40
|
| `branch.deletion` | … will be permanently deleted and CANNOT be recovered: |
|
|
41
41
|
| `branch.inventory-unknown` | The branch inventory could not be read, so what this wipe destroys is UNKNOWN. |
|
|
@@ -133,6 +133,7 @@ Printed as `! …` on stderr, and as `{ code, message }` in a `--json` document'
|
|
|
133
133
|
| `logout.revoke-failed` | Did not revoke …: … The token was not sent. |
|
|
134
134
|
| `logout.shared-file` | Clearing … in the shared credential file … — this affects every project that reuses it. |
|
|
135
135
|
| `logout.unreadable` | Could not read … (…). |
|
|
136
|
+
| `merge.symlink` | … is a symlink — left it and its target untouched. |
|
|
136
137
|
| `microservice.failed` | Some microservices failed to start: |
|
|
137
138
|
| `microservice.starting` | Microservices are still starting (…/… ready) — they should come up shortly: |
|
|
138
139
|
| `microservice.status-unreadable` | Could not read microservice status (the backend deployed fine): |
|
|
@@ -142,7 +143,9 @@ Printed as `! …` on stderr, and as `{ code, message }` in a `--json` document'
|
|
|
142
143
|
| `module.install-failed` | … failed — the module was not added. |
|
|
143
144
|
| `module.kind-unknown` | … does not declare a module kind we recognize, so it is read as an ordinary package. |
|
|
144
145
|
| `module.legacy-peer-deps` | Installed with --legacy-peer-deps: …. |
|
|
145
|
-
| `module.load-failed` | Could not load …/index.ts to
|
|
146
|
+
| `module.load-failed` | Could not load …/index.ts to … (…). |
|
|
147
|
+
| `module.peer-mismatch` | The project already declares a peer a toolchain module needs, and the installed version falls outside the module's range; it was left as it is. |
|
|
148
|
+
| `module.peer-not-added` | A peer a toolchain module needs could not be added as a direct dependency; the line names the command that adds it. |
|
|
146
149
|
| `module.peer-unresolved` | … declares a peer range this project does not satisfy; --legacy-peer-deps did not resolve it either. |
|
|
147
150
|
| `module.removed-from-marketplace` | … has been removed from the marketplace. |
|
|
148
151
|
| `module.sdk-skew` | … requires `@xano/sdk` … — the module was not added. |
|
|
@@ -224,6 +227,7 @@ Printed as `! …` on stderr, and as `{ code, message }` in a `--json` document'
|
|
|
224
227
|
| `release.seed-rows-not-decoded` | … carries seed rows for …, and a decoded tree carries no rows — they are not in …/. |
|
|
225
228
|
| `release.transfer-cancelled` | Transfer cancelled — nothing was imported. |
|
|
226
229
|
| `routes.cli-skew` | This CLI is another version than the project's installed SDK, so it left the route table for the installed CLI to render. |
|
|
230
|
+
| `routes.module-failed` | A toolchain module could not generate its section of `routes.gen.ts`; the rest was refreshed and its previous block, if any, was kept. |
|
|
227
231
|
| `routes.not-written` | The route table (`routes.gen.ts`) was not written this run; the line says why and what writes it. |
|
|
228
232
|
| `routes.realtime-unresolved` | …: leaving out … — … — whose canonical URL token resolves nowhere, along with their channels. |
|
|
229
233
|
| `secrets.cleartext-export` | … carries … in cleartext — written owner-only (0600); do not commit it. |
|
|
@@ -248,6 +252,7 @@ Printed as `! …` on stderr, and as `{ code, message }` in a `--json` document'
|
|
|
248
252
|
| `static.teardown-unknown` | Could not read …'s static hosting, so this cannot say whether a frontend serves there — this replace takes down any that does. |
|
|
249
253
|
| `static.unconfirmed-live` | Could not confirm the frontend is live within the wait window — the build uploaded and should come online shortly. |
|
|
250
254
|
| `static.upload-failed` | The static-host upload failed — the backend deploy stands: |
|
|
255
|
+
| `sync.record-failed` | The … succeeded, but its sync baseline could not be recorded in …: … |
|
|
251
256
|
| `tenant.deploy-partial` | The deploy stopped partway: … release "…" declares… — answered as a NOT NULL violation, though the release makes no field required: the value converts to nul… |
|
|
252
257
|
| `tenant.deploy-unconfirmed` | Compare its `deployedAt` and `deployedReleaseId` with what they were before this deploy (deployedAt …, deployedReleaseId …). |
|
|
253
258
|
| `tenant.identities-unchecked` | Whether this release's names and pinned public URL slugs are free on … was not checked — …. |
|
|
@@ -309,6 +314,7 @@ Raised while a workspace compiles (`export`, `deploy`, `release`, …). A warnin
|
|
|
309
314
|
| `field.email-default-invalid` | The `default` at … is …, which is not an email address — every insert or request that leaves the field out is refused "Invalid email format.". |
|
|
310
315
|
| `field.enum-default-not-a-value` | The `default` at … is …, which is not one of the enum's values (…) — a value no request can send back. |
|
|
311
316
|
| `field.input-default-invalid` | The `default` at … is …, which … — every request that leaves the input out is refused. |
|
|
317
|
+
| `field.input-required-default-ignored` | The `default` at …, input "…" is …, but the input is `required: true` — the engine refuses a request that leaves a required input out ("Missing param") befor… |
|
|
312
318
|
| `field.vector-not-nullable` | table "…", column "…" is a vector with `nullable: false` and no default — an empty default becomes NULL only on a nullable column, and `''` is not a vector,… |
|
|
313
319
|
| `function.reserved-input-name` | function "…": the input name `…` is reserved by the engine — a call passes its arguments keyed by input name, and the engine skips a `…` key when it evaluate… |
|
|
314
320
|
| `guard.role-unsatisfiable` | A guard.role on a table passed by name checks a column the table lacks, or a role its enum column cannot hold. |
|
package/guides/coverage.md
CHANGED
|
@@ -72,3 +72,8 @@ can learn the SDK without reading source:
|
|
|
72
72
|
Both derive from the SDK's own sources of truth (so they can't drift), regenerate with
|
|
73
73
|
`npm run manifest`, and are available at runtime via `buildManifest()` / `renderLlmsTxt()`,
|
|
74
74
|
both exported from `@xano/sdk/internal`.
|
|
75
|
+
|
|
76
|
+
The package also ships the `xano-backend` agent skill at `skills/xano-backend/SKILL.md`. It
|
|
77
|
+
carries no reference of its own: it tells a coding agent when to set up a Xano backend, runs it
|
|
78
|
+
through `init` and the first deploy, and hands it to the project's `AGENTS.md` and `llms.txt`.
|
|
79
|
+
Installing it is in the [CLI guide](cli.md#the-agent-skill).
|
package/guides/deploying.md
CHANGED
|
@@ -652,6 +652,34 @@ re-importing the backend. One command cannot serve it and refuses it by name: `r
|
|
|
652
652
|
| `xanosdk local cache list` | Each cached engine version, its size on disk, and the engines running on it. |
|
|
653
653
|
| `xanosdk local cache clear` | Removes every cached engine (`--version <v>`: just that one). An engine running on a removed version is stopped first; the next deploy fetches it again. |
|
|
654
654
|
|
|
655
|
+
#### Connecting a coding agent
|
|
656
|
+
|
|
657
|
+
The Xano Engine serves an MCP server for coding agents, and a local deploy prints where. It is
|
|
658
|
+
for looking at the deployed backend (objects, table schemas, rows, run history), seeding and
|
|
659
|
+
editing rows, and running functions, tasks, triggers, endpoints and tests by hand, each
|
|
660
|
+
answering its result and logs. It never changes a primitive: tables, endpoints, functions and
|
|
661
|
+
every other object change in `xano/` and ship with `xanosdk deploy`.
|
|
662
|
+
|
|
663
|
+
`xanosdk init` connects Claude Code (`.mcp.json`) and Cursor (`.cursor/mcp.json`) to it with one
|
|
664
|
+
server, `xano-local`, that launches a bridge:
|
|
665
|
+
|
|
666
|
+
```json
|
|
667
|
+
{ "mcpServers": { "xano-local": { "command": "npx", "args": ["--yes", "--package", "@xano/sdk", "xanosdk", "local", "mcp", "--stdio"] } } }
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
Nothing has to be started or installed by hand: the agent launches the server itself, using the
|
|
671
|
+
project's own `@xano/sdk` when it is installed and fetching it when it is not (a fresh clone opened
|
|
672
|
+
before `npm install`). The config holds no url and no token. The engine may come back on a new port after a restart and
|
|
673
|
+
always mints a new bearer, so the bridge looks both up when it needs them, and again when the
|
|
674
|
+
engine stops answering or refuses the bearer. Before the first deploy the server connects and
|
|
675
|
+
lists no tools; once an engine is up it tells the agent its tools changed. A call cut off after
|
|
676
|
+
it reached the engine is reported as unknown, never sent twice. `xanosdk local mcp` prints the
|
|
677
|
+
details and each agent's config line, and `init` in an existing project adds the server beside
|
|
678
|
+
the ones a config already declares. An engine too old to serve MCP says so on deploy, and
|
|
679
|
+
`xanosdk local update` moves the project to one that does. Claude Code asks once before it
|
|
680
|
+
starts a project's server; a Cursor version that does not pick up the tool change needs the
|
|
681
|
+
`xano-local` server refreshed in its MCP settings after the first deploy.
|
|
682
|
+
|
|
655
683
|
#### A frontend on the Xano Engine, and server rendering
|
|
656
684
|
|
|
657
685
|
`xanosdk deploy <entry> --local --static <dir>` publishes a built frontend to the
|
|
@@ -1243,6 +1271,58 @@ object with the same key *and* the same identity, so a lock cannot pin a guid th
|
|
|
1243
1271
|
never had. If none of the lock's identities appear in the source, that is what pointing a
|
|
1244
1272
|
project at an unrelated backend looks like, and the pull is refused unless you pass `--yes`.
|
|
1245
1273
|
|
|
1274
|
+
### Which side changed: the sync baseline
|
|
1275
|
+
|
|
1276
|
+
When a workspace and this project differ, `workspace diff` also says **which side moved** since
|
|
1277
|
+
they last matched. Every command that makes them match records a baseline in `xano.lock`, under
|
|
1278
|
+
`synced`. A baseline is one content digest per object, kept per workspace and per branch. The
|
|
1279
|
+
commands that record one are `deploy --to workspace`, a verified `promote`, `pull workspace`
|
|
1280
|
+
and `init --from workspace`. Commit it with the rest of the lock.
|
|
1281
|
+
|
|
1282
|
+
```bash
|
|
1283
|
+
xanosdk workspace diff ./xano/index.ts --json
|
|
1284
|
+
```
|
|
1285
|
+
|
|
1286
|
+
```jsonc
|
|
1287
|
+
{
|
|
1288
|
+
"matched": false,
|
|
1289
|
+
"differing": ["query:GET list (apiGroup orders)", "table:order"],
|
|
1290
|
+
"baseline": { "at": "2026-10-05T13:36:31.000Z", "by": "pull" },
|
|
1291
|
+
"changedThere": ["query:GET list (apiGroup orders)"], // edited in Xano since the baseline
|
|
1292
|
+
"changedHere": ["table:order"], // edited in this project since
|
|
1293
|
+
"changedBoth": [], // edited on both sides: a conflict
|
|
1294
|
+
"unclassified": [] // differs, direction unknown
|
|
1295
|
+
}
|
|
1296
|
+
```
|
|
1297
|
+
|
|
1298
|
+
- `changedThere`: pull before you deploy, or the deploy overwrites that edit.
|
|
1299
|
+
- `changedHere`: deploy it.
|
|
1300
|
+
- `changedBoth`: reconcile by hand.
|
|
1301
|
+
- `unclassified`: the baseline cannot tell. The object has no baseline entry, both sides
|
|
1302
|
+
already differed when it was taken, or it is the workspace's own settings row, which is
|
|
1303
|
+
never digested. A changed slug also shows only here, because digests leave slugs out.
|
|
1304
|
+
|
|
1305
|
+
Additions and deletions are classified as well. The baseline keeps this project's objects apart
|
|
1306
|
+
from the rest of the branch, so an object the project never held (another source's, or a section
|
|
1307
|
+
a pull does not write into `xano/`) is never reported as deleted here; it shows up only when it
|
|
1308
|
+
changes in Xano. An object that is new in Xano counts as `changedThere` only when the baseline is
|
|
1309
|
+
**complete**: a pull, an `init --from`, a verified
|
|
1310
|
+
`promote` and a `--replace` record every object on the branch, and so does a merge deploy
|
|
1311
|
+
that read the branch first. With no baseline for the branch, `baseline` is `null` and the
|
|
1312
|
+
four lists are empty. A run that finds the branch exactly as recorded leaves the lock alone.
|
|
1313
|
+
|
|
1314
|
+
A few things to know about the baseline:
|
|
1315
|
+
|
|
1316
|
+
- It records what the branch holds after the sync, read back from the branch where the command
|
|
1317
|
+
can do so, so an object stored differently from how it compiles is not reported as changed in
|
|
1318
|
+
Xano. It is recorded whoever's objects landed (a `--bundle` from elsewhere, a release another
|
|
1319
|
+
project cut), because it describes the branch, not ownership.
|
|
1320
|
+
- A baseline taken by a different SDK version under an older digest scheme is set aside
|
|
1321
|
+
(`baseline: null`) and replaced by the next sync, rather than read as every object changed.
|
|
1322
|
+
- An SDK older than this feature drops `synced` when it rewrites `xano.lock`. Nothing breaks: the
|
|
1323
|
+
next sync records a new baseline.
|
|
1324
|
+
- On a merge conflict in `xano.lock`, keep either side's baseline for a branch, or delete it.
|
|
1325
|
+
|
|
1246
1326
|
### Deploying to a branch
|
|
1247
1327
|
|
|
1248
1328
|
`--branch <label>` stages on a Xano branch instead of the live one, which is the safer shape
|
package/guides/marketplace.md
CHANGED
|
@@ -169,6 +169,23 @@ that arrived some other way is configured by this run too: a plain `npm install`
|
|
|
169
169
|
pull request, a `git pull` that changed `package.json`. It also means nothing has to recover
|
|
170
170
|
a package name out of a `file:` or tarball specifier in order to configure it.
|
|
171
171
|
|
|
172
|
+
A **toolchain module** gets two more steps, and `reinstall` runs both as well. Its peers other
|
|
173
|
+
than `@xano/sdk` (`zod`, say) are added as direct dependencies through the project's package
|
|
174
|
+
manager: yarn never installs peers, and pnpm does not link them where `routes.gen.ts` can import
|
|
175
|
+
them. Then, when the project keeps a `routes.gen.ts` beside its entry, the file is regenerated,
|
|
176
|
+
so the module's section lands with the module rather than at the next `xano:routes`. Under
|
|
177
|
+
`--json`, `peers` lists the specs that were added (`["zod@^4.0.0"]`, or `[]`), and `routes` says
|
|
178
|
+
what happened to the file:
|
|
179
|
+
|
|
180
|
+
| `routes` | Meaning |
|
|
181
|
+
|---|---|
|
|
182
|
+
| `written` | Regenerated. |
|
|
183
|
+
| `unchanged` | Already up to date. |
|
|
184
|
+
| `absent` | The project has no `routes.gen.ts` to refresh. |
|
|
185
|
+
| `skipped` | It could not be regenerated here. The warning says why; run `npm run xano:routes`. |
|
|
186
|
+
|
|
187
|
+
`remove` reports `routes` the same way, for the file it regenerates without the removed module.
|
|
188
|
+
|
|
172
189
|
`init` takes the same names and resolves them the same way — `--marketplace auth` is
|
|
173
190
|
`@xano-sdk/auth`, and an unlisted name exits 8 before anything is written — so a project can be
|
|
174
191
|
scaffolded with its add-ons already installed and registered:
|
|
@@ -207,6 +224,10 @@ What happens then depends on whether the module predates the command:
|
|
|
207
224
|
| `install` re-run over a module already in `dependencies`, or `reinstall` | Refused and **left alone**, settings included, because deleting a module you already had over a version mismatch is not a repair. Upgrade the SDK, or `marketplace remove` it. |
|
|
208
225
|
| `init --marketplace` | Reported as a module that was not added and taken back off disk. The scaffold itself completes and works. |
|
|
209
226
|
|
|
227
|
+
A *different* installed module that is out of range does not stop the verb. `install`, `reinstall`
|
|
228
|
+
and `remove` skip it with a warning naming its range and the fix, and leave its settings and its
|
|
229
|
+
`routes.gen.ts` block exactly as they were. `export`, `deploy` and `preflight` still refuse it.
|
|
230
|
+
|
|
210
231
|
The point of undoing the install is that the alternative is worse: a module whose hooks were
|
|
211
232
|
built against a contract this SDK does not have registers and applies **nothing**, so
|
|
212
233
|
`Installed` would be followed by a project where every command that loads modules refuses it.
|
|
@@ -163,6 +163,7 @@ const plugin: ToolchainPlugin = {
|
|
|
163
163
|
answersFromConfig: (config) => ({ ... }),
|
|
164
164
|
onBundle: async (ctx) => ({ ... }),
|
|
165
165
|
onPreflight: async (ctx) => ({ ... }),
|
|
166
|
+
routesManifest: (ctx) => ({ imports: [...], source: "..." }),
|
|
166
167
|
};
|
|
167
168
|
|
|
168
169
|
export default plugin;
|
|
@@ -175,10 +176,11 @@ guessing which would run code the manifest did not describe.
|
|
|
175
176
|
Every hook is optional. A module that only adds a `.gitattributes` line declares
|
|
176
177
|
`contributes` alone.
|
|
177
178
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
179
|
+
Six hooks, and deliberately no more. The first five were designed from one example (a module
|
|
180
|
+
that renders the workspace to a committed tree) and cover exactly what it needed. The sixth,
|
|
181
|
+
`routesManifest`, was added when a second module, `@xano-sdk/zod`, brought a second real set
|
|
182
|
+
of requirements: writing into a file the SDK generates rather than a tree of its own. A hook
|
|
183
|
+
is added when a module needs it, not in anticipation.
|
|
182
184
|
|
|
183
185
|
## Questions
|
|
184
186
|
|
|
@@ -452,6 +454,78 @@ reason to blank.
|
|
|
452
454
|
A project whose plugins declare no `onPreflight` never pays for the engine's rendering at all,
|
|
453
455
|
so declaring the hook is what turns that fetch on.
|
|
454
456
|
|
|
457
|
+
## `routesManifest`
|
|
458
|
+
|
|
459
|
+
```ts
|
|
460
|
+
import type { ToolchainPlugin } from "@xano/sdk/plugin";
|
|
461
|
+
|
|
462
|
+
const plugin: ToolchainPlugin = {
|
|
463
|
+
kind: "toolchain",
|
|
464
|
+
routesManifest: (ctx) => ({
|
|
465
|
+
imports: [{ from: "zod", names: ["z"] }],
|
|
466
|
+
source: `export const ROUTE_SCHEMAS = ...;`,
|
|
467
|
+
}),
|
|
468
|
+
};
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
Your module's section of the route manifest, `xano/routes.gen.ts`. It runs wherever that file
|
|
472
|
+
is written: `xanosdk routes ./xano/index.ts --emit xano/routes.gen.ts` (the scaffold's
|
|
473
|
+
`xano:routes`), `pull`, `generate`, and the refresh `marketplace install`, `reinstall` and
|
|
474
|
+
`remove` make, so your block lands with your module.
|
|
475
|
+
|
|
476
|
+
| `RoutesManifestContext` | What it carries |
|
|
477
|
+
|---|---|
|
|
478
|
+
| `inputs` | Every endpoint's, channel's and message's request inputs, under the manifest's final keys (`routes`, `channels`, `messages`), in a fixed order. |
|
|
479
|
+
| `config` | Your block from the project's `package.json` `"xanosdk"` object. |
|
|
480
|
+
| `sdkVersion` | The running `@xano/sdk` version. |
|
|
481
|
+
|
|
482
|
+
`inputs` is a validator-neutral description (type `RouteInputs` in `@xano/sdk/plugin`, not
|
|
483
|
+
the generated map of the same name): each input's name, type, `required`, `nullable`, list
|
|
484
|
+
bounds, enum values, methods, and children. A database link is one `dbLink` entry carrying the
|
|
485
|
+
linked table's expanded `columns`, to spread into the surrounding object; `columns` is
|
|
486
|
+
`undefined` when the payload does not carry that table, which is not "no columns". Walk this
|
|
487
|
+
rather than the payload: it is the same description the SDK renders its own `RouteInputs`,
|
|
488
|
+
`ChannelInputs` and `MessageInputs` types from, so a validator built from it cannot disagree
|
|
489
|
+
with them.
|
|
490
|
+
|
|
491
|
+
**Where the section lands.** The SDK composes the file: the merged imports of every module at
|
|
492
|
+
the top, then the core sections, then each module's `source` in a marked block, blocks ordered
|
|
493
|
+
by package name:
|
|
494
|
+
|
|
495
|
+
```ts
|
|
496
|
+
// xanosdk:begin @xano-sdk/zod
|
|
497
|
+
// xanosdk:version 1.0.3 - generated; edits inside this block are overwritten
|
|
498
|
+
...
|
|
499
|
+
// xanosdk:end @xano-sdk/zod
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
Your source is in the same file as the core sections, so it names `RouteInputs`,
|
|
503
|
+
`ChannelInputs`, `MessageInputs` and `MessageName` directly, without importing them; all four
|
|
504
|
+
are always emitted, as `{}` when empty. Anything you export is exported from `routes.gen.ts`.
|
|
505
|
+
Your names share one scope with the core sections and every other module's, so a collision
|
|
506
|
+
fails the user's typecheck rather than being renamed. A blank `source` writes no block, and its
|
|
507
|
+
imports are dropped with it: that is how a config that turns the section off removes it.
|
|
508
|
+
|
|
509
|
+
**Imports are declared, never written.** The core sections import nothing, which is what keeps
|
|
510
|
+
the file free of the SDK runtime in a frontend bundle. Declare yours in `imports`; never put an
|
|
511
|
+
`import` line in `source`. Each `from` must be a bare package name: `@xano/sdk` and its
|
|
512
|
+
subpaths, a relative or absolute path, and a protocol (`node:`) are all refused, naming your
|
|
513
|
+
module. Each name must be a plain identifier, with no `as` rename. A package you import must
|
|
514
|
+
resolve from the user's project, so declare it in your `peerDependencies`:
|
|
515
|
+
`xanosdk marketplace install` adds each peer other than `@xano/sdk` that the project does not
|
|
516
|
+
already declare as a direct dependency, with your range, through the project's package manager.
|
|
517
|
+
|
|
518
|
+
**Synchronous and pure.** No filesystem, network, clock or randomness: the same context must
|
|
519
|
+
return the same section every time. Every writer of the file must produce the same bytes for
|
|
520
|
+
the same workspace and installed modules, or `routes --emit --strict` passes or fails depending
|
|
521
|
+
on which command last wrote it. A Promise, or any value that is not `{ imports?, source }`, is
|
|
522
|
+
refused, and `source` must not spell a block marker (`// xanosdk:begin`, `// xanosdk:end`).
|
|
523
|
+
|
|
524
|
+
**A throw is your module failing, not the manifest.** The core sections are still refreshed,
|
|
525
|
+
your previous block is kept exactly as it was, and a warning names your module. On
|
|
526
|
+
`routes --emit --strict` it is fatal instead, because a check that did not run must not read
|
|
527
|
+
as one that passed.
|
|
528
|
+
|
|
455
529
|
## `HookResult`: `failed` is not a throw
|
|
456
530
|
|
|
457
531
|
```ts
|
|
@@ -544,6 +618,8 @@ Things worth proving about your own module:
|
|
|
544
618
|
- Your `onBundle` writes nothing when `ctx.frozen` is true.
|
|
545
619
|
- Your `onBundle` handles `ctx.entry === undefined`.
|
|
546
620
|
- Your hooks never read `payload.env` values, because they are blanked.
|
|
621
|
+
- `routesManifest` returns the same section for the same context, called twice, and what it
|
|
622
|
+
writes typechecks beside the core sections of a real `routes.gen.ts`.
|
|
547
623
|
|
|
548
624
|
## Publishing
|
|
549
625
|
|
package/guides/scaffold.md
CHANGED
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
# The scaffolded project
|
|
2
2
|
|
|
3
|
-
What `xanosdk init` writes, the two frontend presets, theming, add-ons, and the SvelteKit prerendering rules.
|
|
3
|
+
What `xanosdk init` writes, the two frontend presets, a project with no frontend, adding the backend to an existing app, theming, add-ons, and the SvelteKit prerendering rules.
|
|
4
4
|
|
|
5
5
|
## init flags and add-ons
|
|
6
6
|
|
|
7
|
-
`init` flags: `--framework <react|svelte>` (default: `react`
|
|
7
|
+
`init` flags: `--framework <react|svelte|none>` (default: `react`; `none` writes the
|
|
8
|
+
backend alone — see [No frontend, and existing apps](#no-frontend-and-existing-apps)), `--name <name>`
|
|
8
9
|
(default: the folder name), `--theme <id>` / `--radius <len>` / `--dark <mode>` /
|
|
9
10
|
`--font <id>` / `--font-mono <id>` / `--font-heading <id>` / `--icons <id>`
|
|
10
11
|
(the look — see [Theming](#theming)), `--no-agents-md` (skip the `AGENTS.md`
|
|
11
12
|
agent brief, which every coding agent reads and `init` writes by default),
|
|
12
13
|
`--marketplace <pkg>` (repeatable, comma-separated; installs add-ons and
|
|
13
|
-
registers them — below), `--force` (
|
|
14
|
-
|
|
15
|
-
without a terminal — files it does not write are kept),
|
|
14
|
+
registers them — below), `--force` (write over what clashes when adding the backend to
|
|
15
|
+
a non-empty folder; it lists the files and scripts it would overwrite and asks, `--yes`
|
|
16
|
+
answering without a terminal — files it does not write are kept),
|
|
16
17
|
`--no-install` (skip `npm install`), `--web` (choose all of the above in a
|
|
17
18
|
browser instead — see [Choosing in a browser](#choosing-in-a-browser)),
|
|
18
19
|
`--from <source>` (fill `xano/` from an existing backend — any
|
|
19
20
|
[backend spelling](cli.md#naming-a-backend) or a bundle path — rather than the
|
|
20
21
|
starter — see [Pulling an existing workspace](codegen.md); over an existing `xano/` it lists
|
|
21
22
|
what it replaces and asks, and `--yes` answers without a terminal).
|
|
22
|
-
In a terminal, `init` prompts for the framework
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
In a terminal, `init` prompts for the framework in an empty or missing folder
|
|
24
|
+
(React, Svelte, or "No frontend"); the prompt has a default, so pressing enter is a
|
|
25
|
+
valid answer. A folder that already has files gets no prompt and no frontend. The look
|
|
26
|
+
is never prompted for — it comes from the flags above, or from `--web`.
|
|
25
27
|
The starter backend is empty but already compiles and deploys — grow it from the
|
|
26
28
|
walkthrough in `xano/EXAMPLE.md`.
|
|
27
29
|
|
|
@@ -113,10 +115,59 @@ project — the mistake npm answers by silently writing to the wrong `package.js
|
|
|
113
115
|
The package name is passed through exactly as typed, so version specifiers, tags,
|
|
114
116
|
and third-party packages all work.
|
|
115
117
|
|
|
118
|
+
## No frontend, and existing apps
|
|
119
|
+
|
|
120
|
+
`init` reads its target directory before it writes anything. An empty or missing directory
|
|
121
|
+
is a **new** project, and `--framework` decides its frontend. Any other directory is an
|
|
122
|
+
**existing** project, which has its own app and gets the backend only.
|
|
123
|
+
|
|
124
|
+
**A new project with `--framework none`** (or "No frontend" at the prompt) gets everything
|
|
125
|
+
above except the frontend: `xano/`, a `package.json` with only the backend's scripts and
|
|
126
|
+
dependencies, `.gitignore`, `.gitattributes`, the CI check, a README and `AGENTS.md`. There is
|
|
127
|
+
no `frontend/` and no root `tsconfig.json`; `xano/` type-checks under its own
|
|
128
|
+
`xano/tsconfig.json`, and `npm run xano:typecheck` checks it and its lambdas.
|
|
129
|
+
`xano:deploy:ephemeral` deploys the backend alone, and there is no `dev`, `build` or
|
|
130
|
+
`xano:deploy:frontend`.
|
|
131
|
+
|
|
132
|
+
**An existing project** (any non-empty directory) gets:
|
|
133
|
+
|
|
134
|
+
- `xano/`, the same starter a new project gets. When the project's `package.json` is not
|
|
135
|
+
`"type": "module"` (Next.js and `npm init -y` write one that is not), `init` also writes
|
|
136
|
+
`xano/package.json` holding only `{"type": "module"}`, so `xano/` loads as ES modules
|
|
137
|
+
without changing the project's own type.
|
|
138
|
+
- The `xano:*` scripts and the backend's dependencies merged into `package.json`. The
|
|
139
|
+
project's entries win: a dependency it already has keeps its range, a script it already
|
|
140
|
+
has keeps its command, and no other key changes (an add-on's settings under `"xanosdk"`
|
|
141
|
+
aside). The file keeps its indentation and line endings. A project with no
|
|
142
|
+
`package.json` gets one holding only what the backend needs.
|
|
143
|
+
- A marked block in `.gitignore` (created when missing) and in `AGENTS.md`, added or
|
|
144
|
+
refreshed in place; the rest of each file is left as it was. A symlinked `AGENTS.md` is left
|
|
145
|
+
alone, and `--no-agents-md` skips it.
|
|
146
|
+
- No frontend, README, CI workflow or root `tsconfig.json`. The line-ending rule goes in
|
|
147
|
+
`xano/.gitattributes`, scoped to `xano/`, so the project's own files are not renormalized.
|
|
148
|
+
|
|
149
|
+
What would be written over is a **clash**: an existing `xano/`, any other file `init` writes
|
|
150
|
+
that is already there, and a `xano:*` script the project defines with a different command (the
|
|
151
|
+
same command is no clash). `init` lists every clash and writes nothing; `--force` lists what it
|
|
152
|
+
overwrites and asks first. A `package.json` that is not valid JSON is refused, since there is
|
|
153
|
+
nothing to merge into.
|
|
154
|
+
|
|
155
|
+
`--framework react` or `--framework svelte` in a non-empty directory is refused, as are the
|
|
156
|
+
frontend-only flags (`--theme`, `--radius`, `--dark`, `--font`, `--font-mono`,
|
|
157
|
+
`--font-heading`, `--icons`) wherever no frontend is written. After the merge, `npm run
|
|
158
|
+
xano:deploy` runs the backend on the Xano Engine as it does in a new project.
|
|
159
|
+
|
|
160
|
+
If the project's own root `tsconfig.json` includes every `.ts` file (Next.js's does), add
|
|
161
|
+
`"xano/lambdas"` to its `exclude` before adding the first lambda: the lambda globals
|
|
162
|
+
type-check only under `xano/lambdas/tsconfig.json`. `init` leaves that file alone, and the
|
|
163
|
+
`AGENTS.md` it writes says the same.
|
|
164
|
+
|
|
116
165
|
## Git and CI
|
|
117
166
|
|
|
118
|
-
|
|
119
|
-
below the repository root, so moving it up never replaces another workflow).
|
|
167
|
+
A new project gets a `.gitattributes` and a `.github/workflows/check.yml` (`xanosdk-<dir>.yml`
|
|
168
|
+
below the repository root, so moving it up never replaces another workflow). An existing
|
|
169
|
+
project gets no workflow, and its line-ending rule is scoped to `xano/`; run
|
|
170
|
+
`npm run xano:check` from its own CI.
|
|
120
171
|
|
|
121
172
|
The attributes file normalizes line endings, so any generated artifact the project
|
|
122
173
|
commits is byte-identical on every checkout and a `--frozen-lock` check cannot fail
|
package/guides/typed-frontend.md
CHANGED
|
@@ -238,5 +238,42 @@ const ws = new WebSocket(socketUrl("chat", XANO_HOST), token);
|
|
|
238
238
|
ws.send(JSON.stringify({ action: "join", channel: channelPath("rooms/{room_id}", { room_id }) }));
|
|
239
239
|
```
|
|
240
240
|
|
|
241
|
+
**Request types come from the same file.** It exports four types-only maps, keyed exactly
|
|
242
|
+
like the runtime tables they sit beside, so a frontend types what it sends without importing a
|
|
243
|
+
def at all:
|
|
244
|
+
|
|
245
|
+
| Type | Keyed by | Holds |
|
|
246
|
+
|---|---|---|
|
|
247
|
+
| `RouteInputs` | the `ROUTES` key (`"POST listings"`, `"v1:GET vehicles"`) | the endpoint's inputs, path params included |
|
|
248
|
+
| `ChannelInputs` | the `CHANNELS` key (`"rooms/{room_id}"`) | the channel's path params |
|
|
249
|
+
| `MessageInputs` | `"<channel key> <message name>"` (`"rooms/{room_id} send"`) | the message's payload |
|
|
250
|
+
| `MessageName` | | every `MessageInputs` key |
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
import { ROUTES, routePath, type RouteInputs } from "../xano/routes.gen";
|
|
254
|
+
|
|
255
|
+
type NewListing = RouteInputs["POST listings"];
|
|
256
|
+
|
|
257
|
+
fetch(BASE + routePath("POST listings"), {
|
|
258
|
+
method: ROUTES["POST listings"].verb,
|
|
259
|
+
headers: { "content-type": "application/json" },
|
|
260
|
+
body: JSON.stringify({ title, price } satisfies NewListing),
|
|
261
|
+
});
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Each type agrees with `InferInput<typeof def>` for the same endpoint — required and optional
|
|
265
|
+
keys, `null`, enums, nested objects and lists — so code that already imports a def can keep
|
|
266
|
+
using `InferInput`. The one difference is a database-link input (`input.dbLink(table)`): the
|
|
267
|
+
manifest types it as the linked table's columns, which is what the server accepts, where
|
|
268
|
+
`InferInput` shows an opaque marker under the link's name. Responses are not in the manifest;
|
|
269
|
+
type them with `InferResponse` on an `import type` of the def.
|
|
270
|
+
|
|
271
|
+
These are types, so they add nothing to a bundle. For runtime validation, install
|
|
272
|
+
`@xano-sdk/zod` (`npx xanosdk marketplace install zod`): it writes `ROUTE_SCHEMAS`,
|
|
273
|
+
`CHANNEL_SCHEMAS` and `MESSAGE_SCHEMAS` into the same file under the same keys
|
|
274
|
+
(`ROUTE_SCHEMAS["POST listings"].parse(body)`), each checked against its type when you
|
|
275
|
+
typecheck, so a schema cannot drift from the type it validates. The file then imports `zod`,
|
|
276
|
+
and still never `@xano/sdk`.
|
|
277
|
+
|
|
241
278
|
Add `--strict` in CI to fail when the committed manifest is out of date. A hand-typed
|
|
242
279
|
`ROUTES` table is the option that gives up both the bundle saving and the rename safety.
|