chrome-cmd
Version:
Control Chrome from the command line - List tabs, execute JavaScript, and more
118 lines (117 loc) • 3.73 kB
JavaScript
import { existsSync, readFileSync, unlinkSync } from "node:fs";
import { Command } from "commander";
import { BRIDGE_CONFIG } from "../../bridge/bridge.config.js";
import { FILES_CONFIG } from "../../shared/configs/files.config.js";
import { logger } from "../../shared/utils/helpers/logger.js";
import { execAsync } from "../utils/cli-utils.js";
function createBridgeCommand() {
const bridge = new Command("bridge").description("Manage the bridge process (internal/debug)");
bridge.command("status").description("Check if bridge is running").action(async () => {
try {
const result = await checkBridgeStatus();
if (result.running) {
logger.success("\u2713 Bridge is running");
logger.dim(` PID: ${result.pid}`);
logger.dim(` Port: ${BRIDGE_CONFIG.PORT}`);
} else {
logger.warning("\u25CB Bridge is not running");
}
} catch (error) {
logger.error("Error checking status:", error instanceof Error ? error.message : error);
process.exit(1);
}
});
bridge.command("kill").description("Kill the bridge process").action(async () => {
try {
const killed = await killBridge();
if (killed) {
logger.success("\u2713 Bridge process killed");
logger.dim("\nTip: The Chrome extension will restart it automatically when needed");
} else {
logger.warning("\u25CB No bridge process found");
}
} catch (error) {
logger.error("Error killing bridge:", error instanceof Error ? error.message : error);
process.exit(1);
}
});
bridge.command("restart").description("Restart the bridge process").action(async () => {
try {
logger.blue("\u27F3 Restarting bridge...");
logger.newline();
const lockCleaned = await cleanLockFile();
if (lockCleaned) {
logger.dim(" \u2713 Cleaned stale lock file");
}
const killed = await killBridge();
if (killed) {
logger.dim(" \u2713 Killed old process");
}
await new Promise((resolve) => setTimeout(resolve, 1e3));
logger.dim(" \u2713 Waiting for Chrome extension to restart it...");
logger.newline();
logger.warning("Please reload the Chrome extension at chrome://extensions/");
logger.dim("The extension will automatically start a new bridge instance");
logger.newline();
} catch (error) {
logger.error("Error restarting bridge:", error instanceof Error ? error.message : error);
process.exit(1);
}
});
return bridge;
}
async function checkBridgeStatus() {
try {
const { stdout } = await execAsync(`lsof -i :${BRIDGE_CONFIG.PORT} -t`);
const pid = parseInt(stdout.trim(), 10);
if (pid) {
return { running: true, pid };
}
} catch {
}
return { running: false };
}
async function killBridge() {
try {
const { stdout } = await execAsync(`lsof -i :${BRIDGE_CONFIG.PORT} -t`);
const pid = stdout.trim();
if (pid) {
await execAsync(`kill -9 ${pid}`);
return true;
}
} catch {
}
return false;
}
async function cleanLockFile() {
if (!existsSync(FILES_CONFIG.BRIDGE_LOCK_FILE)) {
return false;
}
try {
const lockContent = readFileSync(FILES_CONFIG.BRIDGE_LOCK_FILE, "utf-8").trim();
let pid;
try {
const lockData = JSON.parse(lockContent);
pid = lockData.pid;
} catch {
pid = parseInt(lockContent, 10);
}
try {
process.kill(pid, 0);
return false;
} catch {
unlinkSync(FILES_CONFIG.BRIDGE_LOCK_FILE);
return true;
}
} catch {
try {
unlinkSync(FILES_CONFIG.BRIDGE_LOCK_FILE);
return true;
} catch {
return false;
}
}
}
export {
createBridgeCommand
};