deepdebug-local-agent 0.3.1
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/.dockerignore +24 -0
- package/.idea/deepdebug-local-agent.iml +12 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/Dockerfile +46 -0
- package/cloudbuild.yaml +42 -0
- package/index.js +42 -0
- package/mcp-server.js +533 -0
- package/package.json +22 -0
- package/src/ai-engine.js +861 -0
- package/src/analyzers/config-analyzer.js +446 -0
- package/src/analyzers/controller-analyzer.js +429 -0
- package/src/analyzers/dto-analyzer.js +455 -0
- package/src/detectors/build-tool-detector.js +0 -0
- package/src/detectors/framework-detector.js +91 -0
- package/src/detectors/language-detector.js +89 -0
- package/src/detectors/multi-project-detector.js +191 -0
- package/src/detectors/service-detector.js +244 -0
- package/src/detectors.js +30 -0
- package/src/exec-utils.js +215 -0
- package/src/fs-utils.js +34 -0
- package/src/git/base-git-provider.js +384 -0
- package/src/git/git-provider-registry.js +110 -0
- package/src/git/github-provider.js +502 -0
- package/src/mcp-http-server.js +313 -0
- package/src/patch/patch-engine.js +339 -0
- package/src/patch-manager.js +816 -0
- package/src/patch.js +607 -0
- package/src/patch_bkp.js +154 -0
- package/src/ports.js +69 -0
- package/src/routes/workspace.route.js +528 -0
- package/src/runtimes/base-runtime.js +290 -0
- package/src/runtimes/java/gradle-runtime.js +378 -0
- package/src/runtimes/java/java-integrations.js +339 -0
- package/src/runtimes/java/maven-runtime.js +418 -0
- package/src/runtimes/node/node-integrations.js +247 -0
- package/src/runtimes/node/npm-runtime.js +466 -0
- package/src/runtimes/node/yarn-runtime.js +354 -0
- package/src/runtimes/runtime-registry.js +256 -0
- package/src/server-local.js +576 -0
- package/src/server.js +4565 -0
- package/src/utils/environment-diagnostics.js +666 -0
- package/src/utils/exec-utils.js +264 -0
- package/src/utils/fs-utils.js +218 -0
- package/src/workspace/detect-port.js +176 -0
- package/src/workspace/file-reader.js +54 -0
- package/src/workspace/git-client.js +0 -0
- package/src/workspace/process-manager.js +619 -0
- package/src/workspace/scanner.js +72 -0
- package/src/workspace-manager.js +172 -0
|
@@ -0,0 +1,666 @@
|
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
|
|
6
|
+
const execAsync = promisify(exec);
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* EnvironmentDiagnostics
|
|
10
|
+
*
|
|
11
|
+
* Detecta automaticamente ferramentas de desenvolvimento instaladas no sistema.
|
|
12
|
+
* Útil para debugging e setup do ambiente.
|
|
13
|
+
*/
|
|
14
|
+
export class EnvironmentDiagnostics {
|
|
15
|
+
|
|
16
|
+
constructor() {
|
|
17
|
+
this.cache = null;
|
|
18
|
+
this.cacheTime = 0;
|
|
19
|
+
this.cacheTTL = 60000; // 1 minuto
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Executa diagnóstico completo do ambiente
|
|
24
|
+
*/
|
|
25
|
+
async diagnose() {
|
|
26
|
+
// Usar cache se ainda válido
|
|
27
|
+
if (this.cache && (Date.now() - this.cacheTime) < this.cacheTTL) {
|
|
28
|
+
return this.cache;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const startTime = Date.now();
|
|
32
|
+
|
|
33
|
+
const [
|
|
34
|
+
system,
|
|
35
|
+
java,
|
|
36
|
+
maven,
|
|
37
|
+
gradle,
|
|
38
|
+
node,
|
|
39
|
+
npm,
|
|
40
|
+
yarn,
|
|
41
|
+
python,
|
|
42
|
+
pip,
|
|
43
|
+
go,
|
|
44
|
+
dotnet,
|
|
45
|
+
git,
|
|
46
|
+
docker
|
|
47
|
+
] = await Promise.all([
|
|
48
|
+
this.getSystemInfo(),
|
|
49
|
+
this.detectJava(),
|
|
50
|
+
this.detectMaven(),
|
|
51
|
+
this.detectGradle(),
|
|
52
|
+
this.detectNode(),
|
|
53
|
+
this.detectNpm(),
|
|
54
|
+
this.detectYarn(),
|
|
55
|
+
this.detectPython(),
|
|
56
|
+
this.detectPip(),
|
|
57
|
+
this.detectGo(),
|
|
58
|
+
this.detectDotnet(),
|
|
59
|
+
this.detectGit(),
|
|
60
|
+
this.detectDocker()
|
|
61
|
+
]);
|
|
62
|
+
|
|
63
|
+
const result = {
|
|
64
|
+
timestamp: new Date().toISOString(),
|
|
65
|
+
diagnosisTime: Date.now() - startTime,
|
|
66
|
+
system,
|
|
67
|
+
tools: {
|
|
68
|
+
java,
|
|
69
|
+
maven,
|
|
70
|
+
gradle,
|
|
71
|
+
node,
|
|
72
|
+
npm,
|
|
73
|
+
yarn,
|
|
74
|
+
python,
|
|
75
|
+
pip,
|
|
76
|
+
go,
|
|
77
|
+
dotnet,
|
|
78
|
+
git,
|
|
79
|
+
docker
|
|
80
|
+
},
|
|
81
|
+
summary: this.generateSummary({ java, maven, gradle, node, npm, yarn, python, go, dotnet }),
|
|
82
|
+
issues: this.detectIssues({ java, maven, gradle, node, npm, yarn, python, go, dotnet })
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
this.cache = result;
|
|
86
|
+
this.cacheTime = Date.now();
|
|
87
|
+
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Informações do sistema
|
|
93
|
+
*/
|
|
94
|
+
async getSystemInfo() {
|
|
95
|
+
return {
|
|
96
|
+
platform: os.platform(),
|
|
97
|
+
arch: os.arch(),
|
|
98
|
+
release: os.release(),
|
|
99
|
+
hostname: os.hostname(),
|
|
100
|
+
cpus: os.cpus().length,
|
|
101
|
+
memory: {
|
|
102
|
+
total: Math.round(os.totalmem() / 1024 / 1024 / 1024 * 100) / 100, // GB
|
|
103
|
+
free: Math.round(os.freemem() / 1024 / 1024 / 1024 * 100) / 100 // GB
|
|
104
|
+
},
|
|
105
|
+
uptime: Math.floor(os.uptime() / 3600), // hours
|
|
106
|
+
user: os.userInfo().username,
|
|
107
|
+
home: os.homedir(),
|
|
108
|
+
shell: process.env.SHELL || 'unknown'
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Detecta Java
|
|
114
|
+
*/
|
|
115
|
+
async detectJava() {
|
|
116
|
+
const result = {
|
|
117
|
+
installed: false,
|
|
118
|
+
version: null,
|
|
119
|
+
vendor: null,
|
|
120
|
+
javaHome: process.env.JAVA_HOME || null,
|
|
121
|
+
path: null
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
// Tentar java -version
|
|
126
|
+
const { stderr } = await execAsync('java -version 2>&1');
|
|
127
|
+
const output = stderr || '';
|
|
128
|
+
|
|
129
|
+
result.installed = true;
|
|
130
|
+
|
|
131
|
+
// Extrair versão (ex: "openjdk version "17.0.1"")
|
|
132
|
+
const versionMatch = output.match(/version\s+"([^"]+)"/);
|
|
133
|
+
if (versionMatch) {
|
|
134
|
+
result.version = versionMatch[1];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Extrair vendor
|
|
138
|
+
if (output.includes('OpenJDK')) {
|
|
139
|
+
result.vendor = 'OpenJDK';
|
|
140
|
+
} else if (output.includes('Oracle')) {
|
|
141
|
+
result.vendor = 'Oracle';
|
|
142
|
+
} else if (output.includes('Azul')) {
|
|
143
|
+
result.vendor = 'Azul Zulu';
|
|
144
|
+
} else if (output.includes('Amazon')) {
|
|
145
|
+
result.vendor = 'Amazon Corretto';
|
|
146
|
+
} else if (output.includes('Eclipse')) {
|
|
147
|
+
result.vendor = 'Eclipse Temurin';
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Encontrar path
|
|
151
|
+
const { stdout: whichOutput } = await execAsync('which java').catch(() => ({ stdout: '' }));
|
|
152
|
+
result.path = whichOutput.trim() || null;
|
|
153
|
+
|
|
154
|
+
} catch (err) {
|
|
155
|
+
result.error = err.message;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return result;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Detecta Maven
|
|
163
|
+
*/
|
|
164
|
+
async detectMaven() {
|
|
165
|
+
const result = {
|
|
166
|
+
installed: false,
|
|
167
|
+
version: null,
|
|
168
|
+
path: null,
|
|
169
|
+
mavenHome: process.env.MAVEN_HOME || process.env.M2_HOME || null
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
const { stdout } = await execAsync('mvn -version 2>&1');
|
|
174
|
+
|
|
175
|
+
result.installed = true;
|
|
176
|
+
|
|
177
|
+
// Extrair versão (ex: "Apache Maven 3.9.0")
|
|
178
|
+
const versionMatch = stdout.match(/Apache Maven (\d+\.\d+\.\d+)/);
|
|
179
|
+
if (versionMatch) {
|
|
180
|
+
result.version = versionMatch[1];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Extrair Java version usado pelo Maven
|
|
184
|
+
const javaMatch = stdout.match(/Java version: ([^\n,]+)/);
|
|
185
|
+
if (javaMatch) {
|
|
186
|
+
result.javaVersion = javaMatch[1].trim();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Encontrar path
|
|
190
|
+
const { stdout: whichOutput } = await execAsync('which mvn').catch(() => ({ stdout: '' }));
|
|
191
|
+
result.path = whichOutput.trim() || null;
|
|
192
|
+
|
|
193
|
+
} catch (err) {
|
|
194
|
+
result.error = err.message;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return result;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Detecta Gradle
|
|
202
|
+
*/
|
|
203
|
+
async detectGradle() {
|
|
204
|
+
const result = {
|
|
205
|
+
installed: false,
|
|
206
|
+
version: null,
|
|
207
|
+
path: null,
|
|
208
|
+
gradleHome: process.env.GRADLE_HOME || null
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
try {
|
|
212
|
+
const { stdout } = await execAsync('gradle -version 2>&1');
|
|
213
|
+
|
|
214
|
+
result.installed = true;
|
|
215
|
+
|
|
216
|
+
// Extrair versão (ex: "Gradle 8.0")
|
|
217
|
+
const versionMatch = stdout.match(/Gradle (\d+\.\d+\.?\d*)/);
|
|
218
|
+
if (versionMatch) {
|
|
219
|
+
result.version = versionMatch[1];
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Encontrar path
|
|
223
|
+
const { stdout: whichOutput } = await execAsync('which gradle').catch(() => ({ stdout: '' }));
|
|
224
|
+
result.path = whichOutput.trim() || null;
|
|
225
|
+
|
|
226
|
+
} catch (err) {
|
|
227
|
+
result.error = err.message;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Detecta Node.js
|
|
235
|
+
*/
|
|
236
|
+
async detectNode() {
|
|
237
|
+
const result = {
|
|
238
|
+
installed: false,
|
|
239
|
+
version: null,
|
|
240
|
+
path: null
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
try {
|
|
244
|
+
const { stdout } = await execAsync('node -version 2>&1');
|
|
245
|
+
|
|
246
|
+
result.installed = true;
|
|
247
|
+
result.version = stdout.trim().replace('v', '');
|
|
248
|
+
|
|
249
|
+
// Encontrar path
|
|
250
|
+
const { stdout: whichOutput } = await execAsync('which node').catch(() => ({ stdout: '' }));
|
|
251
|
+
result.path = whichOutput.trim() || null;
|
|
252
|
+
|
|
253
|
+
} catch (err) {
|
|
254
|
+
result.error = err.message;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return result;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Detecta npm
|
|
262
|
+
*/
|
|
263
|
+
async detectNpm() {
|
|
264
|
+
const result = {
|
|
265
|
+
installed: false,
|
|
266
|
+
version: null,
|
|
267
|
+
path: null,
|
|
268
|
+
globalPrefix: null
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
try {
|
|
272
|
+
const { stdout } = await execAsync('npm -version 2>&1');
|
|
273
|
+
|
|
274
|
+
result.installed = true;
|
|
275
|
+
result.version = stdout.trim();
|
|
276
|
+
|
|
277
|
+
// Prefix global
|
|
278
|
+
const { stdout: prefixOutput } = await execAsync('npm config get prefix').catch(() => ({ stdout: '' }));
|
|
279
|
+
result.globalPrefix = prefixOutput.trim() || null;
|
|
280
|
+
|
|
281
|
+
// Encontrar path
|
|
282
|
+
const { stdout: whichOutput } = await execAsync('which npm').catch(() => ({ stdout: '' }));
|
|
283
|
+
result.path = whichOutput.trim() || null;
|
|
284
|
+
|
|
285
|
+
} catch (err) {
|
|
286
|
+
result.error = err.message;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return result;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Detecta Yarn
|
|
294
|
+
*/
|
|
295
|
+
async detectYarn() {
|
|
296
|
+
const result = {
|
|
297
|
+
installed: false,
|
|
298
|
+
version: null,
|
|
299
|
+
path: null
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
try {
|
|
303
|
+
const { stdout } = await execAsync('yarn -version 2>&1');
|
|
304
|
+
|
|
305
|
+
result.installed = true;
|
|
306
|
+
result.version = stdout.trim();
|
|
307
|
+
|
|
308
|
+
// Encontrar path
|
|
309
|
+
const { stdout: whichOutput } = await execAsync('which yarn').catch(() => ({ stdout: '' }));
|
|
310
|
+
result.path = whichOutput.trim() || null;
|
|
311
|
+
|
|
312
|
+
} catch (err) {
|
|
313
|
+
result.error = err.message;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return result;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Detecta Python
|
|
321
|
+
*/
|
|
322
|
+
async detectPython() {
|
|
323
|
+
const result = {
|
|
324
|
+
installed: false,
|
|
325
|
+
version: null,
|
|
326
|
+
path: null,
|
|
327
|
+
python3: false
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
try {
|
|
331
|
+
// Tentar python3 primeiro
|
|
332
|
+
const { stdout } = await execAsync('python3 --version 2>&1').catch(() =>
|
|
333
|
+
execAsync('python --version 2>&1')
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
result.installed = true;
|
|
337
|
+
|
|
338
|
+
// Extrair versão (ex: "Python 3.11.0")
|
|
339
|
+
const versionMatch = stdout.match(/Python (\d+\.\d+\.?\d*)/);
|
|
340
|
+
if (versionMatch) {
|
|
341
|
+
result.version = versionMatch[1];
|
|
342
|
+
result.python3 = result.version.startsWith('3');
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Encontrar path
|
|
346
|
+
const { stdout: whichOutput } = await execAsync('which python3 || which python').catch(() => ({ stdout: '' }));
|
|
347
|
+
result.path = whichOutput.trim() || null;
|
|
348
|
+
|
|
349
|
+
} catch (err) {
|
|
350
|
+
result.error = err.message;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return result;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Detecta pip
|
|
358
|
+
*/
|
|
359
|
+
async detectPip() {
|
|
360
|
+
const result = {
|
|
361
|
+
installed: false,
|
|
362
|
+
version: null,
|
|
363
|
+
path: null
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
try {
|
|
367
|
+
const { stdout } = await execAsync('pip3 --version 2>&1').catch(() =>
|
|
368
|
+
execAsync('pip --version 2>&1')
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
result.installed = true;
|
|
372
|
+
|
|
373
|
+
// Extrair versão (ex: "pip 23.0.1")
|
|
374
|
+
const versionMatch = stdout.match(/pip (\d+\.\d+\.?\d*)/);
|
|
375
|
+
if (versionMatch) {
|
|
376
|
+
result.version = versionMatch[1];
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Encontrar path
|
|
380
|
+
const { stdout: whichOutput } = await execAsync('which pip3 || which pip').catch(() => ({ stdout: '' }));
|
|
381
|
+
result.path = whichOutput.trim() || null;
|
|
382
|
+
|
|
383
|
+
} catch (err) {
|
|
384
|
+
result.error = err.message;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return result;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Detecta Go
|
|
392
|
+
*/
|
|
393
|
+
async detectGo() {
|
|
394
|
+
const result = {
|
|
395
|
+
installed: false,
|
|
396
|
+
version: null,
|
|
397
|
+
path: null,
|
|
398
|
+
gopath: process.env.GOPATH || null,
|
|
399
|
+
goroot: process.env.GOROOT || null
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
try {
|
|
403
|
+
const { stdout } = await execAsync('go version 2>&1');
|
|
404
|
+
|
|
405
|
+
result.installed = true;
|
|
406
|
+
|
|
407
|
+
// Extrair versão (ex: "go version go1.21.0 darwin/amd64")
|
|
408
|
+
const versionMatch = stdout.match(/go(\d+\.\d+\.?\d*)/);
|
|
409
|
+
if (versionMatch) {
|
|
410
|
+
result.version = versionMatch[1];
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Encontrar path
|
|
414
|
+
const { stdout: whichOutput } = await execAsync('which go').catch(() => ({ stdout: '' }));
|
|
415
|
+
result.path = whichOutput.trim() || null;
|
|
416
|
+
|
|
417
|
+
} catch (err) {
|
|
418
|
+
result.error = err.message;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
return result;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Detecta .NET
|
|
426
|
+
*/
|
|
427
|
+
async detectDotnet() {
|
|
428
|
+
const result = {
|
|
429
|
+
installed: false,
|
|
430
|
+
version: null,
|
|
431
|
+
sdks: [],
|
|
432
|
+
runtimes: [],
|
|
433
|
+
path: null
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
try {
|
|
437
|
+
const { stdout } = await execAsync('dotnet --version 2>&1');
|
|
438
|
+
|
|
439
|
+
result.installed = true;
|
|
440
|
+
result.version = stdout.trim();
|
|
441
|
+
|
|
442
|
+
// Listar SDKs
|
|
443
|
+
const { stdout: sdkOutput } = await execAsync('dotnet --list-sdks 2>&1').catch(() => ({ stdout: '' }));
|
|
444
|
+
result.sdks = sdkOutput.trim().split('\n').filter(Boolean);
|
|
445
|
+
|
|
446
|
+
// Listar Runtimes
|
|
447
|
+
const { stdout: runtimeOutput } = await execAsync('dotnet --list-runtimes 2>&1').catch(() => ({ stdout: '' }));
|
|
448
|
+
result.runtimes = runtimeOutput.trim().split('\n').filter(Boolean).slice(0, 5); // Limitar
|
|
449
|
+
|
|
450
|
+
// Encontrar path
|
|
451
|
+
const { stdout: whichOutput } = await execAsync('which dotnet').catch(() => ({ stdout: '' }));
|
|
452
|
+
result.path = whichOutput.trim() || null;
|
|
453
|
+
|
|
454
|
+
} catch (err) {
|
|
455
|
+
result.error = err.message;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
return result;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Detecta Git
|
|
463
|
+
*/
|
|
464
|
+
async detectGit() {
|
|
465
|
+
const result = {
|
|
466
|
+
installed: false,
|
|
467
|
+
version: null,
|
|
468
|
+
path: null,
|
|
469
|
+
user: null,
|
|
470
|
+
email: null
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
try {
|
|
474
|
+
const { stdout } = await execAsync('git --version 2>&1');
|
|
475
|
+
|
|
476
|
+
result.installed = true;
|
|
477
|
+
|
|
478
|
+
// Extrair versão (ex: "git version 2.39.0")
|
|
479
|
+
const versionMatch = stdout.match(/git version (\d+\.\d+\.?\d*)/);
|
|
480
|
+
if (versionMatch) {
|
|
481
|
+
result.version = versionMatch[1];
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// User e email
|
|
485
|
+
const { stdout: userOutput } = await execAsync('git config --global user.name').catch(() => ({ stdout: '' }));
|
|
486
|
+
result.user = userOutput.trim() || null;
|
|
487
|
+
|
|
488
|
+
const { stdout: emailOutput } = await execAsync('git config --global user.email').catch(() => ({ stdout: '' }));
|
|
489
|
+
result.email = emailOutput.trim() || null;
|
|
490
|
+
|
|
491
|
+
// Encontrar path
|
|
492
|
+
const { stdout: whichOutput } = await execAsync('which git').catch(() => ({ stdout: '' }));
|
|
493
|
+
result.path = whichOutput.trim() || null;
|
|
494
|
+
|
|
495
|
+
} catch (err) {
|
|
496
|
+
result.error = err.message;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
return result;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Detecta Docker
|
|
504
|
+
*/
|
|
505
|
+
async detectDocker() {
|
|
506
|
+
const result = {
|
|
507
|
+
installed: false,
|
|
508
|
+
version: null,
|
|
509
|
+
running: false,
|
|
510
|
+
path: null
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
try {
|
|
514
|
+
const { stdout } = await execAsync('docker --version 2>&1');
|
|
515
|
+
|
|
516
|
+
result.installed = true;
|
|
517
|
+
|
|
518
|
+
// Extrair versão (ex: "Docker version 24.0.0, build xxx")
|
|
519
|
+
const versionMatch = stdout.match(/Docker version (\d+\.\d+\.?\d*)/);
|
|
520
|
+
if (versionMatch) {
|
|
521
|
+
result.version = versionMatch[1];
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Verificar se está rodando
|
|
525
|
+
try {
|
|
526
|
+
await execAsync('docker info 2>&1');
|
|
527
|
+
result.running = true;
|
|
528
|
+
} catch {
|
|
529
|
+
result.running = false;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// Encontrar path
|
|
533
|
+
const { stdout: whichOutput } = await execAsync('which docker').catch(() => ({ stdout: '' }));
|
|
534
|
+
result.path = whichOutput.trim() || null;
|
|
535
|
+
|
|
536
|
+
} catch (err) {
|
|
537
|
+
result.error = err.message;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
return result;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Gera sumário das capacidades
|
|
545
|
+
*/
|
|
546
|
+
generateSummary(tools) {
|
|
547
|
+
const capabilities = [];
|
|
548
|
+
|
|
549
|
+
if (tools.java?.installed && tools.maven?.installed) {
|
|
550
|
+
capabilities.push('java-maven');
|
|
551
|
+
}
|
|
552
|
+
if (tools.java?.installed && tools.gradle?.installed) {
|
|
553
|
+
capabilities.push('java-gradle');
|
|
554
|
+
}
|
|
555
|
+
if (tools.node?.installed && tools.npm?.installed) {
|
|
556
|
+
capabilities.push('node-npm');
|
|
557
|
+
}
|
|
558
|
+
if (tools.node?.installed && tools.yarn?.installed) {
|
|
559
|
+
capabilities.push('node-yarn');
|
|
560
|
+
}
|
|
561
|
+
if (tools.python?.installed) {
|
|
562
|
+
capabilities.push('python');
|
|
563
|
+
}
|
|
564
|
+
if (tools.go?.installed) {
|
|
565
|
+
capabilities.push('go');
|
|
566
|
+
}
|
|
567
|
+
if (tools.dotnet?.installed) {
|
|
568
|
+
capabilities.push('dotnet');
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
return {
|
|
572
|
+
capabilities,
|
|
573
|
+
canRunJava: tools.java?.installed && (tools.maven?.installed || tools.gradle?.installed),
|
|
574
|
+
canRunNode: tools.node?.installed && (tools.npm?.installed || tools.yarn?.installed),
|
|
575
|
+
canRunPython: tools.python?.installed,
|
|
576
|
+
canRunGo: tools.go?.installed,
|
|
577
|
+
canRunDotnet: tools.dotnet?.installed
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Detecta problemas de configuração
|
|
583
|
+
*/
|
|
584
|
+
detectIssues(tools) {
|
|
585
|
+
const issues = [];
|
|
586
|
+
|
|
587
|
+
// Java sem JAVA_HOME
|
|
588
|
+
if (tools.java?.installed && !process.env.JAVA_HOME) {
|
|
589
|
+
issues.push({
|
|
590
|
+
severity: 'warning',
|
|
591
|
+
tool: 'java',
|
|
592
|
+
message: 'JAVA_HOME não está configurado',
|
|
593
|
+
fix: 'export JAVA_HOME=$(/usr/libexec/java_home)'
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// Java instalado mas Maven não
|
|
598
|
+
if (tools.java?.installed && !tools.maven?.installed) {
|
|
599
|
+
issues.push({
|
|
600
|
+
severity: 'info',
|
|
601
|
+
tool: 'maven',
|
|
602
|
+
message: 'Maven não está instalado (necessário para projetos Maven)',
|
|
603
|
+
fix: 'brew install maven'
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// Node sem npm
|
|
608
|
+
if (tools.node?.installed && !tools.npm?.installed) {
|
|
609
|
+
issues.push({
|
|
610
|
+
severity: 'error',
|
|
611
|
+
tool: 'npm',
|
|
612
|
+
message: 'Node está instalado mas npm não foi encontrado',
|
|
613
|
+
fix: 'Reinstale o Node.js'
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// Python 2 ao invés de 3
|
|
618
|
+
if (tools.python?.installed && !tools.python?.python3) {
|
|
619
|
+
issues.push({
|
|
620
|
+
severity: 'warning',
|
|
621
|
+
tool: 'python',
|
|
622
|
+
message: 'Python 2 detectado. Recomendado usar Python 3',
|
|
623
|
+
fix: 'brew install python3'
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
return issues;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* Diagnóstico rápido apenas para uma linguagem
|
|
632
|
+
*/
|
|
633
|
+
async diagnoseFor(language) {
|
|
634
|
+
switch (language) {
|
|
635
|
+
case 'java':
|
|
636
|
+
return {
|
|
637
|
+
java: await this.detectJava(),
|
|
638
|
+
maven: await this.detectMaven(),
|
|
639
|
+
gradle: await this.detectGradle()
|
|
640
|
+
};
|
|
641
|
+
case 'node':
|
|
642
|
+
return {
|
|
643
|
+
node: await this.detectNode(),
|
|
644
|
+
npm: await this.detectNpm(),
|
|
645
|
+
yarn: await this.detectYarn()
|
|
646
|
+
};
|
|
647
|
+
case 'python':
|
|
648
|
+
return {
|
|
649
|
+
python: await this.detectPython(),
|
|
650
|
+
pip: await this.detectPip()
|
|
651
|
+
};
|
|
652
|
+
case 'go':
|
|
653
|
+
return {
|
|
654
|
+
go: await this.detectGo()
|
|
655
|
+
};
|
|
656
|
+
case 'dotnet':
|
|
657
|
+
return {
|
|
658
|
+
dotnet: await this.detectDotnet()
|
|
659
|
+
};
|
|
660
|
+
default:
|
|
661
|
+
return await this.diagnose();
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
export default EnvironmentDiagnostics;
|