chrome-cdp-cli 2.1.1 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,7 +10,7 @@ class OutputManager {
10
10
  this.currentOperation = {
11
11
  name: operationName,
12
12
  startTime: Date.now(),
13
- command
13
+ command,
14
14
  };
15
15
  }
16
16
  endOperation(result) {
@@ -23,17 +23,17 @@ class OutputManager {
23
23
  metadata = {
24
24
  command: this.currentOperation.command.name,
25
25
  args: this.currentOperation.command.args,
26
- config: this.currentOperation.command.config
26
+ config: this.currentOperation.command.config,
27
27
  };
28
28
  operationConfig = this.currentOperation.command.config;
29
29
  this.currentOperation = undefined;
30
30
  }
31
31
  else {
32
32
  operationConfig = {
33
- outputFormat: 'text',
33
+ outputFormat: "text",
34
34
  quiet: false,
35
35
  verbose: false,
36
- debug: false
36
+ debug: false,
37
37
  };
38
38
  }
39
39
  const enhancedResult = (0, OutputFormatter_1.enhanceCommandResult)(result, timing, metadata);
@@ -51,7 +51,7 @@ class OutputManager {
51
51
  const result = {
52
52
  success: false,
53
53
  error,
54
- exitCode
54
+ exitCode,
55
55
  };
56
56
  const options = (0, OutputFormatter_1.createOutputOptions)(config, false, false);
57
57
  return this.formatter.formatOutput(result, options);
@@ -59,7 +59,7 @@ class OutputManager {
59
59
  formatSuccess(config, data) {
60
60
  const result = {
61
61
  success: true,
62
- data
62
+ data,
63
63
  };
64
64
  const options = (0, OutputFormatter_1.createOutputOptions)(config, false, false);
65
65
  return this.formatter.formatOutput(result, options);
@@ -69,14 +69,16 @@ class OutputManager {
69
69
  name,
70
70
  description,
71
71
  template,
72
- variables
72
+ variables,
73
73
  });
74
74
  }
75
75
  getAvailableTemplates() {
76
76
  return this.formatter.getAvailableTemplates();
77
77
  }
78
78
  shouldSuppressOutput(config, result) {
79
- return config.quiet && result.success && (result.data === undefined || result.data === null);
79
+ return (config.quiet &&
80
+ result.success &&
81
+ (result.data === undefined || result.data === null));
80
82
  }
81
83
  getTimingInfo(startTime, endTime, operationName) {
82
84
  const duration = endTime - startTime;
@@ -84,14 +86,12 @@ class OutputManager {
84
86
  }
85
87
  formatDataSourceInfo(dataSource, hasHistoricalData) {
86
88
  if (!dataSource)
87
- return '';
88
- const sourceIcon = dataSource === 'proxy' ? 'šŸ“Š' : 'āš ļø';
89
- const sourceText = dataSource === 'proxy'
90
- ? 'Data from proxy server'
91
- : 'Data from direct connection';
89
+ return "";
90
+ const sourceIcon = "āš ļø";
91
+ const sourceText = "Data from direct connection";
92
92
  const historyText = hasHistoricalData
93
- ? '(includes historical data)'
94
- : '(new data only)';
93
+ ? "(includes historical data)"
94
+ : "(new data only)";
95
95
  return `${sourceIcon} ${sourceText} ${historyText}`;
96
96
  }
97
97
  createProgressIndicator(message) {
@@ -99,8 +99,8 @@ class OutputManager {
99
99
  }
100
100
  formatValidationErrors(errors) {
101
101
  if (errors.length === 0)
102
- return '';
103
- let output = 'āŒ Validation Errors:\n\n';
102
+ return "";
103
+ let output = "āŒ Validation Errors:\n\n";
104
104
  errors.forEach((error, index) => {
105
105
  output += `${index + 1}. ${error.field}: ${error.message}\n`;
106
106
  if (error.suggestion) {
@@ -112,7 +112,7 @@ class OutputManager {
112
112
  formatHelpInfo(title, content, examples) {
113
113
  let output = `šŸ“– ${title}\n\n${content}\n`;
114
114
  if (examples && examples.length > 0) {
115
- output += '\nšŸ’” Examples:\n';
115
+ output += "\nšŸ’” Examples:\n";
116
116
  examples.forEach((example, index) => {
117
117
  output += `${index + 1}. ${example}\n`;
118
118
  });
@@ -127,7 +127,7 @@ class ProgressIndicator {
127
127
  this.startTime = Date.now();
128
128
  }
129
129
  start() {
130
- const frames = ['ā ‹', 'ā ™', 'ā ¹', 'ā ø', 'ā ¼', 'ā “', 'ā ¦', 'ā §', 'ā ‡', 'ā '];
130
+ const frames = ["ā ‹", "ā ™", "ā ¹", "ā ø", "ā ¼", "ā “", "ā ¦", "ā §", "ā ‡", "ā "];
131
131
  let frameIndex = 0;
132
132
  this.interval = setInterval(() => {
133
133
  const elapsed = Date.now() - this.startTime;
@@ -141,7 +141,7 @@ class ProgressIndicator {
141
141
  clearInterval(this.interval);
142
142
  this.interval = undefined;
143
143
  }
144
- process.stdout.write('\r\x1b[K');
144
+ process.stdout.write("\r\x1b[K");
145
145
  }
146
146
  updateMessage(message) {
147
147
  this.message = message;
@@ -15,4 +15,3 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./CDPClient"), exports);
18
- __exportStar(require("./ProxyClient"), exports);
@@ -1,18 +1,11 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.EvaluateScriptHandler = void 0;
7
- const ProxyClient_1 = require("../client/ProxyClient");
8
4
  const logger_1 = require("../utils/logger");
9
5
  const fs_1 = require("fs");
10
- const node_fetch_1 = __importDefault(require("node-fetch"));
11
6
  class EvaluateScriptHandler {
12
- constructor(useProxy = false, debug = false) {
13
- this.name = 'eval';
14
- this.proxyClient = new ProxyClient_1.ProxyClient();
15
- this.useProxy = useProxy;
7
+ constructor(debug = false) {
8
+ this.name = "eval";
16
9
  this.logger = new logger_1.Logger();
17
10
  if (debug) {
18
11
  this.logger.setLevel(3);
@@ -22,55 +15,24 @@ class EvaluateScriptHandler {
22
15
  }
23
16
  }
24
17
  setDebug(debug) {
25
- if (debug) {
26
- this.logger.setLevel(3);
27
- }
28
- else {
29
- this.logger.setLevel(2);
30
- }
18
+ this.logger.setLevel(debug ? 3 : 2);
31
19
  }
32
20
  async execute(client, args) {
33
- this.logger.debug('EvaluateScriptHandler.execute called with args:', args);
21
+ this.logger.debug("EvaluateScriptHandler.execute called with args:", args);
34
22
  const scriptArgs = args;
35
23
  if (!scriptArgs.expression && !scriptArgs.file) {
36
24
  return {
37
25
  success: false,
38
- error: 'Either "expression" or "file" argument is required'
26
+ error: 'Either "expression" or "file" argument is required',
39
27
  };
40
28
  }
41
29
  if (scriptArgs.expression && scriptArgs.file) {
42
30
  return {
43
31
  success: false,
44
- error: 'Cannot specify both "expression" and "file" arguments'
32
+ error: 'Cannot specify both "expression" and "file" arguments',
45
33
  };
46
34
  }
47
- this.logger.debug('Arguments validated, useProxy:', this.useProxy);
48
35
  try {
49
- if (this.useProxy) {
50
- this.logger.debug('Checking proxy availability...');
51
- const proxyAvailable = await this.proxyClient.isProxyAvailable();
52
- this.logger.debug('Proxy available:', proxyAvailable);
53
- if (proxyAvailable) {
54
- console.log('[INFO] Using proxy connection for script evaluation');
55
- this.logger.debug('About to call executeWithProxy...');
56
- const result = await this.executeWithProxy(scriptArgs);
57
- this.logger.debug('executeWithProxy returned:', result);
58
- return result;
59
- }
60
- else {
61
- console.warn('[WARN] Proxy not available, falling back to direct CDP connection');
62
- }
63
- }
64
- }
65
- catch (error) {
66
- console.warn('[WARN] Proxy execution failed, falling back to direct CDP:', error instanceof Error ? error.message : error);
67
- }
68
- this.logger.debug('Falling back to direct CDP');
69
- return await this.executeWithDirectCDP(client, scriptArgs);
70
- }
71
- async executeWithProxy(scriptArgs) {
72
- try {
73
- this.logger.debug('Starting executeWithProxy');
74
36
  let expression;
75
37
  if (scriptArgs.file) {
76
38
  expression = await this.readScriptFile(scriptArgs.file);
@@ -78,128 +40,18 @@ class EvaluateScriptHandler {
78
40
  else {
79
41
  expression = scriptArgs.expression;
80
42
  }
81
- this.logger.debug('Expression to execute:', expression.substring(0, 100));
82
- this.logger.debug('Creating new proxy connection...');
83
- const connectionId = await this.proxyClient.connect('localhost', 9222);
84
- this.logger.debug(`Created new proxy connection: ${connectionId}`);
85
- try {
86
- const result = await this.executeScriptThroughHTTP(connectionId, expression, scriptArgs);
87
- return {
88
- success: true,
89
- data: result
90
- };
91
- }
92
- finally {
93
- await this.proxyClient.disconnect();
94
- }
43
+ return await this.executeWithTimeout(client, expression, scriptArgs);
95
44
  }
96
45
  catch (error) {
97
- this.logger.debug('Error in executeWithProxy:', error);
98
46
  return {
99
47
  success: false,
100
- error: error instanceof Error ? error.message : String(error)
101
- };
102
- }
103
- }
104
- async executeScriptThroughHTTP(connectionId, expression, args) {
105
- const timeout = args.timeout || 30000;
106
- const awaitPromise = args.awaitPromise ?? true;
107
- const returnByValue = args.returnByValue ?? true;
108
- console.log(`[DEBUG] Starting HTTP script execution, timeout: ${timeout}ms`);
109
- console.log(`[DEBUG] Expression: ${expression.substring(0, 100)}${expression.length > 100 ? '...' : ''}`);
110
- try {
111
- const proxyUrl = this.proxyClient.getConfig().proxyUrl;
112
- const commandId = Date.now() + Math.floor(Math.random() * 10000);
113
- const command = {
114
- id: commandId,
115
- method: 'Runtime.evaluate',
116
- params: {
117
- expression: expression,
118
- awaitPromise: awaitPromise,
119
- returnByValue: returnByValue,
120
- userGesture: true,
121
- generatePreview: false
122
- }
123
- };
124
- console.log(`[DEBUG] Sending HTTP command to ${proxyUrl}/api/execute/${connectionId}`);
125
- const controller = new AbortController();
126
- const timeoutHandle = setTimeout(() => controller.abort(), timeout);
127
- try {
128
- const response = await (0, node_fetch_1.default)(`${proxyUrl}/api/execute/${connectionId}`, {
129
- method: 'POST',
130
- headers: {
131
- 'Content-Type': 'application/json',
132
- 'x-client-id': `eval_handler_${Date.now()}`
133
- },
134
- body: JSON.stringify({
135
- command,
136
- timeout
137
- }),
138
- signal: controller.signal
139
- });
140
- clearTimeout(timeoutHandle);
141
- if (!response.ok) {
142
- const errorData = await response.json().catch(() => ({}));
143
- throw new Error(`HTTP ${response.status}: ${errorData.error || response.statusText}`);
144
- }
145
- const result = await response.json();
146
- console.log(`[DEBUG] HTTP command response:`, result);
147
- if (!result.success) {
148
- throw new Error(`Command execution failed: ${result.error || 'Unknown error'}`);
149
- }
150
- const commandResult = result.data.result;
151
- if (result.data.error) {
152
- throw new Error(`CDP Error: ${result.data.error.message}`);
153
- }
154
- if (commandResult.exceptionDetails) {
155
- console.log(`[DEBUG] Exception details:`, commandResult.exceptionDetails);
156
- const error = new Error(commandResult.result?.description || 'Script execution failed');
157
- error.exceptionDetails = commandResult.exceptionDetails;
158
- throw error;
159
- }
160
- let value = commandResult.result?.value;
161
- if (commandResult.result?.type === 'undefined') {
162
- value = '';
163
- }
164
- else if (commandResult.result?.unserializableValue) {
165
- value = commandResult.result.unserializableValue;
166
- }
167
- console.log(`[DEBUG] Successful HTTP result:`, value);
168
- return value;
169
- }
170
- catch (error) {
171
- clearTimeout(timeoutHandle);
172
- throw error;
173
- }
174
- }
175
- catch (error) {
176
- console.log(`[DEBUG] Error in HTTP script execution:`, error);
177
- throw error;
178
- }
179
- }
180
- async executeWithDirectCDP(client, scriptArgs) {
181
- try {
182
- let expression;
183
- if (scriptArgs.file) {
184
- expression = await this.readScriptFile(scriptArgs.file);
185
- }
186
- else {
187
- expression = scriptArgs.expression;
188
- }
189
- const result = await this.executeWithTimeout(client, expression, scriptArgs);
190
- return result;
191
- }
192
- catch (error) {
193
- return {
194
- success: false,
195
- error: error instanceof Error ? error.message : String(error)
48
+ error: error instanceof Error ? error.message : String(error),
196
49
  };
197
50
  }
198
51
  }
199
52
  async readScriptFile(filePath) {
200
53
  try {
201
- const content = await fs_1.promises.readFile(filePath, 'utf-8');
202
- return content;
54
+ return await fs_1.promises.readFile(filePath, "utf-8");
203
55
  }
204
56
  catch (error) {
205
57
  throw new Error(`Failed to read script file "${filePath}": ${error instanceof Error ? error.message : String(error)}`);
@@ -210,171 +62,133 @@ class EvaluateScriptHandler {
210
62
  const awaitPromise = args.awaitPromise ?? true;
211
63
  const returnByValue = args.returnByValue ?? true;
212
64
  const timeoutPromise = new Promise((_, reject) => {
213
- setTimeout(() => {
214
- reject(new Error(`Script execution timeout after ${timeout}ms`));
215
- }, timeout);
65
+ setTimeout(() => reject(new Error(`Script execution timeout after ${timeout}ms`)), timeout);
216
66
  });
217
67
  const executionPromise = this.executeScript(client, expression, awaitPromise, returnByValue);
218
68
  try {
219
- const result = await Promise.race([executionPromise, timeoutPromise]);
220
- return result;
69
+ return await Promise.race([executionPromise, timeoutPromise]);
221
70
  }
222
71
  catch (error) {
223
72
  return {
224
73
  success: false,
225
- error: error instanceof Error ? error.message : String(error)
74
+ error: error instanceof Error ? error.message : String(error),
226
75
  };
227
76
  }
228
77
  }
229
78
  async executeScript(client, expression, awaitPromise, returnByValue) {
230
- const consoleHandler = (params) => {
231
- this.handleConsoleOutput(params);
232
- };
233
- client.on('Runtime.consoleAPICalled', consoleHandler);
79
+ const consoleHandler = (params) => this.handleConsoleOutput(params);
80
+ client.on("Runtime.consoleAPICalled", consoleHandler);
234
81
  try {
235
- const response = (await client.send('Runtime.evaluate', {
82
+ const response = (await client.send("Runtime.evaluate", {
236
83
  expression,
237
84
  awaitPromise,
238
85
  returnByValue,
239
86
  userGesture: true,
240
- generatePreview: false
87
+ generatePreview: false,
241
88
  }));
242
89
  if (!response) {
243
- return {
244
- success: false,
245
- error: 'CDP returned empty response'
246
- };
90
+ return { success: false, error: "CDP returned empty response" };
247
91
  }
248
92
  if (response.exceptionDetails) {
249
93
  return this.formatException(response.exceptionDetails);
250
94
  }
251
95
  if (!response.result) {
252
- return {
253
- success: false,
254
- error: 'CDP response missing result field'
255
- };
96
+ return { success: false, error: "CDP response missing result field" };
256
97
  }
257
- return {
258
- success: true,
259
- data: this.formatResult(response.result)
260
- };
98
+ return { success: true, data: this.formatResult(response.result) };
261
99
  }
262
100
  catch (error) {
263
101
  return {
264
102
  success: false,
265
- error: `CDP command failed: ${error instanceof Error ? error.message : String(error)}`
103
+ error: `CDP command failed: ${error instanceof Error ? error.message : String(error)}`,
266
104
  };
267
105
  }
268
106
  finally {
269
- client.off('Runtime.consoleAPICalled', consoleHandler);
107
+ client.off("Runtime.consoleAPICalled", consoleHandler);
270
108
  }
271
109
  }
272
110
  handleConsoleOutput(params) {
273
111
  try {
274
- const consoleParams = params;
275
- const messageText = this.formatConsoleArgs(consoleParams.args || []);
276
- const messageType = this.mapConsoleType(consoleParams.type);
277
- if (messageType === 'log' || messageType === 'info' || messageType === 'debug') {
278
- process.stdout.write(messageText + '\n');
112
+ const p = params;
113
+ const text = (p.args || [])
114
+ .map((a) => a.value !== undefined
115
+ ? typeof a.value === "string"
116
+ ? a.value
117
+ : JSON.stringify(a.value)
118
+ : a.description || "")
119
+ .join(" ");
120
+ const type = this.mapConsoleType(p.type);
121
+ if (type === "warn" || type === "error") {
122
+ process.stderr.write(text + "\n");
279
123
  }
280
124
  else {
281
- process.stderr.write(messageText + '\n');
125
+ process.stdout.write(text + "\n");
282
126
  }
283
127
  }
284
- catch (error) {
285
- this.logger.debug('Error handling console output:', error);
128
+ catch {
286
129
  }
287
130
  }
288
- formatConsoleArgs(args) {
289
- return args.map(arg => {
290
- if (arg.value !== undefined) {
291
- if (typeof arg.value === 'string') {
292
- return arg.value;
293
- }
294
- return JSON.stringify(arg.value);
295
- }
296
- return arg.description || '';
297
- }).join(' ');
298
- }
299
131
  mapConsoleType(cdpType) {
300
132
  switch (cdpType) {
301
- case 'log':
302
- return 'log';
303
- case 'info':
304
- return 'info';
305
- case 'warning':
306
- return 'warn';
307
- case 'error':
308
- return 'error';
309
- case 'debug':
310
- return 'debug';
133
+ case "warning":
134
+ return "warn";
135
+ case "error":
136
+ return "error";
137
+ case "info":
138
+ return "info";
139
+ case "debug":
140
+ return "debug";
311
141
  default:
312
- return 'log';
142
+ return "log";
313
143
  }
314
144
  }
315
145
  formatException(exceptionDetails) {
316
146
  if (!exceptionDetails) {
317
- return {
318
- success: false,
319
- error: 'Unknown JavaScript error'
320
- };
147
+ return { success: false, error: "Unknown JavaScript error" };
321
148
  }
322
- const exception = exceptionDetails.exception;
323
- const errorMessage = exception?.description || exceptionDetails.text;
324
- let stackTrace = '';
149
+ const errorMessage = exceptionDetails.exception?.description || exceptionDetails.text;
150
+ let stackTrace = "";
325
151
  if (exceptionDetails.stackTrace?.callFrames) {
326
- stackTrace = '\nStack trace:\n' +
327
- exceptionDetails.stackTrace.callFrames
328
- .map(frame => ` at ${frame.functionName || '<anonymous>'} (${frame.url}:${frame.lineNumber}:${frame.columnNumber})`)
329
- .join('\n');
152
+ stackTrace =
153
+ "\nStack trace:\n" +
154
+ exceptionDetails.stackTrace.callFrames
155
+ .map((f) => ` at ${f.functionName || "<anonymous>"} (${f.url}:${f.lineNumber}:${f.columnNumber})`)
156
+ .join("\n");
330
157
  }
331
158
  return {
332
159
  success: false,
333
- error: `JavaScript error at line ${exceptionDetails.lineNumber}, column ${exceptionDetails.columnNumber}: ${errorMessage}${stackTrace}`
160
+ error: `JavaScript error at line ${exceptionDetails.lineNumber}, column ${exceptionDetails.columnNumber}: ${errorMessage}${stackTrace}`,
334
161
  };
335
162
  }
336
163
  formatResult(result) {
337
- if (!result) {
338
- return '';
339
- }
340
- if (result.type === 'undefined') {
341
- return '';
342
- }
343
- if (result.value !== undefined) {
164
+ if (!result || result.type === "undefined")
165
+ return "";
166
+ if (result.value !== undefined)
344
167
  return result.value;
345
- }
346
- if (result.objectId) {
168
+ if (result.objectId)
347
169
  return {
348
170
  type: result.type,
349
171
  description: result.description,
350
- objectId: result.objectId
172
+ objectId: result.objectId,
351
173
  };
352
- }
353
174
  return result.description || result.type;
354
175
  }
355
176
  validateArgs(args) {
356
- if (typeof args !== 'object' || args === null) {
177
+ if (typeof args !== "object" || args === null)
357
178
  return false;
358
- }
359
- const scriptArgs = args;
360
- if (!scriptArgs.expression && !scriptArgs.file) {
179
+ const a = args;
180
+ if (!a.expression && !a.file)
361
181
  return false;
362
- }
363
- if (scriptArgs.expression && scriptArgs.file) {
182
+ if (a.expression && a.file)
364
183
  return false;
365
- }
366
- if (scriptArgs.expression && typeof scriptArgs.expression !== 'string') {
184
+ if (a.expression && typeof a.expression !== "string")
367
185
  return false;
368
- }
369
- if (scriptArgs.file && typeof scriptArgs.file !== 'string') {
186
+ if (a.file && typeof a.file !== "string")
370
187
  return false;
371
- }
372
- if (scriptArgs.awaitPromise !== undefined && typeof scriptArgs.awaitPromise !== 'boolean') {
188
+ if (a.awaitPromise !== undefined && typeof a.awaitPromise !== "boolean")
373
189
  return false;
374
- }
375
- if (scriptArgs.timeout !== undefined && typeof scriptArgs.timeout !== 'number') {
190
+ if (a.timeout !== undefined && typeof a.timeout !== "number")
376
191
  return false;
377
- }
378
192
  return true;
379
193
  }
380
194
  getHelp() {
@@ -382,13 +196,13 @@ class EvaluateScriptHandler {
382
196
  eval - Execute JavaScript code in the browser context
383
197
 
384
198
  Usage:
385
- eval "console.log('Hello')"
386
- eval --file script.js
387
- eval "fetch('/api')" --await-promise
388
- eval "longRunning()" --timeout 60000
199
+ cdp eval "document.title"
200
+ cdp eval --file script.js
201
+ cdp eval "await fetch('/api').then(r => r.json())"
202
+ cdp eval "heavyComputation()" --timeout 60000
389
203
 
390
204
  Arguments:
391
- <expression> JavaScript code to execute (direct argument)
205
+ <expression> JavaScript code to execute
392
206
  --expression <code> JavaScript code to execute (explicit flag)
393
207
  --file <path> Path to JavaScript file to execute
394
208
  --await-promise Wait for Promise resolution (default: true)
@@ -396,20 +210,10 @@ Arguments:
396
210
  --return-by-value Return result by value (default: true)
397
211
 
398
212
  Examples:
399
- # Execute simple expression (recommended)
400
- eval "2 + 2"
401
-
402
- # Execute with explicit flag
403
- eval --expression "2 + 2"
404
-
405
- # Execute async code
406
- eval "await fetch('/api').then(r => r.json())"
407
-
408
- # Execute from file
409
- eval --file ./scripts/init.js
410
-
411
- # Set custom timeout
412
- eval "heavyComputation()" --timeout 120000
213
+ cdp eval "2 + 2"
214
+ cdp eval "Array.from(document.links).map(l => l.href)"
215
+ cdp eval --file ./scripts/init.js
216
+ cdp eval "await new Promise(r => setTimeout(r, 5000))" --timeout 10000
413
217
  `;
414
218
  }
415
219
  }