Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 09:05:55 +08:00
commit 89c3c1ab83
18 changed files with 1955 additions and 0 deletions

View File

@@ -0,0 +1,103 @@
#!/usr/bin/env node
import puppeteer from "puppeteer-core";
import {
DEFAULT_PORT,
createLogger,
fail,
getActivePage,
parseArgs,
printJSON,
resolveBrowserConnection,
normalizeNumber,
} from "./config.js";
const args = parseArgs(process.argv.slice(2), {
boolean: ["new", "json", "quiet"],
string: ["wait", "ws", "host"],
number: ["port", "timeout"],
alias: {
j: "json",
q: "quiet",
},
defaults: {
port: DEFAULT_PORT,
timeout: 30000,
wait: "domcontentloaded",
},
});
const url = args._[0];
if (!url) {
fail("Usage: navigate.js <url> [--new] [--wait=domcontentloaded|networkidle0|load|none]", {
json: Boolean(args.json),
});
}
const jsonOutput = Boolean(args.json);
const logger = createLogger({ quiet: Boolean(args.quiet), json: jsonOutput });
const waitStrategy = normalizeWait(args.wait);
if (!waitStrategy) {
fail("Invalid --wait value. Use domcontentloaded, networkidle0, load, or none.", { json: jsonOutput });
}
const timeout = normalizeNumber(args.timeout, 30000);
const port = normalizeNumber(args.port, DEFAULT_PORT);
logger.info(`🌐 Navigating to ${url}${args.new ? " (new tab)" : ""}...`);
const connectionOptions = resolveBrowserConnection({ port, host: args.host, ws: args.ws });
let browser;
try {
browser = await puppeteer.connect({
...connectionOptions,
timeout,
});
} catch (error) {
fail(`Failed to connect to browser: ${error.message}`, { json: jsonOutput });
}
try {
const page = args.new ? await browser.newPage() : await getExistingPage(browser);
if (!page) {
fail("No active page found. Start Chrome with start.js or use --new to open a tab.", { json: jsonOutput });
}
const gotoOptions = { timeout };
if (waitStrategy !== "none") {
gotoOptions.waitUntil = waitStrategy;
}
await page.goto(url, gotoOptions);
const currentURL = page.url();
if (jsonOutput) {
printJSON({ ok: true, url: currentURL, newPage: Boolean(args.new) });
} else {
process.stdout.write(`${JSON.stringify({ ok: true, url: currentURL, newPage: Boolean(args.new) })}\n`);
logger.info(`✅ Navigated to ${currentURL}`);
}
} catch (error) {
fail(`Navigation failed: ${error.message}`, { json: jsonOutput });
} finally {
if (browser) await browser.disconnect();
}
function normalizeWait(value) {
if (!value) return "domcontentloaded";
const normalized = String(value).toLowerCase();
if (["domcontentloaded", "networkidle0", "load", "none"].includes(normalized)) {
return normalized;
}
return null;
}
async function getExistingPage(browserInstance) {
const page = await getActivePage(browserInstance, { index: -1 });
return page;
}