projscan 0.3.1 → 0.5.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 +62 -1
- package/dist/analyzers/deadCodeCheck.d.ts +18 -0
- package/dist/analyzers/deadCodeCheck.js +168 -0
- package/dist/analyzers/deadCodeCheck.js.map +1 -0
- package/dist/analyzers/dependencyRiskCheck.js +29 -10
- package/dist/analyzers/dependencyRiskCheck.js.map +1 -1
- package/dist/analyzers/unusedDependencyCheck.d.ts +2 -0
- package/dist/analyzers/unusedDependencyCheck.js +144 -0
- package/dist/analyzers/unusedDependencyCheck.js.map +1 -0
- package/dist/cli/index.js +160 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/core/auditRunner.d.ts +16 -0
- package/dist/core/auditRunner.js +222 -0
- package/dist/core/auditRunner.js.map +1 -0
- package/dist/core/coverageJoin.d.ts +6 -0
- package/dist/core/coverageJoin.js +50 -0
- package/dist/core/coverageJoin.js.map +1 -0
- package/dist/core/coverageParser.d.ts +15 -0
- package/dist/core/coverageParser.js +187 -0
- package/dist/core/coverageParser.js.map +1 -0
- package/dist/core/fileInspector.js +20 -13
- package/dist/core/fileInspector.js.map +1 -1
- package/dist/core/hotspotAnalyzer.d.ts +2 -0
- package/dist/core/hotspotAnalyzer.js +20 -1
- package/dist/core/hotspotAnalyzer.js.map +1 -1
- package/dist/core/importGraph.d.ts +31 -0
- package/dist/core/importGraph.js +139 -0
- package/dist/core/importGraph.js.map +1 -0
- package/dist/core/issueEngine.js +4 -0
- package/dist/core/issueEngine.js.map +1 -1
- package/dist/core/outdatedDetector.d.ts +9 -0
- package/dist/core/outdatedDetector.js +87 -0
- package/dist/core/outdatedDetector.js.map +1 -0
- package/dist/core/upgradePreview.d.ts +2 -0
- package/dist/core/upgradePreview.js +167 -0
- package/dist/core/upgradePreview.js.map +1 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/tools.js +73 -0
- package/dist/mcp/tools.js.map +1 -1
- package/dist/reporters/consoleReporter.d.ts +5 -1
- package/dist/reporters/consoleReporter.js +170 -0
- package/dist/reporters/consoleReporter.js.map +1 -1
- package/dist/reporters/jsonReporter.d.ts +5 -1
- package/dist/reporters/jsonReporter.js +12 -0
- package/dist/reporters/jsonReporter.js.map +1 -1
- package/dist/reporters/markdownReporter.d.ts +5 -1
- package/dist/reporters/markdownReporter.js +111 -0
- package/dist/reporters/markdownReporter.js.map +1 -1
- package/dist/types.d.ts +77 -0
- package/dist/utils/banner.js +11 -7
- package/dist/utils/banner.js.map +1 -1
- package/dist/utils/packageJsonLocator.d.ts +11 -0
- package/dist/utils/packageJsonLocator.js +58 -0
- package/dist/utils/packageJsonLocator.js.map +1 -0
- package/dist/utils/semver.d.ts +13 -0
- package/dist/utils/semver.js +45 -0
- package/dist/utils/semver.js.map +1 -0
- package/package.json +2 -2
package/dist/types.d.ts
CHANGED
|
@@ -159,6 +159,82 @@ export interface DiffResult {
|
|
|
159
159
|
hotspotDiff?: HotspotDiffSummary;
|
|
160
160
|
}
|
|
161
161
|
export type ReportFormat = 'console' | 'json' | 'markdown' | 'sarif';
|
|
162
|
+
export type SemverDrift = 'patch' | 'minor' | 'major' | 'same' | 'unknown';
|
|
163
|
+
export interface OutdatedPackage {
|
|
164
|
+
name: string;
|
|
165
|
+
declared: string;
|
|
166
|
+
installed: string | null;
|
|
167
|
+
latest: string | null;
|
|
168
|
+
drift: SemverDrift;
|
|
169
|
+
scope: 'dependency' | 'devDependency';
|
|
170
|
+
}
|
|
171
|
+
export interface OutdatedReport {
|
|
172
|
+
available: boolean;
|
|
173
|
+
reason?: string;
|
|
174
|
+
totalPackages: number;
|
|
175
|
+
packages: OutdatedPackage[];
|
|
176
|
+
}
|
|
177
|
+
export type AuditSeverity = 'critical' | 'high' | 'moderate' | 'low' | 'info';
|
|
178
|
+
export interface AuditFinding {
|
|
179
|
+
name: string;
|
|
180
|
+
severity: AuditSeverity;
|
|
181
|
+
title: string;
|
|
182
|
+
url?: string;
|
|
183
|
+
cve?: string[];
|
|
184
|
+
via: string[];
|
|
185
|
+
range?: string;
|
|
186
|
+
fixAvailable: boolean;
|
|
187
|
+
}
|
|
188
|
+
export interface AuditReport {
|
|
189
|
+
available: boolean;
|
|
190
|
+
reason?: string;
|
|
191
|
+
summary: Record<AuditSeverity, number>;
|
|
192
|
+
findings: AuditFinding[];
|
|
193
|
+
}
|
|
194
|
+
export interface UpgradePreview {
|
|
195
|
+
available: boolean;
|
|
196
|
+
reason?: string;
|
|
197
|
+
name: string;
|
|
198
|
+
declared: string | null;
|
|
199
|
+
installed: string | null;
|
|
200
|
+
latest: string | null;
|
|
201
|
+
drift: SemverDrift;
|
|
202
|
+
breakingMarkers: string[];
|
|
203
|
+
changelogExcerpt?: string;
|
|
204
|
+
importers: string[];
|
|
205
|
+
}
|
|
206
|
+
export type CoverageSource = 'lcov' | 'coverage-final' | 'coverage-summary';
|
|
207
|
+
export interface FileCoverage {
|
|
208
|
+
relativePath: string;
|
|
209
|
+
lineCoverage: number;
|
|
210
|
+
linesFound: number;
|
|
211
|
+
linesHit: number;
|
|
212
|
+
}
|
|
213
|
+
export interface CoverageReport {
|
|
214
|
+
available: boolean;
|
|
215
|
+
reason?: string;
|
|
216
|
+
source: CoverageSource | null;
|
|
217
|
+
sourceFile: string | null;
|
|
218
|
+
totalCoverage: number;
|
|
219
|
+
files: FileCoverage[];
|
|
220
|
+
}
|
|
221
|
+
export interface CoverageJoinedHotspot {
|
|
222
|
+
relativePath: string;
|
|
223
|
+
riskScore: number;
|
|
224
|
+
churn: number;
|
|
225
|
+
lineCount: number;
|
|
226
|
+
issueCount: number;
|
|
227
|
+
coverage: number | null;
|
|
228
|
+
priority: number;
|
|
229
|
+
reasons: string[];
|
|
230
|
+
}
|
|
231
|
+
export interface CoverageJoinedReport {
|
|
232
|
+
available: boolean;
|
|
233
|
+
reason?: string;
|
|
234
|
+
coverageSource: CoverageSource | null;
|
|
235
|
+
coverageSourceFile: string | null;
|
|
236
|
+
entries: CoverageJoinedHotspot[];
|
|
237
|
+
}
|
|
162
238
|
export interface ProjscanConfig {
|
|
163
239
|
minScore?: number;
|
|
164
240
|
baseRef?: string;
|
|
@@ -194,6 +270,7 @@ export interface FileHotspot {
|
|
|
194
270
|
primaryAuthorShare: number;
|
|
195
271
|
busFactorOne: boolean;
|
|
196
272
|
topAuthors: AuthorShare[];
|
|
273
|
+
coverage?: number | null;
|
|
197
274
|
}
|
|
198
275
|
export interface HotspotReport {
|
|
199
276
|
available: boolean;
|
package/dist/utils/banner.js
CHANGED
|
@@ -42,15 +42,15 @@ export function showBanner() {
|
|
|
42
42
|
`${head('Commands')}`,
|
|
43
43
|
`${w('doctor')} ${dim('Health check')}`,
|
|
44
44
|
`${w('hotspots')} ${dim('Risk-rank files')}`,
|
|
45
|
-
`${w('
|
|
46
|
-
`${w('
|
|
47
|
-
`${w('
|
|
48
|
-
`${w('
|
|
45
|
+
`${w('coverage')} ${dim('Untested hotspots')}`,
|
|
46
|
+
`${w('outdated')} ${dim('Dep drift check')}`,
|
|
47
|
+
`${w('audit')} ${dim('Vulnerabilities')}`,
|
|
48
|
+
`${w('upgrade')} ${dim('Preview upgrade')}`,
|
|
49
49
|
`${dim('...projscan --help')}`,
|
|
50
50
|
`${head("What's new")}`,
|
|
51
|
-
`${dim('
|
|
52
|
-
`${dim('
|
|
53
|
-
`${dim('
|
|
51
|
+
`${dim('coverage × hotspots')}`,
|
|
52
|
+
`${dim('Dead-code analyzer')}`,
|
|
53
|
+
`${dim('Coverage-weighted risk')}`,
|
|
54
54
|
];
|
|
55
55
|
const leftW = 42;
|
|
56
56
|
const rightW = 32;
|
|
@@ -108,6 +108,10 @@ export function showHelp() {
|
|
|
108
108
|
{ cmd: 'projscan diagram', desc: 'Show architecture layer diagram' },
|
|
109
109
|
{ cmd: 'projscan structure', desc: 'Show directory structure overview' },
|
|
110
110
|
{ cmd: 'projscan dependencies', desc: 'Analyze project dependencies' },
|
|
111
|
+
{ cmd: 'projscan outdated', desc: 'Declared-vs-installed drift (offline)' },
|
|
112
|
+
{ cmd: 'projscan audit', desc: 'Run npm audit; SARIF-ready vulnerability report' },
|
|
113
|
+
{ cmd: 'projscan upgrade <pkg>', desc: 'Preview upgrade impact (CHANGELOG + importers, offline)' },
|
|
114
|
+
{ cmd: 'projscan coverage', desc: 'Coverage × hotspots — surface scariest untested files' },
|
|
111
115
|
{ cmd: 'projscan badge', desc: 'Generate a health badge for your README' },
|
|
112
116
|
{ cmd: 'projscan mcp', desc: 'Run as MCP server for AI agents (Claude Code, Cursor, …)' },
|
|
113
117
|
];
|
package/dist/utils/banner.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"banner.js","sourceRoot":"","sources":["../../src/utils/banner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,SAAS,UAAU;IACjB,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;QAC9D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACvD,OAAO,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;IAC1B,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;IACtB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACxB,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;IAEtB,iCAAiC;IACjC,MAAM,CAAC,GAAG;QACR,EAAE;QACF,KAAK,CAAC,CAAC,mCAAmC,CAAC,GAAG;QAC9C,KAAK,CAAC,CAAC,mCAAmC,CAAC,GAAG;QAC9C,KAAK,CAAC,CAAC,mCAAmC,CAAC,GAAG;QAC9C,KAAK,CAAC,CAAC,mCAAmC,CAAC,GAAG;QAC9C,KAAK,CAAC,CAAC,mCAAmC,CAAC,GAAG;QAC9C,KAAK,CAAC,CAAC,kCAAkC,CAAC,IAAI;QAC9C,EAAE;QACF,KAAK,GAAG,CAAC,IAAI,OAAO,EAAE,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,2BAA2B,CAAC,EAAE;QACzE,KAAK,GAAG,CAAC,qCAAqC,CAAC,EAAE;QACjD,EAAE;KACH,CAAC;IAEF,4CAA4C;IAC5C,MAAM,CAAC,GAAG;QACR,GAAG,IAAI,CAAC,UAAU,CAAC,EAAE;QACrB,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,GAAG,CAAC,cAAc,CAAC,EAAE;QAC3C,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,iBAAiB,CAAC,EAAE;QAC9C,GAAG,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"banner.js","sourceRoot":"","sources":["../../src/utils/banner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface PackageJsonLocations {
|
|
2
|
+
filePath: string;
|
|
3
|
+
lineOfDependency: Map<string, number>;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Parse package.json and find the line number of each dependency name
|
|
7
|
+
* (within dependencies, devDependencies, peerDependencies, optionalDependencies).
|
|
8
|
+
* Line numbers are 1-based. Uses regex against the raw text — robust enough
|
|
9
|
+
* for typical formatted package.json files.
|
|
10
|
+
*/
|
|
11
|
+
export declare function findDependencyLines(rootPath: string): Promise<PackageJsonLocations | null>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Parse package.json and find the line number of each dependency name
|
|
5
|
+
* (within dependencies, devDependencies, peerDependencies, optionalDependencies).
|
|
6
|
+
* Line numbers are 1-based. Uses regex against the raw text — robust enough
|
|
7
|
+
* for typical formatted package.json files.
|
|
8
|
+
*/
|
|
9
|
+
export async function findDependencyLines(rootPath) {
|
|
10
|
+
const filePath = path.join(rootPath, 'package.json');
|
|
11
|
+
let raw;
|
|
12
|
+
try {
|
|
13
|
+
raw = await fs.readFile(filePath, 'utf-8');
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const lines = raw.split('\n');
|
|
19
|
+
const lineOfDependency = new Map();
|
|
20
|
+
const sections = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
|
|
21
|
+
let currentSection = null;
|
|
22
|
+
let braceDepthInSection = 0;
|
|
23
|
+
for (let i = 0; i < lines.length; i++) {
|
|
24
|
+
const line = lines[i];
|
|
25
|
+
const trimmed = line.trim();
|
|
26
|
+
if (!currentSection) {
|
|
27
|
+
for (const section of sections) {
|
|
28
|
+
if (new RegExp(`["']${section}["']\\s*:\\s*\\{`).test(line)) {
|
|
29
|
+
currentSection = section;
|
|
30
|
+
braceDepthInSection = 1;
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
// Track brace depth to know when we exit the section
|
|
37
|
+
for (const ch of line) {
|
|
38
|
+
if (ch === '{')
|
|
39
|
+
braceDepthInSection++;
|
|
40
|
+
else if (ch === '}')
|
|
41
|
+
braceDepthInSection--;
|
|
42
|
+
}
|
|
43
|
+
if (braceDepthInSection <= 0) {
|
|
44
|
+
currentSection = null;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
// Match "pkg-name": "version" on this line
|
|
48
|
+
const m = trimmed.match(/^["']([^"']+)["']\s*:/);
|
|
49
|
+
if (m) {
|
|
50
|
+
const name = m[1];
|
|
51
|
+
if (!lineOfDependency.has(name)) {
|
|
52
|
+
lineOfDependency.set(name, i + 1);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return { filePath, lineOfDependency };
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=packageJsonLocator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packageJsonLocator.js","sourceRoot":"","sources":["../../src/utils/packageJsonLocator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAO7B;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB;IAEhB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IACrD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEnD,MAAM,QAAQ,GAAG,CAAC,cAAc,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,sBAAsB,CAAC,CAAC;IACjG,IAAI,cAAc,GAAkB,IAAI,CAAC;IACzC,IAAI,mBAAmB,GAAG,CAAC,CAAC;IAE5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAE5B,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAC/B,IAAI,IAAI,MAAM,CAAC,OAAO,OAAO,kBAAkB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC5D,cAAc,GAAG,OAAO,CAAC;oBACzB,mBAAmB,GAAG,CAAC,CAAC;oBACxB,MAAM;gBACR,CAAC;YACH,CAAC;YACD,SAAS;QACX,CAAC;QAED,qDAAqD;QACrD,KAAK,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;YACtB,IAAI,EAAE,KAAK,GAAG;gBAAE,mBAAmB,EAAE,CAAC;iBACjC,IAAI,EAAE,KAAK,GAAG;gBAAE,mBAAmB,EAAE,CAAC;QAC7C,CAAC;QAED,IAAI,mBAAmB,IAAI,CAAC,EAAE,CAAC;YAC7B,cAAc,GAAG,IAAI,CAAC;YACtB,SAAS;QACX,CAAC;QAED,2CAA2C;QAC3C,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACjD,IAAI,CAAC,EAAE,CAAC;YACN,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAClB,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChC,gBAAgB,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SemverDrift } from '../types.js';
|
|
2
|
+
export interface ParsedSemver {
|
|
3
|
+
major: number;
|
|
4
|
+
minor: number;
|
|
5
|
+
patch: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function parse(version: string): ParsedSemver | null;
|
|
8
|
+
export declare function compare(a: string, b: string): number;
|
|
9
|
+
/**
|
|
10
|
+
* Classify drift from "from" → "to". Returns 'same' if equal,
|
|
11
|
+
* 'unknown' if either can't be parsed, and 'patch'/'minor'/'major' otherwise.
|
|
12
|
+
*/
|
|
13
|
+
export declare function drift(from: string | null, to: string | null): SemverDrift;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const PARSE_RE = /^v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/;
|
|
2
|
+
export function parse(version) {
|
|
3
|
+
if (!version)
|
|
4
|
+
return null;
|
|
5
|
+
const cleaned = version.replace(/^[~^>=<]+/, '').trim();
|
|
6
|
+
const m = PARSE_RE.exec(cleaned);
|
|
7
|
+
if (!m)
|
|
8
|
+
return null;
|
|
9
|
+
return {
|
|
10
|
+
major: Number(m[1]),
|
|
11
|
+
minor: Number(m[2]),
|
|
12
|
+
patch: Number(m[3]),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function compare(a, b) {
|
|
16
|
+
const pa = parse(a);
|
|
17
|
+
const pb = parse(b);
|
|
18
|
+
if (!pa || !pb)
|
|
19
|
+
return 0;
|
|
20
|
+
if (pa.major !== pb.major)
|
|
21
|
+
return pa.major - pb.major;
|
|
22
|
+
if (pa.minor !== pb.minor)
|
|
23
|
+
return pa.minor - pb.minor;
|
|
24
|
+
return pa.patch - pb.patch;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Classify drift from "from" → "to". Returns 'same' if equal,
|
|
28
|
+
* 'unknown' if either can't be parsed, and 'patch'/'minor'/'major' otherwise.
|
|
29
|
+
*/
|
|
30
|
+
export function drift(from, to) {
|
|
31
|
+
if (!from || !to)
|
|
32
|
+
return 'unknown';
|
|
33
|
+
const pf = parse(from);
|
|
34
|
+
const pt = parse(to);
|
|
35
|
+
if (!pf || !pt)
|
|
36
|
+
return 'unknown';
|
|
37
|
+
if (pf.major !== pt.major)
|
|
38
|
+
return 'major';
|
|
39
|
+
if (pf.minor !== pt.minor)
|
|
40
|
+
return 'minor';
|
|
41
|
+
if (pf.patch !== pt.patch)
|
|
42
|
+
return 'patch';
|
|
43
|
+
return 'same';
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=semver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semver.js","sourceRoot":"","sources":["../../src/utils/semver.ts"],"names":[],"mappings":"AAEA,MAAM,QAAQ,GAAG,oCAAoC,CAAC;AAQtD,MAAM,UAAU,KAAK,CAAC,OAAe;IACnC,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACxD,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACpB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,CAAS,EAAE,CAAS;IAC1C,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACpB,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,CAAC;IACzB,IAAI,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC;IACtD,IAAI,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC;IACtD,OAAO,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC;AAC7B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,KAAK,CAAC,IAAmB,EAAE,EAAiB;IAC1D,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE;QAAE,OAAO,SAAS,CAAC;IACnC,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC;IACrB,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,OAAO,SAAS,CAAC;IACjC,IAAI,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,KAAK;QAAE,OAAO,OAAO,CAAC;IAC1C,IAAI,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,KAAK;QAAE,OAAO,OAAO,CAAC;IAC1C,IAAI,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,KAAK;QAAE,OAAO,OAAO,CAAC;IAC1C,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projscan",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Instant codebase insights — doctor, hotspots, SARIF for Code Scanning, and MCP server for any repository",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Instant codebase insights — doctor, hotspots, coverage × hotspots, dependency health, SARIF for Code Scanning, and MCP server for any repository",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|