@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,218 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_BRANCH_LABEL
|
|
3
|
+
} from "./chunk-TRJCALW3.js";
|
|
4
|
+
import {
|
|
5
|
+
assertOneName
|
|
6
|
+
} from "./chunk-ZIY7RNUT.js";
|
|
7
|
+
import {
|
|
8
|
+
LookupFailedError,
|
|
9
|
+
isUnansweredLookup,
|
|
10
|
+
lookupFailed,
|
|
11
|
+
unansweredCause
|
|
12
|
+
} from "./chunk-QCNYHBL7.js";
|
|
13
|
+
import {
|
|
14
|
+
findRelease
|
|
15
|
+
} from "./chunk-2ZUEE4EK.js";
|
|
16
|
+
import {
|
|
17
|
+
contextFlags
|
|
18
|
+
} from "./chunk-NAQDMEHV.js";
|
|
19
|
+
import {
|
|
20
|
+
fetchOrExplain,
|
|
21
|
+
parseJsonAnswer,
|
|
22
|
+
safeHttpFailure
|
|
23
|
+
} from "./chunk-YLDALTWZ.js";
|
|
24
|
+
import {
|
|
25
|
+
UsageError,
|
|
26
|
+
safeText
|
|
27
|
+
} from "./chunk-PTHVMXZI.js";
|
|
28
|
+
|
|
29
|
+
// src/deploy/audit-log.ts
|
|
30
|
+
var TIMEOUT_MS = 3e4;
|
|
31
|
+
var PAGE_SIZE = 100;
|
|
32
|
+
var MAX_PAGES = 20;
|
|
33
|
+
function rowTime(v) {
|
|
34
|
+
if (typeof v === "number") return v;
|
|
35
|
+
if (typeof v !== "string") return void 0;
|
|
36
|
+
const t = Date.parse(v.replace(" ", "T").replace(/([+-]\d{2})(\d{2})$/, "$1:$2"));
|
|
37
|
+
return Number.isNaN(t) ? void 0 : t;
|
|
38
|
+
}
|
|
39
|
+
function asString(v) {
|
|
40
|
+
return typeof v === "string" && v !== "" ? v : void 0;
|
|
41
|
+
}
|
|
42
|
+
function obj(v) {
|
|
43
|
+
return v !== null && typeof v === "object" && !Array.isArray(v) ? v : void 0;
|
|
44
|
+
}
|
|
45
|
+
function pageRows(body) {
|
|
46
|
+
if (Array.isArray(body)) return body;
|
|
47
|
+
const items = obj(body)?.items;
|
|
48
|
+
return Array.isArray(items) ? items : [];
|
|
49
|
+
}
|
|
50
|
+
async function findReleaseSource(auth, opts) {
|
|
51
|
+
for (let page = 1; page <= MAX_PAGES; page++) {
|
|
52
|
+
const rows = await readPage(auth, opts.workspaceId, page);
|
|
53
|
+
for (const row of rows) {
|
|
54
|
+
const entry = obj(row);
|
|
55
|
+
if (entry === void 0 || entry.type !== "release:create") continue;
|
|
56
|
+
const data = obj(entry.data);
|
|
57
|
+
if (asString(obj(data?.release)?.name) !== opts.releaseName) continue;
|
|
58
|
+
const source = obj(data?.source);
|
|
59
|
+
const tenantName = asString(source?.tenant_name);
|
|
60
|
+
if (tenantName === void 0) return null;
|
|
61
|
+
return {
|
|
62
|
+
tenantName,
|
|
63
|
+
tenantType: asString(source?.tenant_type),
|
|
64
|
+
records: source?.records === true
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
if (rows.length < PAGE_SIZE) break;
|
|
68
|
+
const oldest = rowTime(obj(rows.at(-1))?.created_at);
|
|
69
|
+
if (opts.notBefore !== void 0 && oldest !== void 0 && oldest < opts.notBefore) break;
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
async function readPage(auth, workspaceId, page) {
|
|
74
|
+
const path = `/api:meta/workspace/${workspaceId}/audit_log?page=${page}&per_page=${PAGE_SIZE}&include_data=true`;
|
|
75
|
+
const action = "confirm the release source";
|
|
76
|
+
const res = await fetchOrExplain(
|
|
77
|
+
new URL(path, auth.instance).href,
|
|
78
|
+
{
|
|
79
|
+
method: "GET",
|
|
80
|
+
headers: {
|
|
81
|
+
accept: "application/json",
|
|
82
|
+
Authorization: `Bearer ${auth.access_token}`
|
|
83
|
+
},
|
|
84
|
+
signal: AbortSignal.timeout(TIMEOUT_MS)
|
|
85
|
+
},
|
|
86
|
+
action,
|
|
87
|
+
TIMEOUT_MS
|
|
88
|
+
);
|
|
89
|
+
const text = await res.text();
|
|
90
|
+
if (!res.ok) {
|
|
91
|
+
throw auditLogHttpError(
|
|
92
|
+
res.status,
|
|
93
|
+
safeHttpFailure(action, res, text, {
|
|
94
|
+
boundWorkspaceId: auth.workspaceId,
|
|
95
|
+
instance: auth.instance,
|
|
96
|
+
profile: auth.profile,
|
|
97
|
+
addressedWorkspaceId: workspaceId,
|
|
98
|
+
credentialType: auth.credentialType,
|
|
99
|
+
// Always the credential's own instance — the audit log lives with the
|
|
100
|
+
// workspace the release landed in, never on a tenant's host.
|
|
101
|
+
tenantHost: false
|
|
102
|
+
})
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
const body = parseJsonAnswer(text, action, res.url, { safe: true });
|
|
106
|
+
return pageRows(body);
|
|
107
|
+
}
|
|
108
|
+
function auditLogHttpError(status, message) {
|
|
109
|
+
return Object.assign(new Error(message), { status });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// src/emit/release-common.ts
|
|
113
|
+
var EXIT_RELEASE_REFUSED = 2;
|
|
114
|
+
function requireName(args, verb) {
|
|
115
|
+
const name = args.positionals[0];
|
|
116
|
+
if (name === void 0 || name === "") {
|
|
117
|
+
throw new UsageError(
|
|
118
|
+
`\`xanosdk release ${verb}\` needs a release name. Run \`xanosdk release list${contextFlags()}\` to see them.`,
|
|
119
|
+
// One line and the pointer: the sentence says what to type.
|
|
120
|
+
{ hintFor: { command: "release", subcommand: verb } }
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
assertOneName(name, "the release name", { args, helpFor: { command: "release", subcommand: verb } });
|
|
124
|
+
return name;
|
|
125
|
+
}
|
|
126
|
+
async function releaseOrigin(auth, release) {
|
|
127
|
+
if (release.copiedFrom !== void 0) {
|
|
128
|
+
const { source: source2, cut } = release.copiedFrom;
|
|
129
|
+
if (cut === void 0) return { kind: "copy", source: source2 };
|
|
130
|
+
return {
|
|
131
|
+
kind: "copy",
|
|
132
|
+
source: source2,
|
|
133
|
+
from: cut.type === "branch" ? { kind: "branch", label: cut.name } : { kind: "environment", ...cut }
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
if (typeof release.branch === "string" && release.branch !== "") return { kind: "branch", label: release.branch };
|
|
137
|
+
if (release.recordedOrigin !== void 0) {
|
|
138
|
+
return { kind: "environment", name: release.recordedOrigin.name, type: release.recordedOrigin.type };
|
|
139
|
+
}
|
|
140
|
+
const created = release.createdAt === void 0 ? NaN : Date.parse(release.createdAt);
|
|
141
|
+
const source = await findReleaseSource(auth, {
|
|
142
|
+
workspaceId: auth.workspaceId,
|
|
143
|
+
releaseName: release.name,
|
|
144
|
+
// A margin for clock skew between the record and the log row.
|
|
145
|
+
...Number.isNaN(created) ? {} : { notBefore: created - 10 * 6e4 }
|
|
146
|
+
}).catch(() => null);
|
|
147
|
+
return source === null ? void 0 : { kind: "environment", name: source.tenantName, type: source.tenantType };
|
|
148
|
+
}
|
|
149
|
+
function passwordHashesWarning(release, columns, where, after = "the landing", origin, takesEntryFile = true) {
|
|
150
|
+
const head = `Release "${release}" carries seeded password hashes (${columns.join(", ")}). A password hash is keyed to the environment that made it \u2014 every workspace, ephemeral and tenant has its own key, and no release carries it \u2014 so `;
|
|
151
|
+
const fix = takesEntryFile ? `Deploy the entry file to seed them from plaintext, or reset those passwords after ${after}.` : `${where[0].toUpperCase()}${where.slice(1)} takes only a release, so they cannot be seeded from plaintext there: reset those passwords on it after ${after}, or land a release cut without that table's rows (\`release create\` without its \`--seed\` guid).`;
|
|
152
|
+
return origin === void 0 ? `${head}logins against these rows fail on ${where} as a bad password unless it is the environment the release was cut from, which is not recorded. ${fix}` : `${head}these verify only on ${origin}, and logins against these rows will fail on ${where} as a bad password. ${fix}`;
|
|
153
|
+
}
|
|
154
|
+
async function passwordOrigin(auth, release) {
|
|
155
|
+
const name = typeof release === "string" ? release : release.name;
|
|
156
|
+
const found = typeof release === "string" ? await findRelease(auth, { workspaceId: auth.workspaceId, name }).catch(() => null) : release;
|
|
157
|
+
let origin;
|
|
158
|
+
if (found !== null) {
|
|
159
|
+
origin = await releaseOrigin(auth, found);
|
|
160
|
+
} else {
|
|
161
|
+
const source = await findReleaseSource(auth, { workspaceId: auth.workspaceId, releaseName: name }).catch(
|
|
162
|
+
() => null
|
|
163
|
+
);
|
|
164
|
+
if (source !== null) origin = { kind: "environment", name: source.tenantName, type: source.tenantType };
|
|
165
|
+
}
|
|
166
|
+
if (origin === void 0) return void 0;
|
|
167
|
+
if (origin.kind === "copy") {
|
|
168
|
+
return {
|
|
169
|
+
name: void 0,
|
|
170
|
+
phrase: origin.from?.kind === "environment" ? `${describeOrigin(origin.from)} of the workspace the release was copied from` : "the workspace the release was copied from"
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
if (origin.kind === "branch") {
|
|
174
|
+
return {
|
|
175
|
+
name: void 0,
|
|
176
|
+
phrase: origin.label === DEFAULT_BRANCH_LABEL ? "the workspace that cut it" : `the workspace (${describeOrigin(origin)})`
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
return { name: origin.name, phrase: describeOrigin(origin) };
|
|
180
|
+
}
|
|
181
|
+
function describeOrigin(origin) {
|
|
182
|
+
if (origin.kind === "copy") {
|
|
183
|
+
const { release, workspaceId, host } = origin.source;
|
|
184
|
+
return `release ${safeText(JSON.stringify(release))} of workspace ${workspaceId} on ${safeText(host)} (copied${origin.from === void 0 ? "" : `; cut there from ${describeOrigin(origin.from)}`})`;
|
|
185
|
+
}
|
|
186
|
+
return origin.kind === "branch" ? `branch "${safeText(origin.label)}"` : `${origin.type ?? "environment"} "${safeText(origin.name)}"`;
|
|
187
|
+
}
|
|
188
|
+
function readUnanswered(kind, what, not, err) {
|
|
189
|
+
if (!isUnansweredLookup(err)) return err;
|
|
190
|
+
const first = ((err instanceof Error ? err.message : String(err)).split("\n")[0] ?? "").trim().replace(/[.:]$/, "");
|
|
191
|
+
const cause = unansweredCause(err);
|
|
192
|
+
return new LookupFailedError(
|
|
193
|
+
`Could not ${what}: ${first}. ${cause}, not ${not} \u2014 nothing was created or changed`,
|
|
194
|
+
"unreachable",
|
|
195
|
+
kind
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
async function lookupRelease(auth, name) {
|
|
199
|
+
try {
|
|
200
|
+
return await findRelease(auth, { workspaceId: auth.workspaceId, name });
|
|
201
|
+
} catch (err) {
|
|
202
|
+
if (isUnansweredLookup(err)) throw lookupFailed("release", name, err);
|
|
203
|
+
throw err;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export {
|
|
208
|
+
findReleaseSource,
|
|
209
|
+
EXIT_RELEASE_REFUSED,
|
|
210
|
+
requireName,
|
|
211
|
+
releaseOrigin,
|
|
212
|
+
passwordHashesWarning,
|
|
213
|
+
passwordOrigin,
|
|
214
|
+
describeOrigin,
|
|
215
|
+
readUnanswered,
|
|
216
|
+
lookupRelease
|
|
217
|
+
};
|
|
218
|
+
//# sourceMappingURL=chunk-AWEIIR2U.js.map
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// src/util/secrets.ts
|
|
2
|
+
var secrets = /* @__PURE__ */ new Set();
|
|
3
|
+
var REDACTED = "<redacted>";
|
|
4
|
+
var MIN_SECRET_LENGTH = 8;
|
|
5
|
+
function registerSecret(value) {
|
|
6
|
+
if (typeof value !== "string") return;
|
|
7
|
+
const forms = /* @__PURE__ */ new Set([value, value.trim()]);
|
|
8
|
+
let piece = "";
|
|
9
|
+
for (const ch of value) {
|
|
10
|
+
const code = ch.charCodeAt(0);
|
|
11
|
+
if (code <= 32 || code === 127 || /\s/.test(ch)) {
|
|
12
|
+
forms.add(piece);
|
|
13
|
+
piece = "";
|
|
14
|
+
} else piece += ch;
|
|
15
|
+
}
|
|
16
|
+
forms.add(piece);
|
|
17
|
+
for (const form of [...forms]) forms.add(JSON.stringify(form).slice(1, -1));
|
|
18
|
+
for (const form of forms) {
|
|
19
|
+
if (form.length >= MIN_SECRET_LENGTH) secrets.add(form);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function redactSecrets(text) {
|
|
23
|
+
if (secrets.size === 0) return text;
|
|
24
|
+
let out = text;
|
|
25
|
+
for (const secret of [...secrets].sort((a, b) => b.length - a.length)) {
|
|
26
|
+
if (out.includes(secret)) out = out.split(secret).join(REDACTED);
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
var dataWrites = /* @__PURE__ */ new WeakSet();
|
|
31
|
+
function writeData(stream, data) {
|
|
32
|
+
dataWrites.add(stream);
|
|
33
|
+
try {
|
|
34
|
+
return stream.write(data);
|
|
35
|
+
} finally {
|
|
36
|
+
dataWrites.delete(stream);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function installSecretRedaction(stream) {
|
|
40
|
+
const original = stream.write.bind(stream);
|
|
41
|
+
stream.write = ((chunk, ...rest) => {
|
|
42
|
+
if (secrets.size > 0 && !dataWrites.has(stream)) {
|
|
43
|
+
if (typeof chunk === "string") chunk = redactSecrets(chunk);
|
|
44
|
+
else if (chunk instanceof Uint8Array) chunk = redactBytes(chunk);
|
|
45
|
+
}
|
|
46
|
+
return original(chunk, ...rest);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function redactBytes(chunk) {
|
|
50
|
+
const buf = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength);
|
|
51
|
+
for (const secret of secrets) {
|
|
52
|
+
if (buf.includes(secret)) return Buffer.from(redactSecrets(buf.toString("utf8")), "utf8");
|
|
53
|
+
}
|
|
54
|
+
return chunk;
|
|
55
|
+
}
|
|
56
|
+
function tokenTextProblem(token) {
|
|
57
|
+
for (let i = 0; i < token.length; i++) {
|
|
58
|
+
const code = token.charCodeAt(i);
|
|
59
|
+
if (code >= 33 && code <= 126) continue;
|
|
60
|
+
const kind = code === 10 || code === 13 ? "a line break" : code === 32 || code === 9 ? "whitespace" : code < 32 || code === 127 ? "a control character" : "a non-ASCII character";
|
|
61
|
+
return `contains ${kind} at character ${i + 1} of ${token.length}`;
|
|
62
|
+
}
|
|
63
|
+
return void 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export {
|
|
67
|
+
registerSecret,
|
|
68
|
+
redactSecrets,
|
|
69
|
+
writeData,
|
|
70
|
+
installSecretRedaction,
|
|
71
|
+
tokenTextProblem
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=chunk-AWQ7BQTQ.js.map
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import {
|
|
2
|
+
listOverrideEntries,
|
|
3
|
+
listReleaseEntries,
|
|
4
|
+
readEngineEntry,
|
|
5
|
+
readPin,
|
|
6
|
+
verifiedEngineExecutable
|
|
7
|
+
} from "./chunk-6ELFRN3P.js";
|
|
8
|
+
import {
|
|
9
|
+
clearEngineRecordsNamed,
|
|
10
|
+
listEngineRecords
|
|
11
|
+
} from "./chunk-3M4LFYNQ.js";
|
|
12
|
+
import {
|
|
13
|
+
assertLoopbackUrl,
|
|
14
|
+
engineCacheDir,
|
|
15
|
+
engineRunHome,
|
|
16
|
+
localEngineHome,
|
|
17
|
+
parseEngineHandshake,
|
|
18
|
+
parseEngineListing
|
|
19
|
+
} from "./chunk-AM4FKL4J.js";
|
|
20
|
+
import {
|
|
21
|
+
fetchOrExplain,
|
|
22
|
+
httpFailureError
|
|
23
|
+
} from "./chunk-YLDALTWZ.js";
|
|
24
|
+
|
|
25
|
+
// src/deploy/local-engine-process.ts
|
|
26
|
+
import { spawn as nodeSpawn, spawnSync } from "child_process";
|
|
27
|
+
import { appendFileSync, existsSync, mkdirSync, readdirSync, rmSync } from "fs";
|
|
28
|
+
import { dirname, join, sep } from "path";
|
|
29
|
+
var HANDSHAKE_TIMEOUT_MS = 6e4;
|
|
30
|
+
var MAX_HANDSHAKE_BYTES = 64 * 1024;
|
|
31
|
+
var MAX_STDERR_BYTES = 64 * 1024;
|
|
32
|
+
var ENGINE_ENV_ALLOWLIST = [
|
|
33
|
+
"HOME",
|
|
34
|
+
"PATH",
|
|
35
|
+
"TMPDIR",
|
|
36
|
+
"LANG",
|
|
37
|
+
"LC_ALL",
|
|
38
|
+
"USER",
|
|
39
|
+
"LOGNAME",
|
|
40
|
+
"SHELL",
|
|
41
|
+
"TERM"
|
|
42
|
+
];
|
|
43
|
+
var defaultSpawn = (executable, args, options) => nodeSpawn(executable, [...args], { ...options, windowsHide: true });
|
|
44
|
+
var defaultRun = (executable, args, options) => {
|
|
45
|
+
const result = spawnSync(executable, [...args], { ...options, encoding: "utf8", windowsHide: true });
|
|
46
|
+
return {
|
|
47
|
+
status: result.status,
|
|
48
|
+
stdout: result.stdout ?? "",
|
|
49
|
+
stderr: result.stderr ?? ""
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
function redactSecrets(text) {
|
|
53
|
+
return text.replace(/eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*/g, "[redacted]").replace(/(\bkey=)[^&\s"']+/gi, "$1[redacted]").replace(/(\bBearer\s+)\S+/gi, "$1[redacted]");
|
|
54
|
+
}
|
|
55
|
+
function engineChildEnv(env = process.env) {
|
|
56
|
+
const built = {};
|
|
57
|
+
for (const key of ENGINE_ENV_ALLOWLIST) {
|
|
58
|
+
const value = env[key];
|
|
59
|
+
if (value !== void 0) built[key] = value;
|
|
60
|
+
}
|
|
61
|
+
built.PATH = env.PATH ?? "";
|
|
62
|
+
built.HOME = engineRunHome(env);
|
|
63
|
+
return built;
|
|
64
|
+
}
|
|
65
|
+
function engineLogPath(name, env = process.env) {
|
|
66
|
+
return join(localEngineHome(env), "logs", `${name}.log`);
|
|
67
|
+
}
|
|
68
|
+
function engineOwnLogs(env = process.env) {
|
|
69
|
+
const cache = engineCacheDir(env);
|
|
70
|
+
try {
|
|
71
|
+
for (const entry of readdirSync(cache, { withFileTypes: true })) {
|
|
72
|
+
const logs = join(cache, entry.name, "logs");
|
|
73
|
+
if (entry.isDirectory() && existsSync(logs)) return logs;
|
|
74
|
+
}
|
|
75
|
+
} catch {
|
|
76
|
+
}
|
|
77
|
+
return cache;
|
|
78
|
+
}
|
|
79
|
+
var FIRST_TTL_RELEASE = [0, 1, 15];
|
|
80
|
+
function engineExpiresEphemerals(version) {
|
|
81
|
+
const parts = /^v?(\d+)\.(\d+)\.(\d+)/.exec(version?.trim() ?? "")?.slice(1).map(Number);
|
|
82
|
+
if (parts === void 0) return false;
|
|
83
|
+
for (let i = 0; i < 3; i++) if (parts[i] !== FIRST_TTL_RELEASE[i]) return parts[i] > FIRST_TTL_RELEASE[i];
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
async function startEngine(opts) {
|
|
87
|
+
const env = opts.env ?? process.env;
|
|
88
|
+
const spawn = opts.spawn ?? defaultSpawn;
|
|
89
|
+
const executable = verifiedEngineExecutable(opts.entry, env);
|
|
90
|
+
const logPath = engineLogPath(opts.name, env);
|
|
91
|
+
mkdirSync(join(localEngineHome(env), "logs"), { recursive: true, mode: 448 });
|
|
92
|
+
mkdirSync(engineRunHome(env), { recursive: true, mode: 448 });
|
|
93
|
+
rmSync(logPath, { force: true });
|
|
94
|
+
let launcherPrinted = false;
|
|
95
|
+
const outputIsIn = () => {
|
|
96
|
+
const own = engineOwnLogs(env);
|
|
97
|
+
const where = [
|
|
98
|
+
...existsSync(own) ? [`The engine's own log is the newest file in ${own}`] : [],
|
|
99
|
+
...launcherPrinted ? [`What it printed while starting is in ${logPath}`] : []
|
|
100
|
+
];
|
|
101
|
+
return where.join("; ").replace(/; What/, "; what");
|
|
102
|
+
};
|
|
103
|
+
const checkOutput = () => {
|
|
104
|
+
const where = outputIsIn();
|
|
105
|
+
return where === "" ? "It left no log to check \u2014 re-run it." : `${where} \u2014 check it, then re-run.`;
|
|
106
|
+
};
|
|
107
|
+
const child = spawn(
|
|
108
|
+
executable,
|
|
109
|
+
// `--ephemeral` for a throwaway backend, `--detach` so the launcher prints
|
|
110
|
+
// the handshake and exits while the engine keeps serving, `--name` so this
|
|
111
|
+
// project's engine is findable by the one handle everything matches on.
|
|
112
|
+
// `--ttl 0` because a project's engine is reused across deploys and holds
|
|
113
|
+
// its data and static site: the default one-hour lifetime would delete both.
|
|
114
|
+
["--ephemeral", "--detach", "--name", opts.name, ...engineExpiresEphemerals(opts.version) ? ["--ttl", "0"] : []],
|
|
115
|
+
{
|
|
116
|
+
detached: true,
|
|
117
|
+
// stdin ignored: nothing here answers a prompt, and an inherited stdin is
|
|
118
|
+
// a detached process competing with the CLI for the terminal.
|
|
119
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
120
|
+
env: engineChildEnv(env)
|
|
121
|
+
}
|
|
122
|
+
);
|
|
123
|
+
return new Promise((resolve, reject) => {
|
|
124
|
+
let settled = false;
|
|
125
|
+
let stdout = "";
|
|
126
|
+
let stderr = "";
|
|
127
|
+
const timeoutMs = opts.timeoutMs ?? HANDSHAKE_TIMEOUT_MS;
|
|
128
|
+
const timer = setTimeout(() => {
|
|
129
|
+
fail(
|
|
130
|
+
new Error(
|
|
131
|
+
`The engine did not report itself started within ${Math.round(timeoutMs / 1e3)}s.
|
|
132
|
+
` + checkOutput()
|
|
133
|
+
)
|
|
134
|
+
);
|
|
135
|
+
}, timeoutMs);
|
|
136
|
+
function finish(engine) {
|
|
137
|
+
if (settled) return;
|
|
138
|
+
settled = true;
|
|
139
|
+
clearTimeout(timer);
|
|
140
|
+
child.unref();
|
|
141
|
+
resolve(engine);
|
|
142
|
+
}
|
|
143
|
+
function fail(err) {
|
|
144
|
+
if (settled) return;
|
|
145
|
+
settled = true;
|
|
146
|
+
clearTimeout(timer);
|
|
147
|
+
try {
|
|
148
|
+
child.kill();
|
|
149
|
+
} catch {
|
|
150
|
+
}
|
|
151
|
+
reject(err);
|
|
152
|
+
}
|
|
153
|
+
child.stdout?.on("data", (chunk) => {
|
|
154
|
+
stdout += String(chunk);
|
|
155
|
+
if (stdout.length > MAX_HANDSHAKE_BYTES) {
|
|
156
|
+
fail(
|
|
157
|
+
new Error(
|
|
158
|
+
`The engine printed too much output without reporting itself started.
|
|
159
|
+
` + checkOutput()
|
|
160
|
+
)
|
|
161
|
+
);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
try {
|
|
165
|
+
JSON.parse(stdout.trim());
|
|
166
|
+
} catch {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
finish(parseEngineHandshake(stdout));
|
|
171
|
+
} catch (err) {
|
|
172
|
+
fail(err);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
child.stderr?.on("data", (chunk) => {
|
|
176
|
+
const text = redactSecrets(String(chunk));
|
|
177
|
+
if (stderr.length < MAX_STDERR_BYTES) stderr += text;
|
|
178
|
+
try {
|
|
179
|
+
appendFileSync(logPath, text, { mode: 384 });
|
|
180
|
+
launcherPrinted = true;
|
|
181
|
+
} catch {
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
child.on("error", (err) => {
|
|
185
|
+
fail(
|
|
186
|
+
new Error(
|
|
187
|
+
`The engine could not be started: ${err.message}
|
|
188
|
+
Fetch a fresh copy with \`xanosdk local-engine cache clear\`, then deploy again (\`xanosdk deploy --local-engine\`).`
|
|
189
|
+
)
|
|
190
|
+
);
|
|
191
|
+
});
|
|
192
|
+
child.on("close", (code) => {
|
|
193
|
+
setImmediate(() => {
|
|
194
|
+
if (settled) return;
|
|
195
|
+
fail(new Error(bootFailure(opts.name, code, stderr.trim(), outputIsIn(), engineRunHome(env))));
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
function bootFailure(name, code, tail, outputIsIn, runHome) {
|
|
201
|
+
const reported = /\bexit status \d+/i.test(tail);
|
|
202
|
+
const head = `The engine ${name} exited${reported || code === null ? "" : ` (status ${code})`} instead of starting.`;
|
|
203
|
+
const lines = tail.split("\n").map((l) => l.trim()).filter((l) => l !== "");
|
|
204
|
+
let cause;
|
|
205
|
+
const denied = lines.find((l) => /permission denied|\bEACCES\b|operation not permitted|read-only file system/i.test(l));
|
|
206
|
+
if (denied !== void 0) {
|
|
207
|
+
const named = /(\/[^\s:"']+)\s*:\s*(?:permission denied|operation not permitted|read-only file system)/i.exec(denied)?.[1];
|
|
208
|
+
const dir = nearestExisting(named ?? join(runHome, "x"));
|
|
209
|
+
cause = dir === void 0 ? `It could not write its own files \u2014 make ${runHome} and everything under it writable (\`chmod -R u+w ${runHome}\`), then re-run.` : `It could not write under ${dir} \u2014 make it writable (\`chmod u+w ${dir}\`), then re-run.`;
|
|
210
|
+
} else if (lines.some((l) => /already (?:in use|taken|running|exists)|address in use|\bEADDRINUSE\b/i.test(l))) {
|
|
211
|
+
cause = `The name or port is already taken \u2014 stop the engine holding it with \`xanosdk local-engine stop ${name}\`, then re-run.`;
|
|
212
|
+
} else {
|
|
213
|
+
const last = [...lines].reverse().find((l) => /\berror\b|failed|denied|cannot|refused|not found|no such/i.test(l));
|
|
214
|
+
cause = last === void 0 ? "Check it, then re-run." : `Its last error: ${last}`;
|
|
215
|
+
}
|
|
216
|
+
return `${head}${tail === "" ? "" : `
|
|
217
|
+
${tail}`}
|
|
218
|
+
${outputIsIn === "" ? "" : `${outputIsIn}. `}${cause}`;
|
|
219
|
+
}
|
|
220
|
+
function nearestExisting(path) {
|
|
221
|
+
for (let dir = dirname(path); dirname(dir) !== dir; dir = dirname(dir)) {
|
|
222
|
+
if (existsSync(dir)) return dir;
|
|
223
|
+
}
|
|
224
|
+
return void 0;
|
|
225
|
+
}
|
|
226
|
+
function cachedEngineEntry(env, cwd = process.cwd(), exclude = /* @__PURE__ */ new Set()) {
|
|
227
|
+
const keep = (e) => e !== void 0 && !exclude.has(e.dir) ? e : void 0;
|
|
228
|
+
const pin = readPin(cwd);
|
|
229
|
+
if (typeof pin === "string") {
|
|
230
|
+
const pinned = keep(readEngineEntry({ version: pin }, env));
|
|
231
|
+
if (pinned !== void 0) return pinned;
|
|
232
|
+
}
|
|
233
|
+
return listReleaseEntries(env).find((e) => keep(e)) ?? listOverrideEntries(env).find((e) => keep(e));
|
|
234
|
+
}
|
|
235
|
+
function runVerb(args, opts) {
|
|
236
|
+
const env = opts.env ?? process.env;
|
|
237
|
+
const run = opts.run ?? defaultRun;
|
|
238
|
+
return run(verifiedEngineExecutable(opts.entry, env), args, { env: engineChildEnv(env) });
|
|
239
|
+
}
|
|
240
|
+
function listEngines(opts) {
|
|
241
|
+
const result = runVerb(["list", "--json"], opts);
|
|
242
|
+
if (result.status !== 0) {
|
|
243
|
+
throw new Error(
|
|
244
|
+
`The engine could not list what is running` + (result.stderr.trim() === "" ? `.` : `: ${redactSecrets(result.stderr.trim())}`) + `
|
|
245
|
+
Re-run, and if it happens again fetch a fresh copy with \`xanosdk local-engine cache clear\`, then \`xanosdk deploy --local-engine\`.`
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
return parseEngineListing(result.stdout);
|
|
249
|
+
}
|
|
250
|
+
function engineVersionToken(output) {
|
|
251
|
+
const first = output.split("\n")[0].trim();
|
|
252
|
+
if (first === "") return void 0;
|
|
253
|
+
return /\bv?\d+\.\d+\.\d+\S*/.exec(first)?.[0] ?? first;
|
|
254
|
+
}
|
|
255
|
+
function engineVersion(opts) {
|
|
256
|
+
const result = runVerb(["version"], opts);
|
|
257
|
+
if (result.status !== 0) {
|
|
258
|
+
throw new Error(
|
|
259
|
+
`The engine could not report its version.
|
|
260
|
+
Re-run with the engine's URL or an archive path on the flag to get a fresh one.`
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
return result.stdout.trim();
|
|
264
|
+
}
|
|
265
|
+
var LOGIN_LINK_TIMEOUT_MS = 1e4;
|
|
266
|
+
var defaultLoginFetch = (url, init) => fetchOrExplain(url, init, "open a local engine", LOGIN_LINK_TIMEOUT_MS);
|
|
267
|
+
async function mintEngineLoginLink(engine, opts = {}) {
|
|
268
|
+
assertLoopbackUrl(engine.loginLinkEndpoint, "The engine's sign-in route");
|
|
269
|
+
const doFetch = opts.fetch ?? defaultLoginFetch;
|
|
270
|
+
const res = await doFetch(engine.loginLinkEndpoint, {
|
|
271
|
+
method: "POST",
|
|
272
|
+
headers: {
|
|
273
|
+
// The enumeration's bearer, on a loopback url, and nowhere else.
|
|
274
|
+
authorization: `Bearer ${engine.token}`,
|
|
275
|
+
"content-type": "application/json"
|
|
276
|
+
},
|
|
277
|
+
// A body either way: the route reads one, and `{}` is the plain session.
|
|
278
|
+
body: JSON.stringify(opts.guest === true ? { guest_read_only: true } : {})
|
|
279
|
+
});
|
|
280
|
+
if (!res.ok) {
|
|
281
|
+
const body = redactSecrets(await res.text().catch(() => ""));
|
|
282
|
+
if (res.status === 401) {
|
|
283
|
+
throw new Error(
|
|
284
|
+
`The engine no longer accepts the credential it reported for "${engine.name}".
|
|
285
|
+
It was most likely restarted since it was listed \u2014 run \`xanosdk local-engine list\` to see what is running, then try again.`
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
throw httpFailureError(`open a local engine`, res, body);
|
|
289
|
+
}
|
|
290
|
+
const data = await res.json().catch(() => ({}));
|
|
291
|
+
if (typeof data._ti !== "string" || data._ti === "" || typeof data.url !== "string" || data.url === "") {
|
|
292
|
+
throw new Error(
|
|
293
|
+
`The engine did not return a one-time sign-in (\`_ti\`) and a url for "${engine.name}".
|
|
294
|
+
That is not an engine this SDK knows how to drive \u2014 move to a current one with \`xanosdk local-engine update\`.`
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
assertLoopbackUrl(data.url, "The sign-in the engine returned");
|
|
298
|
+
return { _ti: data._ti, url: data.url };
|
|
299
|
+
}
|
|
300
|
+
function resolveRecordedEngine(record, running) {
|
|
301
|
+
const engine = running.find((e) => e.name === record.name);
|
|
302
|
+
if (engine === void 0) return { state: "stale" };
|
|
303
|
+
try {
|
|
304
|
+
assertLoopbackUrl(engine.url, "The engine recorded for this project");
|
|
305
|
+
} catch (err) {
|
|
306
|
+
return { state: "unusable", reason: err.message };
|
|
307
|
+
}
|
|
308
|
+
return { state: "live", engine };
|
|
309
|
+
}
|
|
310
|
+
function stopEngineNamed(name, opts) {
|
|
311
|
+
const result = runVerb(["stop", name], opts);
|
|
312
|
+
return {
|
|
313
|
+
name,
|
|
314
|
+
stopped: result.status === 0,
|
|
315
|
+
clearedProjects: clearEngineRecordsNamed(name, opts.env ?? process.env)
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
function stopAllEngines(opts) {
|
|
319
|
+
const env = opts.env ?? process.env;
|
|
320
|
+
const running = listEngines(opts);
|
|
321
|
+
const ours = new Set(listEngineRecords(env).map((r) => r.name));
|
|
322
|
+
const stopped = [];
|
|
323
|
+
const foreign = [];
|
|
324
|
+
for (const engine of running) {
|
|
325
|
+
if (ours.has(engine.name)) stopped.push(stopEngineNamed(engine.name, opts));
|
|
326
|
+
else foreign.push(engine.name);
|
|
327
|
+
}
|
|
328
|
+
return { stopped, foreign, orphans: stopOrphanedEngineProcesses(opts) };
|
|
329
|
+
}
|
|
330
|
+
var defaultProcessTable = () => {
|
|
331
|
+
if (process.platform === "win32") return [];
|
|
332
|
+
const result = spawnSync("ps", ["-axo", "pid=,ppid=,command="], { encoding: "utf8", windowsHide: true });
|
|
333
|
+
if (result.status !== 0 || typeof result.stdout !== "string") return [];
|
|
334
|
+
return result.stdout.split("\n").flatMap((line) => {
|
|
335
|
+
const m = /^\s*(\d+)\s+(\d+)\s+(.*)$/.exec(line);
|
|
336
|
+
return m === null ? [] : [{ pid: Number(m[1]), ppid: Number(m[2]), command: m[3] }];
|
|
337
|
+
});
|
|
338
|
+
};
|
|
339
|
+
var defaultSignal = (pid, signal) => {
|
|
340
|
+
try {
|
|
341
|
+
process.kill(pid, signal);
|
|
342
|
+
return true;
|
|
343
|
+
} catch {
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
function findOrphanedEngineProcesses(opts = {}) {
|
|
348
|
+
const env = opts.env ?? process.env;
|
|
349
|
+
const runHome = `${engineRunHome(env)}${sep}`;
|
|
350
|
+
const home = `${localEngineHome(env)}${sep}`;
|
|
351
|
+
const rows = (opts.processes ?? defaultProcessTable)();
|
|
352
|
+
const byPid = new Map(rows.map((row) => [row.pid, row]));
|
|
353
|
+
const isEngine = (row) => row.command.startsWith(home) && !row.command.startsWith(runHome);
|
|
354
|
+
return rows.filter(
|
|
355
|
+
(row) => row.pid !== process.pid && row.command.includes(runHome) && !isEngine(row) && !(byPid.get(row.ppid)?.command.includes(home) ?? false)
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
function stopOrphanedEngineProcesses(opts = {}) {
|
|
359
|
+
const signal = opts.signal ?? defaultSignal;
|
|
360
|
+
const pids = findOrphanedEngineProcesses(opts).map((row) => row.pid).filter((pid) => signal(pid, "SIGTERM"));
|
|
361
|
+
const deadline = Date.now() + (opts.waitMs ?? 1e4);
|
|
362
|
+
let alive = pids.filter((pid) => signal(pid, 0));
|
|
363
|
+
const pause = new Int32Array(new SharedArrayBuffer(4));
|
|
364
|
+
while (alive.length > 0 && Date.now() < deadline) {
|
|
365
|
+
Atomics.wait(pause, 0, 0, 100);
|
|
366
|
+
alive = alive.filter((pid) => signal(pid, 0));
|
|
367
|
+
}
|
|
368
|
+
return { stopped: pids.filter((pid) => !alive.includes(pid)), stillRunning: alive };
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
export {
|
|
372
|
+
HANDSHAKE_TIMEOUT_MS,
|
|
373
|
+
MAX_HANDSHAKE_BYTES,
|
|
374
|
+
ENGINE_ENV_ALLOWLIST,
|
|
375
|
+
engineChildEnv,
|
|
376
|
+
engineLogPath,
|
|
377
|
+
engineOwnLogs,
|
|
378
|
+
engineExpiresEphemerals,
|
|
379
|
+
startEngine,
|
|
380
|
+
bootFailure,
|
|
381
|
+
cachedEngineEntry,
|
|
382
|
+
listEngines,
|
|
383
|
+
engineVersionToken,
|
|
384
|
+
engineVersion,
|
|
385
|
+
LOGIN_LINK_TIMEOUT_MS,
|
|
386
|
+
mintEngineLoginLink,
|
|
387
|
+
resolveRecordedEngine,
|
|
388
|
+
stopEngineNamed,
|
|
389
|
+
stopAllEngines,
|
|
390
|
+
findOrphanedEngineProcesses,
|
|
391
|
+
stopOrphanedEngineProcesses
|
|
392
|
+
};
|
|
393
|
+
//# sourceMappingURL=chunk-BAUZOWGX.js.map
|