@getmikk/diagram-generator 1.7.1 → 1.8.1

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 CHANGED
@@ -1,249 +1,74 @@
1
- # @getmikk/diagram-generator
1
+ # @getmikk/diagram-generator
2
2
 
3
- > Auto-generated Mermaid.js architecture diagrams from your actual codebase — no manual drawing, always accurate.
3
+ > 7 Mermaid architecture diagrams generated from your lock file.
4
4
 
5
5
  [![npm](https://img.shields.io/npm/v/@getmikk/diagram-generator)](https://www.npmjs.com/package/@getmikk/diagram-generator)
6
6
  [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](../../LICENSE)
7
7
 
8
- `@getmikk/diagram-generator` turns `mikk.json` and `mikk.lock.json` into rich [Mermaid.js](https://mermaid.js.org/) diagrams. Every diagram is derived entirely from compiler-grade AST data — function call edges, module assignments, Merkle health scores, import relationships. 7 diagram types: from high-level architecture overviews to per-function call flow sequences to N×N dependency matrices.
8
+ Generates Mermaid `.mmd` files from `mikk.lock.json` and `mikk.json`. All metrics are derived from the actual call graph no manual input.
9
9
 
10
- Because diagrams come from the lock file, they're always accurate. Run `mikk analyze` and your diagrams reflect the current codebase.
11
-
12
- > Part of [Mikk](../../README.md) — the codebase nervous system for AI-assisted development.
10
+ > Part of [Mikk](../../README.md) live architectural context for your AI agent.
13
11
 
14
12
  ---
15
13
 
16
- ## Installation
14
+ ## Usage
15
+
16
+ Generated automatically by `mikk init` and `mikk analyze`. Or regenerate manually:
17
17
 
18
18
  ```bash
19
- npm install @getmikk/diagram-generator
20
- # or
21
- bun add @getmikk/diagram-generator
19
+ mikk visualize all # all 7 diagrams
20
+ mikk visualize module <id> # one module diagram
22
21
  ```
23
22
 
24
- **Peer dependency:** `@getmikk/core`
25
-
26
- ---
27
-
28
- ## Quick Start
23
+ Programmatically:
29
24
 
30
25
  ```typescript
31
26
  import { DiagramOrchestrator } from '@getmikk/diagram-generator'
32
- import { ContractReader, LockReader } from '@getmikk/core'
33
-
34
- const contract = await new ContractReader().read('./mikk.json')
35
- const lock = await new LockReader().read('./mikk.lock.json')
36
-
37
- const orchestrator = new DiagramOrchestrator(contract, lock, process.cwd())
38
- const result = await orchestrator.generateAll()
39
-
40
- console.log(result.generated) // List of generated .mmd file paths
41
- // Files written to .mikk/diagrams/
42
- ```
43
-
44
- ---
45
-
46
- ## Diagram Types
47
-
48
- ### 1. Main Architecture Diagram
49
-
50
- High-level `graph TD` showing all modules with file/function counts and inter-module edges.
51
-
52
- ```typescript
53
- import { MainDiagramGenerator } from '@getmikk/diagram-generator'
54
-
55
- const gen = new MainDiagramGenerator(contract, lock)
56
- const mermaid = gen.generate()
57
- ```
58
-
59
- **Output example:**
60
-
61
- ```mermaid
62
- graph TD
63
- auth["auth<br/>📁 5 files · 📦 12 functions"]
64
- payments["payments<br/>📁 3 files · 📦 8 functions"]
65
- auth --> payments
66
- ```
67
-
68
- ---
69
-
70
- ### 2. Module Detail Diagram
71
-
72
- Zoomed-in per-module diagram showing file subgraphs, internal call edges, and external dependencies.
73
-
74
- ```typescript
75
- import { ModuleDiagramGenerator } from '@getmikk/diagram-generator'
76
-
77
- const gen = new ModuleDiagramGenerator(contract, lock)
78
- const mermaid = gen.generate('auth') // module ID
79
- ```
80
-
81
- Shows:
82
- - Subgraphs for each file in the module
83
- - Function nodes within each file
84
- - Internal call edges between functions
85
- - External call links to other modules
86
-
87
- ---
88
-
89
- ### 3. Impact Diagram
90
-
91
- Visualizes the blast radius of changes — what's directly changed (red) vs. transitively impacted (orange).
92
-
93
- ```typescript
94
- import { ImpactDiagramGenerator } from '@getmikk/diagram-generator'
95
-
96
- const gen = new ImpactDiagramGenerator(lock)
97
- const mermaid = gen.generate(
98
- ['auth/login.ts::validateToken'], // changed node IDs
99
- ['payments/checkout.ts::processPayment'] // impacted node IDs
100
- )
101
- ```
102
-
103
- **Output:** `graph LR` with color-coded nodes:
104
- - 🔴 **Red** — directly changed
105
- - 🟠 **Orange** — transitively impacted
106
- - Edges show the propagation chain
107
-
108
- ---
109
-
110
- ### 4. Health Dashboard
111
-
112
- Module health overview with cohesion percentage, coupling count, function count, and color-coded status.
113
27
 
114
- ```typescript
115
- import { HealthDiagramGenerator } from '@getmikk/diagram-generator'
116
-
117
- const gen = new HealthDiagramGenerator(contract, lock)
118
- const mermaid = gen.generate()
119
- ```
120
-
121
- **Metrics per module:**
122
-
123
- | Metric | Description |
124
- |--------|-------------|
125
- | Cohesion % | Ratio of internal calls to total calls (higher = better) |
126
- | Coupling | Count of cross-module dependencies (lower = better) |
127
- | Functions | Total function count |
128
- | Health | 🟢 Green (>70% cohesion) · 🟡 Yellow (40-70%) · 🔴 Red (<40%) |
129
-
130
- ---
131
-
132
- ### 5. Flow Diagram (Sequence)
133
-
134
- Traces a function's call chain as a Mermaid sequence diagram.
135
-
136
- ```typescript
137
- import { FlowDiagramGenerator } from '@getmikk/diagram-generator'
138
-
139
- const gen = new FlowDiagramGenerator(lock)
140
-
141
- // Trace from a specific function
142
- const sequence = gen.generate('auth/login.ts::handleLogin', /* maxDepth */ 5)
143
-
144
- // Show all entry-point functions grouped by module
145
- const entryPoints = gen.generateEntryPoints()
146
- ```
147
-
148
- The sequence diagram follows the call graph depth-first, showing which function calls which, across module boundaries.
149
-
150
- ---
151
-
152
- ### 6. Capsule Diagram
153
-
154
- Shows a module's public API surface — the "capsule" boundary:
155
-
156
- ```typescript
157
- import { CapsuleDiagramGenerator } from '@getmikk/diagram-generator'
158
-
159
- const gen = new CapsuleDiagramGenerator(contract, lock)
160
- const mermaid = gen.generate('auth') // module ID
28
+ const orchestrator = new DiagramOrchestrator(contract, lock, projectRoot)
29
+ const { generated } = await orchestrator.generateAll()
30
+ // generated: string[] — paths of written .mmd files
161
31
  ```
162
32
 
163
- **Visualizes:**
164
- - **Public functions** — exported and listed in the module's `publicApi`
165
- - **Internal functions** — everything else
166
- - **External consumers** — other modules that call into this module's public API
167
-
168
33
  ---
169
34
 
170
- ### 7. Dependency Matrix
35
+ ## Diagrams
171
36
 
172
- N×N cross-module dependency analysis:
37
+ All files are written to `.mikk/diagrams/`.
173
38
 
174
- ```typescript
175
- import { DependencyMatrixGenerator } from '@getmikk/diagram-generator'
39
+ ### `main.mmd`
40
+ Full architecture overview. All modules as nodes, inter-module dependencies as directed edges. Entry points marked distinctly.
176
41
 
177
- const gen = new DependencyMatrixGenerator(contract, lock)
42
+ ### `health.mmd`
43
+ Module health dashboard. For each module, shows:
44
+ - **Cohesion** — ratio of internal calls to total calls (higher = more self-contained)
45
+ - **Coupling** — count of external function calls + cross-module file imports (lower = more independent)
46
+ - **Function count**
47
+ - **Health indicator** — 🟢 healthy (> 70%), 🟡 warning (40–70%), 🔴 critical (< 40%)
178
48
 
179
- // Mermaid graph with weighted edges
180
- const graph = gen.generate()
49
+ Metrics are computed directly from the call graph in the lock file — not estimated.
181
50
 
182
- // Markdown table (N×N matrix)
183
- const table = gen.generateTable()
184
- ```
51
+ ### `matrix.mmd`
52
+ Dependency matrix. Grid of which modules depend on which. Identifies tight coupling and potential circular dependencies at a glance.
185
53
 
186
- **Markdown table example:**
54
+ ### `flow-entrypoints.mmd`
55
+ Entry point call flow. Traces how calls propagate from declared entry functions into the rest of the codebase.
187
56
 
188
- | | auth | payments | users |
189
- |---|---|---|---|
190
- | **auth** | — | 5 | 2 |
191
- | **payments** | 1 | — | 3 |
192
- | **users** | 0 | 0 | — |
57
+ ### `impact-<file>.mmd`
58
+ Blast radius visualization for a specific file change. Generated by `mikk context impact <file>`. Shows the change origin and all impacted nodes.
193
59
 
194
- Numbers represent cross-module function call counts.
60
+ ### `modules/<id>.mmd`
61
+ Per-module internal call graph. All functions in the module as nodes, internal function calls as edges. Exported functions marked distinctly.
195
62
 
196
- ---
197
-
198
- ## DiagramOrchestrator
199
-
200
- The orchestrator generates all diagrams at once and writes them to `.mikk/diagrams/`:
201
-
202
- ```typescript
203
- import { DiagramOrchestrator } from '@getmikk/diagram-generator'
204
-
205
- const orchestrator = new DiagramOrchestrator(contract, lock, projectRoot)
206
-
207
- // Generate everything
208
- const result = await orchestrator.generateAll()
209
- // Writes:
210
- // .mikk/diagrams/main.mmd
211
- // .mikk/diagrams/health.mmd
212
- // .mikk/diagrams/matrix.mmd
213
- // .mikk/diagrams/flow-entrypoints.mmd
214
- // .mikk/diagrams/module-{id}.mmd (one per module)
215
- // .mikk/diagrams/capsule-{id}.mmd (one per module)
216
-
217
- // Generate impact diagram for specific changes
218
- const impactMmd = await orchestrator.generateImpact(changedIds, impactedIds)
219
- // Writes: .mikk/diagrams/impact.mmd
220
- ```
221
-
222
- **Output files:** All diagrams are `.mmd` files that can be rendered with:
223
- - [Mermaid Live Editor](https://mermaid.live/)
224
- - GitHub Markdown (native Mermaid support)
225
- - VS Code Mermaid extensions
226
- - `mmdc` CLI (mermaid-cli)
63
+ ### `capsules/<id>.mmd`
64
+ Per-module public API capsule. Shows only the exported surface — function names, params, return types — without internal implementation detail.
227
65
 
228
66
  ---
229
67
 
230
- ## Types
231
-
232
- ```typescript
233
- import {
234
- DiagramOrchestrator,
235
- MainDiagramGenerator,
236
- ModuleDiagramGenerator,
237
- ImpactDiagramGenerator,
238
- HealthDiagramGenerator,
239
- FlowDiagramGenerator,
240
- CapsuleDiagramGenerator,
241
- DependencyMatrixGenerator,
242
- } from '@getmikk/diagram-generator'
243
- ```
244
-
245
- ---
68
+ ## Viewing Diagrams
246
69
 
247
- ## License
70
+ Any Mermaid-compatible renderer works. Recommended:
248
71
 
249
- [Apache-2.0](../../LICENSE)
72
+ - **VS Code**: install the "Mermaid Preview" extension, then open any `.mmd` file
73
+ - **GitHub**: Mermaid renders natively in `.md` files — embed with ` ```mermaid ` fences
74
+ - **Mermaid Live**: paste at https://mermaid.live
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getmikk/diagram-generator",
3
- "version": "1.7.1",
3
+ "version": "1.8.1",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,7 +21,7 @@
21
21
  "dev": "tsc --watch"
22
22
  },
23
23
  "dependencies": {
24
- "@getmikk/core": "^1.7.1"
24
+ "@getmikk/core": "^1.8.3"
25
25
  },
26
26
  "devDependencies": {
27
27
  "typescript": "^5.7.0",
@@ -0,0 +1,100 @@
1
+ import type { MikkContract, MikkLock } from '@getmikk/core'
2
+
3
+ /**
4
+ * Generates a Mermaid mindmap of all mikk CLI commands grouped by category.
5
+ * Does not depend on contract or lock data — it is a static reference diagram.
6
+ */
7
+ export class CommandsDiagramGenerator {
8
+ // contract/lock kept for interface consistency with other generators
9
+ constructor(
10
+ private _contract?: MikkContract,
11
+ private _lock?: MikkLock,
12
+ ) {}
13
+
14
+ generate(): string {
15
+ return `mindmap
16
+ root((mikk))
17
+ Setup
18
+ mikk init
19
+ Scan project
20
+ Build dependency graph
21
+ Generate all artifacts
22
+ mikk analyze
23
+ Re-analyze after changes
24
+ Update lock file
25
+ mikk watch
26
+ Live file watcher daemon
27
+ Incremental updates
28
+ 100ms debounce
29
+ mikk diff
30
+ Files changed since last analysis
31
+ mikk remove
32
+ Uninstall mikk
33
+ Delete all artifacts
34
+ Health
35
+ mikk stats
36
+ Per-module metrics
37
+ Function counts
38
+ Dead code %
39
+ mikk doctor
40
+ 7-point diagnostic check
41
+ Config validation
42
+ Lock freshness
43
+ mikk dead-code
44
+ Unused functions
45
+ Filter by module
46
+ Architecture
47
+ mikk ci
48
+ Exit non-zero on violations
49
+ CI pipeline gate
50
+ mikk ci --strict
51
+ Also enforce dead code threshold
52
+ mikk ci --format json
53
+ Machine-readable output
54
+ mikk contract validate
55
+ Constraint violations
56
+ Drift detection
57
+ mikk contract show-boundaries
58
+ Cross-module dependencies
59
+ Context
60
+ mikk context query
61
+ Architecture question
62
+ Graph-traced response
63
+ mikk context impact
64
+ Blast radius of a file change
65
+ Classified by severity
66
+ mikk context for
67
+ Token-budgeted task context
68
+ Refactoring
69
+ mikk intent
70
+ Pre-flight a refactor
71
+ Detect conflicts before coding
72
+ mikk rename
73
+ Coordinated multi-file rename
74
+ Find all call sites
75
+ MCP Server
76
+ mikk mcp
77
+ Start MCP server
78
+ 22 tools available
79
+ mikk mcp install
80
+ Install into Claude Desktop
81
+ Install into Cursor
82
+ Visualization
83
+ mikk visualize all
84
+ Regenerate all diagrams
85
+ 7 diagram types
86
+ mikk visualize module
87
+ Per-module call graph
88
+ Public API capsule
89
+ mikk visualize commands
90
+ This diagram
91
+ Decisions
92
+ mikk adr list
93
+ All architectural decisions
94
+ mikk adr add
95
+ New ADR
96
+ mikk adr get
97
+ Details for a specific ADR
98
+ `
99
+ }
100
+ }
@@ -93,7 +93,9 @@ export class DependencyMatrixGenerator {
93
93
  // Count file-level cross-module imports
94
94
  for (const file of Object.values(this.lock.files)) {
95
95
  if (!file.imports) continue
96
- for (const importedPath of file.imports) {
96
+ for (const imp of file.imports) {
97
+ const importedPath = imp.resolvedPath
98
+ if (!importedPath) continue
97
99
  const importedFile = this.lock.files[importedPath]
98
100
  if (importedFile && file.moduleId !== importedFile.moduleId) {
99
101
  const key = `${file.moduleId}|${importedFile.moduleId}`
@@ -45,7 +45,9 @@ export class HealthDiagramGenerator {
45
45
  }
46
46
  for (const file of Object.values(this.lock.files)) {
47
47
  if (!file.imports) continue
48
- for (const importedPath of file.imports) {
48
+ for (const imp of file.imports) {
49
+ const importedPath = imp.resolvedPath
50
+ if (!importedPath) continue
49
51
  const importedFile = this.lock.files[importedPath]
50
52
  if (importedFile && file.moduleId !== importedFile.moduleId) {
51
53
  const key = `${file.moduleId}|${importedFile.moduleId}`
@@ -88,7 +90,9 @@ export class HealthDiagramGenerator {
88
90
  }
89
91
  for (const file of moduleFiles) {
90
92
  if (!file.imports) continue
91
- for (const importedPath of file.imports) {
93
+ for (const imp of file.imports) {
94
+ const importedPath = imp.resolvedPath
95
+ if (!importedPath) continue
92
96
  const importedFile = this.lock.files[importedPath]
93
97
  if (importedFile) {
94
98
  if (importedFile.moduleId === moduleId) internalCalls++
@@ -61,7 +61,9 @@ export class MainDiagramGenerator {
61
61
  // File-level cross-module imports
62
62
  for (const file of Object.values(this.lock.files)) {
63
63
  if (!file.imports) continue
64
- for (const importedPath of file.imports) {
64
+ for (const imp of file.imports) {
65
+ const importedPath = imp.resolvedPath
66
+ if (!importedPath) continue
65
67
  const importedFile = this.lock.files[importedPath]
66
68
  if (importedFile && file.moduleId !== importedFile.moduleId) {
67
69
  const edgeKey = `${file.moduleId}→${importedFile.moduleId}`
@@ -103,7 +105,7 @@ export class MainDiagramGenerator {
103
105
  const ranked = allFiles
104
106
  .map(f => ({
105
107
  ...f,
106
- connections: (f.imports?.length || 0) + (Object.values(this.lock.files).filter(other => other.imports?.includes(f.path)).length),
108
+ connections: (f.imports?.length || 0) + (Object.values(this.lock.files).filter(other => other.imports?.some(i => i.resolvedPath === f.path)).length),
107
109
  }))
108
110
  .sort((a, b) => b.connections - a.connections)
109
111
 
@@ -146,8 +148,8 @@ export class MainDiagramGenerator {
146
148
  for (const file of filesToShow) {
147
149
  if (!file.imports) continue
148
150
  for (const imp of file.imports) {
149
- if (shownPaths.has(imp)) {
150
- lines.push(` ${this.sanitizeId(file.path)} --> ${this.sanitizeId(imp)}`)
151
+ if (imp.resolvedPath && shownPaths.has(imp.resolvedPath)) {
152
+ lines.push(` ${this.sanitizeId(file.path)} --> ${this.sanitizeId(imp.resolvedPath)}`)
151
153
  }
152
154
  }
153
155
  }
package/src/index.ts CHANGED
@@ -6,3 +6,4 @@ export { HealthDiagramGenerator } from './generators/health-diagram.js'
6
6
  export { FlowDiagramGenerator } from './generators/flow-diagram.js'
7
7
  export { CapsuleDiagramGenerator } from './generators/capsule-diagram.js'
8
8
  export { DependencyMatrixGenerator } from './generators/dependency-matrix.js'
9
+ export { CommandsDiagramGenerator } from './generators/commands-diagram.js'
@@ -8,6 +8,7 @@ import { HealthDiagramGenerator } from './generators/health-diagram.js'
8
8
  import { FlowDiagramGenerator } from './generators/flow-diagram.js'
9
9
  import { CapsuleDiagramGenerator } from './generators/capsule-diagram.js'
10
10
  import { DependencyMatrixGenerator } from './generators/dependency-matrix.js'
11
+ import { CommandsDiagramGenerator } from './generators/commands-diagram.js'
11
12
 
12
13
  /**
13
14
  * DiagramOrchestrator — generates all diagram types and writes them to
@@ -0,0 +1,57 @@
1
+ import { describe, it, expect } from 'bun:test'
2
+ import { MainDiagramGenerator } from '../src/generators/main-diagram.js'
3
+ import type { MikkContract, MikkLock } from '@getmikk/core'
4
+
5
+ describe('MainDiagramGenerator', () => {
6
+ it('generates a file-level view for 0 modules', () => {
7
+ const contract: MikkContract = {
8
+ project: { name: 'test', language: 'typescript', framework: null },
9
+ declared: {
10
+ modules: [],
11
+ constraints: [],
12
+ decisions: []
13
+ },
14
+ overwrite: { mode: 'never', requireConfirmation: false }
15
+ }
16
+ const lock: MikkLock = {
17
+ version: '1',
18
+ lastUpdated: new Date().toISOString(),
19
+ files: {},
20
+ functions: {},
21
+ classes: {},
22
+ modules: {}
23
+ }
24
+
25
+ const gen = new MainDiagramGenerator(contract, lock)
26
+ const diagram = gen.generate()
27
+ expect(diagram).toContain('graph TD')
28
+ })
29
+
30
+ it('generates a multi-module view for 2+ modules', () => {
31
+ const contract: MikkContract = {
32
+ project: { name: 'test', language: 'typescript', framework: null },
33
+ declared: {
34
+ modules: [
35
+ { id: 'auth', name: 'Auth', functions: [] },
36
+ { id: 'db', name: 'Database', functions: [] }
37
+ ],
38
+ constraints: [],
39
+ decisions: []
40
+ },
41
+ overwrite: { mode: 'never', requireConfirmation: false }
42
+ }
43
+ const lock: MikkLock = {
44
+ version: '1',
45
+ lastUpdated: new Date().toISOString(),
46
+ files: {},
47
+ functions: {},
48
+ classes: {},
49
+ modules: {}
50
+ }
51
+
52
+ const gen = new MainDiagramGenerator(contract, lock)
53
+ const diagram = gen.generate()
54
+ expect(diagram).toContain('auth["📦 Auth')
55
+ expect(diagram).toContain('db["📦 Database')
56
+ })
57
+ })