projscan 0.1.13 → 0.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/README.md +92 -9
- package/dist/cli/index.js +108 -144
- package/dist/cli/index.js.map +1 -1
- package/dist/core/fileInspector.d.ts +13 -0
- package/dist/core/fileInspector.js +205 -0
- package/dist/core/fileInspector.js.map +1 -0
- package/dist/core/hotspotAnalyzer.d.ts +16 -0
- package/dist/core/hotspotAnalyzer.js +342 -0
- package/dist/core/hotspotAnalyzer.js.map +1 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/prompts.d.ts +14 -0
- package/dist/mcp/prompts.js +126 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/resources.d.ts +8 -0
- package/dist/mcp/resources.js +57 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/server.d.ts +5 -0
- package/dist/mcp/server.js +205 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +9 -0
- package/dist/mcp/tools.js +176 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/reporters/consoleReporter.d.ts +3 -1
- package/dist/reporters/consoleReporter.js +127 -0
- package/dist/reporters/consoleReporter.js.map +1 -1
- package/dist/reporters/jsonReporter.d.ts +3 -1
- package/dist/reporters/jsonReporter.js +6 -0
- package/dist/reporters/jsonReporter.js.map +1 -1
- package/dist/reporters/markdownReporter.d.ts +3 -1
- package/dist/reporters/markdownReporter.js +99 -0
- package/dist/reporters/markdownReporter.js.map +1 -1
- package/dist/types.d.ts +88 -0
- package/dist/utils/baseline.d.ts +4 -4
- package/dist/utils/baseline.js +71 -5
- package/dist/utils/baseline.js.map +1 -1
- package/package.json +2 -2
package/dist/utils/baseline.js
CHANGED
|
@@ -2,17 +2,26 @@ import fs from 'node:fs/promises';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { calculateScore } from './scoreCalculator.js';
|
|
4
4
|
const DEFAULT_FILENAME = '.projscan-baseline.json';
|
|
5
|
-
|
|
5
|
+
const HOTSPOT_SNAPSHOT_LIMIT = 20;
|
|
6
|
+
export function baselineFromIssues(issues, hotspotReport) {
|
|
6
7
|
const { score, grade } = calculateScore(issues);
|
|
8
|
+
const hotspots = hotspotReport && hotspotReport.available
|
|
9
|
+
? hotspotReport.hotspots.slice(0, HOTSPOT_SNAPSHOT_LIMIT).map((h) => ({
|
|
10
|
+
relativePath: h.relativePath,
|
|
11
|
+
riskScore: h.riskScore,
|
|
12
|
+
churn: h.churn,
|
|
13
|
+
}))
|
|
14
|
+
: undefined;
|
|
7
15
|
return {
|
|
8
16
|
score,
|
|
9
17
|
grade,
|
|
10
18
|
issues: issues.map((i) => ({ id: i.id, title: i.title, severity: i.severity })),
|
|
19
|
+
hotspots,
|
|
11
20
|
timestamp: new Date().toISOString(),
|
|
12
21
|
};
|
|
13
22
|
}
|
|
14
|
-
export async function saveBaseline(rootPath, issues) {
|
|
15
|
-
const baseline = baselineFromIssues(issues);
|
|
23
|
+
export async function saveBaseline(rootPath, issues, hotspotReport) {
|
|
24
|
+
const baseline = baselineFromIssues(issues, hotspotReport);
|
|
16
25
|
const filePath = path.join(rootPath, DEFAULT_FILENAME);
|
|
17
26
|
await fs.writeFile(filePath, JSON.stringify(baseline, null, 2) + '\n', 'utf-8');
|
|
18
27
|
return filePath;
|
|
@@ -22,8 +31,8 @@ export async function loadBaseline(filePath, rootPath) {
|
|
|
22
31
|
const content = await fs.readFile(resolvedPath, 'utf-8');
|
|
23
32
|
return JSON.parse(content);
|
|
24
33
|
}
|
|
25
|
-
export function computeDiff(before, currentIssues) {
|
|
26
|
-
const after = baselineFromIssues(currentIssues);
|
|
34
|
+
export function computeDiff(before, currentIssues, currentHotspots) {
|
|
35
|
+
const after = baselineFromIssues(currentIssues, currentHotspots);
|
|
27
36
|
const beforeTitles = new Set(before.issues.map((i) => i.title));
|
|
28
37
|
const afterTitles = new Set(after.issues.map((i) => i.title));
|
|
29
38
|
const newIssues = after.issues
|
|
@@ -32,12 +41,69 @@ export function computeDiff(before, currentIssues) {
|
|
|
32
41
|
const resolvedIssues = before.issues
|
|
33
42
|
.filter((i) => !afterTitles.has(i.title))
|
|
34
43
|
.map((i) => i.title);
|
|
44
|
+
const hotspotDiff = before.hotspots && after.hotspots ? diffHotspots(before.hotspots, after.hotspots) : undefined;
|
|
35
45
|
return {
|
|
36
46
|
before,
|
|
37
47
|
after,
|
|
38
48
|
scoreDelta: after.score - before.score,
|
|
39
49
|
newIssues,
|
|
40
50
|
resolvedIssues,
|
|
51
|
+
hotspotDiff,
|
|
41
52
|
};
|
|
42
53
|
}
|
|
54
|
+
function diffHotspots(before, after) {
|
|
55
|
+
const beforeMap = new Map(before.map((h) => [h.relativePath, h]));
|
|
56
|
+
const afterMap = new Map(after.map((h) => [h.relativePath, h]));
|
|
57
|
+
const rose = [];
|
|
58
|
+
const fell = [];
|
|
59
|
+
const appeared = [];
|
|
60
|
+
const resolved = [];
|
|
61
|
+
for (const [path, afterEntry] of afterMap) {
|
|
62
|
+
const beforeEntry = beforeMap.get(path);
|
|
63
|
+
if (!beforeEntry) {
|
|
64
|
+
appeared.push({
|
|
65
|
+
relativePath: path,
|
|
66
|
+
beforeScore: null,
|
|
67
|
+
afterScore: afterEntry.riskScore,
|
|
68
|
+
scoreDelta: afterEntry.riskScore,
|
|
69
|
+
});
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const delta = round1(afterEntry.riskScore - beforeEntry.riskScore);
|
|
73
|
+
if (delta > 0) {
|
|
74
|
+
rose.push({
|
|
75
|
+
relativePath: path,
|
|
76
|
+
beforeScore: beforeEntry.riskScore,
|
|
77
|
+
afterScore: afterEntry.riskScore,
|
|
78
|
+
scoreDelta: delta,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
else if (delta < 0) {
|
|
82
|
+
fell.push({
|
|
83
|
+
relativePath: path,
|
|
84
|
+
beforeScore: beforeEntry.riskScore,
|
|
85
|
+
afterScore: afterEntry.riskScore,
|
|
86
|
+
scoreDelta: delta,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
for (const [path, beforeEntry] of beforeMap) {
|
|
91
|
+
if (!afterMap.has(path)) {
|
|
92
|
+
resolved.push({
|
|
93
|
+
relativePath: path,
|
|
94
|
+
beforeScore: beforeEntry.riskScore,
|
|
95
|
+
afterScore: null,
|
|
96
|
+
scoreDelta: round1(-beforeEntry.riskScore),
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
rose.sort((a, b) => b.scoreDelta - a.scoreDelta);
|
|
101
|
+
fell.sort((a, b) => a.scoreDelta - b.scoreDelta);
|
|
102
|
+
appeared.sort((a, b) => (b.afterScore ?? 0) - (a.afterScore ?? 0));
|
|
103
|
+
resolved.sort((a, b) => (b.beforeScore ?? 0) - (a.beforeScore ?? 0));
|
|
104
|
+
return { rose, fell, appeared, resolved };
|
|
105
|
+
}
|
|
106
|
+
function round1(n) {
|
|
107
|
+
return Math.round(n * 10) / 10;
|
|
108
|
+
}
|
|
43
109
|
//# sourceMappingURL=baseline.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"baseline.js","sourceRoot":"","sources":["../../src/utils/baseline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"baseline.js","sourceRoot":"","sources":["../../src/utils/baseline.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projscan",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Instant codebase insights — doctor,
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Instant codebase insights — doctor, hotspots, and MCP server for any repository",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|