@commandgarden/cli 0.2.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +126 -5
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -7,7 +7,7 @@ var __export = (target, all) => {
|
|
|
7
7
|
|
|
8
8
|
// src/main.ts
|
|
9
9
|
import { Command } from "commander";
|
|
10
|
-
import { join as
|
|
10
|
+
import { join as join3, dirname } from "path";
|
|
11
11
|
import { homedir } from "os";
|
|
12
12
|
import { fileURLToPath } from "url";
|
|
13
13
|
|
|
@@ -4870,13 +4870,114 @@ async function executeConfigSet(client, key, value) {
|
|
|
4870
4870
|
}
|
|
4871
4871
|
}
|
|
4872
4872
|
|
|
4873
|
+
// src/commands/gui-cmd.ts
|
|
4874
|
+
import { spawn as spawn2 } from "child_process";
|
|
4875
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync2, existsSync as existsSync3, unlinkSync as unlinkSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
4876
|
+
import { join as join2 } from "path";
|
|
4877
|
+
import { exec } from "child_process";
|
|
4878
|
+
import { parse as parseYaml2 } from "yaml";
|
|
4879
|
+
function readAppPort(configPath) {
|
|
4880
|
+
try {
|
|
4881
|
+
if (existsSync3(configPath)) {
|
|
4882
|
+
const config2 = parseYaml2(readFileSync5(configPath, "utf-8"));
|
|
4883
|
+
const port = config2?.app?.port;
|
|
4884
|
+
if (typeof port === "number") return port;
|
|
4885
|
+
}
|
|
4886
|
+
} catch {
|
|
4887
|
+
}
|
|
4888
|
+
return 19826;
|
|
4889
|
+
}
|
|
4890
|
+
async function executeGuiStart(baseUrl, cgHome, appScript, opts) {
|
|
4891
|
+
const appPort = opts.configPath ? readAppPort(opts.configPath) : 19826;
|
|
4892
|
+
try {
|
|
4893
|
+
const resp = await fetch(`${baseUrl}/api/status`);
|
|
4894
|
+
if (!resp.ok) throw new Error();
|
|
4895
|
+
} catch {
|
|
4896
|
+
return "Daemon is not running. Start it with: cg daemon start (or use cg up)";
|
|
4897
|
+
}
|
|
4898
|
+
const pidPath = join2(cgHome, "app.pid");
|
|
4899
|
+
if (existsSync3(pidPath)) {
|
|
4900
|
+
const pid = parseInt(readFileSync5(pidPath, "utf-8").trim(), 10);
|
|
4901
|
+
try {
|
|
4902
|
+
process.kill(pid, 0);
|
|
4903
|
+
return "GUI is already running.";
|
|
4904
|
+
} catch {
|
|
4905
|
+
unlinkSync2(pidPath);
|
|
4906
|
+
}
|
|
4907
|
+
}
|
|
4908
|
+
mkdirSync2(cgHome, { recursive: true });
|
|
4909
|
+
if (opts.background) {
|
|
4910
|
+
const child2 = spawn2("node", [appScript], { detached: true, stdio: "ignore" });
|
|
4911
|
+
if (child2.pid) writeFileSync2(pidPath, String(child2.pid));
|
|
4912
|
+
child2.unref();
|
|
4913
|
+
if (!opts.noOpen) openBrowser(`http://127.0.0.1:${appPort}`);
|
|
4914
|
+
return `GUI started (PID: ${child2.pid ?? "unknown"}).`;
|
|
4915
|
+
}
|
|
4916
|
+
if (!opts.noOpen) openBrowser(`http://127.0.0.1:${appPort}`);
|
|
4917
|
+
const child = spawn2("node", [appScript], { stdio: "inherit" });
|
|
4918
|
+
await new Promise((resolve) => child.on("exit", () => resolve()));
|
|
4919
|
+
return "GUI stopped.";
|
|
4920
|
+
}
|
|
4921
|
+
function executeGuiStop(cgHome) {
|
|
4922
|
+
const pidPath = join2(cgHome, "app.pid");
|
|
4923
|
+
if (!existsSync3(pidPath)) return "GUI is not running (no PID file found).";
|
|
4924
|
+
const pid = parseInt(readFileSync5(pidPath, "utf-8").trim(), 10);
|
|
4925
|
+
try {
|
|
4926
|
+
process.kill(pid, "SIGTERM");
|
|
4927
|
+
unlinkSync2(pidPath);
|
|
4928
|
+
return `GUI stopped (PID: ${pid}).`;
|
|
4929
|
+
} catch {
|
|
4930
|
+
unlinkSync2(pidPath);
|
|
4931
|
+
return `GUI process ${pid} not found (stale PID file cleaned up).`;
|
|
4932
|
+
}
|
|
4933
|
+
}
|
|
4934
|
+
function executeGuiStatus(cgHome) {
|
|
4935
|
+
const pidPath = join2(cgHome, "app.pid");
|
|
4936
|
+
if (!existsSync3(pidPath)) return "GUI: not running (no PID file found).";
|
|
4937
|
+
const pid = parseInt(readFileSync5(pidPath, "utf-8").trim(), 10);
|
|
4938
|
+
try {
|
|
4939
|
+
process.kill(pid, 0);
|
|
4940
|
+
return `GUI: running (PID: ${pid}).`;
|
|
4941
|
+
} catch {
|
|
4942
|
+
return "GUI: not running (stale PID file).";
|
|
4943
|
+
}
|
|
4944
|
+
}
|
|
4945
|
+
function openBrowser(url) {
|
|
4946
|
+
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
4947
|
+
exec(`${cmd} ${url}`);
|
|
4948
|
+
}
|
|
4949
|
+
|
|
4950
|
+
// src/commands/up-down.ts
|
|
4951
|
+
async function executeUp(baseUrl, cgHome, daemonScript, appScript, configPath) {
|
|
4952
|
+
const lines = [];
|
|
4953
|
+
lines.push(await executeDaemonStart(baseUrl, cgHome, daemonScript));
|
|
4954
|
+
for (let i = 0; i < 10; i++) {
|
|
4955
|
+
try {
|
|
4956
|
+
const resp = await fetch(`${baseUrl}/api/status`);
|
|
4957
|
+
if (resp.ok) break;
|
|
4958
|
+
} catch {
|
|
4959
|
+
}
|
|
4960
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
4961
|
+
}
|
|
4962
|
+
lines.push(await executeGuiStart(baseUrl, cgHome, appScript, { background: true, configPath }));
|
|
4963
|
+
return lines.join("\n");
|
|
4964
|
+
}
|
|
4965
|
+
async function executeDown(cgHome) {
|
|
4966
|
+
const lines = [];
|
|
4967
|
+
lines.push(executeGuiStop(cgHome));
|
|
4968
|
+
lines.push(await executeDaemonStop(cgHome));
|
|
4969
|
+
lines.push("All services stopped.");
|
|
4970
|
+
return lines.join("\n");
|
|
4971
|
+
}
|
|
4972
|
+
|
|
4873
4973
|
// src/main.ts
|
|
4874
4974
|
var __filename = fileURLToPath(import.meta.url);
|
|
4875
4975
|
var __dirname = dirname(__filename);
|
|
4876
|
-
var DAEMON_SCRIPT =
|
|
4877
|
-
var
|
|
4878
|
-
var
|
|
4879
|
-
var
|
|
4976
|
+
var DAEMON_SCRIPT = join3(__dirname, "..", "..", "daemon", "dist", "main.js");
|
|
4977
|
+
var APP_SCRIPT = join3(__dirname, "..", "..", "app", "dist", "server", "main.js");
|
|
4978
|
+
var CG_HOME = join3(homedir(), ".commandgarden");
|
|
4979
|
+
var TOKEN_PATH = join3(CG_HOME, "session-token");
|
|
4980
|
+
var CONFIG_PATH = join3(CG_HOME, "config.yaml");
|
|
4880
4981
|
var BASE_URL = `http://127.0.0.1:19825`;
|
|
4881
4982
|
function createClient() {
|
|
4882
4983
|
const token = readToken(TOKEN_PATH);
|
|
@@ -4945,4 +5046,24 @@ config.command("set <key> <value>").description("Set a configuration value (e.g.
|
|
|
4945
5046
|
const client = createClient();
|
|
4946
5047
|
console.log(await executeConfigSet(client, key, value));
|
|
4947
5048
|
});
|
|
5049
|
+
var gui = program.command("gui").description("Manage the GUI app server");
|
|
5050
|
+
gui.command("start", { isDefault: true }).description("Start the GUI (foreground by default)").option("-b, --background", "Run in background").option("--no-open", "Do not open browser").action(async (opts) => {
|
|
5051
|
+
console.log(await executeGuiStart(BASE_URL, CG_HOME, APP_SCRIPT, {
|
|
5052
|
+
background: opts.background,
|
|
5053
|
+
noOpen: opts.open === false,
|
|
5054
|
+
configPath: CONFIG_PATH
|
|
5055
|
+
}));
|
|
5056
|
+
});
|
|
5057
|
+
gui.command("stop").description("Stop the GUI").action(() => {
|
|
5058
|
+
console.log(executeGuiStop(CG_HOME));
|
|
5059
|
+
});
|
|
5060
|
+
gui.command("status").description("Check GUI status").action(() => {
|
|
5061
|
+
console.log(executeGuiStatus(CG_HOME));
|
|
5062
|
+
});
|
|
5063
|
+
program.command("up").description("Start daemon + GUI, open browser").action(async () => {
|
|
5064
|
+
console.log(await executeUp(BASE_URL, CG_HOME, DAEMON_SCRIPT, APP_SCRIPT, CONFIG_PATH));
|
|
5065
|
+
});
|
|
5066
|
+
program.command("down").description("Stop GUI + daemon").action(async () => {
|
|
5067
|
+
console.log(await executeDown(CG_HOME));
|
|
5068
|
+
});
|
|
4948
5069
|
program.parse();
|