UNPKG

browse

Version:

Unified Browserbase CLI for browser automation and cloud APIs.

104 lines (103 loc) 3.52 kB
import { Flags } from "@oclif/core"; import { autoConnectFlag, cdpFlag, headedFlag, headlessFlag, localFlag, remoteFlag, sessionFlag, sessionName, targetIdFlag, } from "./flags.js"; import { getDriverStatus } from "./daemon/client.js"; import { resolveConnectionTarget } from "./mode.js"; import { outputJson } from "../output.js"; import { runDriverCommandWithTarget } from "./runtime.js"; export const driverCommandFlags = { "auto-connect": autoConnectFlag, cdp: cdpFlag, headed: headedFlag, headless: headlessFlag, local: localFlag, remote: remoteFlag, session: sessionFlag, "target-id": targetIdFlag, }; export const waitUntilFlag = Flags.string({ default: "load", description: "Load state to wait for before returning.", helpValue: "<state>", options: ["load", "domcontentloaded", "networkidle"], }); export const timeoutMsFlag = Flags.integer({ default: 30_000, description: "Timeout in milliseconds.", helpValue: "<ms>", }); export const buttonFlag = Flags.string({ default: "left", description: "Mouse button to use.", helpValue: "<button>", options: ["left", "middle", "right"], }); export async function runDriverCommandFromFlags(command, params, flags) { const session = sessionName(flags.session); const target = await resolveTargetForCommand(session, flags); outputJson(await runDriverCommandWithTarget(session, target, command, params)); } export async function resolveTargetForCommand(session, flags) { const hasExplicitTarget = hasExplicitDriverTarget(flags); if (!hasExplicitTarget || hasModeOnlyFlag(flags)) { const status = await getDriverStatus(session); if (status?.target && (!hasExplicitTarget || targetMatchesRequestedMode(status.target, flags))) { return status.target; } } return resolveConnectionTarget(flags); } export function hasExplicitDriverTarget(flags) { return Boolean(flags.local || flags.remote || flags["auto-connect"] || flags.cdp || flags["target-id"] || flags.headed || flags.headless); } function hasModeOnlyFlag(flags) { return Boolean((flags.local || flags.remote) && !flags["auto-connect"] && !flags.cdp && !flags["target-id"] && !flags.headed && !flags.headless && flags.local !== flags.remote); } function targetMatchesRequestedMode(target, flags) { if (flags.local) return target.kind === "managed-local"; if (flags.remote) return target.kind === "remote"; return false; } export function parseClip(value) { if (!value) return undefined; const match = value.match(/^(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?),(\d+(?:\.\d+)?),(\d+(?:\.\d+)?)$/); if (!match) { throw new Error("Invalid clip. Use x,y,width,height, for example 0,0,800,600."); } const [, x, y, width, height] = match; return { height: Number.parseFloat(height), width: Number.parseFloat(width), x: Number.parseFloat(x), y: Number.parseFloat(y), }; } export function parseNumber(value, name) { const number = Number(value); if (!Number.isFinite(number)) { throw new Error(`${name} must be a number.`); } return number; } export function parseInteger(value, name) { const number = parseNumber(value, name); if (!Number.isInteger(number)) { throw new Error(`${name} must be an integer.`); } return number; }