@devness/coverit 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.
- package/LICENSE +21 -0
- package/README.md +169 -0
- package/dist/agents/orchestrator.d.ts +21 -0
- package/dist/agents/orchestrator.d.ts.map +1 -0
- package/dist/agents/orchestrator.js +235 -0
- package/dist/agents/orchestrator.js.map +1 -0
- package/dist/agents/reporter.d.ts +13 -0
- package/dist/agents/reporter.d.ts.map +1 -0
- package/dist/agents/reporter.js +323 -0
- package/dist/agents/reporter.js.map +1 -0
- package/dist/ai/anthropic-provider.d.ts +19 -0
- package/dist/ai/anthropic-provider.d.ts.map +1 -0
- package/dist/ai/anthropic-provider.js +83 -0
- package/dist/ai/anthropic-provider.js.map +1 -0
- package/dist/ai/claude-cli-provider.d.ts +22 -0
- package/dist/ai/claude-cli-provider.d.ts.map +1 -0
- package/dist/ai/claude-cli-provider.js +197 -0
- package/dist/ai/claude-cli-provider.js.map +1 -0
- package/dist/ai/index.d.ts +15 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +16 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/ollama-provider.d.ts +17 -0
- package/dist/ai/ollama-provider.d.ts.map +1 -0
- package/dist/ai/ollama-provider.js +88 -0
- package/dist/ai/ollama-provider.js.map +1 -0
- package/dist/ai/openai-provider.d.ts +20 -0
- package/dist/ai/openai-provider.d.ts.map +1 -0
- package/dist/ai/openai-provider.js +74 -0
- package/dist/ai/openai-provider.js.map +1 -0
- package/dist/ai/prompts.d.ts +36 -0
- package/dist/ai/prompts.d.ts.map +1 -0
- package/dist/ai/prompts.js +259 -0
- package/dist/ai/prompts.js.map +1 -0
- package/dist/ai/provider-factory.d.ts +26 -0
- package/dist/ai/provider-factory.d.ts.map +1 -0
- package/dist/ai/provider-factory.js +111 -0
- package/dist/ai/provider-factory.js.map +1 -0
- package/dist/ai/types.d.ts +37 -0
- package/dist/ai/types.d.ts.map +1 -0
- package/dist/ai/types.js +10 -0
- package/dist/ai/types.js.map +1 -0
- package/dist/analysis/code-scanner.d.ts +9 -0
- package/dist/analysis/code-scanner.d.ts.map +1 -0
- package/dist/analysis/code-scanner.js +409 -0
- package/dist/analysis/code-scanner.js.map +1 -0
- package/dist/analysis/dependency-graph.d.ts +9 -0
- package/dist/analysis/dependency-graph.d.ts.map +1 -0
- package/dist/analysis/dependency-graph.js +149 -0
- package/dist/analysis/dependency-graph.js.map +1 -0
- package/dist/analysis/diff-analyzer.d.ts +9 -0
- package/dist/analysis/diff-analyzer.d.ts.map +1 -0
- package/dist/analysis/diff-analyzer.js +232 -0
- package/dist/analysis/diff-analyzer.js.map +1 -0
- package/dist/analysis/index.d.ts +5 -0
- package/dist/analysis/index.d.ts.map +1 -0
- package/dist/analysis/index.js +5 -0
- package/dist/analysis/index.js.map +1 -0
- package/dist/analysis/strategy-planner.d.ts +11 -0
- package/dist/analysis/strategy-planner.d.ts.map +1 -0
- package/dist/analysis/strategy-planner.js +384 -0
- package/dist/analysis/strategy-planner.js.map +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +288 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/executors/base-executor.d.ts +35 -0
- package/dist/executors/base-executor.d.ts.map +1 -0
- package/dist/executors/base-executor.js +138 -0
- package/dist/executors/base-executor.js.map +1 -0
- package/dist/executors/browser-runner.d.ts +24 -0
- package/dist/executors/browser-runner.d.ts.map +1 -0
- package/dist/executors/browser-runner.js +194 -0
- package/dist/executors/browser-runner.js.map +1 -0
- package/dist/executors/cloud-runner.d.ts +41 -0
- package/dist/executors/cloud-runner.d.ts.map +1 -0
- package/dist/executors/cloud-runner.js +153 -0
- package/dist/executors/cloud-runner.js.map +1 -0
- package/dist/executors/index.d.ts +12 -0
- package/dist/executors/index.d.ts.map +1 -0
- package/dist/executors/index.js +28 -0
- package/dist/executors/index.js.map +1 -0
- package/dist/executors/local-runner.d.ts +40 -0
- package/dist/executors/local-runner.d.ts.map +1 -0
- package/dist/executors/local-runner.js +395 -0
- package/dist/executors/local-runner.js.map +1 -0
- package/dist/executors/reporter.d.ts +6 -0
- package/dist/executors/reporter.d.ts.map +1 -0
- package/dist/executors/reporter.js +6 -0
- package/dist/executors/reporter.js.map +1 -0
- package/dist/executors/simulator-runner.d.ts +30 -0
- package/dist/executors/simulator-runner.d.ts.map +1 -0
- package/dist/executors/simulator-runner.js +339 -0
- package/dist/executors/simulator-runner.js.map +1 -0
- package/dist/generators/api-test.d.ts +22 -0
- package/dist/generators/api-test.d.ts.map +1 -0
- package/dist/generators/api-test.js +235 -0
- package/dist/generators/api-test.js.map +1 -0
- package/dist/generators/base-generator.d.ts +79 -0
- package/dist/generators/base-generator.d.ts.map +1 -0
- package/dist/generators/base-generator.js +234 -0
- package/dist/generators/base-generator.js.map +1 -0
- package/dist/generators/desktop-test.d.ts +22 -0
- package/dist/generators/desktop-test.d.ts.map +1 -0
- package/dist/generators/desktop-test.js +290 -0
- package/dist/generators/desktop-test.js.map +1 -0
- package/dist/generators/e2e-browser.d.ts +19 -0
- package/dist/generators/e2e-browser.d.ts.map +1 -0
- package/dist/generators/e2e-browser.js +233 -0
- package/dist/generators/e2e-browser.js.map +1 -0
- package/dist/generators/index.d.ts +21 -0
- package/dist/generators/index.d.ts.map +1 -0
- package/dist/generators/index.js +66 -0
- package/dist/generators/index.js.map +1 -0
- package/dist/generators/mobile-test.d.ts +22 -0
- package/dist/generators/mobile-test.d.ts.map +1 -0
- package/dist/generators/mobile-test.js +286 -0
- package/dist/generators/mobile-test.js.map +1 -0
- package/dist/generators/unit-test.d.ts +23 -0
- package/dist/generators/unit-test.d.ts.map +1 -0
- package/dist/generators/unit-test.js +282 -0
- package/dist/generators/unit-test.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/server.d.ts +8 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +217 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/types/index.d.ts +295 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/framework-detector.d.ts +28 -0
- package/dist/utils/framework-detector.d.ts.map +1 -0
- package/dist/utils/framework-detector.js +184 -0
- package/dist/utils/framework-detector.js.map +1 -0
- package/dist/utils/git.d.ts +33 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +82 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/logger.d.ts +17 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +47 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +86 -0
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
import { Project, SyntaxKind } from "ts-morph";
|
|
2
|
+
import { resolve, relative, extname } from "path";
|
|
3
|
+
const EXTENSION_TO_LANGUAGE = {
|
|
4
|
+
".ts": "typescript",
|
|
5
|
+
".tsx": "typescript",
|
|
6
|
+
".js": "javascript",
|
|
7
|
+
".jsx": "javascript",
|
|
8
|
+
".mjs": "javascript",
|
|
9
|
+
".cjs": "javascript",
|
|
10
|
+
};
|
|
11
|
+
const FILE_TYPE_RULES = [
|
|
12
|
+
[/\.(test|spec)\.[^/]+$/, "test"],
|
|
13
|
+
[/\/src-tauri\//, "desktop-window"],
|
|
14
|
+
[/\/desktop\/.*components?\//, "desktop-component"],
|
|
15
|
+
[/\/desktop\//, "desktop-window"],
|
|
16
|
+
[/\/mobile\/.*screens?\//, "mobile-screen"],
|
|
17
|
+
[/\/mobile\/.*components?\//, "mobile-component"],
|
|
18
|
+
[/\/expo\/.*screens?\//, "mobile-screen"],
|
|
19
|
+
[/\/expo\/.*components?\//, "mobile-component"],
|
|
20
|
+
[/\/routes?\//, "api-route"],
|
|
21
|
+
[/\/api\//, "api-route"],
|
|
22
|
+
[/\/controllers?\//, "api-controller"],
|
|
23
|
+
[/\/middleware\//, "middleware"],
|
|
24
|
+
[/\/pages?\//, "react-page"],
|
|
25
|
+
[/\/screens?\//, "react-page"],
|
|
26
|
+
[/\/hooks?\//, "react-hook"],
|
|
27
|
+
[/\/components?\//, "react-component"],
|
|
28
|
+
[/\/services?\//, "service"],
|
|
29
|
+
[/\/utils?\//, "utility"],
|
|
30
|
+
[/\/helpers?\//, "utility"],
|
|
31
|
+
[/\/models?\//, "model"],
|
|
32
|
+
[/\/entities\//, "model"],
|
|
33
|
+
[/\/schemas?\//, "schema"],
|
|
34
|
+
[/\/migrations?\//, "migration"],
|
|
35
|
+
[/\.(config|rc)\.[^/]+$/, "config"],
|
|
36
|
+
[/\/config\//, "config"],
|
|
37
|
+
[/\.(css|scss|sass|less|styl)$/, "style"],
|
|
38
|
+
];
|
|
39
|
+
function detectLanguage(filePath) {
|
|
40
|
+
const ext = extname(filePath).toLowerCase();
|
|
41
|
+
return EXTENSION_TO_LANGUAGE[ext] ?? "unknown";
|
|
42
|
+
}
|
|
43
|
+
function detectFileType(filePath) {
|
|
44
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
45
|
+
for (const [pattern, fileType] of FILE_TYPE_RULES) {
|
|
46
|
+
if (pattern.test(normalized))
|
|
47
|
+
return fileType;
|
|
48
|
+
}
|
|
49
|
+
if (normalized.endsWith(".tsx"))
|
|
50
|
+
return "react-component";
|
|
51
|
+
return "unknown";
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Count branching/logical operators in a function body for cyclomatic complexity.
|
|
55
|
+
* Base complexity is 1 (single path). Each branch point adds 1.
|
|
56
|
+
*/
|
|
57
|
+
function calculateComplexity(node) {
|
|
58
|
+
let complexity = 1;
|
|
59
|
+
node.forEachDescendant((descendant) => {
|
|
60
|
+
switch (descendant.getKind()) {
|
|
61
|
+
case SyntaxKind.IfStatement:
|
|
62
|
+
case SyntaxKind.ForStatement:
|
|
63
|
+
case SyntaxKind.ForInStatement:
|
|
64
|
+
case SyntaxKind.ForOfStatement:
|
|
65
|
+
case SyntaxKind.WhileStatement:
|
|
66
|
+
case SyntaxKind.DoStatement:
|
|
67
|
+
case SyntaxKind.CatchClause:
|
|
68
|
+
case SyntaxKind.ConditionalExpression: // ternary
|
|
69
|
+
case SyntaxKind.CaseClause:
|
|
70
|
+
complexity++;
|
|
71
|
+
break;
|
|
72
|
+
case SyntaxKind.BinaryExpression: {
|
|
73
|
+
const opToken = descendant.getChildAtIndex(1);
|
|
74
|
+
if (opToken) {
|
|
75
|
+
const opKind = opToken.getKind();
|
|
76
|
+
if (opKind === SyntaxKind.AmpersandAmpersandToken ||
|
|
77
|
+
opKind === SyntaxKind.BarBarToken ||
|
|
78
|
+
opKind === SyntaxKind.QuestionQuestionToken) {
|
|
79
|
+
complexity++;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
return complexity;
|
|
87
|
+
}
|
|
88
|
+
function extractParams(params) {
|
|
89
|
+
return params.map((p) => ({
|
|
90
|
+
name: p.getName(),
|
|
91
|
+
type: p.getType().getText() ?? null,
|
|
92
|
+
isOptional: p.isOptional(),
|
|
93
|
+
defaultValue: p.getInitializer()?.getText() ?? null,
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
function extractExports(sourceFile) {
|
|
97
|
+
const symbols = [];
|
|
98
|
+
for (const decl of sourceFile.getExportedDeclarations()) {
|
|
99
|
+
const [name, declarations] = decl;
|
|
100
|
+
for (const d of declarations) {
|
|
101
|
+
let kind = "variable";
|
|
102
|
+
const nodeKind = d.getKind();
|
|
103
|
+
if (nodeKind === SyntaxKind.FunctionDeclaration)
|
|
104
|
+
kind = "function";
|
|
105
|
+
else if (nodeKind === SyntaxKind.ClassDeclaration)
|
|
106
|
+
kind = "class";
|
|
107
|
+
else if (nodeKind === SyntaxKind.TypeAliasDeclaration)
|
|
108
|
+
kind = "type";
|
|
109
|
+
else if (nodeKind === SyntaxKind.InterfaceDeclaration)
|
|
110
|
+
kind = "interface";
|
|
111
|
+
else if (nodeKind === SyntaxKind.EnumDeclaration)
|
|
112
|
+
kind = "enum";
|
|
113
|
+
// Check if this is the default export
|
|
114
|
+
const isDefault = name === "default";
|
|
115
|
+
symbols.push({
|
|
116
|
+
name: isDefault ? (d.getSymbol()?.getName() ?? "default") : name,
|
|
117
|
+
kind,
|
|
118
|
+
isDefault,
|
|
119
|
+
line: d.getStartLineNumber(),
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return symbols;
|
|
124
|
+
}
|
|
125
|
+
function extractImports(sourceFile) {
|
|
126
|
+
return sourceFile.getImportDeclarations().map((decl) => {
|
|
127
|
+
const source = decl.getModuleSpecifierValue();
|
|
128
|
+
const specifiers = [];
|
|
129
|
+
const defaultImport = decl.getDefaultImport();
|
|
130
|
+
if (defaultImport) {
|
|
131
|
+
specifiers.push(defaultImport.getText());
|
|
132
|
+
}
|
|
133
|
+
for (const named of decl.getNamedImports()) {
|
|
134
|
+
specifiers.push(named.getName());
|
|
135
|
+
}
|
|
136
|
+
const namespaceImport = decl.getNamespaceImport();
|
|
137
|
+
if (namespaceImport) {
|
|
138
|
+
specifiers.push(`* as ${namespaceImport.getText()}`);
|
|
139
|
+
}
|
|
140
|
+
// External = not starting with . or /
|
|
141
|
+
const isExternal = !source.startsWith(".") && !source.startsWith("/");
|
|
142
|
+
return { source, specifiers, isExternal };
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function extractFunctions(sourceFile) {
|
|
146
|
+
const functions = [];
|
|
147
|
+
// Top-level function declarations
|
|
148
|
+
for (const fn of sourceFile.getFunctions()) {
|
|
149
|
+
functions.push({
|
|
150
|
+
name: fn.getName() ?? "(anonymous)",
|
|
151
|
+
params: extractParams(fn.getParameters()),
|
|
152
|
+
returnType: fn.getReturnTypeNode()?.getText() ?? null,
|
|
153
|
+
isAsync: fn.isAsync(),
|
|
154
|
+
isExported: fn.isExported(),
|
|
155
|
+
line: fn.getStartLineNumber(),
|
|
156
|
+
complexity: calculateComplexity(fn),
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
// Top-level variable declarations with arrow functions
|
|
160
|
+
for (const stmt of sourceFile.getVariableStatements()) {
|
|
161
|
+
const isExported = stmt.isExported();
|
|
162
|
+
for (const decl of stmt.getDeclarations()) {
|
|
163
|
+
const initializer = decl.getInitializer();
|
|
164
|
+
if (!initializer)
|
|
165
|
+
continue;
|
|
166
|
+
const isArrow = initializer.getKind() === SyntaxKind.ArrowFunction;
|
|
167
|
+
const isFnExpr = initializer.getKind() === SyntaxKind.FunctionExpression;
|
|
168
|
+
if (isArrow || isFnExpr) {
|
|
169
|
+
const fn = initializer;
|
|
170
|
+
functions.push({
|
|
171
|
+
name: decl.getName(),
|
|
172
|
+
params: extractParams(fn.getParameters()),
|
|
173
|
+
returnType: fn.getReturnTypeNode()?.getText() ?? null,
|
|
174
|
+
isAsync: fn.isAsync(),
|
|
175
|
+
isExported,
|
|
176
|
+
line: decl.getStartLineNumber(),
|
|
177
|
+
complexity: calculateComplexity(initializer),
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return functions;
|
|
183
|
+
}
|
|
184
|
+
function extractClasses(sourceFile) {
|
|
185
|
+
return sourceFile.getClasses().map((cls) => {
|
|
186
|
+
const methods = cls.getMethods().map((m) => ({
|
|
187
|
+
name: m.getName(),
|
|
188
|
+
params: extractParams(m.getParameters()),
|
|
189
|
+
returnType: m.getReturnTypeNode()?.getText() ?? null,
|
|
190
|
+
isAsync: m.isAsync(),
|
|
191
|
+
isExported: false,
|
|
192
|
+
line: m.getStartLineNumber(),
|
|
193
|
+
complexity: calculateComplexity(m),
|
|
194
|
+
}));
|
|
195
|
+
const properties = cls.getProperties().map((p) => ({
|
|
196
|
+
name: p.getName(),
|
|
197
|
+
type: p.getTypeNode()?.getText() ?? null,
|
|
198
|
+
isPublic: p.getScope() === undefined ||
|
|
199
|
+
p.getScope() === "public" ||
|
|
200
|
+
// ts-morph returns undefined for implicit public
|
|
201
|
+
!["private", "protected"].includes(p.getScope() ?? ""),
|
|
202
|
+
}));
|
|
203
|
+
return {
|
|
204
|
+
name: cls.getName() ?? "(anonymous)",
|
|
205
|
+
methods,
|
|
206
|
+
properties,
|
|
207
|
+
isExported: cls.isExported(),
|
|
208
|
+
line: cls.getStartLineNumber(),
|
|
209
|
+
};
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Detect HTTP endpoint registrations:
|
|
214
|
+
* - Hono: app.get('/path', handler), app.post(...)
|
|
215
|
+
* - Express: router.get('/path', handler), app.post(...)
|
|
216
|
+
* - NestJS: @Get('/path'), @Post('/path') decorators
|
|
217
|
+
*/
|
|
218
|
+
function extractEndpoints(sourceFile) {
|
|
219
|
+
const endpoints = [];
|
|
220
|
+
const httpMethods = ["get", "post", "put", "patch", "delete"];
|
|
221
|
+
const toUpper = (m) => m.toUpperCase();
|
|
222
|
+
// Hono / Express style: app.get('/path', handler) or router.post(...)
|
|
223
|
+
for (const callExpr of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {
|
|
224
|
+
const expr = callExpr.getExpression();
|
|
225
|
+
if (expr.getKind() !== SyntaxKind.PropertyAccessExpression)
|
|
226
|
+
continue;
|
|
227
|
+
const propAccess = expr.asKind(SyntaxKind.PropertyAccessExpression);
|
|
228
|
+
if (!propAccess)
|
|
229
|
+
continue;
|
|
230
|
+
const methodName = propAccess.getName().toLowerCase();
|
|
231
|
+
if (!httpMethods.includes(methodName))
|
|
232
|
+
continue;
|
|
233
|
+
const args = callExpr.getArguments();
|
|
234
|
+
if (args.length === 0)
|
|
235
|
+
continue;
|
|
236
|
+
const firstArg = args[0];
|
|
237
|
+
// First argument should be a string literal (the path)
|
|
238
|
+
if (firstArg.getKind() !== SyntaxKind.StringLiteral)
|
|
239
|
+
continue;
|
|
240
|
+
const path = firstArg.getText().replace(/['"]/g, "");
|
|
241
|
+
const middleware = [];
|
|
242
|
+
let handler = "(anonymous)";
|
|
243
|
+
// Last argument is the handler, middle arguments are middleware
|
|
244
|
+
for (let i = 1; i < args.length; i++) {
|
|
245
|
+
const arg = args[i];
|
|
246
|
+
const text = arg.getText();
|
|
247
|
+
if (i === args.length - 1) {
|
|
248
|
+
handler = text.includes("=>") || text.includes("function") ? "(inline)" : text;
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
middleware.push(text);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
endpoints.push({
|
|
255
|
+
method: toUpper(methodName),
|
|
256
|
+
path,
|
|
257
|
+
handler,
|
|
258
|
+
middleware,
|
|
259
|
+
line: callExpr.getStartLineNumber(),
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
// NestJS decorators: @Get('/path'), @Post('/path')
|
|
263
|
+
const decoratorMethods = {
|
|
264
|
+
Get: "GET",
|
|
265
|
+
Post: "POST",
|
|
266
|
+
Put: "PUT",
|
|
267
|
+
Patch: "PATCH",
|
|
268
|
+
Delete: "DELETE",
|
|
269
|
+
};
|
|
270
|
+
for (const cls of sourceFile.getClasses()) {
|
|
271
|
+
for (const method of cls.getMethods()) {
|
|
272
|
+
for (const decorator of method.getDecorators()) {
|
|
273
|
+
const decoratorName = decorator.getName();
|
|
274
|
+
const httpMethod = decoratorMethods[decoratorName];
|
|
275
|
+
if (!httpMethod)
|
|
276
|
+
continue;
|
|
277
|
+
const decoratorArgs = decorator.getArguments();
|
|
278
|
+
const path = decoratorArgs.length > 0
|
|
279
|
+
? decoratorArgs[0].getText().replace(/['"]/g, "")
|
|
280
|
+
: "/";
|
|
281
|
+
// Collect middleware decorators like @UseGuards, @UseInterceptors
|
|
282
|
+
const middleware = method
|
|
283
|
+
.getDecorators()
|
|
284
|
+
.filter((d) => d.getName() !== decoratorName)
|
|
285
|
+
.map((d) => d.getName());
|
|
286
|
+
endpoints.push({
|
|
287
|
+
method: httpMethod,
|
|
288
|
+
path,
|
|
289
|
+
handler: method.getName(),
|
|
290
|
+
middleware,
|
|
291
|
+
line: decorator.getStartLineNumber(),
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return endpoints;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Detect React function components that return JSX.
|
|
300
|
+
* Identifies props interface and hook usage.
|
|
301
|
+
*/
|
|
302
|
+
function extractComponents(sourceFile) {
|
|
303
|
+
const components = [];
|
|
304
|
+
const filePath = sourceFile.getFilePath();
|
|
305
|
+
// Only check tsx/jsx files (or files already identified as component types)
|
|
306
|
+
if (!filePath.endsWith(".tsx") && !filePath.endsWith(".jsx")) {
|
|
307
|
+
return components;
|
|
308
|
+
}
|
|
309
|
+
// Check exported function declarations returning JSX
|
|
310
|
+
for (const fn of sourceFile.getFunctions()) {
|
|
311
|
+
if (!fn.isExported())
|
|
312
|
+
continue;
|
|
313
|
+
const name = fn.getName();
|
|
314
|
+
if (!name || !/^[A-Z]/.test(name))
|
|
315
|
+
continue; // React components are PascalCase
|
|
316
|
+
if (containsJsx(fn)) {
|
|
317
|
+
components.push({
|
|
318
|
+
name,
|
|
319
|
+
props: extractParams(fn.getParameters()),
|
|
320
|
+
hooks: extractHooks(fn),
|
|
321
|
+
isPage: isPageComponent(filePath),
|
|
322
|
+
line: fn.getStartLineNumber(),
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
// Check exported arrow functions returning JSX
|
|
327
|
+
for (const stmt of sourceFile.getVariableStatements()) {
|
|
328
|
+
if (!stmt.isExported())
|
|
329
|
+
continue;
|
|
330
|
+
for (const decl of stmt.getDeclarations()) {
|
|
331
|
+
const name = decl.getName();
|
|
332
|
+
if (!/^[A-Z]/.test(name))
|
|
333
|
+
continue;
|
|
334
|
+
const initializer = decl.getInitializer();
|
|
335
|
+
if (!initializer)
|
|
336
|
+
continue;
|
|
337
|
+
if (initializer.getKind() === SyntaxKind.ArrowFunction ||
|
|
338
|
+
initializer.getKind() === SyntaxKind.FunctionExpression) {
|
|
339
|
+
if (containsJsx(initializer)) {
|
|
340
|
+
const fn = initializer;
|
|
341
|
+
components.push({
|
|
342
|
+
name,
|
|
343
|
+
props: extractParams(fn.getParameters()),
|
|
344
|
+
hooks: extractHooks(initializer),
|
|
345
|
+
isPage: isPageComponent(filePath),
|
|
346
|
+
line: decl.getStartLineNumber(),
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return components;
|
|
353
|
+
}
|
|
354
|
+
function containsJsx(node) {
|
|
355
|
+
return (node.getDescendantsOfKind(SyntaxKind.JsxElement).length > 0 ||
|
|
356
|
+
node.getDescendantsOfKind(SyntaxKind.JsxSelfClosingElement).length > 0 ||
|
|
357
|
+
node.getDescendantsOfKind(SyntaxKind.JsxFragment).length > 0);
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Extract React hook calls (useXxx pattern) from a function body.
|
|
361
|
+
*/
|
|
362
|
+
function extractHooks(node) {
|
|
363
|
+
const hooks = new Set();
|
|
364
|
+
for (const call of node.getDescendantsOfKind(SyntaxKind.CallExpression)) {
|
|
365
|
+
const expr = call.getExpression();
|
|
366
|
+
const text = expr.getText();
|
|
367
|
+
// Match useXxx pattern (built-in and custom hooks)
|
|
368
|
+
if (/^use[A-Z]/.test(text)) {
|
|
369
|
+
hooks.add(text);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return Array.from(hooks);
|
|
373
|
+
}
|
|
374
|
+
function isPageComponent(filePath) {
|
|
375
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
376
|
+
return /\/(pages?|screens?)\//.test(normalized);
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Perform AST-level code analysis on a TypeScript/JavaScript file.
|
|
380
|
+
*
|
|
381
|
+
* @param filePath - Absolute path to the source file
|
|
382
|
+
* @param projectRoot - Absolute path to the project root (for relative path computation)
|
|
383
|
+
*/
|
|
384
|
+
export async function scanCode(filePath, projectRoot) {
|
|
385
|
+
const absolutePath = resolve(filePath);
|
|
386
|
+
const relPath = relative(resolve(projectRoot), absolutePath);
|
|
387
|
+
const project = new Project({
|
|
388
|
+
compilerOptions: {
|
|
389
|
+
allowJs: true,
|
|
390
|
+
jsx: 2, // React
|
|
391
|
+
noEmit: true,
|
|
392
|
+
strict: false, // Lenient for scanning; we're reading structure, not type-checking
|
|
393
|
+
},
|
|
394
|
+
skipAddingFilesFromTsConfig: true,
|
|
395
|
+
});
|
|
396
|
+
const sourceFile = project.addSourceFileAtPath(absolutePath);
|
|
397
|
+
return {
|
|
398
|
+
file: relPath,
|
|
399
|
+
language: detectLanguage(absolutePath),
|
|
400
|
+
fileType: detectFileType(relPath),
|
|
401
|
+
exports: extractExports(sourceFile),
|
|
402
|
+
imports: extractImports(sourceFile),
|
|
403
|
+
functions: extractFunctions(sourceFile),
|
|
404
|
+
classes: extractClasses(sourceFile),
|
|
405
|
+
endpoints: extractEndpoints(sourceFile),
|
|
406
|
+
components: extractComponents(sourceFile),
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
//# sourceMappingURL=code-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-scanner.js","sourceRoot":"","sources":["../../src/analysis/code-scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DependencyGraph } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Build a dependency graph mapping each file to its direct dependencies and dependents.
|
|
4
|
+
*
|
|
5
|
+
* @param projectRoot - Absolute path to the project root
|
|
6
|
+
* @param files - Optional subset of files to include. If omitted, all source files are discovered.
|
|
7
|
+
*/
|
|
8
|
+
export declare function buildDependencyGraph(projectRoot: string, files?: string[]): Promise<DependencyGraph>;
|
|
9
|
+
//# sourceMappingURL=dependency-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependency-graph.d.ts","sourceRoot":"","sources":["../../src/analysis/dependency-graph.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AA8FzD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,MAAM,EAAE,GACf,OAAO,CAAC,eAAe,CAAC,CAwE1B"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import fg from "fast-glob";
|
|
2
|
+
import { resolve, dirname, relative } from "path";
|
|
3
|
+
import { readFile } from "fs/promises";
|
|
4
|
+
/** Source file extensions we trace imports through. */
|
|
5
|
+
const SOURCE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
6
|
+
/** Glob patterns for discovering source files. */
|
|
7
|
+
const SOURCE_GLOBS = ["**/*.{ts,tsx,js,jsx,mjs,cjs}"];
|
|
8
|
+
/** Directories to exclude from scanning. */
|
|
9
|
+
const IGNORE_PATTERNS = [
|
|
10
|
+
"**/node_modules/**",
|
|
11
|
+
"**/dist/**",
|
|
12
|
+
"**/build/**",
|
|
13
|
+
"**/.next/**",
|
|
14
|
+
"**/coverage/**",
|
|
15
|
+
"**/__mocks__/**",
|
|
16
|
+
];
|
|
17
|
+
/**
|
|
18
|
+
* Regex to match import/require statements and extract the module specifier.
|
|
19
|
+
* Handles:
|
|
20
|
+
* import ... from "specifier"
|
|
21
|
+
* import "specifier"
|
|
22
|
+
* export ... from "specifier"
|
|
23
|
+
* require("specifier")
|
|
24
|
+
* dynamic import("specifier")
|
|
25
|
+
*/
|
|
26
|
+
const IMPORT_REGEX = /(?:import\s+(?:[\s\S]*?\s+from\s+)?["']([^"']+)["']|export\s+(?:[\s\S]*?\s+from\s+)?["']([^"']+)["']|require\s*\(\s*["']([^"']+)["']\s*\)|import\s*\(\s*["']([^"']+)["']\s*\))/g;
|
|
27
|
+
/**
|
|
28
|
+
* Resolve a relative import specifier to an absolute file path.
|
|
29
|
+
* Tries the specifier as-is, then with each source extension appended,
|
|
30
|
+
* then as a directory index file.
|
|
31
|
+
*/
|
|
32
|
+
function resolveImport(specifier, importerDir, allFiles) {
|
|
33
|
+
// Only resolve relative imports
|
|
34
|
+
if (!specifier.startsWith("."))
|
|
35
|
+
return null;
|
|
36
|
+
const basePath = resolve(importerDir, specifier);
|
|
37
|
+
// Direct match (specifier already has extension)
|
|
38
|
+
if (allFiles.has(basePath))
|
|
39
|
+
return basePath;
|
|
40
|
+
// Try appending source extensions
|
|
41
|
+
for (const ext of SOURCE_EXTENSIONS) {
|
|
42
|
+
const withExt = basePath + ext;
|
|
43
|
+
if (allFiles.has(withExt))
|
|
44
|
+
return withExt;
|
|
45
|
+
}
|
|
46
|
+
// Strip .js extension and try .ts/.tsx (common in ESM projects importing .js that are actually .ts)
|
|
47
|
+
if (specifier.endsWith(".js")) {
|
|
48
|
+
const stripped = basePath.slice(0, -3);
|
|
49
|
+
for (const ext of [".ts", ".tsx"]) {
|
|
50
|
+
const mapped = stripped + ext;
|
|
51
|
+
if (allFiles.has(mapped))
|
|
52
|
+
return mapped;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Try as directory index
|
|
56
|
+
for (const ext of SOURCE_EXTENSIONS) {
|
|
57
|
+
const indexPath = resolve(basePath, `index${ext}`);
|
|
58
|
+
if (allFiles.has(indexPath))
|
|
59
|
+
return indexPath;
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Extract import specifiers from file content using regex.
|
|
65
|
+
* Faster than full AST parsing for dependency graph purposes.
|
|
66
|
+
*/
|
|
67
|
+
function extractImportSpecifiers(content) {
|
|
68
|
+
const specifiers = [];
|
|
69
|
+
let match;
|
|
70
|
+
// Reset lastIndex for the global regex
|
|
71
|
+
IMPORT_REGEX.lastIndex = 0;
|
|
72
|
+
while ((match = IMPORT_REGEX.exec(content)) !== null) {
|
|
73
|
+
// One of the capture groups will have the specifier
|
|
74
|
+
const specifier = match[1] ?? match[2] ?? match[3] ?? match[4];
|
|
75
|
+
if (specifier) {
|
|
76
|
+
specifiers.push(specifier);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return specifiers;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Build a dependency graph mapping each file to its direct dependencies and dependents.
|
|
83
|
+
*
|
|
84
|
+
* @param projectRoot - Absolute path to the project root
|
|
85
|
+
* @param files - Optional subset of files to include. If omitted, all source files are discovered.
|
|
86
|
+
*/
|
|
87
|
+
export async function buildDependencyGraph(projectRoot, files) {
|
|
88
|
+
const root = resolve(projectRoot);
|
|
89
|
+
// Discover all source files for import resolution
|
|
90
|
+
const allSourceFiles = await fg(SOURCE_GLOBS, {
|
|
91
|
+
cwd: root,
|
|
92
|
+
absolute: true,
|
|
93
|
+
ignore: IGNORE_PATTERNS,
|
|
94
|
+
});
|
|
95
|
+
const allFilesSet = new Set(allSourceFiles);
|
|
96
|
+
// Determine which files to analyze (all or a provided subset)
|
|
97
|
+
const filesToAnalyze = files
|
|
98
|
+
? files.map((f) => resolve(root, f)).filter((f) => allFilesSet.has(f))
|
|
99
|
+
: allSourceFiles;
|
|
100
|
+
const graph = new Map();
|
|
101
|
+
// Initialize nodes for all discovered files so dependedBy edges are complete
|
|
102
|
+
for (const absPath of allSourceFiles) {
|
|
103
|
+
const relPath = relative(root, absPath);
|
|
104
|
+
if (!graph.has(relPath)) {
|
|
105
|
+
graph.set(relPath, { file: relPath, dependsOn: [], dependedBy: [] });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Parse imports and build forward edges (dependsOn)
|
|
109
|
+
const readPromises = filesToAnalyze.map(async (absPath) => {
|
|
110
|
+
const relPath = relative(root, absPath);
|
|
111
|
+
let node = graph.get(relPath);
|
|
112
|
+
if (!node) {
|
|
113
|
+
node = { file: relPath, dependsOn: [], dependedBy: [] };
|
|
114
|
+
graph.set(relPath, node);
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const content = await readFile(absPath, "utf-8");
|
|
118
|
+
const specifiers = extractImportSpecifiers(content);
|
|
119
|
+
const importerDir = dirname(absPath);
|
|
120
|
+
for (const spec of specifiers) {
|
|
121
|
+
const resolved = resolveImport(spec, importerDir, allFilesSet);
|
|
122
|
+
if (!resolved)
|
|
123
|
+
continue;
|
|
124
|
+
const resolvedRel = relative(root, resolved);
|
|
125
|
+
// Avoid self-references
|
|
126
|
+
if (resolvedRel === relPath)
|
|
127
|
+
continue;
|
|
128
|
+
if (!node.dependsOn.includes(resolvedRel)) {
|
|
129
|
+
node.dependsOn.push(resolvedRel);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// File may have been deleted or be unreadable; skip silently
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
await Promise.all(readPromises);
|
|
138
|
+
// Build reverse edges (dependedBy) from forward edges
|
|
139
|
+
for (const [filePath, node] of graph) {
|
|
140
|
+
for (const dep of node.dependsOn) {
|
|
141
|
+
const depNode = graph.get(dep);
|
|
142
|
+
if (depNode && !depNode.dependedBy.includes(filePath)) {
|
|
143
|
+
depNode.dependedBy.push(filePath);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return graph;
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=dependency-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependency-graph.js","sourceRoot":"","sources":["../../src/analysis/dependency-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DiffResult } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Analyze git diff to identify changed files with metadata.
|
|
4
|
+
*
|
|
5
|
+
* @param projectRoot - Absolute path to the git repository root
|
|
6
|
+
* @param baseBranch - Branch to diff against (defaults to HEAD for uncommitted changes)
|
|
7
|
+
*/
|
|
8
|
+
export declare function analyzeDiff(projectRoot: string, baseBranch?: string): Promise<DiffResult>;
|
|
9
|
+
//# sourceMappingURL=diff-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-analyzer.d.ts","sourceRoot":"","sources":["../../src/analysis/diff-analyzer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,UAAU,EAKX,MAAM,mBAAmB,CAAC;AA+I3B;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,CAAC,CAgHrB"}
|