projscan 0.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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +193 -0
  3. package/dist/analyzers/architectureCheck.d.ts +2 -0
  4. package/dist/analyzers/architectureCheck.js +91 -0
  5. package/dist/analyzers/architectureCheck.js.map +1 -0
  6. package/dist/analyzers/dependencyRiskCheck.d.ts +2 -0
  7. package/dist/analyzers/dependencyRiskCheck.js +17 -0
  8. package/dist/analyzers/dependencyRiskCheck.js.map +1 -0
  9. package/dist/analyzers/eslintCheck.d.ts +2 -0
  10. package/dist/analyzers/eslintCheck.js +49 -0
  11. package/dist/analyzers/eslintCheck.js.map +1 -0
  12. package/dist/analyzers/prettierCheck.d.ts +2 -0
  13. package/dist/analyzers/prettierCheck.js +53 -0
  14. package/dist/analyzers/prettierCheck.js.map +1 -0
  15. package/dist/analyzers/testCheck.d.ts +2 -0
  16. package/dist/analyzers/testCheck.js +52 -0
  17. package/dist/analyzers/testCheck.js.map +1 -0
  18. package/dist/cli/index.d.ts +2 -0
  19. package/dist/cli/index.js +558 -0
  20. package/dist/cli/index.js.map +1 -0
  21. package/dist/core/dependencyAnalyzer.d.ts +2 -0
  22. package/dist/core/dependencyAnalyzer.js +96 -0
  23. package/dist/core/dependencyAnalyzer.js.map +1 -0
  24. package/dist/core/frameworkDetector.d.ts +2 -0
  25. package/dist/core/frameworkDetector.js +152 -0
  26. package/dist/core/frameworkDetector.js.map +1 -0
  27. package/dist/core/issueEngine.d.ts +2 -0
  28. package/dist/core/issueEngine.js +21 -0
  29. package/dist/core/issueEngine.js.map +1 -0
  30. package/dist/core/languageDetector.d.ts +2 -0
  31. package/dist/core/languageDetector.js +107 -0
  32. package/dist/core/languageDetector.js.map +1 -0
  33. package/dist/core/repositoryScanner.d.ts +2 -0
  34. package/dist/core/repositoryScanner.js +79 -0
  35. package/dist/core/repositoryScanner.js.map +1 -0
  36. package/dist/fixes/editorconfigFix.d.ts +2 -0
  37. package/dist/fixes/editorconfigFix.js +28 -0
  38. package/dist/fixes/editorconfigFix.js.map +1 -0
  39. package/dist/fixes/eslintFix.d.ts +2 -0
  40. package/dist/fixes/eslintFix.js +46 -0
  41. package/dist/fixes/eslintFix.js.map +1 -0
  42. package/dist/fixes/fixRegistry.d.ts +3 -0
  43. package/dist/fixes/fixRegistry.js +24 -0
  44. package/dist/fixes/fixRegistry.js.map +1 -0
  45. package/dist/fixes/prettierFix.d.ts +2 -0
  46. package/dist/fixes/prettierFix.js +39 -0
  47. package/dist/fixes/prettierFix.js.map +1 -0
  48. package/dist/fixes/testFix.d.ts +2 -0
  49. package/dist/fixes/testFix.js +61 -0
  50. package/dist/fixes/testFix.js.map +1 -0
  51. package/dist/index.d.ts +7 -0
  52. package/dist/index.js +7 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/reporters/consoleReporter.d.ts +9 -0
  55. package/dist/reporters/consoleReporter.js +240 -0
  56. package/dist/reporters/consoleReporter.js.map +1 -0
  57. package/dist/reporters/jsonReporter.d.ts +7 -0
  58. package/dist/reporters/jsonReporter.js +27 -0
  59. package/dist/reporters/jsonReporter.js.map +1 -0
  60. package/dist/reporters/markdownReporter.d.ts +7 -0
  61. package/dist/reporters/markdownReporter.js +129 -0
  62. package/dist/reporters/markdownReporter.js.map +1 -0
  63. package/dist/types.d.ts +110 -0
  64. package/dist/types.js +3 -0
  65. package/dist/types.js.map +1 -0
  66. package/dist/utils/cache.d.ts +3 -0
  67. package/dist/utils/cache.js +51 -0
  68. package/dist/utils/cache.js.map +1 -0
  69. package/dist/utils/fileWalker.d.ts +7 -0
  70. package/dist/utils/fileWalker.js +45 -0
  71. package/dist/utils/fileWalker.js.map +1 -0
  72. package/dist/utils/logger.d.ts +9 -0
  73. package/dist/utils/logger.js +41 -0
  74. package/dist/utils/logger.js.map +1 -0
  75. package/package.json +48 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Abhi Yoheswaran
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,193 @@
1
+ # projscan
2
+
3
+ Instant codebase insights — doctor, x-ray, and architecture map for any repository.
4
+
5
+ Run once, learn something immediately. Run daily, improve your codebase.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install -g projscan
11
+ ```
12
+
13
+ Or run directly:
14
+
15
+ ```bash
16
+ npx projscan
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ Run inside any repository:
22
+
23
+ ```bash
24
+ projscan
25
+ ```
26
+
27
+ This runs the default `analyze` command and outputs a full project report including language breakdown, frameworks, structure, issues, and suggestions.
28
+
29
+ For a comprehensive walkthrough of every feature, use case, and output format, see the **[Full Guide](docs/GUIDE.md)**.
30
+
31
+ ## Commands
32
+
33
+ ### `projscan analyze`
34
+
35
+ Full project analysis — language detection, framework detection, dependency audit, and issue scanning.
36
+
37
+ ```bash
38
+ projscan analyze
39
+ ```
40
+
41
+ ### `projscan doctor`
42
+
43
+ Health check for your project. Detects missing tooling, architecture smells, and dependency risks.
44
+
45
+ ```bash
46
+ projscan doctor
47
+ ```
48
+
49
+ Example output:
50
+
51
+ ```
52
+ Project Health Report
53
+ ──────────────────────────────────────────
54
+
55
+ Found 3 warnings, 2 info
56
+
57
+ Issues Detected
58
+ ──────────────────────────────────────────
59
+ ⚠ No ESLint configuration
60
+ ⚠ No Prettier configuration
61
+ ⚠ No test framework detected
62
+ ℹ Missing .editorconfig
63
+ ℹ README is nearly empty
64
+
65
+ Recommendations
66
+ ──────────────────────────────────────────
67
+ 1. Fix: No ESLint configuration
68
+ 2. Fix: No Prettier configuration
69
+ 3. Fix: No test framework detected
70
+ 4. Fix: Missing .editorconfig
71
+
72
+ Run projscan fix to auto-fix 4 issues.
73
+ ```
74
+
75
+ ### `projscan fix`
76
+
77
+ Automatically installs and configures missing developer tools.
78
+
79
+ ```bash
80
+ projscan fix
81
+ ```
82
+
83
+ Detects issues, proposes fixes, prompts for confirmation, then applies:
84
+
85
+ - Installs ESLint with TypeScript support
86
+ - Installs Prettier with sensible defaults
87
+ - Installs Vitest with a sample test
88
+ - Creates `.editorconfig`
89
+
90
+ Use `-y` to skip the prompt:
91
+
92
+ ```bash
93
+ projscan fix -y
94
+ ```
95
+
96
+ ### `projscan explain <file>`
97
+
98
+ Explains a file — its purpose, imports, exports, and potential issues.
99
+
100
+ ```bash
101
+ projscan explain src/services/payment.ts
102
+ ```
103
+
104
+ ### `projscan diagram`
105
+
106
+ Generates an ASCII architecture diagram showing project layers and technologies.
107
+
108
+ ```bash
109
+ projscan diagram
110
+ ```
111
+
112
+ ### `projscan structure`
113
+
114
+ Shows the project directory tree with file counts.
115
+
116
+ ```bash
117
+ projscan structure
118
+ ```
119
+
120
+ ### `projscan dependencies`
121
+
122
+ Analyzes project dependencies — counts, risks, and recommendations.
123
+
124
+ ```bash
125
+ projscan dependencies
126
+ ```
127
+
128
+ ## Output Formats
129
+
130
+ All commands support `--format` for different output targets:
131
+
132
+ ```bash
133
+ projscan analyze --format json
134
+ projscan doctor --format markdown > HEALTH.md
135
+ ```
136
+
137
+ Formats: `console` (default), `json`, `markdown`
138
+
139
+ ## Options
140
+
141
+ | Flag | Description |
142
+ |------|-------------|
143
+ | `--format <type>` | Output format: console, json, markdown |
144
+ | `--verbose` | Enable debug output |
145
+ | `--quiet` | Suppress non-essential output |
146
+ | `-V, --version` | Show version |
147
+ | `-h, --help` | Show help |
148
+
149
+ ## Performance
150
+
151
+ ProjScan is designed for speed:
152
+
153
+ - 5,000 files analyzed in under 1.5 seconds
154
+ - 20,000 files analyzed in under 3 seconds
155
+ - Zero network requests — everything runs locally
156
+ - Minimal dependencies (4 runtime packages)
157
+
158
+ ## What It Detects
159
+
160
+ **Languages**: TypeScript, JavaScript, Python, Go, Rust, Java, Ruby, C/C++, PHP, Swift, Kotlin, and 20+ more
161
+
162
+ **Frameworks**: React, Next.js, Vue, Nuxt, Svelte, Angular, Express, Fastify, NestJS, Vite, Tailwind CSS, Prisma, and more
163
+
164
+ **Issues**:
165
+ - Missing ESLint configuration
166
+ - Missing Prettier configuration
167
+ - Missing test framework
168
+ - Missing `.editorconfig`
169
+ - Large utility directories (architecture smell)
170
+ - Excessive dependencies
171
+ - Deprecated packages
172
+ - Wildcard version ranges
173
+ - Missing lockfile
174
+
175
+ ## Development
176
+
177
+ ```bash
178
+ git clone https://github.com/your-org/projscan.git
179
+ cd projscan
180
+ npm install
181
+ npm run build
182
+ npm link
183
+ ```
184
+
185
+ Run tests:
186
+
187
+ ```bash
188
+ npm test
189
+ ```
190
+
191
+ ## License
192
+
193
+ MIT
@@ -0,0 +1,2 @@
1
+ import type { FileEntry, Issue } from '../types.js';
2
+ export declare function check(rootPath: string, files: FileEntry[]): Promise<Issue[]>;
@@ -0,0 +1,91 @@
1
+ import path from 'node:path';
2
+ const LARGE_DIR_THRESHOLD = 10;
3
+ const SUSPECT_DIRS = ['utils', 'helpers', 'lib', 'shared'];
4
+ export async function check(rootPath, files) {
5
+ const issues = [];
6
+ // Check for large utility directories
7
+ const dirFileCounts = new Map();
8
+ for (const file of files) {
9
+ const parts = file.directory.split(path.sep);
10
+ for (const part of parts) {
11
+ if (SUSPECT_DIRS.includes(part)) {
12
+ const key = file.directory;
13
+ dirFileCounts.set(key, (dirFileCounts.get(key) ?? 0) + 1);
14
+ }
15
+ }
16
+ }
17
+ for (const [dir, count] of dirFileCounts) {
18
+ if (count > LARGE_DIR_THRESHOLD) {
19
+ const dirName = path.basename(dir);
20
+ issues.push({
21
+ id: `large-${dirName}-dir`,
22
+ title: `Large ${dirName}/ directory (${count} files)`,
23
+ description: `The ${dir}/ directory contains ${count} files. Consider splitting into domain-specific modules for better organization.`,
24
+ severity: 'warning',
25
+ category: 'architecture',
26
+ fixAvailable: false,
27
+ });
28
+ }
29
+ }
30
+ // Check for missing source directory organization
31
+ const hasSourceDir = files.some((f) => {
32
+ const topDir = f.directory.split(path.sep)[0];
33
+ return ['src', 'lib', 'app', 'pages', 'source'].includes(topDir);
34
+ });
35
+ const hasCodeFiles = files.some((f) => ['.js', '.jsx', '.ts', '.tsx', '.py', '.go', '.rs', '.java'].includes(f.extension));
36
+ if (hasCodeFiles && !hasSourceDir) {
37
+ const rootCodeFiles = files.filter((f) => (!f.directory || f.directory === '.') &&
38
+ ['.js', '.jsx', '.ts', '.tsx'].includes(f.extension));
39
+ if (rootCodeFiles.length > 3) {
40
+ issues.push({
41
+ id: 'no-source-dir',
42
+ title: 'No source directory organization',
43
+ description: 'Source code files are at the project root without a src/ or app/ directory. Consider organizing code into a source directory.',
44
+ severity: 'info',
45
+ category: 'architecture',
46
+ fixAvailable: false,
47
+ });
48
+ }
49
+ }
50
+ // Check for missing .editorconfig
51
+ const hasEditorConfig = files.some((f) => path.basename(f.relativePath) === '.editorconfig' && (!f.directory || f.directory === '.'));
52
+ if (!hasEditorConfig) {
53
+ issues.push({
54
+ id: 'missing-editorconfig',
55
+ title: 'Missing .editorconfig',
56
+ description: 'No .editorconfig file found. EditorConfig helps maintain consistent coding styles across different editors.',
57
+ severity: 'info',
58
+ category: 'architecture',
59
+ fixAvailable: true,
60
+ fixId: 'add-editorconfig',
61
+ });
62
+ }
63
+ // Check for missing or empty README
64
+ const readmeFile = files.find((f) => {
65
+ const name = path.basename(f.relativePath).toLowerCase();
66
+ return ((name === 'readme.md' || name === 'readme' || name === 'readme.txt') &&
67
+ (!f.directory || f.directory === '.'));
68
+ });
69
+ if (!readmeFile) {
70
+ issues.push({
71
+ id: 'missing-readme',
72
+ title: 'Missing README',
73
+ description: 'No README file found. A README is essential for project documentation and onboarding.',
74
+ severity: 'warning',
75
+ category: 'architecture',
76
+ fixAvailable: false,
77
+ });
78
+ }
79
+ else if (readmeFile.sizeBytes < 50) {
80
+ issues.push({
81
+ id: 'empty-readme',
82
+ title: 'README is nearly empty',
83
+ description: 'The README file contains very little content. Consider adding project description, setup instructions, and usage examples.',
84
+ severity: 'info',
85
+ category: 'architecture',
86
+ fixAvailable: false,
87
+ });
88
+ }
89
+ return issues;
90
+ }
91
+ //# sourceMappingURL=architectureCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"architectureCheck.js","sourceRoot":"","sources":["../../src/analyzers/architectureCheck.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { FileEntry, Issue } from '../types.js';
2
+ export declare function check(rootPath: string, _files: FileEntry[]): Promise<Issue[]>;
@@ -0,0 +1,17 @@
1
+ import { analyzeDependencies } from '../core/dependencyAnalyzer.js';
2
+ export async function check(rootPath, _files) {
3
+ const report = await analyzeDependencies(rootPath);
4
+ if (!report)
5
+ return [];
6
+ return report.risks.map((risk) => ({
7
+ id: `dep-risk-${risk.name}`,
8
+ title: risk.name === 'excessive-dependencies' || risk.name === 'many-dependencies' || risk.name === 'no-lockfile'
9
+ ? risk.reason
10
+ : `Dependency risk: ${risk.name}`,
11
+ description: risk.reason,
12
+ severity: risk.severity === 'high' ? 'error' : risk.severity === 'medium' ? 'warning' : 'info',
13
+ category: 'dependencies',
14
+ fixAvailable: false,
15
+ }));
16
+ }
17
+ //# sourceMappingURL=dependencyRiskCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependencyRiskCheck.js","sourceRoot":"","sources":["../../src/analyzers/dependencyRiskCheck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAGpE,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,QAAgB,EAAE,MAAmB;IAC/D,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAEvB,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACjC,EAAE,EAAE,YAAY,IAAI,CAAC,IAAI,EAAE;QAC3B,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,wBAAwB,IAAI,IAAI,CAAC,IAAI,KAAK,mBAAmB,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa;YAC/G,CAAC,CAAC,IAAI,CAAC,MAAM;YACb,CAAC,CAAC,oBAAoB,IAAI,CAAC,IAAI,EAAE;QACnC,WAAW,EAAE,IAAI,CAAC,MAAM;QACxB,QAAQ,EAAE,IAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,OAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAkB,CAAC,CAAC,CAAC,MAAe;QACzH,QAAQ,EAAE,cAAc;QACxB,YAAY,EAAE,KAAK;KACpB,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { FileEntry, Issue } from '../types.js';
2
+ export declare function check(rootPath: string, files: FileEntry[]): Promise<Issue[]>;
@@ -0,0 +1,49 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ const ESLINT_CONFIG_FILES = [
4
+ '.eslintrc',
5
+ '.eslintrc.js',
6
+ '.eslintrc.cjs',
7
+ '.eslintrc.json',
8
+ '.eslintrc.yml',
9
+ '.eslintrc.yaml',
10
+ 'eslint.config.js',
11
+ 'eslint.config.mjs',
12
+ 'eslint.config.cjs',
13
+ 'eslint.config.ts',
14
+ 'eslint.config.mts',
15
+ ];
16
+ export async function check(rootPath, files) {
17
+ const rootFiles = new Set(files.filter((f) => !f.directory || f.directory === '.').map((f) => path.basename(f.relativePath)));
18
+ // Check for config files
19
+ for (const configFile of ESLINT_CONFIG_FILES) {
20
+ if (rootFiles.has(configFile))
21
+ return [];
22
+ }
23
+ // Check for eslintConfig in package.json
24
+ try {
25
+ const raw = await fs.readFile(path.join(rootPath, 'package.json'), 'utf-8');
26
+ const pkg = JSON.parse(raw);
27
+ if (pkg.eslintConfig)
28
+ return [];
29
+ }
30
+ catch {
31
+ // No package.json or invalid JSON
32
+ }
33
+ // Check if this is a JS/TS project (ESLint only relevant for these)
34
+ const hasJsTs = files.some((f) => ['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs'].includes(f.extension));
35
+ if (!hasJsTs)
36
+ return [];
37
+ return [
38
+ {
39
+ id: 'missing-eslint',
40
+ title: 'No ESLint configuration',
41
+ description: 'No ESLint configuration file detected. ESLint helps catch bugs and enforce code style.',
42
+ severity: 'warning',
43
+ category: 'linting',
44
+ fixAvailable: true,
45
+ fixId: 'add-eslint',
46
+ },
47
+ ];
48
+ }
49
+ //# sourceMappingURL=eslintCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eslintCheck.js","sourceRoot":"","sources":["../../src/analyzers/eslintCheck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,mBAAmB,GAAG;IAC1B,WAAW;IACX,cAAc;IACd,eAAe;IACf,gBAAgB;IAChB,eAAe;IACf,gBAAgB;IAChB,kBAAkB;IAClB,mBAAmB;IACnB,mBAAmB;IACnB,kBAAkB;IAClB,mBAAmB;CACpB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,QAAgB,EAAE,KAAkB;IAC9D,MAAM,SAAS,GAAG,IAAI,GAAG,CACvB,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,SAAS,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CACnG,CAAC;IAEF,yBAAyB;IACzB,KAAK,MAAM,UAAU,IAAI,mBAAmB,EAAE,CAAC;QAC7C,IAAI,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC;YAAE,OAAO,EAAE,CAAC;IAC3C,CAAC;IAED,yCAAyC;IACzC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC;QAC5E,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,GAAG,CAAC,YAAY;YAAE,OAAO,EAAE,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,kCAAkC;IACpC,CAAC;IAED,oEAAoE;IACpE,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC/B,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CACrE,CAAC;IAEF,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAExB,OAAO;QACL;YACE,EAAE,EAAE,gBAAgB;YACpB,KAAK,EAAE,yBAAyB;YAChC,WAAW,EACT,wFAAwF;YAC1F,QAAQ,EAAE,SAAS;YACnB,QAAQ,EAAE,SAAS;YACnB,YAAY,EAAE,IAAI;YAClB,KAAK,EAAE,YAAY;SACpB;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { FileEntry, Issue } from '../types.js';
2
+ export declare function check(rootPath: string, files: FileEntry[]): Promise<Issue[]>;
@@ -0,0 +1,53 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ const PRETTIER_CONFIG_FILES = [
4
+ '.prettierrc',
5
+ '.prettierrc.js',
6
+ '.prettierrc.cjs',
7
+ '.prettierrc.mjs',
8
+ '.prettierrc.json',
9
+ '.prettierrc.yml',
10
+ '.prettierrc.yaml',
11
+ '.prettierrc.toml',
12
+ 'prettier.config.js',
13
+ 'prettier.config.cjs',
14
+ 'prettier.config.mjs',
15
+ 'prettier.config.ts',
16
+ ];
17
+ export async function check(rootPath, files) {
18
+ const rootFiles = new Set(files.filter((f) => !f.directory || f.directory === '.').map((f) => path.basename(f.relativePath)));
19
+ for (const configFile of PRETTIER_CONFIG_FILES) {
20
+ if (rootFiles.has(configFile))
21
+ return [];
22
+ }
23
+ // Check for prettier key in package.json
24
+ try {
25
+ const raw = await fs.readFile(path.join(rootPath, 'package.json'), 'utf-8');
26
+ const pkg = JSON.parse(raw);
27
+ if (pkg.prettier)
28
+ return [];
29
+ }
30
+ catch {
31
+ // No package.json
32
+ }
33
+ // Only relevant for JS/TS/CSS/HTML projects
34
+ const relevantExtensions = new Set([
35
+ '.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs',
36
+ '.css', '.scss', '.less', '.html', '.vue', '.svelte', '.json',
37
+ ]);
38
+ const hasRelevantFiles = files.some((f) => relevantExtensions.has(f.extension));
39
+ if (!hasRelevantFiles)
40
+ return [];
41
+ return [
42
+ {
43
+ id: 'missing-prettier',
44
+ title: 'No Prettier configuration',
45
+ description: 'No Prettier configuration file detected. Prettier ensures consistent code formatting across your project.',
46
+ severity: 'warning',
47
+ category: 'formatting',
48
+ fixAvailable: true,
49
+ fixId: 'add-prettier',
50
+ },
51
+ ];
52
+ }
53
+ //# sourceMappingURL=prettierCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prettierCheck.js","sourceRoot":"","sources":["../../src/analyzers/prettierCheck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,qBAAqB,GAAG;IAC5B,aAAa;IACb,gBAAgB;IAChB,iBAAiB;IACjB,iBAAiB;IACjB,kBAAkB;IAClB,iBAAiB;IACjB,kBAAkB;IAClB,kBAAkB;IAClB,oBAAoB;IACpB,qBAAqB;IACrB,qBAAqB;IACrB,oBAAoB;CACrB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,QAAgB,EAAE,KAAkB;IAC9D,MAAM,SAAS,GAAG,IAAI,GAAG,CACvB,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,SAAS,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CACnG,CAAC;IAEF,KAAK,MAAM,UAAU,IAAI,qBAAqB,EAAE,CAAC;QAC/C,IAAI,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC;YAAE,OAAO,EAAE,CAAC;IAC3C,CAAC;IAED,yCAAyC;IACzC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC;QAC5E,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,GAAG,CAAC,QAAQ;YAAE,OAAO,EAAE,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,kBAAkB;IACpB,CAAC;IAED,4CAA4C;IAC5C,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;QACjC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;QAC5C,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO;KAC9D,CAAC,CAAC;IACH,MAAM,gBAAgB,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC,gBAAgB;QAAE,OAAO,EAAE,CAAC;IAEjC,OAAO;QACL;YACE,EAAE,EAAE,kBAAkB;YACtB,KAAK,EAAE,2BAA2B;YAClC,WAAW,EACT,2GAA2G;YAC7G,QAAQ,EAAE,SAAS;YACnB,QAAQ,EAAE,YAAY;YACtB,YAAY,EAAE,IAAI;YAClB,KAAK,EAAE,cAAc;SACtB;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { FileEntry, Issue } from '../types.js';
2
+ export declare function check(rootPath: string, files: FileEntry[]): Promise<Issue[]>;
@@ -0,0 +1,52 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ const TEST_FRAMEWORKS = ['vitest', 'jest', 'mocha', 'ava', 'tap', 'jasmine', '@playwright/test', 'cypress'];
4
+ const TEST_FILE_PATTERNS = ['.test.', '.spec.', '__tests__'];
5
+ export async function check(rootPath, files) {
6
+ const issues = [];
7
+ // Check if this is a JS/TS project
8
+ const hasJsTs = files.some((f) => ['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs'].includes(f.extension));
9
+ if (!hasJsTs)
10
+ return [];
11
+ // Check for test framework in dependencies
12
+ let hasTestFramework = false;
13
+ try {
14
+ const raw = await fs.readFile(path.join(rootPath, 'package.json'), 'utf-8');
15
+ const pkg = JSON.parse(raw);
16
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
17
+ for (const framework of TEST_FRAMEWORKS) {
18
+ if (allDeps[framework]) {
19
+ hasTestFramework = true;
20
+ break;
21
+ }
22
+ }
23
+ }
24
+ catch {
25
+ // No package.json
26
+ }
27
+ // Check for test files
28
+ const testFiles = files.filter((f) => TEST_FILE_PATTERNS.some((pattern) => f.relativePath.includes(pattern)));
29
+ if (!hasTestFramework) {
30
+ issues.push({
31
+ id: 'missing-test-framework',
32
+ title: 'No test framework detected',
33
+ description: 'No testing framework found in dependencies. Testing is essential for code quality and reliability.',
34
+ severity: 'warning',
35
+ category: 'testing',
36
+ fixAvailable: true,
37
+ fixId: 'add-tests',
38
+ });
39
+ }
40
+ else if (testFiles.length === 0) {
41
+ issues.push({
42
+ id: 'no-test-files',
43
+ title: 'No test files found',
44
+ description: 'A test framework is configured but no test files were found. Consider adding tests for your code.',
45
+ severity: 'info',
46
+ category: 'testing',
47
+ fixAvailable: false,
48
+ });
49
+ }
50
+ return issues;
51
+ }
52
+ //# sourceMappingURL=testCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testCheck.js","sourceRoot":"","sources":["../../src/analyzers/testCheck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,SAAS,CAAC,CAAC;AAE5G,MAAM,kBAAkB,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;AAE7D,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,QAAgB,EAAE,KAAkB;IAC9D,MAAM,MAAM,GAAY,EAAE,CAAC;IAE3B,mCAAmC;IACnC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC/B,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CACrE,CAAC;IACF,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAExB,2CAA2C;IAC3C,IAAI,gBAAgB,GAAG,KAAK,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC;QAC5E,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,OAAO,GAAG,EAAE,GAAG,GAAG,CAAC,YAAY,EAAE,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC;QAEhE,KAAK,MAAM,SAAS,IAAI,eAAe,EAAE,CAAC;YACxC,IAAI,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;gBACvB,gBAAgB,GAAG,IAAI,CAAC;gBACxB,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,kBAAkB;IACpB,CAAC;IAED,uBAAuB;IACvB,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACnC,kBAAkB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CACvE,CAAC;IAEF,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC;YACV,EAAE,EAAE,wBAAwB;YAC5B,KAAK,EAAE,4BAA4B;YACnC,WAAW,EACT,oGAAoG;YACtG,QAAQ,EAAE,SAAS;YACnB,QAAQ,EAAE,SAAS;YACnB,YAAY,EAAE,IAAI;YAClB,KAAK,EAAE,WAAW;SACnB,CAAC,CAAC;IACL,CAAC;SAAM,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC;YACV,EAAE,EAAE,eAAe;YACnB,KAAK,EAAE,qBAAqB;YAC5B,WAAW,EACT,mGAAmG;YACrG,QAAQ,EAAE,MAAM;YAChB,QAAQ,EAAE,SAAS;YACnB,YAAY,EAAE,KAAK;SACpB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};