Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
86 lines
2.2 KiB
JavaScript
86 lines
2.2 KiB
JavaScript
/**
|
|
* Kill whatever is listening on the Descrybe dev ports so `npm run dev` can bind.
|
|
* Skip when DESCRYBE_DEV_PORTS_FREED=1 (parent already freed; children must not
|
|
* re-kill the just-started sibling).
|
|
*
|
|
* Usage: node scripts/free-dev-ports.mjs
|
|
*/
|
|
import { spawnSync } from "node:child_process";
|
|
import { pathToFileURL } from "node:url";
|
|
import { DEV_API_PORT, DEV_WEB_PORT } from "./dev-ports.mjs";
|
|
|
|
export function freeDevPorts(ports = [DEV_API_PORT, DEV_WEB_PORT]) {
|
|
if (process.env.DESCRYBE_DEV_PORTS_FREED === "1") {
|
|
return;
|
|
}
|
|
|
|
for (const port of ports) {
|
|
const pids = listenersOnPort(port);
|
|
if (pids.length === 0) {
|
|
console.log(`[dev-ports] ${port} free`);
|
|
continue;
|
|
}
|
|
for (const pid of pids) {
|
|
console.log(`[dev-ports] killing PID ${pid} on :${port}`);
|
|
killPidTree(pid);
|
|
}
|
|
}
|
|
}
|
|
|
|
function listenersOnPort(port) {
|
|
if (process.platform === "win32") {
|
|
const ps = [
|
|
`$conns = @(Get-NetTCPConnection -LocalPort ${port} -State Listen -ErrorAction SilentlyContinue);`,
|
|
`if ($conns.Count -eq 0) { exit 0 };`,
|
|
`$conns | ForEach-Object { $_.OwningProcess } | Sort-Object -Unique | ForEach-Object { Write-Output $_ }`,
|
|
].join(" ");
|
|
const r = spawnSync(
|
|
"powershell.exe",
|
|
["-NoProfile", "-NonInteractive", "-Command", ps],
|
|
{ encoding: "utf8" },
|
|
);
|
|
return parsePids(r.stdout || "");
|
|
}
|
|
|
|
const r = spawnSync("lsof", ["-tiTCP:" + port, "-sTCP:LISTEN"], {
|
|
encoding: "utf8",
|
|
});
|
|
if (r.status !== 0) return [];
|
|
return parsePids(r.stdout || "");
|
|
}
|
|
|
|
function parsePids(text) {
|
|
const seen = new Set();
|
|
const out = [];
|
|
for (const raw of text.split(/\r?\n/)) {
|
|
const n = Number.parseInt(raw.trim(), 10);
|
|
if (!Number.isFinite(n) || n <= 0 || seen.has(n)) continue;
|
|
if (n === process.pid) continue;
|
|
seen.add(n);
|
|
out.push(n);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
function killPidTree(pid) {
|
|
if (process.platform === "win32") {
|
|
spawnSync("taskkill.exe", ["/T", "/F", "/PID", String(pid)], {
|
|
stdio: "ignore",
|
|
});
|
|
return;
|
|
}
|
|
try {
|
|
process.kill(pid, "SIGKILL");
|
|
} catch {
|
|
/* already gone */
|
|
}
|
|
}
|
|
|
|
const isDirect =
|
|
process.argv[1] &&
|
|
import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
|
|
if (isDirect) {
|
|
freeDevPorts();
|
|
}
|