Files
Sauci/.codex/skills/dev-browser/scripts/start-server.ts
T
jjbrunton 8d4d9d8750 refactor(swipe): split swipe screen modules
Move swipe screen logic into hooks/services and extract
state-specific UI components to keep files small while
preserving existing behavior.

Reference: US-002
2026-01-25 21:05:54 +00:00

118 lines
3.6 KiB
TypeScript

import { serve } from "@/index.js";
import { execSync } from "child_process";
import { mkdirSync, existsSync, readdirSync } from "fs";
import { join, dirname } from "path";
import { fileURLToPath } from "url";
const __dirname = dirname(fileURLToPath(import.meta.url));
const tmpDir = join(__dirname, "..", "tmp");
const profileDir = join(__dirname, "..", "profiles");
// Create tmp and profile directories if they don't exist
console.log("Creating tmp directory...");
mkdirSync(tmpDir, { recursive: true });
console.log("Creating profiles directory...");
mkdirSync(profileDir, { recursive: true });
// Install Playwright browsers if not already installed
console.log("Checking Playwright browser installation...");
function findPackageManager(): { name: string; command: string } | null {
const managers = [
{ name: "bun", command: "bunx playwright install chromium" },
{ name: "pnpm", command: "pnpm exec playwright install chromium" },
{ name: "npm", command: "npx playwright install chromium" },
];
for (const manager of managers) {
try {
execSync(`which ${manager.name}`, { stdio: "ignore" });
return manager;
} catch {
// Package manager not found, try next
}
}
return null;
}
function isChromiumInstalled(): boolean {
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
const playwrightCacheDir = join(homeDir, ".cache", "ms-playwright");
if (!existsSync(playwrightCacheDir)) {
return false;
}
// Check for chromium directories (e.g., chromium-1148, chromium_headless_shell-1148)
try {
const entries = readdirSync(playwrightCacheDir);
return entries.some((entry) => entry.startsWith("chromium"));
} catch {
return false;
}
}
try {
if (!isChromiumInstalled()) {
console.log("Playwright Chromium not found. Installing (this may take a minute)...");
const pm = findPackageManager();
if (!pm) {
throw new Error("No package manager found (tried bun, pnpm, npm)");
}
console.log(`Using ${pm.name} to install Playwright...`);
execSync(pm.command, { stdio: "inherit" });
console.log("Chromium installed successfully.");
} else {
console.log("Playwright Chromium already installed.");
}
} catch (error) {
console.error("Failed to install Playwright browsers:", error);
console.log("You may need to run: npx playwright install chromium");
}
// Check if server is already running
console.log("Checking for existing servers...");
try {
const res = await fetch("http://localhost:9222", {
signal: AbortSignal.timeout(1000),
});
if (res.ok) {
console.log("Server already running on port 9222");
process.exit(0);
}
} catch {
// Server not running, continue to start
}
// Clean up stale CDP port if HTTP server isn't running (crash recovery)
// This handles the case where Node crashed but Chrome is still running on 9223
try {
const pid = execSync("lsof -ti:9223", { encoding: "utf-8" }).trim();
if (pid) {
console.log(`Cleaning up stale Chrome process on CDP port 9223 (PID: ${pid})`);
execSync(`kill -9 ${pid}`);
}
} catch {
// No process on CDP port, which is expected
}
console.log("Starting dev browser server...");
const headless = process.env.HEADLESS === "true";
const server = await serve({
port: 9222,
headless,
profileDir,
});
console.log(`Dev browser server started`);
console.log(` WebSocket: ${server.wsEndpoint}`);
console.log(` Tmp directory: ${tmpDir}`);
console.log(` Profile directory: ${profileDir}`);
console.log(`\nReady`);
console.log(`\nPress Ctrl+C to stop`);
// Keep the process running
await new Promise(() => {});