chrome-cdp-cli 2.1.0 → 2.1.2

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.
@@ -1,278 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ProxyClient = void 0;
7
- const ws_1 = require("ws");
8
- const node_fetch_1 = __importDefault(require("node-fetch"));
9
- const ProxyManager_1 = require("../proxy/ProxyManager");
10
- class ProxyClient {
11
- constructor(config) {
12
- this.config = {
13
- proxyUrl: 'http://localhost:9223',
14
- fallbackToDirect: true,
15
- startProxyIfNeeded: true,
16
- ...config
17
- };
18
- this.proxyManager = ProxyManager_1.ProxyManager.getInstance();
19
- }
20
- async ensureProxyRunning() {
21
- if (this.config.startProxyIfNeeded) {
22
- return await this.proxyManager.ensureProxyReady();
23
- }
24
- return await this.isProxyRunning();
25
- }
26
- async isProxyAvailable() {
27
- return await this.isProxyRunning();
28
- }
29
- async isProxyRunning() {
30
- try {
31
- const controller = new AbortController();
32
- const timeout = setTimeout(() => controller.abort(), 2000);
33
- const response = await (0, node_fetch_1.default)(`${this.config.proxyUrl}/api/health`, {
34
- method: 'GET',
35
- signal: controller.signal
36
- });
37
- clearTimeout(timeout);
38
- return response.ok;
39
- }
40
- catch (error) {
41
- return false;
42
- }
43
- }
44
- async connect(host, port, targetId) {
45
- const request = {
46
- host,
47
- port,
48
- targetId
49
- };
50
- try {
51
- const controller = new AbortController();
52
- const timeout = setTimeout(() => controller.abort(), 30000);
53
- const response = await (0, node_fetch_1.default)(`${this.config.proxyUrl}/api/connect`, {
54
- method: 'POST',
55
- headers: {
56
- 'Content-Type': 'application/json'
57
- },
58
- body: JSON.stringify(request),
59
- signal: controller.signal
60
- });
61
- clearTimeout(timeout);
62
- if (!response.ok) {
63
- throw new Error(`Proxy connect failed: ${response.status} ${response.statusText}`);
64
- }
65
- const result = await response.json();
66
- if (!result.success) {
67
- throw new Error(`Proxy connect failed: ${result.error}`);
68
- }
69
- this.connectionId = result.data.connectionId;
70
- return this.connectionId;
71
- }
72
- catch (error) {
73
- throw new Error(`Failed to connect through proxy: ${error instanceof Error ? error.message : error}`);
74
- }
75
- }
76
- async getConsoleMessages(filter) {
77
- if (!this.connectionId) {
78
- throw new Error('No active connection. Call connect() first.');
79
- }
80
- try {
81
- const url = new URL(`${this.config.proxyUrl}/api/console/${this.connectionId}`);
82
- if (filter) {
83
- if (filter.types) {
84
- url.searchParams.set('types', filter.types.join(','));
85
- }
86
- if (filter.textPattern) {
87
- url.searchParams.set('textPattern', filter.textPattern);
88
- }
89
- if (filter.maxMessages) {
90
- url.searchParams.set('maxMessages', filter.maxMessages.toString());
91
- }
92
- if (filter.startTime) {
93
- url.searchParams.set('startTime', filter.startTime.toString());
94
- }
95
- if (filter.endTime) {
96
- url.searchParams.set('endTime', filter.endTime.toString());
97
- }
98
- if (filter.source) {
99
- url.searchParams.set('source', filter.source);
100
- }
101
- }
102
- const controller = new AbortController();
103
- const timeout = setTimeout(() => controller.abort(), 5000);
104
- const response = await (0, node_fetch_1.default)(url.toString(), {
105
- method: 'GET',
106
- signal: controller.signal
107
- });
108
- clearTimeout(timeout);
109
- if (!response.ok) {
110
- throw new Error(`Failed to get console messages: ${response.status} ${response.statusText}`);
111
- }
112
- const result = await response.json();
113
- if (!result.success) {
114
- throw new Error(`Failed to get console messages: ${result.error}`);
115
- }
116
- return result.data?.messages || [];
117
- }
118
- catch (error) {
119
- throw new Error(`Failed to get console messages: ${error instanceof Error ? error.message : error}`);
120
- }
121
- }
122
- async getNetworkRequests(filter) {
123
- if (!this.connectionId) {
124
- throw new Error('No active connection. Call connect() first.');
125
- }
126
- try {
127
- const url = new URL(`${this.config.proxyUrl}/api/network/${this.connectionId}`);
128
- if (filter) {
129
- if (filter.methods) {
130
- url.searchParams.set('methods', filter.methods.join(','));
131
- }
132
- if (filter.statusCodes) {
133
- url.searchParams.set('statusCodes', filter.statusCodes.join(','));
134
- }
135
- if (filter.urlPattern) {
136
- url.searchParams.set('urlPattern', filter.urlPattern);
137
- }
138
- if (filter.maxRequests) {
139
- url.searchParams.set('maxRequests', filter.maxRequests.toString());
140
- }
141
- if (filter.startTime) {
142
- url.searchParams.set('startTime', filter.startTime.toString());
143
- }
144
- if (filter.endTime) {
145
- url.searchParams.set('endTime', filter.endTime.toString());
146
- }
147
- if (filter.includeResponseBody !== undefined) {
148
- url.searchParams.set('includeResponseBody', filter.includeResponseBody.toString());
149
- }
150
- }
151
- const controller = new AbortController();
152
- const timeout = setTimeout(() => controller.abort(), 5000);
153
- const response = await (0, node_fetch_1.default)(url.toString(), {
154
- method: 'GET',
155
- signal: controller.signal
156
- });
157
- clearTimeout(timeout);
158
- if (!response.ok) {
159
- throw new Error(`Failed to get network requests: ${response.status} ${response.statusText}`);
160
- }
161
- const result = await response.json();
162
- if (!result.success) {
163
- throw new Error(`Failed to get network requests: ${result.error}`);
164
- }
165
- return result.data?.requests || [];
166
- }
167
- catch (error) {
168
- throw new Error(`Failed to get network requests: ${error instanceof Error ? error.message : error}`);
169
- }
170
- }
171
- async createWebSocketProxy() {
172
- if (!this.connectionId) {
173
- throw new Error('No active connection. Call connect() first.');
174
- }
175
- console.log(`[DEBUG] Creating WebSocket proxy for connection: ${this.connectionId}`);
176
- try {
177
- const wsUrl = this.config.proxyUrl.replace('http://', 'ws://').replace('https://', 'wss://');
178
- const fullWsUrl = `${wsUrl}/ws/${this.connectionId}`;
179
- console.log(`[DEBUG] WebSocket URL: ${fullWsUrl}`);
180
- const ws = new ws_1.WebSocket(fullWsUrl);
181
- return new Promise((resolve, reject) => {
182
- const timeout = setTimeout(() => {
183
- console.log(`[DEBUG] WebSocket connection timeout for ${this.connectionId}`);
184
- reject(new Error('WebSocket connection timeout'));
185
- }, 10000);
186
- ws.on('open', () => {
187
- console.log(`[DEBUG] WebSocket connection opened for ${this.connectionId}`);
188
- clearTimeout(timeout);
189
- this.wsConnection = ws;
190
- resolve(ws);
191
- });
192
- ws.on('error', (error) => {
193
- console.log(`[DEBUG] WebSocket connection error for ${this.connectionId}:`, error);
194
- clearTimeout(timeout);
195
- reject(error);
196
- });
197
- });
198
- }
199
- catch (error) {
200
- console.log(`[DEBUG] Failed to create WebSocket proxy for ${this.connectionId}:`, error);
201
- throw new Error(`Failed to create WebSocket proxy: ${error instanceof Error ? error.message : error}`);
202
- }
203
- }
204
- async healthCheck() {
205
- if (!this.connectionId) {
206
- return null;
207
- }
208
- try {
209
- const controller = new AbortController();
210
- const timeout = setTimeout(() => controller.abort(), 5000);
211
- const response = await (0, node_fetch_1.default)(`${this.config.proxyUrl}/api/health/${this.connectionId}`, {
212
- method: 'GET',
213
- signal: controller.signal
214
- });
215
- clearTimeout(timeout);
216
- if (!response.ok) {
217
- throw new Error(`Health check failed: ${response.status} ${response.statusText}`);
218
- }
219
- const result = await response.json();
220
- if (!result.success) {
221
- throw new Error(`Health check failed: ${result.error}`);
222
- }
223
- return result.data || null;
224
- }
225
- catch (error) {
226
- console.warn('Health check failed:', error instanceof Error ? error.message : error);
227
- return null;
228
- }
229
- }
230
- async disconnect() {
231
- try {
232
- if (this.connectionId) {
233
- try {
234
- const controller = new AbortController();
235
- const timeout = setTimeout(() => controller.abort(), 5000);
236
- await (0, node_fetch_1.default)(`${this.config.proxyUrl}/api/client/release`, {
237
- method: 'POST',
238
- headers: {
239
- 'Content-Type': 'application/json',
240
- 'x-client-id': `proxy_client_${Date.now()}`
241
- },
242
- signal: controller.signal
243
- });
244
- clearTimeout(timeout);
245
- }
246
- catch (error) {
247
- }
248
- }
249
- if (this.wsConnection) {
250
- this.wsConnection.close();
251
- this.wsConnection = undefined;
252
- }
253
- if (this.connectionId) {
254
- try {
255
- const controller = new AbortController();
256
- const timeout = setTimeout(() => controller.abort(), 5000);
257
- await (0, node_fetch_1.default)(`${this.config.proxyUrl}/api/connection/${this.connectionId}`, {
258
- method: 'DELETE',
259
- signal: controller.signal
260
- });
261
- clearTimeout(timeout);
262
- }
263
- catch (error) {
264
- }
265
- this.connectionId = undefined;
266
- }
267
- }
268
- catch (error) {
269
- }
270
- }
271
- getConnectionId() {
272
- return this.connectionId;
273
- }
274
- getConfig() {
275
- return { ...this.config };
276
- }
277
- }
278
- exports.ProxyClient = ProxyClient;
@@ -1,97 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RestartProxyHandler = void 0;
4
- const ProxyManager_1 = require("../proxy/ProxyManager");
5
- class RestartProxyHandler {
6
- constructor() {
7
- this.name = 'restart';
8
- }
9
- async execute(_client, args) {
10
- try {
11
- const params = args;
12
- const proxyManager = ProxyManager_1.ProxyManager.getInstance();
13
- const status = await proxyManager.getStatus();
14
- if (status.isHealthy && !params.force) {
15
- return {
16
- success: true,
17
- data: {
18
- message: 'Proxy server is already running and healthy',
19
- status: status
20
- }
21
- };
22
- }
23
- const success = await proxyManager.restart();
24
- if (success) {
25
- await new Promise(resolve => setTimeout(resolve, 1000));
26
- const newStatus = await proxyManager.getStatus();
27
- return {
28
- success: true,
29
- data: {
30
- message: 'Proxy server restarted successfully',
31
- status: newStatus
32
- }
33
- };
34
- }
35
- else {
36
- return {
37
- success: false,
38
- error: 'Failed to restart proxy server. Check logs for details.'
39
- };
40
- }
41
- }
42
- catch (error) {
43
- return {
44
- success: false,
45
- error: error instanceof Error ? error.message : 'Unknown error occurred while restarting proxy'
46
- };
47
- }
48
- }
49
- validateArgs(args) {
50
- if (typeof args !== 'object' || args === null) {
51
- return false;
52
- }
53
- const params = args;
54
- if ('force' in params && typeof params.force !== 'boolean') {
55
- return false;
56
- }
57
- return true;
58
- }
59
- getHelp() {
60
- return `
61
- restart - Restart the proxy server process
62
-
63
- Usage:
64
- cdp restart
65
- cdp restart --force
66
-
67
- Description:
68
- Restarts the proxy server process. This will:
69
- - Stop the current proxy server process
70
- - Clear all stored console messages and network requests
71
- - Start a new proxy server process
72
-
73
- When to use:
74
- Use this command when console or network command output becomes stale:
75
- - Console messages are not refreshing or showing old data
76
- - Network requests are not updating or displaying outdated information
77
- - Logs appear to be stuck or not reflecting current browser state
78
- Restarting the proxy will clear the message store and start fresh monitoring.
79
-
80
- Options:
81
- --force Force restart even if proxy is healthy
82
-
83
- Examples:
84
- # Restart the proxy server
85
- cdp restart
86
-
87
- # Force restart even if proxy is healthy
88
- cdp restart --force
89
-
90
- Note:
91
- - Restarting the proxy will clear all stored console messages and network requests
92
- - The proxy server must be restarted if logs are not refreshing properly
93
- - After restart, you may need to reconnect to Chrome DevTools
94
- `;
95
- }
96
- }
97
- exports.RestartProxyHandler = RestartProxyHandler;
@@ -1,270 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.ProxyManager = void 0;
40
- const ProxyClient_1 = require("../client/ProxyClient");
41
- const child_process_1 = require("child_process");
42
- const path = __importStar(require("path"));
43
- const fs = __importStar(require("fs"));
44
- const node_fetch_1 = __importDefault(require("node-fetch"));
45
- class ProxyManager {
46
- constructor(config) {
47
- this.isStarting = false;
48
- this.lastHealthCheck = 0;
49
- this.healthCheckCacheMs = 5000;
50
- this.config = {
51
- proxyUrl: 'http://localhost:9223',
52
- maxRetries: 3,
53
- retryDelayMs: 1000,
54
- healthCheckTimeoutMs: 2000,
55
- startupTimeoutMs: 10000,
56
- enableLogging: false,
57
- ...config
58
- };
59
- }
60
- static getInstance(config) {
61
- if (!ProxyManager.instance) {
62
- ProxyManager.instance = new ProxyManager(config);
63
- }
64
- return ProxyManager.instance;
65
- }
66
- async ensureProxyReady() {
67
- try {
68
- if (await this.isProxyHealthy()) {
69
- return true;
70
- }
71
- return await this.startOrRestartProxy();
72
- }
73
- catch (error) {
74
- this.log(`Failed to ensure proxy ready: ${error instanceof Error ? error.message : error}`);
75
- return false;
76
- }
77
- }
78
- async isProxyHealthy() {
79
- const now = Date.now();
80
- if (now - this.lastHealthCheck < this.healthCheckCacheMs) {
81
- return true;
82
- }
83
- try {
84
- const controller = new AbortController();
85
- const timeout = setTimeout(() => controller.abort(), this.config.healthCheckTimeoutMs);
86
- const response = await (0, node_fetch_1.default)(`${this.config.proxyUrl}/api/health`, {
87
- method: 'GET',
88
- signal: controller.signal
89
- });
90
- clearTimeout(timeout);
91
- if (response.ok) {
92
- this.lastHealthCheck = now;
93
- return true;
94
- }
95
- return false;
96
- }
97
- catch (error) {
98
- return false;
99
- }
100
- }
101
- async restart() {
102
- return await this.startOrRestartProxy();
103
- }
104
- async startOrRestartProxy() {
105
- if (this.isStarting) {
106
- return await this.waitForStartup();
107
- }
108
- this.isStarting = true;
109
- try {
110
- await this.killExistingProxy();
111
- const success = await this.startProxyProcess();
112
- if (success) {
113
- this.log('Proxy server started successfully');
114
- }
115
- else {
116
- this.log('Failed to start proxy server');
117
- }
118
- return success;
119
- }
120
- finally {
121
- this.isStarting = false;
122
- }
123
- }
124
- async killExistingProxy() {
125
- if (this.proxyProcess) {
126
- try {
127
- this.proxyProcess.kill('SIGTERM');
128
- await new Promise(resolve => setTimeout(resolve, 1000));
129
- if (!this.proxyProcess.killed) {
130
- this.proxyProcess.kill('SIGKILL');
131
- }
132
- }
133
- catch (error) {
134
- }
135
- this.proxyProcess = undefined;
136
- }
137
- try {
138
- const { spawn } = require('child_process');
139
- const port = new URL(this.config.proxyUrl).port || '9223';
140
- const lsof = spawn('lsof', ['-ti', `:${port}`]);
141
- let pids = '';
142
- lsof.stdout.on('data', (data) => {
143
- pids += data.toString();
144
- });
145
- lsof.on('close', (code) => {
146
- if (code === 0 && pids.trim()) {
147
- const pidList = pids.trim().split('\n');
148
- pidList.forEach(pid => {
149
- try {
150
- process.kill(parseInt(pid), 'SIGTERM');
151
- }
152
- catch (error) {
153
- }
154
- });
155
- }
156
- });
157
- }
158
- catch (error) {
159
- }
160
- }
161
- async startProxyProcess() {
162
- try {
163
- const proxyServerPath = this.findProxyServerExecutable();
164
- if (!proxyServerPath) {
165
- this.log('Proxy server executable not found');
166
- return false;
167
- }
168
- this.log(`Starting proxy server: ${proxyServerPath}`);
169
- this.proxyProcess = (0, child_process_1.spawn)('node', [proxyServerPath], {
170
- detached: true,
171
- stdio: this.config.enableLogging ? 'inherit' : 'ignore'
172
- });
173
- this.proxyProcess.unref();
174
- this.proxyProcess.on('error', (error) => {
175
- this.log(`Proxy process error: ${error.message}`);
176
- this.proxyProcess = undefined;
177
- });
178
- this.proxyProcess.on('exit', (code, signal) => {
179
- this.log(`Proxy process exited with code ${code}, signal ${signal}`);
180
- this.proxyProcess = undefined;
181
- });
182
- return await this.waitForProxyStartup();
183
- }
184
- catch (error) {
185
- this.log(`Failed to start proxy process: ${error instanceof Error ? error.message : error}`);
186
- return false;
187
- }
188
- }
189
- async waitForProxyStartup() {
190
- const startTime = Date.now();
191
- const maxWaitTime = this.config.startupTimeoutMs;
192
- while (Date.now() - startTime < maxWaitTime) {
193
- this.lastHealthCheck = 0;
194
- if (await this.isProxyHealthy()) {
195
- return true;
196
- }
197
- await new Promise(resolve => setTimeout(resolve, 500));
198
- }
199
- this.log(`Proxy startup timeout after ${maxWaitTime}ms`);
200
- return false;
201
- }
202
- async waitForStartup() {
203
- const maxWait = this.config.startupTimeoutMs;
204
- const startTime = Date.now();
205
- while (this.isStarting && Date.now() - startTime < maxWait) {
206
- await new Promise(resolve => setTimeout(resolve, 100));
207
- }
208
- return !this.isStarting && await this.isProxyHealthy();
209
- }
210
- findProxyServerExecutable() {
211
- const distPath = path.join(__dirname, '../../dist/proxy/index.js');
212
- if (fs.existsSync(distPath)) {
213
- return distPath;
214
- }
215
- const srcPath = path.join(__dirname, '../proxy/index.js');
216
- if (fs.existsSync(srcPath)) {
217
- return srcPath;
218
- }
219
- const currentDistPath = path.join(process.cwd(), 'dist/proxy/index.js');
220
- if (fs.existsSync(currentDistPath)) {
221
- return currentDistPath;
222
- }
223
- const nodeModulesPath = path.join(__dirname, '../../../node_modules/chrome-cdp-cli/dist/proxy/index.js');
224
- if (fs.existsSync(nodeModulesPath)) {
225
- return nodeModulesPath;
226
- }
227
- return null;
228
- }
229
- async getProxyClient() {
230
- if (await this.ensureProxyReady()) {
231
- return new ProxyClient_1.ProxyClient({
232
- proxyUrl: this.config.proxyUrl,
233
- fallbackToDirect: true,
234
- startProxyIfNeeded: false
235
- });
236
- }
237
- return null;
238
- }
239
- async shutdown() {
240
- if (this.proxyProcess) {
241
- try {
242
- this.proxyProcess.kill('SIGTERM');
243
- await new Promise(resolve => setTimeout(resolve, 2000));
244
- if (!this.proxyProcess.killed) {
245
- this.proxyProcess.kill('SIGKILL');
246
- }
247
- }
248
- catch (error) {
249
- }
250
- this.proxyProcess = undefined;
251
- }
252
- }
253
- setLogging(enabled) {
254
- this.config.enableLogging = enabled;
255
- }
256
- log(message) {
257
- if (this.config.enableLogging) {
258
- console.log(`[ProxyManager] ${message}`);
259
- }
260
- }
261
- async getStatus() {
262
- return {
263
- isHealthy: await this.isProxyHealthy(),
264
- isStarting: this.isStarting,
265
- hasProcess: !!this.proxyProcess,
266
- lastHealthCheck: this.lastHealthCheck
267
- };
268
- }
269
- }
270
- exports.ProxyManager = ProxyManager;