@miosa/cli 1.0.52 → 1.0.53
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/README.md +42 -65
- package/dist/app-manifest.d.ts +19 -0
- package/dist/app-manifest.d.ts.map +1 -1
- package/dist/app-manifest.js +39 -12
- package/dist/app-manifest.js.map +1 -1
- package/dist/bin/miosa.js +0 -9
- package/dist/bin/miosa.js.map +1 -1
- package/dist/commands/capabilities.d.ts.map +1 -1
- package/dist/commands/capabilities.js +5 -207
- package/dist/commands/capabilities.js.map +1 -1
- package/dist/commands/databases.d.ts.map +1 -1
- package/dist/commands/databases.js +0 -85
- package/dist/commands/databases.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +2 -109
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/docker-deploy.d.ts.map +1 -1
- package/dist/commands/docker-deploy.js +114 -0
- package/dist/commands/docker-deploy.js.map +1 -1
- package/dist/commands/enterprise-util.d.ts +1 -3
- package/dist/commands/enterprise-util.d.ts.map +1 -1
- package/dist/commands/enterprise-util.js +9 -25
- package/dist/commands/enterprise-util.js.map +1 -1
- package/dist/commands/logs.d.ts.map +1 -1
- package/dist/commands/logs.js +17 -171
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/{app.d.ts → machines.d.ts} +1 -1
- package/dist/commands/machines.d.ts.map +1 -0
- package/dist/commands/machines.js +29 -0
- package/dist/commands/machines.js.map +1 -0
- package/dist/commands/new.js +2 -2
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/sandbox.d.ts.map +1 -1
- package/dist/commands/sandbox.js +42 -169
- package/dist/commands/sandbox.js.map +1 -1
- package/dist/config.d.ts +1 -24
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -87
- package/dist/config.js.map +1 -1
- package/dist/miosa-linux-x64 +0 -0
- package/package.json +2 -3
- package/dist/app-advisor.d.ts +0 -80
- package/dist/app-advisor.d.ts.map +0 -1
- package/dist/app-advisor.js +0 -473
- package/dist/app-advisor.js.map +0 -1
- package/dist/commands/app.d.ts.map +0 -1
- package/dist/commands/app.js +0 -115
- package/dist/commands/app.js.map +0 -1
- package/dist/commands/command-overview.d.ts +0 -13
- package/dist/commands/command-overview.d.ts.map +0 -1
- package/dist/commands/command-overview.js +0 -50
- package/dist/commands/command-overview.js.map +0 -1
- package/dist/commands/context.d.ts +0 -3
- package/dist/commands/context.d.ts.map +0 -1
- package/dist/commands/context.js +0 -248
- package/dist/commands/context.js.map +0 -1
package/dist/commands/sandbox.js
CHANGED
|
@@ -383,9 +383,6 @@ export function register(program) {
|
|
|
383
383
|
.allowExcessArguments()
|
|
384
384
|
.option("--cwd <path>", "Working directory inside the Sandbox")
|
|
385
385
|
.option("--workdir <path>", "Alias for --cwd")
|
|
386
|
-
.option("--cmd <command>", "Explicit command string to run; avoids CLI parsing command flags")
|
|
387
|
-
.option("--command <command>", "Alias for --cmd")
|
|
388
|
-
.option("--shell-cmd <shell>", "Run --cmd through this shell, e.g. 'bash -lc'")
|
|
389
386
|
.option("--env <pair>", "Environment variable KEY=VALUE. Repeatable.", collectOption, [])
|
|
390
387
|
.option("--background", "Start the command in the background and return immediately")
|
|
391
388
|
.option("--detached", "Create a durable backend command and return command_id immediately")
|
|
@@ -403,7 +400,7 @@ export function register(program) {
|
|
|
403
400
|
await postAndPrint(`/sandboxes/${enc(id)}/exec`, opts, {});
|
|
404
401
|
return;
|
|
405
402
|
}
|
|
406
|
-
const cmd =
|
|
403
|
+
const cmd = joinCommandWords(words);
|
|
407
404
|
const effectiveCommand = opts.background
|
|
408
405
|
? backgroundCommand(cmd)
|
|
409
406
|
: cmd;
|
|
@@ -417,7 +414,7 @@ export function register(program) {
|
|
|
417
414
|
}
|
|
418
415
|
const env = parseEnvPairs(opts.env ?? []);
|
|
419
416
|
if (opts.detached) {
|
|
420
|
-
const result = await createSandboxCommand(id,
|
|
417
|
+
const result = await createSandboxCommand(id, words.join(" "), {
|
|
421
418
|
cwd,
|
|
422
419
|
env,
|
|
423
420
|
user: opts.user,
|
|
@@ -451,9 +448,6 @@ export function register(program) {
|
|
|
451
448
|
.allowExcessArguments()
|
|
452
449
|
.option("--cwd <path>", "Working directory inside the Sandbox")
|
|
453
450
|
.option("--workdir <path>", "Alias for --cwd")
|
|
454
|
-
.option("--cmd <command>", "Explicit command string to run; avoids CLI parsing command flags")
|
|
455
|
-
.option("--command <command>", "Alias for --cmd")
|
|
456
|
-
.option("--shell-cmd <shell>", "Run --cmd through this shell, e.g. 'bash -lc'")
|
|
457
451
|
.option("--env <pair>", "Environment variable KEY=VALUE. Repeatable.", collectOption, [])
|
|
458
452
|
.option("--background", "Start the command in the background and return immediately")
|
|
459
453
|
.option("--detached", "Create a durable backend command and return command_id immediately")
|
|
@@ -471,7 +465,7 @@ export function register(program) {
|
|
|
471
465
|
await postAndPrint(`/sandboxes/${enc(id)}/exec`, opts, {});
|
|
472
466
|
return;
|
|
473
467
|
}
|
|
474
|
-
const cmd =
|
|
468
|
+
const cmd = joinCommandWords(words);
|
|
475
469
|
const effectiveCommand = opts.background
|
|
476
470
|
? backgroundCommand(cmd)
|
|
477
471
|
: cmd;
|
|
@@ -485,7 +479,7 @@ export function register(program) {
|
|
|
485
479
|
}
|
|
486
480
|
const env = parseEnvPairs(opts.env ?? []);
|
|
487
481
|
if (opts.detached) {
|
|
488
|
-
const result = await createSandboxCommand(id,
|
|
482
|
+
const result = await createSandboxCommand(id, words.join(" "), {
|
|
489
483
|
cwd,
|
|
490
484
|
env,
|
|
491
485
|
user: opts.user,
|
|
@@ -516,10 +510,12 @@ export function register(program) {
|
|
|
516
510
|
.description("List listening TCP ports inside a Sandbox")
|
|
517
511
|
.option("--json", "Output as JSON")
|
|
518
512
|
.action((id, opts) => runAction(async () => {
|
|
519
|
-
const
|
|
520
|
-
const
|
|
513
|
+
const c = client();
|
|
514
|
+
const result = await execSandboxRaw(c, id, "ss -ltnH 2>/dev/null || cat /proc/net/tcp /proc/net/tcp6 2>/dev/null");
|
|
515
|
+
const stdout = String(result["stdout"] ?? "");
|
|
516
|
+
const ports = parseListeningPorts(stdout);
|
|
521
517
|
if (isJsonMode(opts)) {
|
|
522
|
-
console.log(JSON.stringify(
|
|
518
|
+
console.log(JSON.stringify(ports, null, 2));
|
|
523
519
|
return;
|
|
524
520
|
}
|
|
525
521
|
if (ports.length === 0) {
|
|
@@ -527,11 +523,6 @@ export function register(program) {
|
|
|
527
523
|
return;
|
|
528
524
|
}
|
|
529
525
|
renderTable(ports, [
|
|
530
|
-
{
|
|
531
|
-
header: "PROTO",
|
|
532
|
-
key: (p) => p.protocol ?? "tcp",
|
|
533
|
-
width: 8,
|
|
534
|
-
},
|
|
535
526
|
{
|
|
536
527
|
header: "PORT",
|
|
537
528
|
key: "port",
|
|
@@ -542,33 +533,8 @@ export function register(program) {
|
|
|
542
533
|
key: "address",
|
|
543
534
|
width: 24,
|
|
544
535
|
},
|
|
545
|
-
{
|
|
546
|
-
header: "STATE",
|
|
547
|
-
key: (p) => p.state ?? "listen",
|
|
548
|
-
width: 10,
|
|
549
|
-
},
|
|
550
|
-
{
|
|
551
|
-
header: "PROCESS",
|
|
552
|
-
key: (p) => p.process?.name
|
|
553
|
-
? `${p.process.name}${p.process.pid ? `:${p.process.pid}` : ""}`
|
|
554
|
-
: chalk.dim("-"),
|
|
555
|
-
width: 28,
|
|
556
|
-
},
|
|
557
536
|
]);
|
|
558
537
|
}));
|
|
559
|
-
sandbox
|
|
560
|
-
.command("metrics <sandbox-id>")
|
|
561
|
-
.description("Show Sandbox resource, uptime, timeout, and readiness metrics")
|
|
562
|
-
.option("--window <window>", "Metrics window: 1h, 24h, or 7d", "1h")
|
|
563
|
-
.option("--json", "Output as JSON")
|
|
564
|
-
.action((id, opts) => runAction(async () => {
|
|
565
|
-
const result = await client().apiGet(apiPath(`/sandboxes/${enc(id)}/metrics?window=${enc(opts.window)}`));
|
|
566
|
-
if (isJsonMode(opts)) {
|
|
567
|
-
console.log(JSON.stringify(result, null, 2));
|
|
568
|
-
return;
|
|
569
|
-
}
|
|
570
|
-
renderResourceMetrics("Sandbox metrics", result);
|
|
571
|
-
}));
|
|
572
538
|
sandbox
|
|
573
539
|
.command("deploy [local-dir]")
|
|
574
540
|
.description("Upload an app directory, start it in a sandbox, expose a preview URL, and wait for readiness")
|
|
@@ -679,9 +645,8 @@ export function register(program) {
|
|
|
679
645
|
.option("--environment <name>", "Target environment label", "production")
|
|
680
646
|
.option("--build-command <cmd>", "Build command to run before publishing")
|
|
681
647
|
.option("--run-command <cmd>", "Run command for dynamic/server deployments")
|
|
648
|
+
.option("--docker-deploy", "Publish onto the workspace Docker Deploy runtime instead of standard app hosting")
|
|
682
649
|
.option("--domain <domain>", "Custom domain to attach")
|
|
683
|
-
.option("--docker-deploy", "Publish through the workspace Docker Deploy runtime")
|
|
684
|
-
.option("--deployment-type <type>", "Deployment runtime type: miosa_deploy, docker_deploy, dynamic, static")
|
|
685
650
|
.option("--database <mode>", "none, create:postgres, postgres, or existing:<db-id>")
|
|
686
651
|
.option("--port <port>", "Runtime port for dynamic deployments", parseIntegerOption)
|
|
687
652
|
.option("--wait", "Wait for the production URL to answer")
|
|
@@ -699,10 +664,6 @@ export function register(program) {
|
|
|
699
664
|
console.log(` ${chalk.bold("App")} ${result.deployment_id ?? result.app_id ?? ""}`);
|
|
700
665
|
if (result.release_id)
|
|
701
666
|
console.log(` ${chalk.bold("Release")} ${result.release_id}`);
|
|
702
|
-
if (result.deployment_product)
|
|
703
|
-
console.log(` ${chalk.bold("Product")} ${String(result.deployment_product)}`);
|
|
704
|
-
if (result.docker_deploy_host_id)
|
|
705
|
-
console.log(` ${chalk.bold("Docker")} ${String(result.docker_deploy_host_id)}`);
|
|
706
667
|
if (result.url)
|
|
707
668
|
console.log(` ${chalk.bold("URL")} ${chalk.cyan(String(result.url))}`);
|
|
708
669
|
console.log(` ${chalk.bold("Ready")} ${result.ready ? chalk.green("yes") : chalk.yellow("pending")}`);
|
|
@@ -1791,6 +1752,8 @@ async function publishSandbox(sandboxId, opts) {
|
|
|
1791
1752
|
? { environment: opts.environment, deployment_product: "docker_deploy" }
|
|
1792
1753
|
: { environment: opts.environment },
|
|
1793
1754
|
};
|
|
1755
|
+
if (opts.dockerDeploy)
|
|
1756
|
+
body["deployment_type"] = "docker-deploy";
|
|
1794
1757
|
if (opts.app)
|
|
1795
1758
|
body["deployment_id"] = opts.app;
|
|
1796
1759
|
// Bug 9: avoid creating a duplicate deployment on retry. When publishing by
|
|
@@ -1815,11 +1778,6 @@ async function publishSandbox(sandboxId, opts) {
|
|
|
1815
1778
|
body["domain"] = opts.domain;
|
|
1816
1779
|
if (opts.port != null)
|
|
1817
1780
|
body["port"] = opts.port;
|
|
1818
|
-
const deploymentType = opts.dockerDeploy
|
|
1819
|
-
? "docker-deploy"
|
|
1820
|
-
: opts.deploymentType;
|
|
1821
|
-
if (deploymentType)
|
|
1822
|
-
body["deployment_type"] = deploymentType;
|
|
1823
1781
|
const database = parsePublishDatabase(opts.database);
|
|
1824
1782
|
if (database !== undefined)
|
|
1825
1783
|
body["database"] = database;
|
|
@@ -1840,29 +1798,11 @@ async function publishSandbox(sandboxId, opts) {
|
|
|
1840
1798
|
extractUrl(deployment) ??
|
|
1841
1799
|
stringField(data, "url") ??
|
|
1842
1800
|
null;
|
|
1843
|
-
let deploymentProduct = stringField(response, "deployment_product") ??
|
|
1844
|
-
stringField(data, "deployment_product") ??
|
|
1845
|
-
stringField(deployment, "deployment_product") ??
|
|
1846
|
-
stringField(asRecord(deployment?.["metadata"]), "deployment_product") ??
|
|
1847
|
-
null;
|
|
1848
|
-
let dockerDeployHostId = stringField(response, "docker_deploy_host_id") ??
|
|
1849
|
-
stringField(data, "docker_deploy_host_id") ??
|
|
1850
|
-
stringField(deployment, "docker_deploy_host_id") ??
|
|
1851
|
-
stringField(asRecord(deployment?.["metadata"]), "docker_deploy_host_id") ??
|
|
1852
|
-
null;
|
|
1853
1801
|
if (opts.wait && deploymentId) {
|
|
1854
1802
|
deployStep(opts, "Waiting for durable deployment");
|
|
1855
1803
|
const waited = await waitForDeploymentReady(c, deploymentId, opts.timeout);
|
|
1856
1804
|
state = stringField(waited, "state") ?? state;
|
|
1857
1805
|
url = extractUrl(waited) ?? url;
|
|
1858
|
-
deploymentProduct =
|
|
1859
|
-
stringField(waited, "deployment_product") ??
|
|
1860
|
-
stringField(asRecord(waited["metadata"]), "deployment_product") ??
|
|
1861
|
-
deploymentProduct;
|
|
1862
|
-
dockerDeployHostId =
|
|
1863
|
-
stringField(waited, "docker_deploy_host_id") ??
|
|
1864
|
-
stringField(asRecord(waited["metadata"]), "docker_deploy_host_id") ??
|
|
1865
|
-
dockerDeployHostId;
|
|
1866
1806
|
response["state"] = state;
|
|
1867
1807
|
if (url)
|
|
1868
1808
|
response["url"] = url;
|
|
@@ -1888,8 +1828,6 @@ async function publishSandbox(sandboxId, opts) {
|
|
|
1888
1828
|
version_id: versionId,
|
|
1889
1829
|
url,
|
|
1890
1830
|
state,
|
|
1891
|
-
deployment_product: deploymentProduct,
|
|
1892
|
-
docker_deploy_host_id: dockerDeployHostId,
|
|
1893
1831
|
ready,
|
|
1894
1832
|
probe,
|
|
1895
1833
|
data: raw,
|
|
@@ -2129,93 +2067,37 @@ async function execSandboxRaw(c, sandboxId, command, cwd, timeout) {
|
|
|
2129
2067
|
body["timeout"] = timeout;
|
|
2130
2068
|
return unwrap(await c.apiPost(apiPath(`/sandboxes/${enc(sandboxId)}/exec`), body));
|
|
2131
2069
|
}
|
|
2132
|
-
function
|
|
2133
|
-
const
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
{ label: "ready", value: formatBool(current["ready"]) },
|
|
2161
|
-
{ label: "cpu", value: formatMaybe(current["cpu_count"]) },
|
|
2162
|
-
{ label: "memory", value: formatMb(current["memory_mb"]) },
|
|
2163
|
-
{ label: "disk", value: formatMb(current["disk_size_mb"]) },
|
|
2164
|
-
{ label: "uptime", value: formatSeconds(current["uptime_sec"]) },
|
|
2165
|
-
{
|
|
2166
|
-
label: "timeout_remaining",
|
|
2167
|
-
value: formatSecondsOrAlwaysOn(current["timeout_remaining_sec"]),
|
|
2168
|
-
},
|
|
2169
|
-
{ label: "node", value: formatMaybe(current["node_id"]) },
|
|
2170
|
-
{ label: "ip", value: formatMaybe(current["ip_address"]) },
|
|
2171
|
-
{ label: "boot", value: formatMs(current["boot_ms"]) },
|
|
2172
|
-
{ label: "envd_ready", value: formatMs(current["envd_ready_ms"]) },
|
|
2173
|
-
]));
|
|
2174
|
-
}
|
|
2175
|
-
function formatState(value) {
|
|
2176
|
-
const state = String(value ?? "unknown");
|
|
2177
|
-
if (["running", "active", "healthy", "ready"].includes(state)) {
|
|
2178
|
-
return chalk.green(state);
|
|
2179
|
-
}
|
|
2180
|
-
if (["provisioning", "starting", "building", "pending"].includes(state)) {
|
|
2181
|
-
return chalk.yellow(state);
|
|
2182
|
-
}
|
|
2183
|
-
if (["failed", "error", "unhealthy"].includes(state)) {
|
|
2184
|
-
return chalk.red(state);
|
|
2070
|
+
function parseListeningPorts(stdout) {
|
|
2071
|
+
const lines = stdout.split("\n").map((l) => l.trim());
|
|
2072
|
+
const seen = new Set();
|
|
2073
|
+
const out = [];
|
|
2074
|
+
// ss -ltnH columns: State Recv-Q Send-Q Local-Address:Port Peer-Address:Port
|
|
2075
|
+
const ssLine = /^LISTEN\s+\d+\s+\d+\s+(\S+):(\d+)\s+/;
|
|
2076
|
+
// /proc/net/tcp: sl local_address rem_address st ... (hex)
|
|
2077
|
+
const procLine = /^\d+:\s+([0-9A-Fa-f]+):([0-9A-Fa-f]+)\s+\S+\s+([0-9A-Fa-f]+)/;
|
|
2078
|
+
for (const line of lines) {
|
|
2079
|
+
if (!line)
|
|
2080
|
+
continue;
|
|
2081
|
+
const ss = ssLine.exec(line);
|
|
2082
|
+
if (ss && ss[2]) {
|
|
2083
|
+
const port = Number(ss[2]);
|
|
2084
|
+
if (!seen.has(port)) {
|
|
2085
|
+
seen.add(port);
|
|
2086
|
+
out.push({ port, address: ss[1] ?? "*" });
|
|
2087
|
+
}
|
|
2088
|
+
continue;
|
|
2089
|
+
}
|
|
2090
|
+
const proc = procLine.exec(line);
|
|
2091
|
+
if (proc && proc[3] === "0A" && proc[2]) {
|
|
2092
|
+
const port = parseInt(proc[2], 16);
|
|
2093
|
+
if (!Number.isNaN(port) && !seen.has(port)) {
|
|
2094
|
+
seen.add(port);
|
|
2095
|
+
out.push({ port, address: "*" });
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2185
2098
|
}
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
function formatBool(value) {
|
|
2189
|
-
if (value === true)
|
|
2190
|
-
return chalk.green("true");
|
|
2191
|
-
if (value === false)
|
|
2192
|
-
return chalk.red("false");
|
|
2193
|
-
return chalk.dim("-");
|
|
2194
|
-
}
|
|
2195
|
-
function formatMaybe(value) {
|
|
2196
|
-
if (value === null || value === undefined || value === "")
|
|
2197
|
-
return chalk.dim("-");
|
|
2198
|
-
return String(value);
|
|
2199
|
-
}
|
|
2200
|
-
function formatMb(value) {
|
|
2201
|
-
if (typeof value !== "number")
|
|
2202
|
-
return formatMaybe(value);
|
|
2203
|
-
return formatBytes(value * 1024 * 1024);
|
|
2204
|
-
}
|
|
2205
|
-
function formatMs(value) {
|
|
2206
|
-
if (typeof value !== "number")
|
|
2207
|
-
return formatMaybe(value);
|
|
2208
|
-
return `${value}ms`;
|
|
2209
|
-
}
|
|
2210
|
-
function formatSeconds(value) {
|
|
2211
|
-
if (typeof value !== "number")
|
|
2212
|
-
return formatMaybe(value);
|
|
2213
|
-
return formatDuration(value * 1000);
|
|
2214
|
-
}
|
|
2215
|
-
function formatSecondsOrAlwaysOn(value) {
|
|
2216
|
-
if (value === null || value === undefined)
|
|
2217
|
-
return chalk.dim("always-on/none");
|
|
2218
|
-
return formatSeconds(value);
|
|
2099
|
+
out.sort((a, b) => a.port - b.port);
|
|
2100
|
+
return out;
|
|
2219
2101
|
}
|
|
2220
2102
|
// Stream exec output: run in background to a log file, poll-read new bytes
|
|
2221
2103
|
// until the process exits, then print the final exit code.
|
|
@@ -2505,15 +2387,6 @@ function backgroundCommand(command) {
|
|
|
2505
2387
|
const logPath = `/tmp/miosa-bg-${Date.now()}.log`;
|
|
2506
2388
|
return `nohup sh -lc ${shellQuote(command)} > ${shellQuote(logPath)} 2>&1 & echo $!`;
|
|
2507
2389
|
}
|
|
2508
|
-
function resolveSandboxCommand(words, opts) {
|
|
2509
|
-
const positional = words.length === 1 ? (words[0] ?? "") : joinCommandWords(words);
|
|
2510
|
-
const cmd = opts.cmd ?? opts.command ?? positional;
|
|
2511
|
-
if (!opts.shellCmd)
|
|
2512
|
-
return cmd;
|
|
2513
|
-
if (!cmd.trim())
|
|
2514
|
-
return opts.shellCmd;
|
|
2515
|
-
return `${opts.shellCmd} ${shellQuote(cmd)}`;
|
|
2516
|
-
}
|
|
2517
2390
|
function collectOption(value, previous) {
|
|
2518
2391
|
return [...previous, value];
|
|
2519
2392
|
}
|