svamp-cli 0.1.50 → 0.1.52
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/dist/cli.mjs +25 -22
- package/dist/{commands-D-nIO_Sf.mjs → commands-1tmye7o_.mjs} +7 -3
- package/dist/{commands-D1brd9fB.mjs → commands-CI_BVphs.mjs} +7 -3
- package/dist/{commands-DHnFOhQC.mjs → commands-DcFOU9nW.mjs} +7 -3
- package/dist/commands-DwY2B7KW.mjs +562 -0
- package/dist/index.mjs +1 -1
- package/dist/{package-BLDik3NY.mjs → package-BRivSAkK.mjs} +1 -1
- package/dist/{package-BYUO-39f.mjs → package-D7EUXtnk.mjs} +1 -1
- package/dist/{run-BE_AIJ7z.mjs → run-BYJX5syg.mjs} +1 -1
- package/dist/{run-CE4H8ZiN.mjs → run-BnnUavlu.mjs} +199 -65
- package/dist/{run-BG3279Kg.mjs → run-Bw6aGHLA.mjs} +1 -1
- package/dist/{run-4li60ojK.mjs → run-DOwarObi.mjs} +1 -1
- package/dist/{run-C0ecvcRP.mjs → run-DxISzP_V.mjs} +63 -8
- package/dist/{run-Bc83CRUn.mjs → run-eYBOEaWw.mjs} +22 -7
- package/dist/tunnel-C2_V6y3d.mjs +299 -0
- package/package.json +1 -1
- package/dist/commands-4_MiOQVp.mjs +0 -1217
- package/dist/commands-8UAWGJrC.mjs +0 -1208
- package/dist/commands-8Wmq0uak.mjs +0 -1407
- package/dist/commands-8Xn02pQg.mjs +0 -1217
- package/dist/commands-9DPsh6ku.mjs +0 -1217
- package/dist/commands-9rMB13FP.mjs +0 -1214
- package/dist/commands-B-XaqFDB.mjs +0 -1407
- package/dist/commands-B53zuBHB.mjs +0 -1217
- package/dist/commands-B7yLt11i.mjs +0 -1217
- package/dist/commands-BDVAO_N2.mjs +0 -1217
- package/dist/commands-BD_NjWJL.mjs +0 -1217
- package/dist/commands-BEhSQqTp.mjs +0 -507
- package/dist/commands-BIFQZZGw.mjs +0 -1375
- package/dist/commands-BImRR1Wr.mjs +0 -1217
- package/dist/commands-BLmRIMdf.mjs +0 -1217
- package/dist/commands-BOYo9cdy.mjs +0 -1741
- package/dist/commands-BQ_347V_.mjs +0 -1374
- package/dist/commands-BTEmyf2m.mjs +0 -1407
- package/dist/commands-BVjcCbWS.mjs +0 -1375
- package/dist/commands-BVsLRttq.mjs +0 -1217
- package/dist/commands-BVuE0VQU.mjs +0 -507
- package/dist/commands-BY09VTpk.mjs +0 -1375
- package/dist/commands-Bcdp0X-o.mjs +0 -1217
- package/dist/commands-BdnG1cqQ.mjs +0 -1217
- package/dist/commands-BdvvRQIo.mjs +0 -1415
- package/dist/commands-Bgg_dvDw.mjs +0 -1683
- package/dist/commands-Bi0zYJvj.mjs +0 -1407
- package/dist/commands-BmirUCVt.mjs +0 -1208
- package/dist/commands-BpSUbvmr.mjs +0 -1217
- package/dist/commands-BuJ6xTfc.mjs +0 -1217
- package/dist/commands-BzbYPx0f.mjs +0 -1208
- package/dist/commands-C-RtFjJl.mjs +0 -1217
- package/dist/commands-C20_f6oo.mjs +0 -1217
- package/dist/commands-C6KDr9Yp.mjs +0 -1407
- package/dist/commands-C9TOoTCv.mjs +0 -1395
- package/dist/commands-C9TdN_El.mjs +0 -1683
- package/dist/commands-CFv6lO0D.mjs +0 -1217
- package/dist/commands-CJ2n5jS2.mjs +0 -1375
- package/dist/commands-CKEKQ_5B.mjs +0 -1217
- package/dist/commands-CQz67Rm1.mjs +0 -1395
- package/dist/commands-CRZbJjqN.mjs +0 -1375
- package/dist/commands-CToIvBFX.mjs +0 -1375
- package/dist/commands-CWsfciHn.mjs +0 -1217
- package/dist/commands-CYMSyqYC.mjs +0 -1395
- package/dist/commands-CZ7KPLLJ.mjs +0 -1217
- package/dist/commands-Cc73uUnP.mjs +0 -1375
- package/dist/commands-CdMsAD1-.mjs +0 -1217
- package/dist/commands-CdyCWC3y.mjs +0 -1395
- package/dist/commands-ClVCprrK.mjs +0 -1217
- package/dist/commands-Cnmf8znA.mjs +0 -1196
- package/dist/commands-CorUNLRF.mjs +0 -1375
- package/dist/commands-Cq0oj5_v.mjs +0 -1217
- package/dist/commands-CrdvbXPI.mjs +0 -1395
- package/dist/commands-Cw2Od6mc.mjs +0 -1683
- package/dist/commands-CwC2aVzu.mjs +0 -1217
- package/dist/commands-CxSCUJCB.mjs +0 -1217
- package/dist/commands-D-PTwdZz.mjs +0 -1217
- package/dist/commands-D7-NHH5q.mjs +0 -1407
- package/dist/commands-D7kH-7Vn.mjs +0 -1217
- package/dist/commands-DBv6A3aJ.mjs +0 -507
- package/dist/commands-DD3HXakm.mjs +0 -1217
- package/dist/commands-DLoe6FyK.mjs +0 -1375
- package/dist/commands-DPbH8KF0.mjs +0 -1217
- package/dist/commands-DUAQ9MZM.mjs +0 -1217
- package/dist/commands-DVw-P6-0.mjs +0 -1407
- package/dist/commands-DVygnMsh.mjs +0 -1217
- package/dist/commands-DWira-Cz.mjs +0 -1741
- package/dist/commands-DYTdUlul.mjs +0 -1217
- package/dist/commands-DZfaDmsk.mjs +0 -1374
- package/dist/commands-Dd8cn8mW.mjs +0 -1217
- package/dist/commands-DsIoygTL.mjs +0 -1395
- package/dist/commands-Du-fdLLu.mjs +0 -969
- package/dist/commands-DuJGOq1y.mjs +0 -1217
- package/dist/commands-DwBr3sBn.mjs +0 -1217
- package/dist/commands-DwveR96q.mjs +0 -1683
- package/dist/commands-DypTF36z.mjs +0 -506
- package/dist/commands-EUMJqBCs.mjs +0 -1407
- package/dist/commands-HLu7P96l.mjs +0 -1214
- package/dist/commands-HrBaGV-C.mjs +0 -1683
- package/dist/commands-Jk5no-DX.mjs +0 -1407
- package/dist/commands-KH5dj9dv.mjs +0 -1214
- package/dist/commands-LaNHVHjc.mjs +0 -1217
- package/dist/commands-O1Q9g00y.mjs +0 -1395
- package/dist/commands-OwMfbBrU.mjs +0 -1395
- package/dist/commands-SQ0Wp_kD.mjs +0 -1217
- package/dist/commands-S_MFQ9n1.mjs +0 -354
- package/dist/commands-T3q8VKCY.mjs +0 -1407
- package/dist/commands-Ugz9TtRu.mjs +0 -1420
- package/dist/commands-Wng0OuNY.mjs +0 -1683
- package/dist/commands-YBW5jFpy.mjs +0 -1217
- package/dist/commands-Z-CbuF8E.mjs +0 -1217
- package/dist/commands-fSZOP80Z.mjs +0 -1217
- package/dist/commands-fqBuJe1b.mjs +0 -1217
- package/dist/commands-g-1n3_Rp.mjs +0 -1395
- package/dist/commands-mC0oe0lj.mjs +0 -1217
- package/dist/commands-od2hOku5.mjs +0 -1217
- package/dist/commands-otgzprjb.mjs +0 -1375
- package/dist/commands-rhHI6Wb2.mjs +0 -1420
- package/dist/commands-zGHnUXh5.mjs +0 -1217
- package/dist/package-BMCjXPI9.mjs +0 -58
- package/dist/package-BPMWPlS0.mjs +0 -57
- package/dist/package-BaGfG8vL.mjs +0 -58
- package/dist/package-BkBE6ZdN.mjs +0 -57
- package/dist/package-BufekbY1.mjs +0 -57
- package/dist/package-C1hpYMj4.mjs +0 -57
- package/dist/package-CmIBOZtY.mjs +0 -57
- package/dist/package-CmVt1kdw.mjs +0 -58
- package/dist/package-Cn6Ya4A0.mjs +0 -57
- package/dist/package-Csd530Ym.mjs +0 -57
- package/dist/package-D6mNQtUs.mjs +0 -57
- package/dist/package-DG0AkZdm.mjs +0 -58
- package/dist/package-DRO1LpXW.mjs +0 -58
- package/dist/package-Dav8qh6X.mjs +0 -57
- package/dist/package-DiA55dzE.mjs +0 -57
- package/dist/package-UwLIU765.mjs +0 -58
- package/dist/package-k3XsdP9k.mjs +0 -58
- package/dist/package-rasGC9_z.mjs +0 -58
- package/dist/run-4B1XZQB8.mjs +0 -5426
- package/dist/run-4eArMb_9.mjs +0 -1050
- package/dist/run-67wfoMuo.mjs +0 -5383
- package/dist/run-6N2IdEX7.mjs +0 -5410
- package/dist/run-6dwQnoBL.mjs +0 -1051
- package/dist/run-7iQKryzo.mjs +0 -5383
- package/dist/run-7s8lOXqB.mjs +0 -1050
- package/dist/run-8kKykzTs.mjs +0 -5367
- package/dist/run-8mLZV2lg.mjs +0 -1050
- package/dist/run-9x7I9Ck-.mjs +0 -5264
- package/dist/run-B-PWtXF-.mjs +0 -5894
- package/dist/run-B1ivovUl.mjs +0 -5964
- package/dist/run-B1l9Ed8k.mjs +0 -5403
- package/dist/run-B2zRMxE0.mjs +0 -5508
- package/dist/run-B31biy0V.mjs +0 -1050
- package/dist/run-B5o5fMMd.mjs +0 -5369
- package/dist/run-B7V-xXM7.mjs +0 -5775
- package/dist/run-B9ND6srh.mjs +0 -6154
- package/dist/run-BHZNzX1F.mjs +0 -5235
- package/dist/run-BKdOv7gX.mjs +0 -1050
- package/dist/run-BLySdZ1K.mjs +0 -5251
- package/dist/run-BOVkQfM-.mjs +0 -1050
- package/dist/run-BQ0lIare.mjs +0 -1050
- package/dist/run-BREPr7Yc.mjs +0 -5508
- package/dist/run-BTwshVk1.mjs +0 -5728
- package/dist/run-BUL3eAqT.mjs +0 -1050
- package/dist/run-BVcPemGr.mjs +0 -5947
- package/dist/run-BWqEmIiz.mjs +0 -5964
- package/dist/run-BWsDPiNe.mjs +0 -1050
- package/dist/run-BX4iy6k8.mjs +0 -1050
- package/dist/run-BXYfq8mK.mjs +0 -5836
- package/dist/run-BY12Ataq.mjs +0 -5732
- package/dist/run-BYDOX4yk.mjs +0 -5402
- package/dist/run-Bd-t6s63.mjs +0 -5373
- package/dist/run-BenYqfwQ.mjs +0 -5273
- package/dist/run-BfF4bgA3.mjs +0 -5403
- package/dist/run-Bhh05yic.mjs +0 -5369
- package/dist/run-BicITYWX.mjs +0 -6138
- package/dist/run-BieEN0Pg.mjs +0 -5761
- package/dist/run-BjEQi6PN.mjs +0 -1050
- package/dist/run-BjZ6SyFy.mjs +0 -1051
- package/dist/run-Bl8OkKyC.mjs +0 -5969
- package/dist/run-BlEFlhfn.mjs +0 -5510
- package/dist/run-BmL1m0Bk.mjs +0 -1050
- package/dist/run-Bmx5wEBF.mjs +0 -1051
- package/dist/run-BnX5Rw8x.mjs +0 -5403
- package/dist/run-BpjmHeht.mjs +0 -1050
- package/dist/run-BxTdRjCG.mjs +0 -1051
- package/dist/run-ByOVDgvx.mjs +0 -6115
- package/dist/run-BzRP6Q5t.mjs +0 -1051
- package/dist/run-C0dyMP62.mjs +0 -1051
- package/dist/run-C1lS3SwN.mjs +0 -5733
- package/dist/run-C3PAp02X.mjs +0 -5252
- package/dist/run-C3eaYQub.mjs +0 -1050
- package/dist/run-C4pdX4sY.mjs +0 -1051
- package/dist/run-C676pHe-.mjs +0 -5423
- package/dist/run-C8GkzcfP.mjs +0 -1050
- package/dist/run-C9Hrqjy_.mjs +0 -1050
- package/dist/run-CC2C8P-U.mjs +0 -6031
- package/dist/run-CCcW4asS.mjs +0 -1050
- package/dist/run-CDBKhQ1Z.mjs +0 -1051
- package/dist/run-CEB6sYzn.mjs +0 -5962
- package/dist/run-CF6aXLmA.mjs +0 -5445
- package/dist/run-CHyN5U0t.mjs +0 -1050
- package/dist/run-CIFezmkC.mjs +0 -5949
- package/dist/run-CLA9zw7J.mjs +0 -5907
- package/dist/run-COWb9ovq.mjs +0 -1050
- package/dist/run-CSUAy5T5.mjs +0 -1051
- package/dist/run-CSk7i0Hq.mjs +0 -1050
- package/dist/run-CUtqSGWJ.mjs +0 -1050
- package/dist/run-CXrEt0TM.mjs +0 -5008
- package/dist/run-CY8Y0JPW.mjs +0 -5287
- package/dist/run-CZCKBcQ-.mjs +0 -5244
- package/dist/run-CZj0sRCs.mjs +0 -1050
- package/dist/run-C_1x2cNU.mjs +0 -5381
- package/dist/run-C_8iOjO1.mjs +0 -5892
- package/dist/run-C_KIew8H.mjs +0 -1051
- package/dist/run-CajRcN3C.mjs +0 -1050
- package/dist/run-CbzXO7fw.mjs +0 -1050
- package/dist/run-CcSr4x2f.mjs +0 -1050
- package/dist/run-CcYaXgCy.mjs +0 -6091
- package/dist/run-CdihMx0V.mjs +0 -1051
- package/dist/run-Cf2Dl_ck.mjs +0 -1051
- package/dist/run-CjH1H4vq.mjs +0 -1050
- package/dist/run-CkbDK6jA.mjs +0 -1051
- package/dist/run-Ckh6JE9F.mjs +0 -1050
- package/dist/run-Ckyg9-fm.mjs +0 -6079
- package/dist/run-CqL3ZWdr.mjs +0 -5381
- package/dist/run-Csj7sJAh.mjs +0 -1050
- package/dist/run-Ct--DWF1.mjs +0 -1051
- package/dist/run-CtJRxaFC.mjs +0 -1051
- package/dist/run-CuIMdkKF.mjs +0 -6099
- package/dist/run-CuckJGM-.mjs +0 -1050
- package/dist/run-CxGAa9MH.mjs +0 -1050
- package/dist/run-CyU4-O-e.mjs +0 -5411
- package/dist/run-CymDyu2b.mjs +0 -5389
- package/dist/run-CzIY4_RE.mjs +0 -6093
- package/dist/run-D0Ha4aWt.mjs +0 -1050
- package/dist/run-D0ow-xms.mjs +0 -5905
- package/dist/run-D1PFrNZB.mjs +0 -6273
- package/dist/run-D2X3jEqg.mjs +0 -1051
- package/dist/run-D39C7Ta3.mjs +0 -1050
- package/dist/run-D3Lqxasl.mjs +0 -1051
- package/dist/run-D3bhRCCb.mjs +0 -1051
- package/dist/run-D5N42sVA.mjs +0 -1050
- package/dist/run-D691XPXy.mjs +0 -6031
- package/dist/run-D7dLDpq3.mjs +0 -5403
- package/dist/run-D8mQ_fL5.mjs +0 -1050
- package/dist/run-DA-YBjNw.mjs +0 -6018
- package/dist/run-DByI8mI0.mjs +0 -1051
- package/dist/run-DCINWip4.mjs +0 -1050
- package/dist/run-DCrZ3vke.mjs +0 -5406
- package/dist/run-DDF-tRbn.mjs +0 -5954
- package/dist/run-DGSgljJE.mjs +0 -5421
- package/dist/run-DGsXW19O.mjs +0 -5541
- package/dist/run-DHrF2xpW.mjs +0 -5776
- package/dist/run-DIB0W42M.mjs +0 -1050
- package/dist/run-DJ4k0WzZ.mjs +0 -1051
- package/dist/run-DMI83W7i.mjs +0 -5434
- package/dist/run-DNX3djCI.mjs +0 -1050
- package/dist/run-DOPaGRT2.mjs +0 -6027
- package/dist/run-DP7KSZqR.mjs +0 -1051
- package/dist/run-DQ0yljWr.mjs +0 -1050
- package/dist/run-DTkldU6a.mjs +0 -1050
- package/dist/run-DU10B3gK.mjs +0 -5728
- package/dist/run-DV86VJNG.mjs +0 -5386
- package/dist/run-DVZGKdKO.mjs +0 -1050
- package/dist/run-DWdtp6VD.mjs +0 -6136
- package/dist/run-DWzA1gZ-.mjs +0 -1050
- package/dist/run-DXJ2M19k.mjs +0 -1050
- package/dist/run-DZOeccNu.mjs +0 -5484
- package/dist/run-D_W5YF0D.mjs +0 -6046
- package/dist/run-DaReJPf8.mjs +0 -1051
- package/dist/run-DaYrEeQ9.mjs +0 -5400
- package/dist/run-DbC9-WM4.mjs +0 -1050
- package/dist/run-Dd9XkswU.mjs +0 -1051
- package/dist/run-De-wkVl3.mjs +0 -5487
- package/dist/run-DfU2luyX.mjs +0 -1050
- package/dist/run-Dfl3Ze2L.mjs +0 -5541
- package/dist/run-DfuHUDIJ.mjs +0 -1051
- package/dist/run-DfwfyFqj.mjs +0 -5975
- package/dist/run-DgUDGHZy.mjs +0 -1051
- package/dist/run-Dge2K7h1.mjs +0 -1050
- package/dist/run-Di3I0USw.mjs +0 -1050
- package/dist/run-Dm3U4FB5.mjs +0 -6018
- package/dist/run-Du0YOs48.mjs +0 -5446
- package/dist/run-DuaIQAE4.mjs +0 -5392
- package/dist/run-Dwm19YhI.mjs +0 -1050
- package/dist/run-DxM7xaBa.mjs +0 -1050
- package/dist/run-DysN-cGm.mjs +0 -1050
- package/dist/run-DzXohf8-.mjs +0 -1051
- package/dist/run-E_MwVOtN.mjs +0 -5272
- package/dist/run-FPoL2-FD.mjs +0 -5381
- package/dist/run-HU4XjZfs.mjs +0 -6023
- package/dist/run-HhiYlJuS.mjs +0 -5414
- package/dist/run-JXLlRLFb.mjs +0 -1050
- package/dist/run-K-_jahIg.mjs +0 -1051
- package/dist/run-K_S7pfZ-.mjs +0 -1050
- package/dist/run-LDiT4WF-.mjs +0 -1050
- package/dist/run-NToLJWx-.mjs +0 -5442
- package/dist/run-RBufRqbs.mjs +0 -1050
- package/dist/run-YFYpyThQ.mjs +0 -1051
- package/dist/run-YG1Pb9dY.mjs +0 -5385
- package/dist/run-ZDa17iLg.mjs +0 -6060
- package/dist/run-ZN0qMdS_.mjs +0 -1051
- package/dist/run-azpFWM6w.mjs +0 -1050
- package/dist/run-coIDvBK_.mjs +0 -6127
- package/dist/run-jLp4pbTE.mjs +0 -1050
- package/dist/run-m3oAuSg0.mjs +0 -1050
- package/dist/run-r9CAcL_U.mjs +0 -5403
- package/dist/run-v32uF2bP.mjs +0 -5378
- package/dist/run-vTsskoZc.mjs +0 -5340
- package/dist/run-vt26p5D7.mjs +0 -1050
- package/dist/run-vvQiCHpi.mjs +0 -5427
- package/dist/run-w-HVv5py.mjs +0 -5410
- package/dist/run-wpUutZ9C.mjs +0 -1051
- package/dist/run-yTjJ7noq.mjs +0 -1051
- package/dist/run-zo5GSoVC.mjs +0 -1050
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
function getSandboxEnv() {
|
|
2
|
+
return {
|
|
3
|
+
apiUrl: process.env.SANDBOX_API_URL || "",
|
|
4
|
+
apiKey: process.env.SANDBOX_API_KEY || "",
|
|
5
|
+
namespace: process.env.SANDBOX_NAMESPACE || "",
|
|
6
|
+
sandboxId: process.env.SANDBOX_ID || ""
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
function requireSandboxEnv() {
|
|
10
|
+
const env = getSandboxEnv();
|
|
11
|
+
if (!env.apiUrl) {
|
|
12
|
+
throw new Error(
|
|
13
|
+
"SANDBOX_API_URL is not set. Service commands require a sandbox environment.\nThis is normally set by the Svamp provisioner when running in a cloud machine."
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
if (!env.apiKey) {
|
|
17
|
+
throw new Error("SANDBOX_API_KEY is not set.");
|
|
18
|
+
}
|
|
19
|
+
if (!env.namespace) {
|
|
20
|
+
throw new Error("SANDBOX_NAMESPACE is not set.");
|
|
21
|
+
}
|
|
22
|
+
return env;
|
|
23
|
+
}
|
|
24
|
+
function requireSandboxApiEnv() {
|
|
25
|
+
const env = getSandboxEnv();
|
|
26
|
+
if (!env.apiUrl) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
"SANDBOX_API_URL is not set. Set it via environment variable or `svamp service config`."
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
if (!env.apiKey) {
|
|
32
|
+
throw new Error("SANDBOX_API_KEY is not set.");
|
|
33
|
+
}
|
|
34
|
+
return env;
|
|
35
|
+
}
|
|
36
|
+
async function sandboxFetch(env, path, init) {
|
|
37
|
+
const url = `${env.apiUrl.replace(/\/+$/, "")}${path}`;
|
|
38
|
+
const headers = {
|
|
39
|
+
"Authorization": `Bearer ${env.apiKey}`,
|
|
40
|
+
"Content-Type": "application/json",
|
|
41
|
+
...init?.headers || {}
|
|
42
|
+
};
|
|
43
|
+
const res = await fetch(url, { ...init, headers });
|
|
44
|
+
if (!res.ok) {
|
|
45
|
+
const body = await res.text().catch(() => "");
|
|
46
|
+
let detail = body;
|
|
47
|
+
try {
|
|
48
|
+
detail = JSON.parse(body).detail || body;
|
|
49
|
+
} catch {
|
|
50
|
+
}
|
|
51
|
+
throw new Error(`${res.status} ${res.statusText}: ${detail}`);
|
|
52
|
+
}
|
|
53
|
+
return res;
|
|
54
|
+
}
|
|
55
|
+
async function createServiceGroup(name, ports, options) {
|
|
56
|
+
const env = requireSandboxEnv();
|
|
57
|
+
const body = {};
|
|
58
|
+
if (ports.length === 1 && options?.subdomain) {
|
|
59
|
+
body.port = ports[0];
|
|
60
|
+
body.subdomain = options.subdomain;
|
|
61
|
+
} else {
|
|
62
|
+
body.ports = ports.map((p) => ({ port: p }));
|
|
63
|
+
}
|
|
64
|
+
if (options?.healthPath) {
|
|
65
|
+
body.health_path = options.healthPath;
|
|
66
|
+
if (options.healthInterval) {
|
|
67
|
+
body.health_interval = options.healthInterval;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const res = await sandboxFetch(env, `/services/${env.namespace}/${name}`, {
|
|
71
|
+
method: "POST",
|
|
72
|
+
body: JSON.stringify(body)
|
|
73
|
+
});
|
|
74
|
+
return res.json();
|
|
75
|
+
}
|
|
76
|
+
async function listServiceGroups() {
|
|
77
|
+
const env = requireSandboxEnv();
|
|
78
|
+
const res = await sandboxFetch(env, `/services/${env.namespace}`);
|
|
79
|
+
return res.json();
|
|
80
|
+
}
|
|
81
|
+
async function getServiceGroup(name) {
|
|
82
|
+
const env = requireSandboxEnv();
|
|
83
|
+
const res = await sandboxFetch(env, `/services/${env.namespace}/${name}`);
|
|
84
|
+
return res.json();
|
|
85
|
+
}
|
|
86
|
+
async function deleteServiceGroup(name) {
|
|
87
|
+
const env = requireSandboxEnv();
|
|
88
|
+
const res = await sandboxFetch(env, `/services/${env.namespace}/${name}`, {
|
|
89
|
+
method: "DELETE"
|
|
90
|
+
});
|
|
91
|
+
return res.json();
|
|
92
|
+
}
|
|
93
|
+
async function addPort(name, port, subdomain) {
|
|
94
|
+
const env = requireSandboxEnv();
|
|
95
|
+
const res = await sandboxFetch(env, `/services/${env.namespace}/${name}/ports`, {
|
|
96
|
+
method: "POST",
|
|
97
|
+
body: JSON.stringify({ port, subdomain })
|
|
98
|
+
});
|
|
99
|
+
return res.json();
|
|
100
|
+
}
|
|
101
|
+
async function removePort(name, port) {
|
|
102
|
+
const env = requireSandboxEnv();
|
|
103
|
+
const res = await sandboxFetch(env, `/services/${env.namespace}/${name}/ports/${port}`, {
|
|
104
|
+
method: "DELETE"
|
|
105
|
+
});
|
|
106
|
+
return res.json();
|
|
107
|
+
}
|
|
108
|
+
async function renameSubdomain(name, port, subdomain) {
|
|
109
|
+
const env = requireSandboxEnv();
|
|
110
|
+
const res = await sandboxFetch(env, `/services/${env.namespace}/${name}/subdomain`, {
|
|
111
|
+
method: "PUT",
|
|
112
|
+
body: JSON.stringify({ port, subdomain })
|
|
113
|
+
});
|
|
114
|
+
return res.json();
|
|
115
|
+
}
|
|
116
|
+
async function addBackend(name, sandboxId) {
|
|
117
|
+
const env = requireSandboxEnv();
|
|
118
|
+
const sid = sandboxId || env.sandboxId;
|
|
119
|
+
if (!sid) {
|
|
120
|
+
throw new Error(
|
|
121
|
+
"No sandbox ID provided and SANDBOX_ID is not set.\nUse --sandbox-id <id> to specify which sandbox to add."
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
const res = await sandboxFetch(env, `/services/${env.namespace}/${name}/backends`, {
|
|
125
|
+
method: "POST",
|
|
126
|
+
body: JSON.stringify({ sandbox_id: sid })
|
|
127
|
+
});
|
|
128
|
+
return res.json();
|
|
129
|
+
}
|
|
130
|
+
async function removeBackend(name, sandboxId) {
|
|
131
|
+
const env = requireSandboxEnv();
|
|
132
|
+
const sid = sandboxId || env.sandboxId;
|
|
133
|
+
if (!sid) {
|
|
134
|
+
throw new Error(
|
|
135
|
+
"No sandbox ID provided and SANDBOX_ID is not set.\nUse --sandbox-id <id> to specify which sandbox to remove."
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
const res = await sandboxFetch(env, `/services/${env.namespace}/${name}/backends/${sid}`, {
|
|
139
|
+
method: "DELETE"
|
|
140
|
+
});
|
|
141
|
+
return res.json();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function getFlag(args, flag) {
|
|
145
|
+
const idx = args.indexOf(flag);
|
|
146
|
+
return idx !== -1 && idx + 1 < args.length ? args[idx + 1] : void 0;
|
|
147
|
+
}
|
|
148
|
+
function getAllFlags(args, flag) {
|
|
149
|
+
const values = [];
|
|
150
|
+
for (let i = 0; i < args.length; i++) {
|
|
151
|
+
if (args[i] === flag && i + 1 < args.length) {
|
|
152
|
+
values.push(args[i + 1]);
|
|
153
|
+
i++;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return values;
|
|
157
|
+
}
|
|
158
|
+
function hasFlag(args, ...flags) {
|
|
159
|
+
return flags.some((f) => args.includes(f));
|
|
160
|
+
}
|
|
161
|
+
function positionalArgs(args) {
|
|
162
|
+
const result = [];
|
|
163
|
+
for (let i = 0; i < args.length; i++) {
|
|
164
|
+
if (args[i].startsWith("--")) {
|
|
165
|
+
if (i + 1 < args.length && !args[i + 1].startsWith("--")) {
|
|
166
|
+
i++;
|
|
167
|
+
}
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
result.push(args[i]);
|
|
171
|
+
}
|
|
172
|
+
return result;
|
|
173
|
+
}
|
|
174
|
+
function parsePorts(args) {
|
|
175
|
+
const portStrs = getAllFlags(args, "--port");
|
|
176
|
+
if (portStrs.length === 0) return [];
|
|
177
|
+
const ports = [];
|
|
178
|
+
for (const s of portStrs) {
|
|
179
|
+
const p = parseInt(s, 10);
|
|
180
|
+
if (isNaN(p) || p < 1 || p > 65535) {
|
|
181
|
+
console.error(`Error: invalid port '${s}' \u2014 must be 1-65535`);
|
|
182
|
+
process.exit(1);
|
|
183
|
+
}
|
|
184
|
+
ports.push(p);
|
|
185
|
+
}
|
|
186
|
+
return ports;
|
|
187
|
+
}
|
|
188
|
+
function printServiceGroupInfo(info) {
|
|
189
|
+
console.log(`Service group: ${info.name}`);
|
|
190
|
+
console.log(` Namespace: ${info.namespace}`);
|
|
191
|
+
console.log(` K8s svc: ${info.k8s_service}`);
|
|
192
|
+
console.log(` Created: ${info.created_at}`);
|
|
193
|
+
if (info.health_path) {
|
|
194
|
+
console.log(` Health: ${info.health_path} (every ${info.health_interval}s)`);
|
|
195
|
+
}
|
|
196
|
+
console.log(` Ports (${info.ports.length}):`);
|
|
197
|
+
for (const p of info.ports) {
|
|
198
|
+
console.log(` ${p.port} \u2192 ${p.url}`);
|
|
199
|
+
}
|
|
200
|
+
console.log(` Backends (${info.backends.length}):`);
|
|
201
|
+
for (const b of info.backends) {
|
|
202
|
+
const healthTag = b.healthy === false ? " [unhealthy]" : b.healthy === true ? "" : "";
|
|
203
|
+
const failInfo = b.consecutive_failures ? ` (${b.consecutive_failures} failures)` : "";
|
|
204
|
+
console.log(` - ${b.sandbox_id} (${b.pod_ip})${healthTag}${failInfo}`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function printServiceGroupListItem(g) {
|
|
208
|
+
console.log(` ${g.name}`);
|
|
209
|
+
if (g.ports.length > 1) {
|
|
210
|
+
for (const p of g.ports) {
|
|
211
|
+
console.log(` ${p.port} \u2192 ${p.url}`);
|
|
212
|
+
}
|
|
213
|
+
} else {
|
|
214
|
+
console.log(` URL: ${g.url}`);
|
|
215
|
+
console.log(` Port: ${g.port}`);
|
|
216
|
+
}
|
|
217
|
+
console.log(` Backends: ${g.backend_count}`);
|
|
218
|
+
}
|
|
219
|
+
function validateSubdomain(sub) {
|
|
220
|
+
if (sub.split("-").length - 1 < 2) {
|
|
221
|
+
console.error(`Error: custom subdomain must contain at least 2 hyphens (e.g., my-cool-service), got '${sub}'`);
|
|
222
|
+
process.exit(1);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
async function serviceCreate(args) {
|
|
226
|
+
const positional = positionalArgs(args);
|
|
227
|
+
const name = positional[0];
|
|
228
|
+
const ports = parsePorts(args);
|
|
229
|
+
const subdomain = getFlag(args, "--subdomain");
|
|
230
|
+
const healthPath = getFlag(args, "--health-path");
|
|
231
|
+
const healthIntervalStr = getFlag(args, "--health-interval");
|
|
232
|
+
if (!name || ports.length === 0) {
|
|
233
|
+
console.error("Usage: svamp service create <name> --port <port> [--port <port2>] [--health-path <path>]");
|
|
234
|
+
process.exit(1);
|
|
235
|
+
}
|
|
236
|
+
if (subdomain) validateSubdomain(subdomain);
|
|
237
|
+
const healthInterval = healthIntervalStr ? parseInt(healthIntervalStr, 10) : void 0;
|
|
238
|
+
try {
|
|
239
|
+
const result = await createServiceGroup(name, ports, {
|
|
240
|
+
subdomain,
|
|
241
|
+
healthPath,
|
|
242
|
+
healthInterval
|
|
243
|
+
});
|
|
244
|
+
console.log(`Service group created: ${result.name}`);
|
|
245
|
+
for (const p of result.ports) {
|
|
246
|
+
console.log(` ${p.port} \u2192 ${p.url}`);
|
|
247
|
+
}
|
|
248
|
+
console.log(` K8s svc: ${result.k8s_service}`);
|
|
249
|
+
console.log(` Backends: ${result.backends.length}`);
|
|
250
|
+
} catch (err) {
|
|
251
|
+
console.error(`Error creating service group: ${err.message}`);
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
async function serviceList(args) {
|
|
256
|
+
const jsonOutput = hasFlag(args, "--json");
|
|
257
|
+
try {
|
|
258
|
+
const groups = await listServiceGroups();
|
|
259
|
+
if (jsonOutput) {
|
|
260
|
+
console.log(JSON.stringify(groups, null, 2));
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
if (groups.length === 0) {
|
|
264
|
+
console.log("No service groups found.");
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
console.log(`Service groups (${groups.length}):
|
|
268
|
+
`);
|
|
269
|
+
for (const g of groups) {
|
|
270
|
+
printServiceGroupListItem(g);
|
|
271
|
+
console.log();
|
|
272
|
+
}
|
|
273
|
+
} catch (err) {
|
|
274
|
+
console.error(`Error listing service groups: ${err.message}`);
|
|
275
|
+
process.exit(1);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
async function serviceInfo(args) {
|
|
279
|
+
const positional = positionalArgs(args);
|
|
280
|
+
const name = positional[0];
|
|
281
|
+
const jsonOutput = hasFlag(args, "--json");
|
|
282
|
+
if (!name) {
|
|
283
|
+
console.error("Usage: svamp service info <name> [--json]");
|
|
284
|
+
process.exit(1);
|
|
285
|
+
}
|
|
286
|
+
try {
|
|
287
|
+
const info = await getServiceGroup(name);
|
|
288
|
+
if (jsonOutput) {
|
|
289
|
+
console.log(JSON.stringify(info, null, 2));
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
printServiceGroupInfo(info);
|
|
293
|
+
} catch (err) {
|
|
294
|
+
console.error(`Error getting service group: ${err.message}`);
|
|
295
|
+
process.exit(1);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
async function serviceDelete(args) {
|
|
299
|
+
const positional = positionalArgs(args);
|
|
300
|
+
const name = positional[0];
|
|
301
|
+
if (!name) {
|
|
302
|
+
console.error("Usage: svamp service delete <name>");
|
|
303
|
+
process.exit(1);
|
|
304
|
+
}
|
|
305
|
+
try {
|
|
306
|
+
await deleteServiceGroup(name);
|
|
307
|
+
console.log(`Service group '${name}' deleted.`);
|
|
308
|
+
} catch (err) {
|
|
309
|
+
console.error(`Error deleting service group: ${err.message}`);
|
|
310
|
+
process.exit(1);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
async function serviceAddBackend(args) {
|
|
314
|
+
const positional = positionalArgs(args);
|
|
315
|
+
const name = positional[0];
|
|
316
|
+
const sandboxId = getFlag(args, "--sandbox-id");
|
|
317
|
+
if (!name) {
|
|
318
|
+
console.error("Usage: svamp service add-backend <name> [--sandbox-id <id>]");
|
|
319
|
+
process.exit(1);
|
|
320
|
+
}
|
|
321
|
+
try {
|
|
322
|
+
const result = await addBackend(name, sandboxId);
|
|
323
|
+
console.log(`Backend added to '${name}': ${result.sandbox_id} (${result.pod_ip})`);
|
|
324
|
+
console.log(` Total backends: ${result.backend_count}`);
|
|
325
|
+
} catch (err) {
|
|
326
|
+
console.error(`Error adding backend: ${err.message}`);
|
|
327
|
+
process.exit(1);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
async function serviceRemoveBackend(args) {
|
|
331
|
+
const positional = positionalArgs(args);
|
|
332
|
+
const name = positional[0];
|
|
333
|
+
const sandboxId = getFlag(args, "--sandbox-id");
|
|
334
|
+
if (!name) {
|
|
335
|
+
console.error("Usage: svamp service remove-backend <name> [--sandbox-id <id>]");
|
|
336
|
+
process.exit(1);
|
|
337
|
+
}
|
|
338
|
+
try {
|
|
339
|
+
const result = await removeBackend(name, sandboxId);
|
|
340
|
+
console.log(`Backend removed from '${name}': ${result.sandbox_id}`);
|
|
341
|
+
console.log(` Remaining backends: ${result.backend_count}`);
|
|
342
|
+
} catch (err) {
|
|
343
|
+
console.error(`Error removing backend: ${err.message}`);
|
|
344
|
+
process.exit(1);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
async function serviceAddPort(args) {
|
|
348
|
+
const positional = positionalArgs(args);
|
|
349
|
+
const name = positional[0];
|
|
350
|
+
const ports = parsePorts(args);
|
|
351
|
+
const subdomain = getFlag(args, "--subdomain");
|
|
352
|
+
if (!name || ports.length !== 1) {
|
|
353
|
+
console.error("Usage: svamp service add-port <name> --port <port> [--subdomain <sub>]");
|
|
354
|
+
process.exit(1);
|
|
355
|
+
}
|
|
356
|
+
if (subdomain) validateSubdomain(subdomain);
|
|
357
|
+
try {
|
|
358
|
+
const result = await addPort(name, ports[0], subdomain);
|
|
359
|
+
console.log(`Port added to '${name}': ${result.port} \u2192 ${result.url}`);
|
|
360
|
+
console.log(` Total ports: ${result.total_ports}`);
|
|
361
|
+
} catch (err) {
|
|
362
|
+
console.error(`Error adding port: ${err.message}`);
|
|
363
|
+
process.exit(1);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
async function serviceRemovePort(args) {
|
|
367
|
+
const positional = positionalArgs(args);
|
|
368
|
+
const name = positional[0];
|
|
369
|
+
const ports = parsePorts(args);
|
|
370
|
+
if (!name || ports.length !== 1) {
|
|
371
|
+
console.error("Usage: svamp service remove-port <name> --port <port>");
|
|
372
|
+
process.exit(1);
|
|
373
|
+
}
|
|
374
|
+
try {
|
|
375
|
+
const result = await removePort(name, ports[0]);
|
|
376
|
+
console.log(`Port removed from '${name}': ${result.port}`);
|
|
377
|
+
console.log(` Remaining ports: ${result.total_ports}`);
|
|
378
|
+
} catch (err) {
|
|
379
|
+
console.error(`Error removing port: ${err.message}`);
|
|
380
|
+
process.exit(1);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
async function serviceRename(args) {
|
|
384
|
+
const positional = positionalArgs(args);
|
|
385
|
+
const name = positional[0];
|
|
386
|
+
const ports = parsePorts(args);
|
|
387
|
+
const subdomain = getFlag(args, "--subdomain");
|
|
388
|
+
if (!name || ports.length !== 1 || !subdomain) {
|
|
389
|
+
console.error("Usage: svamp service rename <name> --port <port> --subdomain <new-subdomain>");
|
|
390
|
+
console.error(" The subdomain must contain at least 2 hyphens (e.g., my-cool-service)");
|
|
391
|
+
process.exit(1);
|
|
392
|
+
}
|
|
393
|
+
if (subdomain.split("-").length - 1 < 2) {
|
|
394
|
+
console.error(`Error: subdomain must contain at least 2 hyphens (e.g., my-cool-service), got '${subdomain}'`);
|
|
395
|
+
process.exit(1);
|
|
396
|
+
}
|
|
397
|
+
try {
|
|
398
|
+
const result = await renameSubdomain(name, ports[0], subdomain);
|
|
399
|
+
if (result.status === "unchanged") {
|
|
400
|
+
console.log(`Subdomain already set to '${result.subdomain}' \u2014 no change.`);
|
|
401
|
+
} else {
|
|
402
|
+
console.log(`Subdomain renamed: ${result.old_subdomain} \u2192 ${result.subdomain}`);
|
|
403
|
+
console.log(` New URL: ${result.url}`);
|
|
404
|
+
}
|
|
405
|
+
} catch (err) {
|
|
406
|
+
console.error(`Error renaming subdomain: ${err.message}`);
|
|
407
|
+
process.exit(1);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
async function serviceExpose(args) {
|
|
411
|
+
const positional = positionalArgs(args);
|
|
412
|
+
const name = positional[0];
|
|
413
|
+
const ports = parsePorts(args);
|
|
414
|
+
const subdomain = getFlag(args, "--subdomain");
|
|
415
|
+
const healthPath = getFlag(args, "--health-path");
|
|
416
|
+
const healthIntervalStr = getFlag(args, "--health-interval");
|
|
417
|
+
if (!name || ports.length === 0) {
|
|
418
|
+
console.error("Usage: svamp service expose <name> --port <port> [--port <port2>] [--health-path <path>]");
|
|
419
|
+
process.exit(1);
|
|
420
|
+
}
|
|
421
|
+
if (subdomain) validateSubdomain(subdomain);
|
|
422
|
+
const healthInterval = healthIntervalStr ? parseInt(healthIntervalStr, 10) : void 0;
|
|
423
|
+
const env = getSandboxEnv();
|
|
424
|
+
try {
|
|
425
|
+
const group = await createServiceGroup(name, ports, {
|
|
426
|
+
subdomain,
|
|
427
|
+
healthPath,
|
|
428
|
+
healthInterval
|
|
429
|
+
});
|
|
430
|
+
if (env.sandboxId) {
|
|
431
|
+
const result = await addBackend(name);
|
|
432
|
+
console.log(`Backend added: ${result.sandbox_id} (${result.pod_ip})`);
|
|
433
|
+
console.log(`
|
|
434
|
+
Service is live:`);
|
|
435
|
+
for (const p of group.ports) {
|
|
436
|
+
console.log(` ${p.port} \u2192 ${p.url}`);
|
|
437
|
+
}
|
|
438
|
+
} else {
|
|
439
|
+
console.log(`No SANDBOX_ID detected \u2014 starting reverse tunnel.`);
|
|
440
|
+
const { runTunnel } = await import('./tunnel-C2_V6y3d.mjs');
|
|
441
|
+
await runTunnel(name, ports);
|
|
442
|
+
}
|
|
443
|
+
} catch (err) {
|
|
444
|
+
console.error(`Error exposing service: ${err.message}`);
|
|
445
|
+
process.exit(1);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
async function serviceTunnel(args) {
|
|
449
|
+
const positional = positionalArgs(args);
|
|
450
|
+
const name = positional[0];
|
|
451
|
+
const ports = parsePorts(args);
|
|
452
|
+
if (!name || ports.length === 0) {
|
|
453
|
+
console.error("Usage: svamp service tunnel <name> --port <port> [--port <port2>]");
|
|
454
|
+
process.exit(1);
|
|
455
|
+
}
|
|
456
|
+
const { runTunnel } = await import('./tunnel-C2_V6y3d.mjs');
|
|
457
|
+
await runTunnel(name, ports);
|
|
458
|
+
}
|
|
459
|
+
async function handleServiceCommand() {
|
|
460
|
+
const args = process.argv.slice(2);
|
|
461
|
+
const serviceArgs = args.slice(1);
|
|
462
|
+
const sub = serviceArgs[0];
|
|
463
|
+
if (!sub || sub === "--help" || sub === "-h") {
|
|
464
|
+
printServiceHelp();
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
const commandArgs = serviceArgs.slice(1);
|
|
468
|
+
if (sub === "create") {
|
|
469
|
+
await serviceCreate(commandArgs);
|
|
470
|
+
} else if (sub === "list" || sub === "ls") {
|
|
471
|
+
await serviceList(commandArgs);
|
|
472
|
+
} else if (sub === "info" || sub === "show") {
|
|
473
|
+
await serviceInfo(commandArgs);
|
|
474
|
+
} else if (sub === "delete" || sub === "rm") {
|
|
475
|
+
await serviceDelete(commandArgs);
|
|
476
|
+
} else if (sub === "add-backend" || sub === "add") {
|
|
477
|
+
await serviceAddBackend(commandArgs);
|
|
478
|
+
} else if (sub === "remove-backend" || sub === "remove") {
|
|
479
|
+
await serviceRemoveBackend(commandArgs);
|
|
480
|
+
} else if (sub === "add-port") {
|
|
481
|
+
await serviceAddPort(commandArgs);
|
|
482
|
+
} else if (sub === "remove-port") {
|
|
483
|
+
await serviceRemovePort(commandArgs);
|
|
484
|
+
} else if (sub === "rename") {
|
|
485
|
+
await serviceRename(commandArgs);
|
|
486
|
+
} else if (sub === "expose") {
|
|
487
|
+
await serviceExpose(commandArgs);
|
|
488
|
+
} else if (sub === "tunnel") {
|
|
489
|
+
await serviceTunnel(commandArgs);
|
|
490
|
+
} else {
|
|
491
|
+
console.error(`Unknown service command: ${sub}`);
|
|
492
|
+
printServiceHelp();
|
|
493
|
+
process.exit(1);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
function printServiceHelp() {
|
|
497
|
+
console.log(`
|
|
498
|
+
svamp service \u2014 Manage load-balanced service groups
|
|
499
|
+
|
|
500
|
+
Usage:
|
|
501
|
+
svamp service create <name> --port <port> [--port <port2>] [options] Create a service group
|
|
502
|
+
svamp service list [--json] List service groups
|
|
503
|
+
svamp service info <name> [--json] Show service group details
|
|
504
|
+
svamp service delete <name> Delete a service group
|
|
505
|
+
svamp service add-backend <name> [--sandbox-id <id>] Add a pod as backend
|
|
506
|
+
svamp service remove-backend <name> [--sandbox-id <id>] Remove a backend
|
|
507
|
+
svamp service add-port <name> --port <port> [--subdomain <sub>] Add port to existing group
|
|
508
|
+
svamp service remove-port <name> --port <port> Remove port from group
|
|
509
|
+
svamp service rename <name> --port <port> --subdomain <sub> Rename subdomain of a port
|
|
510
|
+
svamp service expose <name> --port <port> [--port <port2>] [options] Create + join (auto-detects tunnel)
|
|
511
|
+
svamp service tunnel <name> --port <port> [--port <port2>] Tunnel local ports to service group
|
|
512
|
+
|
|
513
|
+
Create/Expose options:
|
|
514
|
+
--health-path <path> Health check endpoint (e.g., /health)
|
|
515
|
+
--health-interval <sec> Health check interval in seconds (default: 30)
|
|
516
|
+
--subdomain <sub> Custom subdomain (must contain at least 2 hyphens)
|
|
517
|
+
|
|
518
|
+
Service groups expose HTTP services via stable URLs with K8s-native load
|
|
519
|
+
balancing. Multiple pods can serve the same service \u2014 K8s handles traffic
|
|
520
|
+
distribution automatically.
|
|
521
|
+
|
|
522
|
+
Multi-port: Use --port multiple times to expose several ports under one
|
|
523
|
+
service group. Each port gets its own unique subdomain and URL.
|
|
524
|
+
|
|
525
|
+
Auto-detect: 'expose' automatically detects the environment:
|
|
526
|
+
- Cloud sandbox (SANDBOX_ID set): adds pod as K8s backend
|
|
527
|
+
- Local machine (no SANDBOX_ID): starts reverse tunnel
|
|
528
|
+
|
|
529
|
+
Environment variables (set by provisioner):
|
|
530
|
+
SANDBOX_API_URL Agent-sandbox API base URL
|
|
531
|
+
SANDBOX_API_KEY API authentication token
|
|
532
|
+
SANDBOX_NAMESPACE User's sandbox namespace
|
|
533
|
+
SANDBOX_ID This pod's sandbox ID
|
|
534
|
+
|
|
535
|
+
Examples:
|
|
536
|
+
svamp service expose my-api --port 8000
|
|
537
|
+
svamp service expose my-api --port 8000 --port 3000 --health-path /health
|
|
538
|
+
svamp service add-port my-api --port 5000
|
|
539
|
+
svamp service remove-port my-api --port 5000
|
|
540
|
+
svamp service list
|
|
541
|
+
svamp service info my-api
|
|
542
|
+
svamp service delete my-api
|
|
543
|
+
`.trim());
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
var commands = /*#__PURE__*/Object.freeze({
|
|
547
|
+
__proto__: null,
|
|
548
|
+
handleServiceCommand: handleServiceCommand,
|
|
549
|
+
serviceAddBackend: serviceAddBackend,
|
|
550
|
+
serviceAddPort: serviceAddPort,
|
|
551
|
+
serviceCreate: serviceCreate,
|
|
552
|
+
serviceDelete: serviceDelete,
|
|
553
|
+
serviceExpose: serviceExpose,
|
|
554
|
+
serviceInfo: serviceInfo,
|
|
555
|
+
serviceList: serviceList,
|
|
556
|
+
serviceRemoveBackend: serviceRemoveBackend,
|
|
557
|
+
serviceRemovePort: serviceRemovePort,
|
|
558
|
+
serviceRename: serviceRename,
|
|
559
|
+
serviceTunnel: serviceTunnel
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
export { commands as c, requireSandboxApiEnv as r };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { c as connectToHypha, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, a as registerSessionService, s as startDaemon, b as stopDaemon } from './run-
|
|
1
|
+
export { c as connectToHypha, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, a as registerSessionService, s as startDaemon, b as stopDaemon } from './run-BnnUavlu.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -2,7 +2,7 @@ import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(im
|
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import { join, resolve } from 'node:path';
|
|
4
4
|
import { mkdirSync, writeFileSync, existsSync, unlinkSync, readFileSync, watch } from 'node:fs';
|
|
5
|
-
import { c as connectToHypha, a as registerSessionService } from './run-
|
|
5
|
+
import { c as connectToHypha, a as registerSessionService } from './run-eYBOEaWw.mjs';
|
|
6
6
|
import { createServer } from 'node:http';
|
|
7
7
|
import { spawn } from 'node:child_process';
|
|
8
8
|
import { createInterface } from 'node:readline';
|