svamp-cli 0.1.85 → 0.1.87
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/package.json +1 -1
- package/dist/agentCommands-BrImgZsc.mjs +0 -263
- package/dist/api-BRbsyqJ4.mjs +0 -147
- package/dist/cli.mjs +0 -1535
- package/dist/commands-2Hgmysua.mjs +0 -593
- package/dist/commands-BYbuedOK.mjs +0 -469
- package/dist/commands-DJo7kCIf.mjs +0 -1899
- package/dist/commands-DJoYOM_1.mjs +0 -531
- package/dist/index.mjs +0 -20
- package/dist/package-BXisDMWj.mjs +0 -62
- package/dist/run-D0PoM5_v.mjs +0 -8260
- package/dist/run-Ds7dVmnU.mjs +0 -1103
- package/dist/staticServer-CWcmMF5V.mjs +0 -477
- package/dist/tunnel-BDKdemh0.mjs +0 -383
|
@@ -1,469 +0,0 @@
|
|
|
1
|
-
import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { createServiceGroup, listServiceGroups, getServiceGroup, deleteServiceGroup, addBackend, removeBackend, addPort, removePort, renameSubdomain, getSandboxEnv } from './api-BRbsyqJ4.mjs';
|
|
2
|
-
|
|
3
|
-
function getFlag(args, flag) {
|
|
4
|
-
const idx = args.indexOf(flag);
|
|
5
|
-
return idx !== -1 && idx + 1 < args.length ? args[idx + 1] : void 0;
|
|
6
|
-
}
|
|
7
|
-
function getAllFlags(args, flag) {
|
|
8
|
-
const values = [];
|
|
9
|
-
for (let i = 0; i < args.length; i++) {
|
|
10
|
-
if (args[i] === flag && i + 1 < args.length) {
|
|
11
|
-
values.push(args[i + 1]);
|
|
12
|
-
i++;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
return values;
|
|
16
|
-
}
|
|
17
|
-
function hasFlag(args, ...flags) {
|
|
18
|
-
return flags.some((f) => args.includes(f));
|
|
19
|
-
}
|
|
20
|
-
function positionalArgs(args) {
|
|
21
|
-
const result = [];
|
|
22
|
-
for (let i = 0; i < args.length; i++) {
|
|
23
|
-
if (args[i].startsWith("--")) {
|
|
24
|
-
if (i + 1 < args.length && !args[i + 1].startsWith("--")) {
|
|
25
|
-
i++;
|
|
26
|
-
}
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
result.push(args[i]);
|
|
30
|
-
}
|
|
31
|
-
return result;
|
|
32
|
-
}
|
|
33
|
-
function parsePorts(args) {
|
|
34
|
-
const portStrs = getAllFlags(args, "--port");
|
|
35
|
-
if (portStrs.length === 0) return [];
|
|
36
|
-
const ports = [];
|
|
37
|
-
for (const s of portStrs) {
|
|
38
|
-
const p = parseInt(s, 10);
|
|
39
|
-
if (isNaN(p) || p < 1 || p > 65535) {
|
|
40
|
-
console.error(`Error: invalid port '${s}' \u2014 must be 1-65535`);
|
|
41
|
-
process.exit(1);
|
|
42
|
-
}
|
|
43
|
-
ports.push(p);
|
|
44
|
-
}
|
|
45
|
-
return ports;
|
|
46
|
-
}
|
|
47
|
-
function printServiceGroupInfo(info) {
|
|
48
|
-
console.log(`Service group: ${info.name}`);
|
|
49
|
-
console.log(` Namespace: ${info.namespace}`);
|
|
50
|
-
console.log(` K8s svc: ${info.k8s_service}`);
|
|
51
|
-
console.log(` Created: ${info.created_at}`);
|
|
52
|
-
if (info.health_path) {
|
|
53
|
-
console.log(` Health: ${info.health_path} (every ${info.health_interval}s)`);
|
|
54
|
-
}
|
|
55
|
-
console.log(` Ports (${info.ports.length}):`);
|
|
56
|
-
for (const p of info.ports) {
|
|
57
|
-
console.log(` ${p.port} \u2192 ${p.url}`);
|
|
58
|
-
}
|
|
59
|
-
console.log(` Backends (${info.backends.length}):`);
|
|
60
|
-
for (const b of info.backends) {
|
|
61
|
-
const healthTag = b.healthy === false ? " [unhealthy]" : b.healthy === true ? "" : "";
|
|
62
|
-
const failInfo = b.consecutive_failures ? ` (${b.consecutive_failures} failures)` : "";
|
|
63
|
-
console.log(` - ${b.sandbox_id} (${b.pod_ip})${healthTag}${failInfo}`);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
function printServiceGroupListItem(g) {
|
|
67
|
-
console.log(` ${g.name}`);
|
|
68
|
-
if (g.ports.length > 1) {
|
|
69
|
-
for (const p of g.ports) {
|
|
70
|
-
console.log(` ${p.port} \u2192 ${p.url}`);
|
|
71
|
-
}
|
|
72
|
-
} else {
|
|
73
|
-
console.log(` URL: ${g.url}`);
|
|
74
|
-
console.log(` Port: ${g.port}`);
|
|
75
|
-
}
|
|
76
|
-
console.log(` Backends: ${g.backend_count}`);
|
|
77
|
-
}
|
|
78
|
-
function validateSubdomain(sub) {
|
|
79
|
-
if (sub.split("-").length - 1 < 2) {
|
|
80
|
-
console.error(`Error: custom subdomain must contain at least 2 hyphens (e.g., my-cool-service), got '${sub}'`);
|
|
81
|
-
process.exit(1);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
async function serviceCreate(args) {
|
|
85
|
-
const positional = positionalArgs(args);
|
|
86
|
-
const name = positional[0];
|
|
87
|
-
const ports = parsePorts(args);
|
|
88
|
-
const subdomain = getFlag(args, "--subdomain");
|
|
89
|
-
const healthPath = getFlag(args, "--health-path");
|
|
90
|
-
const healthIntervalStr = getFlag(args, "--health-interval");
|
|
91
|
-
if (!name || ports.length === 0) {
|
|
92
|
-
console.error("Usage: svamp service create <name> --port <port> [--port <port2>] [--health-path <path>]");
|
|
93
|
-
process.exit(1);
|
|
94
|
-
}
|
|
95
|
-
if (subdomain) validateSubdomain(subdomain);
|
|
96
|
-
const healthInterval = healthIntervalStr ? parseInt(healthIntervalStr, 10) : void 0;
|
|
97
|
-
try {
|
|
98
|
-
const result = await createServiceGroup(name, ports, {
|
|
99
|
-
subdomain,
|
|
100
|
-
healthPath,
|
|
101
|
-
healthInterval
|
|
102
|
-
});
|
|
103
|
-
console.log(`Service group created: ${result.name}`);
|
|
104
|
-
for (const p of result.ports) {
|
|
105
|
-
console.log(` ${p.port} \u2192 ${p.url}`);
|
|
106
|
-
}
|
|
107
|
-
console.log(` K8s svc: ${result.k8s_service}`);
|
|
108
|
-
console.log(` Backends: ${result.backends.length}`);
|
|
109
|
-
} catch (err) {
|
|
110
|
-
console.error(`Error creating service group: ${err.message}`);
|
|
111
|
-
process.exit(1);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
async function serviceList(args) {
|
|
115
|
-
const jsonOutput = hasFlag(args, "--json");
|
|
116
|
-
try {
|
|
117
|
-
const groups = await listServiceGroups();
|
|
118
|
-
if (jsonOutput) {
|
|
119
|
-
console.log(JSON.stringify(groups, null, 2));
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
if (groups.length === 0) {
|
|
123
|
-
console.log("No service groups found.");
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
console.log(`Service groups (${groups.length}):
|
|
127
|
-
`);
|
|
128
|
-
for (const g of groups) {
|
|
129
|
-
printServiceGroupListItem(g);
|
|
130
|
-
console.log();
|
|
131
|
-
}
|
|
132
|
-
} catch (err) {
|
|
133
|
-
console.error(`Error listing service groups: ${err.message}`);
|
|
134
|
-
process.exit(1);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
async function serviceInfo(args) {
|
|
138
|
-
const positional = positionalArgs(args);
|
|
139
|
-
const name = positional[0];
|
|
140
|
-
const jsonOutput = hasFlag(args, "--json");
|
|
141
|
-
if (!name) {
|
|
142
|
-
console.error("Usage: svamp service info <name> [--json]");
|
|
143
|
-
process.exit(1);
|
|
144
|
-
}
|
|
145
|
-
try {
|
|
146
|
-
const info = await getServiceGroup(name);
|
|
147
|
-
if (jsonOutput) {
|
|
148
|
-
console.log(JSON.stringify(info, null, 2));
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
printServiceGroupInfo(info);
|
|
152
|
-
} catch (err) {
|
|
153
|
-
console.error(`Error getting service group: ${err.message}`);
|
|
154
|
-
process.exit(1);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
async function serviceDelete(args) {
|
|
158
|
-
const positional = positionalArgs(args);
|
|
159
|
-
const name = positional[0];
|
|
160
|
-
if (!name) {
|
|
161
|
-
console.error("Usage: svamp service delete <name>");
|
|
162
|
-
process.exit(1);
|
|
163
|
-
}
|
|
164
|
-
try {
|
|
165
|
-
await deleteServiceGroup(name);
|
|
166
|
-
console.log(`Service group '${name}' deleted.`);
|
|
167
|
-
} catch (err) {
|
|
168
|
-
console.error(`Error deleting service group: ${err.message}`);
|
|
169
|
-
process.exit(1);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
async function serviceAddBackend(args) {
|
|
173
|
-
const positional = positionalArgs(args);
|
|
174
|
-
const name = positional[0];
|
|
175
|
-
const sandboxId = getFlag(args, "--sandbox-id");
|
|
176
|
-
if (!name) {
|
|
177
|
-
console.error("Usage: svamp service add-backend <name> [--sandbox-id <id>]");
|
|
178
|
-
process.exit(1);
|
|
179
|
-
}
|
|
180
|
-
try {
|
|
181
|
-
const result = await addBackend(name, sandboxId);
|
|
182
|
-
console.log(`Backend added to '${name}': ${result.sandbox_id} (${result.pod_ip})`);
|
|
183
|
-
console.log(` Total backends: ${result.backend_count}`);
|
|
184
|
-
} catch (err) {
|
|
185
|
-
console.error(`Error adding backend: ${err.message}`);
|
|
186
|
-
process.exit(1);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
async function serviceRemoveBackend(args) {
|
|
190
|
-
const positional = positionalArgs(args);
|
|
191
|
-
const name = positional[0];
|
|
192
|
-
const sandboxId = getFlag(args, "--sandbox-id");
|
|
193
|
-
if (!name) {
|
|
194
|
-
console.error("Usage: svamp service remove-backend <name> [--sandbox-id <id>]");
|
|
195
|
-
process.exit(1);
|
|
196
|
-
}
|
|
197
|
-
try {
|
|
198
|
-
const result = await removeBackend(name, sandboxId);
|
|
199
|
-
console.log(`Backend removed from '${name}': ${result.sandbox_id}`);
|
|
200
|
-
console.log(` Remaining backends: ${result.backend_count}`);
|
|
201
|
-
} catch (err) {
|
|
202
|
-
console.error(`Error removing backend: ${err.message}`);
|
|
203
|
-
process.exit(1);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
async function serviceAddPort(args) {
|
|
207
|
-
const positional = positionalArgs(args);
|
|
208
|
-
const name = positional[0];
|
|
209
|
-
const ports = parsePorts(args);
|
|
210
|
-
const subdomain = getFlag(args, "--subdomain");
|
|
211
|
-
if (!name || ports.length !== 1) {
|
|
212
|
-
console.error("Usage: svamp service add-port <name> --port <port> [--subdomain <sub>]");
|
|
213
|
-
process.exit(1);
|
|
214
|
-
}
|
|
215
|
-
if (subdomain) validateSubdomain(subdomain);
|
|
216
|
-
try {
|
|
217
|
-
const result = await addPort(name, ports[0], subdomain);
|
|
218
|
-
console.log(`Port added to '${name}': ${result.port} \u2192 ${result.url}`);
|
|
219
|
-
console.log(` Total ports: ${result.total_ports}`);
|
|
220
|
-
} catch (err) {
|
|
221
|
-
console.error(`Error adding port: ${err.message}`);
|
|
222
|
-
process.exit(1);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
async function serviceRemovePort(args) {
|
|
226
|
-
const positional = positionalArgs(args);
|
|
227
|
-
const name = positional[0];
|
|
228
|
-
const ports = parsePorts(args);
|
|
229
|
-
if (!name || ports.length !== 1) {
|
|
230
|
-
console.error("Usage: svamp service remove-port <name> --port <port>");
|
|
231
|
-
process.exit(1);
|
|
232
|
-
}
|
|
233
|
-
try {
|
|
234
|
-
const result = await removePort(name, ports[0]);
|
|
235
|
-
console.log(`Port removed from '${name}': ${result.port}`);
|
|
236
|
-
console.log(` Remaining ports: ${result.total_ports}`);
|
|
237
|
-
} catch (err) {
|
|
238
|
-
console.error(`Error removing port: ${err.message}`);
|
|
239
|
-
process.exit(1);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
async function serviceRename(args) {
|
|
243
|
-
const positional = positionalArgs(args);
|
|
244
|
-
const name = positional[0];
|
|
245
|
-
const ports = parsePorts(args);
|
|
246
|
-
const subdomain = getFlag(args, "--subdomain");
|
|
247
|
-
if (!name || ports.length !== 1 || !subdomain) {
|
|
248
|
-
console.error("Usage: svamp service rename <name> --port <port> --subdomain <new-subdomain>");
|
|
249
|
-
console.error(" The subdomain must contain at least 2 hyphens (e.g., my-cool-service)");
|
|
250
|
-
process.exit(1);
|
|
251
|
-
}
|
|
252
|
-
if (subdomain.split("-").length - 1 < 2) {
|
|
253
|
-
console.error(`Error: subdomain must contain at least 2 hyphens (e.g., my-cool-service), got '${subdomain}'`);
|
|
254
|
-
process.exit(1);
|
|
255
|
-
}
|
|
256
|
-
try {
|
|
257
|
-
const result = await renameSubdomain(name, ports[0], subdomain);
|
|
258
|
-
if (result.status === "unchanged") {
|
|
259
|
-
console.log(`Subdomain already set to '${result.subdomain}' \u2014 no change.`);
|
|
260
|
-
} else {
|
|
261
|
-
console.log(`Subdomain renamed: ${result.old_subdomain} \u2192 ${result.subdomain}`);
|
|
262
|
-
console.log(` New URL: ${result.url}`);
|
|
263
|
-
}
|
|
264
|
-
} catch (err) {
|
|
265
|
-
console.error(`Error renaming subdomain: ${err.message}`);
|
|
266
|
-
process.exit(1);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
async function serviceExpose(args) {
|
|
270
|
-
const positional = positionalArgs(args);
|
|
271
|
-
const name = positional[0];
|
|
272
|
-
const ports = parsePorts(args);
|
|
273
|
-
const subdomain = getFlag(args, "--subdomain");
|
|
274
|
-
const healthPath = getFlag(args, "--health-path");
|
|
275
|
-
const healthIntervalStr = getFlag(args, "--health-interval");
|
|
276
|
-
if (!name || ports.length === 0) {
|
|
277
|
-
console.error("Usage: svamp service expose <name> --port <port> [--port <port2>] [--health-path <path>]");
|
|
278
|
-
process.exit(1);
|
|
279
|
-
}
|
|
280
|
-
if (subdomain) validateSubdomain(subdomain);
|
|
281
|
-
const healthInterval = healthIntervalStr ? parseInt(healthIntervalStr, 10) : void 0;
|
|
282
|
-
const env = getSandboxEnv();
|
|
283
|
-
try {
|
|
284
|
-
const group = await createServiceGroup(name, ports, {
|
|
285
|
-
subdomain,
|
|
286
|
-
healthPath,
|
|
287
|
-
healthInterval
|
|
288
|
-
});
|
|
289
|
-
if (env.sandboxId) {
|
|
290
|
-
const result = await addBackend(name);
|
|
291
|
-
console.log(`Backend added: ${result.sandbox_id} (${result.pod_ip})`);
|
|
292
|
-
console.log(`
|
|
293
|
-
Service is live:`);
|
|
294
|
-
for (const p of group.ports) {
|
|
295
|
-
console.log(` ${p.port} \u2192 ${p.url}`);
|
|
296
|
-
}
|
|
297
|
-
} else {
|
|
298
|
-
console.log(`No SANDBOX_ID detected \u2014 starting reverse tunnel.`);
|
|
299
|
-
const { runTunnel } = await import('./tunnel-BDKdemh0.mjs');
|
|
300
|
-
await runTunnel(name, ports);
|
|
301
|
-
}
|
|
302
|
-
} catch (err) {
|
|
303
|
-
console.error(`Error exposing service: ${err.message}`);
|
|
304
|
-
process.exit(1);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
async function serviceServe(args) {
|
|
308
|
-
const positional = positionalArgs(args);
|
|
309
|
-
const name = positional[0];
|
|
310
|
-
const directory = positional[1] || ".";
|
|
311
|
-
const subdomain = getFlag(args, "--subdomain");
|
|
312
|
-
const healthPath = getFlag(args, "--health-path");
|
|
313
|
-
const healthIntervalStr = getFlag(args, "--health-interval");
|
|
314
|
-
const noListing = hasFlag(args, "--no-listing");
|
|
315
|
-
if (!name) {
|
|
316
|
-
console.error("Usage: svamp service serve <name> [directory] [--subdomain <sub>] [--no-listing]");
|
|
317
|
-
console.error(" directory defaults to current directory");
|
|
318
|
-
process.exit(1);
|
|
319
|
-
}
|
|
320
|
-
if (subdomain) validateSubdomain(subdomain);
|
|
321
|
-
const healthInterval = healthIntervalStr ? parseInt(healthIntervalStr, 10) : void 0;
|
|
322
|
-
try {
|
|
323
|
-
const { startStaticServer } = await import('./staticServer-CWcmMF5V.mjs');
|
|
324
|
-
const resolvedDir = require("path").resolve(directory);
|
|
325
|
-
console.log(`Serving ${resolvedDir}`);
|
|
326
|
-
const staticServer = await startStaticServer({
|
|
327
|
-
directory: resolvedDir,
|
|
328
|
-
listing: !noListing
|
|
329
|
-
});
|
|
330
|
-
console.log(`Static server listening on 127.0.0.1:${staticServer.port}`);
|
|
331
|
-
const ports = [staticServer.port];
|
|
332
|
-
const env = getSandboxEnv();
|
|
333
|
-
const group = await createServiceGroup(name, ports, {
|
|
334
|
-
subdomain,
|
|
335
|
-
healthPath,
|
|
336
|
-
healthInterval
|
|
337
|
-
});
|
|
338
|
-
if (env.sandboxId) {
|
|
339
|
-
const result = await addBackend(name);
|
|
340
|
-
console.log(`Backend added: ${result.sandbox_id} (${result.pod_ip})`);
|
|
341
|
-
console.log(`
|
|
342
|
-
Serving ${resolvedDir}:`);
|
|
343
|
-
for (const p of group.ports) {
|
|
344
|
-
console.log(` ${p.url}`);
|
|
345
|
-
}
|
|
346
|
-
} else {
|
|
347
|
-
console.log(`No SANDBOX_ID detected \u2014 starting reverse tunnel.`);
|
|
348
|
-
const { runTunnel } = await import('./tunnel-BDKdemh0.mjs');
|
|
349
|
-
await runTunnel(name, ports);
|
|
350
|
-
}
|
|
351
|
-
const cleanup = () => {
|
|
352
|
-
staticServer.close();
|
|
353
|
-
process.exit(0);
|
|
354
|
-
};
|
|
355
|
-
process.on("SIGINT", cleanup);
|
|
356
|
-
process.on("SIGTERM", cleanup);
|
|
357
|
-
} catch (err) {
|
|
358
|
-
console.error(`Error serving directory: ${err.message}`);
|
|
359
|
-
process.exit(1);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
async function serviceTunnel(args) {
|
|
363
|
-
const positional = positionalArgs(args);
|
|
364
|
-
const name = positional[0];
|
|
365
|
-
const ports = parsePorts(args);
|
|
366
|
-
if (!name || ports.length === 0) {
|
|
367
|
-
console.error("Usage: svamp service tunnel <name> --port <port> [--port <port2>]");
|
|
368
|
-
process.exit(1);
|
|
369
|
-
}
|
|
370
|
-
const { runTunnel } = await import('./tunnel-BDKdemh0.mjs');
|
|
371
|
-
await runTunnel(name, ports);
|
|
372
|
-
}
|
|
373
|
-
async function handleServiceCommand() {
|
|
374
|
-
const args = process.argv.slice(2);
|
|
375
|
-
const serviceArgs = args.slice(1);
|
|
376
|
-
const sub = serviceArgs[0];
|
|
377
|
-
if (!sub || sub === "--help" || sub === "-h") {
|
|
378
|
-
printServiceHelp();
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
const commandArgs = serviceArgs.slice(1);
|
|
382
|
-
if (sub === "create") {
|
|
383
|
-
await serviceCreate(commandArgs);
|
|
384
|
-
} else if (sub === "list" || sub === "ls") {
|
|
385
|
-
await serviceList(commandArgs);
|
|
386
|
-
} else if (sub === "info" || sub === "show") {
|
|
387
|
-
await serviceInfo(commandArgs);
|
|
388
|
-
} else if (sub === "delete" || sub === "rm") {
|
|
389
|
-
await serviceDelete(commandArgs);
|
|
390
|
-
} else if (sub === "add-backend" || sub === "add") {
|
|
391
|
-
await serviceAddBackend(commandArgs);
|
|
392
|
-
} else if (sub === "remove-backend" || sub === "remove") {
|
|
393
|
-
await serviceRemoveBackend(commandArgs);
|
|
394
|
-
} else if (sub === "add-port") {
|
|
395
|
-
await serviceAddPort(commandArgs);
|
|
396
|
-
} else if (sub === "remove-port") {
|
|
397
|
-
await serviceRemovePort(commandArgs);
|
|
398
|
-
} else if (sub === "rename") {
|
|
399
|
-
await serviceRename(commandArgs);
|
|
400
|
-
} else if (sub === "expose") {
|
|
401
|
-
await serviceExpose(commandArgs);
|
|
402
|
-
} else if (sub === "serve") {
|
|
403
|
-
await serviceServe(commandArgs);
|
|
404
|
-
} else if (sub === "tunnel") {
|
|
405
|
-
await serviceTunnel(commandArgs);
|
|
406
|
-
} else {
|
|
407
|
-
console.error(`Unknown service command: ${sub}`);
|
|
408
|
-
printServiceHelp();
|
|
409
|
-
process.exit(1);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
function printServiceHelp() {
|
|
413
|
-
console.log(`
|
|
414
|
-
svamp service \u2014 Manage load-balanced service groups
|
|
415
|
-
|
|
416
|
-
Usage:
|
|
417
|
-
svamp service create <name> --port <port> [--port <port2>] [options] Create a service group
|
|
418
|
-
svamp service list [--json] List service groups
|
|
419
|
-
svamp service info <name> [--json] Show service group details
|
|
420
|
-
svamp service delete <name> Delete a service group
|
|
421
|
-
svamp service add-backend <name> [--sandbox-id <id>] Add a pod as backend
|
|
422
|
-
svamp service remove-backend <name> [--sandbox-id <id>] Remove a backend
|
|
423
|
-
svamp service add-port <name> --port <port> [--subdomain <sub>] Add port to existing group
|
|
424
|
-
svamp service remove-port <name> --port <port> Remove port from group
|
|
425
|
-
svamp service rename <name> --port <port> --subdomain <sub> Rename subdomain of a port
|
|
426
|
-
svamp service expose <name> --port <port> [--port <port2>] [options] Create + join (auto-detects tunnel)
|
|
427
|
-
svamp service serve <name> [directory] [options] Serve a directory as static files
|
|
428
|
-
svamp service tunnel <name> --port <port> [--port <port2>] Tunnel local ports to service group
|
|
429
|
-
|
|
430
|
-
Create/Expose options:
|
|
431
|
-
--health-path <path> Health check endpoint (e.g., /health)
|
|
432
|
-
--health-interval <sec> Health check interval in seconds (default: 30)
|
|
433
|
-
--subdomain <sub> Custom subdomain (must contain at least 2 hyphens)
|
|
434
|
-
|
|
435
|
-
Service groups expose HTTP services via stable URLs with K8s-native load
|
|
436
|
-
balancing. Multiple pods can serve the same service \u2014 K8s handles traffic
|
|
437
|
-
distribution automatically.
|
|
438
|
-
|
|
439
|
-
Multi-port: Use --port multiple times to expose several ports under one
|
|
440
|
-
service group. Each port gets its own unique subdomain and URL.
|
|
441
|
-
|
|
442
|
-
Auto-detect: 'expose' automatically detects the environment:
|
|
443
|
-
- Cloud sandbox (SANDBOX_ID set): adds pod as K8s backend
|
|
444
|
-
- Local machine (no SANDBOX_ID): starts reverse tunnel
|
|
445
|
-
|
|
446
|
-
Environment variables (set by provisioner):
|
|
447
|
-
SANDBOX_API_URL Agent-sandbox API base URL
|
|
448
|
-
SANDBOX_API_KEY API authentication token
|
|
449
|
-
SANDBOX_NAMESPACE User's sandbox namespace
|
|
450
|
-
SANDBOX_ID This pod's sandbox ID
|
|
451
|
-
|
|
452
|
-
Serve options:
|
|
453
|
-
--no-listing Disable directory listing
|
|
454
|
-
--subdomain <sub> Custom subdomain (must contain at least 2 hyphens)
|
|
455
|
-
|
|
456
|
-
Examples:
|
|
457
|
-
svamp service expose my-api --port 8000
|
|
458
|
-
svamp service expose my-api --port 8000 --port 3000 --health-path /health
|
|
459
|
-
svamp service serve my-site ./dist
|
|
460
|
-
svamp service serve my-site (serves current directory)
|
|
461
|
-
svamp service add-port my-api --port 5000
|
|
462
|
-
svamp service remove-port my-api --port 5000
|
|
463
|
-
svamp service list
|
|
464
|
-
svamp service info my-api
|
|
465
|
-
svamp service delete my-api
|
|
466
|
-
`.trim());
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
export { handleServiceCommand, serviceAddBackend, serviceAddPort, serviceCreate, serviceDelete, serviceExpose, serviceInfo, serviceList, serviceRemoveBackend, serviceRemovePort, serviceRename, serviceServe, serviceTunnel };
|