@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,1119 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assertStorageModesKept,
|
|
3
|
+
discloseTableEffects,
|
|
4
|
+
droppedAndAdded,
|
|
5
|
+
tableEffectFields,
|
|
6
|
+
tableEffectsOf
|
|
7
|
+
} from "./chunk-BWPNT55T.js";
|
|
8
|
+
import "./chunk-TPHWJ7UG.js";
|
|
9
|
+
import {
|
|
10
|
+
tableRowCounter
|
|
11
|
+
} from "./chunk-C6RIMRU4.js";
|
|
12
|
+
import {
|
|
13
|
+
XANOSDK_IMPORT_UNIQUENESS_CODE,
|
|
14
|
+
XanoSdkImportRefusal,
|
|
15
|
+
detectXanoSdkImportRoute,
|
|
16
|
+
xanosdkImport
|
|
17
|
+
} from "./chunk-WQFNASK4.js";
|
|
18
|
+
import {
|
|
19
|
+
exportWorkspaceBundle
|
|
20
|
+
} from "./chunk-CJHQKJU4.js";
|
|
21
|
+
import {
|
|
22
|
+
encodeWorkspaceArchive
|
|
23
|
+
} from "./chunk-3DRXWLJ5.js";
|
|
24
|
+
import "./chunk-X4DVXBFY.js";
|
|
25
|
+
import {
|
|
26
|
+
diffAgainstLive,
|
|
27
|
+
payloadOf,
|
|
28
|
+
planTypeSection,
|
|
29
|
+
rowLabeler,
|
|
30
|
+
sectionKind,
|
|
31
|
+
storedColumnsAfter,
|
|
32
|
+
tableAdditions
|
|
33
|
+
} from "./chunk-45UIT5T2.js";
|
|
34
|
+
import "./chunk-HRVBLCVJ.js";
|
|
35
|
+
import "./chunk-2ZUEE4EK.js";
|
|
36
|
+
import "./chunk-AN6BL47T.js";
|
|
37
|
+
import "./chunk-A3UDOZB6.js";
|
|
38
|
+
import "./chunk-2MNLRIOX.js";
|
|
39
|
+
import "./chunk-7G3CTU7I.js";
|
|
40
|
+
import "./chunk-6PBR37LN.js";
|
|
41
|
+
import "./chunk-NAQDMEHV.js";
|
|
42
|
+
import {
|
|
43
|
+
shellWord
|
|
44
|
+
} from "./chunk-FWD7AL6N.js";
|
|
45
|
+
import "./chunk-4KHEMC32.js";
|
|
46
|
+
import {
|
|
47
|
+
seedRowsByTableGuid
|
|
48
|
+
} from "./chunk-U64O2MXY.js";
|
|
49
|
+
import "./chunk-ROY4YAEQ.js";
|
|
50
|
+
import "./chunk-XW6KISBB.js";
|
|
51
|
+
import "./chunk-AWQ7BQTQ.js";
|
|
52
|
+
import "./chunk-EUUUMY7J.js";
|
|
53
|
+
import {
|
|
54
|
+
UNTRUSTED_CERTIFICATE
|
|
55
|
+
} from "./chunk-YLDALTWZ.js";
|
|
56
|
+
import "./chunk-5FBYXK5P.js";
|
|
57
|
+
import "./chunk-LLNZGEFK.js";
|
|
58
|
+
import "./chunk-QXTKSOFI.js";
|
|
59
|
+
import "./chunk-X2NL4KUO.js";
|
|
60
|
+
import "./chunk-3YW23UFH.js";
|
|
61
|
+
import {
|
|
62
|
+
CliError,
|
|
63
|
+
detail,
|
|
64
|
+
displayPath,
|
|
65
|
+
warn,
|
|
66
|
+
withSpinner
|
|
67
|
+
} from "./chunk-PTHVMXZI.js";
|
|
68
|
+
import "./chunk-2CMJZDCL.js";
|
|
69
|
+
import "./chunk-K5BBGTYZ.js";
|
|
70
|
+
import "./chunk-LQCMKAJ7.js";
|
|
71
|
+
import "./chunk-6HO3NCSJ.js";
|
|
72
|
+
import "./chunk-5V5XU32D.js";
|
|
73
|
+
import "./chunk-HVRUQXGD.js";
|
|
74
|
+
import "./chunk-ERVIASGL.js";
|
|
75
|
+
import "./chunk-4POWHT2K.js";
|
|
76
|
+
import "./chunk-H2V3N23D.js";
|
|
77
|
+
import "./chunk-3JDU4VRL.js";
|
|
78
|
+
import "./chunk-WTPZRR4I.js";
|
|
79
|
+
import "./chunk-UTI5G6OJ.js";
|
|
80
|
+
import "./chunk-2EZ3ZJZZ.js";
|
|
81
|
+
import {
|
|
82
|
+
LOCK_PAYLOAD_KEYS
|
|
83
|
+
} from "./chunk-6MR5TI5V.js";
|
|
84
|
+
import {
|
|
85
|
+
shellQuote
|
|
86
|
+
} from "./chunk-5ZSO4T2G.js";
|
|
87
|
+
import "./chunk-XNCP4KYO.js";
|
|
88
|
+
import "./chunk-YU4HSQW7.js";
|
|
89
|
+
import "./chunk-TFFGOFVZ.js";
|
|
90
|
+
import "./chunk-EHP3WPEG.js";
|
|
91
|
+
import "./chunk-L5JYN3NM.js";
|
|
92
|
+
import "./chunk-G554NZNI.js";
|
|
93
|
+
import "./chunk-N5GKCWE5.js";
|
|
94
|
+
import "./chunk-OXA6PSZT.js";
|
|
95
|
+
import "./chunk-VAX3UZOY.js";
|
|
96
|
+
import "./chunk-NZOWWHU5.js";
|
|
97
|
+
import "./chunk-4BW2SG2N.js";
|
|
98
|
+
import "./chunk-TTEIYD5P.js";
|
|
99
|
+
import "./chunk-CIMQZRRE.js";
|
|
100
|
+
import "./chunk-OHX6MIUZ.js";
|
|
101
|
+
import "./chunk-36JUQZVQ.js";
|
|
102
|
+
import "./chunk-PZ5AY32C.js";
|
|
103
|
+
|
|
104
|
+
// src/emit/canonical-steps.ts
|
|
105
|
+
function slugMoveSteps(moves, held) {
|
|
106
|
+
const at = new Map(moves.map((m) => [m.guid, m.from]));
|
|
107
|
+
const owner = new Map(held);
|
|
108
|
+
const taken = /* @__PURE__ */ new Set([...held.keys(), ...moves.map((m) => m.to)]);
|
|
109
|
+
const steps = [];
|
|
110
|
+
for (let round = 0; round <= moves.length + 1; round++) {
|
|
111
|
+
const pending = moves.filter((m) => at.get(m.guid) !== m.to);
|
|
112
|
+
const blocked = pending.filter((m) => {
|
|
113
|
+
const holder = owner.get(m.to);
|
|
114
|
+
return holder !== void 0 && holder !== m.guid;
|
|
115
|
+
});
|
|
116
|
+
if (blocked.length === 0) {
|
|
117
|
+
steps.push([]);
|
|
118
|
+
return steps;
|
|
119
|
+
}
|
|
120
|
+
if (blocked.some((m) => !pending.some((p) => p.guid === owner.get(m.to)))) return void 0;
|
|
121
|
+
const wants = new Map(blocked.map((m) => [m.guid, m.to]));
|
|
122
|
+
const parked = /* @__PURE__ */ new Set();
|
|
123
|
+
for (const m of blocked) {
|
|
124
|
+
const seen = [];
|
|
125
|
+
let cur = m.guid;
|
|
126
|
+
while (cur !== void 0 && wants.has(cur) && !seen.includes(cur)) {
|
|
127
|
+
seen.push(cur);
|
|
128
|
+
cur = owner.get(wants.get(cur));
|
|
129
|
+
}
|
|
130
|
+
if (cur === void 0 || !seen.includes(cur)) continue;
|
|
131
|
+
const cycle = seen.slice(seen.indexOf(cur));
|
|
132
|
+
if (!cycle.some((g) => parked.has(g))) parked.add(cycle[0]);
|
|
133
|
+
}
|
|
134
|
+
const blockedGuids = new Set(wants.keys());
|
|
135
|
+
const step = [];
|
|
136
|
+
const next = /* @__PURE__ */ new Map();
|
|
137
|
+
for (const m of pending) {
|
|
138
|
+
if (!blockedGuids.has(m.guid)) {
|
|
139
|
+
next.set(m.guid, m.to);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const here = at.get(m.guid);
|
|
143
|
+
if (parked.has(m.guid) || here === void 0) {
|
|
144
|
+
const slug = freeSlug(here ?? m.to, taken);
|
|
145
|
+
taken.add(slug);
|
|
146
|
+
step.push({ kind: m.kind, name: m.name, slug, declared: m.to, why: "park" });
|
|
147
|
+
next.set(m.guid, slug);
|
|
148
|
+
} else {
|
|
149
|
+
step.push({ kind: m.kind, name: m.name, slug: here, declared: m.to, why: "stay" });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
for (const [guid, slug] of next) {
|
|
153
|
+
const before = at.get(guid);
|
|
154
|
+
if (before !== void 0 && owner.get(before) === guid) owner.delete(before);
|
|
155
|
+
if (slug !== void 0) owner.set(slug, guid);
|
|
156
|
+
at.set(guid, slug);
|
|
157
|
+
}
|
|
158
|
+
steps.push(step);
|
|
159
|
+
}
|
|
160
|
+
return void 0;
|
|
161
|
+
}
|
|
162
|
+
function freeSlug(base, taken) {
|
|
163
|
+
for (let n = 1; ; n++) {
|
|
164
|
+
const slug = n === 1 ? `${base}-tmp` : `${base}-tmp${n}`;
|
|
165
|
+
if (!taken.has(slug)) return slug;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function renderSlugSteps(steps, rerun, indent = " ") {
|
|
169
|
+
const id = (o) => `${o.kind}\0${o.name}`;
|
|
170
|
+
return steps.map((step, i) => {
|
|
171
|
+
const here = new Set(step.map(id));
|
|
172
|
+
const set = step.map(
|
|
173
|
+
(o) => `${o.kind} "${o.name}"'s canonical to "${o.slug}" (${o.why === "park" ? "a slug nobody holds" : "where it is now"})`
|
|
174
|
+
);
|
|
175
|
+
const back = (i === 0 ? [] : steps[i - 1]).filter((o) => !here.has(id(o))).map((o) => `${o.kind} "${o.name}"'s canonical back to "${o.declared}" (as declared)`);
|
|
176
|
+
const listed = [...set, ...back];
|
|
177
|
+
const what = listed.length === 0 ? "deploy the project as declared" : `set ${listed.join(", ")} \u2014 every other canonical as declared`;
|
|
178
|
+
return `${indent}${i + 1}. ${what}, then run \`${rerun}\``;
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// src/emit/keep-data-merge.ts
|
|
183
|
+
var TABLE_KINDS = /* @__PURE__ */ new Set(["table", "dbo"]);
|
|
184
|
+
function cannotMergeError(label) {
|
|
185
|
+
return new Error(
|
|
186
|
+
`\`--keep-data\` cannot keep ${label}'s rows: this environment predates the SDK import route, which every deploy writes through. Nothing was sent, and its data is untouched.
|
|
187
|
+
Update it: \`xanosdk local-engine update\` for a local engine, or update the Xano instance behind an ephemeral environment. Dropping \`--keep-data\` will not help \u2014 a replacing deploy uses the same route.`
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
async function unreachableProbeError(err, req) {
|
|
191
|
+
const reach = err instanceof Error ? /: could not reach it \((.*)\)\.\n/.exec(err.message) : null;
|
|
192
|
+
const status = err?.status;
|
|
193
|
+
const answered = err instanceof Error ? /: the probe answered (.*)\n/.exec(err.message) : null;
|
|
194
|
+
if (status === 501 && answered !== null) {
|
|
195
|
+
const label = `${req.label[0].toUpperCase()}${req.label.slice(1)}`;
|
|
196
|
+
const replace = req.rerun === void 0 ? "deploy without `--keep-data`" : `\`${req.rerun.command.split(" ").filter((w) => w !== "--keep-data").join(" ")}\``;
|
|
197
|
+
return new Error(
|
|
198
|
+
`${label} answered the check whether it can merge with ${answered[1].replace(/\.$/, "")}: it does not support a \`--keep-data\` merge. Nothing was sent, and its data is untouched. To deploy anyway, ${replace} \u2014 a replace, which also replaces its rows with the seed rows.${req.rerun?.note ?? ""}`
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
const serverError = typeof status === "number" && (status >= 500 || status === 429) && answered !== null;
|
|
202
|
+
if (reach === null && !serverError || req.rerun === void 0) return err;
|
|
203
|
+
const { LookupFailedError, rateLimitedCause } = await import("./source-resolve-S2XA3XZF.js");
|
|
204
|
+
const failed = new LookupFailedError(
|
|
205
|
+
reach !== null ? `Could not reach ${req.label} to ask whether it can merge (${reach[1]}). ${reach[1].includes(UNTRUSTED_CERTIFICATE) ? "A certificate problem" : "A network failure"} \u2014 nothing was sent and its data is untouched` : `${req.label[0].toUpperCase()}${req.label.slice(1)} answered the check whether it can merge with ${status === 429 ? "its rate limit" : "a server error"} (${answered[1].replace(/\.$/, "")}). ${status === 429 ? `${rateLimitedCause()}: nothing` : "Nothing"} was sent and its data is untouched`,
|
|
206
|
+
"unreachable",
|
|
207
|
+
req.kind ?? "ephemeral",
|
|
208
|
+
`run \`${req.rerun.command}\` again`,
|
|
209
|
+
status === 429 ? "Once the wait is over" : void 0
|
|
210
|
+
);
|
|
211
|
+
failed.message += req.rerun.note;
|
|
212
|
+
return failed;
|
|
213
|
+
}
|
|
214
|
+
async function unansweredReadError(err, req) {
|
|
215
|
+
if (req.rerun === void 0) return err;
|
|
216
|
+
const { LookupFailedError, isRateLimited, isServerError, isTransportFailure, unansweredCause } = await import("./source-resolve-S2XA3XZF.js");
|
|
217
|
+
const transport = isTransportFailure(err);
|
|
218
|
+
if (!transport && !isServerError(err)) return err;
|
|
219
|
+
const first = ((err instanceof Error ? err.message : String(err)).trim().split("\n")[0] ?? "").replace(/[.:]$/, "");
|
|
220
|
+
const failed = new LookupFailedError(
|
|
221
|
+
`${first[0]?.toUpperCase() ?? ""}${first.slice(1)}. ${unansweredCause(err)} \u2014 nothing was written and its data is untouched`,
|
|
222
|
+
"unreachable",
|
|
223
|
+
req.kind ?? "ephemeral",
|
|
224
|
+
`run \`${req.rerun.command}\` again`,
|
|
225
|
+
isRateLimited(err) ? "Once the wait is over" : void 0
|
|
226
|
+
);
|
|
227
|
+
failed.message += req.rerun.note;
|
|
228
|
+
return failed;
|
|
229
|
+
}
|
|
230
|
+
var EXIT_CONFLICT = 2;
|
|
231
|
+
function refusalDetails(refused, lists) {
|
|
232
|
+
return {
|
|
233
|
+
refused,
|
|
234
|
+
...lists.serverCode === void 0 ? {} : { serverCode: lists.serverCode },
|
|
235
|
+
conflicts: lists.conflicts ?? [],
|
|
236
|
+
renames: lists.renames ?? [],
|
|
237
|
+
outOfScope: lists.outOfScope ?? []
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
var EXIT_TRANSIENT = 8;
|
|
241
|
+
function importInProgressError(label, rerun, refusal) {
|
|
242
|
+
const again = rerun === void 0 ? "run the same command again" : `run \`${rerun.command}\` again`;
|
|
243
|
+
return new CliError(
|
|
244
|
+
"SDK_IMPORT_REFUSED",
|
|
245
|
+
`${label.charAt(0).toUpperCase()}${label.slice(1)} was busy with another import, so this one did not start.
|
|
246
|
+
Nothing was written \u2014 its data is intact, and nothing in the project has to change: ${again} in a moment.${rerun?.note ?? ""}`,
|
|
247
|
+
{
|
|
248
|
+
exitCode: EXIT_TRANSIENT,
|
|
249
|
+
details: { refused: "importInProgress", landed: false, serverCode: refusal.code, ...rerun === void 0 ? {} : { rerun: rerun.command } }
|
|
250
|
+
}
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
function refusedError(label, refusal, indexChanges = [], rerun) {
|
|
254
|
+
if (refusal.retryable) return importInProgressError(label, rerun, refusal);
|
|
255
|
+
const conflicts = refusal.conflicts.map(
|
|
256
|
+
(c) => ` ${c.kind} "${c.identity}"${c.owner.guid === void 0 ? "" : ` (held by guid ${c.owner.guid})`}`
|
|
257
|
+
);
|
|
258
|
+
const uniqueAdds = indexChanges.filter((c) => c.action === "add" && c.unique);
|
|
259
|
+
const unique = refusal.code === XANOSDK_IMPORT_UNIQUENESS_CODE && uniqueAdds.length > 0 ? `The merge adds ${uniqueAdds.length === 1 ? "a unique index" : "unique indexes"} the rows already there may hold duplicates for:
|
|
260
|
+
${uniqueAdds.map((c) => ` table ${c.table}: ${c.index}`).join("\n")}
|
|
261
|
+
Remove the duplicate rows or the index.
|
|
262
|
+
` : "";
|
|
263
|
+
const message = `${label} refused the merge: ${refusal.reason}
|
|
264
|
+
` + (conflicts.length > 0 ? `${conflicts.join("\n")}
|
|
265
|
+
` : "") + unique + `Nothing was written \u2014 the environment's data is intact.
|
|
266
|
+
Fix what it names and deploy again, or rebuild the environment from the project with \`${rerun === void 0 ? "xanosdk deploy --keep-data --reset" : withFlag(rerun.command, "--reset")}\` (that replaces its rows with the seed rows).${rerun?.note ?? ""}`;
|
|
267
|
+
if (refusal.code === XANOSDK_IMPORT_UNIQUENESS_CODE) {
|
|
268
|
+
const err2 = new CliError("SDK_IMPORT_REFUSED", message, {
|
|
269
|
+
exitCode: EXIT_CONFLICT,
|
|
270
|
+
details: {
|
|
271
|
+
...refusalDetails("uniqueViolation", { serverCode: refusal.code }),
|
|
272
|
+
landed: false,
|
|
273
|
+
indexes: uniqueAdds.map((c) => ({ table: c.table, index: c.index }))
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
return Object.assign(err2, { cause: refusal });
|
|
277
|
+
}
|
|
278
|
+
if (refusal.conflicts.length === 0) return new Error(message, { cause: refusal });
|
|
279
|
+
const err = new CliError("SDK_IDENTITY_CONFLICT", message, {
|
|
280
|
+
exitCode: EXIT_CONFLICT,
|
|
281
|
+
details: refusalDetails("identityConflict", {
|
|
282
|
+
serverCode: refusal.code,
|
|
283
|
+
conflicts: refusal.conflicts.map((c) => ({
|
|
284
|
+
kind: sectionKind(planTypeSection(c.kind)),
|
|
285
|
+
name: c.identity,
|
|
286
|
+
liveGuid: c.owner.guid ?? null,
|
|
287
|
+
projectGuid: c.archiveGuid ?? null
|
|
288
|
+
}))
|
|
289
|
+
})
|
|
290
|
+
});
|
|
291
|
+
return Object.assign(err, { cause: refusal });
|
|
292
|
+
}
|
|
293
|
+
function liveTableTriggers(live) {
|
|
294
|
+
const tables = /* @__PURE__ */ new Map();
|
|
295
|
+
for (const row of payloadRows(live, "dbo")) {
|
|
296
|
+
if (typeof row.guid === "string" && typeof row.name === "string") tables.set(row.guid, row.name);
|
|
297
|
+
}
|
|
298
|
+
return payloadRows(live, "trigger").filter((row) => row.obj_type === "database").map((row) => {
|
|
299
|
+
const table = typeof row.obj_id === "string" ? row.obj_id : "";
|
|
300
|
+
return { name: typeof row.name === "string" ? row.name : "", table: tables.get(table) ?? table };
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
function tableTriggerMergeError(label, triggers, remedy) {
|
|
304
|
+
const one = triggers.length === 1;
|
|
305
|
+
const lines = triggers.map((t) => ` ${t.name} (table ${t.table})`);
|
|
306
|
+
return new CliError(
|
|
307
|
+
"SDK_IMPORT_REFUSED",
|
|
308
|
+
`${label.charAt(0).toUpperCase()}${label.slice(1)} was not merged: it holds ${one ? "a table trigger" : `${triggers.length} table triggers`}, and a merge into an ephemeral or a tenant fails while one is there (the instance answers 500, after part of the merge may have landed):
|
|
309
|
+
${lines.join("\n")}
|
|
310
|
+
Nothing was written \u2014 the environment's data is intact. Removing the trigger from the project does not help while the environment holds it. A replace works; it replaces the rows with the seed rows: \`${remedy.command}\`.${remedy.note}`,
|
|
311
|
+
{
|
|
312
|
+
exitCode: EXIT_CONFLICT,
|
|
313
|
+
details: { refused: "tableTrigger", landed: false, triggers: triggers.map((t) => ({ ...t })) }
|
|
314
|
+
}
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
function nameCollisions(operations, live, outgoing) {
|
|
318
|
+
const deleted = new Set(operations.filter((o) => o.action === "delete").map((o) => `${o.type}\0${o.name}`));
|
|
319
|
+
const pairs = operations.filter((o) => o.action === "create" && deleted.has(`${o.type}\0${o.name}`));
|
|
320
|
+
if (pairs.length === 0) return [];
|
|
321
|
+
const liveLabel = rowLabeler(payloadOf(live));
|
|
322
|
+
const outLabel = rowLabeler(payloadOf(outgoing));
|
|
323
|
+
const guids = (rows) => new Set(rows.map((r) => r.guid));
|
|
324
|
+
const out = [];
|
|
325
|
+
for (const op of pairs) {
|
|
326
|
+
const section = planTypeSection(op.type);
|
|
327
|
+
const liveRows = payloadRows(live, section);
|
|
328
|
+
const outRows = payloadRows(outgoing, section);
|
|
329
|
+
const liveGuids = guids(liveRows);
|
|
330
|
+
const outGuids = guids(outRows);
|
|
331
|
+
const gone = liveRows.filter((r) => r.name === op.name && !outGuids.has(r.guid));
|
|
332
|
+
for (const row of outRows.filter((r) => r.name === op.name && !liveGuids.has(r.guid))) {
|
|
333
|
+
const label = outLabel(section, row);
|
|
334
|
+
const held = gone.find((g) => liveLabel(section, g) === label);
|
|
335
|
+
if (held === void 0) continue;
|
|
336
|
+
out.push({
|
|
337
|
+
kind: sectionKind(section, row),
|
|
338
|
+
name: label.slice(label.indexOf(":") + 1),
|
|
339
|
+
liveGuid: typeof held.guid === "string" ? held.guid : null,
|
|
340
|
+
projectGuid: typeof row.guid === "string" ? row.guid : null
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return out;
|
|
345
|
+
}
|
|
346
|
+
function collisionError(label, collisions, resetRerun) {
|
|
347
|
+
const one = collisions.length === 1;
|
|
348
|
+
const lines = collisions.map(
|
|
349
|
+
(c) => ` ${c.kind} "${c.name}" \u2014 live guid ${c.liveGuid ?? "unknown"}, the project's ${c.projectGuid ?? "unknown"}`
|
|
350
|
+
);
|
|
351
|
+
return new CliError(
|
|
352
|
+
"SDK_IDENTITY_CONFLICT",
|
|
353
|
+
`${label} cannot merge: it holds ${one ? "an object" : "objects"} under ${one ? "a name" : "names"} the project sends under another identity. A merge matches on guid, so it would delete the live one and create the project's beside it, which the environment refuses by name:
|
|
354
|
+
${lines.join("\n")}
|
|
355
|
+
Nothing was written \u2014 the environment's data is intact.
|
|
356
|
+
Rebuild the environment from the project with \`${resetRerun}\` (that replaces its rows with the seed rows), or give one of ${one ? "the two" : "each pair"} another name.`,
|
|
357
|
+
{ exitCode: EXIT_CONFLICT, details: refusalDetails("identityConflict", { conflicts: collisions }) }
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
var COMPOSING_PARENTS = {
|
|
361
|
+
message: ["channel", "realtime_server"],
|
|
362
|
+
channel: ["realtime_server"],
|
|
363
|
+
query: ["app"]
|
|
364
|
+
};
|
|
365
|
+
function parentRenames(collisions, live, outgoing, pins) {
|
|
366
|
+
const entries = pins?.entries;
|
|
367
|
+
if (entries === void 0 || pins?.keyFixUps === void 0) return [];
|
|
368
|
+
const keyOf = /* @__PURE__ */ new Map();
|
|
369
|
+
for (const [key, guid] of entries) keyOf.set(guid, key);
|
|
370
|
+
const guidsIn = (bundle, section) => new Set(payloadRows(bundle, section).map((r) => r.guid).filter((g) => typeof g === "string"));
|
|
371
|
+
const out = /* @__PURE__ */ new Map();
|
|
372
|
+
for (const collision of collisions) {
|
|
373
|
+
const key = collision.liveGuid === null ? void 0 : keyOf.get(collision.liveGuid);
|
|
374
|
+
if (key === void 0) continue;
|
|
375
|
+
const sep = key.indexOf(":");
|
|
376
|
+
const parts = key.slice(sep + 1).split("|");
|
|
377
|
+
let found;
|
|
378
|
+
for (let n = parts.length - 1; n >= 1 && found === void 0; n--) {
|
|
379
|
+
const name = parts.slice(0, n).join("|");
|
|
380
|
+
for (const section of COMPOSING_PARENTS[key.slice(0, sep)] ?? []) {
|
|
381
|
+
const guid = entries.get(`${section}:${name}`);
|
|
382
|
+
if (guid === void 0 || !guidsIn(live, section).has(guid) || guidsIn(outgoing, section).has(guid)) continue;
|
|
383
|
+
found = { section, name, guid };
|
|
384
|
+
break;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
if (found === void 0) continue;
|
|
388
|
+
const parentKey = `${found.section}:${found.name}`;
|
|
389
|
+
const existing = out.get(parentKey);
|
|
390
|
+
if (existing !== void 0) {
|
|
391
|
+
existing.children.push(collision);
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
const scope = found.name.includes("|") ? found.name.slice(0, found.name.lastIndexOf("|") + 1) : "";
|
|
395
|
+
const liveGuids = guidsIn(live, found.section);
|
|
396
|
+
const sent = guidsIn(outgoing, found.section);
|
|
397
|
+
const candidates = [...entries].filter(([k, g]) => k.startsWith(`${found.section}:${scope}`) && sent.has(g) && !liveGuids.has(g)).map(([k]) => k.slice(found.section.length + 1)).filter((name) => scope === "" ? !name.includes("|") : !name.slice(scope.length).includes("|"));
|
|
398
|
+
const fix = pins.keyFixUps(parentKey, candidates.length === 1 ? candidates[0] : void 0);
|
|
399
|
+
if (fix === void 0) continue;
|
|
400
|
+
out.set(parentKey, {
|
|
401
|
+
kind: sectionKind(found.section),
|
|
402
|
+
name: found.name,
|
|
403
|
+
guid: found.guid,
|
|
404
|
+
candidates,
|
|
405
|
+
rename: fix.rename,
|
|
406
|
+
children: [collision]
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
const explained = new Set([...out.values()].flatMap((p) => p.children));
|
|
410
|
+
for (const collision of collisions) {
|
|
411
|
+
if (explained.has(collision) || collision.liveGuid === null || collision.projectGuid === null) continue;
|
|
412
|
+
const key = keyOf.get(collision.liveGuid);
|
|
413
|
+
const target = keyOf.get(collision.projectGuid);
|
|
414
|
+
if (key === void 0 || target === void 0 || key === target) continue;
|
|
415
|
+
const section = key.slice(0, key.indexOf(":"));
|
|
416
|
+
if (!target.startsWith(`${section}:`) || guidsIn(outgoing, section).has(collision.liveGuid)) continue;
|
|
417
|
+
const name = key.slice(section.length + 1);
|
|
418
|
+
const newName = target.slice(section.length + 1);
|
|
419
|
+
const fix = pins.keyFixUps(key, newName);
|
|
420
|
+
if (fix === void 0) continue;
|
|
421
|
+
out.set(key, {
|
|
422
|
+
kind: sectionKind(section),
|
|
423
|
+
name,
|
|
424
|
+
guid: collision.liveGuid,
|
|
425
|
+
candidates: [newName],
|
|
426
|
+
rename: fix.rename,
|
|
427
|
+
children: [collision],
|
|
428
|
+
self: true
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
return [...out.values()];
|
|
432
|
+
}
|
|
433
|
+
function parentRenameError(label, parents, collisions, resetRerun) {
|
|
434
|
+
const explained = new Set(parents.flatMap((p) => p.children));
|
|
435
|
+
const others = collisions.filter((c) => !explained.has(c));
|
|
436
|
+
const collisionLine = (c, indent) => `${indent}${c.kind} "${c.name}" \u2014 live guid ${c.liveGuid ?? "unknown"}, the project's ${c.projectGuid ?? "unknown"}`;
|
|
437
|
+
const lines = [];
|
|
438
|
+
for (const p of parents) {
|
|
439
|
+
lines.push(
|
|
440
|
+
` ${p.kind} "${p.name}" (guid ${p.guid}) \u2014 xano.lock still pins it, ` + (p.candidates.length === 0 ? "and the project no longer declares it" : `and the project now adds ${p.candidates.map((c) => `"${c}"`).join(", ")}`) + (p.self === true ? "; the project sends it under a new identity:" : `; what it holds took new identities with its name:`),
|
|
441
|
+
...p.children.map((c) => collisionLine(c, " ")),
|
|
442
|
+
` renamed? run: ${p.rename}`
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
if (others.length > 0) lines.push(...others.map((c) => collisionLine(c, " ")));
|
|
446
|
+
const one = parents.length === 1;
|
|
447
|
+
return new CliError(
|
|
448
|
+
"SDK_IDENTITY_CONFLICT",
|
|
449
|
+
`${label} was not merged: ${one ? "an object" : "objects"} renamed in code that xano.lock still pins under the old name \u2014 a rename the lock was not told about. What ${one ? "it holds is" : "they hold is"} keyed by ${one ? "its" : "their"} name, so the merge would delete each live child and create the project's under the same name, which the environment refuses:
|
|
450
|
+
${lines.join("\n")}
|
|
451
|
+
Nothing was written \u2014 the environment's data is intact. Run the \`lock rename\`, then deploy again: the merge ` + (parents.every((p) => p.self === true) ? `then updates ${one ? "it" : "them"} in place, keeping ${one ? "its" : "their"} identity. If` : `then renames ${one ? "it" : "them"} in place and what ${one ? "it holds keeps its" : "they hold keeps their"} identity. If`) + ` it was not a rename, rebuild the environment with \`${resetRerun}\` (that replaces its rows with the seed rows), or give one of each pair another name.`,
|
|
452
|
+
{
|
|
453
|
+
exitCode: EXIT_CONFLICT,
|
|
454
|
+
details: refusalDetails("renamePending", {
|
|
455
|
+
conflicts: collisions,
|
|
456
|
+
renames: parents.map((p) => ({
|
|
457
|
+
kind: p.kind,
|
|
458
|
+
name: p.name,
|
|
459
|
+
guid: p.guid,
|
|
460
|
+
candidates: p.candidates,
|
|
461
|
+
rename: p.rename,
|
|
462
|
+
conflicts: p.children.map((c) => `${c.kind}:${c.name}`)
|
|
463
|
+
}))
|
|
464
|
+
})
|
|
465
|
+
}
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
function setGuidRemedy(guid, candidates, codePinned) {
|
|
469
|
+
if (codePinned === void 0 || candidates.length === 0) return void 0;
|
|
470
|
+
const pins = candidates.map((c) => codePinned.get(c)?.guid);
|
|
471
|
+
if (pins.some((g) => g === void 0 || g === guid)) return void 0;
|
|
472
|
+
return { ...candidates.length === 1 ? { table: candidates[0] } : {}, guid, pins };
|
|
473
|
+
}
|
|
474
|
+
function clearReplacedCommand(name, lockPath) {
|
|
475
|
+
return `xanosdk lock prune --identity-only ${shellWord(`table:${name}`)} --lock=${shellWord(displayPath(lockPath))} --yes`;
|
|
476
|
+
}
|
|
477
|
+
function pendingRenameLines(p, still = "the table would still be dropped", sameName = {}) {
|
|
478
|
+
const adds = p.candidates.map((c) => `"${c}"`).join(", ");
|
|
479
|
+
if (sameNameRepin(p)) {
|
|
480
|
+
const temp = `${p.table}_tmp`;
|
|
481
|
+
const { rebuild, addFlag } = sameName;
|
|
482
|
+
const deploy = addFlag === void 0 ? "deploy" : `deploy with \`${addFlag}\``;
|
|
483
|
+
return [
|
|
484
|
+
` table "${p.table}" (guid ${p.guid}) \u2014 its def now pins another guid (${p.setGuid.pins[0]}) under the same name, and a merge cannot replace a table with another of its own name: the environment refuses it by name.`,
|
|
485
|
+
` same table? set the def of "${p.table}" back to \`guid: "${p.guid}"\` \u2014 the merge keeps it and its rows`,
|
|
486
|
+
` not wanted? run: ${p.prune} \u2014 then rename the def to "${temp}" and ${deploy} (the merge drops the old table with its rows and creates this one), rename it back to "${p.table}" and deploy again (the merge renames it)`,
|
|
487
|
+
...rebuild === void 0 ? [] : [` or rebuild the environment from the project: \`${rebuild}\` (replaces every table's rows with the seed rows)`]
|
|
488
|
+
];
|
|
489
|
+
}
|
|
490
|
+
if (p.setGuid === void 0) {
|
|
491
|
+
return [
|
|
492
|
+
` table "${p.table}" (guid ${p.guid}) \u2014 xano.lock still pins it, and the project now adds ${adds}:`,
|
|
493
|
+
` renamed? run: ${p.rename ?? ""}`,
|
|
494
|
+
` deleted? run: ${p.prune}`
|
|
495
|
+
];
|
|
496
|
+
}
|
|
497
|
+
const one = p.setGuid.table !== void 0;
|
|
498
|
+
if (p.setGuid.pins.length === 0) {
|
|
499
|
+
return [
|
|
500
|
+
` table "${p.table}" (guid ${p.guid}) \u2014 xano.lock keeps it as a guid a def's \`guid:\` replaced, and the project now adds ${adds}:`,
|
|
501
|
+
` renamed? set ${one ? `the def of "${p.setGuid.table}"` : "the def of the table it became"} to \`guid: "${p.guid}"\``,
|
|
502
|
+
` deleted? run: ${p.prune}`
|
|
503
|
+
];
|
|
504
|
+
}
|
|
505
|
+
return [
|
|
506
|
+
` table "${p.table}" (guid ${p.guid}) \u2014 xano.lock still pins it, and the project now adds ${adds}, ${one ? `whose def pins its own guid (${p.setGuid.pins[0]})` : "each pinning its own guid in its def"}:`,
|
|
507
|
+
` renamed? set ${one ? `the def of "${p.setGuid.table}"` : "the def of the table it became"} to \`guid: "${p.guid}"\` \u2014 not a \`lock rename\`: the def's own guid replaces any lock entry, so ${still}`,
|
|
508
|
+
` deleted? run: ${p.prune}`
|
|
509
|
+
];
|
|
510
|
+
}
|
|
511
|
+
function sameNameRepin(p) {
|
|
512
|
+
return p.setGuid !== void 0 && p.setGuid.pins.length === 1 && p.candidates.length === 1 && p.candidates[0] === p.table;
|
|
513
|
+
}
|
|
514
|
+
function pendingRenameFollowUp(all, afterPrune) {
|
|
515
|
+
const pending = all.filter((p) => !sameNameRepin(p));
|
|
516
|
+
if (pending.length === 0) return "Do one, then deploy again.";
|
|
517
|
+
const inCode = pending.filter((p) => p.setGuid !== void 0).length;
|
|
518
|
+
const kept = inCode === 0 ? "after `lock rename` the merge renames the table" : inCode === pending.length ? "with the def's `guid:` set to the old guid the merge renames the table" : "after `lock rename` (or, where the def pins its own guid, the def's `guid:` set to the old one) the merge renames the table";
|
|
519
|
+
return `${inCode === 0 ? "Run" : "Do"} one, then deploy again: ${kept} and keeps its rows; after \`lock prune\` ${afterPrune}`;
|
|
520
|
+
}
|
|
521
|
+
function pendingRenames(operations, nameDelete, pins) {
|
|
522
|
+
if (pins === void 0) return [];
|
|
523
|
+
const created = operations.filter((o) => o.action === "create" && TABLE_KINDS.has(o.type)).map((o) => o.name);
|
|
524
|
+
if (created.length === 0) return [];
|
|
525
|
+
const replacedBy = new Map([...pins.codePinned ?? []].flatMap(([name, t]) => (t.replaces ?? []).map((g) => [g, name])));
|
|
526
|
+
const out = [];
|
|
527
|
+
for (const op of operations.filter((o) => o.action === "delete" && TABLE_KINDS.has(o.type))) {
|
|
528
|
+
const guid = nameDelete(op).guid;
|
|
529
|
+
if (guid === void 0) continue;
|
|
530
|
+
const orphan = pins.tables.get(guid);
|
|
531
|
+
const pinned = orphan ?? replacedBy.get(guid) ?? pins.replaced?.get(guid);
|
|
532
|
+
if (pinned === void 0) continue;
|
|
533
|
+
const fix = pins.fixUps(pinned, created.length === 1 ? created[0] : void 0);
|
|
534
|
+
const prune = orphan === void 0 && pins.clearReplaced !== void 0 ? pins.clearReplaced(pinned) : fix.prune;
|
|
535
|
+
const setGuid = setGuidRemedy(guid, created, pins.codePinned) ?? (orphan === void 0 ? { ...created.length === 1 ? { table: created[0] } : {}, guid, pins: [] } : void 0);
|
|
536
|
+
out.push({ table: op.name, guid, candidates: created, ...setGuid === void 0 ? { rename: fix.rename } : { setGuid }, prune });
|
|
537
|
+
}
|
|
538
|
+
return out;
|
|
539
|
+
}
|
|
540
|
+
function pendingRenameDetail(p) {
|
|
541
|
+
return {
|
|
542
|
+
table: p.table,
|
|
543
|
+
guid: p.guid,
|
|
544
|
+
candidates: [...p.candidates],
|
|
545
|
+
...p.rename !== void 0 ? { rename: p.rename } : {},
|
|
546
|
+
...p.setGuid !== void 0 ? { setGuid: { ...p.setGuid, pins: [...p.setGuid.pins] } } : {},
|
|
547
|
+
...sameNameRepin(p) ? { sameName: true } : {},
|
|
548
|
+
prune: p.prune
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
function pendingRenameError(label, pending, resetRerun) {
|
|
552
|
+
const lines = pending.flatMap((p) => pendingRenameLines(p, void 0, { rebuild: resetRerun }));
|
|
553
|
+
const one = pending.length === 1;
|
|
554
|
+
const lead = pending.every(sameNameRepin) ? `${label} was not merged: ${one ? "a table's def pins" : "table defs pin"} a new guid under the name the table already has, and a merge matches on guid, so it would delete the old table with every row.` : `${label} was not merged: it would DROP ${one ? "a table" : "tables"} xano.lock still pins, with every row, while the project adds a new table \u2014 a rename the lock was not told about. A merge matches on guid, so it would delete the old table and create an empty one.`;
|
|
555
|
+
return new CliError(
|
|
556
|
+
"SDK_IDENTITY_CONFLICT",
|
|
557
|
+
`${lead}
|
|
558
|
+
${lines.join("\n")}
|
|
559
|
+
Nothing was written \u2014 the environment's data is intact. ` + pendingRenameFollowUp(pending, `it drops ${one ? "it" : "them"} as a deletion.`),
|
|
560
|
+
{
|
|
561
|
+
exitCode: EXIT_CONFLICT,
|
|
562
|
+
details: refusalDetails("renamePending", { renames: pending.map(pendingRenameDetail) })
|
|
563
|
+
}
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
function liveCanonicalRow(live, kind, guid, name) {
|
|
567
|
+
const rows = payloadRows(live, planTypeSection(kind));
|
|
568
|
+
if (guid !== void 0) {
|
|
569
|
+
const byGuid = rows.find((r) => r.guid === guid);
|
|
570
|
+
if (byGuid !== void 0) return byGuid;
|
|
571
|
+
}
|
|
572
|
+
return rows.find((r) => r.name === name && (typeof r.guid !== "string" || r.guid === ""));
|
|
573
|
+
}
|
|
574
|
+
function slugOf(row) {
|
|
575
|
+
return typeof row?.canonical === "string" && row.canonical !== "" ? row.canonical : void 0;
|
|
576
|
+
}
|
|
577
|
+
function canonicalChanges(canonicals, live) {
|
|
578
|
+
const out = [];
|
|
579
|
+
for (const c of canonicals) {
|
|
580
|
+
const row = liveCanonicalRow(live, c.kind, c.guid, c.name);
|
|
581
|
+
const from = slugOf(row);
|
|
582
|
+
if (row === void 0 || from === void 0 || c.served === void 0 || c.served === from) continue;
|
|
583
|
+
out.push({ kind: sectionKind(planTypeSection(c.kind), row), name: c.name, from, to: c.served });
|
|
584
|
+
}
|
|
585
|
+
return out;
|
|
586
|
+
}
|
|
587
|
+
function canonicalConflicts(conflicts, canonicals, operations, live, pins, workspaceId) {
|
|
588
|
+
const out = [];
|
|
589
|
+
for (const conflict of conflicts.filter((c) => c.kind === "canonical")) {
|
|
590
|
+
const wanted = canonicals.find((c) => c.guid !== void 0 && c.guid === conflict.archiveGuid) ?? canonicals.find((c) => c.outcome === "conflict" && c.requested === conflict.identity);
|
|
591
|
+
const kind = wanted === void 0 ? "object" : sectionKind(planTypeSection(wanted.kind));
|
|
592
|
+
const name = wanted?.name ?? conflict.archiveGuid ?? conflict.identity;
|
|
593
|
+
const section = wanted === void 0 ? void 0 : planTypeSection(wanted.kind);
|
|
594
|
+
const holder = section === void 0 ? void 0 : payloadRows(live, section).find(
|
|
595
|
+
(r) => conflict.owner.guid !== void 0 && r.guid === conflict.owner.guid || slugOf(r) === conflict.identity && r.name !== name
|
|
596
|
+
);
|
|
597
|
+
const deleted = holder !== void 0 && operations.some((o) => o.action === "delete" && planTypeSection(o.type) === section && o.name === holder.name);
|
|
598
|
+
const entry = {
|
|
599
|
+
kind,
|
|
600
|
+
name,
|
|
601
|
+
canonical: conflict.identity,
|
|
602
|
+
ownerGuid: conflict.owner.guid ?? null
|
|
603
|
+
};
|
|
604
|
+
if (deleted && holder !== void 0 && typeof holder.name === "string") {
|
|
605
|
+
entry.heldBy = {
|
|
606
|
+
kind: sectionKind(section, holder),
|
|
607
|
+
name: holder.name,
|
|
608
|
+
guid: typeof holder.guid === "string" ? holder.guid : conflict.owner.guid ?? null
|
|
609
|
+
};
|
|
610
|
+
const fix = pins?.keyFixUps?.(`${section}:${holder.name}`, name);
|
|
611
|
+
if (fix !== void 0) entry.rename = fix.rename;
|
|
612
|
+
} else if (conflict.owner.workspaceId !== workspaceId) {
|
|
613
|
+
entry.elsewhere = conflict.owner.workspaceId;
|
|
614
|
+
} else {
|
|
615
|
+
const kept = canonicals.find(
|
|
616
|
+
(c) => c.guid !== void 0 && c.guid === conflict.owner.guid && c.guid !== conflict.archiveGuid
|
|
617
|
+
);
|
|
618
|
+
if (kept?.guid !== void 0 && kept.requested !== void 0 && kept.requested !== conflict.identity) {
|
|
619
|
+
const row = liveCanonicalRow(live, kept.kind, kept.guid, kept.name);
|
|
620
|
+
entry.sibling = { kind: sectionKind(planTypeSection(kept.kind), row), name: kept.name, guid: kept.guid, to: kept.requested };
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
out.push(entry);
|
|
624
|
+
}
|
|
625
|
+
return out;
|
|
626
|
+
}
|
|
627
|
+
function siblingSlugSteps(conflicts, canonicals, live) {
|
|
628
|
+
if (conflicts.length === 0 || conflicts.some((c) => c.sibling === void 0)) return void 0;
|
|
629
|
+
const held = /* @__PURE__ */ new Map();
|
|
630
|
+
for (const section of /* @__PURE__ */ new Set(["app", ...canonicals.map((c) => planTypeSection(c.kind))])) {
|
|
631
|
+
for (const row of payloadRows(live, section)) {
|
|
632
|
+
const slug = slugOf(row);
|
|
633
|
+
if (slug !== void 0 && typeof row.guid === "string") held.set(slug, row.guid);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
const moves = [];
|
|
637
|
+
for (const c of canonicals) {
|
|
638
|
+
if (c.guid === void 0 || c.requested === void 0) continue;
|
|
639
|
+
const row = liveCanonicalRow(live, c.kind, c.guid, c.name);
|
|
640
|
+
const from = slugOf(row);
|
|
641
|
+
if (from === c.requested) continue;
|
|
642
|
+
moves.push({ kind: sectionKind(planTypeSection(c.kind), row), name: c.name, guid: c.guid, from, to: c.requested });
|
|
643
|
+
}
|
|
644
|
+
return slugMoveSteps(moves, held);
|
|
645
|
+
}
|
|
646
|
+
function canonicalConflictError(label, conflicts, resetRerun, steps) {
|
|
647
|
+
const lines = [];
|
|
648
|
+
for (const c of conflicts) {
|
|
649
|
+
if (c.sibling !== void 0) {
|
|
650
|
+
lines.push(
|
|
651
|
+
` ${c.kind} "${c.name}" pins canonical "${c.canonical}", which ${c.sibling.kind} "${c.sibling.name}" of this environment serves now and this deploy moves to "${c.sibling.to}".`
|
|
652
|
+
);
|
|
653
|
+
} else if (c.heldBy !== void 0) {
|
|
654
|
+
lines.push(
|
|
655
|
+
` ${c.kind} "${c.name}" pins canonical "${c.canonical}", which ${c.heldBy.kind} "${c.heldBy.name}" serves \u2014 the merge would create "${c.name}" beside it and delete "${c.heldBy.name}" after, so the slug is not free when it is asked for.`
|
|
656
|
+
);
|
|
657
|
+
if (c.rename !== void 0) lines.push(` renamed? run: ${c.rename}`);
|
|
658
|
+
} else {
|
|
659
|
+
lines.push(
|
|
660
|
+
` ${c.kind} "${c.name}" pins canonical "${c.canonical}", which ` + (c.elsewhere === void 0 ? "another object in this environment serves" : `an object in workspace ${c.elsewhere} on the same backend serves`) + `${c.ownerGuid === null ? "" : ` (guid ${c.ownerGuid})`}.`
|
|
661
|
+
);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
const renames = conflicts.some((c) => c.rename !== void 0);
|
|
665
|
+
return new CliError(
|
|
666
|
+
"SDK_IDENTITY_CONFLICT",
|
|
667
|
+
`${label} was not merged: ${conflicts.length === 1 ? "a public URL slug" : "public URL slugs"} the project pins cannot be served as declared:
|
|
668
|
+
${lines.join("\n")}
|
|
669
|
+
Nothing was written \u2014 the environment's data is intact.
|
|
670
|
+
` + (steps !== void 0 ? `One deploy cannot hand a slug from one object to another: each pinned slug is checked against what the environment serves when the deploy starts. Move them in ${steps.list.length} deploys, each keeping the data:
|
|
671
|
+
` + renderSlugSteps(steps.list, steps.rerun).join("\n") : renames ? `If it is a rename, run the \`lock rename\` and deploy again: the merge then renames the object in place and it keeps its URL. If not, pick another \`canonical\`, or rebuild the environment with \`${resetRerun}\` (that replaces its rows with the seed rows).` : `Pick another \`canonical\`, or \u2014 when the holder is this environment's own object \u2014 rebuild the environment with \`${resetRerun}\` (that replaces its rows with the seed rows).`),
|
|
672
|
+
{
|
|
673
|
+
exitCode: EXIT_CONFLICT,
|
|
674
|
+
details: {
|
|
675
|
+
...refusalDetails("identityConflict", {
|
|
676
|
+
conflicts: conflicts.map((c) => {
|
|
677
|
+
const holder = c.sibling ?? c.heldBy;
|
|
678
|
+
return {
|
|
679
|
+
kind: c.kind,
|
|
680
|
+
name: c.name,
|
|
681
|
+
canonical: c.canonical,
|
|
682
|
+
liveGuid: holder?.guid ?? c.ownerGuid,
|
|
683
|
+
...holder === void 0 ? {} : { heldBy: `${holder.kind}:${holder.name}` },
|
|
684
|
+
...c.rename === void 0 ? {} : { rename: c.rename }
|
|
685
|
+
};
|
|
686
|
+
})
|
|
687
|
+
}),
|
|
688
|
+
...steps === void 0 ? {} : {
|
|
689
|
+
steps: steps.list.map((step) => ({
|
|
690
|
+
set: step.map((o) => ({ object: `${o.kind}:${o.name}`, canonical: o.slug, why: o.why })),
|
|
691
|
+
run: steps.rerun
|
|
692
|
+
}))
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
function canonicalNotServedError(label, missed, resetRerun) {
|
|
699
|
+
const lines = missed.map(
|
|
700
|
+
(c) => ` ${sectionKind(planTypeSection(c.kind))} "${c.name}" \u2014 pinned "${c.requested ?? ""}", serves ${c.served === void 0 ? "a slug the environment chose" : `"${c.served}"`} (${c.outcome})`
|
|
701
|
+
);
|
|
702
|
+
return new CliError(
|
|
703
|
+
"SDK_ERROR",
|
|
704
|
+
`${label} merged, but ${missed.length === 1 ? "a pinned public URL is" : "pinned public URLs are"} not served as declared \u2014 every endpoint under the declared slug answers 404:
|
|
705
|
+
${lines.join("\n")}
|
|
706
|
+
Rebuild the environment from the project with \`${resetRerun}\` (that replaces its rows with the seed rows).`,
|
|
707
|
+
{
|
|
708
|
+
details: {
|
|
709
|
+
landed: true,
|
|
710
|
+
canonicals: missed.map((c) => ({
|
|
711
|
+
kind: sectionKind(planTypeSection(c.kind)),
|
|
712
|
+
name: c.name,
|
|
713
|
+
requested: c.requested ?? null,
|
|
714
|
+
served: c.served ?? null,
|
|
715
|
+
outcome: c.outcome
|
|
716
|
+
}))
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
);
|
|
720
|
+
}
|
|
721
|
+
var KeepDataDeclined = class extends Error {
|
|
722
|
+
declined = true;
|
|
723
|
+
constructor(label, verb = "merged") {
|
|
724
|
+
super(`Nothing was ${verb} \u2014 ${label} and its data are as they were.`);
|
|
725
|
+
this.name = "KeepDataDeclined";
|
|
726
|
+
}
|
|
727
|
+
};
|
|
728
|
+
async function gateForeignReplace(req) {
|
|
729
|
+
const answered = req.allowForeignDeletes === true;
|
|
730
|
+
let live;
|
|
731
|
+
try {
|
|
732
|
+
live = await withSpinner(
|
|
733
|
+
"Reading the environment to check what the replace clears\u2026",
|
|
734
|
+
() => exportWorkspaceBundle(req.auth, { base: req.baseUrl, workspaceId: req.workspaceId, label: `${req.label} live read` })
|
|
735
|
+
);
|
|
736
|
+
} catch (err) {
|
|
737
|
+
if (answered) {
|
|
738
|
+
warn(
|
|
739
|
+
`Could not read ${req.label} to list what the replace clears that this project did not land; \`--yes\` deletes it unlisted.`,
|
|
740
|
+
"plan.object-remove-unlisted",
|
|
741
|
+
[err instanceof Error ? err.message : String(err)]
|
|
742
|
+
);
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
throw await unansweredReadError(err, req);
|
|
746
|
+
}
|
|
747
|
+
const foreign = foreignObjects(live, JSON.parse(req.bundle), req.landedGuids);
|
|
748
|
+
if (foreign.length === 0) return;
|
|
749
|
+
const one = foreign.length === 1;
|
|
750
|
+
const what = `${plural(foreign.length, "object", "objects")} ${NOT_LANDED}`;
|
|
751
|
+
warn(
|
|
752
|
+
answered ? `The replace DELETES ${what} \u2014 a replace clears everything ${req.label} holds:` : `The replace would DELETE ${what} \u2014 a replace clears everything ${req.label} holds:`,
|
|
753
|
+
"plan.object-remove",
|
|
754
|
+
foreign.map((o) => o.label)
|
|
755
|
+
);
|
|
756
|
+
if (answered) return;
|
|
757
|
+
if (req.confirm !== void 0) {
|
|
758
|
+
if (await req.confirm(`Delete ${what} from ${req.label}?`)) return;
|
|
759
|
+
throw new KeepDataDeclined(req.label, "deployed");
|
|
760
|
+
}
|
|
761
|
+
const rerun = req.rerun === void 0 ? void 0 : withFlag(req.rerun.command, "--yes", "-y");
|
|
762
|
+
throw new CliError(
|
|
763
|
+
"SDK_PRUNE_OUT_OF_SCOPE",
|
|
764
|
+
`${req.label} was not replaced: the replace would delete ${what} (${foreign.map((o) => o.label).join(", ")}) \u2014 this project's landing record does not name ${one ? "it" : "them"}. Nothing was written.
|
|
765
|
+
To delete ${one ? "it" : "them"}, ${rerun === void 0 ? "pass `--yes`" : `run \`${rerun}\``}${req.rerun?.note ?? ""}; to keep ${one ? "it" : "them"}, declare ${one ? "it" : "them"} in this project.`,
|
|
766
|
+
{ exitCode: EXIT_CONFLICT, details: refusalDetails("pruneOutOfScope", { outOfScope: foreign }) }
|
|
767
|
+
);
|
|
768
|
+
}
|
|
769
|
+
function foreignObjects(live, outgoing, landedGuids) {
|
|
770
|
+
const sent = /* @__PURE__ */ new Set();
|
|
771
|
+
for (const key of LOCK_PAYLOAD_KEYS) {
|
|
772
|
+
for (const row of payloadRows(outgoing, key)) if (typeof row.guid === "string") sent.add(row.guid);
|
|
773
|
+
}
|
|
774
|
+
const label = rowLabeler(payloadOf(live));
|
|
775
|
+
const out = [];
|
|
776
|
+
for (const key of LOCK_PAYLOAD_KEYS) {
|
|
777
|
+
for (const row of payloadRows(live, key)) {
|
|
778
|
+
if (typeof row.guid !== "string" || row.guid === "" || sent.has(row.guid) || landedGuids.has(row.guid)) continue;
|
|
779
|
+
out.push({ type: sectionKind(key, row), name: typeof row.name === "string" ? row.name : "", label: label(key, row) });
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
return out;
|
|
783
|
+
}
|
|
784
|
+
async function gateForeignDeletes(req, notLanded) {
|
|
785
|
+
if (notLanded.length === 0 || req.allowForeignDeletes === true) return;
|
|
786
|
+
const one = notLanded.length === 1;
|
|
787
|
+
const what = `${plural(notLanded.length, "object", "objects")} ${NOT_LANDED} (${notLanded.map((o) => o.label).join(", ")})`;
|
|
788
|
+
if (req.confirm !== void 0) {
|
|
789
|
+
if (await req.confirm(`Delete ${what} from ${req.label}?`)) return;
|
|
790
|
+
throw new KeepDataDeclined(req.label);
|
|
791
|
+
}
|
|
792
|
+
const rerun = req.rerun === void 0 ? void 0 : withFlag(req.rerun.command, "--yes", "-y");
|
|
793
|
+
throw new CliError(
|
|
794
|
+
"SDK_PRUNE_OUT_OF_SCOPE",
|
|
795
|
+
`${req.label} was not merged: the merge would delete ${what} \u2014 this project's landing record does not name ${one ? "it" : "them"}. Nothing was written.
|
|
796
|
+
To delete ${one ? "it" : "them"}, ${rerun === void 0 ? "pass `--yes`" : `run \`${rerun}\``}${req.rerun?.note ?? ""}; to keep ${one ? "it" : "them"}, declare ${one ? "it" : "them"} in this project.`,
|
|
797
|
+
{ exitCode: EXIT_CONFLICT, details: refusalDetails("pruneOutOfScope", { outOfScope: [...notLanded] }) }
|
|
798
|
+
);
|
|
799
|
+
}
|
|
800
|
+
function withFlag(command, flag, alias) {
|
|
801
|
+
const words = command.split(" ");
|
|
802
|
+
if (words.some((w) => w === flag || w === alias)) return command;
|
|
803
|
+
const mode = flag === "--reset" ? words.indexOf("--keep-data") : -1;
|
|
804
|
+
if (mode === -1) return `${command} ${flag}`;
|
|
805
|
+
words.splice(mode + 1, 0, flag);
|
|
806
|
+
return words.join(" ");
|
|
807
|
+
}
|
|
808
|
+
function plural(n, one, many) {
|
|
809
|
+
return `${n} ${n === 1 ? one : many}`;
|
|
810
|
+
}
|
|
811
|
+
function seededTableNames(bundle, content) {
|
|
812
|
+
const seeded = new Set(seedRowsByTableGuid(content).keys());
|
|
813
|
+
const out = /* @__PURE__ */ new Set();
|
|
814
|
+
const dbo = bundle?.payload?.dbo;
|
|
815
|
+
if (!Array.isArray(dbo)) return out;
|
|
816
|
+
for (const table of dbo) {
|
|
817
|
+
const { guid, name } = table ?? {};
|
|
818
|
+
if (typeof guid === "string" && typeof name === "string" && seeded.has(guid)) out.add(name);
|
|
819
|
+
}
|
|
820
|
+
return out;
|
|
821
|
+
}
|
|
822
|
+
function renamedTables(live, outgoing) {
|
|
823
|
+
return renamedRows(live, outgoing, "dbo");
|
|
824
|
+
}
|
|
825
|
+
function renamedRows(live, outgoing, section) {
|
|
826
|
+
const liveNames = /* @__PURE__ */ new Map();
|
|
827
|
+
for (const row of payloadRows(live, section)) {
|
|
828
|
+
if (typeof row.guid === "string" && typeof row.name === "string") liveNames.set(row.guid, row.name);
|
|
829
|
+
}
|
|
830
|
+
const out = [];
|
|
831
|
+
for (const row of payloadRows(outgoing, section)) {
|
|
832
|
+
if (typeof row.guid !== "string" || typeof row.name !== "string") continue;
|
|
833
|
+
const from = liveNames.get(row.guid);
|
|
834
|
+
if (from !== void 0 && from !== row.name) out.push({ from, to: row.name });
|
|
835
|
+
}
|
|
836
|
+
return out;
|
|
837
|
+
}
|
|
838
|
+
function payloadRows(bundle, key) {
|
|
839
|
+
const rows = bundle?.payload?.[key];
|
|
840
|
+
return Array.isArray(rows) ? rows.filter((r) => r !== null && typeof r === "object") : [];
|
|
841
|
+
}
|
|
842
|
+
function planLabel(op) {
|
|
843
|
+
return `${sectionKind(planTypeSection(op.type))}:${op.name}`;
|
|
844
|
+
}
|
|
845
|
+
function deleteNamer(live, outgoing) {
|
|
846
|
+
const label = rowLabeler(payloadOf(live));
|
|
847
|
+
const claimed = /* @__PURE__ */ new Set();
|
|
848
|
+
return (op) => {
|
|
849
|
+
const section = planTypeSection(op.type);
|
|
850
|
+
const kept = new Set(
|
|
851
|
+
payloadRows(outgoing, section).map((r) => r.guid).filter((g) => typeof g === "string")
|
|
852
|
+
);
|
|
853
|
+
const row = payloadRows(live, section).find(
|
|
854
|
+
(r) => !claimed.has(r) && r.name === op.name && (typeof r.guid !== "string" || !kept.has(r.guid))
|
|
855
|
+
);
|
|
856
|
+
if (row === void 0) return { type: sectionKind(section), label: planLabel(op) };
|
|
857
|
+
claimed.add(row);
|
|
858
|
+
return {
|
|
859
|
+
type: sectionKind(section, row),
|
|
860
|
+
label: label(section, row),
|
|
861
|
+
...typeof row.guid === "string" ? { guid: row.guid } : {}
|
|
862
|
+
};
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
var NOT_LANDED = "not in this project (landed by another source)";
|
|
866
|
+
var MIRRORS = "keep-data mirrors this project's source";
|
|
867
|
+
function classifyDeletes(operations, nameDelete, landedGuids) {
|
|
868
|
+
const deletes = operations.filter((o) => o.action === "delete");
|
|
869
|
+
const landed = (guid) => landedGuids === void 0 || guid !== void 0 && landedGuids.has(guid);
|
|
870
|
+
const tables = deletes.filter((o) => TABLE_KINDS.has(o.type)).map((o) => ({ name: o.name, guid: nameDelete(o).guid })).map((t) => ({ name: t.name, ours: landed(t.guid), ...t.guid === void 0 ? {} : { guid: t.guid } }));
|
|
871
|
+
const others = deletes.filter((o) => !TABLE_KINDS.has(o.type)).map((o) => ({ op: o, ...nameDelete(o) })).map((d) => ({ label: d.label, ours: landed(d.guid), type: d.type, name: d.op.name, ...d.guid === void 0 ? {} : { guid: d.guid } }));
|
|
872
|
+
const notLanded = [
|
|
873
|
+
...tables.filter((t) => !t.ours).map((t) => ({ type: "table", name: t.name, label: `table:${t.name}` })),
|
|
874
|
+
...others.filter((o) => !o.ours).map((o) => ({ type: o.type, name: o.name, label: o.label }))
|
|
875
|
+
];
|
|
876
|
+
return { tables, others, notLanded };
|
|
877
|
+
}
|
|
878
|
+
function discloseMerge(operations, diff, seeded, deletes, renamed, envSetTo = "", resetRerun = "xanosdk deploy --keep-data --reset", asking = false, slugMoves = [], channelRenames = [], addedColumns = []) {
|
|
879
|
+
const tableDeletes = deletes.tables;
|
|
880
|
+
const droppedTables = tableDeletes.map((t) => t.name);
|
|
881
|
+
const will = asking ? "would" : "will";
|
|
882
|
+
const effects = tableEffectsOf(diff, { createdTables: [], addedColumns: [...addedColumns], addedDefaults: {}, renamedTables: [] }, { mode: "merge" });
|
|
883
|
+
const unseededTables = operations.filter((o) => o.action === "create" && TABLE_KINDS.has(o.type) && seeded.has(o.name)).map((o) => o.name);
|
|
884
|
+
const keptEnv = diff.unchangedEnv.map((e) => e.name);
|
|
885
|
+
for (const { from, to } of renamed) detail(`The merge ${will} rename table ${from} \u2192 ${to} (rows kept).`);
|
|
886
|
+
if (slugMoves.length > 0) {
|
|
887
|
+
warn(
|
|
888
|
+
`The merge ${will} move ${plural(slugMoves.length, "public URL", "public URLs")} \u2014 the project pins another \`canonical\`, and every endpoint under the old slug stops answering:`,
|
|
889
|
+
"plan.canonical-change",
|
|
890
|
+
slugMoves.map((m) => `${m.kind} "${m.name}": ${m.from} \u2192 ${m.to}`)
|
|
891
|
+
);
|
|
892
|
+
}
|
|
893
|
+
const detached = [
|
|
894
|
+
...slugMoves.filter((m) => m.kind === "realtimeServer").map((m) => `${m.kind} "${m.name}": ${m.from} \u2192 ${m.to}`),
|
|
895
|
+
...channelRenames.map((c) => `realtimeChannel "${c.from}" \u2192 "${c.to}"`)
|
|
896
|
+
];
|
|
897
|
+
if (detached.length > 0) {
|
|
898
|
+
warn(
|
|
899
|
+
`The merge ${will} detach realtime history: sockets on the old ${channelRenames.length === 0 ? "slug" : slugMoves.some((m) => m.kind === "realtimeServer") ? "slug or channel" : "channel"} stop connecting, and the \`conversation\` transcript and the \`at_least_once\` replay stay under the old name \u2014 a client joins with no history. Moving the name back restores them:`,
|
|
900
|
+
"plan.realtime-history-detached",
|
|
901
|
+
detached
|
|
902
|
+
);
|
|
903
|
+
}
|
|
904
|
+
for (const ours of [true, false]) {
|
|
905
|
+
const tables = tableDeletes.filter((t) => t.ours === ours).map((t) => t.name);
|
|
906
|
+
if (tables.length === 0) continue;
|
|
907
|
+
const rows = `with every row in ${tables.length === 1 ? "it" : "them"}`;
|
|
908
|
+
warn(
|
|
909
|
+
ours ? `The merge ${will} DROP ${plural(tables.length, "table", "tables")} the project no longer declares, ${rows}:` : `The merge ${will} DROP ${plural(tables.length, "table", "tables")} ${NOT_LANDED}, ${rows} \u2014 ${MIRRORS}:`,
|
|
910
|
+
"plan.table-drop",
|
|
911
|
+
tables
|
|
912
|
+
);
|
|
913
|
+
}
|
|
914
|
+
discloseTableEffects(effects, {
|
|
915
|
+
subject: "the merge",
|
|
916
|
+
stages: "deploys",
|
|
917
|
+
will,
|
|
918
|
+
remedies: {
|
|
919
|
+
"plan.column-retype": "`--reset` re-seeds instead.",
|
|
920
|
+
"plan.enum-values-removed": "`--reset` re-seeds instead.",
|
|
921
|
+
"plan.not-null-kept": `A replace recreates the table, which relaxes it (and replaces its rows with the seed rows): \`${resetRerun}\`, or a deploy without \`--keep-data\`.`,
|
|
922
|
+
"plan.not-null-tightened": `Give ${effects.notNullTightened.length === 1 ? "it" : "them"} a value in each row, or keep \`nullable: true\`; a replace re-seeds instead (\`${resetRerun}\`).`
|
|
923
|
+
}
|
|
924
|
+
});
|
|
925
|
+
const removed = deletes.others.map((d) => d.label);
|
|
926
|
+
const removedOurs = deletes.others.filter((d) => d.ours).map((d) => d.label);
|
|
927
|
+
const removedOthers = deletes.others.filter((d) => !d.ours).map((d) => d.label);
|
|
928
|
+
if (removedOurs.length > 0) {
|
|
929
|
+
warn(
|
|
930
|
+
`The merge ${will} also remove, as the project no longer declares ${removedOurs.length === 1 ? "it" : "them"}:`,
|
|
931
|
+
"plan.object-remove",
|
|
932
|
+
removedOurs
|
|
933
|
+
);
|
|
934
|
+
}
|
|
935
|
+
if (removedOthers.length > 0) {
|
|
936
|
+
warn(`The merge ${will} also remove, ${NOT_LANDED} \u2014 ${MIRRORS}:`, "plan.object-remove", removedOthers);
|
|
937
|
+
}
|
|
938
|
+
const notLanded = deletes.notLanded.map((o) => o.label);
|
|
939
|
+
if (unseededTables.length > 0) {
|
|
940
|
+
warn(
|
|
941
|
+
`${plural(unseededTables.length, "new table declares", "new tables declare")} seed rows a merge does not write \u2014 ${unseededTables.join(", ")}. \`--reset\` seeds ${unseededTables.length === 1 ? "it" : "them"}, and replaces every other table's rows with its seeds too.`,
|
|
942
|
+
"plan.seed-not-written"
|
|
943
|
+
);
|
|
944
|
+
}
|
|
945
|
+
const differing = diff.unchangedEnv.filter((e) => !e.empty).map((e) => e.name);
|
|
946
|
+
const unfilled = diff.unchangedEnv.filter((e) => e.empty).map((e) => e.name);
|
|
947
|
+
if (differing.length > 0) {
|
|
948
|
+
const one = differing.length === 1;
|
|
949
|
+
warn(
|
|
950
|
+
`${plural(differing.length, "environment variable keeps its", "environment variables keep their")} live value \u2014 the project's differs, and a merge does not update values: ${differing.join(", ")}. To apply the project's, run:`,
|
|
951
|
+
"plan.env-kept",
|
|
952
|
+
[
|
|
953
|
+
...differing.map((name) => envSetFromStdin(name, envSetTo)),
|
|
954
|
+
`or deploy with \`--reset\`, which applies ${one ? "it" : "them"} and also replaces the rows with the seed rows.`
|
|
955
|
+
]
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
if (unfilled.length > 0) {
|
|
959
|
+
const one = unfilled.length === 1;
|
|
960
|
+
warn(
|
|
961
|
+
`${plural(unfilled.length, "environment variable keeps its", "environment variables keep their")} live value \u2014 the project's is empty: ${unfilled.join(", ")}. A merge never updates a value; to change ${one ? "it" : "them"}, run:`,
|
|
962
|
+
"plan.env-kept",
|
|
963
|
+
[
|
|
964
|
+
...unfilled.map((name) => envSetFromStdin(name, envSetTo)),
|
|
965
|
+
`or fill ${one ? "it" : "them"} in the backend's \`.env\` and deploy with \`--reset\` (which also replaces the rows with the seed rows).`
|
|
966
|
+
]
|
|
967
|
+
);
|
|
968
|
+
}
|
|
969
|
+
const unappliedDocumentation = [...diff.unappliedDocumentation];
|
|
970
|
+
if (unappliedDocumentation.length > 0) {
|
|
971
|
+
const what = unappliedDocumentation.includes("require_token") ? unappliedDocumentation.includes("token") ? "documentation gate and token" : "documentation gate" : "documentation token";
|
|
972
|
+
warn(
|
|
973
|
+
`The workspace ${what} ${will} NOT be updated \u2014 a merge does not write the workspace's \`documentation\` block. \`--reset\` writes it.`,
|
|
974
|
+
"plan.doc-not-updated"
|
|
975
|
+
);
|
|
976
|
+
}
|
|
977
|
+
return {
|
|
978
|
+
droppedTables,
|
|
979
|
+
...tableEffectFields(effects),
|
|
980
|
+
removed,
|
|
981
|
+
removedGuids: [...deletes.tables, ...deletes.others].filter((d) => d.ours && d.guid !== void 0).map((d) => d.guid),
|
|
982
|
+
notLanded,
|
|
983
|
+
unseededTables,
|
|
984
|
+
renamedTables: renamed,
|
|
985
|
+
keptEnv,
|
|
986
|
+
unappliedDocumentation,
|
|
987
|
+
canonicalChanges: [...slugMoves],
|
|
988
|
+
pairedColumns: droppedAndAdded(effects)
|
|
989
|
+
};
|
|
990
|
+
}
|
|
991
|
+
async function mergeKeepingData(req) {
|
|
992
|
+
const target = {
|
|
993
|
+
baseUrl: req.baseUrl,
|
|
994
|
+
workspaceId: req.workspaceId,
|
|
995
|
+
label: req.label,
|
|
996
|
+
...req.stateCheck === void 0 ? {} : { stateCheck: req.stateCheck },
|
|
997
|
+
...req.fetchFn === void 0 ? {} : { fetchFn: req.fetchFn }
|
|
998
|
+
};
|
|
999
|
+
let capable;
|
|
1000
|
+
try {
|
|
1001
|
+
capable = await detectXanoSdkImportRoute(req.auth, target);
|
|
1002
|
+
} catch (err) {
|
|
1003
|
+
throw await unreachableProbeError(err, req);
|
|
1004
|
+
}
|
|
1005
|
+
if (!capable) throw cannotMergeError(req.label);
|
|
1006
|
+
const outgoing = JSON.parse(req.bundle);
|
|
1007
|
+
let live;
|
|
1008
|
+
try {
|
|
1009
|
+
live = await withSpinner(
|
|
1010
|
+
"Reading the environment to preview the merge\u2026",
|
|
1011
|
+
() => exportWorkspaceBundle(req.auth, { base: req.baseUrl, workspaceId: req.workspaceId, label: `${req.label} live read` })
|
|
1012
|
+
);
|
|
1013
|
+
} catch (err) {
|
|
1014
|
+
throw await unansweredReadError(err, req);
|
|
1015
|
+
}
|
|
1016
|
+
const triggers = req.kind === "local-engine" ? [] : liveTableTriggers(live);
|
|
1017
|
+
if (triggers.length > 0) {
|
|
1018
|
+
const reset = req.rerun === void 0 ? "xanosdk deploy --keep-data --reset" : withFlag(req.rerun.command, "--reset");
|
|
1019
|
+
throw tableTriggerMergeError(req.label, triggers, { command: reset, note: req.rerun?.note ?? "" });
|
|
1020
|
+
}
|
|
1021
|
+
const diff = diffAgainstLive(outgoing, live, { mode: "merge", ...req.storedColumns === void 0 ? {} : { stored: req.storedColumns } });
|
|
1022
|
+
const resetRerun = req.rerun === void 0 ? "xanosdk deploy --keep-data --reset" : withFlag(req.rerun.command, "--reset");
|
|
1023
|
+
if (req.kind !== "local-engine") {
|
|
1024
|
+
await assertStorageModesKept(diff.storageChanges, tableRowCounter(req.auth, { workspaceId: req.workspaceId, base: req.baseUrl }), {
|
|
1025
|
+
target: req.label,
|
|
1026
|
+
subject: "the merge",
|
|
1027
|
+
remedy: `rebuild the environment with \`${resetRerun}\` ` + (req.content.length > 0 ? "(that replaces its rows with the seed rows)." : "(that leaves its tables EMPTY \u2014 this deploy carries no seed rows to put back).") + (req.rerun?.note ?? "")
|
|
1028
|
+
});
|
|
1029
|
+
}
|
|
1030
|
+
const archive = encodeWorkspaceArchive(req.bundle, req.files ?? []);
|
|
1031
|
+
const pinned = req.pinned ?? [];
|
|
1032
|
+
const request = { ...target, archive, mode: "merge", prune: true, pinned };
|
|
1033
|
+
let plan;
|
|
1034
|
+
try {
|
|
1035
|
+
plan = await withSpinner("Previewing the merge\u2026", () => xanosdkImport(req.auth, { ...request, dryRun: true }));
|
|
1036
|
+
} catch (err) {
|
|
1037
|
+
if (err instanceof XanoSdkImportRefusal) throw refusedError(req.label, err, diff.indexChanges, req.rerun);
|
|
1038
|
+
const unanswered = await unansweredReadError(err, req);
|
|
1039
|
+
if (unanswered !== err) throw unanswered;
|
|
1040
|
+
if (!(err instanceof Error && /writes nothing|untouched|intact/.test(err.message))) {
|
|
1041
|
+
detail("The preview writes nothing, so the environment's data is untouched.");
|
|
1042
|
+
}
|
|
1043
|
+
throw err;
|
|
1044
|
+
}
|
|
1045
|
+
const operations = plan.plan.operations;
|
|
1046
|
+
const renames = pendingRenames(operations, deleteNamer(live, outgoing), req.lockPins);
|
|
1047
|
+
if (renames.length > 0) throw pendingRenameError(req.label, renames, resetRerun);
|
|
1048
|
+
const collisions = nameCollisions(operations, live, outgoing);
|
|
1049
|
+
if (collisions.length > 0) {
|
|
1050
|
+
const parents = parentRenames(collisions, live, outgoing, req.lockPins);
|
|
1051
|
+
throw parents.length > 0 ? parentRenameError(req.label, parents, collisions, resetRerun) : collisionError(req.label, collisions, resetRerun);
|
|
1052
|
+
}
|
|
1053
|
+
const slugConflicts = canonicalConflicts(plan.conflicts, plan.canonicals, operations, live, req.lockPins, req.workspaceId);
|
|
1054
|
+
if (slugConflicts.length > 0) {
|
|
1055
|
+
const steps = siblingSlugSteps(slugConflicts, plan.canonicals, live);
|
|
1056
|
+
const again = req.rerun?.command ?? "xanosdk deploy --keep-data";
|
|
1057
|
+
throw canonicalConflictError(req.label, slugConflicts, resetRerun, steps === void 0 ? void 0 : { list: steps, rerun: again });
|
|
1058
|
+
}
|
|
1059
|
+
const deletes = classifyDeletes(operations, deleteNamer(live, outgoing), req.landedGuids);
|
|
1060
|
+
const foreign = deletes.notLanded.length > 0 && req.allowForeignDeletes !== true;
|
|
1061
|
+
if (foreign && req.confirm === void 0) await gateForeignDeletes(req, deletes.notLanded);
|
|
1062
|
+
const result = discloseMerge(
|
|
1063
|
+
operations,
|
|
1064
|
+
diff,
|
|
1065
|
+
seededTableNames(outgoing, req.content),
|
|
1066
|
+
deletes,
|
|
1067
|
+
renamedTables(live, outgoing),
|
|
1068
|
+
req.envSetTo,
|
|
1069
|
+
req.rerun === void 0 ? void 0 : withFlag(req.rerun.command, "--reset"),
|
|
1070
|
+
foreign,
|
|
1071
|
+
canonicalChanges(plan.canonicals, live),
|
|
1072
|
+
renamedRows(live, outgoing, "channel"),
|
|
1073
|
+
tableAdditions(outgoing, live).addedColumns
|
|
1074
|
+
);
|
|
1075
|
+
await gateForeignDeletes(req, deletes.notLanded);
|
|
1076
|
+
const relabel = await req.beforeWrite?.() ?? {};
|
|
1077
|
+
const label = relabel.label ?? req.label;
|
|
1078
|
+
const stateCheck = relabel.stateCheck ?? req.stateCheck;
|
|
1079
|
+
let applied;
|
|
1080
|
+
try {
|
|
1081
|
+
applied = await withSpinner(
|
|
1082
|
+
"Merging the workspace, keeping its data\u2026",
|
|
1083
|
+
() => xanosdkImport(req.auth, { ...request, label, ...stateCheck === void 0 ? {} : { stateCheck }, dryRun: false })
|
|
1084
|
+
);
|
|
1085
|
+
} catch (err) {
|
|
1086
|
+
if (err instanceof XanoSdkImportRefusal) throw refusedError(label, err, diff.indexChanges, req.rerun);
|
|
1087
|
+
throw err;
|
|
1088
|
+
}
|
|
1089
|
+
const missed = applied.canonicals.filter(
|
|
1090
|
+
(c) => c.guid !== void 0 && pinned.includes(c.guid) && c.outcome !== "honored"
|
|
1091
|
+
);
|
|
1092
|
+
if (missed.length > 0) throw canonicalNotServedError(label, missed, resetRerun);
|
|
1093
|
+
return {
|
|
1094
|
+
...result,
|
|
1095
|
+
canonicalChanges: canonicalChanges(applied.canonicals, live),
|
|
1096
|
+
storedColumns: storedColumnsAfter(outgoing, live, req.storedColumns ?? /* @__PURE__ */ new Map(), "merge")
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
function envSetFromStdin(name, to) {
|
|
1100
|
+
return `printf %s "$VALUE" | xanosdk env set ${shellQuote(name)}${to}`;
|
|
1101
|
+
}
|
|
1102
|
+
export {
|
|
1103
|
+
KeepDataDeclined,
|
|
1104
|
+
cannotMergeError,
|
|
1105
|
+
clearReplacedCommand,
|
|
1106
|
+
gateForeignReplace,
|
|
1107
|
+
importInProgressError,
|
|
1108
|
+
liveTableTriggers,
|
|
1109
|
+
mergeKeepingData,
|
|
1110
|
+
pendingRenameDetail,
|
|
1111
|
+
pendingRenameFollowUp,
|
|
1112
|
+
pendingRenameLines,
|
|
1113
|
+
sameNameRepin,
|
|
1114
|
+
setGuidRemedy,
|
|
1115
|
+
tableTriggerMergeError,
|
|
1116
|
+
unansweredReadError,
|
|
1117
|
+
unreachableProbeError
|
|
1118
|
+
};
|
|
1119
|
+
//# sourceMappingURL=keep-data-merge-7MPLVAVI.js.map
|