chrome-cdp-cli 1.5.0 → 1.6.0

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,6 +1,41 @@
1
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
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.logger = exports.Logger = exports.LogLevel = void 0;
36
+ exports.createLogger = exports.logger = exports.Logger = exports.LogLevel = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
4
39
  var LogLevel;
5
40
  (function (LogLevel) {
6
41
  LogLevel[LogLevel["ERROR"] = 0] = "ERROR";
@@ -9,36 +44,239 @@ var LogLevel;
9
44
  LogLevel[LogLevel["DEBUG"] = 3] = "DEBUG";
10
45
  })(LogLevel || (exports.LogLevel = LogLevel = {}));
11
46
  class Logger {
12
- constructor(level = LogLevel.INFO, quiet = false) {
13
- this.level = level;
14
- this.quiet = quiet;
47
+ constructor(config = {}) {
48
+ this.currentFileSize = 0;
49
+ this.config = {
50
+ level: LogLevel.INFO,
51
+ quiet: false,
52
+ maxFileSize: 10 * 1024 * 1024,
53
+ maxFiles: 5,
54
+ enableConsole: true,
55
+ enableStructured: true,
56
+ ...config
57
+ };
58
+ if (this.config.file) {
59
+ this.initializeLogFile();
60
+ }
61
+ }
62
+ initializeLogFile() {
63
+ if (!this.config.file)
64
+ return;
65
+ try {
66
+ const logDir = path.dirname(this.config.file);
67
+ if (!fs.existsSync(logDir)) {
68
+ fs.mkdirSync(logDir, { recursive: true });
69
+ }
70
+ if (fs.existsSync(this.config.file)) {
71
+ const stats = fs.statSync(this.config.file);
72
+ this.currentFileSize = stats.size;
73
+ if (this.currentFileSize >= (this.config.maxFileSize || 10 * 1024 * 1024)) {
74
+ this.rotateLogFile();
75
+ }
76
+ }
77
+ this.logFileHandle = fs.createWriteStream(this.config.file, { flags: 'a' });
78
+ this.logFileHandle.on('error', (error) => {
79
+ console.error('Log file write error:', error);
80
+ });
81
+ }
82
+ catch (error) {
83
+ console.error('Failed to initialize log file:', error);
84
+ }
85
+ }
86
+ rotateLogFile() {
87
+ if (!this.config.file || !this.logFileHandle)
88
+ return;
89
+ try {
90
+ this.logFileHandle.end();
91
+ for (let i = (this.config.maxFiles || 5) - 1; i > 0; i--) {
92
+ const oldFile = `${this.config.file}.${i}`;
93
+ const newFile = `${this.config.file}.${i + 1}`;
94
+ if (fs.existsSync(oldFile)) {
95
+ if (i === (this.config.maxFiles || 5) - 1) {
96
+ fs.unlinkSync(oldFile);
97
+ }
98
+ else {
99
+ fs.renameSync(oldFile, newFile);
100
+ }
101
+ }
102
+ }
103
+ if (fs.existsSync(this.config.file)) {
104
+ fs.renameSync(this.config.file, `${this.config.file}.1`);
105
+ }
106
+ this.currentFileSize = 0;
107
+ this.logFileHandle = fs.createWriteStream(this.config.file, { flags: 'a' });
108
+ this.logFileHandle.on('error', (error) => {
109
+ console.error('Log file write error:', error);
110
+ });
111
+ }
112
+ catch (error) {
113
+ console.error('Failed to rotate log file:', error);
114
+ }
115
+ }
116
+ formatLogEntry(entry) {
117
+ if (this.config.enableStructured) {
118
+ return JSON.stringify(entry) + '\n';
119
+ }
120
+ else {
121
+ const timestamp = entry.timestamp;
122
+ const level = entry.level.padEnd(5);
123
+ const component = entry.component ? `[${entry.component}]` : '';
124
+ const connectionId = entry.connectionId ? `{conn:${entry.connectionId}}` : '';
125
+ const clientId = entry.clientId ? `{client:${entry.clientId}}` : '';
126
+ let message = `${timestamp} ${level} ${component}${connectionId}${clientId} ${entry.message}`;
127
+ if (entry.data) {
128
+ message += ` | Data: ${JSON.stringify(entry.data)}`;
129
+ }
130
+ if (entry.error) {
131
+ message += ` | Error: ${entry.error.message}`;
132
+ if (entry.error.stack) {
133
+ message += `\nStack: ${entry.error.stack}`;
134
+ }
135
+ }
136
+ if (entry.metrics) {
137
+ message += ` | Metrics: ${JSON.stringify(entry.metrics)}`;
138
+ }
139
+ return message + '\n';
140
+ }
141
+ }
142
+ writeLog(entry) {
143
+ const formattedEntry = this.formatLogEntry(entry);
144
+ if (this.config.enableConsole && !this.config.quiet) {
145
+ const consoleMessage = this.config.enableStructured
146
+ ? formattedEntry.trim()
147
+ : formattedEntry.trim();
148
+ switch (entry.level) {
149
+ case 'ERROR':
150
+ console.error(consoleMessage);
151
+ break;
152
+ case 'WARN':
153
+ console.warn(consoleMessage);
154
+ break;
155
+ case 'INFO':
156
+ console.info(consoleMessage);
157
+ break;
158
+ case 'DEBUG':
159
+ console.debug(consoleMessage);
160
+ break;
161
+ }
162
+ }
163
+ if (this.logFileHandle) {
164
+ const entrySize = Buffer.byteLength(formattedEntry, 'utf8');
165
+ if (this.currentFileSize + entrySize >= (this.config.maxFileSize || 10 * 1024 * 1024)) {
166
+ this.rotateLogFile();
167
+ }
168
+ this.logFileHandle.write(formattedEntry);
169
+ this.currentFileSize += entrySize;
170
+ }
171
+ }
172
+ createLogEntry(level, message, data, error, context) {
173
+ const entry = {
174
+ timestamp: new Date().toISOString(),
175
+ level,
176
+ message,
177
+ component: context?.component || this.config.component
178
+ };
179
+ if (context?.connectionId)
180
+ entry.connectionId = context.connectionId;
181
+ if (context?.clientId)
182
+ entry.clientId = context.clientId;
183
+ if (data !== undefined)
184
+ entry.data = data;
185
+ if (context?.metrics)
186
+ entry.metrics = context.metrics;
187
+ if (error) {
188
+ entry.error = {
189
+ message: error.message,
190
+ stack: error.stack,
191
+ code: error.code
192
+ };
193
+ }
194
+ return entry;
15
195
  }
16
196
  setLevel(level) {
17
- this.level = level;
197
+ this.config.level = level;
18
198
  }
19
199
  setQuiet(quiet) {
20
- this.quiet = quiet;
200
+ this.config.quiet = quiet;
201
+ }
202
+ setComponent(component) {
203
+ this.config.component = component;
21
204
  }
22
- error(message, ...args) {
23
- if (!this.quiet && this.level >= LogLevel.ERROR) {
24
- console.error(`[ERROR] ${message}`, ...args);
205
+ error(message, errorOrData, context) {
206
+ if (this.config.level >= LogLevel.ERROR) {
207
+ let error;
208
+ let data;
209
+ if (errorOrData instanceof Error) {
210
+ error = errorOrData;
211
+ data = context?.data;
212
+ }
213
+ else {
214
+ data = errorOrData;
215
+ error = undefined;
216
+ }
217
+ const entry = this.createLogEntry('ERROR', message, data, error, context);
218
+ this.writeLog(entry);
25
219
  }
26
220
  }
27
- warn(message, ...args) {
28
- if (!this.quiet && this.level >= LogLevel.WARN) {
29
- console.warn(`[WARN] ${message}`, ...args);
221
+ warn(message, data, context) {
222
+ if (this.config.level >= LogLevel.WARN) {
223
+ const entry = this.createLogEntry('WARN', message, data, undefined, context);
224
+ this.writeLog(entry);
30
225
  }
31
226
  }
32
- info(message, ...args) {
33
- if (!this.quiet && this.level >= LogLevel.INFO) {
34
- console.info(`[INFO] ${message}`, ...args);
227
+ info(message, data, context) {
228
+ if (this.config.level >= LogLevel.INFO) {
229
+ const entry = this.createLogEntry('INFO', message, data, undefined, context);
230
+ this.writeLog(entry);
35
231
  }
36
232
  }
37
- debug(message, ...args) {
38
- if (!this.quiet && this.level >= LogLevel.DEBUG) {
39
- console.debug(`[DEBUG] ${message}`, ...args);
233
+ debug(message, data, context) {
234
+ if (this.config.level >= LogLevel.DEBUG) {
235
+ const entry = this.createLogEntry('DEBUG', message, data, undefined, context);
236
+ this.writeLog(entry);
237
+ }
238
+ }
239
+ logServerEvent(event, message, data, error) {
240
+ const metrics = event === 'startup' || event === 'shutdown' ? {
241
+ memoryUsage: process.memoryUsage()
242
+ } : undefined;
243
+ const entry = this.createLogEntry(event === 'error' ? 'ERROR' : 'INFO', `[SERVER-${event.toUpperCase()}] ${message}`, data, error, { component: 'ProxyServer', metrics });
244
+ this.writeLog(entry);
245
+ }
246
+ logConnectionEvent(event, connectionId, message, data, error) {
247
+ const entry = this.createLogEntry(error ? 'ERROR' : 'INFO', `[CONNECTION-${event.toUpperCase()}] ${message}`, data, error, { component: 'ConnectionPool', connectionId });
248
+ this.writeLog(entry);
249
+ }
250
+ logClientEvent(event, clientId, message, data, error) {
251
+ const entry = this.createLogEntry(error ? 'ERROR' : 'INFO', `[CLIENT-${event.toUpperCase()}] ${message}`, data, error, { component: 'WSProxy', clientId });
252
+ this.writeLog(entry);
253
+ }
254
+ logMemoryEvent(event, message, metrics) {
255
+ const entry = this.createLogEntry('INFO', `[MEMORY-${event.toUpperCase()}] ${message}`, undefined, undefined, { component: 'MemoryManager', metrics });
256
+ this.writeLog(entry);
257
+ }
258
+ logAPIEvent(method, path, statusCode, duration, clientIP, error) {
259
+ const entry = this.createLogEntry(error ? 'ERROR' : 'INFO', `[API] ${method} ${path} - ${statusCode} (${duration}ms)`, { clientIP, duration, statusCode }, error, { component: 'ProxyAPI' });
260
+ this.writeLog(entry);
261
+ }
262
+ logSecurityEvent(event, message, data, error) {
263
+ const entry = this.createLogEntry(error ? 'ERROR' : 'WARN', `[SECURITY-${event.toUpperCase()}] ${message}`, data, error, { component: 'SecurityManager' });
264
+ this.writeLog(entry);
265
+ }
266
+ logPerformanceMetrics(component, metrics) {
267
+ const entry = this.createLogEntry('INFO', `[PERFORMANCE] ${component} metrics`, undefined, undefined, { component, metrics });
268
+ this.writeLog(entry);
269
+ }
270
+ close() {
271
+ if (this.logFileHandle) {
272
+ this.logFileHandle.end();
273
+ this.logFileHandle = undefined;
40
274
  }
41
275
  }
42
276
  }
43
277
  exports.Logger = Logger;
44
278
  exports.logger = new Logger();
279
+ const createLogger = (config = {}) => {
280
+ return new Logger(config);
281
+ };
282
+ exports.createLogger = createLogger;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chrome-cdp-cli",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "LLM-first browser automation CLI via Chrome DevTools Protocol. Eval-first design optimized for AI assistants - LLMs write JavaScript scripts for rapid validation. Features: JavaScript execution, element interaction, screenshots, DOM snapshots, console/network monitoring. Built-in IDE integration for Cursor and Claude.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -20,8 +20,10 @@
20
20
  "build:prod": "node scripts/build.js production",
21
21
  "build:watch": "tsc --watch",
22
22
  "dev": "ts-node src/index.ts",
23
+ "dev:proxy": "ts-node src/proxy/index.ts",
23
24
  "demo": "ts-node demo.ts",
24
25
  "start": "node dist/index.js",
26
+ "start:proxy": "node dist/proxy/index.js",
25
27
  "test": "jest",
26
28
  "test:watch": "jest --watch",
27
29
  "test:coverage": "jest --coverage",
@@ -58,10 +60,14 @@
58
60
  "homepage": "https://github.com/nicoster/chrome-devtools-cli#readme",
59
61
  "dependencies": {
60
62
  "commander": "^11.1.0",
63
+ "express": "^4.18.2",
64
+ "express-rate-limit": "^8.2.1",
61
65
  "node-fetch": "^2.7.0",
62
66
  "ws": "^8.14.2"
63
67
  },
64
68
  "devDependencies": {
69
+ "@types/express": "^4.17.21",
70
+ "@types/express-rate-limit": "^5.1.3",
65
71
  "@types/jest": "^29.5.8",
66
72
  "@types/node": "^20.9.0",
67
73
  "@types/node-fetch": "^2.6.13",