@xano/sdk 1.0.4 → 1.0.6
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 +32 -5
- package/README.md +250 -342
- package/dist/.build-fingerprint +1 -1
- package/dist/agent-file-refresh-67QIX45H.js +39 -0
- package/dist/{answer-shape-LVV2SVBK.js → answer-shape-UCDUKPAN.js} +6 -6
- package/dist/{backend-dir-WZADOK3L.js → backend-dir-3LIL6SCT.js} +16 -15
- package/dist/{backend-slot-NSCTWCUX.js → backend-slot-JREP27UD.js} +4 -4
- package/dist/bin.js +59 -58
- package/dist/{branch-ONWPJ4V6.js → branch-2IPHOAYS.js} +10 -10
- package/dist/{branch-commands-ZT2MJIRS.js → branch-commands-KTKAXBAN.js} +31 -32
- package/dist/bundle.js +9 -39
- package/dist/{capture-3JNUA6C2.js → capture-GW5KNKMB.js} +4 -4
- package/dist/{chunk-FPBGAT5D.js → chunk-26MOFAJT.js} +3 -3
- package/dist/{chunk-O7QOWS6M.js → chunk-2FLIJGBZ.js} +12 -12
- package/dist/{chunk-QAEQGT5I.js → chunk-2WBH5HUY.js} +7 -7
- package/dist/{chunk-37AHZ7JX.js → chunk-3BBIDW3Y.js} +6 -6
- package/dist/{chunk-DGWHAVRG.js → chunk-3EDSPMXN.js} +12 -1
- package/dist/{chunk-2AUV6NXK.js → chunk-3II44CUJ.js} +36 -36
- package/dist/{chunk-7GX445AE.js → chunk-4XHAT7C5.js} +2 -2
- package/dist/{chunk-OOXWYAA4.js → chunk-57A5ZKPO.js} +1 -1
- package/dist/{chunk-OOGXZL7Z.js → chunk-5KJBWIDZ.js} +84 -6
- package/dist/{chunk-5YL5OC2G.js → chunk-5QMJOE2K.js} +6 -6
- package/dist/{chunk-3H3EPMFY.js → chunk-5TVFLG3C.js} +2 -2
- package/dist/{chunk-WFMVKY7I.js → chunk-5YQV35C2.js} +9 -9
- package/dist/{chunk-NA3PXMEF.js → chunk-64WWE3EF.js} +1 -1
- package/dist/{chunk-FMOEVAGT.js → chunk-6X3MY2JP.js} +3 -3
- package/dist/{chunk-2LVTBPW2.js → chunk-6X6BJN6Y.js} +3 -3
- package/dist/{chunk-DYG5D3FD.js → chunk-763M6LX3.js} +16 -2
- package/dist/{chunk-EESV6NU2.js → chunk-7FIMUFBP.js} +2 -2
- package/dist/{chunk-CFSFBKHP.js → chunk-7GAIJW62.js} +2 -2
- package/dist/{chunk-6R7S775T.js → chunk-7REDHC4N.js} +2 -2
- package/dist/chunk-7VR4IO5B.js +44 -0
- package/dist/chunk-A7MRZ4GF.js +78 -0
- package/dist/{chunk-D5ZEAF4G.js → chunk-ATJ2W7DC.js} +81 -58
- package/dist/{chunk-BUJRS7XB.js → chunk-AVS4WPPY.js} +2 -2
- package/dist/{chunk-MEE5RZ6G.js → chunk-BL3AZ3AP.js} +2 -2
- package/dist/chunk-BTVUYHWV.js +111 -0
- package/dist/{chunk-T4DUFQ2S.js → chunk-CCU5CCRX.js} +5 -5
- package/dist/{chunk-5T2CTWTB.js → chunk-CHINR7WD.js} +6 -6
- package/dist/{chunk-VD32O6KZ.js → chunk-CJDPSCMX.js} +45 -5
- package/dist/{chunk-3HOGFGKG.js → chunk-D3KEPRRN.js} +2 -2
- package/dist/{chunk-SBR2WZXG.js → chunk-D7BUMOKU.js} +60 -53
- package/dist/{chunk-WRBKLYSJ.js → chunk-DNBP4GJN.js} +4 -3
- package/dist/{chunk-JTUKLCXS.js → chunk-DXUICABI.js} +1 -1
- package/dist/{chunk-XMDDBEEM.js → chunk-E763QI3G.js} +2 -2
- package/dist/{chunk-KTGRGWZW.js → chunk-EADVVTDK.js} +7 -7
- package/dist/{chunk-FJWZ5OVV.js → chunk-ENMBEXOP.js} +3 -3
- package/dist/{chunk-OPHB5ORL.js → chunk-EQFYOOO6.js} +171 -92
- package/dist/{chunk-WOGJB2F6.js → chunk-FNLTFOUD.js} +4 -9
- package/dist/{chunk-II747OWE.js → chunk-FQ53GTII.js} +10 -10
- package/dist/{chunk-JP7M7OU7.js → chunk-FU3VCE5A.js} +46 -27
- package/dist/{chunk-OGBMUST4.js → chunk-GHQ4BVI4.js} +14 -14
- package/dist/{chunk-45YPFB7B.js → chunk-GLY552SI.js} +84 -57
- package/dist/{chunk-QV3GXQRE.js → chunk-GOLFAEUV.js} +2 -2
- package/dist/{chunk-L2GLOJAO.js → chunk-GW5RHGOB.js} +22 -22
- package/dist/{chunk-A6QTTJUI.js → chunk-GWTFI3GA.js} +2 -2
- package/dist/{chunk-MCTIKRMN.js → chunk-GZHLCUZ6.js} +8 -8
- package/dist/{chunk-664LSWE5.js → chunk-HCG7NDIL.js} +4 -4
- package/dist/{chunk-7PMVIHB3.js → chunk-I3H3HCPY.js} +50 -29
- package/dist/{chunk-LIVN53UV.js → chunk-I3VHW6XM.js} +31 -31
- package/dist/{chunk-C4FHQA7R.js → chunk-IF4PEGVD.js} +8 -8
- package/dist/{chunk-WFG67AYS.js → chunk-IMELQ2I6.js} +3 -3
- package/dist/{chunk-3P3HXN76.js → chunk-ITC2R2OT.js} +11 -11
- package/dist/{chunk-W5ONYLOP.js → chunk-IXFJORNH.js} +4 -4
- package/dist/{chunk-HMLGM2MW.js → chunk-IYXL5NYU.js} +260 -32
- package/dist/{chunk-2B22WWKL.js → chunk-JFBRXRJD.js} +59 -35
- package/dist/chunk-JI3BLXWQ.js +107 -0
- package/dist/{chunk-4DJTQ6W4.js → chunk-JIKGT7DO.js} +2 -1
- package/dist/{chunk-O5V3YH5P.js → chunk-JRVQ7M7W.js} +8 -8
- package/dist/{chunk-4APOHK7Y.js → chunk-JXVJGF3Y.js} +2 -2
- package/dist/chunk-KPFS3RGM.js +257 -0
- package/dist/{chunk-PML67X22.js → chunk-LAOMN6QQ.js} +3 -3
- package/dist/{chunk-TTVAHCWP.js → chunk-LBJA7IEM.js} +370 -45
- package/dist/{chunk-KUTFFHUM.js → chunk-LD6ARK3A.js} +2 -2
- package/dist/{chunk-HUSH7LRI.js → chunk-LL7SGTRC.js} +36 -33
- package/dist/{chunk-I2BGYNHD.js → chunk-M5CSVB23.js} +7 -7
- package/dist/{chunk-UCQ2VUTG.js → chunk-M6ZFSTIZ.js} +2 -2
- package/dist/{chunk-MNVDVR3M.js → chunk-MBDFH7XB.js} +4 -4
- package/dist/{chunk-QXTKSOFI.js → chunk-MF4W6FHU.js} +1 -1
- package/dist/{chunk-RX3EMQGN.js → chunk-MFWF2NZJ.js} +12 -5
- package/dist/{chunk-SEUCZZCP.js → chunk-N5I37JFB.js} +3 -3
- package/dist/{chunk-IJ3SXSZM.js → chunk-ND43ZOS3.js} +6 -6
- package/dist/chunk-NDWVJ2QZ.js +67 -0
- package/dist/{chunk-E65QIWOO.js → chunk-NPODGBVJ.js} +4 -4
- package/dist/{chunk-CYB7UQA2.js → chunk-OIKLDDYC.js} +5 -5
- package/dist/{chunk-MLGI2SRQ.js → chunk-PFBXSVZF.js} +4 -4
- package/dist/{chunk-AM4FKL4J.js → chunk-PL7AIAWS.js} +12 -12
- package/dist/{chunk-S7E2AHV3.js → chunk-PMMHSX4H.js} +26 -9
- package/dist/{chunk-WL2DSNJV.js → chunk-Q22BMRPF.js} +2 -2
- package/dist/{chunk-3FN2BIGB.js → chunk-QJM5XZ4K.js} +6 -6
- package/dist/{chunk-EWCDPFW5.js → chunk-QXYMDARD.js} +4 -4
- package/dist/{chunk-MLPDSGJQ.js → chunk-QZEAANWP.js} +5 -5
- package/dist/{chunk-ESZ2FF57.js → chunk-RIN4YY34.js} +88 -74
- package/dist/{chunk-37FBPMNE.js → chunk-S56YBYMN.js} +5 -2
- package/dist/{chunk-CBYQ2ZN3.js → chunk-SKEG3V2V.js} +2 -2
- package/dist/{chunk-4PQHO74B.js → chunk-SLGJIWCY.js} +4 -4
- package/dist/{chunk-IVKRT476.js → chunk-SPITRSOF.js} +2 -2
- package/dist/{chunk-BUECLQXK.js → chunk-SPKA2LV6.js} +4 -4
- package/dist/{chunk-HHW5AWVD.js → chunk-SSITMX7I.js} +30 -30
- package/dist/{chunk-OPG4DYX2.js → chunk-T4LJ5UR2.js} +29 -7
- package/dist/{chunk-LXNQWHZM.js → chunk-TECTL2NU.js} +4 -4
- package/dist/{chunk-E6H5ZEV3.js → chunk-TTEIDD5Q.js} +3 -3
- package/dist/{chunk-6VBTPV2Y.js → chunk-U35MTOXQ.js} +3 -3
- package/dist/{chunk-UKUIUS3E.js → chunk-U6MTGB46.js} +5 -5
- package/dist/{chunk-Y2ZLKBM6.js → chunk-UD2Z7K6W.js} +4 -4
- package/dist/{chunk-IXUPUFCG.js → chunk-UIVMR7UK.js} +2 -2
- package/dist/{chunk-UDE5C2XN.js → chunk-VDHA5SSQ.js} +3 -3
- package/dist/{chunk-5W7DOMIU.js → chunk-VJFMUJWZ.js} +4 -4
- package/dist/{chunk-XNCP4KYO.js → chunk-VQPDATQT.js} +1 -1
- package/dist/{chunk-KCAL4QYP.js → chunk-VW4CWVYX.js} +4 -4
- package/dist/chunk-WAVNUTMT.js +9 -0
- package/dist/{chunk-DIG3NITC.js → chunk-WBH4KJWM.js} +3 -3
- package/dist/{chunk-HSEQYBDO.js → chunk-WZHLMU6T.js} +3 -3
- package/dist/{chunk-WYEQFD6A.js → chunk-XFBGXB7X.js} +173 -105
- package/dist/{chunk-UI4OPTYR.js → chunk-Y453TW6J.js} +2 -2
- package/dist/{chunk-LUTMOHOW.js → chunk-YGLMRH5U.js} +9 -9
- package/dist/{chunk-GPI3OWRE.js → chunk-YHB34BN6.js} +2 -1
- package/dist/{chunk-5WGVIXMD.js → chunk-YKP4ZKVO.js} +14 -10
- package/dist/{chunk-MN2PB6WB.js → chunk-YR2I5HGE.js} +3 -3
- package/dist/{chunk-ZG7E72VI.js → chunk-YYC2DZMG.js} +7 -7
- package/dist/{chunk-D64XUF5Q.js → chunk-YYLUBYXM.js} +16 -16
- package/dist/{chunk-VRVKNY4A.js → chunk-Z4ZGTCCD.js} +8 -8
- package/dist/{chunk-44B4V2LR.js → chunk-ZDP6GDAB.js} +142 -142
- package/dist/{chunk-ET5DSBAC.js → chunk-ZJSTUD6D.js} +8 -8
- package/dist/cli.d.ts +36 -26
- package/dist/cli.js +57 -56
- package/dist/{codegen-command-HTWIW56U.js → codegen-command-R5IASBFC.js} +78 -72
- package/dist/codegen.d.ts +2 -2
- package/dist/codegen.js +2 -2
- package/dist/{commands-CVFYC4GK.js → commands-H7CPMMHH.js} +3 -3
- package/dist/{completion-AUEQC4XJ.js → completion-W5ZAI6TN.js} +12 -12
- package/dist/{config-JU6OQC77.js → config-MZ5KG4EP.js} +5 -5
- package/dist/{deploy-command-5WTFHMBT.js → deploy-command-34T2LKQ5.js} +64 -63
- package/dist/deploy-source-YLQ7WMYR.js +82 -0
- package/dist/{dev-env-sync-X636HLMK.js → dev-env-sync-TMJTNU3U.js} +58 -57
- package/dist/{diagnostics-LSMGB4TY.js → diagnostics-OMN5Y2AH.js} +2 -2
- package/dist/{display-name-hint-DMORHANO.js → display-name-hint-ZJGFNJKQ.js} +12 -12
- package/dist/{emit-hOFbgzde.d.ts → emit-D125xxty.d.ts} +67 -21
- package/dist/env-example-refresh-CQP3ZMKM.js +133 -0
- package/dist/{env-pull-command-WZZ7RL2E.js → env-pull-command-UTG6IC2K.js} +53 -53
- package/dist/{env-target-PO3MOLH5.js → env-target-FZROWYFS.js} +14 -14
- package/dist/{env-var-command-YKTJZFJN.js → env-var-command-VYDBQJJW.js} +51 -50
- package/dist/{ephemeral-BMFY55BQ.js → ephemeral-BIE6FMJV.js} +10 -10
- package/dist/{ephemeral-command-VDSQCOYL.js → ephemeral-command-OZ26RGXF.js} +54 -54
- package/dist/{ephemeral-state-6TY4JIPA.js → ephemeral-state-SNZOX2YK.js} +12 -12
- package/dist/{generate-command-3NTNRQRS.js → generate-command-4HR7MR36.js} +87 -79
- package/dist/{gitignore-FWPEDX6C.js → gitignore-EWQBXNX2.js} +20 -19
- package/dist/{guards-EJU2ONAX.js → guards-KYEOCVHN.js} +7 -7
- package/dist/{hosted-file-PSHJB3HX.js → hosted-file-S7YUQAH6.js} +2 -2
- package/dist/{impersonate-command-QEJA72Q2.js → impersonate-command-WC7OGKUM.js} +44 -43
- package/dist/{import-TBTOTU52.js → import-7Z4GCCPO.js} +6 -6
- package/dist/index.d.ts +14 -20
- package/dist/index.js +14 -14
- package/dist/init-command-HAO3WXH3.js +128 -0
- package/dist/{init-modules-HZRQFRLE.js → init-modules-NSKD4ASY.js} +12 -11
- package/dist/{init-web-Y2PBNJTQ.js → init-web-MKFFOQUU.js} +3 -3
- package/dist/internal.d.ts +5 -5
- package/dist/internal.js +61 -35
- package/dist/{io-ZUKAGFVE.js → io-PGTCBSIQ.js} +7 -5
- package/dist/{keep-data-merge-X5LDDCI3.js → keep-data-merge-QR2TMKEO.js} +33 -34
- package/dist/{lambda-config-reconcile-OUZ4OYAB.js → lambda-config-reconcile-7FJXXV6V.js} +4 -4
- package/dist/{landed-6VO7CX5P.js → landed-F7PCHGCK.js} +4 -4
- package/dist/{landing-record-QYECWLQ5.js → landing-record-MWXFIRCP.js} +26 -25
- package/dist/{live-diff-2S7E3SBZ.js → live-diff-5E2BQWQ7.js} +10 -9
- package/dist/local-engine-choice-VD5LNXJU.js +80 -0
- package/dist/{local-engine-command-HMTQK7MN.js → local-engine-command-RYLGMQ2O.js} +96 -95
- package/dist/{local-engine-config-5U3SC434.js → local-engine-config-W3KB7RWM.js} +2 -2
- package/dist/{local-engine-deploy-TXAOYRGF.js → local-engine-deploy-6O7NKZCA.js} +17 -17
- package/dist/{local-engine-process-6VZ7JJBP.js → local-engine-process-ZLLZEIRF.js} +12 -12
- package/dist/{local-engine-state-TJWPWCC4.js → local-engine-state-OCW5YDD7.js} +3 -3
- package/dist/{local-engine-update-check-R5SPDVEJ.js → local-engine-update-check-LVX4HBBI.js} +8 -8
- package/dist/{lock-TS465GVY.js → lock-HDCHD2ON.js} +5 -3
- package/dist/{lock-commands-4VT3L5W5.js → lock-commands-X2OECR4R.js} +62 -61
- package/dist/{login-command-O6WA4FYL.js → login-command-RLLKD565.js} +31 -30
- package/dist/{logout-command-6CPWGFY2.js → logout-command-XDMSXCDO.js} +17 -17
- package/dist/{loop-UFHKSOQ4.js → loop-SUB6C2LK.js} +9 -10
- package/dist/{marketplace-command-HKACSYKS.js → marketplace-command-2NHHY2X3.js} +89 -53
- package/dist/{marketplace-resolve-KLFYVRWS.js → marketplace-resolve-OTZYT4FG.js} +9 -8
- package/dist/{meta-client-73PX6UGJ.js → meta-client-TMHVBZFY.js} +15 -15
- package/dist/{module-manifest-GIKFNXPE.js → module-manifest-FNMW23IX.js} +7 -4
- package/dist/node.d.ts +5 -5
- package/dist/node.js +63 -63
- package/dist/operation-outcome-RN62735X.js +51 -0
- package/dist/{output-target-SZMBNYF4.js → output-target-MOLCTPBP.js} +21 -20
- package/dist/{package-manager-PRAHUSCN.js → package-manager-K762W7XT.js} +2 -2
- package/dist/{plan-disclosure-BHYG7TZ7.js → plan-disclosure-CY7AF6KP.js} +21 -22
- package/dist/{plugin-contributions-X4V22PJQ.js → plugin-contributions-WR26U7NT.js} +6 -6
- package/dist/{plugin-prompt-DKNQHW6Y.js → plugin-prompt-ZUYQQIX4.js} +5 -5
- package/dist/{plugin-questions-CQRVOWFK.js → plugin-questions-HAZOQ67R.js} +4 -4
- package/dist/plugin.d.ts +254 -10
- package/dist/{preflight-command-EBQ6XQF3.js → preflight-command-OHJXYND3.js} +70 -70
- package/dist/{profile-command-NPKBJYPM.js → profile-command-6JWT2BTL.js} +33 -32
- package/dist/{profile-pointer-UOO7JNFG.js → profile-pointer-PDA5XBIB.js} +5 -5
- package/dist/{profile-select-74TRDEPD.js → profile-select-45G5VPJK.js} +2 -2
- package/dist/{project-dependency-RRMTWOPC.js → project-dependency-GZWWGWEW.js} +13 -10
- package/dist/{project-sdk-FOR4IOXL.js → project-sdk-3W72H5QO.js} +4 -4
- package/dist/promote-command-UYAMUXKB.js +146 -0
- package/dist/{prompt-5GUQTCSP.js → prompt-U37K5RPQ.js} +4 -4
- package/dist/{publish-command-LGLZBOCB.js → publish-command-BUS27HGB.js} +138 -66
- package/dist/pull-command-ZGUNP27P.js +168 -0
- package/dist/{pull-superseded-GGURV5J3.js → pull-superseded-EZBGYRZF.js} +4 -4
- package/dist/{raw-where-EoWl5fqY.d.ts → raw-where-ZMLND6AG.d.ts} +20 -3
- package/dist/release-command-BQ6OHS3P.js +150 -0
- package/dist/{release-ns-command-EIBN3JVM.js → release-ns-command-ATGVBVIU.js} +94 -94
- package/dist/{retry-command-Y5YJGOH3.js → retry-command-QJ57WVW7.js} +9 -9
- package/dist/{routes-manifest-3BNZIVST.js → routes-manifest-YR4ZIMLM.js} +16 -8
- package/dist/routes-manifest-file-UALYSZLY.js +41 -0
- package/dist/scaffold.js +3 -3
- package/dist/{secrets-file-FUG7WCES.js → secrets-file-LMS7KX3E.js} +20 -19
- package/dist/{secrets-fill-command-QEOCUOAY.js → secrets-fill-command-QNBDGCGM.js} +61 -60
- package/dist/{seed-GJHJSEUE.js → seed-SZ6OS5DQ.js} +9 -9
- package/dist/{source-resolve-DMDZVPMM.js → source-resolve-MKLNYFWG.js} +24 -24
- package/dist/{static-host-WM24RG25.js → static-host-ONEHA4LI.js} +10 -10
- package/dist/{status-command-XUH5OGQX.js → status-command-XKIFKBGM.js} +57 -56
- package/dist/{store-CfgPaVPO.d.ts → store-Bg4Na6Sm.d.ts} +4 -4
- package/dist/{store-MR7IKXKK.js → store-X6ZH7EC3.js} +7 -7
- package/dist/sveltekit.d.ts +5 -5
- package/dist/sveltekit.js +1 -1
- package/dist/sync-baseline-DOV5AGIO.js +36 -0
- package/dist/{sync-contributions-DHP7XSTX.js → sync-contributions-HNVHDIQW.js} +21 -13
- package/dist/sync-record-PRXHLK4S.js +42 -0
- package/dist/{table-ZBDPKMNH.js → table-DC36QA4Y.js} +10 -10
- package/dist/{tables-command-X3JK7VSK.js → tables-command-UQLKTELN.js} +44 -43
- package/dist/{tenant-GKXMOYLK.js → tenant-EKNQGG5A.js} +11 -11
- package/dist/{tenant-command-P27EQHBU.js → tenant-command-2LWP2MPB.js} +105 -100
- package/dist/{test-command-A4G2FP7G.js → test-command-IU5MBBXY.js} +44 -43
- package/dist/{tests-C55M5EQS.js → tests-RG2Y5EQ4.js} +7 -7
- package/dist/{token-CMAB35GD.js → token-7AWSJLKO.js} +13 -13
- package/dist/toolchain-hooks-4ZMQLBPQ.js +46 -0
- package/dist/{toolchain-modules-3M7QDJBV.js → toolchain-modules-VU7SURVJ.js} +9 -6
- package/dist/toolchain-peers-CIDNEEQV.js +28 -0
- package/dist/tracked-backend-4BHSV7NC.js +81 -0
- package/dist/{update-check-LNNKIMML.js → update-check-A7FXIINW.js} +60 -59
- package/dist/{upgrade-command-7EUXML3P.js → upgrade-command-C5KBITFI.js} +64 -63
- package/dist/{whoami-command-KNWFWAX6.js → whoami-command-7WQII2H4.js} +16 -16
- package/dist/{workspace-TGPYOODG.js → workspace-Z46PUZNI.js} +6 -6
- package/dist/{workspace-binding-2TWZBHQY.js → workspace-binding-JE6YNDZJ.js} +15 -15
- package/dist/{workspace-command-T7Z2BDHD.js → workspace-command-FC4IMLAE.js} +119 -88
- package/dist/{workspace-env-VA7XN3UX.js → workspace-env-N4ZPFT6A.js} +17 -16
- package/dist/{workspace-export-AIGM6LC7.js → workspace-export-3A5BZTPS.js} +6 -6
- package/dist/{writable-FYJBTJOU.js → writable-D7KCZI5N.js} +4 -4
- package/dist/{xano-BSHYVFSE.js → xano-LCI7VWPS.js} +9 -9
- package/dist/{xanosdk-import-J6SRBZHW.js → xanosdk-import-P2A2KSXM.js} +10 -10
- package/dist/xanosdk-project-6AGMW2SL.js +42 -0
- package/guides/README.md +1 -0
- package/guides/authoring.md +3 -5
- package/guides/bundle.md +45 -0
- package/guides/cli.md +36 -34
- package/guides/codegen.md +5 -4
- package/guides/codes.md +16 -11
- package/guides/deploying.md +115 -58
- package/guides/environment.md +13 -13
- package/guides/marketplace.md +21 -0
- package/guides/module-contract.md +80 -4
- package/guides/project-structure.md +14 -0
- package/guides/typed-frontend.md +37 -0
- package/llms/client.md +14 -5
- package/llms/errors.md +1 -1
- package/llms/filters.md +4 -0
- package/llms/kinds-core.md +1 -1
- package/llms/statements-data.md +3 -2
- package/llms/tests.md +2 -2
- package/llms/toolchain.md +12 -0
- package/llms-full.txt +47 -21
- package/llms.txt +10 -10
- package/manifest.json +110 -107
- package/package.json +4 -4
- package/dist/agent-file-refresh-LB6KIMFY.js +0 -38
- package/dist/chunk-XXZZGXW2.js +0 -243
- package/dist/deploy-source-5CET3A5D.js +0 -81
- package/dist/env-example-refresh-ZO6XAV44.js +0 -127
- package/dist/init-command-27SFBW2F.js +0 -126
- package/dist/local-engine-choice-6BSPEG3E.js +0 -79
- package/dist/operation-outcome-2P4BVSEV.js +0 -51
- package/dist/promote-command-4F2NAE6P.js +0 -141
- package/dist/pull-command-WQFPLITW.js +0 -162
- package/dist/release-command-2OTNVMIL.js +0 -147
- package/dist/toolchain-hooks-BGZBDFAT.js +0 -96
- package/dist/tracked-backend-PZGUWD5J.js +0 -80
- package/dist/xanosdk-project-6KTCO47O.js +0 -41
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.
|
package/llms/client.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Consuming defs from a client
|
|
2
2
|
|
|
3
|
-
> Read when a frontend imports a def
|
|
3
|
+
> Read when a frontend calls the deployed backend or imports a def — request types and zod schemas without the import, its cost, `window.XANO_HOST`, local dev, file URLs, a Node spot-check.
|
|
4
4
|
|
|
5
5
|
Importing a def into a browser bundle or a Node script — for `getPath()`, `getUrl()`, `verb`, or `InferResponse` — runs its factory calls; these are the costs and the checks.
|
|
6
6
|
|
|
@@ -15,6 +15,16 @@ Importing a def into a browser bundle or a Node script — for `getPath()`, `get
|
|
|
15
15
|
plain data importing NOTHING, still compile-checked: `routePath("GET blog/{slug}", { slug })`
|
|
16
16
|
`channelPath("rooms/{room_id}", { room_id })`, `socketUrl("chat", baseUrl)` (tenant base
|
|
17
17
|
URLs lifted to `wss://h/ws/<tenant>:<canonical>`). A rename is a type error, not a 404.
|
|
18
|
+
- **Request types without the def.** `routes.gen.ts` also exports types-only `RouteInputs`,
|
|
19
|
+
`ChannelInputs`, `MessageInputs` (and `MessageName`), keyed like `ROUTES`, `CHANNELS`, and
|
|
20
|
+
`"<channel key> <message name>"`: `type NewListing = RouteInputs["POST listings"]`. A
|
|
21
|
+
frontend types bodies, channel params and payloads from these, not `InferInput` on a def;
|
|
22
|
+
keep `InferInput` in code that already imports defs. They match `InferInput`, except a
|
|
23
|
+
`dbLink` input appears as the linked table's columns (what the server accepts). Responses
|
|
24
|
+
are not in the file: `InferResponse` on an `import type` of the def.
|
|
25
|
+
Runtime validation: `xanosdk marketplace install zod` adds `@xano-sdk/zod`, which writes
|
|
26
|
+
`ROUTE_SCHEMAS`/`CHANNEL_SCHEMAS`/`MESSAGE_SCHEMAS` into the file under the same keys, each
|
|
27
|
+
checked against its type at typecheck; the file then imports `zod`, never `@xano/sdk`.
|
|
18
28
|
- **Verifying a def outside a bundler.** Inside a bundler (Vite/webpack) importing a
|
|
19
29
|
query def to read `getPath()`/`verb` works directly. To spot-check from Node, run a REAL
|
|
20
30
|
file with `tsx <file.ts>` **from inside the project root** — not `tsx -e "import …"`
|
|
@@ -40,11 +50,10 @@ by grepping `window.XANO_HOST` matches nothing and reads as a failed inject. Gre
|
|
|
40
50
|
bare `XANO_HOST` token.
|
|
41
51
|
**Frontend without the backend.** `xanosdk publish <dir> [--to <backend>]` uploads an
|
|
42
52
|
already-built directory and nothing else — no compile, no import (scaffold script
|
|
43
|
-
`npm run xano:deploy:frontend`).
|
|
44
|
-
deploy
|
|
45
|
-
`xanosdk deploy <entry> --local-engine --static <dir>` (served at `http://<prefix>.localhost:<port>`).
|
|
53
|
+
`npm run xano:deploy:frontend`). A Xano Engine (`--to local`, or bare after a local
|
|
54
|
+
deploy) serves it, server half included, at `http://<prefix>.localhost:<port>`.
|
|
46
55
|
**Server-rendered SvelteKit.** `adapter()` from `@xano/sdk/sveltekit` (needs `esbuild`) writes
|
|
47
|
-
the static half at the build's root plus a server half in `.xano-ssr/`. A
|
|
56
|
+
the static half at the build's root plus a server half in `.xano-ssr/`. A Xano Engine renders every
|
|
48
57
|
path that is not a file through it (`load` reads the engine's own URL as `XANO_HOST` from
|
|
49
58
|
`$env/dynamic/private`; a rendered page gets the deploy's `window.XANO_HOST` too). Any other host
|
|
50
59
|
is not sent `.xano-ssr/`: it serves the static half and answers other paths with the `404.html`
|
package/llms/errors.md
CHANGED
|
@@ -51,6 +51,6 @@ A failure document's `exitCode` matches.
|
|
|
51
51
|
| 5 | `test` / `deploy --test`: the suite ran and a test failed. A deploy is not retracted. | Fix the test or the code. |
|
|
52
52
|
| 6 | `test`, `deploy --test`: the suite could not be reached. | Check the backend; rerun. |
|
|
53
53
|
| 7 | `upgrade --check`: an upgrade is available. | `xanosdk upgrade`. |
|
|
54
|
-
| 8 | A named backend could not be addressed (or a named release, profile, branch, test, module, lock entry, `--seed` guid or
|
|
54
|
+
| 8 | A named backend could not be addressed (or a named release, profile, branch, test, module, lock entry, `--seed` guid or Xano Engine version is missing): gone, expired, unreachable, a stopped Xano Engine, or a busy import. | Retry, or redeploy. |
|
|
55
55
|
| 9 | A write whose outcome is unknown, Ctrl-C during a write included. | Read the target's state before retrying. |
|
|
56
56
|
| 130 | Ctrl-C outside a write or install. | — |
|
package/llms/filters.md
CHANGED
|
@@ -27,6 +27,10 @@ with `c.obj`/`c.array`. Any argument also takes a runtime value (`inp`, `ref`, a
|
|
|
27
27
|
`withFilters` chain) — inside `obj()`/`expr()` an argument cannot carry its own filter
|
|
28
28
|
chain, so compute it in a prior `set_var`. The arg types below name each argument's
|
|
29
29
|
ENGINE type, not the JS type you may pass.
|
|
30
|
+
`fl.add`/`fl.sub`/`fl.mul` keep an INT when both operands are ints (`2 × 3` is `6`, not
|
|
31
|
+
`6.0`) and give a decimal only when either operand is one — the `decimal` return type
|
|
32
|
+
below covers both, so an int pipeline needs no `fl.to_int()`. `fl.div` is an int only
|
|
33
|
+
when it divides exactly.
|
|
30
34
|
To add to a numeric column (counter, stock, balance), use `s.db.increment`
|
|
31
35
|
(`llms/statements-data.md`) — one atomic UPDATE. A pipeline read-modify-write is NOT
|
|
32
36
|
atomic (concurrent writers lose updates), and `col("clicks")` does NOT resolve to the
|
package/llms/kinds-core.md
CHANGED
|
@@ -25,7 +25,7 @@ to survive a rename).
|
|
|
25
25
|
- `getPath` percent-encodes each value (so `?`/`#`/spaces stay in their segment) and throws on what encoding cannot contain: a `/`, and a segment that becomes `.`/`..` as sent (a URL parser drops those before routing, addressing a different endpoint).
|
|
26
26
|
- The keys are typed from the literal `name`, so a typo is a compile error.
|
|
27
27
|
- `q.toSearchParams(input)` drops GET path params (free `query.toSearchParams` keeps them); lists send `k[]=a&k[]=b` (`k=a&k=b` binds only `b`).
|
|
28
|
-
- Browser bundle cost, the `routes.gen.ts` alternative, and spot-checking a def from Node: `llms/client.md`.
|
|
28
|
+
- Browser bundle cost, the `routes.gen.ts` alternative (paths and request types), and spot-checking a def from Node: `llms/client.md`.
|
|
29
29
|
- `apiGroup({ name, guid?, canonical?, description?, docs?, swagger?, apiGroupEnabled?, documentation?, cors?, middleware? })` — a query container; queries bind to it via their `apiGroup`. `canonical` holds only letters, digits, `_` and `-` (it is the `<canonical>` of `/api:<canonical>`); anything else THROWS at build.
|
|
30
30
|
- `documentation?`: `{ require_token? }` — the gate on this group's hosted docs. `require_token: true` IS the declaration; the token lives in `xano/.secrets.json` under this group's guid, and a literal `token` FAILS the export. ⚠ ALWAYS emitted, present or not: an absent key is written as the engine default on import, so omitting the block CLEARS an existing gate (the opposite of the `workspaceConfig` rule). `swagger: true` publishes the docs; `require_token` gates them only alongside a non-empty token, so `swagger: true` with no gate makes the whole group readable by anyone with the URL — export warns once per build and `--strict` fails; `diagnostics: { allow: ["api-group.docs-public"] }` accepts it. A declared gate with NO token drops the block, so those bytes clear it: export FAILS under `swagger: true`, and with `swagger` off warns and completes.
|
|
31
31
|
- `cors?`: `{ mode?, allowOrigins?: string[], allowHeaders?: string[], allowCredentials?, maxAge?, allowMethods?: { get?, post?, put?, patch?, delete?, head? } }`.
|
package/llms/statements-data.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Array blocks (an `if`/`transform` is applied per item):
|
|
6
6
|
|
|
7
|
-
- `s.array.map({ source, as?, transform? })` — `transform` is either a per-item `Value` expression (each item maps to that value) or a **record of values** (each item maps to an object with those keys), or a list of `{ key, value }` pairs, for a key computed per item or two rows sharing one. Use `ref("$this")` for the item and `ref("$index")` for its position. These are THIS statement's own bindings, in a value expression — not the JavaScript lambda contract (see **Lambda bodies**), which binds a different set per surface and is written with `lam.fn`.
|
|
7
|
+
- `s.array.map({ source, as?, transform? })` — `transform` is either a per-item `Value` expression (each item maps to that value) or a **record of values** (each item maps to an object with those keys), or a list of `{ key, value }` pairs, for a key computed per item or two rows sharing one. Use `ref("$this")` for the item and `ref("$index")` for its position. A `transform` value, filter arguments included, can read `ref("$this.<path>")` and any outer stack variable or input. These are THIS statement's own bindings, in a value expression — not the JavaScript lambda contract (see **Lambda bodies**), which binds a different set per surface and is written with `lam.fn`.
|
|
8
8
|
- `s.array.union({ source, with, as?, transform? })` — set-union two arrays. `with` is REQUIRED; omitted → `Unable to locate input: `.
|
|
9
9
|
|
|
10
10
|
DB reads/writes (`table` is a def handle or name; `fieldName` defaults to the
|
|
@@ -58,7 +58,8 @@ primary key `id`):
|
|
|
58
58
|
- Template placeholders are Twig over the request scope: `{{ $input.name }}` for an input, `{{ $var.name }}` for a stack variable. ⚠ A BARE `{{ name }}` renders as the empty string — HTTP 200, no error, a query that silently ran with a blank where the value belonged. A bound `?` arg carries a VALUE without the template at all.
|
|
59
59
|
- ⚠ A table's PHYSICAL name is **not stable across deploys**. A deploy is a full replace, so every table is created afresh and the id in its name moves every time — the same unchanged project redeployed three times gave one table three different names. Never store, cache, hardcode or fixture one: resolve it from `information_schema` inside the same request that uses it.
|
|
60
60
|
- `s.db.external.<engine>.direct_query({ sql, connectionString, responseType?, args?, parser?, as? })` — same shape against an EXTERNAL database; `<engine>` is `postgres`/`mysql`/`mssql`/`oracle`/`snowflake`. `connectionString` is a `Value` — reach for `env(...)`, not a literal — stored as `context.connection_string_flex`. A bare string stores the older `context.connection_string` instead (an env-var name unless it looks like a URL); each form round-trips as itself.
|
|
61
|
-
- `s.db.transaction({ body
|
|
61
|
+
- `s.db.transaction({ body })` — run a `Statement[]` atomically. It returns nothing, so it takes no `as`: read what the body binds. An `s.return` in the body ends the WHOLE stack with that value, and the writes before it commit.
|
|
62
|
+
- The body shares the enclosing stack: a variable it binds (`as: "order"` on an `s.db.add`) is still bound AFTER the transaction.
|
|
62
63
|
- `s.db.bulk.add({ table, items, allowIdField?, as? })` / `s.db.bulk.update` / `s.db.bulk.patch` — `items` is an array `Value`.
|
|
63
64
|
- ⚠ `bulk.add` **drops `id` on every row unless `allowIdField: true`** (silently, next sequence value instead) — the opposite of `seed`, where `id` pins. Rows referenced by a foreign key need `allowIdField: true`; literal `items` carrying `id` without it throw. `bulk.update`/`patch` keep `id` (their match key).
|
|
64
65
|
- ⚠ **`bulk.update` is a whole-row REPLACE: every column an item OMITS is zeroed** (`""`/`0`/`null`), HTTP 200, no error — `{ id: 7, status: "done" }` blanks the rest of row 7. **Use `s.db.bulk.patch`** for the partial write "update these rows" means. `export()` warns on a STATIC `items` missing columns (`--strict` fails); a `ref`/`inp` `items` is uninspectable.
|
package/llms/tests.md
CHANGED
|
@@ -51,9 +51,9 @@ The run is isolated in ways that make a correct test fail for reasons the failur
|
|
|
51
51
|
|
|
52
52
|
`xanosdk test run-all` runs the unit tests AND the `workflowTest()` objects an environment carries. It takes no entry file and compiles nothing: it runs what is DEPLOYED, so deploy before testing.
|
|
53
53
|
|
|
54
|
-
- `--on <backend>` picks the backend — `--on ephemeral:<name>`, `--on local
|
|
54
|
+
- `--on <backend>` picks the backend — `--on ephemeral:<name>`, `--on local`, `--on tenant:<name>`, `--on workspace`; omitted, the one this project last deployed to (grammar: **Backends** in `llms.txt`). ⚠ `workspace` runs against the REAL database: safe only while every test keeps `datasource: ""`, since a stored non-empty datasource is CLONED before the run.
|
|
55
55
|
- `xanosdk test list` shows what is there without running it; `test run "<name>"` runs one; an ambiguous name prints qualified forms (`function:math/happy path`, `workflow:<name>`) `run` accepts.
|
|
56
56
|
- `--kind unit|workflow` narrows to one family. `--concurrency <n>` defaults to 1: tests share the environment database.
|
|
57
57
|
- A failing suite exits 5; exit 6 when the suite could not be reached — retry it; a backend that can't be looked up exits 8 (see errors). Having no tests is success.
|
|
58
|
-
- For CI: the exit code says THAT something failed, the JSON says WHICH. Progress goes to stderr; stdout carries one JSON document when not a terminal, or with `--json`. `run-all` and `run`: `{ kind, env, name, display, total, passed, failed, tests: [{ kind, name, qualified, object?, status: "pass"|"fail", message?, expectations?: [{ index, status, message? }], timing? }] }` (`message`: the first failure; `expectations`: a unit test's every expectation in order, `index` from 0; `env`: an ephemeral's or tenant's name; `name`: the backend's own, a
|
|
58
|
+
- For CI: the exit code says THAT something failed, the JSON says WHICH. Progress goes to stderr; stdout carries one JSON document when not a terminal, or with `--json`. `run-all` and `run`: `{ kind, env, name, display, total, passed, failed, tests: [{ kind, name, qualified, object?, status: "pass"|"fail", message?, expectations?: [{ index, status, message? }], timing? }] }` (`message`: the first failure; `expectations`: a unit test's every expectation in order, `index` from 0; `env`: an ephemeral's or tenant's name; `name`: the backend's own, a Xano Engine's too; null if none), same keys on an empty suite. `list` is `{ kind, env, name, display, total, tests }`; `deploy --test` nests the run under `testRun`.
|
|
59
59
|
- `xanosdk deploy ./index.ts --test` deploys and then runs the suite against what it just shipped. A failure exits 5 WITHOUT retracting the deploy — the environment is live either way.
|
package/llms/toolchain.md
CHANGED
|
@@ -14,3 +14,15 @@ shipped defaults. `marketplace reinstall <pkg>` re-asks with the current setting
|
|
|
14
14
|
defaults and re-enables a disabled one; `marketplace remove <pkg>` drops block, lines and
|
|
15
15
|
dependency together — a plain `npm uninstall` leaves the block, and a package it names
|
|
16
16
|
that is no longer installed fails every `--frozen-lock` run.
|
|
17
|
+
|
|
18
|
+
**A module's section of `xano/routes.gen.ts`.** A module with a `routesManifest` hook (types:
|
|
19
|
+
`@xano/sdk/plugin`) writes a block between `// xanosdk:begin <pkg>` and `// xanosdk:end <pkg>`
|
|
20
|
+
after the core sections, on every write of the file (`routes --emit`, `xano:routes`, `pull`,
|
|
21
|
+
`generate`, `marketplace install|reinstall|remove`). Edits inside the block are overwritten.
|
|
22
|
+
Install also adds the module's non-SDK peers (e.g. `zod`) as direct dependencies.
|
|
23
|
+
The hook is synchronous and pure: given
|
|
24
|
+
the request inputs under the manifest's keys and its config, it returns `{ imports?, source }`,
|
|
25
|
+
imports as bare package names (`@xano/sdk*`, relative and `node:` are refused). A module that
|
|
26
|
+
fails to load or throws leaves its previous block as it was, with a warning naming it, and the
|
|
27
|
+
core sections still refresh; under `routes --emit --strict` it is fatal. `@xano-sdk/zod`
|
|
28
|
+
(`xanosdk marketplace install zod`) is one: it adds `ROUTE_SCHEMAS` and its siblings.
|
package/llms-full.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# xanosdk v1.0.
|
|
1
|
+
# xanosdk v1.0.6
|
|
2
2
|
|
|
3
3
|
> TypeScript SDK that compiles a typed Xano workspace into the importable packageExport JSON bundle.
|
|
4
4
|
|
|
@@ -39,7 +39,7 @@ plain file read resolves them at the version you have.
|
|
|
39
39
|
|
|
40
40
|
- [Object kinds](llms/object-kinds.md): Read when deciding WHAT to build — every authorable primitive, what each is, and which factory + register method builds it. Also when `register*` will not typecheck an array built by `.flatMap()`/`.concat()`.
|
|
41
41
|
- [Core def shapes](llms/kinds-core.md): Read when authoring a function, query, api group, task, workflow test, middleware, tool, or addon — and for the `response` and `expr` shapes every one of them uses.
|
|
42
|
-
- [Consuming defs from a client](llms/client.md): Read when a frontend imports a def
|
|
42
|
+
- [Consuming defs from a client](llms/client.md): Read when a frontend calls the deployed backend or imports a def — request types and zod schemas without the import, its cost, `window.XANO_HOST`, local dev, file URLs, a Node spot-check.
|
|
43
43
|
- [Toolchain modules](llms/toolchain.md): Read when `package.json` has a `"xanosdk"` block or you run `xanosdk marketplace`.
|
|
44
44
|
- [Error index](llms/errors.md): Read when a request, test, build, or pull fails with a message you did not write — the string, its cause, and where the fix is.
|
|
45
45
|
- [Saved unit tests, assertions, and mocks](llms/tests.md): Read when authoring a `workflowTest()` stack, when a query/function/middleware carries `tests`, when a statement needs a `mock`, or when running a deployed environment's tests.
|
|
@@ -155,19 +155,19 @@ export. Pruning, programmatic seeding, and which commands write the lock:
|
|
|
155
155
|
`export` (honoring `xano.lock`), imports the result, and prints the URL.
|
|
156
156
|
⚠ Every deploy is a FULL REPLACE of its destination — objects AND records.
|
|
157
157
|
|
|
158
|
-
**Backends** — one grammar: `workspace` | `ephemeral[:<name>]` | `local
|
|
158
|
+
**Backends** — one grammar: `workspace` | `ephemeral[:<name>]` | `local[:<name>]`
|
|
159
159
|
(no credential) | `tenant:<name>` | `release:<name>` | a bundle path where a file fits. Reads
|
|
160
160
|
`--from`, writes `--to`, `test --on`; positional on `deploy`/`pull`/`generate`/`tables`/
|
|
161
|
-
`impersonate`. Omitted = the ephemeral or
|
|
162
|
-
workspace/tenant; bare `deploy` compiles the
|
|
163
|
-
|
|
164
|
-
names the reason and the spellings (`
|
|
161
|
+
`impersonate`. Omitted = the ephemeral or Xano Engine this project last deployed to, never
|
|
162
|
+
workspace/tenant; bare `deploy` compiles onto the Xano Engine instead (`--ephemeral`: an
|
|
163
|
+
ephemeral), and `generate`/`init --from` need one. A refusal, typed or tracked,
|
|
164
|
+
names the reason and the spellings (`release create` refuses a Xano Engine).
|
|
165
165
|
`release create --from` records a run: no bundle path, no `release:`,
|
|
166
166
|
and a `tenant:` only if throwaway (`standard`/`run` refused).
|
|
167
167
|
|
|
168
|
-
**Destinations** —
|
|
168
|
+
**Destinations** — the Xano Engine by default, real only when you say so:
|
|
169
169
|
|
|
170
|
-
- `xanosdk deploy [source]` → a NAMED, auto-expiring ephemeral (~1h; `--expires-hours`
|
|
170
|
+
- `xanosdk deploy [source]` → the Xano Engine on this machine (no account). `--ephemeral` → a NAMED, auto-expiring ephemeral (~1h; `--expires-hours`
|
|
171
171
|
1–24), tracked in `./.xano/ephemeral.json`, so deploying again REFRESHES it at the same
|
|
172
172
|
URL; if it expired or was swept, a fresh one is created and the new URL called out.
|
|
173
173
|
⚠ Only the BACKEND URL survives a refresh — the replace clears static hosting, so
|
|
@@ -436,7 +436,7 @@ Non-obvious authoring rules:
|
|
|
436
436
|
checked only by the `xanosdk export`/`deploy` CLI path. Only `deploy` ships seed rows.
|
|
437
437
|
- Entry points: the `node:fs` writers (`writeBundle`/`writeArtifact`) and lock-file I/O
|
|
438
438
|
import from `@xano/sdk/node`, NOT the browser-safe `@xano/sdk` entry (a frontend
|
|
439
|
-
imports
|
|
439
|
+
imports from it; request types come from `routes.gen.ts`). `@xano/sdk/internal` is the
|
|
440
440
|
compiler machinery, never needed to author. READING a bundle back is `@xano/sdk/bundle`
|
|
441
441
|
— a statement walker (`2.if.0` paths), a structural hash, `mvp:*` catalog, `tableRefOf`.
|
|
442
442
|
- **Intra-workspace imports use `.js` specifiers** (`../tables/links.js`), not
|
|
@@ -554,7 +554,7 @@ to survive a rename).
|
|
|
554
554
|
- `getPath` percent-encodes each value (so `?`/`#`/spaces stay in their segment) and throws on what encoding cannot contain: a `/`, and a segment that becomes `.`/`..` as sent (a URL parser drops those before routing, addressing a different endpoint).
|
|
555
555
|
- The keys are typed from the literal `name`, so a typo is a compile error.
|
|
556
556
|
- `q.toSearchParams(input)` drops GET path params (free `query.toSearchParams` keeps them); lists send `k[]=a&k[]=b` (`k=a&k=b` binds only `b`).
|
|
557
|
-
- Browser bundle cost, the `routes.gen.ts` alternative, and spot-checking a def from Node: `llms/client.md`.
|
|
557
|
+
- Browser bundle cost, the `routes.gen.ts` alternative (paths and request types), and spot-checking a def from Node: `llms/client.md`.
|
|
558
558
|
- `apiGroup({ name, guid?, canonical?, description?, docs?, swagger?, apiGroupEnabled?, documentation?, cors?, middleware? })` — a query container; queries bind to it via their `apiGroup`. `canonical` holds only letters, digits, `_` and `-` (it is the `<canonical>` of `/api:<canonical>`); anything else THROWS at build.
|
|
559
559
|
- `documentation?`: `{ require_token? }` — the gate on this group's hosted docs. `require_token: true` IS the declaration; the token lives in `xano/.secrets.json` under this group's guid, and a literal `token` FAILS the export. ⚠ ALWAYS emitted, present or not: an absent key is written as the engine default on import, so omitting the block CLEARS an existing gate (the opposite of the `workspaceConfig` rule). `swagger: true` publishes the docs; `require_token` gates them only alongside a non-empty token, so `swagger: true` with no gate makes the whole group readable by anyone with the URL — export warns once per build and `--strict` fails; `diagnostics: { allow: ["api-group.docs-public"] }` accepts it. A declared gate with NO token drops the block, so those bytes clear it: export FAILS under `swagger: true`, and with `swagger` off warns and completes.
|
|
560
560
|
- `cors?`: `{ mode?, allowOrigins?: string[], allowHeaders?: string[], allowCredentials?, maxAge?, allowMethods?: { get?, post?, put?, patch?, delete?, head? } }`.
|
|
@@ -630,7 +630,7 @@ surface — `s.conditional`/`s.while` `when` (incl. each `elif` branch), and
|
|
|
630
630
|
|
|
631
631
|
# Consuming defs from a client
|
|
632
632
|
|
|
633
|
-
> Read when a frontend imports a def
|
|
633
|
+
> Read when a frontend calls the deployed backend or imports a def — request types and zod schemas without the import, its cost, `window.XANO_HOST`, local dev, file URLs, a Node spot-check.
|
|
634
634
|
|
|
635
635
|
Importing a def into a browser bundle or a Node script — for `getPath()`, `getUrl()`, `verb`, or `InferResponse` — runs its factory calls; these are the costs and the checks.
|
|
636
636
|
|
|
@@ -645,6 +645,16 @@ Importing a def into a browser bundle or a Node script — for `getPath()`, `get
|
|
|
645
645
|
plain data importing NOTHING, still compile-checked: `routePath("GET blog/{slug}", { slug })`
|
|
646
646
|
`channelPath("rooms/{room_id}", { room_id })`, `socketUrl("chat", baseUrl)` (tenant base
|
|
647
647
|
URLs lifted to `wss://h/ws/<tenant>:<canonical>`). A rename is a type error, not a 404.
|
|
648
|
+
- **Request types without the def.** `routes.gen.ts` also exports types-only `RouteInputs`,
|
|
649
|
+
`ChannelInputs`, `MessageInputs` (and `MessageName`), keyed like `ROUTES`, `CHANNELS`, and
|
|
650
|
+
`"<channel key> <message name>"`: `type NewListing = RouteInputs["POST listings"]`. A
|
|
651
|
+
frontend types bodies, channel params and payloads from these, not `InferInput` on a def;
|
|
652
|
+
keep `InferInput` in code that already imports defs. They match `InferInput`, except a
|
|
653
|
+
`dbLink` input appears as the linked table's columns (what the server accepts). Responses
|
|
654
|
+
are not in the file: `InferResponse` on an `import type` of the def.
|
|
655
|
+
Runtime validation: `xanosdk marketplace install zod` adds `@xano-sdk/zod`, which writes
|
|
656
|
+
`ROUTE_SCHEMAS`/`CHANNEL_SCHEMAS`/`MESSAGE_SCHEMAS` into the file under the same keys, each
|
|
657
|
+
checked against its type at typecheck; the file then imports `zod`, never `@xano/sdk`.
|
|
648
658
|
- **Verifying a def outside a bundler.** Inside a bundler (Vite/webpack) importing a
|
|
649
659
|
query def to read `getPath()`/`verb` works directly. To spot-check from Node, run a REAL
|
|
650
660
|
file with `tsx <file.ts>` **from inside the project root** — not `tsx -e "import …"`
|
|
@@ -670,11 +680,10 @@ by grepping `window.XANO_HOST` matches nothing and reads as a failed inject. Gre
|
|
|
670
680
|
bare `XANO_HOST` token.
|
|
671
681
|
**Frontend without the backend.** `xanosdk publish <dir> [--to <backend>]` uploads an
|
|
672
682
|
already-built directory and nothing else — no compile, no import (scaffold script
|
|
673
|
-
`npm run xano:deploy:frontend`).
|
|
674
|
-
deploy
|
|
675
|
-
`xanosdk deploy <entry> --local-engine --static <dir>` (served at `http://<prefix>.localhost:<port>`).
|
|
683
|
+
`npm run xano:deploy:frontend`). A Xano Engine (`--to local`, or bare after a local
|
|
684
|
+
deploy) serves it, server half included, at `http://<prefix>.localhost:<port>`.
|
|
676
685
|
**Server-rendered SvelteKit.** `adapter()` from `@xano/sdk/sveltekit` (needs `esbuild`) writes
|
|
677
|
-
the static half at the build's root plus a server half in `.xano-ssr/`. A
|
|
686
|
+
the static half at the build's root plus a server half in `.xano-ssr/`. A Xano Engine renders every
|
|
678
687
|
path that is not a file through it (`load` reads the engine's own URL as `XANO_HOST` from
|
|
679
688
|
`$env/dynamic/private`; a rendered page gets the deploy's `window.XANO_HOST` too). Any other host
|
|
680
689
|
is not sent `.xano-ssr/`: it serves the static half and answers other paths with the `404.html`
|
|
@@ -709,6 +718,18 @@ defaults and re-enables a disabled one; `marketplace remove <pkg>` drops block,
|
|
|
709
718
|
dependency together — a plain `npm uninstall` leaves the block, and a package it names
|
|
710
719
|
that is no longer installed fails every `--frozen-lock` run.
|
|
711
720
|
|
|
721
|
+
**A module's section of `xano/routes.gen.ts`.** A module with a `routesManifest` hook (types:
|
|
722
|
+
`@xano/sdk/plugin`) writes a block between `// xanosdk:begin <pkg>` and `// xanosdk:end <pkg>`
|
|
723
|
+
after the core sections, on every write of the file (`routes --emit`, `xano:routes`, `pull`,
|
|
724
|
+
`generate`, `marketplace install|reinstall|remove`). Edits inside the block are overwritten.
|
|
725
|
+
Install also adds the module's non-SDK peers (e.g. `zod`) as direct dependencies.
|
|
726
|
+
The hook is synchronous and pure: given
|
|
727
|
+
the request inputs under the manifest's keys and its config, it returns `{ imports?, source }`,
|
|
728
|
+
imports as bare package names (`@xano/sdk*`, relative and `node:` are refused). A module that
|
|
729
|
+
fails to load or throws leaves its previous block as it was, with a warning naming it, and the
|
|
730
|
+
core sections still refresh; under `routes --emit --strict` it is fatal. `@xano-sdk/zod`
|
|
731
|
+
(`xanosdk marketplace install zod`) is one: it adds `ROUTE_SCHEMAS` and its siblings.
|
|
732
|
+
|
|
712
733
|
# Error index
|
|
713
734
|
|
|
714
735
|
> Read when a request, test, build, or pull fails with a message you did not write — the string, its cause, and where the fix is.
|
|
@@ -762,7 +783,7 @@ A failure document's `exitCode` matches.
|
|
|
762
783
|
| 5 | `test` / `deploy --test`: the suite ran and a test failed. A deploy is not retracted. | Fix the test or the code. |
|
|
763
784
|
| 6 | `test`, `deploy --test`: the suite could not be reached. | Check the backend; rerun. |
|
|
764
785
|
| 7 | `upgrade --check`: an upgrade is available. | `xanosdk upgrade`. |
|
|
765
|
-
| 8 | A named backend could not be addressed (or a named release, profile, branch, test, module, lock entry, `--seed` guid or
|
|
786
|
+
| 8 | A named backend could not be addressed (or a named release, profile, branch, test, module, lock entry, `--seed` guid or Xano Engine version is missing): gone, expired, unreachable, a stopped Xano Engine, or a busy import. | Retry, or redeploy. |
|
|
766
787
|
| 9 | A write whose outcome is unknown, Ctrl-C during a write included. | Read the target's state before retrying. |
|
|
767
788
|
| 130 | Ctrl-C outside a write or install. | — |
|
|
768
789
|
|
|
@@ -819,11 +840,11 @@ The run is isolated in ways that make a correct test fail for reasons the failur
|
|
|
819
840
|
|
|
820
841
|
`xanosdk test run-all` runs the unit tests AND the `workflowTest()` objects an environment carries. It takes no entry file and compiles nothing: it runs what is DEPLOYED, so deploy before testing.
|
|
821
842
|
|
|
822
|
-
- `--on <backend>` picks the backend — `--on ephemeral:<name>`, `--on local
|
|
843
|
+
- `--on <backend>` picks the backend — `--on ephemeral:<name>`, `--on local`, `--on tenant:<name>`, `--on workspace`; omitted, the one this project last deployed to (grammar: **Backends** in `llms.txt`). ⚠ `workspace` runs against the REAL database: safe only while every test keeps `datasource: ""`, since a stored non-empty datasource is CLONED before the run.
|
|
823
844
|
- `xanosdk test list` shows what is there without running it; `test run "<name>"` runs one; an ambiguous name prints qualified forms (`function:math/happy path`, `workflow:<name>`) `run` accepts.
|
|
824
845
|
- `--kind unit|workflow` narrows to one family. `--concurrency <n>` defaults to 1: tests share the environment database.
|
|
825
846
|
- A failing suite exits 5; exit 6 when the suite could not be reached — retry it; a backend that can't be looked up exits 8 (see errors). Having no tests is success.
|
|
826
|
-
- For CI: the exit code says THAT something failed, the JSON says WHICH. Progress goes to stderr; stdout carries one JSON document when not a terminal, or with `--json`. `run-all` and `run`: `{ kind, env, name, display, total, passed, failed, tests: [{ kind, name, qualified, object?, status: "pass"|"fail", message?, expectations?: [{ index, status, message? }], timing? }] }` (`message`: the first failure; `expectations`: a unit test's every expectation in order, `index` from 0; `env`: an ephemeral's or tenant's name; `name`: the backend's own, a
|
|
847
|
+
- For CI: the exit code says THAT something failed, the JSON says WHICH. Progress goes to stderr; stdout carries one JSON document when not a terminal, or with `--json`. `run-all` and `run`: `{ kind, env, name, display, total, passed, failed, tests: [{ kind, name, qualified, object?, status: "pass"|"fail", message?, expectations?: [{ index, status, message? }], timing? }] }` (`message`: the first failure; `expectations`: a unit test's every expectation in order, `index` from 0; `env`: an ephemeral's or tenant's name; `name`: the backend's own, a Xano Engine's too; null if none), same keys on an empty suite. `list` is `{ kind, env, name, display, total, tests }`; `deploy --test` nests the run under `testRun`.
|
|
827
848
|
- `xanosdk deploy ./index.ts --test` deploys and then runs the suite against what it just shipped. A failure exits 5 WITHOUT retracting the deploy — the environment is live either way.
|
|
828
849
|
|
|
829
850
|
# Agent and MCP def shapes
|
|
@@ -998,7 +1019,7 @@ off); a trigger's own failure reaches the error log only while it is on.
|
|
|
998
1019
|
|
|
999
1020
|
Array blocks (an `if`/`transform` is applied per item):
|
|
1000
1021
|
|
|
1001
|
-
- `s.array.map({ source, as?, transform? })` — `transform` is either a per-item `Value` expression (each item maps to that value) or a **record of values** (each item maps to an object with those keys), or a list of `{ key, value }` pairs, for a key computed per item or two rows sharing one. Use `ref("$this")` for the item and `ref("$index")` for its position. These are THIS statement's own bindings, in a value expression — not the JavaScript lambda contract (see **Lambda bodies**), which binds a different set per surface and is written with `lam.fn`.
|
|
1022
|
+
- `s.array.map({ source, as?, transform? })` — `transform` is either a per-item `Value` expression (each item maps to that value) or a **record of values** (each item maps to an object with those keys), or a list of `{ key, value }` pairs, for a key computed per item or two rows sharing one. Use `ref("$this")` for the item and `ref("$index")` for its position. A `transform` value, filter arguments included, can read `ref("$this.<path>")` and any outer stack variable or input. These are THIS statement's own bindings, in a value expression — not the JavaScript lambda contract (see **Lambda bodies**), which binds a different set per surface and is written with `lam.fn`.
|
|
1002
1023
|
- `s.array.union({ source, with, as?, transform? })` — set-union two arrays. `with` is REQUIRED; omitted → `Unable to locate input: `.
|
|
1003
1024
|
|
|
1004
1025
|
DB reads/writes (`table` is a def handle or name; `fieldName` defaults to the
|
|
@@ -1052,7 +1073,8 @@ primary key `id`):
|
|
|
1052
1073
|
- Template placeholders are Twig over the request scope: `{{ $input.name }}` for an input, `{{ $var.name }}` for a stack variable. ⚠ A BARE `{{ name }}` renders as the empty string — HTTP 200, no error, a query that silently ran with a blank where the value belonged. A bound `?` arg carries a VALUE without the template at all.
|
|
1053
1074
|
- ⚠ A table's PHYSICAL name is **not stable across deploys**. A deploy is a full replace, so every table is created afresh and the id in its name moves every time — the same unchanged project redeployed three times gave one table three different names. Never store, cache, hardcode or fixture one: resolve it from `information_schema` inside the same request that uses it.
|
|
1054
1075
|
- `s.db.external.<engine>.direct_query({ sql, connectionString, responseType?, args?, parser?, as? })` — same shape against an EXTERNAL database; `<engine>` is `postgres`/`mysql`/`mssql`/`oracle`/`snowflake`. `connectionString` is a `Value` — reach for `env(...)`, not a literal — stored as `context.connection_string_flex`. A bare string stores the older `context.connection_string` instead (an env-var name unless it looks like a URL); each form round-trips as itself.
|
|
1055
|
-
- `s.db.transaction({ body
|
|
1076
|
+
- `s.db.transaction({ body })` — run a `Statement[]` atomically. It returns nothing, so it takes no `as`: read what the body binds. An `s.return` in the body ends the WHOLE stack with that value, and the writes before it commit.
|
|
1077
|
+
- The body shares the enclosing stack: a variable it binds (`as: "order"` on an `s.db.add`) is still bound AFTER the transaction.
|
|
1056
1078
|
- `s.db.bulk.add({ table, items, allowIdField?, as? })` / `s.db.bulk.update` / `s.db.bulk.patch` — `items` is an array `Value`.
|
|
1057
1079
|
- ⚠ `bulk.add` **drops `id` on every row unless `allowIdField: true`** (silently, next sequence value instead) — the opposite of `seed`, where `id` pins. Rows referenced by a foreign key need `allowIdField: true`; literal `items` carrying `id` without it throw. `bulk.update`/`patch` keep `id` (their match key).
|
|
1058
1080
|
- ⚠ **`bulk.update` is a whole-row REPLACE: every column an item OMITS is zeroed** (`""`/`0`/`null`), HTTP 200, no error — `{ id: 7, status: "done" }` blanks the rest of row 7. **Use `s.db.bulk.patch`** for the partial write "update these rows" means. `export()` warns on a STATIC `items` missing columns (`--strict` fails); a `ref`/`inp` `items` is uninspectable.
|
|
@@ -1429,6 +1451,10 @@ with `c.obj`/`c.array`. Any argument also takes a runtime value (`inp`, `ref`, a
|
|
|
1429
1451
|
`withFilters` chain) — inside `obj()`/`expr()` an argument cannot carry its own filter
|
|
1430
1452
|
chain, so compute it in a prior `set_var`. The arg types below name each argument's
|
|
1431
1453
|
ENGINE type, not the JS type you may pass.
|
|
1454
|
+
`fl.add`/`fl.sub`/`fl.mul` keep an INT when both operands are ints (`2 × 3` is `6`, not
|
|
1455
|
+
`6.0`) and give a decimal only when either operand is one — the `decimal` return type
|
|
1456
|
+
below covers both, so an int pipeline needs no `fl.to_int()`. `fl.div` is an int only
|
|
1457
|
+
when it divides exactly.
|
|
1432
1458
|
To add to a numeric column (counter, stock, balance), use `s.db.increment`
|
|
1433
1459
|
(`llms/statements-data.md`) — one atomic UPDATE. A pipeline read-modify-write is NOT
|
|
1434
1460
|
atomic (concurrent writers lose updates), and `col("clicks")` does NOT resolve to the
|
package/llms.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# xanosdk v1.0.
|
|
1
|
+
# xanosdk v1.0.6
|
|
2
2
|
|
|
3
3
|
> TypeScript SDK that compiles a typed Xano workspace into the importable packageExport JSON bundle.
|
|
4
4
|
|
|
@@ -39,7 +39,7 @@ plain file read resolves them at the version you have.
|
|
|
39
39
|
|
|
40
40
|
- [Object kinds](llms/object-kinds.md): Read when deciding WHAT to build — every authorable primitive, what each is, and which factory + register method builds it. Also when `register*` will not typecheck an array built by `.flatMap()`/`.concat()`.
|
|
41
41
|
- [Core def shapes](llms/kinds-core.md): Read when authoring a function, query, api group, task, workflow test, middleware, tool, or addon — and for the `response` and `expr` shapes every one of them uses.
|
|
42
|
-
- [Consuming defs from a client](llms/client.md): Read when a frontend imports a def
|
|
42
|
+
- [Consuming defs from a client](llms/client.md): Read when a frontend calls the deployed backend or imports a def — request types and zod schemas without the import, its cost, `window.XANO_HOST`, local dev, file URLs, a Node spot-check.
|
|
43
43
|
- [Toolchain modules](llms/toolchain.md): Read when `package.json` has a `"xanosdk"` block or you run `xanosdk marketplace`.
|
|
44
44
|
- [Error index](llms/errors.md): Read when a request, test, build, or pull fails with a message you did not write — the string, its cause, and where the fix is.
|
|
45
45
|
- [Saved unit tests, assertions, and mocks](llms/tests.md): Read when authoring a `workflowTest()` stack, when a query/function/middleware carries `tests`, when a statement needs a `mock`, or when running a deployed environment's tests.
|
|
@@ -155,19 +155,19 @@ export. Pruning, programmatic seeding, and which commands write the lock:
|
|
|
155
155
|
`export` (honoring `xano.lock`), imports the result, and prints the URL.
|
|
156
156
|
⚠ Every deploy is a FULL REPLACE of its destination — objects AND records.
|
|
157
157
|
|
|
158
|
-
**Backends** — one grammar: `workspace` | `ephemeral[:<name>]` | `local
|
|
158
|
+
**Backends** — one grammar: `workspace` | `ephemeral[:<name>]` | `local[:<name>]`
|
|
159
159
|
(no credential) | `tenant:<name>` | `release:<name>` | a bundle path where a file fits. Reads
|
|
160
160
|
`--from`, writes `--to`, `test --on`; positional on `deploy`/`pull`/`generate`/`tables`/
|
|
161
|
-
`impersonate`. Omitted = the ephemeral or
|
|
162
|
-
workspace/tenant; bare `deploy` compiles the
|
|
163
|
-
|
|
164
|
-
names the reason and the spellings (`
|
|
161
|
+
`impersonate`. Omitted = the ephemeral or Xano Engine this project last deployed to, never
|
|
162
|
+
workspace/tenant; bare `deploy` compiles onto the Xano Engine instead (`--ephemeral`: an
|
|
163
|
+
ephemeral), and `generate`/`init --from` need one. A refusal, typed or tracked,
|
|
164
|
+
names the reason and the spellings (`release create` refuses a Xano Engine).
|
|
165
165
|
`release create --from` records a run: no bundle path, no `release:`,
|
|
166
166
|
and a `tenant:` only if throwaway (`standard`/`run` refused).
|
|
167
167
|
|
|
168
|
-
**Destinations** —
|
|
168
|
+
**Destinations** — the Xano Engine by default, real only when you say so:
|
|
169
169
|
|
|
170
|
-
- `xanosdk deploy [source]` → a NAMED, auto-expiring ephemeral (~1h; `--expires-hours`
|
|
170
|
+
- `xanosdk deploy [source]` → the Xano Engine on this machine (no account). `--ephemeral` → a NAMED, auto-expiring ephemeral (~1h; `--expires-hours`
|
|
171
171
|
1–24), tracked in `./.xano/ephemeral.json`, so deploying again REFRESHES it at the same
|
|
172
172
|
URL; if it expired or was swept, a fresh one is created and the new URL called out.
|
|
173
173
|
⚠ Only the BACKEND URL survives a refresh — the replace clears static hosting, so
|
|
@@ -436,7 +436,7 @@ Non-obvious authoring rules:
|
|
|
436
436
|
checked only by the `xanosdk export`/`deploy` CLI path. Only `deploy` ships seed rows.
|
|
437
437
|
- Entry points: the `node:fs` writers (`writeBundle`/`writeArtifact`) and lock-file I/O
|
|
438
438
|
import from `@xano/sdk/node`, NOT the browser-safe `@xano/sdk` entry (a frontend
|
|
439
|
-
imports
|
|
439
|
+
imports from it; request types come from `routes.gen.ts`). `@xano/sdk/internal` is the
|
|
440
440
|
compiler machinery, never needed to author. READING a bundle back is `@xano/sdk/bundle`
|
|
441
441
|
— a statement walker (`2.if.0` paths), a structural hash, `mvp:*` catalog, `tableRefOf`.
|
|
442
442
|
- **Intra-workspace imports use `.js` specifiers** (`../tables/links.js`), not
|