@miosa/cli 1.0.52 → 1.0.54

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.
Files changed (56) hide show
  1. package/README.md +42 -65
  2. package/dist/app-manifest.d.ts +19 -0
  3. package/dist/app-manifest.d.ts.map +1 -1
  4. package/dist/app-manifest.js +39 -12
  5. package/dist/app-manifest.js.map +1 -1
  6. package/dist/bin/miosa.js +0 -9
  7. package/dist/bin/miosa.js.map +1 -1
  8. package/dist/commands/capabilities.d.ts.map +1 -1
  9. package/dist/commands/capabilities.js +5 -207
  10. package/dist/commands/capabilities.js.map +1 -1
  11. package/dist/commands/databases.d.ts.map +1 -1
  12. package/dist/commands/databases.js +0 -85
  13. package/dist/commands/databases.js.map +1 -1
  14. package/dist/commands/deploy.d.ts.map +1 -1
  15. package/dist/commands/deploy.js +2 -109
  16. package/dist/commands/deploy.js.map +1 -1
  17. package/dist/commands/docker-deploy.d.ts.map +1 -1
  18. package/dist/commands/docker-deploy.js +156 -0
  19. package/dist/commands/docker-deploy.js.map +1 -1
  20. package/dist/commands/enterprise-util.d.ts +1 -3
  21. package/dist/commands/enterprise-util.d.ts.map +1 -1
  22. package/dist/commands/enterprise-util.js +9 -25
  23. package/dist/commands/enterprise-util.js.map +1 -1
  24. package/dist/commands/logs.d.ts.map +1 -1
  25. package/dist/commands/logs.js +17 -171
  26. package/dist/commands/logs.js.map +1 -1
  27. package/dist/commands/{app.d.ts → machines.d.ts} +1 -1
  28. package/dist/commands/machines.d.ts.map +1 -0
  29. package/dist/commands/machines.js +29 -0
  30. package/dist/commands/machines.js.map +1 -0
  31. package/dist/commands/new.js +2 -2
  32. package/dist/commands/new.js.map +1 -1
  33. package/dist/commands/sandbox.d.ts.map +1 -1
  34. package/dist/commands/sandbox.js +42 -169
  35. package/dist/commands/sandbox.js.map +1 -1
  36. package/dist/config.d.ts +1 -24
  37. package/dist/config.d.ts.map +1 -1
  38. package/dist/config.js +0 -87
  39. package/dist/config.js.map +1 -1
  40. package/dist/miosa-linux-x64 +0 -0
  41. package/package.json +2 -3
  42. package/dist/app-advisor.d.ts +0 -80
  43. package/dist/app-advisor.d.ts.map +0 -1
  44. package/dist/app-advisor.js +0 -473
  45. package/dist/app-advisor.js.map +0 -1
  46. package/dist/commands/app.d.ts.map +0 -1
  47. package/dist/commands/app.js +0 -115
  48. package/dist/commands/app.js.map +0 -1
  49. package/dist/commands/command-overview.d.ts +0 -13
  50. package/dist/commands/command-overview.d.ts.map +0 -1
  51. package/dist/commands/command-overview.js +0 -50
  52. package/dist/commands/command-overview.js.map +0 -1
  53. package/dist/commands/context.d.ts +0 -3
  54. package/dist/commands/context.d.ts.map +0 -1
  55. package/dist/commands/context.js +0 -248
  56. package/dist/commands/context.js.map +0 -1
@@ -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 = resolveSandboxCommand(words, opts);
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, cmd, {
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 = resolveSandboxCommand(words, opts);
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, cmd, {
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 result = await client().apiGet(apiPath(`/sandboxes/${enc(id)}/ports`));
520
- const ports = sandboxPortsFromResponse(result);
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(result, null, 2));
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 sandboxPortsFromResponse(raw) {
2133
- const root = unwrap(raw);
2134
- if (Array.isArray(root))
2135
- return root;
2136
- if (root && typeof root === "object") {
2137
- const row = root;
2138
- if (Array.isArray(row["ports"]))
2139
- return row["ports"];
2140
- if (Array.isArray(row["data"]))
2141
- return row["data"];
2142
- }
2143
- return [];
2144
- }
2145
- function renderResourceMetrics(title, raw) {
2146
- const root = unwrap(raw);
2147
- if (!root || typeof root !== "object") {
2148
- printValue(root, {});
2149
- return;
2150
- }
2151
- const row = root;
2152
- const current = row["current"] && typeof row["current"] === "object"
2153
- ? row["current"]
2154
- : {};
2155
- printBanner({ subtitle: title });
2156
- console.log(kvPanel([
2157
- { label: "resource_id", value: String(row["resource_id"] ?? row["sandbox_id"] ?? "-") },
2158
- { label: "window", value: String(row["window"] ?? "1h") },
2159
- { label: "state", value: formatState(current["state"]) },
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
- return state;
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
  }