@dynamicu/chromedebug-mcp 2.5.4 → 2.5.6
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/README.md +83 -2
- package/chrome-extension/icon128.png +0 -0
- package/chrome-extension/icon16.png +0 -0
- package/chrome-extension/icon48.png +0 -0
- package/chrome-extension/manifest.free.json +3 -3
- package/package.json +6 -4
- package/scripts/validate-manifest.js +143 -0
- package/src/cli.js +6 -0
- package/src/commands/install-pro.js +551 -0
- package/src/commands/install-pro.js.bak +542 -0
- package/chrome-extension/manifest.json +0 -73
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChromeDebug PRO License Installer
|
|
3
|
+
*
|
|
4
|
+
* Handles installation of PRO extension after purchase:
|
|
5
|
+
* - Validates license key format
|
|
6
|
+
* - Extracts PRO extension ZIP to ~/.chromedebug-pro/extension/
|
|
7
|
+
* - Saves license information to ~/.chromedebug-pro/license.json
|
|
8
|
+
* - Configures shell environment for CHROMEDEBUG_EXTENSION_PATH
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import fs from 'fs/promises';
|
|
12
|
+
import fsSync from 'fs';
|
|
13
|
+
import path from 'path';
|
|
14
|
+
import os from 'os';
|
|
15
|
+
import { execSync } from 'child_process';
|
|
16
|
+
import AdmZip from 'adm-zip';
|
|
17
|
+
|
|
18
|
+
// Constants
|
|
19
|
+
const CHROMEDEBUG_DIR = path.join(os.homedir(), '.chromedebug-pro');
|
|
20
|
+
const EXTENSION_DIR = path.join(CHROMEDEBUG_DIR, 'extension');
|
|
21
|
+
const LICENSE_FILE = path.join(CHROMEDEBUG_DIR, 'license.json');
|
|
22
|
+
const INSTALL_LOG = path.join(CHROMEDEBUG_DIR, 'install.log');
|
|
23
|
+
const ENV_VAR_NAME = 'CHROMEDEBUG_EXTENSION_PATH';
|
|
24
|
+
|
|
25
|
+
// License key format: LICENSEID-HASH (e.g., ABC12345-0123456789ABCDEF)
|
|
26
|
+
const LICENSE_KEY_REGEX = /^[A-Z0-9]{8,}-[A-Z0-9]{16,}$/i;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Log installation activity
|
|
30
|
+
*/
|
|
31
|
+
async function logInstall(message, isError = false) {
|
|
32
|
+
const timestamp = new Date().toISOString();
|
|
33
|
+
const logMessage = `[${timestamp}] ${isError ? 'ERROR: ' : ''}${message}\n`;
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
await fs.appendFile(INSTALL_LOG, logMessage);
|
|
37
|
+
} catch (err) {
|
|
38
|
+
// Ignore log errors - don't let logging break installation
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (isError) {
|
|
42
|
+
console.error(message);
|
|
43
|
+
} else {
|
|
44
|
+
console.log(message);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Validate command-line arguments
|
|
50
|
+
*/
|
|
51
|
+
function validateArguments(args) {
|
|
52
|
+
const licenseIndex = args.indexOf('--license');
|
|
53
|
+
const pathIndex = args.indexOf('--extension-path');
|
|
54
|
+
|
|
55
|
+
if (licenseIndex === -1 || pathIndex === -1) {
|
|
56
|
+
console.error(`
|
|
57
|
+
ChromeDebug PRO License Installer
|
|
58
|
+
|
|
59
|
+
Usage:
|
|
60
|
+
chromedebug-mcp install-pro --license YOUR_LICENSE_KEY --extension-path /path/to/chromedebug-pro-extension.zip
|
|
61
|
+
|
|
62
|
+
Required Arguments:
|
|
63
|
+
--license Your PRO license key (received after purchase)
|
|
64
|
+
--extension-path Path to the PRO extension ZIP file
|
|
65
|
+
|
|
66
|
+
Example:
|
|
67
|
+
chromedebug-mcp install-pro \\
|
|
68
|
+
--license ABC12345-0123456789ABCDEF \\
|
|
69
|
+
--extension-path ~/Downloads/chromedebug-pro-extension.zip
|
|
70
|
+
|
|
71
|
+
Get PRO: https://chromedebug.com/pro
|
|
72
|
+
`);
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const license = args[licenseIndex + 1];
|
|
77
|
+
const extensionPath = args[pathIndex + 1];
|
|
78
|
+
|
|
79
|
+
if (!license || !extensionPath) {
|
|
80
|
+
console.error('Error: Missing values for --license or --extension-path');
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return { license, extensionPath };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Validate license key format
|
|
89
|
+
*/
|
|
90
|
+
function validateLicenseKey(key) {
|
|
91
|
+
if (!LICENSE_KEY_REGEX.test(key)) {
|
|
92
|
+
console.error(`
|
|
93
|
+
Error: Invalid license key format
|
|
94
|
+
|
|
95
|
+
Expected format: LICENSEID-HASH
|
|
96
|
+
Example: ABC12345-0123456789ABCDEF
|
|
97
|
+
|
|
98
|
+
Your key: ${maskLicenseKey(key)}
|
|
99
|
+
|
|
100
|
+
Please check your purchase confirmation email for the correct license key.
|
|
101
|
+
Need help? https://github.com/dynamicupgrade/ChromeDebug/issues
|
|
102
|
+
`);
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Mask license key for display (show first 6 and last 3 chars)
|
|
110
|
+
*/
|
|
111
|
+
function maskLicenseKey(key) {
|
|
112
|
+
if (key.length <= 9) return '***';
|
|
113
|
+
return `${key.substring(0, 6)}...${key.substring(key.length - 3)}`;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Check pre-flight conditions
|
|
118
|
+
*/
|
|
119
|
+
async function preflightChecks() {
|
|
120
|
+
// Check write permission to home directory
|
|
121
|
+
try {
|
|
122
|
+
const testFile = path.join(os.homedir(), '.chromedebug-test');
|
|
123
|
+
await fs.writeFile(testFile, 'test');
|
|
124
|
+
await fs.unlink(testFile);
|
|
125
|
+
} catch (err) {
|
|
126
|
+
console.error(`
|
|
127
|
+
Error: Cannot write to home directory
|
|
128
|
+
|
|
129
|
+
Possible causes:
|
|
130
|
+
1. Permission denied - check: ls -ld ~
|
|
131
|
+
2. Disk full - check: df -h ~
|
|
132
|
+
3. Home directory not writable
|
|
133
|
+
|
|
134
|
+
Need help? https://github.com/dynamicupgrade/ChromeDebug/issues
|
|
135
|
+
`);
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Check for existing installation
|
|
144
|
+
*/
|
|
145
|
+
async function checkExistingInstallation() {
|
|
146
|
+
try {
|
|
147
|
+
const stats = await fs.stat(LICENSE_FILE);
|
|
148
|
+
if (stats.isFile()) {
|
|
149
|
+
const licenseData = JSON.parse(await fs.readFile(LICENSE_FILE, 'utf-8'));
|
|
150
|
+
return {
|
|
151
|
+
exists: true,
|
|
152
|
+
installed_at: licenseData.installed_at,
|
|
153
|
+
extension_version: licenseData.extension_version,
|
|
154
|
+
license_key: licenseData.license_key
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
} catch (err) {
|
|
158
|
+
// No existing installation
|
|
159
|
+
}
|
|
160
|
+
return { exists: false };
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Prompt for confirmation (synchronous for CLI)
|
|
165
|
+
*/
|
|
166
|
+
function promptConfirmation(message) {
|
|
167
|
+
// For now, we'll auto-continue with a warning
|
|
168
|
+
// In future, could add readline for interactive prompts
|
|
169
|
+
console.log(`\n${message}`);
|
|
170
|
+
console.log('Continuing with installation...\n');
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Extract and validate ZIP file
|
|
176
|
+
*/
|
|
177
|
+
async function extractExtension(zipPath, targetPath) {
|
|
178
|
+
// Resolve path (handle ~ and relative paths)
|
|
179
|
+
const resolvedZipPath = zipPath.startsWith('~')
|
|
180
|
+
? path.join(os.homedir(), zipPath.slice(1))
|
|
181
|
+
: path.resolve(zipPath);
|
|
182
|
+
|
|
183
|
+
// Check if ZIP exists
|
|
184
|
+
try {
|
|
185
|
+
await fs.access(resolvedZipPath);
|
|
186
|
+
} catch (err) {
|
|
187
|
+
console.error(`
|
|
188
|
+
Error: Extension ZIP file not found
|
|
189
|
+
|
|
190
|
+
Path: ${resolvedZipPath}
|
|
191
|
+
|
|
192
|
+
Please check:
|
|
193
|
+
1. File path is correct
|
|
194
|
+
2. File exists at the specified location
|
|
195
|
+
3. You have read permission
|
|
196
|
+
|
|
197
|
+
Need help? https://github.com/dynamicupgrade/ChromeDebug/issues
|
|
198
|
+
`);
|
|
199
|
+
throw err;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Create target directory (clean if exists)
|
|
203
|
+
try {
|
|
204
|
+
await fs.rm(targetPath, { recursive: true, force: true });
|
|
205
|
+
} catch (err) {
|
|
206
|
+
// Ignore - directory might not exist
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
await fs.mkdir(targetPath, { recursive: true });
|
|
210
|
+
|
|
211
|
+
// Extract ZIP
|
|
212
|
+
try {
|
|
213
|
+
const zip = new AdmZip(resolvedZipPath);
|
|
214
|
+
zip.extractAllTo(targetPath, true);
|
|
215
|
+
} catch (err) {
|
|
216
|
+
console.error(`
|
|
217
|
+
Error: Failed to extract ZIP file
|
|
218
|
+
|
|
219
|
+
Possible causes:
|
|
220
|
+
1. ZIP file is corrupted - try re-downloading
|
|
221
|
+
2. Not a valid ZIP file
|
|
222
|
+
3. Disk space full
|
|
223
|
+
|
|
224
|
+
Error details: ${err.message}
|
|
225
|
+
|
|
226
|
+
Need help? https://github.com/dynamicupgrade/ChromeDebug/issues
|
|
227
|
+
`);
|
|
228
|
+
throw err;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Validate extracted contents
|
|
232
|
+
const manifestPath = path.join(targetPath, 'manifest.json');
|
|
233
|
+
try {
|
|
234
|
+
const manifestContent = await fs.readFile(manifestPath, 'utf-8');
|
|
235
|
+
const manifest = JSON.parse(manifestContent);
|
|
236
|
+
|
|
237
|
+
if (!manifest.name || !manifest.name.toLowerCase().includes('chromedebug')) {
|
|
238
|
+
throw new Error('Extension does not appear to be ChromeDebug');
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return {
|
|
242
|
+
version: manifest.version,
|
|
243
|
+
name: manifest.name
|
|
244
|
+
};
|
|
245
|
+
} catch (err) {
|
|
246
|
+
console.error(`
|
|
247
|
+
Error: Invalid extension package
|
|
248
|
+
|
|
249
|
+
The extracted files do not appear to be a valid ChromeDebug extension.
|
|
250
|
+
Expected manifest.json with ChromeDebug name.
|
|
251
|
+
|
|
252
|
+
Please verify you downloaded the correct PRO extension ZIP.
|
|
253
|
+
|
|
254
|
+
Need help? https://github.com/dynamicupgrade/ChromeDebug/issues
|
|
255
|
+
`);
|
|
256
|
+
throw err;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Save license information
|
|
262
|
+
*/
|
|
263
|
+
async function saveLicenseInfo(license, extensionVersion) {
|
|
264
|
+
const licenseData = {
|
|
265
|
+
license_key: license,
|
|
266
|
+
installed_at: new Date().toISOString(),
|
|
267
|
+
extension_version: extensionVersion,
|
|
268
|
+
extension_path: EXTENSION_DIR
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
await fs.writeFile(LICENSE_FILE, JSON.stringify(licenseData, null, 2), 'utf-8');
|
|
272
|
+
|
|
273
|
+
// Set restrictive permissions (owner read/write only)
|
|
274
|
+
await fs.chmod(LICENSE_FILE, 0o600);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Detect user's shell
|
|
279
|
+
*/
|
|
280
|
+
function detectShell() {
|
|
281
|
+
try {
|
|
282
|
+
const shell = process.env.SHELL || '';
|
|
283
|
+
|
|
284
|
+
if (shell.includes('zsh')) return 'zsh';
|
|
285
|
+
if (shell.includes('bash')) return 'bash';
|
|
286
|
+
if (shell.includes('fish')) return 'fish';
|
|
287
|
+
|
|
288
|
+
// Default to bash
|
|
289
|
+
return 'bash';
|
|
290
|
+
} catch (err) {
|
|
291
|
+
return 'bash';
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Get shell configuration file path
|
|
297
|
+
*/
|
|
298
|
+
function getShellConfigFile(shell) {
|
|
299
|
+
const home = os.homedir();
|
|
300
|
+
|
|
301
|
+
switch (shell) {
|
|
302
|
+
case 'zsh':
|
|
303
|
+
return path.join(home, '.zshrc');
|
|
304
|
+
case 'bash':
|
|
305
|
+
// Prefer .bashrc on Linux, .bash_profile on macOS
|
|
306
|
+
if (process.platform === 'darwin') {
|
|
307
|
+
return path.join(home, '.bash_profile');
|
|
308
|
+
}
|
|
309
|
+
return path.join(home, '.bashrc');
|
|
310
|
+
case 'fish':
|
|
311
|
+
return path.join(home, '.config', 'fish', 'config.fish');
|
|
312
|
+
default:
|
|
313
|
+
return path.join(home, '.bashrc');
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Check if environment variable is already configured
|
|
319
|
+
*/
|
|
320
|
+
async function checkIfAlreadyConfigured(configFile) {
|
|
321
|
+
try {
|
|
322
|
+
const content = await fs.readFile(configFile, 'utf-8');
|
|
323
|
+
const envVarLine = `export ${ENV_VAR_NAME}=`;
|
|
324
|
+
|
|
325
|
+
if (content.includes(envVarLine)) {
|
|
326
|
+
// Check if it's the correct path
|
|
327
|
+
const regex = new RegExp(`export ${ENV_VAR_NAME}=["']?([^"'\\n]+)["']?`);
|
|
328
|
+
const match = content.match(regex);
|
|
329
|
+
|
|
330
|
+
if (match && match[1]) {
|
|
331
|
+
const currentPath = match[1].replace(/^~/, os.homedir());
|
|
332
|
+
const targetPath = EXTENSION_DIR;
|
|
333
|
+
|
|
334
|
+
if (path.resolve(currentPath) === path.resolve(targetPath)) {
|
|
335
|
+
return { configured: true, needsUpdate: false, currentPath };
|
|
336
|
+
} else {
|
|
337
|
+
return { configured: true, needsUpdate: true, currentPath };
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
} catch (err) {
|
|
342
|
+
// File doesn't exist or can't be read
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return { configured: false, needsUpdate: false };
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Update shell configuration
|
|
350
|
+
*/
|
|
351
|
+
async function updateShellConfig(configFile, envVarValue) {
|
|
352
|
+
// Create backup
|
|
353
|
+
const backupFile = `${configFile}.chromedebug-backup`;
|
|
354
|
+
try {
|
|
355
|
+
await fs.copyFile(configFile, backupFile);
|
|
356
|
+
} catch (err) {
|
|
357
|
+
// Config file might not exist yet
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Read existing content
|
|
361
|
+
let content = '';
|
|
362
|
+
try {
|
|
363
|
+
content = await fs.readFile(configFile, 'utf-8');
|
|
364
|
+
} catch (err) {
|
|
365
|
+
// File doesn't exist, create new
|
|
366
|
+
if (configFile.includes('.bash')) {
|
|
367
|
+
content = '#!/bin/bash\n\n';
|
|
368
|
+
} else if (configFile.includes('.zsh')) {
|
|
369
|
+
content = '#!/bin/zsh\n\n';
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Check if already configured
|
|
374
|
+
const status = await checkIfAlreadyConfigured(configFile);
|
|
375
|
+
|
|
376
|
+
if (status.configured && !status.needsUpdate) {
|
|
377
|
+
return { updated: false, reason: 'already_configured' };
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Add or update environment variable
|
|
381
|
+
const envVarLine = `export ${ENV_VAR_NAME}="${envVarValue}"`;
|
|
382
|
+
const commentLine = '# ChromeDebug PRO extension path';
|
|
383
|
+
|
|
384
|
+
if (status.configured && status.needsUpdate) {
|
|
385
|
+
// Update existing line
|
|
386
|
+
const regex = new RegExp(`export ${ENV_VAR_NAME}=["']?[^"'\\n]+["']?`, 'g');
|
|
387
|
+
content = content.replace(regex, envVarLine);
|
|
388
|
+
} else {
|
|
389
|
+
// Add new lines
|
|
390
|
+
if (!content.endsWith('\n')) {
|
|
391
|
+
content += '\n';
|
|
392
|
+
}
|
|
393
|
+
content += `\n${commentLine}\n${envVarLine}\n`;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Write updated content
|
|
397
|
+
await fs.writeFile(configFile, content, 'utf-8');
|
|
398
|
+
|
|
399
|
+
// Ensure proper permissions
|
|
400
|
+
await fs.chmod(configFile, 0o644);
|
|
401
|
+
|
|
402
|
+
return { updated: true, reason: status.needsUpdate ? 'updated' : 'added' };
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Configure shell environment
|
|
407
|
+
*/
|
|
408
|
+
async function configureShell() {
|
|
409
|
+
const shell = detectShell();
|
|
410
|
+
const configFile = getShellConfigFile(shell);
|
|
411
|
+
|
|
412
|
+
await logInstall(`Detected shell: ${shell}`);
|
|
413
|
+
await logInstall(`Config file: ${configFile}`);
|
|
414
|
+
|
|
415
|
+
// Ensure config directory exists (for fish)
|
|
416
|
+
const configDir = path.dirname(configFile);
|
|
417
|
+
await fs.mkdir(configDir, { recursive: true });
|
|
418
|
+
|
|
419
|
+
// Update configuration
|
|
420
|
+
const result = await updateShellConfig(configFile, EXTENSION_DIR);
|
|
421
|
+
|
|
422
|
+
return { shell, configFile, ...result };
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Main installation flow
|
|
427
|
+
*/
|
|
428
|
+
export async function installPro(args) {
|
|
429
|
+
console.log('\nChromeDebug PRO License Installer\n');
|
|
430
|
+
|
|
431
|
+
try {
|
|
432
|
+
// Create ChromeDebug directory
|
|
433
|
+
await fs.mkdir(CHROMEDEBUG_DIR, { recursive: true });
|
|
434
|
+
|
|
435
|
+
// Start logging
|
|
436
|
+
await logInstall('=== Installation Started ===');
|
|
437
|
+
|
|
438
|
+
// 1. Validate arguments
|
|
439
|
+
const parsedArgs = validateArguments(args);
|
|
440
|
+
if (!parsedArgs) {
|
|
441
|
+
return process.exit(1);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const { license, extensionPath } = parsedArgs;
|
|
445
|
+
|
|
446
|
+
// 2. Validate license key
|
|
447
|
+
console.log('Validating license key...');
|
|
448
|
+
if (!validateLicenseKey(license)) {
|
|
449
|
+
await logInstall(`Invalid license key: ${maskLicenseKey(license)}`, true);
|
|
450
|
+
return process.exit(1);
|
|
451
|
+
}
|
|
452
|
+
await logInstall(`License key validated: ${maskLicenseKey(license)}`);
|
|
453
|
+
console.log(` License key validated: ${maskLicenseKey(license)}\n`);
|
|
454
|
+
|
|
455
|
+
// 3. Pre-flight checks
|
|
456
|
+
if (!(await preflightChecks())) {
|
|
457
|
+
await logInstall('Pre-flight checks failed', true);
|
|
458
|
+
return process.exit(1);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// 4. Check for existing installation
|
|
462
|
+
const existing = await checkExistingInstallation();
|
|
463
|
+
if (existing.exists) {
|
|
464
|
+
const message = `
|
|
465
|
+
Existing PRO installation found:
|
|
466
|
+
- Installed: ${new Date(existing.installed_at).toLocaleDateString()}
|
|
467
|
+
- Version: ${existing.extension_version}
|
|
468
|
+
- License: ${maskLicenseKey(existing.license_key)}
|
|
469
|
+
|
|
470
|
+
This will overwrite the existing installation.`;
|
|
471
|
+
|
|
472
|
+
promptConfirmation(message);
|
|
473
|
+
await logInstall('Overwriting existing installation');
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// 5. Extract extension
|
|
477
|
+
console.log('Extracting PRO extension...');
|
|
478
|
+
const extensionInfo = await extractExtension(extensionPath, EXTENSION_DIR);
|
|
479
|
+
await logInstall(`Extension extracted: ${extensionInfo.name} v${extensionInfo.version}`);
|
|
480
|
+
console.log(` PRO extension extracted to ${EXTENSION_DIR}`);
|
|
481
|
+
console.log(` Version: ${extensionInfo.version}\n`);
|
|
482
|
+
|
|
483
|
+
// Set extension directory permissions
|
|
484
|
+
await fs.chmod(EXTENSION_DIR, 0o755);
|
|
485
|
+
|
|
486
|
+
// 6. Save license information
|
|
487
|
+
console.log('Saving license information...');
|
|
488
|
+
await saveLicenseInfo(license, extensionInfo.version);
|
|
489
|
+
await logInstall(`License saved: ${maskLicenseKey(license)}`);
|
|
490
|
+
console.log(` License saved to ${LICENSE_FILE}\n`);
|
|
491
|
+
|
|
492
|
+
// 7. Configure shell environment
|
|
493
|
+
console.log('Configuring shell environment...');
|
|
494
|
+
let shellResult;
|
|
495
|
+
let shellConfigFailed = false;
|
|
496
|
+
|
|
497
|
+
try {
|
|
498
|
+
shellResult = await configureShell();
|
|
499
|
+
await logInstall(`Shell configured: ${shellResult.shell} (${shellResult.configFile})`);
|
|
500
|
+
|
|
501
|
+
if (shellResult.updated) {
|
|
502
|
+
console.log(` Shell configured: export ${ENV_VAR_NAME}="${EXTENSION_DIR}"`);
|
|
503
|
+
console.log(` Config file: ${shellResult.configFile}`);
|
|
504
|
+
console.log(` Backup saved: ${shellResult.configFile}.chromedebug-backup\n`);
|
|
505
|
+
} else {
|
|
506
|
+
console.log(` Shell already configured correctly\n`);
|
|
507
|
+
}
|
|
508
|
+
} catch (shellErr) {
|
|
509
|
+
shellConfigFailed = true;
|
|
510
|
+
await logInstall(`Shell configuration failed: ${shellErr.message}`, false);
|
|
511
|
+
console.log(`⚠ Could not automatically configure shell environment`);
|
|
512
|
+
console.log(` Error: ${shellErr.message}\n`);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// 8. Success!
|
|
516
|
+
await logInstall('=== Installation Completed Successfully ===');
|
|
517
|
+
|
|
518
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
519
|
+
console.log('✓ PRO features are now active!');
|
|
520
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
|
|
521
|
+
|
|
522
|
+
if (shellConfigFailed) {
|
|
523
|
+
console.log('⚠ Manual Configuration Required:');
|
|
524
|
+
console.log(` Add this line to your shell configuration file:`);
|
|
525
|
+
console.log(` export ${ENV_VAR_NAME}="${EXTENSION_DIR}"\n`);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
console.log('Next steps:');
|
|
529
|
+
if (shellResult && shellResult.configFile) {
|
|
530
|
+
console.log(`1. Restart your terminal or run: source ${shellResult.configFile}`);
|
|
531
|
+
} else {
|
|
532
|
+
console.log(`1. Add the environment variable to your shell config and restart terminal`);
|
|
533
|
+
}
|
|
534
|
+
console.log('2. Close any running Chrome instances');
|
|
535
|
+
console.log('3. Launch ChromeDebug MCP: chromedebug-mcp');
|
|
536
|
+
console.log('4. The PRO extension will be loaded automatically\n');
|
|
537
|
+
|
|
538
|
+
console.log('Verify installation:');
|
|
539
|
+
console.log(` echo $${ENV_VAR_NAME}`);
|
|
540
|
+
console.log(` (should output: ${EXTENSION_DIR})\n`);
|
|
541
|
+
|
|
542
|
+
console.log('Installation log: ' + INSTALL_LOG);
|
|
543
|
+
console.log('\nNeed help? https://github.com/dynamicupgrade/ChromeDebug/issues\n');
|
|
544
|
+
} catch (err) {
|
|
545
|
+
await logInstall(`Installation failed: ${err.message}`, true);
|
|
546
|
+
console.error('\n Installation failed\n');
|
|
547
|
+
console.error('Check the installation log for details: ' + INSTALL_LOG);
|
|
548
|
+
console.error('\nNeed help? https://github.com/dynamicupgrade/ChromeDebug/issues\n');
|
|
549
|
+
process.exit(1);
|
|
550
|
+
}
|
|
551
|
+
}
|