@xano/sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +788 -0
- package/LICENSE +21 -0
- package/README.md +541 -0
- package/dist/.build-fingerprint +1 -0
- package/dist/agent-file-refresh-ZEMK33AX.js +38 -0
- package/dist/answer-shape-K67TAAPY.js +33 -0
- package/dist/backend-dir-2U53CIAL.js +39 -0
- package/dist/backend-slot-7QXW2QYC.js +28 -0
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +255 -0
- package/dist/branch-NCRNWQBQ.js +61 -0
- package/dist/branch-commands-ACIRCEQJ.js +79 -0
- package/dist/bundle.d.ts +223 -0
- package/dist/bundle.js +153 -0
- package/dist/capture-WAXPD7DR.js +41 -0
- package/dist/chunk-27GWNP2I.js +23 -0
- package/dist/chunk-2CMJZDCL.js +177 -0
- package/dist/chunk-2EZ3ZJZZ.js +302 -0
- package/dist/chunk-2GNFDZA2.js +390 -0
- package/dist/chunk-2MNLRIOX.js +11 -0
- package/dist/chunk-2TFRR6JV.js +104 -0
- package/dist/chunk-2ZUEE4EK.js +408 -0
- package/dist/chunk-36JUQZVQ.js +22 -0
- package/dist/chunk-3DRXWLJ5.js +83 -0
- package/dist/chunk-3JDU4VRL.js +137 -0
- package/dist/chunk-3KZCLN4Z.js +241 -0
- package/dist/chunk-3LDULPRE.js +168 -0
- package/dist/chunk-3M4LFYNQ.js +111 -0
- package/dist/chunk-3XI5CTUE.js +22 -0
- package/dist/chunk-3YW23UFH.js +50 -0
- package/dist/chunk-45UIT5T2.js +862 -0
- package/dist/chunk-4BW2SG2N.js +46 -0
- package/dist/chunk-4KHEMC32.js +79 -0
- package/dist/chunk-4POWHT2K.js +321 -0
- package/dist/chunk-4Q2GN7NW.js +192 -0
- package/dist/chunk-5A2PLKZB.js +70 -0
- package/dist/chunk-5FBYXK5P.js +159 -0
- package/dist/chunk-5HVXPTU4.js +323 -0
- package/dist/chunk-5QU2P5CA.js +304 -0
- package/dist/chunk-5V5XU32D.js +191 -0
- package/dist/chunk-5ZSO4T2G.js +10 -0
- package/dist/chunk-622HUCZT.js +10 -0
- package/dist/chunk-65HWOMGV.js +177 -0
- package/dist/chunk-6ELFRN3P.js +365 -0
- package/dist/chunk-6HO3NCSJ.js +1055 -0
- package/dist/chunk-6IUMKYWI.js +457 -0
- package/dist/chunk-6KEB3C3U.js +65 -0
- package/dist/chunk-6MR5TI5V.js +987 -0
- package/dist/chunk-6NNTNXN7.js +157 -0
- package/dist/chunk-6PBR37LN.js +97 -0
- package/dist/chunk-6QXLMMT3.js +155 -0
- package/dist/chunk-6ZGJCBZS.js +224 -0
- package/dist/chunk-73IVBKMA.js +250 -0
- package/dist/chunk-7G3CTU7I.js +286 -0
- package/dist/chunk-A3UDOZB6.js +222 -0
- package/dist/chunk-A6E77GDW.js +85 -0
- package/dist/chunk-AHJWCYQO.js +660 -0
- package/dist/chunk-AKNCFVKZ.js +36 -0
- package/dist/chunk-AM4FKL4J.js +237 -0
- package/dist/chunk-AN6BL47T.js +26 -0
- package/dist/chunk-AOSYVMUS.js +147 -0
- package/dist/chunk-APWXY5SL.js +182 -0
- package/dist/chunk-AWEIIR2U.js +218 -0
- package/dist/chunk-AWQ7BQTQ.js +73 -0
- package/dist/chunk-BAUZOWGX.js +393 -0
- package/dist/chunk-BHACRS6R.js +940 -0
- package/dist/chunk-BWPNT55T.js +680 -0
- package/dist/chunk-C6RIMRU4.js +187 -0
- package/dist/chunk-CGVQZXYG.js +263 -0
- package/dist/chunk-CIMQZRRE.js +162 -0
- package/dist/chunk-CJHQKJU4.js +113 -0
- package/dist/chunk-CTMO46PK.js +1897 -0
- package/dist/chunk-D53J55C5.js +106 -0
- package/dist/chunk-D7VGG3WS.js +90 -0
- package/dist/chunk-DAD3ONIS.js +245 -0
- package/dist/chunk-DGWHAVRG.js +162 -0
- package/dist/chunk-DX4QR4B2.js +483 -0
- package/dist/chunk-EHP3WPEG.js +21 -0
- package/dist/chunk-ELP2HMXC.js +432 -0
- package/dist/chunk-ERVIASGL.js +21 -0
- package/dist/chunk-ET4Y4XCB.js +865 -0
- package/dist/chunk-ETO6LGLD.js +4750 -0
- package/dist/chunk-EUUUMY7J.js +24 -0
- package/dist/chunk-FQJ2TTHP.js +218 -0
- package/dist/chunk-FQOF7E2E.js +133 -0
- package/dist/chunk-FWD7AL6N.js +21 -0
- package/dist/chunk-FXFV3KU6.js +138 -0
- package/dist/chunk-FXRQOWTE.js +171 -0
- package/dist/chunk-G554NZNI.js +210 -0
- package/dist/chunk-GSGDWJB5.js +13 -0
- package/dist/chunk-H2V3N23D.js +66 -0
- package/dist/chunk-H5C7MBCR.js +159 -0
- package/dist/chunk-HHN734BU.js +371 -0
- package/dist/chunk-HRVBLCVJ.js +243 -0
- package/dist/chunk-HVRUQXGD.js +1264 -0
- package/dist/chunk-I4F5TCJH.js +130 -0
- package/dist/chunk-IDOTCMDV.js +57 -0
- package/dist/chunk-IGOLHKWF.js +427 -0
- package/dist/chunk-JGE7CAWB.js +148 -0
- package/dist/chunk-JTUKLCXS.js +92 -0
- package/dist/chunk-JZGVVJSI.js +66 -0
- package/dist/chunk-K4WX6UUU.js +923 -0
- package/dist/chunk-K5BBGTYZ.js +217 -0
- package/dist/chunk-K6RXBGUB.js +427 -0
- package/dist/chunk-KTSDSD36.js +165 -0
- package/dist/chunk-L5JYN3NM.js +1038 -0
- package/dist/chunk-LIEOKXKD.js +354 -0
- package/dist/chunk-LLNZGEFK.js +51 -0
- package/dist/chunk-LPECSJ2J.js +55 -0
- package/dist/chunk-LQCMKAJ7.js +413 -0
- package/dist/chunk-LRN4ZJCQ.js +1145 -0
- package/dist/chunk-MJ4ZVHKN.js +17 -0
- package/dist/chunk-MXHSQOC4.js +3061 -0
- package/dist/chunk-N5GKCWE5.js +367 -0
- package/dist/chunk-NA3PXMEF.js +10 -0
- package/dist/chunk-NAQDMEHV.js +76 -0
- package/dist/chunk-NWKXM5RD.js +109 -0
- package/dist/chunk-NZOWWHU5.js +196 -0
- package/dist/chunk-OHX6MIUZ.js +184 -0
- package/dist/chunk-OOXWYAA4.js +15 -0
- package/dist/chunk-OPHB5ORL.js +1990 -0
- package/dist/chunk-OXA6PSZT.js +1725 -0
- package/dist/chunk-P2HAGF6H.js +73 -0
- package/dist/chunk-PTHVMXZI.js +3036 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-Q325JKYB.js +189 -0
- package/dist/chunk-Q7DGTQ5G.js +255 -0
- package/dist/chunk-QCNYHBL7.js +601 -0
- package/dist/chunk-QO6BVGS5.js +145 -0
- package/dist/chunk-QXTKSOFI.js +76 -0
- package/dist/chunk-ROY4YAEQ.js +66 -0
- package/dist/chunk-RTJRZFFY.js +447 -0
- package/dist/chunk-SAVJUS2X.js +128 -0
- package/dist/chunk-SFLHVCKX.js +173 -0
- package/dist/chunk-STSFNCY4.js +127 -0
- package/dist/chunk-SWBF2LTK.js +170 -0
- package/dist/chunk-T5KELPAR.js +109 -0
- package/dist/chunk-TFFGOFVZ.js +1481 -0
- package/dist/chunk-TLHIFK4M.js +256 -0
- package/dist/chunk-TLQE7ZN3.js +156 -0
- package/dist/chunk-TPHWJ7UG.js +1981 -0
- package/dist/chunk-TRJCALW3.js +291 -0
- package/dist/chunk-TTEIYD5P.js +133 -0
- package/dist/chunk-U64O2MXY.js +407 -0
- package/dist/chunk-UCQ2VUTG.js +630 -0
- package/dist/chunk-UTI5G6OJ.js +44 -0
- package/dist/chunk-UVHDMMIP.js +188 -0
- package/dist/chunk-UZ6QQWJT.js +120 -0
- package/dist/chunk-VAX3UZOY.js +686 -0
- package/dist/chunk-W3HBUKFO.js +57 -0
- package/dist/chunk-WKQLGKCL.js +2823 -0
- package/dist/chunk-WQFNASK4.js +560 -0
- package/dist/chunk-WRBKLYSJ.js +224 -0
- package/dist/chunk-WTPZRR4I.js +17 -0
- package/dist/chunk-WZDJ2LLX.js +2385 -0
- package/dist/chunk-X2NL4KUO.js +14 -0
- package/dist/chunk-X4DVXBFY.js +38 -0
- package/dist/chunk-X677DMZM.js +7050 -0
- package/dist/chunk-XBKMWY7F.js +612 -0
- package/dist/chunk-XNCP4KYO.js +78 -0
- package/dist/chunk-XVBGLISP.js +35 -0
- package/dist/chunk-XW6KISBB.js +1192 -0
- package/dist/chunk-YGZHHAAB.js +8156 -0
- package/dist/chunk-YHEFQUQB.js +186 -0
- package/dist/chunk-YLDALTWZ.js +653 -0
- package/dist/chunk-YU4HSQW7.js +229 -0
- package/dist/chunk-ZDPP6RKB.js +27 -0
- package/dist/chunk-ZFDZKNGG.js +194 -0
- package/dist/chunk-ZIY7RNUT.js +49 -0
- package/dist/chunk-ZYJP6BOO.js +30 -0
- package/dist/cli.d.ts +1111 -0
- package/dist/cli.js +165 -0
- package/dist/codegen-command-VR2GWR6C.js +173 -0
- package/dist/codegen.d.ts +115 -0
- package/dist/codegen.js +19 -0
- package/dist/commands-GJMJ4XYZ.js +76 -0
- package/dist/completion-ZQLO6PB6.js +738 -0
- package/dist/config-MBYGCAFK.js +136 -0
- package/dist/deploy-command-JVZPWHMK.js +180 -0
- package/dist/deploy-source-3W45CXMP.js +81 -0
- package/dist/dev-env-sync-HN44K4D5.js +188 -0
- package/dist/diagnostics-UEAAHWVF.js +30 -0
- package/dist/display-name-hint-ABBPVQIR.js +46 -0
- package/dist/emit-CyhBDxli.d.ts +7007 -0
- package/dist/env-example-refresh-ET5HMMDW.js +126 -0
- package/dist/env-pull-command-TNMNB3CV.js +323 -0
- package/dist/env-target-O4HRKTGZ.js +40 -0
- package/dist/env-var-command-ZIRDCAZA.js +427 -0
- package/dist/ephemeral-P7F3PMAD.js +54 -0
- package/dist/ephemeral-command-CLJJKOFT.js +592 -0
- package/dist/ephemeral-state-PYCBSOGX.js +61 -0
- package/dist/file-lock-PT74GWYW.js +10 -0
- package/dist/generate-command-AYEOLA26.js +510 -0
- package/dist/gitignore-3SJ3WNRG.js +51 -0
- package/dist/guards-4EBNCZDC.js +162 -0
- package/dist/hosted-file-PSHJB3HX.js +28 -0
- package/dist/impersonate-command-5JAS3WSV.js +152 -0
- package/dist/import-EQSFU6JC.js +19 -0
- package/dist/index.d.ts +5470 -0
- package/dist/index.js +371 -0
- package/dist/init-command-X2FR4UAK.js +125 -0
- package/dist/init-modules-RY7UHAOL.js +50 -0
- package/dist/init-web-M4YZSZK6.js +42 -0
- package/dist/internal.d.ts +179 -0
- package/dist/internal.js +2634 -0
- package/dist/io-RC56QSN5.js +26 -0
- package/dist/keep-data-merge-7MPLVAVI.js +1119 -0
- package/dist/lambda-config-reconcile-OUZ4OYAB.js +116 -0
- package/dist/landed-753YLJ5H.js +40 -0
- package/dist/landing-record-SU52SKXU.js +61 -0
- package/dist/live-diff-YONW2VI3.js +65 -0
- package/dist/local-engine-choice-CH5X3W7E.js +79 -0
- package/dist/local-engine-command-Z3OL7VOD.js +766 -0
- package/dist/local-engine-config-5U3SC434.js +39 -0
- package/dist/local-engine-deploy-PCQ4SNPB.js +39 -0
- package/dist/local-engine-process-EHTE5LLU.js +63 -0
- package/dist/local-engine-state-A4FTRFAF.js +32 -0
- package/dist/local-engine-update-check-6L645VBL.js +162 -0
- package/dist/lock-MRRHW5GS.js +87 -0
- package/dist/lock-commands-2QG25HL7.js +963 -0
- package/dist/login-command-QPYRWOXZ.js +538 -0
- package/dist/logout-command-WOIQLDP6.js +56 -0
- package/dist/loop-ALIZLOSX.js +191 -0
- package/dist/marketplace-command-K5YL42NO.js +977 -0
- package/dist/marketplace-resolve-LY32JES5.js +40 -0
- package/dist/meta-client-YXGPW53C.js +244 -0
- package/dist/module-manifest-JFGHU2TC.js +38 -0
- package/dist/near-key.d.ts +13 -0
- package/dist/near-key.js +8 -0
- package/dist/node.d.ts +95 -0
- package/dist/node.js +969 -0
- package/dist/operation-outcome-TZSESNC7.js +51 -0
- package/dist/output-target-AL3I44GG.js +47 -0
- package/dist/package-manager-PRAHUSCN.js +34 -0
- package/dist/plan-disclosure-6G4MLZKD.js +114 -0
- package/dist/plugin-contributions-WRNY5ABG.js +28 -0
- package/dist/plugin-prompt-4VA3B4FF.js +20 -0
- package/dist/plugin-questions-JTSYA74Q.js +24 -0
- package/dist/plugin.d.ts +396 -0
- package/dist/plugin.js +1 -0
- package/dist/preflight-command-2T5Z36MI.js +321 -0
- package/dist/profile-command-AH3PIM4X.js +800 -0
- package/dist/profile-pointer-GRWJU3YD.js +31 -0
- package/dist/profile-select-74TRDEPD.js +23 -0
- package/dist/project-dependency-KSH63ODT.js +35 -0
- package/dist/project-sdk-REPPOIBD.js +24 -0
- package/dist/promote-command-PCWT5N6S.js +140 -0
- package/dist/prompt-II3F3LND.js +27 -0
- package/dist/publish-command-TTDUUJI5.js +414 -0
- package/dist/pull-command-VBO7C4S3.js +161 -0
- package/dist/pull-superseded-GJWLG7XO.js +20 -0
- package/dist/release-command-N4ZPKMHR.js +146 -0
- package/dist/release-ns-command-3KFDMZ6G.js +1745 -0
- package/dist/response-HlXahv4K.d.ts +925 -0
- package/dist/retry-command-AS5EVREX.js +34 -0
- package/dist/routes-manifest-SNWUVBT6.js +43 -0
- package/dist/runtime-XETHVF33.js +14 -0
- package/dist/scaffold.d.ts +1911 -0
- package/dist/scaffold.js +107 -0
- package/dist/secrets-file-LVZD6IIM.js +56 -0
- package/dist/secrets-fill-command-TTCPSVXN.js +218 -0
- package/dist/seed-VU7C3QYS.js +46 -0
- package/dist/sent-writes-N7X4OVXT.js +22 -0
- package/dist/source-resolve-S2XA3XZF.js +83 -0
- package/dist/static-host-B2Y6AG3W.js +352 -0
- package/dist/status-command-RUDXTF7I.js +554 -0
- package/dist/store-6VNCD4D7.js +20 -0
- package/dist/store-ARM6VMO5.js +98 -0
- package/dist/store-DuYfzKlW.d.ts +3144 -0
- package/dist/suggest-6FOOYKHG.js +12 -0
- package/dist/sveltekit.d.ts +154 -0
- package/dist/sveltekit.js +109 -0
- package/dist/sync-contributions-UCEROO26.js +415 -0
- package/dist/table-ENAVMITR.js +42 -0
- package/dist/tables-command-GUPXXSB5.js +156 -0
- package/dist/tenant-IIHPOHGP.js +42 -0
- package/dist/tenant-command-D5HGI2X4.js +965 -0
- package/dist/test-command-TIKZMDPZ.js +476 -0
- package/dist/tests-BGGIOK3L.js +26 -0
- package/dist/token-NICJUTMT.js +72 -0
- package/dist/toolchain-hooks-GHKLUJOH.js +96 -0
- package/dist/toolchain-modules-5EAZUONB.js +24 -0
- package/dist/tracked-backend-EIBUMDZA.js +80 -0
- package/dist/update-check-2W2NLDTC.js +136 -0
- package/dist/upgrade-command-QHNFWM7O.js +531 -0
- package/dist/verify-rollout-DRCK5TDD.js +61 -0
- package/dist/whoami-command-STGINTXH.js +51 -0
- package/dist/workspace-2CLHU2LK.js +93 -0
- package/dist/workspace-binding-56PIIPCP.js +54 -0
- package/dist/workspace-command-JEXQETJD.js +535 -0
- package/dist/workspace-env-F2RFMSC5.js +70 -0
- package/dist/workspace-export-OJSH2HIW.js +21 -0
- package/dist/writable-VA7OISSK.js +25 -0
- package/dist/xano-ICFUSPFR.js +42 -0
- package/dist/xanosdk-import-GN42TO2B.js +56 -0
- package/dist/xanosdk-project-S6DXJONQ.js +41 -0
- package/dist/xdo-CxDr2Q1C.d.ts +1371 -0
- package/guides/README.md +33 -0
- package/guides/authoring.md +921 -0
- package/guides/cli.md +401 -0
- package/guides/codegen.md +177 -0
- package/guides/codes.md +404 -0
- package/guides/coverage.md +74 -0
- package/guides/deploying.md +1525 -0
- package/guides/environment.md +400 -0
- package/guides/marketplace.md +415 -0
- package/guides/module-contract.md +558 -0
- package/guides/object-kinds.md +433 -0
- package/guides/project-structure.md +43 -0
- package/guides/scaffold.md +351 -0
- package/guides/typed-frontend.md +242 -0
- package/llms/client.md +63 -0
- package/llms/errors.md +56 -0
- package/llms/fields.md +176 -0
- package/llms/filters.md +183 -0
- package/llms/kinds-agent-mcp.md +30 -0
- package/llms/kinds-core.md +100 -0
- package/llms/kinds-knowledge.md +20 -0
- package/llms/kinds-realtime.md +76 -0
- package/llms/lambda.md +94 -0
- package/llms/legacy.md +44 -0
- package/llms/lock.md +40 -0
- package/llms/object-kinds.md +34 -0
- package/llms/statements-calls.md +62 -0
- package/llms/statements-catalog.md +320 -0
- package/llms/statements-data.md +66 -0
- package/llms/statements-runtime.md +68 -0
- package/llms/tests.md +59 -0
- package/llms/toolchain.md +16 -0
- package/llms/triggers.md +36 -0
- package/llms/values.md +29 -0
- package/llms-full.txt +2085 -0
- package/llms.txt +493 -0
- package/manifest.json +11224 -0
- package/package.json +162 -0
- package/types/lambda-globals.d.ts +129 -0
|
@@ -0,0 +1,963 @@
|
|
|
1
|
+
import {
|
|
2
|
+
checkStandInTokens,
|
|
3
|
+
loadDefault,
|
|
4
|
+
renameCandidatesFor
|
|
5
|
+
} from "./chunk-ETO6LGLD.js";
|
|
6
|
+
import "./chunk-ZIY7RNUT.js";
|
|
7
|
+
import "./chunk-DAD3ONIS.js";
|
|
8
|
+
import "./chunk-HHN734BU.js";
|
|
9
|
+
import "./chunk-LPECSJ2J.js";
|
|
10
|
+
import "./chunk-6NNTNXN7.js";
|
|
11
|
+
import "./chunk-QCNYHBL7.js";
|
|
12
|
+
import "./chunk-2ZUEE4EK.js";
|
|
13
|
+
import "./chunk-AN6BL47T.js";
|
|
14
|
+
import "./chunk-ET4Y4XCB.js";
|
|
15
|
+
import "./chunk-SWBF2LTK.js";
|
|
16
|
+
import "./chunk-UZ6QQWJT.js";
|
|
17
|
+
import "./chunk-A3UDOZB6.js";
|
|
18
|
+
import "./chunk-2MNLRIOX.js";
|
|
19
|
+
import "./chunk-3M4LFYNQ.js";
|
|
20
|
+
import "./chunk-AM4FKL4J.js";
|
|
21
|
+
import "./chunk-Q325JKYB.js";
|
|
22
|
+
import "./chunk-STSFNCY4.js";
|
|
23
|
+
import "./chunk-I4F5TCJH.js";
|
|
24
|
+
import {
|
|
25
|
+
allLandings
|
|
26
|
+
} from "./chunk-5QU2P5CA.js";
|
|
27
|
+
import "./chunk-ZYJP6BOO.js";
|
|
28
|
+
import "./chunk-QO6BVGS5.js";
|
|
29
|
+
import "./chunk-JZGVVJSI.js";
|
|
30
|
+
import "./chunk-7G3CTU7I.js";
|
|
31
|
+
import "./chunk-6PBR37LN.js";
|
|
32
|
+
import "./chunk-T5KELPAR.js";
|
|
33
|
+
import "./chunk-622HUCZT.js";
|
|
34
|
+
import {
|
|
35
|
+
contextFlags
|
|
36
|
+
} from "./chunk-NAQDMEHV.js";
|
|
37
|
+
import {
|
|
38
|
+
backendDirIn
|
|
39
|
+
} from "./chunk-5A2PLKZB.js";
|
|
40
|
+
import {
|
|
41
|
+
XANO_DIR
|
|
42
|
+
} from "./chunk-AHJWCYQO.js";
|
|
43
|
+
import "./chunk-DX4QR4B2.js";
|
|
44
|
+
import "./chunk-6QXLMMT3.js";
|
|
45
|
+
import "./chunk-ZFDZKNGG.js";
|
|
46
|
+
import {
|
|
47
|
+
shellWord
|
|
48
|
+
} from "./chunk-FWD7AL6N.js";
|
|
49
|
+
import "./chunk-2GNFDZA2.js";
|
|
50
|
+
import "./chunk-JTUKLCXS.js";
|
|
51
|
+
import "./chunk-4KHEMC32.js";
|
|
52
|
+
import "./chunk-U64O2MXY.js";
|
|
53
|
+
import "./chunk-ROY4YAEQ.js";
|
|
54
|
+
import {
|
|
55
|
+
readLockFile,
|
|
56
|
+
writeLockFile
|
|
57
|
+
} from "./chunk-P2HAGF6H.js";
|
|
58
|
+
import "./chunk-TLQE7ZN3.js";
|
|
59
|
+
import "./chunk-WRBKLYSJ.js";
|
|
60
|
+
import "./chunk-3LDULPRE.js";
|
|
61
|
+
import "./chunk-XW6KISBB.js";
|
|
62
|
+
import "./chunk-AWQ7BQTQ.js";
|
|
63
|
+
import "./chunk-EUUUMY7J.js";
|
|
64
|
+
import "./chunk-YLDALTWZ.js";
|
|
65
|
+
import "./chunk-5FBYXK5P.js";
|
|
66
|
+
import "./chunk-LLNZGEFK.js";
|
|
67
|
+
import "./chunk-QXTKSOFI.js";
|
|
68
|
+
import "./chunk-X2NL4KUO.js";
|
|
69
|
+
import "./chunk-OPHB5ORL.js";
|
|
70
|
+
import "./chunk-UCQ2VUTG.js";
|
|
71
|
+
import "./chunk-DGWHAVRG.js";
|
|
72
|
+
import "./chunk-JGE7CAWB.js";
|
|
73
|
+
import {
|
|
74
|
+
CliError,
|
|
75
|
+
LocalFileNotFoundError,
|
|
76
|
+
UsageError,
|
|
77
|
+
detail,
|
|
78
|
+
displayPath,
|
|
79
|
+
info,
|
|
80
|
+
isMachineOutput,
|
|
81
|
+
missingArgument,
|
|
82
|
+
pastePath,
|
|
83
|
+
relForwardSlash,
|
|
84
|
+
safeText,
|
|
85
|
+
unknownSubcommand,
|
|
86
|
+
warn,
|
|
87
|
+
writeJson
|
|
88
|
+
} from "./chunk-PTHVMXZI.js";
|
|
89
|
+
import "./chunk-MXHSQOC4.js";
|
|
90
|
+
import "./chunk-6IUMKYWI.js";
|
|
91
|
+
import "./chunk-2CMJZDCL.js";
|
|
92
|
+
import {
|
|
93
|
+
Xano
|
|
94
|
+
} from "./chunk-CTMO46PK.js";
|
|
95
|
+
import "./chunk-ZDPP6RKB.js";
|
|
96
|
+
import "./chunk-K5BBGTYZ.js";
|
|
97
|
+
import "./chunk-LQCMKAJ7.js";
|
|
98
|
+
import "./chunk-YGZHHAAB.js";
|
|
99
|
+
import "./chunk-XVBGLISP.js";
|
|
100
|
+
import "./chunk-6HO3NCSJ.js";
|
|
101
|
+
import "./chunk-5V5XU32D.js";
|
|
102
|
+
import "./chunk-GSGDWJB5.js";
|
|
103
|
+
import "./chunk-HVRUQXGD.js";
|
|
104
|
+
import "./chunk-ERVIASGL.js";
|
|
105
|
+
import "./chunk-4POWHT2K.js";
|
|
106
|
+
import "./chunk-H2V3N23D.js";
|
|
107
|
+
import "./chunk-3JDU4VRL.js";
|
|
108
|
+
import "./chunk-WTPZRR4I.js";
|
|
109
|
+
import {
|
|
110
|
+
suggest
|
|
111
|
+
} from "./chunk-UTI5G6OJ.js";
|
|
112
|
+
import {
|
|
113
|
+
setDiagnosticSink
|
|
114
|
+
} from "./chunk-2EZ3ZJZZ.js";
|
|
115
|
+
import {
|
|
116
|
+
LOCK_PAYLOAD_KEYS,
|
|
117
|
+
LockEntryNotFoundError,
|
|
118
|
+
LockImportConflictError,
|
|
119
|
+
LockRenameConflictError,
|
|
120
|
+
NotABundleError,
|
|
121
|
+
UnknownLockKindError,
|
|
122
|
+
WORKSPACE_KEY,
|
|
123
|
+
acceptedLockKinds,
|
|
124
|
+
adoptFromBundle,
|
|
125
|
+
checkRenameTarget,
|
|
126
|
+
createLockContext,
|
|
127
|
+
displayLockKey,
|
|
128
|
+
emptyLock,
|
|
129
|
+
normalizeLockKey,
|
|
130
|
+
renameLockEntry,
|
|
131
|
+
resolvePayloadKey,
|
|
132
|
+
sdkKindName2 as sdkKindName,
|
|
133
|
+
toolsetKindsFromLock,
|
|
134
|
+
toolsetKindsFromPayload,
|
|
135
|
+
withObjects
|
|
136
|
+
} from "./chunk-6MR5TI5V.js";
|
|
137
|
+
import "./chunk-5ZSO4T2G.js";
|
|
138
|
+
import "./chunk-XNCP4KYO.js";
|
|
139
|
+
import "./chunk-AKNCFVKZ.js";
|
|
140
|
+
import "./chunk-YU4HSQW7.js";
|
|
141
|
+
import "./chunk-TFFGOFVZ.js";
|
|
142
|
+
import "./chunk-G554NZNI.js";
|
|
143
|
+
import "./chunk-N5GKCWE5.js";
|
|
144
|
+
import "./chunk-OXA6PSZT.js";
|
|
145
|
+
import "./chunk-VAX3UZOY.js";
|
|
146
|
+
import {
|
|
147
|
+
rawDeriveGuid
|
|
148
|
+
} from "./chunk-NZOWWHU5.js";
|
|
149
|
+
import {
|
|
150
|
+
resetLockOverrides,
|
|
151
|
+
seedLockOverrides
|
|
152
|
+
} from "./chunk-4BW2SG2N.js";
|
|
153
|
+
import "./chunk-TTEIYD5P.js";
|
|
154
|
+
import "./chunk-CIMQZRRE.js";
|
|
155
|
+
import "./chunk-OHX6MIUZ.js";
|
|
156
|
+
import "./chunk-36JUQZVQ.js";
|
|
157
|
+
import "./chunk-PZ5AY32C.js";
|
|
158
|
+
|
|
159
|
+
// src/emit/lock-commands.ts
|
|
160
|
+
import { existsSync, readFileSync, statSync } from "fs";
|
|
161
|
+
import { basename, dirname, join, resolve } from "path";
|
|
162
|
+
import { execFileSync } from "child_process";
|
|
163
|
+
function readExistingLock(lockPath, subcommand, tolerateDuplicates = false) {
|
|
164
|
+
if (!existsSync(lockPath)) {
|
|
165
|
+
throw new UsageError(
|
|
166
|
+
`lock ${subcommand}: no lock file at ${displayPath(lockPath)}. The first \`xanosdk export\` writes xano.lock beside the entry file; point at an existing one with \`--lock=<path>\` or \`--entry=<entry-file>\`.`,
|
|
167
|
+
{ hintFor: { command: "lock", subcommand } }
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
return readLockFile(lockPath, { tolerateDuplicates });
|
|
171
|
+
}
|
|
172
|
+
function warnRemainingDuplicates(lockPath) {
|
|
173
|
+
try {
|
|
174
|
+
readLockFile(lockPath);
|
|
175
|
+
} catch (err) {
|
|
176
|
+
warn(err instanceof Error ? err.message : String(err), "lock.duplicate-identity");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function payloadKeyFor(kind, subcommand) {
|
|
180
|
+
try {
|
|
181
|
+
return resolvePayloadKey(kind);
|
|
182
|
+
} catch (err) {
|
|
183
|
+
if (err instanceof UnknownLockKindError) {
|
|
184
|
+
const meant = suggest(kind, acceptedLockKinds());
|
|
185
|
+
throw new UsageError(meant === void 0 ? err.message : `${err.message} Did you mean "${safeText(meant)}"?`, {
|
|
186
|
+
hintFor: { command: "lock", subcommand }
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
throw err;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function humanOut(args) {
|
|
193
|
+
return isMachineOutput(args) ? process.stderr : process.stdout;
|
|
194
|
+
}
|
|
195
|
+
function entryDoc(entry) {
|
|
196
|
+
return {
|
|
197
|
+
...entry.guid !== void 0 ? { guid: entry.guid } : {},
|
|
198
|
+
...entry.canonical !== void 0 ? { canonical: entry.canonical } : {}
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
async function runLockCommand(args) {
|
|
202
|
+
const [sub] = args.positionals;
|
|
203
|
+
switch (sub) {
|
|
204
|
+
case "rename":
|
|
205
|
+
return lockRename(args);
|
|
206
|
+
case "prune":
|
|
207
|
+
return lockPrune(args);
|
|
208
|
+
case "import":
|
|
209
|
+
return await lockAdopt(args);
|
|
210
|
+
default:
|
|
211
|
+
throw unknownSubcommand("lock", sub);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function describeEntry(entry) {
|
|
215
|
+
const parts = [];
|
|
216
|
+
if (entry.guid !== void 0) parts.push(`guid ${entry.guid}`);
|
|
217
|
+
if (entry.canonical !== void 0) parts.push(`canonical ${entry.canonical}`);
|
|
218
|
+
return parts.join(", ");
|
|
219
|
+
}
|
|
220
|
+
function lockBesideEntry(entryFile) {
|
|
221
|
+
return join(dirname(resolve(entryFile)), "xano.lock");
|
|
222
|
+
}
|
|
223
|
+
function commandLockPath(args, subcommand) {
|
|
224
|
+
if (args.lockPath !== void 0) return resolve(args.lockPath);
|
|
225
|
+
if (args.entryPath !== void 0) return lockBesideEntry(args.entryPath);
|
|
226
|
+
const found = defaultLockPath();
|
|
227
|
+
const cwdLock = resolve("xano.lock");
|
|
228
|
+
if (found !== cwdLock && existsSync(cwdLock)) {
|
|
229
|
+
const shown = displayPath(found);
|
|
230
|
+
warn(
|
|
231
|
+
`A xano.lock also sits at the project root, but \`xanosdk export\` reads ${shown} (beside ${displayPath(entryBesideLock(found) ?? found)}), so ${subcommand === "import" ? "this import writes" : "this uses"} ${shown}. If the root one holds identities you adopted, move it there before exporting (\`mv ${pasteShown(cwdLock)} ${pasteShown(found)}\`); otherwise delete it.`,
|
|
232
|
+
"lock.root-shadowed"
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
if (found === cwdLock && !existsSync(cwdLock)) {
|
|
236
|
+
const backendDir = relForwardSlash(process.cwd(), backendDirIn(process.cwd())) || XANO_DIR;
|
|
237
|
+
const nested = resolve(backendDir, "xano.lock");
|
|
238
|
+
if (existsSync(nested)) {
|
|
239
|
+
const where = pastePath(".") === "." ? "in this directory" : "at the project root";
|
|
240
|
+
throw new UsageError(
|
|
241
|
+
`lock ${subcommand}: no xano.lock ${where}, but one exists at ${pasteShown(nested)} \u2014 the lock sits beside the entry file, in this project's backend directory. Re-run with \`--entry=${pasteShown(resolve(backendDir, "index.ts"))}\` (or \`--lock=${pasteShown(nested)}\`).`
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return found;
|
|
246
|
+
}
|
|
247
|
+
function defaultLockPath() {
|
|
248
|
+
const cwd = process.cwd();
|
|
249
|
+
const cwdLock = resolve("xano.lock");
|
|
250
|
+
if (entryBesideLock(cwdLock) !== void 0) return cwdLock;
|
|
251
|
+
const backendDir = backendDirIn(cwd);
|
|
252
|
+
if (resolve(backendDir) === resolve(cwd)) return cwdLock;
|
|
253
|
+
const nestedLock = join(backendDir, "xano.lock");
|
|
254
|
+
return entryBesideLock(nestedLock) !== void 0 ? nestedLock : cwdLock;
|
|
255
|
+
}
|
|
256
|
+
function lockFlags(args, lockPath) {
|
|
257
|
+
if (args.entryPath !== void 0) return ` --entry=${pasteShown(resolve(args.entryPath))}`;
|
|
258
|
+
return resolve(lockPath) === defaultLockPath() ? "" : ` --lock=${pasteShown(lockPath)}`;
|
|
259
|
+
}
|
|
260
|
+
function staleRecordRemedies(destKeys, flags, tenantLock) {
|
|
261
|
+
const out = [];
|
|
262
|
+
for (const key of destKeys) {
|
|
263
|
+
const m = /\/(tenant|ephemeral)\/([^/]+)$/.exec(key);
|
|
264
|
+
if (m === null) continue;
|
|
265
|
+
out.push(`\`xanosdk ${m[1]} delete ${shellWord(m[2])}${m[1] === "tenant" ? tenantLock : ""}${flags}\``);
|
|
266
|
+
}
|
|
267
|
+
return out;
|
|
268
|
+
}
|
|
269
|
+
var ADOPTED_NOTE = "They pin objects still serving on the backend they were adopted from, so pruning them would hand the engine back its own objects as strangers.";
|
|
270
|
+
function pasteShown(path) {
|
|
271
|
+
return shellWord(displayPath(path));
|
|
272
|
+
}
|
|
273
|
+
async function lockRename(args) {
|
|
274
|
+
const [, kind, oldName, newName] = args.positionals;
|
|
275
|
+
if (!kind || !oldName || !newName) {
|
|
276
|
+
throw missingArgument(!kind ? "kind" : !oldName ? "old" : "new", { command: "lock", subcommand: "rename" });
|
|
277
|
+
}
|
|
278
|
+
const payloadKey = payloadKeyFor(kind, "rename");
|
|
279
|
+
try {
|
|
280
|
+
checkRenameTarget(payloadKey, oldName, newName);
|
|
281
|
+
} catch (err) {
|
|
282
|
+
throw new UsageError(err instanceof Error ? err.message : String(err), {
|
|
283
|
+
hintFor: { command: "lock", subcommand: "rename" }
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
const lockPath = commandLockPath(args, "rename");
|
|
287
|
+
const lock = readExistingLock(lockPath, "rename", true);
|
|
288
|
+
const shownKind = payloadKey === "toolset" ? kind === "agent" ? "agent" : "mcpServer" : sdkKindName(payloadKey);
|
|
289
|
+
const newKey = `${payloadKey}:${newName}`;
|
|
290
|
+
const shownNew = `${shownKind}:${newName}`;
|
|
291
|
+
const shownOld = `${shownKind}:${oldName}`;
|
|
292
|
+
const oldKey = `${payloadKey}:${oldName}`;
|
|
293
|
+
const moved = lock.objects[newKey];
|
|
294
|
+
const wasOld = (guid) => guid === rawDeriveGuid(oldKey) || Object.values(lock.landed ?? {}).some((record) => record[oldKey]?.guid === guid) || lockHistory(lockPath)?.(oldKey) === true;
|
|
295
|
+
if (!(oldKey in lock.objects) && moved?.guid !== void 0 && moved.guid !== rawDeriveGuid(newKey) && wasOld(moved.guid)) {
|
|
296
|
+
humanOut(args).write(
|
|
297
|
+
`Lock entry "${shownOld}" is already renamed: "${shownNew}" carries its identity (${describeEntry(moved)}). Nothing to do.
|
|
298
|
+
`
|
|
299
|
+
);
|
|
300
|
+
if (isMachineOutput(args)) {
|
|
301
|
+
writeJson({ verb: "rename", lock: lockPath, from: shownOld, to: shownNew, entry: entryDoc(moved), discardedCanonical: null, movedChildren: [], alreadyRenamed: true });
|
|
302
|
+
}
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
if (!(oldKey in lock.objects)) {
|
|
306
|
+
const sameKind = Object.keys(lock.objects).filter((k) => k.startsWith(`${payloadKey}:`)).map((k) => k.slice(payloadKey.length + 1));
|
|
307
|
+
const meant = suggest(oldName, sameKind);
|
|
308
|
+
throw new LockEntryNotFoundError(
|
|
309
|
+
`No lock entry "${shownOld}" in ${displayPath(lockPath)}` + (meant === void 0 ? "." : ` \u2014 did you mean "${shownKind}:${meant}"?`) + ` \`lock rename\` moves an existing entry \u2014 check the kind and the old name (kinds: ${acceptedKinds()}).`,
|
|
310
|
+
// Kind-qualified, as `lock prune`'s suggestions are (E2E pass 26).
|
|
311
|
+
meant === void 0 ? {} : { suggestion: `${shownKind}:${meant}` }
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
const moving = lock.objects[oldKey].guid;
|
|
315
|
+
const heldAt = allLandings(process.cwd(), lock).filter(
|
|
316
|
+
([, record]) => record[newKey] !== void 0 && record[newKey].guid !== moving
|
|
317
|
+
);
|
|
318
|
+
const target = heldAt[0]?.[1][newKey].guid;
|
|
319
|
+
const landedAt = heldAt.map(([dest]) => dest);
|
|
320
|
+
if (landedAt.length > 0) {
|
|
321
|
+
const prune = `\`xanosdk lock prune --identity-only ${shellWord(shownOld)} --yes${lockFlags(args, lockPath)}\``;
|
|
322
|
+
const landingDefault = join(backendDirIn(process.cwd()), "xano.lock");
|
|
323
|
+
const tenantLock = resolve(lockPath) === resolve(landingDefault) ? "" : ` --lock=${pasteShown(lockPath)}`;
|
|
324
|
+
const stale = staleRecordRemedies(landedAt, contextFlags(args), tenantLock);
|
|
325
|
+
throw new CliError(
|
|
326
|
+
"SDK_IDENTITY_CONFLICT",
|
|
327
|
+
`${newKey in lock.objects ? "Lock entry " : ""}"${shownNew}" (guid ${target}) is live: this project landed it on ${landedAt.join(", ")}, so it is an object of its own there, not "${shownOld}" renamed. Moving "${shownOld}"'s identity onto it would give that backend two identities under one name, and its next deploy would refuse.` + (stale.length === 0 ? "" : ` If ${stale.length === 1 ? "that backend no longer exists" : "a backend named there no longer exists"}, clear this project's stale record of it \u2014 ${stale.join(", ")} \u2014 and run this rename again.`) + ` If "${shownOld}" was deleted (or a deploy already recreated it as "${shownNew}"), drop its entry: ${prune}.`,
|
|
328
|
+
{ exitCode: 2, details: { from: shownOld, to: shownNew, guid: target, landedOn: landedAt } }
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
const held = lock.objects[newKey];
|
|
332
|
+
if (held !== void 0 && (held.imported === true || held.adopted === true) && held.guid !== moving) {
|
|
333
|
+
const prune = `\`xanosdk lock prune --identity-only ${shellWord(shownOld)} --yes${lockFlags(args, lockPath)}\``;
|
|
334
|
+
throw new CliError(
|
|
335
|
+
"SDK_IDENTITY_CONFLICT",
|
|
336
|
+
`Lock entry "${shownNew}" (${describeEntry(held)}) holds the identity \`lock import\` took from a live backend: it is that backend's object, not "${shownOld}" renamed. Moving "${shownOld}"'s identity onto it would replace the live object's guid, and the next deploy there would recreate it. Nothing was written. If "${shownOld}" was deleted (or folded into "${shownNew}"), drop its entry: ${prune}.`,
|
|
337
|
+
{ exitCode: 2, details: { from: shownOld, to: shownNew, guid: held.guid ?? null, imported: true } }
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
const sourceRequired = newKey in lock.objects;
|
|
341
|
+
const implicitEntry = args.entryPath === void 0 ? entryBesideLock(lockPath) : void 0;
|
|
342
|
+
const entryPath = args.entryPath ?? implicitEntry;
|
|
343
|
+
if (implicitEntry !== void 0) {
|
|
344
|
+
humanOut(args).write(`Reading the workspace from ${displayPath(implicitEntry)} (beside the lock) to check the rename.
|
|
345
|
+
`);
|
|
346
|
+
}
|
|
347
|
+
let observed;
|
|
348
|
+
let observedEntries;
|
|
349
|
+
if (entryPath !== void 0) {
|
|
350
|
+
try {
|
|
351
|
+
observedEntries = await observedRenameEntries(entryPath, lock, `${payloadKey}:${oldName}`);
|
|
352
|
+
observed = new Set(Object.keys(observedEntries));
|
|
353
|
+
} catch (err) {
|
|
354
|
+
if (args.entryPath !== void 0 || sourceRequired) throw err;
|
|
355
|
+
warn(
|
|
356
|
+
`Could not evaluate ${displayPath(entryPath)} to check this rename, so nothing confirms "${shownOld}" was renamed in code. Pass \`--entry=<path>\` to check against the workspace.`,
|
|
357
|
+
"lock.rename-unchecked"
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
if (observed !== void 0 && entryPath !== void 0) {
|
|
362
|
+
if (observed.has(`${payloadKey}:${oldName}`) && !sourceRequired) {
|
|
363
|
+
throw new UsageError(
|
|
364
|
+
`"${displayPath(entryPath)}" still exports ${shownKind} "${oldName}", so this is not a rename: moving "${shownOld}" to "${shownNew}" would take its identity away from an object that still uses it. Rename the object in code first, then re-run \`lock rename\`.`,
|
|
365
|
+
{ hintFor: { command: "lock", subcommand: "rename" } }
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
if (!observed.has(newKey)) {
|
|
369
|
+
const unpinned = [...observed].filter((k) => k.startsWith(`${payloadKey}:`) && !(k in lock.objects)).map((k) => JSON.stringify(k.slice(payloadKey.length + 1)));
|
|
370
|
+
throw new UsageError(
|
|
371
|
+
`"${entryPath}" exports no ${shownKind} "${newName}", so an entry moved to "${shownNew}" would match nothing. ` + (unpinned.length > 0 ? `${shownKind} names it exports that the lock does not pin yet: ${unpinned.join(", ")}.` : `Rename the object in code first, then re-run \`lock rename\`.`)
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
const pins = observedEntries?.[newKey]?.guid;
|
|
375
|
+
const inCode = observedEntries?.[newKey]?.guid_source === "code" || pins !== (lock.objects[newKey]?.guid ?? rawDeriveGuid(newKey));
|
|
376
|
+
if (pins !== void 0 && moving !== void 0 && pins !== moving && inCode) {
|
|
377
|
+
throw new CliError(
|
|
378
|
+
"SDK_IDENTITY_CONFLICT",
|
|
379
|
+
`${shownKind} "${newName}" pins its own guid in its def (${pins}), and a def's guid replaces any lock entry: the next export would re-pin "${shownNew}" to it, and a deploy would drop "${oldName}" (guid ${moving}) with everything it holds. Nothing was written. If "${newName}" is "${oldName}" renamed, set its def to \`guid: "${moving}"\` \u2014 the identity then moves with no \`lock rename\`. If it is a new object, "${shownOld}" was deleted: \`xanosdk lock prune --identity-only ${shellWord(shownOld)} --yes${lockFlags(args, lockPath)}\`.`,
|
|
380
|
+
{ exitCode: 2, details: { from: shownOld, to: shownNew, guid: moving, pins } }
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
let result;
|
|
385
|
+
try {
|
|
386
|
+
result = renameLockEntry(lock, payloadKey, oldName, newName, observed, shownKind);
|
|
387
|
+
} catch (err) {
|
|
388
|
+
if (!(err instanceof LockRenameConflictError)) throw err;
|
|
389
|
+
const flags = lockFlags(args, lockPath);
|
|
390
|
+
const prune = (key) => `\`xanosdk lock prune --identity-only ${shellWord(key)} --yes${flags}\``;
|
|
391
|
+
throw new LockRenameConflictError(
|
|
392
|
+
`${err.message} If "${shownOld}" was deleted and "${shownNew}" is the object to keep, drop the old entry: ${prune(shownOld)}. If "${shownNew}" is the renamed "${shownOld}" and its own entry is stale, drop that one first \u2014 ${prune(shownNew)} \u2014 then re-run this rename.`,
|
|
393
|
+
err.keys
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
const { lock: renamed, discardedNewcomer } = result;
|
|
397
|
+
const movedChildren = result.movedChildren.map((c) => ({
|
|
398
|
+
kind: sdkKindName(c.kind),
|
|
399
|
+
from: displayLockKey(c.from),
|
|
400
|
+
to: displayLockKey(c.to)
|
|
401
|
+
}));
|
|
402
|
+
writeLockFile(lockPath, renamed);
|
|
403
|
+
warnRemainingDuplicates(lockPath);
|
|
404
|
+
humanOut(args).write(
|
|
405
|
+
`Renamed lock entry "${shownOld}" \u2192 "${shownNew}" (${describeEntry(renamed.objects[`${payloadKey}:${newName}`])}).
|
|
406
|
+
`
|
|
407
|
+
);
|
|
408
|
+
for (const c of movedChildren) humanOut(args).write(` and its ${c.kind} "${c.from}" \u2192 "${c.to}".
|
|
409
|
+
`);
|
|
410
|
+
const codeCanonical = discardedNewcomer?.canonical_source === "code" ? discardedNewcomer.canonical : void 0;
|
|
411
|
+
const discardedCanonical = codeCanonical === void 0 ? discardedNewcomer?.canonical : void 0;
|
|
412
|
+
if (discardedNewcomer) {
|
|
413
|
+
const said = `replaced the name-derived entry "${shownNew}" held` + (discardedNewcomer.guid !== void 0 ? ` (guid ${discardedNewcomer.guid})` : "") + ` \u2014 it was never the renamed object's identity` + (codeCanonical !== void 0 ? `; kept the canonical ${codeCanonical} your code pins` : discardedCanonical !== void 0 ? `; its minted canonical ${discardedCanonical} was discarded` : "") + `.`;
|
|
414
|
+
humanOut(args).write(` ${said}
|
|
415
|
+
`);
|
|
416
|
+
}
|
|
417
|
+
const exportEntry = entryPath === void 0 ? void 0 : resolve(entryPath);
|
|
418
|
+
const exportLock = exportEntry !== void 0 && lockBesideEntry(exportEntry) === resolve(lockPath) ? "" : ` --lock=${pasteShown(lockPath)}`;
|
|
419
|
+
humanOut(args).write(
|
|
420
|
+
`The next export or deploy emits the original guid under the new name \u2014 \`xanosdk export ${exportEntry === void 0 ? "<entry-file>" : pasteShown(exportEntry)}${exportLock} --out ${process.platform === "win32" ? "NUL" : "/dev/null"}\` records it now, if you want the lock settled first.
|
|
421
|
+
`
|
|
422
|
+
);
|
|
423
|
+
if (isMachineOutput(args)) {
|
|
424
|
+
writeJson({
|
|
425
|
+
verb: "rename",
|
|
426
|
+
lock: lockPath,
|
|
427
|
+
from: shownOld,
|
|
428
|
+
to: shownNew,
|
|
429
|
+
entry: entryDoc(renamed.objects[`${payloadKey}:${newName}`]),
|
|
430
|
+
discardedCanonical: discardedCanonical ?? null,
|
|
431
|
+
movedChildren,
|
|
432
|
+
alreadyRenamed: false
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
async function observedRenameEntries(entryFile, lock, oldKey) {
|
|
437
|
+
const objects = { ...lock.objects };
|
|
438
|
+
delete objects[oldKey];
|
|
439
|
+
return observedLockEntries(entryFile, withObjects(lock, objects), "lock rename");
|
|
440
|
+
}
|
|
441
|
+
async function observedLockKeys(entryFile, lock, verb = "lock prune") {
|
|
442
|
+
return new Set(Object.keys(await observedLockEntries(entryFile, lock, verb)));
|
|
443
|
+
}
|
|
444
|
+
async function observedLockEntries(entryFile, lock, verb) {
|
|
445
|
+
resetLockOverrides();
|
|
446
|
+
seedLockOverrides(lock);
|
|
447
|
+
let def;
|
|
448
|
+
try {
|
|
449
|
+
def = await loadDefault(entryFile);
|
|
450
|
+
} catch (err) {
|
|
451
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
452
|
+
throw new Error(
|
|
453
|
+
`${verb} evaluated "${entryFile}" to find out which lock entries are still live, and loading it failed:
|
|
454
|
+
${reason}
|
|
455
|
+
Finding orphans requires running your workspace source \u2014 anything the entry file does at module scope (asserting env vars, reading config) runs too. To drop entries you can name yourself, no evaluation is needed: \`xanosdk lock prune --identity-only --yes <key>\u2026\` (e.g. \`table:users\`) with \`--lock=<path>\` or \`--entry=<path>\` to locate the lock.`,
|
|
456
|
+
{ cause: err }
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
if (!Xano.isXano(def)) {
|
|
460
|
+
throw new UsageError(`Module "${entryFile}" must default-export a Xano registry for \`${verb}\`.`);
|
|
461
|
+
}
|
|
462
|
+
const ctx = createLockContext(lock);
|
|
463
|
+
const previousSink = setDiagnosticSink(() => {
|
|
464
|
+
});
|
|
465
|
+
try {
|
|
466
|
+
def.export({ lock: ctx, documentationTokens: checkStandInTokens(def).values });
|
|
467
|
+
} finally {
|
|
468
|
+
setDiagnosticSink(previousSink);
|
|
469
|
+
}
|
|
470
|
+
return ctx.observed;
|
|
471
|
+
}
|
|
472
|
+
var ENGINE_WORKSPACE_KEYS = ["salt", "iv", "checksum", "domain_prefix", "sql_schema_name", "installed_services"];
|
|
473
|
+
function isCompiledBundle(bundle) {
|
|
474
|
+
if (bundle === null || typeof bundle !== "object") return false;
|
|
475
|
+
const payload = bundle.payload;
|
|
476
|
+
if (payload === null || typeof payload !== "object") return false;
|
|
477
|
+
const ws = payload.workspace;
|
|
478
|
+
if (ws === null || typeof ws !== "object" || Array.isArray(ws)) return false;
|
|
479
|
+
return !ENGINE_WORKSPACE_KEYS.some((key) => key in ws);
|
|
480
|
+
}
|
|
481
|
+
function isFile(path) {
|
|
482
|
+
try {
|
|
483
|
+
return statSync(path).isFile();
|
|
484
|
+
} catch {
|
|
485
|
+
return false;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
async function lockPrune(args) {
|
|
489
|
+
const [, ...rest] = args.positionals;
|
|
490
|
+
if (args.identityOnly) {
|
|
491
|
+
const [first, ...others] = rest;
|
|
492
|
+
if (args.entryPath === void 0 && first !== void 0 && isFile(first)) {
|
|
493
|
+
return lockPruneNamed({ ...args, entryPath: first }, others, false);
|
|
494
|
+
}
|
|
495
|
+
return lockPruneNamed(args, rest, args.entryPath !== void 0);
|
|
496
|
+
}
|
|
497
|
+
let entryFile;
|
|
498
|
+
let typedKeys;
|
|
499
|
+
if (args.entryPath !== void 0) {
|
|
500
|
+
entryFile = args.entryPath;
|
|
501
|
+
typedKeys = rest;
|
|
502
|
+
} else {
|
|
503
|
+
[entryFile, ...typedKeys] = rest;
|
|
504
|
+
}
|
|
505
|
+
if (!entryFile) {
|
|
506
|
+
throw missingArgument("entry-file", { command: "lock", subcommand: "prune" });
|
|
507
|
+
}
|
|
508
|
+
if (!isFile(entryFile)) {
|
|
509
|
+
throw new UsageError(`lock prune: no entry file at ${entryFile}.`, {
|
|
510
|
+
hintFor: { command: "lock", subcommand: "prune" }
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
const keys = typedKeys.map(normalizeLockKey);
|
|
514
|
+
const lockPath = args.lockPath !== void 0 ? resolve(args.lockPath) : lockBesideEntry(entryFile);
|
|
515
|
+
const lock = readExistingLock(lockPath, "prune");
|
|
516
|
+
const kinds = typedToolsetKinds(typedKeys, lock);
|
|
517
|
+
const observed = await observedLockKeys(entryFile, lock);
|
|
518
|
+
const orphans = Object.keys(lock.objects).filter((key) => !observed.has(key));
|
|
519
|
+
let targets;
|
|
520
|
+
let gone = [];
|
|
521
|
+
let unproven = [];
|
|
522
|
+
let adopted = [];
|
|
523
|
+
if (keys.length > 0) {
|
|
524
|
+
({ present: targets, gone, unproven } = splitGone(lock, lockPath, keys, args.entryPath !== void 0, kinds));
|
|
525
|
+
for (const key of targets) {
|
|
526
|
+
if (!orphans.includes(key)) {
|
|
527
|
+
throw new UsageError(`Lock entry "${displayLockKey(key, kinds)}" still matches an exported object \u2014 not pruning it.`);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
} else {
|
|
531
|
+
targets = orphans.filter((key) => lock.objects[key].adopted !== true);
|
|
532
|
+
adopted = orphans.filter((key) => lock.objects[key].adopted === true);
|
|
533
|
+
if (adopted.length > 0) {
|
|
534
|
+
const shown = adopted.map((key) => displayLockKey(key, kinds));
|
|
535
|
+
warn(
|
|
536
|
+
`Kept ${entries(adopted.length)} \`lock import\` adopted that this code does not declare: ${shown.join(", ")}. ${ADOPTED_NOTE} To drop them anyway, name them:`,
|
|
537
|
+
"lock.prune-adopted-kept",
|
|
538
|
+
[
|
|
539
|
+
`xanosdk lock prune ${pasteShown(entryFile)} ${shown.map(shellWord).join(" ")}${args.lockPath === void 0 ? "" : ` --lock=${pasteShown(lockPath)}`} --yes`
|
|
540
|
+
]
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
if (targets.length === 0 && gone.length === 0) {
|
|
545
|
+
humanOut(args).write(
|
|
546
|
+
adopted.length === 0 ? "Nothing to prune \u2014 every lock entry matches an exported object.\n" : "Nothing else to prune \u2014 every other lock entry matches an exported object.\n"
|
|
547
|
+
);
|
|
548
|
+
if (isMachineOutput(args)) {
|
|
549
|
+
writeJson({
|
|
550
|
+
verb: "prune",
|
|
551
|
+
lock: lockPath,
|
|
552
|
+
pruned: [],
|
|
553
|
+
alreadyGone: [],
|
|
554
|
+
...adopted.length === 0 ? {} : { keptAdopted: adopted.map((key) => displayLockKey(key, kinds)) },
|
|
555
|
+
discardedCanonicals: 0
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
const candidates = renameCandidatesFor(
|
|
561
|
+
targets,
|
|
562
|
+
lock,
|
|
563
|
+
Object.fromEntries([...observed].map((k) => [k, true])),
|
|
564
|
+
kinds
|
|
565
|
+
);
|
|
566
|
+
const renames = /* @__PURE__ */ new Map();
|
|
567
|
+
for (const key of targets) {
|
|
568
|
+
const c = candidates.get(key);
|
|
569
|
+
if (c === void 0 || c.only === void 0 && c.hint === "") continue;
|
|
570
|
+
const sep = key.indexOf(":");
|
|
571
|
+
const shownKey = displayLockKey(key, kinds);
|
|
572
|
+
const kind = shownKey.slice(0, shownKey.indexOf(":"));
|
|
573
|
+
const placeholder = key.slice(0, sep) === "query" ? `'<group>|<VERB>|<name>'` : "<new-name>";
|
|
574
|
+
const command = `\`xanosdk lock rename ${kind} ${shellWord(key.slice(sep + 1))} ${c.only === void 0 ? placeholder : shellWord(c.only)}${args.lockPath === void 0 ? "" : ` --lock=${pasteShown(lockPath)}`} --entry=${pasteShown(entryFile)}\``;
|
|
575
|
+
renames.set(
|
|
576
|
+
key,
|
|
577
|
+
c.only === void 0 ? `renamed? ${command} keeps its identity${c.hint}` : `renamed to "${c.only}"? ${command} keeps its identity`
|
|
578
|
+
);
|
|
579
|
+
}
|
|
580
|
+
await applyPrune(args, lockPath, lock, targets, kinds, gone, unproven, renames, adopted, entryFile, new Set(orphans));
|
|
581
|
+
}
|
|
582
|
+
function splitGone(lock, lockPath, keys, entryFlag, kinds) {
|
|
583
|
+
const present = [];
|
|
584
|
+
const gone = [];
|
|
585
|
+
const unproven = [];
|
|
586
|
+
let history = null;
|
|
587
|
+
for (const key of keys) {
|
|
588
|
+
if (key in lock.objects) {
|
|
589
|
+
present.push(key);
|
|
590
|
+
continue;
|
|
591
|
+
}
|
|
592
|
+
const colon = key.indexOf(":");
|
|
593
|
+
const knownKind = key === "workspace" || colon > 0 && LOCK_PAYLOAD_KEYS.has(key.slice(0, colon));
|
|
594
|
+
if (!knownKind || isFile(key)) throw noLockEntry(lock, key, entryFlag, kinds, lockPath);
|
|
595
|
+
gone.push(key);
|
|
596
|
+
if (Object.values(lock.landed ?? {}).some((record) => key in record)) continue;
|
|
597
|
+
if (history === null) history = lockHistory(lockPath);
|
|
598
|
+
if (history === void 0 || !history(key)) unproven.push(key);
|
|
599
|
+
}
|
|
600
|
+
return { present, gone, unproven };
|
|
601
|
+
}
|
|
602
|
+
function lockHistory(lockPath) {
|
|
603
|
+
const git = (...argv) => execFileSync("git", argv, {
|
|
604
|
+
cwd: dirname(resolve(lockPath)),
|
|
605
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
606
|
+
timeout: 5e3,
|
|
607
|
+
encoding: "utf8"
|
|
608
|
+
}).trim();
|
|
609
|
+
const file = `./${basename(lockPath)}`;
|
|
610
|
+
try {
|
|
611
|
+
if (git("rev-parse", "--is-shallow-repository") === "true") return void 0;
|
|
612
|
+
if (git("log", "-1", "--format=%H", "--", file) === "") return void 0;
|
|
613
|
+
} catch {
|
|
614
|
+
return void 0;
|
|
615
|
+
}
|
|
616
|
+
return (key) => {
|
|
617
|
+
try {
|
|
618
|
+
return git("log", "-1", "--format=%H", `-S${JSON.stringify(key)}`, "--", file) !== "";
|
|
619
|
+
} catch {
|
|
620
|
+
return false;
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
async function lockPruneNamed(args, keys, entryFlag) {
|
|
625
|
+
if (keys.length === 0) {
|
|
626
|
+
throw new UsageError(
|
|
627
|
+
"`lock prune --identity-only` prunes the entries you name, so it needs at least one key (`table:users`). Without keys there is nothing to prune, because finding orphans is exactly the step --identity-only skips \u2014 drop the flag and pass the entry file to do that.",
|
|
628
|
+
{ helpFor: { command: "lock", subcommand: "prune" } }
|
|
629
|
+
);
|
|
630
|
+
}
|
|
631
|
+
const lockPath = commandLockPath(args, "prune");
|
|
632
|
+
const lock = readExistingLock(lockPath, "prune", true);
|
|
633
|
+
const kinds = typedToolsetKinds(keys, lock);
|
|
634
|
+
const { present, gone, unproven } = splitGone(lock, lockPath, keys.map(normalizeLockKey), entryFlag, kinds);
|
|
635
|
+
keys = present;
|
|
636
|
+
if (keys.length > 0) {
|
|
637
|
+
warn(
|
|
638
|
+
`--identity-only \u2014 nothing was evaluated, so nothing confirms ${keys.length === 1 ? "this key is" : "these keys are"} orphaned. A key the workspace still exports gets a NEW identity at the next export.`,
|
|
639
|
+
"lock.identity-only"
|
|
640
|
+
);
|
|
641
|
+
}
|
|
642
|
+
await applyPrune(args, lockPath, lock, keys, kinds, gone, unproven);
|
|
643
|
+
}
|
|
644
|
+
function typedToolsetKinds(typed, lock) {
|
|
645
|
+
const kinds = toolsetKindsFromLock(lock.objects);
|
|
646
|
+
for (const key of typed) {
|
|
647
|
+
const colon = key.indexOf(":");
|
|
648
|
+
const kind = key.slice(0, colon);
|
|
649
|
+
if (kind === "agent" || kind === "mcpServer" || kind === "mcp_server") {
|
|
650
|
+
kinds.set(key.slice(colon + 1), kind === "agent" ? "agent" : "mcpServer");
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
return kinds;
|
|
654
|
+
}
|
|
655
|
+
function noLockEntry(lock, key, entryFlag, kinds, lockPath) {
|
|
656
|
+
const known = Object.keys(lock.objects);
|
|
657
|
+
const meant = isFile(key) ? void 0 : closestKey(lock, key, kinds);
|
|
658
|
+
const entry = entryBesideLock(lockPath);
|
|
659
|
+
return new LockEntryNotFoundError(
|
|
660
|
+
`No lock entry "${displayLockKey(key, kinds)}" to prune${meant === void 0 ? "." : ` \u2014 did you mean "${meant}"?`}` + (isFile(key) ? entryFlag ? ` It is a file: with \`--entry\` given, every positional is a lock key.` : ` It is a file: only the first positional is the entry file, and every one after it is a lock key.` : "") + (known.length === 0 ? " The lock is empty." : ` Keys look like ${JSON.stringify(displayLockKey(known[0]))} \u2014 run \`xanosdk lock prune ${entry === void 0 ? "<entry-file>" : pasteShown(entry)}\` without keys to list the orphans.`),
|
|
661
|
+
meant === void 0 ? {} : { suggestion: meant }
|
|
662
|
+
);
|
|
663
|
+
}
|
|
664
|
+
function closestKey(lock, key, kinds) {
|
|
665
|
+
return suggest(displayLockKey(key, kinds), Object.keys(lock.objects).map((k) => displayLockKey(k, kinds)));
|
|
666
|
+
}
|
|
667
|
+
function entries(n) {
|
|
668
|
+
return `${n} lock ${n === 1 ? "entry" : "entries"}`;
|
|
669
|
+
}
|
|
670
|
+
function acceptedKinds() {
|
|
671
|
+
return acceptedLockKinds().join(", ");
|
|
672
|
+
}
|
|
673
|
+
function entryBesideLock(lockPath) {
|
|
674
|
+
const dir = dirname(lockPath);
|
|
675
|
+
for (const name of ["index.ts", "index.mts", "index.js", "index.mjs"]) {
|
|
676
|
+
const candidate = join(dir, name);
|
|
677
|
+
if (isFile(candidate)) return candidate;
|
|
678
|
+
}
|
|
679
|
+
return void 0;
|
|
680
|
+
}
|
|
681
|
+
async function applyPrune(args, lockPath, lock, targets, kinds, gone = [], unproven = [], renames = /* @__PURE__ */ new Map(), keptAdopted = [], entryFile, prunable) {
|
|
682
|
+
const proven = unproven.length === 0;
|
|
683
|
+
const kept = keptAdopted.length === 0 ? {} : { keptAdopted: keptAdopted.map((key) => displayLockKey(key, kinds)) };
|
|
684
|
+
const namedAdopted = targets.filter((key) => lock.objects[key]?.adopted === true);
|
|
685
|
+
if (namedAdopted.length > 0) {
|
|
686
|
+
warn(
|
|
687
|
+
`${namedAdopted.map((key) => `"${displayLockKey(key, kinds)}"`).join(", ")} ${namedAdopted.length === 1 ? "was" : "were"} adopted by \`lock import\`. ${ADOPTED_NOTE}`,
|
|
688
|
+
"lock.prune-adopted"
|
|
689
|
+
);
|
|
690
|
+
}
|
|
691
|
+
const goneShown = gone.map((key) => displayLockKey(key, kinds));
|
|
692
|
+
const nearMisses = {};
|
|
693
|
+
for (const key of unproven) {
|
|
694
|
+
const meant = suggest(
|
|
695
|
+
displayLockKey(key, kinds),
|
|
696
|
+
Object.keys(lock.objects).filter((k) => lock.objects[k].adopted !== true && (prunable === void 0 || prunable.has(k))).map((k) => displayLockKey(k, kinds))
|
|
697
|
+
);
|
|
698
|
+
if (meant !== void 0) nearMisses[displayLockKey(key, kinds)] = meant;
|
|
699
|
+
}
|
|
700
|
+
const meants = [...new Set(Object.values(nearMisses))];
|
|
701
|
+
const suggested = meants.length > 0 ? { suggestion: meants[0], ...meants.length > 1 ? { suggestions: meants } : {}, nearMisses } : {};
|
|
702
|
+
const entryWord = args.identityOnly === true ? " --identity-only" : entryFile === void 0 ? "" : ` ${pasteShown(resolve(entryFile))}`;
|
|
703
|
+
const lockWord = args.identityOnly === true ? lockFlags(args, lockPath) : ` --lock=${pasteShown(lockPath)}`;
|
|
704
|
+
for (const [shown, meant] of Object.entries(nearMisses)) {
|
|
705
|
+
warn(`"${shown}" is not in ${displayPath(lockPath)}.`, "lock.prune-near-miss", [
|
|
706
|
+
`Did you mean "${safeText(meant)}"? \`xanosdk lock prune${entryWord} ${shellWord(meant)}${lockWord}\` prunes it, after asking to confirm.`
|
|
707
|
+
]);
|
|
708
|
+
}
|
|
709
|
+
const goneNote = gone.length > 0 ? proven ? `Already pruned (not in ${displayPath(lockPath)}): ${goneShown.join(", ")}.
|
|
710
|
+
` : (
|
|
711
|
+
// No history to tell a typo from a finished prune, so the answer
|
|
712
|
+
// stays the idempotent one; a near miss is named once, by the
|
|
713
|
+
// warning that prints the prune running it (E2E pass 30).
|
|
714
|
+
`Not in ${displayPath(lockPath)} \u2014 already pruned, or never there: ${goneShown.join(", ")}.
|
|
715
|
+
`
|
|
716
|
+
) : "";
|
|
717
|
+
if (targets.length === 0) {
|
|
718
|
+
humanOut(args).write(`Nothing to prune. ${goneNote}`);
|
|
719
|
+
if (isMachineOutput(args)) {
|
|
720
|
+
writeJson({ verb: "prune", lock: lockPath, pruned: [], alreadyGone: goneShown, ...suggested, ...kept, discardedCanonicals: 0 });
|
|
721
|
+
}
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
const lines = targets.sort().map((key) => ` ${displayLockKey(key, kinds)} (${describeEntry(lock.objects[key])})`).join("\n");
|
|
725
|
+
const renameLines = targets.filter((key) => renames.has(key)).map((key) => ` ${displayLockKey(key, kinds)}: ${renames.get(key)} instead.
|
|
726
|
+
`).join("");
|
|
727
|
+
const discarded = targets.filter((key) => lock.objects[key].canonical !== void 0);
|
|
728
|
+
const canonicalNote = (done) => discarded.length > 0 ? `${done ? "Discarded" : "Would discard"} ${discarded.length} ${discarded.length === 1 ? "canonical" : "canonicals"} \u2014 a pruned canonical's public URL is unrecoverable.
|
|
729
|
+
` : "";
|
|
730
|
+
if (!args.yes) {
|
|
731
|
+
humanOut(args).write(`Would prune ${entries(targets.length)}:
|
|
732
|
+
${lines}
|
|
733
|
+
${renameLines}${canonicalNote(false)}${goneNote}`);
|
|
734
|
+
const { confirm } = await import("./prompt-II3F3LND.js");
|
|
735
|
+
const { yesRerun } = await import("./retry-command-AS5EVREX.js");
|
|
736
|
+
const { rerun, note } = yesRerun(args, `lock prune${entryWord}${targets.map((k) => ` ${shellWord(displayLockKey(k, kinds))}`).join("")}${lockWord}`);
|
|
737
|
+
const refusal = {
|
|
738
|
+
details: {
|
|
739
|
+
wouldPrune: targets.map((key) => displayLockKey(key, kinds)),
|
|
740
|
+
alreadyGone: goneShown,
|
|
741
|
+
...suggested,
|
|
742
|
+
...kept,
|
|
743
|
+
wouldDiscardCanonicals: discarded.length
|
|
744
|
+
},
|
|
745
|
+
rerun,
|
|
746
|
+
note
|
|
747
|
+
};
|
|
748
|
+
if (!await confirm(`Prune ${targets.length === 1 ? "it" : "them"} from ${displayPath(lockPath)}?`, { flag: "--yes", refusal })) {
|
|
749
|
+
info(`Lock prune cancelled. Nothing was written to ${displayPath(lockPath)}.`);
|
|
750
|
+
if (isMachineOutput(args)) {
|
|
751
|
+
writeJson({ verb: "prune", lock: lockPath, declined: true, pruned: [], alreadyGone: goneShown, ...suggested, ...kept, discardedCanonicals: 0 });
|
|
752
|
+
}
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
const objects = { ...lock.objects };
|
|
757
|
+
for (const key of targets) delete objects[key];
|
|
758
|
+
writeLockFile(lockPath, withObjects(lock, objects));
|
|
759
|
+
warnRemainingDuplicates(lockPath);
|
|
760
|
+
humanOut(args).write(`Pruned ${entries(targets.length)}:
|
|
761
|
+
${lines}
|
|
762
|
+
${canonicalNote(true)}${goneNote}`);
|
|
763
|
+
if (isMachineOutput(args)) {
|
|
764
|
+
writeJson({
|
|
765
|
+
verb: "prune",
|
|
766
|
+
lock: lockPath,
|
|
767
|
+
pruned: targets.map((key) => displayLockKey(key, kinds)),
|
|
768
|
+
alreadyGone: goneShown,
|
|
769
|
+
...suggested,
|
|
770
|
+
...kept,
|
|
771
|
+
discardedCanonicals: discarded.length
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
async function lockAdopt(args) {
|
|
776
|
+
const [, bundlePath] = args.positionals;
|
|
777
|
+
if (!bundlePath) {
|
|
778
|
+
throw missingArgument("bundle.json", { command: "lock", subcommand: "import" });
|
|
779
|
+
}
|
|
780
|
+
if (!isFile(bundlePath)) {
|
|
781
|
+
throw new (existsSync(bundlePath) ? UsageError : LocalFileNotFoundError)(
|
|
782
|
+
`lock import: no file at ${bundlePath}. It takes a live backend's exported bundle \u2014 \`xanosdk workspace export --path <file>${contextFlags()}\` writes one.`,
|
|
783
|
+
{ hintFor: { command: "lock", subcommand: "import" } }
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
const lockPath = commandLockPath(args, "import");
|
|
787
|
+
const lock = existsSync(lockPath) ? readLockFile(lockPath) : emptyLock();
|
|
788
|
+
let bundle;
|
|
789
|
+
try {
|
|
790
|
+
bundle = JSON.parse(readFileSync(bundlePath, "utf8"));
|
|
791
|
+
} catch (err) {
|
|
792
|
+
throw new UsageError(
|
|
793
|
+
`lock import: ${bundlePath} is not JSON (${err instanceof Error ? err.message : String(err)}). It takes a live backend's exported bundle \u2014 \`xanosdk workspace export --path <file>${contextFlags()}\` writes one.`
|
|
794
|
+
);
|
|
795
|
+
}
|
|
796
|
+
if (isCompiledBundle(bundle)) {
|
|
797
|
+
throw new UsageError(
|
|
798
|
+
`lock import: ${bundlePath} is a bundle this CLI compiled (\`xanosdk export\`), not an export of a live backend. Its identities are the ones your code already derives, so importing it would adopt nothing the backend actually holds. Export the live backend with \`xanosdk workspace export --path <file>${contextFlags()}\` and import that.`,
|
|
799
|
+
{ hintFor: { command: "lock", subcommand: "import" } }
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
let result;
|
|
803
|
+
try {
|
|
804
|
+
result = adoptFromBundle(lock, bundle, bundlePath);
|
|
805
|
+
} catch (err) {
|
|
806
|
+
if (err instanceof LockImportConflictError) {
|
|
807
|
+
const message = err.clash !== void 0 ? await clashMessage(args, lockPath, lock, bundlePath, err.clash) : err.message;
|
|
808
|
+
throw new LockImportConflictError(`lock import: nothing was written. ${message}`);
|
|
809
|
+
}
|
|
810
|
+
if (err instanceof NotABundleError) {
|
|
811
|
+
throw new UsageError(
|
|
812
|
+
`lock import: ${err.message} It takes a live backend's exported bundle \u2014 \`xanosdk workspace export --path <file>${contextFlags()}\` writes one.`,
|
|
813
|
+
{ hintFor: { command: "lock", subcommand: "import" } }
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
throw err;
|
|
817
|
+
}
|
|
818
|
+
const { added, changed, canonicalsSeen, vaultCount, privateVaultCount } = result;
|
|
819
|
+
const adopted = markImported(markAdopted(result.lock, added), result.seen.filter((key) => !added.includes(key)));
|
|
820
|
+
const kinds = toolsetKindsFromPayload(bundle.payload, lock.objects);
|
|
821
|
+
if (changed.length > 0 && !args.yes) {
|
|
822
|
+
const lines = changed.map((c) => ` ${displayLockKey(c.key, kinds)}: ${describeEntry(c.before)} \u2192 ${describeEntry(c.after)}`).join("\n");
|
|
823
|
+
humanOut(args).write(`Adoption would overwrite ${changed.length} existing ${changed.length === 1 ? "lock entry" : "lock entries"}:
|
|
824
|
+
${lines}
|
|
825
|
+
`);
|
|
826
|
+
const { confirm } = await import("./prompt-II3F3LND.js");
|
|
827
|
+
const { yesRerun } = await import("./retry-command-AS5EVREX.js");
|
|
828
|
+
const { rerun, note } = yesRerun(args, `lock import ${shellWord(bundlePath)}`);
|
|
829
|
+
const question = `Overwrite ${changed.length === 1 ? "it" : "them"} with what ${bundlePath} holds?`;
|
|
830
|
+
const refusal = {
|
|
831
|
+
details: { verb: "import", written: false, wouldUpdate: changed.map((c) => displayLockKey(c.key, kinds)) },
|
|
832
|
+
rerun,
|
|
833
|
+
note
|
|
834
|
+
};
|
|
835
|
+
if (!await confirm(question, { flag: "--yes", refusal })) {
|
|
836
|
+
info(`Lock import cancelled. Nothing was written to ${lockPath}.`);
|
|
837
|
+
if (isMachineOutput(args)) {
|
|
838
|
+
writeJson({
|
|
839
|
+
verb: "import",
|
|
840
|
+
lock: lockPath,
|
|
841
|
+
bundle: resolve(bundlePath),
|
|
842
|
+
declined: true,
|
|
843
|
+
added: [],
|
|
844
|
+
updated: [],
|
|
845
|
+
canonicalsSeen,
|
|
846
|
+
vaultEntries: vaultCount
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
if (privateVaultCount > 0) {
|
|
853
|
+
warn(
|
|
854
|
+
`${bundlePath} contains ${privateVaultCount} private stored ${privateVaultCount === 1 ? "file entry" : "file entries"}. Do NOT commit the bundle file; delete it once the import is done.`,
|
|
855
|
+
"secrets.vault-in-bundle"
|
|
856
|
+
);
|
|
857
|
+
}
|
|
858
|
+
if (!canonicalsSeen) {
|
|
859
|
+
warn(
|
|
860
|
+
// NOT a safety guarantee. A public URL
|
|
861
|
+
// slug is unique across the whole INSTANCE, and an import resolves a
|
|
862
|
+
// clash by inventing an identity rather than refusing it — it keeps
|
|
863
|
+
// whatever the object already stored and substitutes a random token when
|
|
864
|
+
// another workspace owns the one asked for, reporting neither. What is
|
|
865
|
+
// true is narrower: the slugs this workspace serves today are not in this
|
|
866
|
+
// file, so adoption cannot have changed them.
|
|
867
|
+
`No canonicals found in ${bundlePath} \u2014 a configuration-only export strips them, so only guids were adopted. Nothing here changed the public URLs this workspace serves, but the lock does not know them either: until an export records one, a release treats every slug as a preference and accepts whatever the workspace already serves. Pin the ones your frontend is built from in code (\`canonical: "..."\`) and re-export \u2014 a pinned slug a release cannot serve fails the release instead of 404-ing your routes.`,
|
|
868
|
+
"lock.no-canonicals"
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
for (const p of result.codePinned) {
|
|
872
|
+
const shown = displayLockKey(p.key, kinds);
|
|
873
|
+
warn(
|
|
874
|
+
`${shown} was not adopted: its def pins \`guid: "${p.guid}"\` in code, which wins over xano.lock, so the live guid ${p.live} would be replaced again at the next export. If the live object is this one, set its def to \`guid: "${p.live}"\` and export; otherwise nothing to do \u2014 the def declares another object than the live one.`,
|
|
875
|
+
"lock.import-code-pinned"
|
|
876
|
+
);
|
|
877
|
+
}
|
|
878
|
+
writeLockFile(lockPath, adopted);
|
|
879
|
+
humanOut(args).write(
|
|
880
|
+
// A re-import of a bundle already adopted: "Adopted …: 0 added, 0 updated"
|
|
881
|
+
// read as something done (E2E pass 16).
|
|
882
|
+
added.length === 0 && changed.length === 0 ? `${lockPath} is already up to date with ${bundlePath} \u2014 nothing to adopt.
|
|
883
|
+
` : `Adopted ${bundlePath} into ${lockPath}: ${added.length} added, ${changed.length} updated.
|
|
884
|
+
`
|
|
885
|
+
);
|
|
886
|
+
const entry = args.entryPath ?? entryBesideLock(lockPath);
|
|
887
|
+
const shownEntry = entry === void 0 ? "<entry-file>" : pasteShown(entry);
|
|
888
|
+
const lockFlag = entry !== void 0 && lockBesideEntry(entry) === resolve(lockPath) ? "" : ` --lock=${pasteShown(lockPath)}`;
|
|
889
|
+
if (added.some((key) => key !== WORKSPACE_KEY) || changed.length > 0) {
|
|
890
|
+
detail(
|
|
891
|
+
`Every identity in ${bundlePath} is now this project's: once a deploy or release lands them on a destination, a \`--prune\` from this project can delete those objects there. If you meant to take over only some, remove the rest before anything lands: \`xanosdk lock prune ${shownEntry} <kind>:<name>\u2026${lockFlag} --yes\`.`
|
|
892
|
+
);
|
|
893
|
+
}
|
|
894
|
+
if (added.length > 0 || changed.length > 0) {
|
|
895
|
+
detail(
|
|
896
|
+
`Next: \`xanosdk export ${shownEntry}${lockFlag} --out ${process.platform === "win32" ? "NUL" : "/dev/null"}\` records what this code emits against it, so \`export --check\` and \`--frozen-lock\` pass \u2014 with \`--allow-lock-orphans\` while this code ports only part of what was adopted: an adopted entry it does not declare is an orphan to them, one still serving live.`
|
|
897
|
+
);
|
|
898
|
+
}
|
|
899
|
+
if (isMachineOutput(args)) {
|
|
900
|
+
writeJson({
|
|
901
|
+
verb: "import",
|
|
902
|
+
lock: lockPath,
|
|
903
|
+
bundle: resolve(bundlePath),
|
|
904
|
+
declined: false,
|
|
905
|
+
added: added.map((key) => displayLockKey(key, kinds)),
|
|
906
|
+
updated: changed.map((c) => displayLockKey(c.key, kinds)),
|
|
907
|
+
codePinned: result.codePinned.map((p) => ({ key: displayLockKey(p.key, kinds), guid: p.guid, live: p.live })),
|
|
908
|
+
canonicalsSeen,
|
|
909
|
+
vaultEntries: vaultCount
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
function markImported(lock, keys) {
|
|
914
|
+
const objects = { ...lock.objects };
|
|
915
|
+
for (const key of keys) {
|
|
916
|
+
const entry = objects[key];
|
|
917
|
+
if (key !== WORKSPACE_KEY && entry?.guid !== void 0 && entry.adopted !== true) objects[key] = { ...entry, imported: true };
|
|
918
|
+
}
|
|
919
|
+
return withObjects(lock, objects);
|
|
920
|
+
}
|
|
921
|
+
function markAdopted(lock, keys) {
|
|
922
|
+
if (keys.length === 0) return lock;
|
|
923
|
+
const objects = { ...lock.objects };
|
|
924
|
+
for (const key of keys) if (key !== WORKSPACE_KEY) objects[key] = { ...objects[key], adopted: true };
|
|
925
|
+
return withObjects(lock, objects);
|
|
926
|
+
}
|
|
927
|
+
async function clashMessage(args, lockPath, lock, bundlePath, clash) {
|
|
928
|
+
const { kind, kindWord, workspaceName, lockName, workspaceKey, lockKey: pinnedKey, guid } = clash;
|
|
929
|
+
const entryPath = args.entryPath ?? entryBesideLock(lockPath);
|
|
930
|
+
const flags = lockFlags(args, lockPath);
|
|
931
|
+
const rename = `\`xanosdk lock rename ${kindWord} ${lockName} ${workspaceName}${flags}\``;
|
|
932
|
+
const head = `${bundlePath} holds guid ${guid} under "${workspaceKey}", but the lock already pins it to "${pinnedKey}".`;
|
|
933
|
+
let observed;
|
|
934
|
+
if (entryPath !== void 0) {
|
|
935
|
+
try {
|
|
936
|
+
observed = await observedLockKeys(entryPath, lock, "lock import");
|
|
937
|
+
} catch {
|
|
938
|
+
observed = void 0;
|
|
939
|
+
} finally {
|
|
940
|
+
resetLockOverrides();
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
if (observed === void 0) {
|
|
944
|
+
return `${head} One side renamed it. If the workspace did, rename it in code to "${workspaceName}" too, then ${rename} and re-run the import. If your source did, the lock already follows it: deploy the rename, then export the workspace again and re-import.`;
|
|
945
|
+
}
|
|
946
|
+
const exportsPinned = observed.has(`${kind}:${lockName}`);
|
|
947
|
+
const exportsWorkspace = observed.has(`${kind}:${workspaceName}`);
|
|
948
|
+
if (exportsPinned && !exportsWorkspace) {
|
|
949
|
+
return `${head} Your source renamed it \u2014 it exports "${lockName}", which the lock already follows \u2014 and the workspace has not received the rename yet. Deploy it, then export the workspace again and re-run the import. To keep the workspace's name instead, rename it back to "${workspaceName}" in code, then ${rename}.`;
|
|
950
|
+
}
|
|
951
|
+
if (exportsWorkspace && !exportsPinned) {
|
|
952
|
+
return `${head} It was renamed on both sides; move the lock entry to match \u2014 ${rename} \u2014 then re-run the import.`;
|
|
953
|
+
}
|
|
954
|
+
if (!exportsPinned) {
|
|
955
|
+
return `${head} The workspace renamed it. Rename it to "${workspaceName}" in code too, then ${rename} and re-run the import.`;
|
|
956
|
+
}
|
|
957
|
+
return `${head} Your source exports both "${lockName}" and "${workspaceName}", so this is not a rename: the workspace's "${workspaceName}" carries the identity your "${lockName}" is pinned to. Export the workspace again after deploying, and re-import.`;
|
|
958
|
+
}
|
|
959
|
+
export {
|
|
960
|
+
isCompiledBundle,
|
|
961
|
+
runLockCommand
|
|
962
|
+
};
|
|
963
|
+
//# sourceMappingURL=lock-commands-2QG25HL7.js.map
|