@rahul05ranjan/dhruv-cli 1.5.0 → 1.6.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.
@@ -1,29 +1,90 @@
1
1
  // Use .js extension for ESM compatibility
2
2
  import fs from 'fs';
3
3
  import path from 'path';
4
+ import { logger } from '../core/logger.js';
4
5
 
5
- export function detectProjectType(directory: string = process.cwd()): string {
6
+ export interface ProjectContext {
7
+ type: string;
8
+ framework?: string;
9
+ diagnostic?: string;
10
+ }
11
+
12
+ export function detectProjectDetails(directory: string = process.cwd()): ProjectContext {
6
13
  const file = (name: string) => path.join(directory, name);
7
14
 
8
15
  if (fs.existsSync(file('package.json'))) {
9
16
  let pkg: { dependencies?: Record<string, string>; devDependencies?: Record<string, string> };
10
17
  try {
11
18
  pkg = JSON.parse(fs.readFileSync(file('package.json'), 'utf-8'));
12
- } catch {
13
- return 'unknown';
19
+ } catch (err) {
20
+ const diagnostic = `Malformed package.json in ${directory}: ${(err as Error).message}`;
21
+ logger.warn(diagnostic);
22
+ return { type: 'unknown', diagnostic };
14
23
  }
15
24
 
16
25
  const dependencies = { ...pkg.dependencies, ...pkg.devDependencies };
17
- if (dependencies.react) return 'react';
18
- if (dependencies.next) return 'nextjs';
19
- if (dependencies.express) return 'node-express';
20
- if (dependencies.typescript || fs.existsSync(file('tsconfig.json'))) return 'node-typescript';
21
- return 'node';
26
+ if (dependencies.react) return { type: 'node', framework: 'react' };
27
+ if (dependencies.next) return { type: 'node', framework: 'nextjs' };
28
+ if (dependencies.vue) return { type: 'node', framework: 'vue' };
29
+ if (dependencies['@angular/core']) return { type: 'node', framework: 'angular' };
30
+ if (dependencies.svelte) return { type: 'node', framework: 'svelte' };
31
+ if (dependencies['@nestjs/core']) return { type: 'node', framework: 'nestjs' };
32
+ if (dependencies.express) return { type: 'node', framework: 'node-express' };
33
+ if (dependencies.typescript || fs.existsSync(file('tsconfig.json'))) return { type: 'node-typescript' };
34
+ return { type: 'node' };
35
+ }
36
+
37
+ if (fs.existsSync(file('tsconfig.json'))) {
38
+ return { type: 'node-typescript' };
39
+ }
40
+
41
+ if (fs.existsSync(file('requirements.txt')) || fs.existsSync(file('pyproject.toml')) || fs.existsSync(file('Pipfile')) || fs.existsSync(file('setup.py'))) {
42
+ let framework: string | undefined;
43
+ if (fs.existsSync(file('manage.py'))) {
44
+ framework = 'django';
45
+ } else if (fs.existsSync(file('requirements.txt'))) {
46
+ try {
47
+ const reqs = fs.readFileSync(file('requirements.txt'), 'utf-8');
48
+ if (/fastapi/i.test(reqs)) framework = 'fastapi';
49
+ else if (/flask/i.test(reqs)) framework = 'flask';
50
+ else if (/django/i.test(reqs)) framework = 'django';
51
+ } catch (err) {
52
+ const diagnostic = `Error reading requirements.txt: ${(err as Error).message}`;
53
+ logger.warn(diagnostic);
54
+ return { type: 'python', diagnostic };
55
+ }
56
+ }
57
+ return { type: 'python', framework };
58
+ }
59
+
60
+ if (fs.existsSync(file('go.mod'))) return { type: 'go' };
61
+ if (fs.existsSync(file('Cargo.toml'))) return { type: 'rust' };
62
+ if (fs.existsSync(file('pom.xml')) || fs.existsSync(file('build.gradle')) || fs.existsSync(file('build.gradle.kts'))) {
63
+ let framework: string | undefined;
64
+ try {
65
+ const pomPath = file('pom.xml');
66
+ const gradlePath = file('build.gradle');
67
+ const content = fs.existsSync(pomPath)
68
+ ? fs.readFileSync(pomPath, 'utf-8')
69
+ : (fs.existsSync(gradlePath) ? fs.readFileSync(gradlePath, 'utf-8') : '');
70
+ if (/spring-boot/i.test(content)) framework = 'spring-boot';
71
+ } catch {
72
+ // safe fallback
73
+ }
74
+ return { type: 'java', framework };
75
+ }
76
+
77
+ return { type: 'unknown' };
78
+ }
79
+
80
+ export function detectProjectType(directory: string = process.cwd()): string {
81
+ const details = detectProjectDetails(directory);
82
+ if (details.type === 'unknown') return 'unknown';
83
+ if (details.framework) {
84
+ if (details.framework === 'react' || details.framework === 'nextjs' || details.framework === 'node-express') {
85
+ return details.framework;
86
+ }
87
+ return `${details.type}-${details.framework}`;
22
88
  }
23
- if (fs.existsSync(file('requirements.txt'))) return 'python';
24
- if (fs.existsSync(file('pyproject.toml'))) return 'python';
25
- if (fs.existsSync(file('go.mod'))) return 'go';
26
- if (fs.existsSync(file('Cargo.toml'))) return 'rust';
27
- if (fs.existsSync(file('pom.xml')) || fs.existsSync(file('build.gradle'))) return 'java';
28
- return 'unknown';
89
+ return details.type;
29
90
  }