@dynamicu/chromedebug-mcp 2.2.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/CLAUDE.md +344 -0
- package/LICENSE +21 -0
- package/README.md +250 -0
- package/chrome-extension/README.md +41 -0
- package/chrome-extension/background.js +3917 -0
- package/chrome-extension/chrome-session-manager.js +706 -0
- package/chrome-extension/content.css +181 -0
- package/chrome-extension/content.js +3022 -0
- package/chrome-extension/data-buffer.js +435 -0
- package/chrome-extension/dom-tracker.js +411 -0
- package/chrome-extension/extension-config.js +78 -0
- package/chrome-extension/firebase-client.js +278 -0
- package/chrome-extension/firebase-config.js +32 -0
- package/chrome-extension/firebase-config.module.js +22 -0
- package/chrome-extension/firebase-config.module.template.js +27 -0
- package/chrome-extension/firebase-config.template.js +36 -0
- package/chrome-extension/frame-capture.js +407 -0
- package/chrome-extension/icon128.png +1 -0
- package/chrome-extension/icon16.png +1 -0
- package/chrome-extension/icon48.png +1 -0
- package/chrome-extension/license-helper.js +181 -0
- package/chrome-extension/logger.js +23 -0
- package/chrome-extension/manifest.json +73 -0
- package/chrome-extension/network-tracker.js +510 -0
- package/chrome-extension/offscreen.html +10 -0
- package/chrome-extension/options.html +203 -0
- package/chrome-extension/options.js +282 -0
- package/chrome-extension/pako.min.js +2 -0
- package/chrome-extension/performance-monitor.js +533 -0
- package/chrome-extension/pii-redactor.js +405 -0
- package/chrome-extension/popup.html +532 -0
- package/chrome-extension/popup.js +2446 -0
- package/chrome-extension/upload-manager.js +323 -0
- package/chrome-extension/web-vitals.iife.js +1 -0
- package/config/api-keys.json +11 -0
- package/config/chrome-pilot-config.json +45 -0
- package/package.json +126 -0
- package/scripts/cleanup-processes.js +109 -0
- package/scripts/config-manager.js +280 -0
- package/scripts/generate-extension-config.js +53 -0
- package/scripts/setup-security.js +64 -0
- package/src/capture/architecture.js +426 -0
- package/src/capture/error-handling-tests.md +38 -0
- package/src/capture/error-handling-types.ts +360 -0
- package/src/capture/index.js +508 -0
- package/src/capture/interfaces.js +625 -0
- package/src/capture/memory-manager.js +713 -0
- package/src/capture/types.js +342 -0
- package/src/chrome-controller.js +2658 -0
- package/src/cli.js +19 -0
- package/src/config-loader.js +303 -0
- package/src/database.js +2178 -0
- package/src/firebase-license-manager.js +462 -0
- package/src/firebase-privacy-guard.js +397 -0
- package/src/http-server.js +1516 -0
- package/src/index-direct.js +157 -0
- package/src/index-modular.js +219 -0
- package/src/index-monolithic-backup.js +2230 -0
- package/src/index.js +305 -0
- package/src/legacy/chrome-controller-old.js +1406 -0
- package/src/legacy/index-express.js +625 -0
- package/src/legacy/index-old.js +977 -0
- package/src/legacy/routes.js +260 -0
- package/src/legacy/shared-storage.js +101 -0
- package/src/logger.js +10 -0
- package/src/mcp/handlers/chrome-tool-handler.js +306 -0
- package/src/mcp/handlers/element-tool-handler.js +51 -0
- package/src/mcp/handlers/frame-tool-handler.js +957 -0
- package/src/mcp/handlers/request-handler.js +104 -0
- package/src/mcp/handlers/workflow-tool-handler.js +636 -0
- package/src/mcp/server.js +68 -0
- package/src/mcp/tools/index.js +701 -0
- package/src/middleware/auth.js +371 -0
- package/src/middleware/security.js +267 -0
- package/src/port-discovery.js +258 -0
- package/src/routes/admin.js +182 -0
- package/src/services/browser-daemon.js +494 -0
- package/src/services/chrome-service.js +375 -0
- package/src/services/failover-manager.js +412 -0
- package/src/services/git-safety-service.js +675 -0
- package/src/services/heartbeat-manager.js +200 -0
- package/src/services/http-client.js +195 -0
- package/src/services/process-manager.js +318 -0
- package/src/services/process-tracker.js +574 -0
- package/src/services/profile-manager.js +449 -0
- package/src/services/project-manager.js +415 -0
- package/src/services/session-manager.js +497 -0
- package/src/services/session-registry.js +491 -0
- package/src/services/unified-session-manager.js +678 -0
- package/src/shared-storage-old.js +267 -0
- package/src/standalone-server.js +53 -0
- package/src/utils/extension-path.js +145 -0
- package/src/utils.js +187 -0
- package/src/validation/log-transformer.js +125 -0
- package/src/validation/schemas.js +391 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProjectManager - Project-local directory management for Chrome Debug
|
|
3
|
+
*
|
|
4
|
+
* Provides intelligent project detection and creates project-local directory
|
|
5
|
+
* structures for Chrome Debug data (.chromedebug/ in project root).
|
|
6
|
+
*
|
|
7
|
+
* Key Features:
|
|
8
|
+
* - Automatic project type detection (npm, git, python, etc.)
|
|
9
|
+
* - Project-local directory structure creation
|
|
10
|
+
* - Automatic .gitignore management
|
|
11
|
+
* - Fallback to global mode when not in a valid project
|
|
12
|
+
* - Path validation and security
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { promises as fs, existsSync as fsExistsSync } from 'fs';
|
|
16
|
+
import path from 'path';
|
|
17
|
+
import os from 'os';
|
|
18
|
+
|
|
19
|
+
export class ProjectManager {
|
|
20
|
+
constructor() {
|
|
21
|
+
this.projectInfo = null;
|
|
22
|
+
this.projectStructure = null;
|
|
23
|
+
this.initialized = false;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Detects if current working directory is part of a valid project
|
|
28
|
+
* @param {string} startPath - Starting path for project detection (defaults to cwd)
|
|
29
|
+
* @returns {ProjectInfo|null} Project information or null if not in project
|
|
30
|
+
*/
|
|
31
|
+
detectProject(startPath = process.cwd()) {
|
|
32
|
+
try {
|
|
33
|
+
const resolvedPath = path.resolve(startPath);
|
|
34
|
+
const projectRoot = this.findProjectRoot(resolvedPath);
|
|
35
|
+
|
|
36
|
+
if (!projectRoot) {
|
|
37
|
+
console.log('[ProjectManager] No valid project detected from:', resolvedPath);
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Determine project type based on markers
|
|
42
|
+
const markers = this.getProjectMarkers(projectRoot);
|
|
43
|
+
const projectType = this.determineProjectType(markers);
|
|
44
|
+
|
|
45
|
+
this.projectInfo = {
|
|
46
|
+
projectDir: projectRoot,
|
|
47
|
+
type: projectType,
|
|
48
|
+
hasMarkers: markers
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
console.log(`[ProjectManager] Detected ${projectType} project at: ${projectRoot}`);
|
|
52
|
+
console.log(`[ProjectManager] Project markers found: ${markers.join(', ')}`);
|
|
53
|
+
|
|
54
|
+
return this.projectInfo;
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.warn('[ProjectManager] Error during project detection:', error.message);
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Recursively searches up directory tree for project markers
|
|
63
|
+
* @param {string} currentPath - Current path to check
|
|
64
|
+
* @returns {string|null} Project root path or null if not found
|
|
65
|
+
*/
|
|
66
|
+
findProjectRoot(currentPath) {
|
|
67
|
+
const rootPath = path.parse(currentPath).root;
|
|
68
|
+
|
|
69
|
+
// Don't go beyond root directory
|
|
70
|
+
if (currentPath === rootPath) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
// Check for project markers in current directory
|
|
76
|
+
const markers = this.getProjectMarkers(currentPath);
|
|
77
|
+
|
|
78
|
+
if (markers.length > 0) {
|
|
79
|
+
return currentPath;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Move up one directory and continue searching
|
|
83
|
+
const parentPath = path.dirname(currentPath);
|
|
84
|
+
|
|
85
|
+
// Avoid infinite recursion at root
|
|
86
|
+
if (parentPath === currentPath) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return this.findProjectRoot(parentPath);
|
|
91
|
+
} catch (error) {
|
|
92
|
+
// Directory might not exist or be accessible
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Gets list of project markers found in a directory
|
|
99
|
+
* @param {string} dirPath - Directory to check for markers
|
|
100
|
+
* @returns {string[]} Array of found marker file/directory names
|
|
101
|
+
*/
|
|
102
|
+
getProjectMarkers(dirPath) {
|
|
103
|
+
const markers = [
|
|
104
|
+
'package.json', // Node.js
|
|
105
|
+
'.git', // Git repository (directory or file for worktrees)
|
|
106
|
+
'requirements.txt', // Python
|
|
107
|
+
'pyproject.toml', // Python (modern)
|
|
108
|
+
'Pipfile', // Python pipenv
|
|
109
|
+
'Cargo.toml', // Rust
|
|
110
|
+
'pom.xml', // Maven (Java)
|
|
111
|
+
'build.gradle', // Gradle (Java/Kotlin)
|
|
112
|
+
'go.mod', // Go
|
|
113
|
+
'composer.json', // PHP Composer
|
|
114
|
+
'Gemfile', // Ruby
|
|
115
|
+
'.project', // Eclipse project
|
|
116
|
+
'CMakeLists.txt', // CMake
|
|
117
|
+
'Makefile' // Make
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
const found = [];
|
|
121
|
+
|
|
122
|
+
for (const marker of markers) {
|
|
123
|
+
try {
|
|
124
|
+
const markerPath = path.join(dirPath, marker);
|
|
125
|
+
|
|
126
|
+
if (this.existsSync(markerPath)) {
|
|
127
|
+
found.push(marker);
|
|
128
|
+
}
|
|
129
|
+
} catch (error) {
|
|
130
|
+
// Ignore access errors for individual markers
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return found;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Synchronously check if path exists (safer than fs.existsSync)
|
|
140
|
+
* @param {string} filePath - Path to check
|
|
141
|
+
* @returns {boolean} True if path exists
|
|
142
|
+
*/
|
|
143
|
+
existsSync(filePath) {
|
|
144
|
+
try {
|
|
145
|
+
return fsExistsSync(filePath);
|
|
146
|
+
} catch {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Determines project type based on found markers
|
|
153
|
+
* @param {string[]} markers - Found project markers
|
|
154
|
+
* @returns {string} Project type identifier
|
|
155
|
+
*/
|
|
156
|
+
determineProjectType(markers) {
|
|
157
|
+
// Priority order for type detection
|
|
158
|
+
if (markers.includes('package.json')) return 'npm';
|
|
159
|
+
if (markers.includes('requirements.txt') || markers.includes('pyproject.toml') || markers.includes('Pipfile')) return 'python';
|
|
160
|
+
if (markers.includes('Cargo.toml')) return 'rust';
|
|
161
|
+
if (markers.includes('pom.xml') || markers.includes('build.gradle')) return 'java';
|
|
162
|
+
if (markers.includes('go.mod')) return 'go';
|
|
163
|
+
if (markers.includes('composer.json')) return 'php';
|
|
164
|
+
if (markers.includes('Gemfile')) return 'ruby';
|
|
165
|
+
if (markers.includes('.git')) return 'git';
|
|
166
|
+
if (markers.includes('CMakeLists.txt') || markers.includes('Makefile')) return 'native';
|
|
167
|
+
|
|
168
|
+
return 'generic';
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Gets the project directory (must call detectProject first)
|
|
173
|
+
* @returns {string} Project directory path
|
|
174
|
+
* @throws {Error} If no project detected
|
|
175
|
+
*/
|
|
176
|
+
getProjectDir() {
|
|
177
|
+
if (!this.projectInfo) {
|
|
178
|
+
throw new Error('No project detected. Call detectProject() first.');
|
|
179
|
+
}
|
|
180
|
+
return this.projectInfo.projectDir;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Validates if a path is a valid project directory
|
|
185
|
+
* @param {string} dirPath - Path to validate
|
|
186
|
+
* @returns {boolean} True if valid project directory
|
|
187
|
+
*/
|
|
188
|
+
isValidProject(dirPath) {
|
|
189
|
+
if (!dirPath || typeof dirPath !== 'string') {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
try {
|
|
194
|
+
const resolvedPath = path.resolve(dirPath);
|
|
195
|
+
const markers = this.getProjectMarkers(resolvedPath);
|
|
196
|
+
return markers.length > 0;
|
|
197
|
+
} catch {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Initializes project-local directory structure
|
|
204
|
+
* Creates .chromedebug/ directory with subdirectories and .gitignore entry
|
|
205
|
+
* @returns {Promise<void>}
|
|
206
|
+
*/
|
|
207
|
+
async initializeProjectStructure() {
|
|
208
|
+
if (!this.projectInfo) {
|
|
209
|
+
throw new Error('No project detected. Call detectProject() first.');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const projectDir = this.projectInfo.projectDir;
|
|
213
|
+
|
|
214
|
+
// Create project structure configuration
|
|
215
|
+
this.projectStructure = {
|
|
216
|
+
baseDir: path.join(projectDir, '.chromedebug'),
|
|
217
|
+
sessionsDir: path.join(projectDir, '.chromedebug', 'sessions'),
|
|
218
|
+
databaseDir: path.join(projectDir, '.chromedebug', 'database'),
|
|
219
|
+
configDir: path.join(projectDir, '.chromedebug', 'config'),
|
|
220
|
+
logsDir: path.join(projectDir, '.chromedebug', 'logs')
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
console.log(`[ProjectManager] Initializing project structure in: ${this.projectStructure.baseDir}`);
|
|
224
|
+
|
|
225
|
+
try {
|
|
226
|
+
// Create all necessary directories
|
|
227
|
+
await fs.mkdir(this.projectStructure.baseDir, { recursive: true });
|
|
228
|
+
await fs.mkdir(this.projectStructure.sessionsDir, { recursive: true });
|
|
229
|
+
await fs.mkdir(this.projectStructure.databaseDir, { recursive: true });
|
|
230
|
+
await fs.mkdir(this.projectStructure.configDir, { recursive: true });
|
|
231
|
+
await fs.mkdir(this.projectStructure.logsDir, { recursive: true });
|
|
232
|
+
|
|
233
|
+
// Add .chromedebug to .gitignore if project has git
|
|
234
|
+
if (this.projectInfo.hasMarkers.includes('.git')) {
|
|
235
|
+
await this.updateGitignore(projectDir);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
console.log('[ProjectManager] Project structure initialized successfully');
|
|
239
|
+
console.log('[ProjectManager] Structure:', this.projectStructure);
|
|
240
|
+
|
|
241
|
+
this.initialized = true;
|
|
242
|
+
} catch (error) {
|
|
243
|
+
console.error('[ProjectManager] Failed to initialize project structure:', error);
|
|
244
|
+
throw new Error(`Project structure initialization failed: ${error.message}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Updates .gitignore to exclude .chromedebug directory
|
|
250
|
+
* @param {string} projectDir - Project directory path
|
|
251
|
+
* @returns {Promise<void>}
|
|
252
|
+
*/
|
|
253
|
+
async updateGitignore(projectDir) {
|
|
254
|
+
const gitignorePath = path.join(projectDir, '.gitignore');
|
|
255
|
+
const chromePilotEntry = '.chromedebug/';
|
|
256
|
+
|
|
257
|
+
try {
|
|
258
|
+
let gitignoreContent = '';
|
|
259
|
+
let needsUpdate = true;
|
|
260
|
+
|
|
261
|
+
// Read existing .gitignore if it exists
|
|
262
|
+
try {
|
|
263
|
+
gitignoreContent = await fs.readFile(gitignorePath, 'utf8');
|
|
264
|
+
|
|
265
|
+
// Check if .chromedebug is already ignored
|
|
266
|
+
const lines = gitignoreContent.split('\n');
|
|
267
|
+
const hasEntry = lines.some(line =>
|
|
268
|
+
line.trim() === chromePilotEntry ||
|
|
269
|
+
line.trim() === '.chromedebug' ||
|
|
270
|
+
line.trim() === '.chromedebug/*'
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
if (hasEntry) {
|
|
274
|
+
needsUpdate = false;
|
|
275
|
+
console.log('[ProjectManager] .chromedebug already in .gitignore');
|
|
276
|
+
}
|
|
277
|
+
} catch (error) {
|
|
278
|
+
// .gitignore doesn't exist, will create it
|
|
279
|
+
console.log('[ProjectManager] Creating new .gitignore file');
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (needsUpdate) {
|
|
283
|
+
// Ensure content ends with newline before adding entry
|
|
284
|
+
if (gitignoreContent && !gitignoreContent.endsWith('\n')) {
|
|
285
|
+
gitignoreContent += '\n';
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Add Chrome Debug section
|
|
289
|
+
const chromePilotSection = `
|
|
290
|
+
# Chrome Debug project-local data
|
|
291
|
+
${chromePilotEntry}
|
|
292
|
+
`;
|
|
293
|
+
|
|
294
|
+
gitignoreContent += chromePilotSection;
|
|
295
|
+
|
|
296
|
+
await fs.writeFile(gitignorePath, gitignoreContent, 'utf8');
|
|
297
|
+
console.log('[ProjectManager] Added .chromedebug to .gitignore');
|
|
298
|
+
}
|
|
299
|
+
} catch (error) {
|
|
300
|
+
console.warn('[ProjectManager] Warning: Could not update .gitignore:', error.message);
|
|
301
|
+
// Don't fail initialization if .gitignore update fails
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Gets the project structure paths (must initialize first)
|
|
307
|
+
* @returns {ProjectStructure} Project structure object
|
|
308
|
+
* @throws {Error} If not initialized
|
|
309
|
+
*/
|
|
310
|
+
getProjectStructure() {
|
|
311
|
+
if (!this.projectStructure) {
|
|
312
|
+
throw new Error('Project structure not initialized. Call initializeProjectStructure() first.');
|
|
313
|
+
}
|
|
314
|
+
return { ...this.projectStructure };
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Gets project-local database path
|
|
319
|
+
* @returns {string} Database file path
|
|
320
|
+
*/
|
|
321
|
+
getProjectDatabasePath() {
|
|
322
|
+
if (!this.projectStructure) {
|
|
323
|
+
throw new Error('Project structure not initialized');
|
|
324
|
+
}
|
|
325
|
+
return path.join(this.projectStructure.databaseDir, 'chromedebug.db');
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Gets project-local config path
|
|
330
|
+
* @returns {string} Config file path
|
|
331
|
+
*/
|
|
332
|
+
getProjectConfigPath() {
|
|
333
|
+
if (!this.projectStructure) {
|
|
334
|
+
throw new Error('Project structure not initialized');
|
|
335
|
+
}
|
|
336
|
+
return path.join(this.projectStructure.configDir, 'config.json');
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Gets project-local sessions directory path
|
|
341
|
+
* @returns {string} Sessions directory path
|
|
342
|
+
*/
|
|
343
|
+
getProjectSessionsDir() {
|
|
344
|
+
if (!this.projectStructure) {
|
|
345
|
+
throw new Error('Project structure not initialized');
|
|
346
|
+
}
|
|
347
|
+
return this.projectStructure.sessionsDir;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Gets project-local logs directory path
|
|
352
|
+
* @returns {string} Logs directory path
|
|
353
|
+
*/
|
|
354
|
+
getProjectLogsDir() {
|
|
355
|
+
if (!this.projectStructure) {
|
|
356
|
+
throw new Error('Project structure not initialized');
|
|
357
|
+
}
|
|
358
|
+
return this.projectStructure.logsDir;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Checks if project mode is available (project detected and initialized)
|
|
363
|
+
* @returns {boolean} True if project mode is available
|
|
364
|
+
*/
|
|
365
|
+
isProjectModeAvailable() {
|
|
366
|
+
return this.projectInfo !== null && this.initialized;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Gets fallback global directories for when not in project mode
|
|
371
|
+
* @returns {ProjectStructure} Global structure paths
|
|
372
|
+
*/
|
|
373
|
+
getGlobalStructure() {
|
|
374
|
+
const globalBaseDir = path.join(os.tmpdir(), 'chromedebug-global');
|
|
375
|
+
|
|
376
|
+
return {
|
|
377
|
+
baseDir: globalBaseDir,
|
|
378
|
+
sessionsDir: path.join(globalBaseDir, 'sessions'),
|
|
379
|
+
databaseDir: path.join(process.cwd(), 'data'), // Existing global database location
|
|
380
|
+
configDir: path.join(process.cwd(), 'config'), // Existing global config location
|
|
381
|
+
logsDir: globalBaseDir
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Resets the project manager state (useful for testing)
|
|
387
|
+
*/
|
|
388
|
+
reset() {
|
|
389
|
+
this.projectInfo = null;
|
|
390
|
+
this.projectStructure = null;
|
|
391
|
+
this.initialized = false;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Gets current mode ('project' or 'global')
|
|
396
|
+
* @returns {string} Current operational mode
|
|
397
|
+
*/
|
|
398
|
+
getCurrentMode() {
|
|
399
|
+
return this.isProjectModeAvailable() ? 'project' : 'global';
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Gets debug information about current state
|
|
404
|
+
* @returns {object} Debug information
|
|
405
|
+
*/
|
|
406
|
+
getDebugInfo() {
|
|
407
|
+
return {
|
|
408
|
+
mode: this.getCurrentMode(),
|
|
409
|
+
projectInfo: this.projectInfo,
|
|
410
|
+
projectStructure: this.projectStructure,
|
|
411
|
+
initialized: this.initialized,
|
|
412
|
+
cwd: process.cwd()
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
}
|