namastejs
Version:
A spiritual greeting from your JavaScript code. Because every function deserves a 'Namaste š'
121 lines (109 loc) ⢠3.5 kB
JavaScript
const { execSync } = require("child_process");
const os = require("os");
// Get readable process name on Windows
function getProcessNameWindows(pid) {
try {
const output = execSync(`tasklist /FI "PID eq ${pid}"`, {
encoding: "utf-8",
});
const lines = output.split("\n").filter((line) => line.includes(pid));
if (lines.length > 0) {
return lines[0].split(/\s+/)[0]; // Get process name like node.exe
}
} catch {
return "unknown";
}
return "unknown";
}
// List ports for both Windows and Unix
function listPorts() {
const platform = os.platform();
const unique = new Map();
try {
if (platform === "win32") {
const output = execSync(`netstat -ano | findstr LISTENING`, {
encoding: "utf-8",
});
const lines = output.split("\n").filter(Boolean);
lines.forEach((line) => {
const match = line.match(/:(\d+)\s+.*LISTENING\s+(\d+)/);
if (match) {
const port = match[1];
const pid = match[2];
const key = `${port}-${pid}`;
if (!unique.has(key)) {
const command = getProcessNameWindows(pid);
unique.set(key, { port, pid, command });
}
}
});
} else {
const output = execSync(`lsof -iTCP -sTCP:LISTEN -Pn`, {
encoding: "utf-8",
});
const lines = output.split("\n").slice(1);
lines.forEach((line) => {
const parts = line.trim().split(/\s+/);
const portMatch = line.match(/:(\d+)->?/);
if (parts.length >= 2 && portMatch) {
const port = portMatch[1];
const pid = parts[1];
const command = parts[0];
const key = `${port}-${pid}`;
if (!unique.has(key)) {
unique.set(key, { port, pid, command });
}
}
});
}
} catch (err) {
console.error("ā Failed to list ports:", err.message);
}
return [...unique.values()];
}
// Kill a port on both platforms
function killPort(port) {
const platform = os.platform();
try {
if (platform === "win32") {
const pidLine = execSync(`netstat -ano | findstr :${port}`, {
encoding: "utf-8",
})
.split("\n")
.find((line) => line.includes("LISTENING"));
if (!pidLine) {
console.log(`ā ļø Port ${port} not found.`);
return;
}
const pid = pidLine.match(/:(\d+)\s+.*LISTENING\s+(\d+)/)[2];
execSync(`taskkill /PID ${pid} /F`);
} else {
execSync(`lsof -ti tcp:${port} | xargs kill -9`);
}
console.log(
`ā
Port ${port} has been freed. May your app rise in peace š`
);
} catch (err) {
console.error(`ā Couldn't kill port ${port}:`, err.message);
}
}
// CLI command logic
function portsCLI(args) {
const killFlag = args.find((arg) => arg.startsWith("--kill="));
if (killFlag) {
const port = killFlag.split("=")[1];
killPort(port);
} else {
const ports = listPorts();
if (ports.length === 0) {
console.log("⨠No active ports found. All is calm. š§āāļø");
} else {
console.log("š Active ports on your machine:\n");
ports.forEach((p) =>
console.log(`${p.port} ā ${p.command || "unknown"} (PID: ${p.pid})`)
);
console.log("\nš Use: npx namastejs ports --kill=PORT");
}
}
}
module.exports = { portsCLI };