Prettier had never been run in --check mode here before, so this had drifted across most files (markdown tables, long option() chains, line wrapping). Purely formatting, no logic changes - needed so a CI format:check gate can actually pass. Adds .prettierignore for pnpm-lock.yaml specifically: prettier's YAML formatter rewrites every quoted key (single -> double quotes) producing an ~8700-line diff of pure noise on a file pnpm itself owns the formatting of. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
70 lines
1.9 KiB
TypeScript
70 lines
1.9 KiB
TypeScript
import { spawn } from "node:child_process";
|
|
import net from "node:net";
|
|
|
|
export function isPortFree(host: string, port: number): Promise<boolean> {
|
|
return new Promise((resolve) => {
|
|
const socket = net.connect({ host, port, timeout: 500 });
|
|
socket.once("connect", () => {
|
|
socket.destroy();
|
|
resolve(false);
|
|
});
|
|
socket.once("timeout", () => {
|
|
socket.destroy();
|
|
resolve(true);
|
|
});
|
|
socket.once("error", () => {
|
|
resolve(true);
|
|
});
|
|
});
|
|
}
|
|
|
|
export async function waitUntilReady(
|
|
url: string,
|
|
timeoutMs: number,
|
|
intervalMs = 400,
|
|
): Promise<boolean> {
|
|
const deadline = Date.now() + timeoutMs;
|
|
while (Date.now() < deadline) {
|
|
try {
|
|
const response = await fetch(url, { signal: AbortSignal.timeout(1500) });
|
|
if (response.status === 200) return true;
|
|
} catch {
|
|
// not ready yet
|
|
}
|
|
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/** Single-shot check (not a poll loop, unlike `waitUntilReady`) for whether a triggershell server
|
|
* is already listening at `url` - used to decide whether `run` can go through the REST/WS API. */
|
|
export async function isServerReachable(url: string): Promise<boolean> {
|
|
try {
|
|
const response = await fetch(`${url}/api/healthz`, {
|
|
signal: AbortSignal.timeout(1000),
|
|
});
|
|
return response.status === 200;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export function openBrowser(url: string): void {
|
|
const command =
|
|
process.platform === "darwin"
|
|
? "open"
|
|
: process.platform === "win32"
|
|
? "start"
|
|
: "xdg-open";
|
|
const args = process.platform === "win32" ? ["", url] : [url];
|
|
try {
|
|
spawn(command, args, {
|
|
detached: true,
|
|
stdio: "ignore",
|
|
shell: process.platform === "win32",
|
|
}).unref();
|
|
} catch {
|
|
// best-effort - not fatal if no browser opener is available
|
|
}
|
|
}
|