| import type { Command } from "commander"; |
| import { danger } from "../globals.js"; |
| import { defaultRuntime } from "../runtime.js"; |
| import { callBrowserRequest, type BrowserParentOpts } from "./browser-cli-shared.js"; |
| import { inheritOptionFromParent } from "./command-options.js"; |
|
|
| function resolveUrl(opts: { url?: string }, command: Command): string | undefined { |
| if (typeof opts.url === "string" && opts.url.trim()) { |
| return opts.url.trim(); |
| } |
| const inherited = inheritOptionFromParent<string>(command, "url"); |
| if (typeof inherited === "string" && inherited.trim()) { |
| return inherited.trim(); |
| } |
| return undefined; |
| } |
|
|
| function resolveTargetId(rawTargetId: unknown, command: Command): string | undefined { |
| const local = typeof rawTargetId === "string" ? rawTargetId.trim() : ""; |
| if (local) { |
| return local; |
| } |
| const inherited = inheritOptionFromParent<string>(command, "targetId"); |
| if (typeof inherited !== "string") { |
| return undefined; |
| } |
| const trimmed = inherited.trim(); |
| return trimmed ? trimmed : undefined; |
| } |
|
|
| async function runMutationRequest(params: { |
| parent: BrowserParentOpts; |
| request: Parameters<typeof callBrowserRequest>[1]; |
| successMessage: string; |
| }) { |
| try { |
| const result = await callBrowserRequest(params.parent, params.request, { timeoutMs: 20000 }); |
| if (params.parent?.json) { |
| defaultRuntime.log(JSON.stringify(result, null, 2)); |
| return; |
| } |
| defaultRuntime.log(params.successMessage); |
| } catch (err) { |
| defaultRuntime.error(danger(String(err))); |
| defaultRuntime.exit(1); |
| } |
| } |
|
|
| export function registerBrowserCookiesAndStorageCommands( |
| browser: Command, |
| parentOpts: (cmd: Command) => BrowserParentOpts, |
| ) { |
| const cookies = browser.command("cookies").description("Read/write cookies"); |
|
|
| cookies |
| .option("--target-id <id>", "CDP target id (or unique prefix)") |
| .action(async (opts, cmd) => { |
| const parent = parentOpts(cmd); |
| const profile = parent?.browserProfile; |
| const targetId = resolveTargetId(opts.targetId, cmd); |
| try { |
| const result = await callBrowserRequest<{ cookies?: unknown[] }>( |
| parent, |
| { |
| method: "GET", |
| path: "/cookies", |
| query: { |
| targetId, |
| profile, |
| }, |
| }, |
| { timeoutMs: 20000 }, |
| ); |
| if (parent?.json) { |
| defaultRuntime.log(JSON.stringify(result, null, 2)); |
| return; |
| } |
| defaultRuntime.log(JSON.stringify(result.cookies ?? [], null, 2)); |
| } catch (err) { |
| defaultRuntime.error(danger(String(err))); |
| defaultRuntime.exit(1); |
| } |
| }); |
|
|
| cookies |
| .command("set") |
| .description("Set a cookie (requires --url or domain+path)") |
| .argument("<name>", "Cookie name") |
| .argument("<value>", "Cookie value") |
| .option("--url <url>", "Cookie URL scope (recommended)") |
| .option("--target-id <id>", "CDP target id (or unique prefix)") |
| .action(async (name: string, value: string, opts, cmd) => { |
| const parent = parentOpts(cmd); |
| const profile = parent?.browserProfile; |
| const targetId = resolveTargetId(opts.targetId, cmd); |
| const url = resolveUrl(opts, cmd); |
| if (!url) { |
| defaultRuntime.error(danger("Missing required --url option for cookies set")); |
| defaultRuntime.exit(1); |
| return; |
| } |
| await runMutationRequest({ |
| parent, |
| request: { |
| method: "POST", |
| path: "/cookies/set", |
| query: profile ? { profile } : undefined, |
| body: { |
| targetId, |
| cookie: { name, value, url }, |
| }, |
| }, |
| successMessage: `cookie set: ${name}`, |
| }); |
| }); |
|
|
| cookies |
| .command("clear") |
| .description("Clear all cookies") |
| .option("--target-id <id>", "CDP target id (or unique prefix)") |
| .action(async (opts, cmd) => { |
| const parent = parentOpts(cmd); |
| const profile = parent?.browserProfile; |
| const targetId = resolveTargetId(opts.targetId, cmd); |
| await runMutationRequest({ |
| parent, |
| request: { |
| method: "POST", |
| path: "/cookies/clear", |
| query: profile ? { profile } : undefined, |
| body: { |
| targetId, |
| }, |
| }, |
| successMessage: "cookies cleared", |
| }); |
| }); |
|
|
| const storage = browser.command("storage").description("Read/write localStorage/sessionStorage"); |
|
|
| function registerStorageKind(kind: "local" | "session") { |
| const cmd = storage.command(kind).description(`${kind}Storage commands`); |
|
|
| cmd |
| .command("get") |
| .description(`Get ${kind}Storage (all keys or one key)`) |
| .argument("[key]", "Key (optional)") |
| .option("--target-id <id>", "CDP target id (or unique prefix)") |
| .action(async (key: string | undefined, opts, cmd2) => { |
| const parent = parentOpts(cmd2); |
| const profile = parent?.browserProfile; |
| const targetId = resolveTargetId(opts.targetId, cmd2); |
| try { |
| const result = await callBrowserRequest<{ values?: Record<string, string> }>( |
| parent, |
| { |
| method: "GET", |
| path: `/storage/${kind}`, |
| query: { |
| key: key?.trim() || undefined, |
| targetId, |
| profile, |
| }, |
| }, |
| { timeoutMs: 20000 }, |
| ); |
| if (parent?.json) { |
| defaultRuntime.log(JSON.stringify(result, null, 2)); |
| return; |
| } |
| defaultRuntime.log(JSON.stringify(result.values ?? {}, null, 2)); |
| } catch (err) { |
| defaultRuntime.error(danger(String(err))); |
| defaultRuntime.exit(1); |
| } |
| }); |
|
|
| cmd |
| .command("set") |
| .description(`Set a ${kind}Storage key`) |
| .argument("<key>", "Key") |
| .argument("<value>", "Value") |
| .option("--target-id <id>", "CDP target id (or unique prefix)") |
| .action(async (key: string, value: string, opts, cmd2) => { |
| const parent = parentOpts(cmd2); |
| const profile = parent?.browserProfile; |
| const targetId = resolveTargetId(opts.targetId, cmd2); |
| await runMutationRequest({ |
| parent, |
| request: { |
| method: "POST", |
| path: `/storage/${kind}/set`, |
| query: profile ? { profile } : undefined, |
| body: { |
| key, |
| value, |
| targetId, |
| }, |
| }, |
| successMessage: `${kind}Storage set: ${key}`, |
| }); |
| }); |
|
|
| cmd |
| .command("clear") |
| .description(`Clear all ${kind}Storage keys`) |
| .option("--target-id <id>", "CDP target id (or unique prefix)") |
| .action(async (opts, cmd2) => { |
| const parent = parentOpts(cmd2); |
| const profile = parent?.browserProfile; |
| const targetId = resolveTargetId(opts.targetId, cmd2); |
| await runMutationRequest({ |
| parent, |
| request: { |
| method: "POST", |
| path: `/storage/${kind}/clear`, |
| query: profile ? { profile } : undefined, |
| body: { |
| targetId, |
| }, |
| }, |
| successMessage: `${kind}Storage cleared`, |
| }); |
| }); |
| } |
|
|
| registerStorageKind("local"); |
| registerStorageKind("session"); |
| } |
|
|