@plumpslabs/fennec-cli 1.13.6 → 1.13.8
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/index.js +51 -80
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2091,7 +2091,7 @@ function hexColor(color) {
|
|
|
2091
2091
|
}
|
|
2092
2092
|
var fennecOrange2 = hexColor("#FF6432");
|
|
2093
2093
|
var fennecGold = hexColor("#FFB347");
|
|
2094
|
-
var VERSION = "1.13.
|
|
2094
|
+
var VERSION = "1.13.8";
|
|
2095
2095
|
var cachedBanner = null;
|
|
2096
2096
|
var cachedCompact = null;
|
|
2097
2097
|
function generateBanner() {
|
|
@@ -2242,13 +2242,14 @@ var COMMANDS = {
|
|
|
2242
2242
|
kill: {
|
|
2243
2243
|
name: "kill",
|
|
2244
2244
|
usage: "kill <pid|name|all>",
|
|
2245
|
-
summary: "Kill a process by PID, name, or
|
|
2246
|
-
description: "Permanently removes a tracked app (unlike `stop`, which keeps it). Prompts before killing.",
|
|
2245
|
+
summary: "Kill a Fennec-tracked process (by PID, tracked name, or all tracked)",
|
|
2246
|
+
description: "Permanently removes a tracked app (unlike `stop`, which keeps it). By NAME it only matches Fennec-tracked apps \u2014 use an explicit PID to kill a system process. Prompts before killing.",
|
|
2247
2247
|
options: [
|
|
2248
2248
|
["--signal <sig>", "Signal to send (default: SIGTERM). e.g. SIGKILL, SIGINT"],
|
|
2249
|
-
["--all, -a", "Kill
|
|
2249
|
+
["--all, -a", "Kill ALL tracked apps (asks for confirmation)"],
|
|
2250
|
+
["-y, --yes", "Skip the confirmation prompt"]
|
|
2250
2251
|
],
|
|
2251
|
-
examples: ["kill web", "kill 12345 --signal SIGKILL", "kill all"]
|
|
2252
|
+
examples: ["kill web", "kill 12345 --signal SIGKILL", "kill all -y"]
|
|
2252
2253
|
},
|
|
2253
2254
|
supervisor: {
|
|
2254
2255
|
name: "supervisor",
|
|
@@ -4240,36 +4241,18 @@ async function killCommand(args2) {
|
|
|
4240
4241
|
const trackedMatch = tracked.find((t) => t.name === rawTarget);
|
|
4241
4242
|
if (trackedMatch) {
|
|
4242
4243
|
if (!isTrackedRunning(trackedMatch)) {
|
|
4244
|
+
removeTrackedByPid(trackedMatch.pid);
|
|
4243
4245
|
console.error(`
|
|
4244
|
-
${pc8.
|
|
4245
|
-
console.error(
|
|
4246
|
-
|
|
4246
|
+
${pc8.green("\u2713")} ${pc8.bold(rawTarget)} ${pc8.dim("removed from tracked apps (was already stopped)")}`);
|
|
4247
|
+
console.error();
|
|
4248
|
+
return;
|
|
4247
4249
|
}
|
|
4248
4250
|
targetPid = trackedMatch.pid;
|
|
4249
4251
|
displayName = `${trackedMatch.name} (PID ${targetPid})`;
|
|
4250
4252
|
} else {
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
if (matches.length === 0) {
|
|
4255
|
-
console.error(renderError("Process not found", `No running process matching "${rawTarget}"`));
|
|
4256
|
-
process.exit(1);
|
|
4257
|
-
}
|
|
4258
|
-
if (matches.length > 1) {
|
|
4259
|
-
console.error(`
|
|
4260
|
-
${pc8.bold(`Multiple processes match "${rawTarget}":`)}`);
|
|
4261
|
-
const selected = await selectPrompt("Select which to kill:", matches.map((p, i) => ({ value: String(i), label: `${p.name} (PID ${p.pid})`, description: `${p.command.slice(0, 80)} \u2014 CPU: ${p.cpuPercent}% MEM: ${p.memPercent}%` })));
|
|
4262
|
-
if (selected === null) {
|
|
4263
|
-
console.error(` ${pc8.dim("Cancelled")}`);
|
|
4264
|
-
return;
|
|
4265
|
-
}
|
|
4266
|
-
const idx = parseInt(selected, 10);
|
|
4267
|
-
targetPid = matches[idx].pid;
|
|
4268
|
-
displayName = `${matches[idx].name} (PID ${targetPid})`;
|
|
4269
|
-
} else {
|
|
4270
|
-
targetPid = matches[0].pid;
|
|
4271
|
-
displayName = `${matches[0].name} (PID ${targetPid})`;
|
|
4272
|
-
}
|
|
4253
|
+
console.error(renderError("Not tracked", `No tracked process named "${rawTarget}".
|
|
4254
|
+
Use ${pc8.cyan(`fennec kill <pid>`)} to kill a system process by its PID.`));
|
|
4255
|
+
process.exit(1);
|
|
4273
4256
|
}
|
|
4274
4257
|
}
|
|
4275
4258
|
const confirmed = force || await confirmPrompt(`Kill ${pc8.bold(displayName)} with ${pc8.yellow(signal)}?`, false);
|
|
@@ -4623,35 +4606,27 @@ import { mkdirSync as mkdirSync6 } from "fs";
|
|
|
4623
4606
|
import { resolve as resolve6 } from "path";
|
|
4624
4607
|
import { homedir as homedir4 } from "os";
|
|
4625
4608
|
async function restartCommand(args2) {
|
|
4626
|
-
const
|
|
4627
|
-
if (!
|
|
4628
|
-
console.error(renderError("Missing process name/pid", "Usage: fennec restart <name|pid>"));
|
|
4609
|
+
const raw = args2[0];
|
|
4610
|
+
if (!raw) {
|
|
4611
|
+
console.error(renderError("Missing process name/pid", "Usage: fennec restart <name|pid> [-y]"));
|
|
4629
4612
|
process.exit(1);
|
|
4630
4613
|
}
|
|
4631
4614
|
const tracked = readTracked();
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
if (trackedEntry) {
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
if (!isNaN(pid) && String(pid) === name) {
|
|
4639
|
-
targetPid = pid;
|
|
4640
|
-
} else {
|
|
4641
|
-
const processes = getSystemProcesses({ name, userOnly: true, limit: 1 });
|
|
4642
|
-
if (processes.length === 0) {
|
|
4643
|
-
console.error(renderError("Process not found", `No process matching "${name}"`));
|
|
4644
|
-
process.exit(1);
|
|
4645
|
-
}
|
|
4646
|
-
targetPid = processes[0].pid;
|
|
4647
|
-
}
|
|
4615
|
+
const pidNum = parseInt(raw, 10);
|
|
4616
|
+
const trackedEntry = tracked.find((t) => t.name === raw) ?? (!isNaN(pidNum) && String(pidNum) === raw ? tracked.find((t) => t.pid === pidNum) : void 0);
|
|
4617
|
+
if (!trackedEntry) {
|
|
4618
|
+
console.error(renderError("Not tracked", `No tracked process named or with PID "${raw}".
|
|
4619
|
+
fennec restart only re-spawns Fennec-tracked apps (from their saved config).`));
|
|
4620
|
+
process.exit(1);
|
|
4648
4621
|
}
|
|
4649
|
-
const
|
|
4622
|
+
const targetPid = trackedEntry.pid;
|
|
4623
|
+
const force = args2.includes("-y") || args2.includes("--yes");
|
|
4624
|
+
const confirmed = force || await confirmPrompt(`Restart ${pc11.bold(`${trackedEntry.name} (PID ${targetPid})`)}?`, false);
|
|
4650
4625
|
if (!confirmed) {
|
|
4651
4626
|
console.error(` ${pc11.dim("Cancelled")}`);
|
|
4652
4627
|
return;
|
|
4653
4628
|
}
|
|
4654
|
-
const spinner = createSpinner(`Stopping PID ${targetPid}...`);
|
|
4629
|
+
const spinner = createSpinner(`Stopping ${trackedEntry.name} (PID ${targetPid})...`);
|
|
4655
4630
|
const killed = killProcess(targetPid, "SIGTERM");
|
|
4656
4631
|
if (!killed) {
|
|
4657
4632
|
spinner.fail(`Failed to stop PID ${targetPid}`);
|
|
@@ -4663,35 +4638,31 @@ async function restartCommand(args2) {
|
|
|
4663
4638
|
killProcess(targetPid, "SIGKILL");
|
|
4664
4639
|
await new Promise((r) => setTimeout(r, 500));
|
|
4665
4640
|
}
|
|
4666
|
-
spinner.succeed(`${name} stopped`);
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
}
|
|
4690
|
-
|
|
4691
|
-
console.error(` ${pc11.dim("Config preserved. Re-run manually:")} ${renderCommand(trackedEntry.command)}`);
|
|
4692
|
-
}
|
|
4693
|
-
} else {
|
|
4694
|
-
console.error(` ${pc11.dim("No tracked config found. Re-run manually:")} ${renderCommand(name)}`);
|
|
4641
|
+
spinner.succeed(`${trackedEntry.name} stopped`);
|
|
4642
|
+
const respawnSpinner = createSpinner(`Re-spawning ${trackedEntry.name}...`);
|
|
4643
|
+
try {
|
|
4644
|
+
const cmdParts = resolveArgs(trackedEntry);
|
|
4645
|
+
const logDir = resolve6(homedir4(), ".fennec", "logs");
|
|
4646
|
+
mkdirSync6(logDir, { recursive: true });
|
|
4647
|
+
const logFilePath = resolve6(logDir, `${trackedEntry.name}.log`);
|
|
4648
|
+
const child = spawnDaemon({ cmdParts, name: trackedEntry.name, cwd: trackedEntry.cwd, logFilePath, env: buildSpawnEnv(trackedEntry.env), logMode: trackedEntry.logMode });
|
|
4649
|
+
removeTrackedByPid(targetPid);
|
|
4650
|
+
addTracked({
|
|
4651
|
+
name: trackedEntry.name,
|
|
4652
|
+
pid: child.pid ?? 0,
|
|
4653
|
+
command: trackedEntry.command,
|
|
4654
|
+
args: cmdParts,
|
|
4655
|
+
port: trackedEntry.port,
|
|
4656
|
+
cwd: trackedEntry.cwd,
|
|
4657
|
+
env: trackedEntry.env,
|
|
4658
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4659
|
+
autoRestart: trackedEntry.autoRestart,
|
|
4660
|
+
logMode: trackedEntry.logMode
|
|
4661
|
+
});
|
|
4662
|
+
respawnSpinner.succeed(`${trackedEntry.name} restarted (PID: ${child.pid})`);
|
|
4663
|
+
} catch (error) {
|
|
4664
|
+
respawnSpinner.fail(`Failed to re-spawn ${trackedEntry.name}: ${String(error)}`);
|
|
4665
|
+
console.error(` ${pc11.dim("Config preserved. Re-run manually:")} ${renderCommand(trackedEntry.command)}`);
|
|
4695
4666
|
}
|
|
4696
4667
|
}
|
|
4697
4668
|
|