@getmikk/core 1.5.1 → 1.7.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 +44 -6
- package/out.log +0 -0
- package/package.json +4 -3
- package/src/contract/adr-manager.ts +75 -0
- package/src/contract/index.ts +2 -0
- package/src/contract/lock-compiler.ts +6 -5
- package/src/contract/lock-reader.ts +40 -26
- package/src/contract/schema.ts +2 -7
- package/src/graph/dead-code-detector.ts +194 -0
- package/src/graph/graph-builder.ts +6 -2
- package/src/graph/impact-analyzer.ts +53 -2
- package/src/graph/index.ts +4 -1
- package/src/graph/types.ts +21 -0
- package/src/index.ts +1 -1
- package/src/parser/go/go-extractor.ts +712 -0
- package/src/parser/go/go-parser.ts +41 -0
- package/src/parser/go/go-resolver.ts +70 -0
- package/src/parser/index.ts +46 -6
- package/src/parser/javascript/js-extractor.ts +262 -0
- package/src/parser/javascript/js-parser.ts +92 -0
- package/src/parser/javascript/js-resolver.ts +83 -0
- package/src/parser/types.ts +1 -1
- package/src/parser/typescript/ts-extractor.ts +93 -42
- package/src/parser/typescript/ts-parser.ts +120 -1
- package/test-output.txt +0 -0
- package/tests/adr-manager.test.ts +97 -0
- package/tests/contract.test.ts +1 -1
- package/tests/dead-code.test.ts +134 -0
- package/tests/go-parser.test.ts +366 -0
- package/tests/helpers.ts +0 -1
- package/tests/impact-classified.test.ts +78 -0
- package/tests/js-parser.test.ts +616 -0
- package/tests/ts-parser.test.ts +93 -0
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import type { DependencyGraph, ImpactResult } from './types.js'
|
|
1
|
+
import type { DependencyGraph, ImpactResult, ClassifiedImpact, RiskLevel } from './types.js'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* ImpactAnalyzer — Given changed nodes, walks the graph backwards (BFS)
|
|
5
5
|
* to find everything that depends on them.
|
|
6
6
|
* Powers "what breaks if I change X?"
|
|
7
|
+
*
|
|
8
|
+
* Now includes risk classification:
|
|
9
|
+
* CRITICAL = direct caller (depth 1) that crosses a module boundary
|
|
10
|
+
* HIGH = direct caller (depth 1) within the same module
|
|
11
|
+
* MEDIUM = depth 2
|
|
12
|
+
* LOW = depth 3+
|
|
7
13
|
*/
|
|
8
14
|
export class ImpactAnalyzer {
|
|
9
15
|
constructor(private graph: DependencyGraph) { }
|
|
@@ -11,13 +17,24 @@ export class ImpactAnalyzer {
|
|
|
11
17
|
/** Given a list of changed node IDs, find everything impacted */
|
|
12
18
|
analyze(changedNodeIds: string[]): ImpactResult {
|
|
13
19
|
const visited = new Set<string>()
|
|
20
|
+
const depthMap = new Map<string, number>()
|
|
14
21
|
const queue: { id: string; depth: number }[] = changedNodeIds.map(id => ({ id, depth: 0 }))
|
|
15
22
|
let maxDepth = 0
|
|
16
23
|
|
|
24
|
+
const changedSet = new Set(changedNodeIds)
|
|
25
|
+
|
|
26
|
+
// Collect module IDs of the changed nodes
|
|
27
|
+
const changedModules = new Set<string | undefined>()
|
|
28
|
+
for (const id of changedNodeIds) {
|
|
29
|
+
const node = this.graph.nodes.get(id)
|
|
30
|
+
if (node) changedModules.add(node.moduleId)
|
|
31
|
+
}
|
|
32
|
+
|
|
17
33
|
while (queue.length > 0) {
|
|
18
34
|
const { id: current, depth } = queue.shift()!
|
|
19
35
|
if (visited.has(current)) continue
|
|
20
36
|
visited.add(current)
|
|
37
|
+
depthMap.set(current, depth)
|
|
21
38
|
maxDepth = Math.max(maxDepth, depth)
|
|
22
39
|
|
|
23
40
|
// Find everything that depends on current (incoming edges)
|
|
@@ -29,13 +46,47 @@ export class ImpactAnalyzer {
|
|
|
29
46
|
}
|
|
30
47
|
}
|
|
31
48
|
|
|
32
|
-
const impacted = [...visited].filter(id => !
|
|
49
|
+
const impacted = [...visited].filter(id => !changedSet.has(id))
|
|
50
|
+
|
|
51
|
+
// Classify each impacted node by risk level
|
|
52
|
+
const classified: ImpactResult['classified'] = {
|
|
53
|
+
critical: [],
|
|
54
|
+
high: [],
|
|
55
|
+
medium: [],
|
|
56
|
+
low: [],
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
for (const id of impacted) {
|
|
60
|
+
const node = this.graph.nodes.get(id)
|
|
61
|
+
if (!node) continue
|
|
62
|
+
|
|
63
|
+
const depth = depthMap.get(id) ?? 999
|
|
64
|
+
const crossesBoundary = !changedModules.has(node.moduleId)
|
|
65
|
+
|
|
66
|
+
const risk: RiskLevel =
|
|
67
|
+
depth === 1 && crossesBoundary ? 'critical' :
|
|
68
|
+
depth === 1 ? 'high' :
|
|
69
|
+
depth === 2 ? 'medium' :
|
|
70
|
+
'low'
|
|
71
|
+
|
|
72
|
+
const entry: ClassifiedImpact = {
|
|
73
|
+
nodeId: id,
|
|
74
|
+
label: node.label,
|
|
75
|
+
file: node.file,
|
|
76
|
+
moduleId: node.moduleId,
|
|
77
|
+
risk,
|
|
78
|
+
depth,
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
classified[risk].push(entry)
|
|
82
|
+
}
|
|
33
83
|
|
|
34
84
|
return {
|
|
35
85
|
changed: changedNodeIds,
|
|
36
86
|
impacted,
|
|
37
87
|
depth: maxDepth,
|
|
38
88
|
confidence: this.computeConfidence(impacted.length, maxDepth),
|
|
89
|
+
classified,
|
|
39
90
|
}
|
|
40
91
|
}
|
|
41
92
|
|
package/src/graph/index.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
export type { DependencyGraph, GraphNode, GraphEdge, ImpactResult, NodeType, EdgeType, ModuleCluster } from './types.js'
|
|
1
|
+
export type { DependencyGraph, GraphNode, GraphEdge, ImpactResult, NodeType, EdgeType, ModuleCluster, RiskLevel, ClassifiedImpact } from './types.js'
|
|
2
2
|
export { GraphBuilder } from './graph-builder.js'
|
|
3
3
|
export { ImpactAnalyzer } from './impact-analyzer.js'
|
|
4
4
|
export { ClusterDetector } from './cluster-detector.js'
|
|
5
|
+
export { DeadCodeDetector } from './dead-code-detector.js'
|
|
6
|
+
export type { DeadCodeResult, DeadCodeEntry } from './dead-code-detector.js'
|
|
7
|
+
|
package/src/graph/types.ts
CHANGED
|
@@ -33,6 +33,7 @@ export interface GraphEdge {
|
|
|
33
33
|
target: string // "fn:src/utils/jwt.ts:jwtDecode"
|
|
34
34
|
type: EdgeType
|
|
35
35
|
weight?: number // How often this call happens (for coupling metrics)
|
|
36
|
+
confidence?: number // 0.0–1.0: 1.0 = direct AST call, 0.8 = via interface, 0.5 = fuzzy/inferred
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
/** The full dependency graph */
|
|
@@ -43,12 +44,32 @@ export interface DependencyGraph {
|
|
|
43
44
|
inEdges: Map<string, GraphEdge[]> // node → [edges coming in]
|
|
44
45
|
}
|
|
45
46
|
|
|
47
|
+
/** Risk level for an impacted node */
|
|
48
|
+
export type RiskLevel = 'critical' | 'high' | 'medium' | 'low'
|
|
49
|
+
|
|
50
|
+
/** A single node in the classified impact result */
|
|
51
|
+
export interface ClassifiedImpact {
|
|
52
|
+
nodeId: string
|
|
53
|
+
label: string
|
|
54
|
+
file: string
|
|
55
|
+
moduleId?: string
|
|
56
|
+
risk: RiskLevel
|
|
57
|
+
depth: number // hops from change
|
|
58
|
+
}
|
|
59
|
+
|
|
46
60
|
/** Result of impact analysis */
|
|
47
61
|
export interface ImpactResult {
|
|
48
62
|
changed: string[] // The directly changed nodes
|
|
49
63
|
impacted: string[] // Everything that depends on changed nodes
|
|
50
64
|
depth: number // How many hops from change to furthest impact
|
|
51
65
|
confidence: 'high' | 'medium' | 'low'
|
|
66
|
+
/** Risk-classified breakdown of impacted nodes */
|
|
67
|
+
classified: {
|
|
68
|
+
critical: ClassifiedImpact[]
|
|
69
|
+
high: ClassifiedImpact[]
|
|
70
|
+
medium: ClassifiedImpact[]
|
|
71
|
+
low: ClassifiedImpact[]
|
|
72
|
+
}
|
|
52
73
|
}
|
|
53
74
|
|
|
54
75
|
/** A cluster of files that naturally belong together */
|
package/src/index.ts
CHANGED
|
@@ -10,4 +10,4 @@ export * from './utils/logger.js'
|
|
|
10
10
|
export { discoverFiles, discoverContextFiles, readFileContent, writeFileContent, fileExists, setupMikkDirectory, readMikkIgnore, parseMikkIgnore, detectProjectLanguage, getDiscoveryPatterns, generateMikkIgnore } from './utils/fs.js'
|
|
11
11
|
export type { ContextFile, ContextFileType, ProjectLanguage } from './utils/fs.js'
|
|
12
12
|
export { minimatch } from './utils/minimatch.js'
|
|
13
|
-
export { scoreFunctions, findFuzzyMatches, levenshtein, splitCamelCase, extractKeywords } from './utils/fuzzy-match.js'
|
|
13
|
+
export { scoreFunctions, findFuzzyMatches, levenshtein, splitCamelCase, extractKeywords } from './utils/fuzzy-match.js'
|