chrome-cdp-cli 2.1.2 → 2.1.4
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.
|
@@ -141,6 +141,9 @@ class CLIApplication {
|
|
|
141
141
|
const title = target.title.toLowerCase();
|
|
142
142
|
return (url.startsWith("chrome-devtools://") ||
|
|
143
143
|
url.startsWith("devtools://") ||
|
|
144
|
+
url.startsWith("chrome://") ||
|
|
145
|
+
url.startsWith("chrome-extension://") ||
|
|
146
|
+
url.startsWith("chrome-untrusted://") ||
|
|
144
147
|
title.includes("devtools") ||
|
|
145
148
|
title.includes("chrome devtools"));
|
|
146
149
|
}
|
|
@@ -161,23 +164,18 @@ class CLIApplication {
|
|
|
161
164
|
const CYAN = "\x1b[36m";
|
|
162
165
|
const DIM = "\x1b[2m";
|
|
163
166
|
const CLEAR_LINE = "\x1b[2K\x1b[G";
|
|
164
|
-
const
|
|
165
|
-
const RESTORE = "\x1b[u";
|
|
167
|
+
const TOTAL_LINES = targets.length * 2 + 5;
|
|
166
168
|
const truncate = (s, max) => s.length > max ? s.substring(0, max - 1) + "…" : s;
|
|
167
169
|
const render = (first) => {
|
|
168
|
-
if (first) {
|
|
169
|
-
process.stderr.write(
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
process.stderr.write(RESTORE);
|
|
170
|
+
if (!first) {
|
|
171
|
+
process.stderr.write(`\x1b[${TOTAL_LINES}A`);
|
|
173
172
|
}
|
|
174
173
|
process.stderr.write(`${CLEAR_LINE}${BOLD}Select a Chrome page${RESET} (↑↓ navigate, Enter select, q quit)\n`);
|
|
175
174
|
process.stderr.write(`${CLEAR_LINE}${"─".repeat(54)}\n`);
|
|
176
175
|
targets.forEach((t, i) => {
|
|
177
176
|
const num = `[${i + 1}]`;
|
|
178
|
-
const
|
|
179
|
-
const
|
|
180
|
-
const url = truncate(t.url, 60);
|
|
177
|
+
const title = truncate(t.title || "(Untitled)", 50);
|
|
178
|
+
const url = truncate(t.url, 58);
|
|
181
179
|
const selected = i === cursor;
|
|
182
180
|
if (selected) {
|
|
183
181
|
process.stderr.write(`${CLEAR_LINE}${CYAN}${BOLD} ❯ ${num} ${title}${RESET}\n`);
|
|
@@ -189,8 +187,8 @@ class CLIApplication {
|
|
|
189
187
|
}
|
|
190
188
|
});
|
|
191
189
|
process.stderr.write(`${CLEAR_LINE}${"─".repeat(54)}\n`);
|
|
192
|
-
process.stderr.write(`${CLEAR_LINE}${DIM}Tip: skip this prompt with cdp -i <number> <command>${RESET}\n`
|
|
193
|
-
|
|
190
|
+
process.stderr.write(`${CLEAR_LINE}${DIM}Tip: skip this prompt with cdp -i <number> <command>${RESET}\n`);
|
|
191
|
+
process.stderr.write(`${CLEAR_LINE}${DIM} or close other tabs until only one remains.${RESET}\n`);
|
|
194
192
|
};
|
|
195
193
|
render(true);
|
|
196
194
|
process.stdin.setRawMode(true);
|
|
@@ -568,7 +568,7 @@ class CommandSchemaRegistry {
|
|
|
568
568
|
name: "log",
|
|
569
569
|
aliases: ["console"],
|
|
570
570
|
description: "Follow console messages in real-time",
|
|
571
|
-
usage: "cdp log [options]",
|
|
571
|
+
usage: "cdp log [PATTERN] [options]",
|
|
572
572
|
examples: [
|
|
573
573
|
{ command: "cdp log", description: "Follow all console messages" },
|
|
574
574
|
{
|
|
@@ -576,8 +576,20 @@ class CommandSchemaRegistry {
|
|
|
576
576
|
description: "Follow only errors and warnings",
|
|
577
577
|
},
|
|
578
578
|
{
|
|
579
|
-
command:
|
|
580
|
-
description: "Follow messages matching /
|
|
579
|
+
command: "cdp log '\\[AI'",
|
|
580
|
+
description: "Follow messages matching regex /\\[AI/i",
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
command: "cdp log -e error -e warn",
|
|
584
|
+
description: "Follow messages matching 'error' OR 'warn'",
|
|
585
|
+
},
|
|
586
|
+
{
|
|
587
|
+
command: "cdp log -F '[AI'",
|
|
588
|
+
description: "Follow messages containing literal string '[AI'",
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
command: "cdp log -v 'debug'",
|
|
592
|
+
description: "Follow messages NOT matching 'debug'",
|
|
581
593
|
},
|
|
582
594
|
{
|
|
583
595
|
command: "cdp log --format json",
|
|
@@ -592,9 +604,28 @@ class CommandSchemaRegistry {
|
|
|
592
604
|
type: "string",
|
|
593
605
|
},
|
|
594
606
|
{
|
|
595
|
-
name: "
|
|
596
|
-
|
|
607
|
+
name: "expression",
|
|
608
|
+
short: "e",
|
|
609
|
+
description: "Pattern to match (regex by default). May be specified multiple times (OR logic).",
|
|
597
610
|
type: "string",
|
|
611
|
+
multiple: true,
|
|
612
|
+
},
|
|
613
|
+
{
|
|
614
|
+
name: "fixed-strings",
|
|
615
|
+
short: "F",
|
|
616
|
+
description: "Treat pattern(s) as literal strings, not regexps",
|
|
617
|
+
type: "boolean",
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
name: "invert-match",
|
|
621
|
+
short: "v",
|
|
622
|
+
description: "Output messages that do NOT match the pattern",
|
|
623
|
+
type: "boolean",
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
name: "case-sensitive",
|
|
627
|
+
description: "Match is case-sensitive (default: case-insensitive)",
|
|
628
|
+
type: "boolean",
|
|
598
629
|
},
|
|
599
630
|
{
|
|
600
631
|
name: "follow",
|
|
@@ -609,7 +640,14 @@ class CommandSchemaRegistry {
|
|
|
609
640
|
choices: ["text", "json", "pretty"],
|
|
610
641
|
},
|
|
611
642
|
],
|
|
612
|
-
arguments: [
|
|
643
|
+
arguments: [
|
|
644
|
+
{
|
|
645
|
+
name: "pattern",
|
|
646
|
+
description: "Pattern to match (regex by default, case-insensitive)",
|
|
647
|
+
type: "string",
|
|
648
|
+
required: false,
|
|
649
|
+
},
|
|
650
|
+
],
|
|
613
651
|
});
|
|
614
652
|
this.registerCommand({
|
|
615
653
|
name: "network",
|
|
@@ -20,21 +20,44 @@ class ListConsoleMessagesHandler {
|
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
+
buildMatcher(params) {
|
|
24
|
+
const rawExpressions = params.expression
|
|
25
|
+
? Array.isArray(params.expression)
|
|
26
|
+
? params.expression
|
|
27
|
+
: [params.expression]
|
|
28
|
+
: [];
|
|
29
|
+
const patterns = [
|
|
30
|
+
...(params.pattern ? [params.pattern] : []),
|
|
31
|
+
...rawExpressions,
|
|
32
|
+
];
|
|
33
|
+
if (patterns.length === 0)
|
|
34
|
+
return () => true;
|
|
35
|
+
const fixedStrings = params.fixedStrings ?? params["fixed-strings"] ?? false;
|
|
36
|
+
const caseSensitive = params.caseSensitive ?? params["case-sensitive"] ?? false;
|
|
37
|
+
const invertMatch = params.invertMatch ?? params["invert-match"] ?? false;
|
|
38
|
+
const flags = caseSensitive ? "" : "i";
|
|
39
|
+
const tests = patterns.map((p) => {
|
|
40
|
+
if (fixedStrings) {
|
|
41
|
+
return caseSensitive
|
|
42
|
+
? (text) => text.includes(p)
|
|
43
|
+
: (text) => text.toLowerCase().includes(p.toLowerCase());
|
|
44
|
+
}
|
|
45
|
+
const re = new RegExp(p, flags);
|
|
46
|
+
return (text) => re.test(text);
|
|
47
|
+
});
|
|
48
|
+
const anyMatch = (text) => tests.some((t) => t(text));
|
|
49
|
+
return invertMatch ? (text) => !anyMatch(text) : anyMatch;
|
|
50
|
+
}
|
|
23
51
|
async executeFollowMode(client, params) {
|
|
24
52
|
if (!this.consoleMonitor) {
|
|
25
53
|
this.consoleMonitor = new ConsoleMonitor_1.ConsoleMonitor(client);
|
|
26
54
|
}
|
|
27
55
|
await this.consoleMonitor.startMonitoring();
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
filter.types = params.types;
|
|
31
|
-
}
|
|
32
|
-
if (params.textPattern) {
|
|
33
|
-
filter.textPattern = params.textPattern;
|
|
34
|
-
}
|
|
56
|
+
const typeFilter = params.types && params.types.length > 0 ? params.types : null;
|
|
57
|
+
const matchText = this.buildMatcher(params);
|
|
35
58
|
const outputFormat = params.format || "text";
|
|
36
59
|
const messageCallback = (message) => {
|
|
37
|
-
if (!this.shouldOutputMessage(message,
|
|
60
|
+
if (!this.shouldOutputMessage(message, typeFilter, matchText)) {
|
|
38
61
|
return;
|
|
39
62
|
}
|
|
40
63
|
this.outputMessage(message, outputFormat);
|
|
@@ -69,19 +92,11 @@ class ListConsoleMessagesHandler {
|
|
|
69
92
|
isLongRunning: true,
|
|
70
93
|
};
|
|
71
94
|
}
|
|
72
|
-
shouldOutputMessage(message,
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
return false;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
if (filter.textPattern) {
|
|
79
|
-
const pattern = new RegExp(filter.textPattern, "i");
|
|
80
|
-
if (!pattern.test(message.text)) {
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
95
|
+
shouldOutputMessage(message, typeFilter, matchText) {
|
|
96
|
+
if (typeFilter && !typeFilter.includes(message.type)) {
|
|
97
|
+
return false;
|
|
83
98
|
}
|
|
84
|
-
return
|
|
99
|
+
return matchText(message.text);
|
|
85
100
|
}
|
|
86
101
|
outputMessage(message, format) {
|
|
87
102
|
switch (format) {
|
|
@@ -142,10 +157,16 @@ class ListConsoleMessagesHandler {
|
|
|
142
157
|
return false;
|
|
143
158
|
}
|
|
144
159
|
}
|
|
145
|
-
if (params.
|
|
146
|
-
typeof params.textPattern !== "string") {
|
|
160
|
+
if (params.pattern !== undefined && typeof params.pattern !== "string") {
|
|
147
161
|
return false;
|
|
148
162
|
}
|
|
163
|
+
if (params.expression !== undefined) {
|
|
164
|
+
const exprs = Array.isArray(params.expression)
|
|
165
|
+
? params.expression
|
|
166
|
+
: [params.expression];
|
|
167
|
+
if (!exprs.every((e) => typeof e === "string"))
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
149
170
|
if (params.format !== undefined) {
|
|
150
171
|
const validFormats = ["text", "json", "pretty"];
|
|
151
172
|
if (typeof params.format !== "string" ||
|
|
@@ -159,21 +180,30 @@ class ListConsoleMessagesHandler {
|
|
|
159
180
|
return `log - Follow console messages in real-time
|
|
160
181
|
|
|
161
182
|
Usage:
|
|
162
|
-
cdp log [options]
|
|
183
|
+
cdp log [PATTERN] [options]
|
|
184
|
+
|
|
185
|
+
Arguments:
|
|
186
|
+
PATTERN Pattern to match (regex, case-insensitive by default)
|
|
163
187
|
|
|
164
188
|
Options:
|
|
165
|
-
--
|
|
166
|
-
--
|
|
167
|
-
--
|
|
189
|
+
-e, --expression <pat> Pattern to match; may be used multiple times (OR logic)
|
|
190
|
+
-F, --fixed-strings Treat pattern(s) as literal strings, not regexps
|
|
191
|
+
-v, --invert-match Output messages that do NOT match the pattern
|
|
192
|
+
--case-sensitive Case-sensitive matching (default: case-insensitive)
|
|
193
|
+
--types <types> Filter by message types (log,info,warn,error,debug)
|
|
194
|
+
--format <format> Output format: text, json, or pretty (default: text)
|
|
168
195
|
-f, --follow Alias flag (follow mode is always active)
|
|
169
196
|
|
|
170
197
|
Examples:
|
|
171
|
-
cdp log
|
|
172
|
-
cdp log
|
|
173
|
-
cdp log
|
|
174
|
-
cdp log
|
|
175
|
-
cdp log
|
|
176
|
-
cdp log
|
|
198
|
+
cdp log # Follow all console messages
|
|
199
|
+
cdp log '\\[AI' # Messages matching regex /\\[AI/i
|
|
200
|
+
cdp log -e error -e warn # Messages containing 'error' OR 'warn'
|
|
201
|
+
cdp log -F '[AI' # Messages containing literal '[AI'
|
|
202
|
+
cdp log -v debug # Messages NOT containing 'debug'
|
|
203
|
+
cdp log '404' --case-sensitive # Case-sensitive match
|
|
204
|
+
cdp log --types error,warn # Filter by type
|
|
205
|
+
cdp log --format json # Output as JSON (one object per line)
|
|
206
|
+
cdp log --format pretty # Colorized output
|
|
177
207
|
|
|
178
208
|
Note:
|
|
179
209
|
This command runs continuously and streams console messages in real-time.
|
package/dist/utils/logger.js
CHANGED
|
@@ -53,7 +53,7 @@ class Logger {
|
|
|
53
53
|
maxFiles: 5,
|
|
54
54
|
enableConsole: true,
|
|
55
55
|
enableStructured: false,
|
|
56
|
-
...config
|
|
56
|
+
...config,
|
|
57
57
|
};
|
|
58
58
|
if (this.config.file) {
|
|
59
59
|
this.initializeLogFile();
|
|
@@ -74,13 +74,15 @@ class Logger {
|
|
|
74
74
|
this.rotateLogFile();
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
-
this.logFileHandle = fs.createWriteStream(this.config.file, {
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
this.logFileHandle = fs.createWriteStream(this.config.file, {
|
|
78
|
+
flags: "a",
|
|
79
|
+
});
|
|
80
|
+
this.logFileHandle.on("error", (error) => {
|
|
81
|
+
console.error("Log file write error:", error);
|
|
80
82
|
});
|
|
81
83
|
}
|
|
82
84
|
catch (error) {
|
|
83
|
-
console.error(
|
|
85
|
+
console.error("Failed to initialize log file:", error);
|
|
84
86
|
}
|
|
85
87
|
}
|
|
86
88
|
rotateLogFile() {
|
|
@@ -104,25 +106,29 @@ class Logger {
|
|
|
104
106
|
fs.renameSync(this.config.file, `${this.config.file}.1`);
|
|
105
107
|
}
|
|
106
108
|
this.currentFileSize = 0;
|
|
107
|
-
this.logFileHandle = fs.createWriteStream(this.config.file, {
|
|
108
|
-
|
|
109
|
-
|
|
109
|
+
this.logFileHandle = fs.createWriteStream(this.config.file, {
|
|
110
|
+
flags: "a",
|
|
111
|
+
});
|
|
112
|
+
this.logFileHandle.on("error", (error) => {
|
|
113
|
+
console.error("Log file write error:", error);
|
|
110
114
|
});
|
|
111
115
|
}
|
|
112
116
|
catch (error) {
|
|
113
|
-
console.error(
|
|
117
|
+
console.error("Failed to rotate log file:", error);
|
|
114
118
|
}
|
|
115
119
|
}
|
|
116
120
|
formatLogEntry(entry) {
|
|
117
121
|
if (this.config.enableStructured) {
|
|
118
|
-
return JSON.stringify(entry) +
|
|
122
|
+
return JSON.stringify(entry) + "\n";
|
|
119
123
|
}
|
|
120
124
|
else {
|
|
121
125
|
const timestamp = entry.timestamp;
|
|
122
126
|
const level = entry.level.padEnd(5);
|
|
123
|
-
const component = entry.component ? `[${entry.component}]` :
|
|
124
|
-
const connectionId = entry.connectionId
|
|
125
|
-
|
|
127
|
+
const component = entry.component ? `[${entry.component}]` : "";
|
|
128
|
+
const connectionId = entry.connectionId
|
|
129
|
+
? `{conn:${entry.connectionId}}`
|
|
130
|
+
: "";
|
|
131
|
+
const clientId = entry.clientId ? `{client:${entry.clientId}}` : "";
|
|
126
132
|
let message = `${timestamp} ${level} ${component}${connectionId}${clientId} ${entry.message}`;
|
|
127
133
|
if (entry.data) {
|
|
128
134
|
message += ` | Data: ${JSON.stringify(entry.data)}`;
|
|
@@ -136,7 +142,7 @@ class Logger {
|
|
|
136
142
|
if (entry.metrics) {
|
|
137
143
|
message += ` | Metrics: ${JSON.stringify(entry.metrics)}`;
|
|
138
144
|
}
|
|
139
|
-
return message +
|
|
145
|
+
return message + "\n";
|
|
140
146
|
}
|
|
141
147
|
}
|
|
142
148
|
writeLog(entry) {
|
|
@@ -145,24 +151,12 @@ class Logger {
|
|
|
145
151
|
const consoleMessage = this.config.enableStructured
|
|
146
152
|
? formattedEntry.trim()
|
|
147
153
|
: formattedEntry.trim();
|
|
148
|
-
|
|
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
|
-
}
|
|
154
|
+
process.stderr.write(consoleMessage + "\n");
|
|
162
155
|
}
|
|
163
156
|
if (this.logFileHandle) {
|
|
164
|
-
const entrySize = Buffer.byteLength(formattedEntry,
|
|
165
|
-
if (this.currentFileSize + entrySize >=
|
|
157
|
+
const entrySize = Buffer.byteLength(formattedEntry, "utf8");
|
|
158
|
+
if (this.currentFileSize + entrySize >=
|
|
159
|
+
(this.config.maxFileSize || 10 * 1024 * 1024)) {
|
|
166
160
|
this.rotateLogFile();
|
|
167
161
|
}
|
|
168
162
|
this.logFileHandle.write(formattedEntry);
|
|
@@ -174,7 +168,7 @@ class Logger {
|
|
|
174
168
|
timestamp: new Date().toISOString(),
|
|
175
169
|
level,
|
|
176
170
|
message,
|
|
177
|
-
component: context?.component || this.config.component
|
|
171
|
+
component: context?.component || this.config.component,
|
|
178
172
|
};
|
|
179
173
|
if (context?.connectionId)
|
|
180
174
|
entry.connectionId = context.connectionId;
|
|
@@ -188,7 +182,7 @@ class Logger {
|
|
|
188
182
|
entry.error = {
|
|
189
183
|
message: error.message,
|
|
190
184
|
stack: error.stack,
|
|
191
|
-
code: error.code
|
|
185
|
+
code: error.code,
|
|
192
186
|
};
|
|
193
187
|
}
|
|
194
188
|
return entry;
|
|
@@ -214,57 +208,59 @@ class Logger {
|
|
|
214
208
|
data = errorOrData;
|
|
215
209
|
error = undefined;
|
|
216
210
|
}
|
|
217
|
-
const entry = this.createLogEntry(
|
|
211
|
+
const entry = this.createLogEntry("ERROR", message, data, error, context);
|
|
218
212
|
this.writeLog(entry);
|
|
219
213
|
}
|
|
220
214
|
}
|
|
221
215
|
warn(message, data, context) {
|
|
222
216
|
if (this.config.level >= LogLevel.WARN) {
|
|
223
|
-
const entry = this.createLogEntry(
|
|
217
|
+
const entry = this.createLogEntry("WARN", message, data, undefined, context);
|
|
224
218
|
this.writeLog(entry);
|
|
225
219
|
}
|
|
226
220
|
}
|
|
227
221
|
info(message, data, context) {
|
|
228
222
|
if (this.config.level >= LogLevel.INFO) {
|
|
229
|
-
const entry = this.createLogEntry(
|
|
223
|
+
const entry = this.createLogEntry("INFO", message, data, undefined, context);
|
|
230
224
|
this.writeLog(entry);
|
|
231
225
|
}
|
|
232
226
|
}
|
|
233
227
|
debug(message, data, context) {
|
|
234
228
|
if (this.config.level >= LogLevel.DEBUG) {
|
|
235
|
-
const entry = this.createLogEntry(
|
|
229
|
+
const entry = this.createLogEntry("DEBUG", message, data, undefined, context);
|
|
236
230
|
this.writeLog(entry);
|
|
237
231
|
}
|
|
238
232
|
}
|
|
239
233
|
logServerEvent(event, message, data, error) {
|
|
240
|
-
const metrics = event ===
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
234
|
+
const metrics = event === "startup" || event === "shutdown"
|
|
235
|
+
? {
|
|
236
|
+
memoryUsage: process.memoryUsage(),
|
|
237
|
+
}
|
|
238
|
+
: undefined;
|
|
239
|
+
const entry = this.createLogEntry(event === "error" ? "ERROR" : "INFO", `[SERVER-${event.toUpperCase()}] ${message}`, data, error, { component: "ProxyServer", metrics });
|
|
244
240
|
this.writeLog(entry);
|
|
245
241
|
}
|
|
246
242
|
logConnectionEvent(event, connectionId, message, data, error) {
|
|
247
|
-
const entry = this.createLogEntry(error ?
|
|
243
|
+
const entry = this.createLogEntry(error ? "ERROR" : "INFO", `[CONNECTION-${event.toUpperCase()}] ${message}`, data, error, { component: "ConnectionPool", connectionId });
|
|
248
244
|
this.writeLog(entry);
|
|
249
245
|
}
|
|
250
246
|
logClientEvent(event, clientId, message, data, error) {
|
|
251
|
-
const entry = this.createLogEntry(error ?
|
|
247
|
+
const entry = this.createLogEntry(error ? "ERROR" : "INFO", `[CLIENT-${event.toUpperCase()}] ${message}`, data, error, { component: "WSProxy", clientId });
|
|
252
248
|
this.writeLog(entry);
|
|
253
249
|
}
|
|
254
250
|
logMemoryEvent(event, message, metrics) {
|
|
255
|
-
const entry = this.createLogEntry(
|
|
251
|
+
const entry = this.createLogEntry("INFO", `[MEMORY-${event.toUpperCase()}] ${message}`, undefined, undefined, { component: "MemoryManager", metrics });
|
|
256
252
|
this.writeLog(entry);
|
|
257
253
|
}
|
|
258
254
|
logAPIEvent(method, path, statusCode, duration, clientIP, error) {
|
|
259
|
-
const entry = this.createLogEntry(error ?
|
|
255
|
+
const entry = this.createLogEntry(error ? "ERROR" : "INFO", `[API] ${method} ${path} - ${statusCode} (${duration}ms)`, { clientIP, duration, statusCode }, error, { component: "ProxyAPI" });
|
|
260
256
|
this.writeLog(entry);
|
|
261
257
|
}
|
|
262
258
|
logSecurityEvent(event, message, data, error) {
|
|
263
|
-
const entry = this.createLogEntry(error ?
|
|
259
|
+
const entry = this.createLogEntry(error ? "ERROR" : "WARN", `[SECURITY-${event.toUpperCase()}] ${message}`, data, error, { component: "SecurityManager" });
|
|
264
260
|
this.writeLog(entry);
|
|
265
261
|
}
|
|
266
262
|
logPerformanceMetrics(component, metrics) {
|
|
267
|
-
const entry = this.createLogEntry(
|
|
263
|
+
const entry = this.createLogEntry("INFO", `[PERFORMANCE] ${component} metrics`, undefined, undefined, { component, metrics });
|
|
268
264
|
this.writeLog(entry);
|
|
269
265
|
}
|
|
270
266
|
close() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chrome-cdp-cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.4",
|
|
4
4
|
"description": "Browser automation CLI via Chrome DevTools Protocol. Designed for developers and AI assistants - combines dedicated commands for common tasks with flexible JavaScript execution for complex scenarios. Features: 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",
|