chrome-cdp-cli 2.0.5 → 2.1.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.
- package/dist/cli/ArgumentParser.js +172 -92
- package/dist/cli/CLIApplication.js +155 -82
- package/dist/cli/CommandRouter.js +98 -74
- package/dist/cli/CommandSchemaRegistry.js +506 -398
- package/dist/cli/HelpSystem.js +286 -256
- package/dist/handlers/ClickHandler.js +91 -27
- package/dist/handlers/InstallClaudeSkillHandler.js +220 -220
- package/dist/handlers/InstallCursorCommandHandler.js +60 -60
- package/dist/handlers/ListConsoleMessagesHandler.js +126 -178
- package/dist/handlers/ListNetworkRequestsHandler.js +128 -108
- package/dist/handlers/RestartProxyHandler.js +4 -4
- package/dist/handlers/TakeScreenshotHandler.js +70 -59
- package/dist/handlers/TakeSnapshotHandler.js +223 -165
- package/dist/handlers/index.js +0 -1
- package/dist/monitors/ConsoleMonitor.js +29 -0
- package/dist/monitors/NetworkMonitor.js +43 -19
- package/dist/proxy/server/CDPProxyServer.js +5 -1
- package/dist/proxy/server/CommandExecutionService.js +1 -1
- package/dist/proxy/server/ProxyAPIServer.js +11 -6
- package/package.json +3 -2
|
@@ -6,23 +6,87 @@ class ArgumentParser {
|
|
|
6
6
|
constructor() {
|
|
7
7
|
this.commands = new Map();
|
|
8
8
|
this.aliases = new Map();
|
|
9
|
+
this.globalOptionDefs = [
|
|
10
|
+
{
|
|
11
|
+
name: "host",
|
|
12
|
+
short: "h",
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "Chrome host address",
|
|
15
|
+
default: "localhost",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: "port",
|
|
19
|
+
short: "p",
|
|
20
|
+
type: "number",
|
|
21
|
+
description: "DevTools port",
|
|
22
|
+
default: 9222,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: "format",
|
|
26
|
+
short: "f",
|
|
27
|
+
type: "string",
|
|
28
|
+
description: "Output format",
|
|
29
|
+
choices: ["json", "text"],
|
|
30
|
+
default: "text",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: "verbose",
|
|
34
|
+
short: "v",
|
|
35
|
+
type: "boolean",
|
|
36
|
+
description: "Enable verbose logging",
|
|
37
|
+
default: false,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "quiet",
|
|
41
|
+
short: "q",
|
|
42
|
+
type: "boolean",
|
|
43
|
+
description: "Enable quiet mode",
|
|
44
|
+
default: false,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "timeout",
|
|
48
|
+
short: "t",
|
|
49
|
+
type: "number",
|
|
50
|
+
description: "Command timeout in milliseconds",
|
|
51
|
+
default: 30000,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "debug",
|
|
55
|
+
short: "d",
|
|
56
|
+
type: "boolean",
|
|
57
|
+
description: "Enable debug logging",
|
|
58
|
+
default: false,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "config",
|
|
62
|
+
short: "c",
|
|
63
|
+
type: "string",
|
|
64
|
+
description: "Configuration file path",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: "target-index",
|
|
68
|
+
short: "i",
|
|
69
|
+
type: "number",
|
|
70
|
+
description: "Target page index (1-based, excludes DevTools windows)",
|
|
71
|
+
},
|
|
72
|
+
];
|
|
9
73
|
this.helpSystem = new HelpSystem_1.HelpSystem(undefined, this);
|
|
10
74
|
}
|
|
11
75
|
parseArguments(argv) {
|
|
12
76
|
try {
|
|
13
77
|
if (!Array.isArray(argv)) {
|
|
14
|
-
return this.createParseResult(
|
|
78
|
+
return this.createParseResult("help", {}, [], true);
|
|
15
79
|
}
|
|
16
80
|
const sliceStart = Math.max(0, Math.min(2, argv.length));
|
|
17
81
|
const args = argv.slice(sliceStart);
|
|
18
82
|
if (args.length === 0) {
|
|
19
|
-
return this.createParseResult(
|
|
83
|
+
return this.createParseResult("help", {}, [], true);
|
|
20
84
|
}
|
|
21
|
-
if (args.includes(
|
|
22
|
-
return this.createParseResult(
|
|
85
|
+
if (args.includes("--help")) {
|
|
86
|
+
return this.createParseResult("help", {}, [], true);
|
|
23
87
|
}
|
|
24
|
-
if (args.includes(
|
|
25
|
-
return this.createParseResult(
|
|
88
|
+
if (args.includes("--version") || args.includes("-V")) {
|
|
89
|
+
return this.createParseResult("version", {}, [], true);
|
|
26
90
|
}
|
|
27
91
|
let globalOptions;
|
|
28
92
|
let commandName;
|
|
@@ -34,41 +98,49 @@ class ArgumentParser {
|
|
|
34
98
|
commandArgs = parseResult.commandArgs;
|
|
35
99
|
}
|
|
36
100
|
catch (parseError) {
|
|
37
|
-
if (args.some(arg => arg ===
|
|
38
|
-
return this.createParseResult(
|
|
101
|
+
if (args.some((arg) => arg === "--help" || arg === "help")) {
|
|
102
|
+
return this.createParseResult("help", {}, [], true);
|
|
39
103
|
}
|
|
40
104
|
throw parseError;
|
|
41
105
|
}
|
|
42
106
|
const resolvedCommand = this.resolveCommandName(commandName);
|
|
43
|
-
if (resolvedCommand ===
|
|
107
|
+
if (resolvedCommand === "help") {
|
|
44
108
|
return this.createParseResult(resolvedCommand, globalOptions, [], true, commandArgs);
|
|
45
109
|
}
|
|
46
110
|
const commandDef = this.commands.get(resolvedCommand);
|
|
47
111
|
if (!commandDef) {
|
|
48
|
-
return this.createParseResult(resolvedCommand, globalOptions, [
|
|
112
|
+
return this.createParseResult(resolvedCommand, globalOptions, [
|
|
113
|
+
`Unknown command: ${commandName}. Use 'help' to see available commands.`,
|
|
114
|
+
], false);
|
|
49
115
|
}
|
|
50
116
|
const parseResult = this.parseCommandArguments(commandDef, commandArgs);
|
|
51
|
-
const allOptions = {
|
|
117
|
+
const allOptions = {
|
|
118
|
+
...globalOptions,
|
|
119
|
+
...parseResult.globalOptions,
|
|
120
|
+
...parseResult.options,
|
|
121
|
+
};
|
|
52
122
|
return this.createParseResult(resolvedCommand, allOptions, parseResult.errors, parseResult.errors.length === 0, parseResult.arguments);
|
|
53
123
|
}
|
|
54
124
|
catch (error) {
|
|
55
125
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
56
126
|
if (process.env.DEBUG) {
|
|
57
|
-
console.error(
|
|
127
|
+
console.error("Parse error details:", error);
|
|
58
128
|
if (error instanceof Error && error.stack) {
|
|
59
|
-
console.error(
|
|
129
|
+
console.error("Stack trace:", error.stack);
|
|
60
130
|
}
|
|
61
131
|
}
|
|
62
|
-
if (errorMessage.includes(
|
|
63
|
-
return this.createParseResult(
|
|
132
|
+
if (errorMessage.includes("Invalid count value")) {
|
|
133
|
+
return this.createParseResult("help", {}, [
|
|
134
|
+
`Parse error: Invalid argument format. Please check your command syntax.`,
|
|
135
|
+
], false);
|
|
64
136
|
}
|
|
65
|
-
return this.createParseResult(
|
|
137
|
+
return this.createParseResult("help", {}, [`Parse error: ${errorMessage}`], false);
|
|
66
138
|
}
|
|
67
139
|
}
|
|
68
140
|
registerCommand(command) {
|
|
69
141
|
const validation = this.validateCommandDefinition(command);
|
|
70
142
|
if (!validation.valid) {
|
|
71
|
-
throw new Error(`Invalid command definition: ${validation.errors.join(
|
|
143
|
+
throw new Error(`Invalid command definition: ${validation.errors.join(", ")}`);
|
|
72
144
|
}
|
|
73
145
|
this.commands.set(command.name, command);
|
|
74
146
|
for (const alias of command.aliases) {
|
|
@@ -80,7 +152,7 @@ class ArgumentParser {
|
|
|
80
152
|
}
|
|
81
153
|
generateHelp(command) {
|
|
82
154
|
if (command) {
|
|
83
|
-
if (command.startsWith(
|
|
155
|
+
if (command.startsWith("topic ")) {
|
|
84
156
|
const topicName = command.substring(6);
|
|
85
157
|
return this.helpSystem.generateTopicHelp(topicName);
|
|
86
158
|
}
|
|
@@ -94,7 +166,7 @@ class ArgumentParser {
|
|
|
94
166
|
return {
|
|
95
167
|
valid: false,
|
|
96
168
|
errors: [`Unknown command: ${command}`],
|
|
97
|
-
warnings: []
|
|
169
|
+
warnings: [],
|
|
98
170
|
};
|
|
99
171
|
}
|
|
100
172
|
const errors = [];
|
|
@@ -104,23 +176,27 @@ class ArgumentParser {
|
|
|
104
176
|
errors.push(`Required option --${option.name} is missing`);
|
|
105
177
|
}
|
|
106
178
|
}
|
|
107
|
-
const requiredArgs = commandDef.arguments.filter(arg => arg.required);
|
|
179
|
+
const requiredArgs = commandDef.arguments.filter((arg) => arg.required);
|
|
108
180
|
if (args.arguments.length < requiredArgs.length) {
|
|
109
181
|
const providedCount = Math.max(0, Math.min(args.arguments.length, requiredArgs.length));
|
|
110
182
|
const missingCount = Math.max(0, requiredArgs.length - providedCount);
|
|
111
183
|
if (missingCount > 0) {
|
|
112
184
|
const startIndex = Math.max(0, providedCount);
|
|
113
185
|
const endIndex = Math.min(requiredArgs.length, startIndex + missingCount);
|
|
114
|
-
if (startIndex < endIndex &&
|
|
115
|
-
|
|
186
|
+
if (startIndex < endIndex &&
|
|
187
|
+
startIndex >= 0 &&
|
|
188
|
+
endIndex <= requiredArgs.length) {
|
|
189
|
+
const missingArgs = requiredArgs
|
|
190
|
+
.slice(startIndex, endIndex)
|
|
191
|
+
.map((arg) => arg.name);
|
|
116
192
|
if (missingArgs.length > 0) {
|
|
117
|
-
errors.push(`Missing required arguments: ${missingArgs.join(
|
|
193
|
+
errors.push(`Missing required arguments: ${missingArgs.join(", ")}`);
|
|
118
194
|
}
|
|
119
195
|
}
|
|
120
196
|
}
|
|
121
197
|
}
|
|
122
198
|
for (const [optionName, value] of Object.entries(args.options)) {
|
|
123
|
-
const optionDef = commandDef.options.find(opt => opt.name === optionName);
|
|
199
|
+
const optionDef = commandDef.options.find((opt) => opt.name === optionName);
|
|
124
200
|
if (optionDef) {
|
|
125
201
|
const optionValidation = this.validateOptionValue(optionDef, value);
|
|
126
202
|
if (!optionValidation.valid) {
|
|
@@ -142,31 +218,21 @@ class ArgumentParser {
|
|
|
142
218
|
return {
|
|
143
219
|
valid: errors.length === 0,
|
|
144
220
|
errors,
|
|
145
|
-
warnings
|
|
221
|
+
warnings,
|
|
146
222
|
};
|
|
147
223
|
}
|
|
148
224
|
parseGlobalAndCommand(args) {
|
|
149
|
-
if (args.includes(
|
|
150
|
-
return { globalOptions: {}, commandName:
|
|
225
|
+
if (args.includes("--help")) {
|
|
226
|
+
return { globalOptions: {}, commandName: "help", commandArgs: [] };
|
|
151
227
|
}
|
|
152
228
|
const globalOptions = {};
|
|
153
|
-
let commandName =
|
|
229
|
+
let commandName = "help";
|
|
154
230
|
let commandArgs = [];
|
|
155
231
|
let i = 0;
|
|
156
|
-
const globalOptionDefs =
|
|
157
|
-
{ name: 'host', short: 'h', type: 'string', description: 'Chrome host address', default: 'localhost' },
|
|
158
|
-
{ name: 'port', short: 'p', type: 'number', description: 'DevTools port', default: 9222 },
|
|
159
|
-
{ name: 'format', short: 'f', type: 'string', description: 'Output format', choices: ['json', 'text'], default: 'text' },
|
|
160
|
-
{ name: 'verbose', short: 'v', type: 'boolean', description: 'Enable verbose logging', default: false },
|
|
161
|
-
{ name: 'quiet', short: 'q', type: 'boolean', description: 'Enable quiet mode', default: false },
|
|
162
|
-
{ name: 'timeout', short: 't', type: 'number', description: 'Command timeout in milliseconds', default: 30000 },
|
|
163
|
-
{ name: 'debug', short: 'd', type: 'boolean', description: 'Enable debug logging', default: false },
|
|
164
|
-
{ name: 'config', short: 'c', type: 'string', description: 'Configuration file path' },
|
|
165
|
-
{ name: 'target-index', type: 'number', description: 'Target page index (1-based, excludes DevTools windows)' }
|
|
166
|
-
];
|
|
232
|
+
const globalOptionDefs = this.globalOptionDefs;
|
|
167
233
|
while (i < args.length) {
|
|
168
234
|
const arg = args[i];
|
|
169
|
-
if (arg.startsWith(
|
|
235
|
+
if (arg.startsWith("--")) {
|
|
170
236
|
const { option, value, consumed } = this.parseLongOption(arg, args, i, globalOptionDefs);
|
|
171
237
|
if (option) {
|
|
172
238
|
globalOptions[option.name] = value;
|
|
@@ -185,7 +251,7 @@ class ArgumentParser {
|
|
|
185
251
|
break;
|
|
186
252
|
}
|
|
187
253
|
}
|
|
188
|
-
else if (arg.startsWith(
|
|
254
|
+
else if (arg.startsWith("-") && arg.length > 1) {
|
|
189
255
|
const { option, value, consumed } = this.parseShortOption(arg, args, i, globalOptionDefs);
|
|
190
256
|
if (option) {
|
|
191
257
|
globalOptions[option.name] = value;
|
|
@@ -222,25 +288,25 @@ class ArgumentParser {
|
|
|
222
288
|
let optionName = arg.substring(2);
|
|
223
289
|
let value;
|
|
224
290
|
let consumed = 1;
|
|
225
|
-
const equalIndex = optionName.indexOf(
|
|
291
|
+
const equalIndex = optionName.indexOf("=");
|
|
226
292
|
if (equalIndex !== -1) {
|
|
227
293
|
value = optionName.substring(equalIndex + 1);
|
|
228
294
|
optionName = optionName.substring(0, equalIndex);
|
|
229
295
|
}
|
|
230
296
|
let isNegated = false;
|
|
231
|
-
if (optionName.startsWith(
|
|
297
|
+
if (optionName.startsWith("no-")) {
|
|
232
298
|
isNegated = true;
|
|
233
299
|
optionName = optionName.substring(3);
|
|
234
300
|
}
|
|
235
|
-
const optionDef = optionDefs.find(opt => opt.name === optionName);
|
|
301
|
+
const optionDef = optionDefs.find((opt) => opt.name === optionName);
|
|
236
302
|
if (!optionDef) {
|
|
237
303
|
return { option: null, value: null, consumed: 0 };
|
|
238
304
|
}
|
|
239
|
-
if (optionDef.type ===
|
|
305
|
+
if (optionDef.type === "boolean") {
|
|
240
306
|
value = !isNegated;
|
|
241
307
|
}
|
|
242
308
|
else if (value === undefined) {
|
|
243
|
-
if (index + 1 < args.length && !args[index + 1].startsWith(
|
|
309
|
+
if (index + 1 < args.length && !args[index + 1].startsWith("-")) {
|
|
244
310
|
value = args[index + 1];
|
|
245
311
|
consumed = 2;
|
|
246
312
|
}
|
|
@@ -256,17 +322,17 @@ class ArgumentParser {
|
|
|
256
322
|
if (shortName.length > 1) {
|
|
257
323
|
return { option: null, value: null, consumed: 0 };
|
|
258
324
|
}
|
|
259
|
-
const optionDef = optionDefs.find(opt => opt.short === shortName);
|
|
325
|
+
const optionDef = optionDefs.find((opt) => opt.short === shortName);
|
|
260
326
|
if (!optionDef) {
|
|
261
327
|
return { option: null, value: null, consumed: 0 };
|
|
262
328
|
}
|
|
263
329
|
let value;
|
|
264
330
|
let consumed = 1;
|
|
265
|
-
if (optionDef.type ===
|
|
331
|
+
if (optionDef.type === "boolean") {
|
|
266
332
|
value = true;
|
|
267
333
|
}
|
|
268
334
|
else {
|
|
269
|
-
if (index + 1 < args.length && !args[index + 1].startsWith(
|
|
335
|
+
if (index + 1 < args.length && !args[index + 1].startsWith("-")) {
|
|
270
336
|
value = args[index + 1];
|
|
271
337
|
consumed = 2;
|
|
272
338
|
}
|
|
@@ -287,49 +353,54 @@ class ArgumentParser {
|
|
|
287
353
|
}
|
|
288
354
|
parseCommandArguments(commandDef, args) {
|
|
289
355
|
const options = {};
|
|
356
|
+
const lateGlobalOptions = {};
|
|
290
357
|
const arguments_ = [];
|
|
291
358
|
const errors = [];
|
|
292
359
|
let i = 0;
|
|
293
360
|
while (i < args.length) {
|
|
294
361
|
const arg = args[i];
|
|
295
|
-
if (arg.startsWith(
|
|
362
|
+
if (arg.startsWith("--")) {
|
|
296
363
|
try {
|
|
297
364
|
const { option, value, consumed } = this.parseLongOption(arg, args, i, commandDef.options);
|
|
298
365
|
if (option) {
|
|
299
366
|
options[option.name] = value;
|
|
300
|
-
|
|
301
|
-
|
|
367
|
+
i += consumed > 0 ? consumed : 1;
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
const { option: gOpt, value: gVal, consumed: gConsumed, } = this.parseLongOption(arg, args, i, this.globalOptionDefs);
|
|
371
|
+
if (gOpt) {
|
|
372
|
+
lateGlobalOptions[gOpt.name] = gVal;
|
|
373
|
+
i += gConsumed > 0 ? gConsumed : 1;
|
|
302
374
|
}
|
|
303
375
|
else {
|
|
376
|
+
errors.push(`Unknown option: ${arg}`);
|
|
304
377
|
i++;
|
|
305
378
|
}
|
|
306
379
|
}
|
|
307
|
-
else {
|
|
308
|
-
errors.push(`Unknown option: ${arg}`);
|
|
309
|
-
i++;
|
|
310
|
-
}
|
|
311
380
|
}
|
|
312
381
|
catch (error) {
|
|
313
382
|
errors.push(error instanceof Error ? error.message : String(error));
|
|
314
383
|
i++;
|
|
315
384
|
}
|
|
316
385
|
}
|
|
317
|
-
else if (arg.startsWith(
|
|
386
|
+
else if (arg.startsWith("-") && arg.length > 1) {
|
|
318
387
|
try {
|
|
319
388
|
const { option, value, consumed } = this.parseShortOption(arg, args, i, commandDef.options);
|
|
320
389
|
if (option) {
|
|
321
390
|
options[option.name] = value;
|
|
322
|
-
|
|
323
|
-
|
|
391
|
+
i += consumed > 0 ? consumed : 1;
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
const { option: gOpt, value: gVal, consumed: gConsumed, } = this.parseShortOption(arg, args, i, this.globalOptionDefs);
|
|
395
|
+
if (gOpt) {
|
|
396
|
+
lateGlobalOptions[gOpt.name] = gVal;
|
|
397
|
+
i += gConsumed > 0 ? gConsumed : 1;
|
|
324
398
|
}
|
|
325
399
|
else {
|
|
400
|
+
errors.push(`Unknown option: ${arg}`);
|
|
326
401
|
i++;
|
|
327
402
|
}
|
|
328
403
|
}
|
|
329
|
-
else {
|
|
330
|
-
errors.push(`Unknown option: ${arg}`);
|
|
331
|
-
i++;
|
|
332
|
-
}
|
|
333
404
|
}
|
|
334
405
|
catch (error) {
|
|
335
406
|
errors.push(error instanceof Error ? error.message : String(error));
|
|
@@ -341,7 +412,12 @@ class ArgumentParser {
|
|
|
341
412
|
i++;
|
|
342
413
|
}
|
|
343
414
|
}
|
|
344
|
-
return {
|
|
415
|
+
return {
|
|
416
|
+
options,
|
|
417
|
+
globalOptions: lateGlobalOptions,
|
|
418
|
+
arguments: arguments_,
|
|
419
|
+
errors,
|
|
420
|
+
};
|
|
345
421
|
}
|
|
346
422
|
convertOptionValue(optionDef, value) {
|
|
347
423
|
if (value === undefined || value === null) {
|
|
@@ -349,32 +425,36 @@ class ArgumentParser {
|
|
|
349
425
|
}
|
|
350
426
|
const stringValue = String(value);
|
|
351
427
|
switch (optionDef.type) {
|
|
352
|
-
case
|
|
428
|
+
case "number": {
|
|
353
429
|
const numValue = Number(stringValue);
|
|
354
430
|
if (isNaN(numValue)) {
|
|
355
431
|
throw new Error(`Option --${optionDef.name} must be a number, got: ${stringValue}`);
|
|
356
432
|
}
|
|
357
433
|
return numValue;
|
|
358
434
|
}
|
|
359
|
-
case
|
|
360
|
-
if (typeof value ===
|
|
435
|
+
case "boolean": {
|
|
436
|
+
if (typeof value === "boolean") {
|
|
361
437
|
return value;
|
|
362
438
|
}
|
|
363
439
|
const lowerValue = stringValue.toLowerCase();
|
|
364
|
-
if (lowerValue ===
|
|
440
|
+
if (lowerValue === "true" ||
|
|
441
|
+
lowerValue === "1" ||
|
|
442
|
+
lowerValue === "yes") {
|
|
365
443
|
return true;
|
|
366
444
|
}
|
|
367
|
-
if (lowerValue ===
|
|
445
|
+
if (lowerValue === "false" ||
|
|
446
|
+
lowerValue === "0" ||
|
|
447
|
+
lowerValue === "no") {
|
|
368
448
|
return false;
|
|
369
449
|
}
|
|
370
450
|
throw new Error(`Option --${optionDef.name} must be a boolean, got: ${stringValue}`);
|
|
371
451
|
}
|
|
372
|
-
case
|
|
452
|
+
case "array":
|
|
373
453
|
if (Array.isArray(value)) {
|
|
374
454
|
return value;
|
|
375
455
|
}
|
|
376
|
-
return stringValue.split(
|
|
377
|
-
case
|
|
456
|
+
return stringValue.split(",").map((s) => s.trim());
|
|
457
|
+
case "string":
|
|
378
458
|
default:
|
|
379
459
|
return stringValue;
|
|
380
460
|
}
|
|
@@ -384,7 +464,7 @@ class ArgumentParser {
|
|
|
384
464
|
const warnings = [];
|
|
385
465
|
if (optionDef.choices && optionDef.choices.length > 0) {
|
|
386
466
|
if (!optionDef.choices.includes(String(value))) {
|
|
387
|
-
errors.push(`Option --${optionDef.name} must be one of: ${optionDef.choices.join(
|
|
467
|
+
errors.push(`Option --${optionDef.name} must be one of: ${optionDef.choices.join(", ")}`);
|
|
388
468
|
}
|
|
389
469
|
}
|
|
390
470
|
if (optionDef.validator) {
|
|
@@ -397,24 +477,24 @@ class ArgumentParser {
|
|
|
397
477
|
return {
|
|
398
478
|
valid: errors.length === 0,
|
|
399
479
|
errors,
|
|
400
|
-
warnings
|
|
480
|
+
warnings,
|
|
401
481
|
};
|
|
402
482
|
}
|
|
403
483
|
validateArgumentValue(argDef, value) {
|
|
404
484
|
const errors = [];
|
|
405
485
|
const warnings = [];
|
|
406
486
|
switch (argDef.type) {
|
|
407
|
-
case
|
|
487
|
+
case "number":
|
|
408
488
|
if (isNaN(Number(value))) {
|
|
409
489
|
errors.push(`Argument ${argDef.name} must be a number, got: ${value}`);
|
|
410
490
|
}
|
|
411
491
|
break;
|
|
412
|
-
case
|
|
413
|
-
if (typeof value !==
|
|
492
|
+
case "file":
|
|
493
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
414
494
|
errors.push(`Argument ${argDef.name} must be a valid file path`);
|
|
415
495
|
}
|
|
416
496
|
break;
|
|
417
|
-
case
|
|
497
|
+
case "url":
|
|
418
498
|
try {
|
|
419
499
|
new URL(String(value));
|
|
420
500
|
}
|
|
@@ -433,7 +513,7 @@ class ArgumentParser {
|
|
|
433
513
|
return {
|
|
434
514
|
valid: errors.length === 0,
|
|
435
515
|
errors,
|
|
436
|
-
warnings
|
|
516
|
+
warnings,
|
|
437
517
|
};
|
|
438
518
|
}
|
|
439
519
|
resolveCommandName(commandName) {
|
|
@@ -441,41 +521,41 @@ class ArgumentParser {
|
|
|
441
521
|
}
|
|
442
522
|
validateCommandDefinition(command) {
|
|
443
523
|
const errors = [];
|
|
444
|
-
if (!command.name || typeof command.name !==
|
|
445
|
-
errors.push(
|
|
524
|
+
if (!command.name || typeof command.name !== "string") {
|
|
525
|
+
errors.push("Command name is required and must be a string");
|
|
446
526
|
}
|
|
447
|
-
if (!command.description || typeof command.description !==
|
|
448
|
-
errors.push(
|
|
527
|
+
if (!command.description || typeof command.description !== "string") {
|
|
528
|
+
errors.push("Command description is required and must be a string");
|
|
449
529
|
}
|
|
450
530
|
if (!Array.isArray(command.aliases)) {
|
|
451
|
-
errors.push(
|
|
531
|
+
errors.push("Command aliases must be an array");
|
|
452
532
|
}
|
|
453
533
|
if (!Array.isArray(command.options)) {
|
|
454
|
-
errors.push(
|
|
534
|
+
errors.push("Command options must be an array");
|
|
455
535
|
}
|
|
456
536
|
if (!Array.isArray(command.arguments)) {
|
|
457
|
-
errors.push(
|
|
537
|
+
errors.push("Command arguments must be an array");
|
|
458
538
|
}
|
|
459
539
|
for (const option of command.options) {
|
|
460
|
-
if (!option.name || typeof option.name !==
|
|
540
|
+
if (!option.name || typeof option.name !== "string") {
|
|
461
541
|
errors.push(`Option name is required and must be a string`);
|
|
462
542
|
}
|
|
463
|
-
if (![
|
|
543
|
+
if (!["string", "number", "boolean", "array"].includes(option.type)) {
|
|
464
544
|
errors.push(`Option ${option.name} has invalid type: ${option.type}`);
|
|
465
545
|
}
|
|
466
546
|
}
|
|
467
547
|
for (const arg of command.arguments) {
|
|
468
|
-
if (!arg.name || typeof arg.name !==
|
|
548
|
+
if (!arg.name || typeof arg.name !== "string") {
|
|
469
549
|
errors.push(`Argument name is required and must be a string`);
|
|
470
550
|
}
|
|
471
|
-
if (![
|
|
551
|
+
if (!["string", "number", "file", "url"].includes(arg.type)) {
|
|
472
552
|
errors.push(`Argument ${arg.name} has invalid type: ${arg.type}`);
|
|
473
553
|
}
|
|
474
554
|
}
|
|
475
555
|
return {
|
|
476
556
|
valid: errors.length === 0,
|
|
477
557
|
errors,
|
|
478
|
-
warnings: []
|
|
558
|
+
warnings: [],
|
|
479
559
|
};
|
|
480
560
|
}
|
|
481
561
|
createParseResult(command, options, errors, success, arguments_ = []) {
|
|
@@ -485,7 +565,7 @@ class ArgumentParser {
|
|
|
485
565
|
options,
|
|
486
566
|
arguments: arguments_,
|
|
487
567
|
errors,
|
|
488
|
-
warnings: []
|
|
568
|
+
warnings: [],
|
|
489
569
|
};
|
|
490
570
|
}
|
|
491
571
|
getCommands() {
|