scripts
This commit is contained in:
+162
-100
@@ -22,7 +22,9 @@ function listSessions(): string[] {
|
||||
const pid = parseInt(fs.readFileSync(pidFile, 'utf8').trim(), 10);
|
||||
process.kill(pid, 0);
|
||||
sessions.push(match[1]);
|
||||
} catch { /* Process not running */ }
|
||||
} catch {
|
||||
/* Process not running */
|
||||
}
|
||||
}
|
||||
}
|
||||
return sessions;
|
||||
@@ -134,14 +136,14 @@ function printResponse(response: Response, jsonMode: boolean): void {
|
||||
console.log(JSON.stringify(response));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!response.success) {
|
||||
console.error(c('red', '✗ Error:'), response.error);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
||||
const data = response.data as Record<string, unknown>;
|
||||
|
||||
|
||||
if (data.url && data.title) {
|
||||
console.log(c('green', '✓'), c('bold', data.title as string));
|
||||
console.log(c('dim', ` ${data.url}`));
|
||||
@@ -178,10 +180,10 @@ function printResponse(response: Response, jsonMode: boolean): void {
|
||||
} else if (data.cookies) {
|
||||
const cookies = data.cookies as Array<{ name: string; value: string }>;
|
||||
if (cookies.length === 0) console.log(c('dim', 'No cookies'));
|
||||
else cookies.forEach(ck => console.log(`${c('cyan', ck.name)}: ${ck.value}`));
|
||||
else cookies.forEach((ck) => console.log(`${c('cyan', ck.name)}: ${ck.value}`));
|
||||
} else if (data.tabs) {
|
||||
const tabs = data.tabs as Array<{ index: number; url: string; title: string; active: boolean }>;
|
||||
tabs.forEach(t => {
|
||||
tabs.forEach((t) => {
|
||||
const marker = t.active ? c('green', '→') : ' ';
|
||||
console.log(`${marker} [${t.index}] ${t.title || c('dim', '(untitled)')}`);
|
||||
if (t.url) console.log(c('dim', ` ${t.url}`));
|
||||
@@ -191,18 +193,19 @@ function printResponse(response: Response, jsonMode: boolean): void {
|
||||
} else if (data.messages) {
|
||||
const msgs = data.messages as Array<{ type: string; text: string }>;
|
||||
if (msgs.length === 0) console.log(c('dim', 'No messages'));
|
||||
else msgs.forEach(m => {
|
||||
const col = m.type === 'error' ? 'red' : m.type === 'warning' ? 'yellow' : 'dim';
|
||||
console.log(`${c(col, `[${m.type}]`)} ${m.text}`);
|
||||
});
|
||||
else
|
||||
msgs.forEach((m) => {
|
||||
const col = m.type === 'error' ? 'red' : m.type === 'warning' ? 'yellow' : 'dim';
|
||||
console.log(`${c(col, `[${m.type}]`)} ${m.text}`);
|
||||
});
|
||||
} else if (data.errors) {
|
||||
const errs = data.errors as Array<{ message: string }>;
|
||||
if (errs.length === 0) console.log(c('dim', 'No errors'));
|
||||
else errs.forEach(e => console.log(c('red', '✗'), e.message));
|
||||
else errs.forEach((e) => console.log(c('red', '✗'), e.message));
|
||||
} else if (data.requests) {
|
||||
const reqs = data.requests as Array<{ method: string; url: string }>;
|
||||
if (reqs.length === 0) console.log(c('dim', 'No requests'));
|
||||
else reqs.forEach(r => console.log(`${c('cyan', r.method)} ${r.url}`));
|
||||
else reqs.forEach((r) => console.log(`${c('cyan', r.method)} ${r.url}`));
|
||||
} else if (data.moved) {
|
||||
console.log(c('green', '✓'), `Moved to (${data.x}, ${data.y})`);
|
||||
} else if (data.body !== undefined && data.status !== undefined) {
|
||||
@@ -225,7 +228,28 @@ function printResponse(response: Response, jsonMode: boolean): void {
|
||||
console.log(c('green', '✓'), 'Browser launched');
|
||||
} else if (data.state) {
|
||||
console.log(c('green', '✓'), `Load state: ${data.state}`);
|
||||
} else if (Object.keys(data).some(k => ['clicked', 'typed', 'filled', 'pressed', 'hovered', 'scrolled', 'selected', 'waited', 'checked', 'unchecked', 'focused', 'set', 'cleared', 'started', 'down', 'up'].includes(k))) {
|
||||
} else if (
|
||||
Object.keys(data).some((k) =>
|
||||
[
|
||||
'clicked',
|
||||
'typed',
|
||||
'filled',
|
||||
'pressed',
|
||||
'hovered',
|
||||
'scrolled',
|
||||
'selected',
|
||||
'waited',
|
||||
'checked',
|
||||
'unchecked',
|
||||
'focused',
|
||||
'set',
|
||||
'cleared',
|
||||
'started',
|
||||
'down',
|
||||
'up',
|
||||
].includes(k)
|
||||
)
|
||||
) {
|
||||
console.log(c('green', '✓'), 'Done');
|
||||
} else {
|
||||
console.log(c('green', '✓'), JSON.stringify(data));
|
||||
@@ -239,7 +263,7 @@ function printResponse(response: Response, jsonMode: boolean): void {
|
||||
async function handleGet(args: string[], id: string): Promise<Record<string, unknown>> {
|
||||
const what = args[0];
|
||||
const selector = args[1];
|
||||
|
||||
|
||||
switch (what) {
|
||||
case 'text':
|
||||
if (!selector) err('Selector required: veb get text <selector>');
|
||||
@@ -271,9 +295,9 @@ async function handleGet(args: string[], id: string): Promise<Record<string, unk
|
||||
async function handleIs(args: string[], id: string): Promise<Record<string, unknown>> {
|
||||
const what = args[0];
|
||||
const selector = args[1];
|
||||
|
||||
|
||||
if (!selector) err(`Selector required: veb is ${what} <selector>`);
|
||||
|
||||
|
||||
switch (what) {
|
||||
case 'visible':
|
||||
return { id, action: 'isvisible', selector };
|
||||
@@ -286,17 +310,21 @@ async function handleIs(args: string[], id: string): Promise<Record<string, unkn
|
||||
}
|
||||
}
|
||||
|
||||
async function handleFind(args: string[], id: string, flags: Flags): Promise<Record<string, unknown>> {
|
||||
async function handleFind(
|
||||
args: string[],
|
||||
id: string,
|
||||
flags: Flags
|
||||
): Promise<Record<string, unknown>> {
|
||||
const locator = args[0];
|
||||
const value = args[1];
|
||||
const subaction = args[2] || 'click';
|
||||
const fillValue = args[3];
|
||||
|
||||
|
||||
if (!value) err(`Value required: veb find ${locator} <value> <action>`);
|
||||
|
||||
|
||||
const exact = flags.exact;
|
||||
const name = flags.name;
|
||||
|
||||
|
||||
switch (locator) {
|
||||
case 'role':
|
||||
return { id, action: 'getbyrole', role: value, subaction, value: fillValue, name, exact };
|
||||
@@ -305,7 +333,14 @@ async function handleFind(args: string[], id: string, flags: Flags): Promise<Rec
|
||||
case 'label':
|
||||
return { id, action: 'getbylabel', label: value, subaction, value: fillValue, exact };
|
||||
case 'placeholder':
|
||||
return { id, action: 'getbyplaceholder', placeholder: value, subaction, value: fillValue, exact };
|
||||
return {
|
||||
id,
|
||||
action: 'getbyplaceholder',
|
||||
placeholder: value,
|
||||
subaction,
|
||||
value: fillValue,
|
||||
exact,
|
||||
};
|
||||
case 'alt':
|
||||
return { id, action: 'getbyalttext', text: value, subaction, exact };
|
||||
case 'title':
|
||||
@@ -325,13 +360,15 @@ async function handleFind(args: string[], id: string, flags: Flags): Promise<Rec
|
||||
return { id, action: 'nth', selector: sel, index: idx, subaction: act, value: val };
|
||||
}
|
||||
default:
|
||||
err(`Unknown locator: ${locator}. Options: role, text, label, placeholder, alt, title, testid, first, last, nth`);
|
||||
err(
|
||||
`Unknown locator: ${locator}. Options: role, text, label, placeholder, alt, title, testid, first, last, nth`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleMouse(args: string[], id: string): Promise<Record<string, unknown>> {
|
||||
const action = args[0];
|
||||
|
||||
|
||||
switch (action) {
|
||||
case 'move': {
|
||||
const x = parseInt(args[1], 10);
|
||||
@@ -355,7 +392,7 @@ async function handleMouse(args: string[], id: string): Promise<Record<string, u
|
||||
|
||||
async function handleSet(args: string[], id: string): Promise<Record<string, unknown>> {
|
||||
const setting = args[0];
|
||||
|
||||
|
||||
switch (setting) {
|
||||
case 'viewport': {
|
||||
const w = parseInt(args[1], 10);
|
||||
@@ -379,26 +416,42 @@ async function handleSet(args: string[], id: string): Promise<Record<string, unk
|
||||
if (!args[1]) err('Usage: veb set headers <json>');
|
||||
try {
|
||||
return { id, action: 'headers', headers: JSON.parse(args[1]) };
|
||||
} catch { err('Invalid JSON for headers'); }
|
||||
} catch {
|
||||
err('Invalid JSON for headers');
|
||||
}
|
||||
break;
|
||||
case 'credentials':
|
||||
case 'auth':
|
||||
if (!args[1] || !args[2]) err('Usage: veb set credentials <user> <pass>');
|
||||
return { id, action: 'credentials', username: args[1], password: args[2] };
|
||||
case 'media': {
|
||||
const colorScheme = args.includes('dark') ? 'dark' : args.includes('light') ? 'light' : undefined;
|
||||
const media = args.includes('print') ? 'print' : args.includes('screen') ? 'screen' : undefined;
|
||||
const colorScheme = args.includes('dark')
|
||||
? 'dark'
|
||||
: args.includes('light')
|
||||
? 'light'
|
||||
: undefined;
|
||||
const media = args.includes('print')
|
||||
? 'print'
|
||||
: args.includes('screen')
|
||||
? 'screen'
|
||||
: undefined;
|
||||
return { id, action: 'emulatemedia', colorScheme, media };
|
||||
}
|
||||
default:
|
||||
err(`Unknown: veb set ${setting}. Options: viewport, device, geo, offline, headers, credentials, media`);
|
||||
err(
|
||||
`Unknown: veb set ${setting}. Options: viewport, device, geo, offline, headers, credentials, media`
|
||||
);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
async function handleNetwork(args: string[], id: string, allArgs: string[]): Promise<Record<string, unknown>> {
|
||||
async function handleNetwork(
|
||||
args: string[],
|
||||
id: string,
|
||||
allArgs: string[]
|
||||
): Promise<Record<string, unknown>> {
|
||||
const action = args[0];
|
||||
|
||||
|
||||
switch (action) {
|
||||
case 'route': {
|
||||
const url = args[1];
|
||||
@@ -406,7 +459,13 @@ async function handleNetwork(args: string[], id: string, allArgs: string[]): Pro
|
||||
const abort = allArgs.includes('--abort');
|
||||
const bodyIdx = allArgs.indexOf('--body');
|
||||
const body = bodyIdx !== -1 ? allArgs[bodyIdx + 1] : undefined;
|
||||
return { id, action: 'route', url, abort, response: body ? { body, contentType: 'application/json' } : undefined };
|
||||
return {
|
||||
id,
|
||||
action: 'route',
|
||||
url,
|
||||
abort,
|
||||
response: body ? { body, contentType: 'application/json' } : undefined,
|
||||
};
|
||||
}
|
||||
case 'unroute':
|
||||
return { id, action: 'unroute', url: args[1] };
|
||||
@@ -425,11 +484,11 @@ async function handleNetwork(args: string[], id: string, allArgs: string[]): Pro
|
||||
async function handleStorage(args: string[], id: string): Promise<Record<string, unknown>> {
|
||||
const type = args[0] as 'local' | 'session';
|
||||
const sub = args[1];
|
||||
|
||||
|
||||
if (type !== 'local' && type !== 'session') {
|
||||
err('Usage: veb storage <local|session> [get|set|clear] [key] [value]');
|
||||
}
|
||||
|
||||
|
||||
if (sub === 'set') {
|
||||
if (!args[2] || !args[3]) err(`Usage: veb storage ${type} set <key> <value>`);
|
||||
return { id, action: 'storage_set', type, key: args[2], value: args[3] };
|
||||
@@ -443,12 +502,14 @@ async function handleStorage(args: string[], id: string): Promise<Record<string,
|
||||
|
||||
async function handleCookies(args: string[], id: string): Promise<Record<string, unknown>> {
|
||||
const sub = args[0];
|
||||
|
||||
|
||||
if (sub === 'set') {
|
||||
if (!args[1]) err('Usage: veb cookies set <json>');
|
||||
try {
|
||||
return { id, action: 'cookies_set', cookies: JSON.parse(args[1]) };
|
||||
} catch { err('Invalid JSON for cookies'); }
|
||||
} catch {
|
||||
err('Invalid JSON for cookies');
|
||||
}
|
||||
} else if (sub === 'clear') {
|
||||
return { id, action: 'cookies_clear' };
|
||||
} else {
|
||||
@@ -459,7 +520,7 @@ async function handleCookies(args: string[], id: string): Promise<Record<string,
|
||||
|
||||
async function handleTab(args: string[], id: string): Promise<Record<string, unknown>> {
|
||||
const sub = args[0];
|
||||
|
||||
|
||||
if (sub === 'new') {
|
||||
return { id, action: 'tab_new' };
|
||||
} else if (sub === 'list' || sub === 'ls' || !sub) {
|
||||
@@ -476,7 +537,7 @@ async function handleTab(args: string[], id: string): Promise<Record<string, unk
|
||||
|
||||
async function handleTrace(args: string[], id: string): Promise<Record<string, unknown>> {
|
||||
const sub = args[0];
|
||||
|
||||
|
||||
if (sub === 'start') {
|
||||
return { id, action: 'trace_start', screenshots: true, snapshots: true };
|
||||
} else if (sub === 'stop') {
|
||||
@@ -491,7 +552,7 @@ async function handleTrace(args: string[], id: string): Promise<Record<string, u
|
||||
async function handleState(args: string[], id: string): Promise<Record<string, unknown>> {
|
||||
const sub = args[0];
|
||||
const path = args[1];
|
||||
|
||||
|
||||
if (sub === 'save') {
|
||||
if (!path) err('Usage: veb state save <path>');
|
||||
return { id, action: 'state_save', path };
|
||||
@@ -531,13 +592,13 @@ function parseFlags(args: string[]): { flags: Flags; cleanArgs: string[] } {
|
||||
session: process.env.VEB_SESSION || 'default',
|
||||
exact: false,
|
||||
};
|
||||
|
||||
|
||||
const cleanArgs: string[] = [];
|
||||
let i = 0;
|
||||
|
||||
|
||||
while (i < args.length) {
|
||||
const arg = args[i];
|
||||
|
||||
|
||||
if (arg === '--json') {
|
||||
flags.json = true;
|
||||
} else if (arg === '--full' || arg === '-f') {
|
||||
@@ -565,7 +626,7 @@ function parseFlags(args: string[]): { flags: Flags; cleanArgs: string[] } {
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
return { flags, cleanArgs };
|
||||
}
|
||||
|
||||
@@ -576,21 +637,21 @@ function parseFlags(args: string[]): { flags: Flags; cleanArgs: string[] } {
|
||||
async function main(): Promise<void> {
|
||||
const rawArgs = process.argv.slice(2);
|
||||
const { flags, cleanArgs } = parseFlags(rawArgs);
|
||||
|
||||
|
||||
if (flags.debug) setDebug(true);
|
||||
setSession(flags.session);
|
||||
|
||||
|
||||
if (cleanArgs.length === 0 || rawArgs.includes('--help') || rawArgs.includes('-h')) {
|
||||
printHelp();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
|
||||
const command = cleanArgs[0];
|
||||
const args = cleanArgs.slice(1);
|
||||
const id = genId();
|
||||
|
||||
|
||||
let cmd: Record<string, unknown>;
|
||||
|
||||
|
||||
switch (command) {
|
||||
// === Core Commands ===
|
||||
case 'open':
|
||||
@@ -601,85 +662,85 @@ async function main(): Promise<void> {
|
||||
cmd = { id, action: 'navigate', url };
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'click':
|
||||
if (!args[0]) err('Selector required');
|
||||
cmd = { id, action: 'click', selector: args[0] };
|
||||
break;
|
||||
|
||||
|
||||
case 'dblclick':
|
||||
if (!args[0]) err('Selector required');
|
||||
cmd = { id, action: 'dblclick', selector: args[0] };
|
||||
break;
|
||||
|
||||
|
||||
case 'type':
|
||||
if (!args[0] || !args[1]) err('Usage: veb type <selector> <text>');
|
||||
cmd = { id, action: 'type', selector: args[0], text: args.slice(1).join(' ') };
|
||||
break;
|
||||
|
||||
|
||||
case 'fill':
|
||||
if (!args[0] || !args[1]) err('Usage: veb fill <selector> <text>');
|
||||
cmd = { id, action: 'fill', selector: args[0], value: args.slice(1).join(' ') };
|
||||
break;
|
||||
|
||||
|
||||
case 'press':
|
||||
case 'key':
|
||||
if (!args[0]) err('Key required');
|
||||
cmd = { id, action: 'press', key: args[0] };
|
||||
break;
|
||||
|
||||
|
||||
case 'keydown':
|
||||
if (!args[0]) err('Key required');
|
||||
cmd = { id, action: 'keydown', key: args[0] };
|
||||
break;
|
||||
|
||||
|
||||
case 'keyup':
|
||||
if (!args[0]) err('Key required');
|
||||
cmd = { id, action: 'keyup', key: args[0] };
|
||||
break;
|
||||
|
||||
|
||||
case 'hover':
|
||||
if (!args[0]) err('Selector required');
|
||||
cmd = { id, action: 'hover', selector: args[0] };
|
||||
break;
|
||||
|
||||
|
||||
case 'focus':
|
||||
if (!args[0]) err('Selector required');
|
||||
cmd = { id, action: 'focus', selector: args[0] };
|
||||
break;
|
||||
|
||||
|
||||
case 'check':
|
||||
if (!args[0]) err('Selector required');
|
||||
cmd = { id, action: 'check', selector: args[0] };
|
||||
break;
|
||||
|
||||
|
||||
case 'uncheck':
|
||||
if (!args[0]) err('Selector required');
|
||||
cmd = { id, action: 'uncheck', selector: args[0] };
|
||||
break;
|
||||
|
||||
|
||||
case 'select':
|
||||
if (!args[0] || !args[1]) err('Usage: veb select <selector> <value>');
|
||||
cmd = { id, action: 'select', selector: args[0], value: args[1] };
|
||||
break;
|
||||
|
||||
|
||||
case 'drag':
|
||||
if (!args[0] || !args[1]) err('Usage: veb drag <source> <target>');
|
||||
cmd = { id, action: 'drag', source: args[0], target: args[1] };
|
||||
break;
|
||||
|
||||
|
||||
case 'upload':
|
||||
if (!args[0] || !args[1]) err('Usage: veb upload <selector> <files...>');
|
||||
cmd = { id, action: 'upload', selector: args[0], files: args.slice(1) };
|
||||
break;
|
||||
|
||||
|
||||
case 'scroll': {
|
||||
const dir = args[0] || 'down';
|
||||
const amount = parseInt(args[1], 10) || 300;
|
||||
cmd = { id, action: 'scroll', direction: dir, amount, selector: flags.selector };
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'wait': {
|
||||
const target = args[0];
|
||||
// Check for flags
|
||||
@@ -701,83 +762,83 @@ async function main(): Promise<void> {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'screenshot': {
|
||||
const path = args[0];
|
||||
cmd = { id, action: 'screenshot', path, fullPage: flags.full, selector: flags.selector };
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'pdf':
|
||||
if (!args[0]) err('Path required');
|
||||
cmd = { id, action: 'pdf', path: args[0] };
|
||||
break;
|
||||
|
||||
|
||||
case 'snapshot':
|
||||
cmd = { id, action: 'snapshot' };
|
||||
break;
|
||||
|
||||
|
||||
case 'eval':
|
||||
if (!args[0]) err('Script required');
|
||||
cmd = { id, action: 'evaluate', script: args.join(' ') };
|
||||
break;
|
||||
|
||||
|
||||
case 'close':
|
||||
case 'quit':
|
||||
case 'exit':
|
||||
cmd = { id, action: 'close' };
|
||||
break;
|
||||
|
||||
|
||||
// === Navigation ===
|
||||
case 'back':
|
||||
cmd = { id, action: 'back' };
|
||||
break;
|
||||
|
||||
|
||||
case 'forward':
|
||||
cmd = { id, action: 'forward' };
|
||||
break;
|
||||
|
||||
|
||||
case 'reload':
|
||||
cmd = { id, action: 'reload' };
|
||||
break;
|
||||
|
||||
|
||||
// === Grouped Commands ===
|
||||
case 'get':
|
||||
cmd = await handleGet(args, id);
|
||||
break;
|
||||
|
||||
|
||||
case 'is':
|
||||
cmd = await handleIs(args, id);
|
||||
break;
|
||||
|
||||
|
||||
case 'find':
|
||||
cmd = await handleFind(args, id, flags);
|
||||
break;
|
||||
|
||||
|
||||
case 'mouse':
|
||||
cmd = await handleMouse(args, id);
|
||||
break;
|
||||
|
||||
|
||||
case 'set':
|
||||
cmd = await handleSet(args, id);
|
||||
break;
|
||||
|
||||
|
||||
case 'network':
|
||||
cmd = await handleNetwork(args, id, rawArgs);
|
||||
break;
|
||||
|
||||
|
||||
case 'storage':
|
||||
cmd = await handleStorage(args, id);
|
||||
break;
|
||||
|
||||
|
||||
case 'cookies':
|
||||
cmd = await handleCookies(args, id);
|
||||
break;
|
||||
|
||||
|
||||
case 'tab':
|
||||
cmd = await handleTab(args, id);
|
||||
break;
|
||||
|
||||
|
||||
case 'window':
|
||||
if (args[0] === 'new') {
|
||||
cmd = { id, action: 'window_new' };
|
||||
@@ -785,7 +846,7 @@ async function main(): Promise<void> {
|
||||
err('Usage: veb window new');
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'frame':
|
||||
if (!args[0]) err('Selector required');
|
||||
if (args[0] === 'main') {
|
||||
@@ -794,7 +855,7 @@ async function main(): Promise<void> {
|
||||
cmd = { id, action: 'frame', selector: args[0] };
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'dialog':
|
||||
if (args[0] === 'accept') {
|
||||
cmd = { id, action: 'dialog', response: 'accept', promptText: args[1] };
|
||||
@@ -804,59 +865,60 @@ async function main(): Promise<void> {
|
||||
err('Usage: veb dialog accept|dismiss');
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'trace':
|
||||
cmd = await handleTrace(args, id);
|
||||
break;
|
||||
|
||||
|
||||
case 'state':
|
||||
cmd = await handleState(args, id);
|
||||
break;
|
||||
|
||||
|
||||
case 'console':
|
||||
cmd = { id, action: 'console', clear: rawArgs.includes('--clear') };
|
||||
break;
|
||||
|
||||
|
||||
case 'errors':
|
||||
cmd = { id, action: 'errors', clear: rawArgs.includes('--clear') };
|
||||
break;
|
||||
|
||||
|
||||
case 'highlight':
|
||||
if (!args[0]) err('Selector required');
|
||||
cmd = { id, action: 'highlight', selector: args[0] };
|
||||
break;
|
||||
|
||||
|
||||
case 'scrollintoview':
|
||||
case 'scrollinto':
|
||||
if (!args[0]) err('Selector required');
|
||||
cmd = { id, action: 'scrollintoview', selector: args[0] };
|
||||
break;
|
||||
|
||||
|
||||
case 'initscript':
|
||||
if (!args[0]) err('Script required');
|
||||
cmd = { id, action: 'addinitscript', script: args.join(' ') };
|
||||
break;
|
||||
|
||||
|
||||
case 'inserttext':
|
||||
case 'insert':
|
||||
if (!args[0]) err('Text required');
|
||||
cmd = { id, action: 'inserttext', text: args.join(' ') };
|
||||
break;
|
||||
|
||||
|
||||
case 'multiselect':
|
||||
if (!args[0] || args.length < 2) err('Usage: veb multiselect <selector> <value1> [value2...]');
|
||||
if (!args[0] || args.length < 2)
|
||||
err('Usage: veb multiselect <selector> <value1> [value2...]');
|
||||
cmd = { id, action: 'multiselect', selector: args[0], values: args.slice(1) };
|
||||
break;
|
||||
|
||||
|
||||
case 'download':
|
||||
cmd = { id, action: 'waitfordownload', path: args[0] };
|
||||
break;
|
||||
|
||||
|
||||
case 'response':
|
||||
if (!args[0]) err('URL pattern required');
|
||||
cmd = { id, action: 'responsebody', url: args[0] };
|
||||
break;
|
||||
|
||||
|
||||
case 'session':
|
||||
if (args[0] === 'list' || args[0] === 'ls') {
|
||||
const sessions = listSessions();
|
||||
@@ -864,7 +926,7 @@ async function main(): Promise<void> {
|
||||
if (sessions.length === 0) {
|
||||
console.log(c('dim', 'No active sessions'));
|
||||
} else {
|
||||
sessions.forEach(s => {
|
||||
sessions.forEach((s) => {
|
||||
const marker = s === current ? c('green', '→') : ' ';
|
||||
console.log(`${marker} ${c('cyan', s)}`);
|
||||
});
|
||||
@@ -874,7 +936,7 @@ async function main(): Promise<void> {
|
||||
console.log(c('cyan', getSession()));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
|
||||
// === Legacy aliases for backwards compatibility ===
|
||||
case 'url':
|
||||
cmd = { id, action: 'url' };
|
||||
@@ -888,13 +950,13 @@ async function main(): Promise<void> {
|
||||
case 'extract':
|
||||
cmd = { id, action: 'content', selector: args[0] };
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
console.error(c('red', 'Unknown command:'), command);
|
||||
console.error(c('dim', 'Run: veb --help'));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const response = await send(cmd);
|
||||
printResponse(response, flags.json);
|
||||
|
||||
Reference in New Issue
Block a user