@shvmgyl15/tsgraph 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.
Files changed (187) hide show
  1. package/AGENTS.md +64 -0
  2. package/README.md +128 -0
  3. package/TODOS.md +61 -0
  4. package/dist/analysis/analysis.test.d.ts +2 -0
  5. package/dist/analysis/analysis.test.d.ts.map +1 -0
  6. package/dist/analysis/analysis.test.js +359 -0
  7. package/dist/analysis/analysis.test.js.map +1 -0
  8. package/dist/analysis/complexity.d.ts +8 -0
  9. package/dist/analysis/complexity.d.ts.map +1 -0
  10. package/dist/analysis/complexity.js +88 -0
  11. package/dist/analysis/complexity.js.map +1 -0
  12. package/dist/analysis/coupling.d.ts +17 -0
  13. package/dist/analysis/coupling.d.ts.map +1 -0
  14. package/dist/analysis/coupling.js +71 -0
  15. package/dist/analysis/coupling.js.map +1 -0
  16. package/dist/analysis/hotspot.d.ts +10 -0
  17. package/dist/analysis/hotspot.d.ts.map +1 -0
  18. package/dist/analysis/hotspot.js +33 -0
  19. package/dist/analysis/hotspot.js.map +1 -0
  20. package/dist/analysis/index.d.ts +9 -0
  21. package/dist/analysis/index.d.ts.map +1 -0
  22. package/dist/analysis/index.js +5 -0
  23. package/dist/analysis/index.js.map +1 -0
  24. package/dist/boundaries/index.d.ts +25 -0
  25. package/dist/boundaries/index.d.ts.map +1 -0
  26. package/dist/boundaries/index.js +103 -0
  27. package/dist/boundaries/index.js.map +1 -0
  28. package/dist/boundaries/index.test.d.ts +2 -0
  29. package/dist/boundaries/index.test.d.ts.map +1 -0
  30. package/dist/boundaries/index.test.js +293 -0
  31. package/dist/boundaries/index.test.js.map +1 -0
  32. package/dist/changes/index.d.ts +28 -0
  33. package/dist/changes/index.d.ts.map +1 -0
  34. package/dist/changes/index.js +48 -0
  35. package/dist/changes/index.js.map +1 -0
  36. package/dist/changes/index.test.d.ts +2 -0
  37. package/dist/changes/index.test.d.ts.map +1 -0
  38. package/dist/changes/index.test.js +104 -0
  39. package/dist/changes/index.test.js.map +1 -0
  40. package/dist/cli/index.d.ts +3 -0
  41. package/dist/cli/index.d.ts.map +1 -0
  42. package/dist/cli/index.js +659 -0
  43. package/dist/cli/index.js.map +1 -0
  44. package/dist/git/index.d.ts +16 -0
  45. package/dist/git/index.d.ts.map +1 -0
  46. package/dist/git/index.js +73 -0
  47. package/dist/git/index.js.map +1 -0
  48. package/dist/git/index.test.d.ts +2 -0
  49. package/dist/git/index.test.d.ts.map +1 -0
  50. package/dist/git/index.test.js +78 -0
  51. package/dist/git/index.test.js.map +1 -0
  52. package/dist/graph/types.d.ts +156 -0
  53. package/dist/graph/types.d.ts.map +1 -0
  54. package/dist/graph/types.js +166 -0
  55. package/dist/graph/types.js.map +1 -0
  56. package/dist/graph/types.test.d.ts +2 -0
  57. package/dist/graph/types.test.d.ts.map +1 -0
  58. package/dist/graph/types.test.js +326 -0
  59. package/dist/graph/types.test.js.map +1 -0
  60. package/dist/mcp/mcp.test.d.ts +2 -0
  61. package/dist/mcp/mcp.test.d.ts.map +1 -0
  62. package/dist/mcp/mcp.test.js +151 -0
  63. package/dist/mcp/mcp.test.js.map +1 -0
  64. package/dist/mcp/server.d.ts +2 -0
  65. package/dist/mcp/server.d.ts.map +1 -0
  66. package/dist/mcp/server.js +209 -0
  67. package/dist/mcp/server.js.map +1 -0
  68. package/dist/nextjs/index.d.ts +8 -0
  69. package/dist/nextjs/index.d.ts.map +1 -0
  70. package/dist/nextjs/index.js +16 -0
  71. package/dist/nextjs/index.js.map +1 -0
  72. package/dist/nextjs/nextjs.test.d.ts +2 -0
  73. package/dist/nextjs/nextjs.test.d.ts.map +1 -0
  74. package/dist/nextjs/nextjs.test.js +190 -0
  75. package/dist/nextjs/nextjs.test.js.map +1 -0
  76. package/dist/nextjs/pages.d.ts +4 -0
  77. package/dist/nextjs/pages.d.ts.map +1 -0
  78. package/dist/nextjs/pages.js +36 -0
  79. package/dist/nextjs/pages.js.map +1 -0
  80. package/dist/nextjs/react.d.ts +3 -0
  81. package/dist/nextjs/react.d.ts.map +1 -0
  82. package/dist/nextjs/react.js +86 -0
  83. package/dist/nextjs/react.js.map +1 -0
  84. package/dist/nextjs/router.d.ts +4 -0
  85. package/dist/nextjs/router.d.ts.map +1 -0
  86. package/dist/nextjs/router.js +86 -0
  87. package/dist/nextjs/router.js.map +1 -0
  88. package/dist/nextjs/routes.d.ts +4 -0
  89. package/dist/nextjs/routes.d.ts.map +1 -0
  90. package/dist/nextjs/routes.js +58 -0
  91. package/dist/nextjs/routes.js.map +1 -0
  92. package/dist/opencode/index.d.ts +7 -0
  93. package/dist/opencode/index.d.ts.map +1 -0
  94. package/dist/opencode/index.js +71 -0
  95. package/dist/opencode/index.js.map +1 -0
  96. package/dist/opencode/index.test.d.ts +2 -0
  97. package/dist/opencode/index.test.d.ts.map +1 -0
  98. package/dist/opencode/index.test.js +71 -0
  99. package/dist/opencode/index.test.js.map +1 -0
  100. package/dist/parser/index.d.ts +4 -0
  101. package/dist/parser/index.d.ts.map +1 -0
  102. package/dist/parser/index.js +282 -0
  103. package/dist/parser/index.js.map +1 -0
  104. package/dist/parser/parser.test.d.ts +2 -0
  105. package/dist/parser/parser.test.d.ts.map +1 -0
  106. package/dist/parser/parser.test.js +225 -0
  107. package/dist/parser/parser.test.js.map +1 -0
  108. package/dist/plan/index.d.ts +32 -0
  109. package/dist/plan/index.d.ts.map +1 -0
  110. package/dist/plan/index.js +107 -0
  111. package/dist/plan/index.js.map +1 -0
  112. package/dist/plan/index.test.d.ts +2 -0
  113. package/dist/plan/index.test.d.ts.map +1 -0
  114. package/dist/plan/index.test.js +143 -0
  115. package/dist/plan/index.test.js.map +1 -0
  116. package/dist/report/index.d.ts +9 -0
  117. package/dist/report/index.d.ts.map +1 -0
  118. package/dist/report/index.js +108 -0
  119. package/dist/report/index.js.map +1 -0
  120. package/dist/scanner/index.d.ts +13 -0
  121. package/dist/scanner/index.d.ts.map +1 -0
  122. package/dist/scanner/index.js +78 -0
  123. package/dist/scanner/index.js.map +1 -0
  124. package/dist/scanner/scanner.test.d.ts +2 -0
  125. package/dist/scanner/scanner.test.d.ts.map +1 -0
  126. package/dist/scanner/scanner.test.js +113 -0
  127. package/dist/scanner/scanner.test.js.map +1 -0
  128. package/dist/search/index.d.ts +32 -0
  129. package/dist/search/index.d.ts.map +1 -0
  130. package/dist/search/index.js +97 -0
  131. package/dist/search/index.js.map +1 -0
  132. package/dist/search/search.test.d.ts +2 -0
  133. package/dist/search/search.test.d.ts.map +1 -0
  134. package/dist/search/search.test.js +446 -0
  135. package/dist/search/search.test.js.map +1 -0
  136. package/dist/traversal/index.d.ts +5 -0
  137. package/dist/traversal/index.d.ts.map +1 -0
  138. package/dist/traversal/index.js +3 -0
  139. package/dist/traversal/index.js.map +1 -0
  140. package/dist/traversal/traversal.d.ts +31 -0
  141. package/dist/traversal/traversal.d.ts.map +1 -0
  142. package/dist/traversal/traversal.js +130 -0
  143. package/dist/traversal/traversal.js.map +1 -0
  144. package/dist/traversal/traversal.test.d.ts +2 -0
  145. package/dist/traversal/traversal.test.d.ts.map +1 -0
  146. package/dist/traversal/traversal.test.js +224 -0
  147. package/dist/traversal/traversal.test.js.map +1 -0
  148. package/opencode.json +24 -0
  149. package/package.json +29 -0
  150. package/src/analysis/analysis.test.ts +405 -0
  151. package/src/analysis/complexity.ts +107 -0
  152. package/src/analysis/coupling.ts +106 -0
  153. package/src/analysis/hotspot.ts +52 -0
  154. package/src/analysis/index.ts +17 -0
  155. package/src/boundaries/index.test.ts +335 -0
  156. package/src/boundaries/index.ts +137 -0
  157. package/src/changes/index.test.ts +114 -0
  158. package/src/changes/index.ts +95 -0
  159. package/src/cli/index.ts +736 -0
  160. package/src/git/index.test.ts +92 -0
  161. package/src/git/index.ts +86 -0
  162. package/src/graph/types.test.ts +383 -0
  163. package/src/graph/types.ts +353 -0
  164. package/src/mcp/mcp.test.ts +176 -0
  165. package/src/mcp/server.ts +217 -0
  166. package/src/nextjs/index.ts +23 -0
  167. package/src/nextjs/nextjs.test.ts +233 -0
  168. package/src/nextjs/pages.ts +43 -0
  169. package/src/nextjs/react.ts +100 -0
  170. package/src/nextjs/router.ts +102 -0
  171. package/src/nextjs/routes.ts +69 -0
  172. package/src/opencode/index.test.ts +90 -0
  173. package/src/opencode/index.ts +83 -0
  174. package/src/parser/index.ts +339 -0
  175. package/src/parser/parser.test.ts +282 -0
  176. package/src/plan/index.test.ts +162 -0
  177. package/src/plan/index.ts +161 -0
  178. package/src/report/index.ts +128 -0
  179. package/src/scanner/index.ts +97 -0
  180. package/src/scanner/scanner.test.ts +135 -0
  181. package/src/search/index.ts +163 -0
  182. package/src/search/search.test.ts +512 -0
  183. package/src/traversal/index.ts +5 -0
  184. package/src/traversal/traversal.test.ts +266 -0
  185. package/src/traversal/traversal.ts +185 -0
  186. package/tsconfig.json +20 -0
  187. package/vitest.config.ts +7 -0
package/AGENTS.md ADDED
@@ -0,0 +1,64 @@
1
+ # tsgraph — Project DNA
2
+
3
+ ## Vision
4
+ A fast, local-only CLI tool that indexes Next.js / React / TypeScript codebases using AST
5
+ parsing into a queryable graph.json for AI coding agents. Equivalent to gograph but for TS.
6
+ Output is Markdown + JSON. No network calls, no telemetry, no SaaS backend.
7
+
8
+ ## Design Philosophy (Go → TS Adaptation)
9
+ tsgraph is inspired by gograph (Go) but adapted for TypeScript/React/Next.js — NOT a blind copy.
10
+ Key language-driven differences:
11
+ - **Export model**: TS `export` keyword maps to `isExported`; class methods are always considered exported (default `public`)
12
+ - **No goroutines/channels** — replaced by async/promise/setTimeout concurrency
13
+ - **No struct tags** — TS has no native equivalent
14
+ - **Router detection** is Next.js App Router / Pages Router, not Gin/mux
15
+ - **React components** tracked via `isClientComponent` / `isServerComponent`
16
+ - **Interface satisfaction** is structural in TS — `ImplementsEdge` may be dropped if unused
17
+ - Go-specific concepts (structs with fields+tests, `MutationEdge`, `StructField.tags`) are present but may be removed if they don't earn their keep for TS
18
+
19
+ ## Tech Stack
20
+ - Runtime: Node.js + tsx (dev) / tsc (build)
21
+ - AST: ts-morph (wraps TypeScript compiler API)
22
+ - CLI: commander
23
+ - MCP: @modelcontextprotocol/sdk
24
+ - Testing: vitest
25
+ - Linting: none (tsc strict mode is sufficient)
26
+
27
+ ## Agent Rules
28
+
29
+ ### Task Management
30
+ - READ TODOS.md at session start to know what's done and what's next
31
+ - UPDATE TODOS.md when you start/finish a task (`[.]` in-progress, `[x]` done)
32
+ - Work in phase order unless a task has no blockers
33
+
34
+ ### Orchestration
35
+ - This is a single-orchestrator project. When a task has multiple independent
36
+ sub-tasks, delegate via the `task` tool (`subagent_type: general`) rather
37
+ than doing them sequentially.
38
+ - For each delegated sub-task, specify:
39
+ 1. Exact files the sub-agent may modify
40
+ 2. Which phase from TODOS.md it belongs to
41
+ 3. What to return (never let sub-agents commit or merge)
42
+ - After all sub-tasks complete, run `npm run build && npm test` and fix
43
+ any issues directly. Do NOT re-delegate broken builds.
44
+
45
+ ### Quality
46
+ - Run `npm run build` (tsc) AND `npm test` (vitest) after every task completion
47
+ - Fix all type errors and test failures before marking `[x]`
48
+ - If build is already broken when you start, note it in TODOS.md and fix it first
49
+
50
+ ### Research
51
+ - Use webfetch when unsure about an API — check ts-morph docs, Next.js docs,
52
+ or reference gograph's Go source at https://github.com/ozgurcd/gograph
53
+ - DO NOT guess API signatures
54
+
55
+ ### Code Style
56
+ - No comments in source files unless logic is non-obvious
57
+ - Named exports only (no default exports)
58
+ - Strict TypeScript everywhere, avoid `any`
59
+ - Follow patterns from adjacent files in the codebase
60
+ - No emojis in source code or commit messages
61
+
62
+ ### Communication
63
+ - Be concise. Use TODOS.md for status, respond with only what's needed.
64
+ - If stuck, explain the blocker clearly rather than overthinking.
package/README.md ADDED
@@ -0,0 +1,128 @@
1
+ # @shvmgyl15/tsgraph
2
+
3
+ A fast, local-only CLI tool that indexes TypeScript/React/Next.js codebases using AST parsing into a queryable graph.json for AI coding agents.
4
+
5
+ No network calls, no telemetry, no SaaS backend.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install -g @shvmgyl15/tsgraph
11
+
12
+ # Or use directly via npx:
13
+ npx @shvmgyl15/tsgraph build .
14
+ ```
15
+
16
+ ## Quick Start
17
+
18
+ ```bash
19
+ # Index your project
20
+ cd my-project
21
+ tsgraph build .
22
+
23
+ # Query the graph
24
+ tsgraph query "getUser" # search symbols
25
+ tsgraph callers "getUser" # who calls getUser
26
+ tsgraph callees "getUser" # what getUser calls
27
+ tsgraph node "getUser" # symbol details
28
+ tsgraph source "getUser" # symbol source code
29
+
30
+ # Analysis
31
+ tsgraph hotspots # files needing refactoring
32
+ tsgraph complexity --sort # cyclomatic complexity
33
+ tsgraph orphans # dead code detection
34
+ tsgraph coupling # package dependency coupling
35
+
36
+ # Traversal
37
+ tsgraph impact "getUser" # downstream blast radius
38
+ tsgraph path "foo" "bar" # shortest call path
39
+ tsgraph trace "error msg" # trace string literal upstream
40
+ ```
41
+
42
+ ## All Commands
43
+
44
+ | Command | Description |
45
+ |---------|-------------|
46
+ | `build <root>` | Index project into `.tsgraph/graph.json` + `GRAPH_REPORT.md` |
47
+ | `callers <symbol>` | Show callers of a symbol |
48
+ | `callees <symbol>` | Show callees of a symbol |
49
+ | `node <symbol>` | Show symbol details |
50
+ | `source <symbol>` | Extract source code for a symbol |
51
+ | `query <pattern>` | Search symbols by pattern |
52
+ | `imports <path>` | Find files importing a package path |
53
+ | `public [package]` | List exported symbols |
54
+ | `focus <package>` | Show all assets for a package |
55
+ | `context <symbol>` | Bundle node + source + callers + callees |
56
+ | `complexity [file]` | Cyclomatic complexity analysis |
57
+ | `hotspot` | Rank files by complexity × size |
58
+ | `coupling` | Package coupling analysis |
59
+ | `deps <symbol>` | Call dependency tree |
60
+ | `impact <symbol>` | Downstream blast radius (BFS) |
61
+ | `path <from> <to>` | Shortest call path (BFS) |
62
+ | `orphans` | Dead code detection |
63
+ | `trace <string>` | String literal trace upstream |
64
+ | `boundaries` | Architecture enforcement via `.tsgraph/boundaries.json` |
65
+ | `changes [--base]` | Git-aware changed files and symbols |
66
+ | `stale [--days]` | Files not modified recently |
67
+ | `plan <files...>` | Change planning with blast radius |
68
+ | `review [--base]` | Code review summary |
69
+ | `add-opencode-plugin` | Configure opencode MCP + agent |
70
+ | `mcp` | Start MCP stdio server |
71
+
72
+ ## Next.js Support
73
+
74
+ @shvmgyl15/tsgraph automatically detects Next.js project structure:
75
+
76
+ - **App Router**: `page.tsx`, `layout.tsx`, `loading.tsx`, `error.tsx`, `route.ts`
77
+ - **Pages Router**: `pages/` directory structure
78
+ - **Client/Server**: `'use client'` / `'use server'` directives
79
+ - **React Hooks**: detects hooks usage for client component inference
80
+ - **API Routes**: extracts route handlers from `route.ts` files
81
+
82
+ ## Architecture Boundaries
83
+
84
+ Define layer rules in `.tsgraph/boundaries.json`:
85
+
86
+ ```json
87
+ {
88
+ "layers": [
89
+ { "name": "ui", "path": "src/components", "dependsOn": ["shared"] },
90
+ { "name": "shared", "path": "src/shared", "dependsOn": ["lib"] },
91
+ { "name": "lib", "path": "src/lib", "dependsOn": [] }
92
+ ]
93
+ }
94
+ ```
95
+
96
+ ```bash
97
+ tsgraph boundaries
98
+ ```
99
+
100
+ ## AI Agent Integration
101
+
102
+ ### opencode
103
+
104
+ ```bash
105
+ tsgraph add-opencode-plugin
106
+ ```
107
+ Updates `opencode.json` with the tsgraph MCP server and creates `.opencode/agents/tsgraph.json`.
108
+
109
+ ### Claude / Any MCP Client
110
+
111
+ ```bash
112
+ tsgraph mcp
113
+ ```
114
+ Starts an MCP stdio server exposing all query/search commands as tools. Configure your MCP client to launch `tsgraph mcp` as a subprocess.
115
+
116
+ ## Development
117
+
118
+ ```bash
119
+ git clone https://github.com/shvmgyl15/tsgraph.git
120
+ cd tsgraph
121
+ npm install
122
+ npm run build
123
+ npm test
124
+ ```
125
+
126
+ ## License
127
+
128
+ MIT
package/TODOS.md ADDED
@@ -0,0 +1,61 @@
1
+ # tsgraph — Implementation Plan
2
+
3
+ ## Phase 1: Project Scaffold
4
+ - [x] Update opencode.json with AGENTS.md reference
5
+ - [x] Create AGENTS.md with project DNA
6
+ - [x] Create TODOS.md (this file)
7
+ - [x] Initialize package.json with dependencies
8
+ - [x] Configure tsconfig.json (strict, ESNext)
9
+ - [x] Setup vitest config
10
+ - [x] Create src directory structure
11
+
12
+ ## Phase 2: Core Data Model
13
+ - [x] Define graph types (Graph, PackageNode, FileNode, SymbolNode, etc.)
14
+ - [x] Add JSON serialization / deserialization
15
+ - [x] Write unit tests for graph types
16
+
17
+ ## Phase 3: Scanner + Parser Core
18
+ - [x] Implement file scanner (walk tree, gitignore support, file classification)
19
+ - [x] Implement symbol extractor (ts-morph: functions, classes, interfaces, types, enums, vars)
20
+ - [x] Implement call expression extractor
21
+ - [x] Implement import edge + dependency (package.json) extractor
22
+ - [x] Wire up `build` command end-to-end
23
+ - [x] Write parser/scanner unit tests
24
+
25
+ ## Phase 4: Query Commands
26
+ - [x] callers / callees
27
+ - [x] node / source / query
28
+ - [x] context (bundle — node + source + callers + callees + tests)
29
+ - [x] imports / public / focus
30
+ - [x] Write query command tests
31
+
32
+ ## Phase 5: Next.js / React Extractors
33
+ - [x] App Router tree detection (page/layout/loading/error/route files)
34
+ - [x] Pages Router detection
35
+ - [x] 'use client' / 'use server' + hooks analysis
36
+ - [x] Route extraction from API / route handlers
37
+ - [x] Write extractor tests
38
+
39
+ ## Phase 6: Analysis Commands
40
+ - [x] complexity (cyclomatic)
41
+ - [x] hotspot / coupling / deps
42
+ - [x] Write analysis tests
43
+
44
+ ## Phase 7: Graph Traversal
45
+ - [x] impact (BFS downstream blast radius)
46
+ - [x] path (BFS shortest path between symbols)
47
+ - [x] orphans (dead code detection)
48
+ - [x] trace / errorflow (reverse BFS from string literal)
49
+ - [x] Write traversal tests
50
+
51
+ ## Phase 8: MCP Server
52
+ - [x] MCP stdio server wrapping all query tools
53
+ - [x] Tool definition for each search/query command
54
+ - [x] MCP integration test
55
+
56
+ ## Phase 9: Advanced Features
57
+ - [x] boundaries (architecture enforcement via .tsgraph/boundaries.json)
58
+ - [x] changes / stale (git-aware incremental analysis)
59
+ - [x] plan / review (change planning reports)
60
+ - [x] add-opencode-plugin (auto-configure opencode MCP + agent)
61
+ - [x] Enhanced GRAPH_REPORT.md (hotspots, boundaries, coupling, stale)
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=analysis.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analysis.test.d.ts","sourceRoot":"","sources":["../../src/analysis/analysis.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,359 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import path from "node:path";
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import { makeGraph, makeSymbolNode, makeCallEdge, makeImportEdge, makeFileNode, } from "../graph/types.js";
6
+ import { cyclomaticComplexity, analyzeComplexity } from "./complexity.js";
7
+ import { findHotspots } from "./hotspot.js";
8
+ import { analyzeCoupling, dependencyTree } from "./coupling.js";
9
+ function createTempDir() {
10
+ return fs.mkdtempSync(path.join(os.tmpdir(), "tsgraph-test-"));
11
+ }
12
+ describe("cyclomaticComplexity", () => {
13
+ it("returns 1 for a function with no branches", () => {
14
+ const code = `function greet() { return "hello"; }`;
15
+ expect(cyclomaticComplexity(code)).toBe(1);
16
+ });
17
+ it("counts if statements", () => {
18
+ const code = `function f() {
19
+ if (a) return 1;
20
+ if (b) return 2;
21
+ }`;
22
+ expect(cyclomaticComplexity(code)).toBe(3);
23
+ });
24
+ it("counts if-else as single branch point", () => {
25
+ const code = `function f() {
26
+ if (a) { return 1; }
27
+ else { return 2; }
28
+ }`;
29
+ expect(cyclomaticComplexity(code)).toBe(2);
30
+ });
31
+ it("counts else-if as additional branch", () => {
32
+ const code = `function f() {
33
+ if (a) { return 1; }
34
+ else if (b) { return 2; }
35
+ else { return 3; }
36
+ }`;
37
+ expect(cyclomaticComplexity(code)).toBe(3);
38
+ });
39
+ it("counts for loops", () => {
40
+ const code = `function f() {
41
+ for (let i = 0; i < 10; i++) {}
42
+ }`;
43
+ expect(cyclomaticComplexity(code)).toBe(2);
44
+ });
45
+ it("counts while loops", () => {
46
+ const code = `function f() {
47
+ while (true) { break; }
48
+ }`;
49
+ expect(cyclomaticComplexity(code)).toBe(2);
50
+ });
51
+ it("counts case labels", () => {
52
+ const code = `function f(x: number) {
53
+ switch (x) {
54
+ case 1: return "a";
55
+ case 2: return "b";
56
+ case 3: return "c";
57
+ }
58
+ }`;
59
+ expect(cyclomaticComplexity(code)).toBe(4);
60
+ });
61
+ it("counts catch clauses", () => {
62
+ const code = `function f() {
63
+ try { doStuff(); }
64
+ catch (e) { handle(); }
65
+ }`;
66
+ expect(cyclomaticComplexity(code)).toBe(2);
67
+ });
68
+ it("counts ternary operators", () => {
69
+ const code = `function f() {
70
+ return a ? b : c;
71
+ }`;
72
+ expect(cyclomaticComplexity(code)).toBe(2);
73
+ });
74
+ it("counts logical && and ||", () => {
75
+ const code = `function f() {
76
+ if (a && b || c) return 1;
77
+ }`;
78
+ expect(cyclomaticComplexity(code)).toBe(4);
79
+ });
80
+ it("avoids counting string literals", () => {
81
+ const code = `function f() {
82
+ const s = "if (true) { for(;;) {} }";
83
+ return s;
84
+ }`;
85
+ expect(cyclomaticComplexity(code)).toBe(1);
86
+ });
87
+ it("ignores comments", () => {
88
+ const code = `function f() {
89
+ // if (true) { return 1; }
90
+ /* for(;;) {} */
91
+ return 0;
92
+ }`;
93
+ expect(cyclomaticComplexity(code)).toBe(1);
94
+ });
95
+ });
96
+ describe("analyzeComplexity", () => {
97
+ it("returns complexity for all functions in a project", () => {
98
+ const dir = createTempDir();
99
+ const filePath = path.join(dir, "src/lib.ts");
100
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
101
+ fs.writeFileSync(filePath, [
102
+ "export function simple() { return 1; }",
103
+ "export function complex() {",
104
+ " if (a) { for(;;) {} }",
105
+ " return 0;",
106
+ "}",
107
+ ].join("\n"), "utf-8");
108
+ const graph = makeGraph({
109
+ root: dir,
110
+ files: [makeFileNode({ path: "src/lib.ts", lines: 5 })],
111
+ symbols: [
112
+ makeSymbolNode({
113
+ id: "simple",
114
+ name: "simple",
115
+ kind: "function",
116
+ file: "src/lib.ts",
117
+ line: 1,
118
+ endLine: 1,
119
+ packageName: "app",
120
+ isExported: true,
121
+ }),
122
+ makeSymbolNode({
123
+ id: "complex",
124
+ name: "complex",
125
+ kind: "function",
126
+ file: "src/lib.ts",
127
+ line: 2,
128
+ endLine: 5,
129
+ packageName: "app",
130
+ isExported: true,
131
+ }),
132
+ ],
133
+ });
134
+ const results = analyzeComplexity(graph);
135
+ expect(results).toHaveLength(2);
136
+ const simple = results.find((r) => r.symbol.name === "simple");
137
+ const complex = results.find((r) => r.symbol.name === "complex");
138
+ expect(simple.complexity).toBe(1);
139
+ expect(complex.complexity).toBeGreaterThanOrEqual(2);
140
+ fs.rmSync(dir, { recursive: true });
141
+ });
142
+ it("filters by file when specified", () => {
143
+ const dir = createTempDir();
144
+ const filePath = path.join(dir, "src/a.ts");
145
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
146
+ fs.writeFileSync(filePath, "export function foo() {}", "utf-8");
147
+ const graph = makeGraph({
148
+ root: dir,
149
+ symbols: [
150
+ makeSymbolNode({
151
+ id: "foo",
152
+ name: "foo",
153
+ kind: "function",
154
+ file: "src/a.ts",
155
+ line: 1,
156
+ endLine: 1,
157
+ }),
158
+ makeSymbolNode({
159
+ id: "bar",
160
+ name: "bar",
161
+ kind: "function",
162
+ file: "src/b.ts",
163
+ line: 1,
164
+ endLine: 1,
165
+ }),
166
+ ],
167
+ });
168
+ const results = analyzeComplexity(graph, "a.ts");
169
+ expect(results).toHaveLength(1);
170
+ expect(results[0].symbol.name).toBe("foo");
171
+ fs.rmSync(dir, { recursive: true });
172
+ });
173
+ });
174
+ describe("findHotspots", () => {
175
+ it("returns top hotspots sorted by score", () => {
176
+ const dir = createTempDir();
177
+ const filePath = path.join(dir, "src/hot.ts");
178
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
179
+ fs.writeFileSync(filePath, [
180
+ "export function a() {",
181
+ " if (x) { for(;;) {} }",
182
+ " if (y) { while(z) {} }",
183
+ " return 0;",
184
+ "}",
185
+ "export function b() { return 1; }",
186
+ ].join("\n"), "utf-8");
187
+ const graph = makeGraph({
188
+ root: dir,
189
+ files: [makeFileNode({ path: "src/hot.ts", lines: 6 })],
190
+ symbols: [
191
+ makeSymbolNode({
192
+ id: "a",
193
+ name: "a",
194
+ kind: "function",
195
+ file: "src/hot.ts",
196
+ line: 1,
197
+ endLine: 5,
198
+ packageName: "app",
199
+ }),
200
+ makeSymbolNode({
201
+ id: "b",
202
+ name: "b",
203
+ kind: "function",
204
+ file: "src/hot.ts",
205
+ line: 6,
206
+ endLine: 6,
207
+ packageName: "app",
208
+ }),
209
+ ],
210
+ });
211
+ const hotspots = findHotspots(graph, 5);
212
+ expect(hotspots.length).toBeGreaterThanOrEqual(1);
213
+ expect(hotspots[0].file).toBe("src/hot.ts");
214
+ fs.rmSync(dir, { recursive: true });
215
+ });
216
+ });
217
+ describe("analyzeCoupling", () => {
218
+ it("finds packages importing from other modules", () => {
219
+ const graph = makeGraph({
220
+ files: [
221
+ makeFileNode({ path: "src/orders.ts", packageName: "orders" }),
222
+ makeFileNode({ path: "src/payment.ts", packageName: "payment" }),
223
+ makeFileNode({ path: "src/notify.ts", packageName: "notify" }),
224
+ ],
225
+ imports: [
226
+ makeImportEdge({
227
+ fromFile: "src/orders.ts",
228
+ fromPackage: "orders",
229
+ importPath: "payment",
230
+ alias: "payment",
231
+ isDefault: true,
232
+ }),
233
+ makeImportEdge({
234
+ fromFile: "src/orders.ts",
235
+ fromPackage: "orders",
236
+ importPath: "notify",
237
+ alias: "notify",
238
+ isDefault: true,
239
+ }),
240
+ makeImportEdge({
241
+ fromFile: "src/orders.ts",
242
+ fromPackage: "orders",
243
+ importPath: "payment",
244
+ alias: "processPayment",
245
+ isDefault: false,
246
+ }),
247
+ ],
248
+ });
249
+ const results = analyzeCoupling(graph);
250
+ expect(results).toHaveLength(2);
251
+ const paymentCoupling = results.find((r) => r.coupledTo === "payment");
252
+ expect(paymentCoupling).toBeTruthy();
253
+ expect(paymentCoupling.importCount).toBe(2);
254
+ expect(paymentCoupling.packageName).toBe("orders");
255
+ });
256
+ });
257
+ describe("dependencyTree", () => {
258
+ it("builds a tree from call edges", () => {
259
+ const graph = makeGraph({
260
+ symbols: [
261
+ makeSymbolNode({
262
+ id: "src/main.ts::serve",
263
+ name: "serve",
264
+ kind: "function",
265
+ file: "src/main.ts",
266
+ line: 1,
267
+ endLine: 5,
268
+ packageName: "app",
269
+ }),
270
+ makeSymbolNode({
271
+ id: "src/main.ts::greet",
272
+ name: "greet",
273
+ kind: "function",
274
+ file: "src/main.ts",
275
+ line: 6,
276
+ endLine: 8,
277
+ packageName: "app",
278
+ }),
279
+ makeSymbolNode({
280
+ id: "src/main.ts::log",
281
+ name: "log",
282
+ kind: "function",
283
+ file: "src/main.ts",
284
+ line: 9,
285
+ endLine: 11,
286
+ packageName: "app",
287
+ }),
288
+ ],
289
+ calls: [
290
+ makeCallEdge({
291
+ callerSymbolId: "src/main.ts::serve",
292
+ callerName: "serve",
293
+ calleeRaw: "greet",
294
+ file: "src/main.ts",
295
+ line: 3,
296
+ }),
297
+ makeCallEdge({
298
+ callerSymbolId: "src/main.ts::serve",
299
+ callerName: "serve",
300
+ calleeRaw: "log",
301
+ file: "src/main.ts",
302
+ line: 4,
303
+ }),
304
+ ],
305
+ });
306
+ const tree = dependencyTree(graph, "serve");
307
+ expect(tree).toBeTruthy();
308
+ expect(tree.name).toBe("serve");
309
+ expect(tree.children).toHaveLength(2);
310
+ const childNames = tree.children.map((c) => c.name).sort();
311
+ expect(childNames).toEqual(["greet", "log"]);
312
+ });
313
+ it("returns undefined for unknown symbol", () => {
314
+ const graph = makeGraph();
315
+ const tree = dependencyTree(graph, "noop");
316
+ expect(tree).toBeUndefined();
317
+ });
318
+ it("respects max depth", () => {
319
+ const graph = makeGraph({
320
+ symbols: [
321
+ makeSymbolNode({
322
+ id: "a",
323
+ name: "a",
324
+ kind: "function",
325
+ file: "a.ts",
326
+ line: 1,
327
+ endLine: 1,
328
+ packageName: "app",
329
+ }),
330
+ makeSymbolNode({
331
+ id: "b",
332
+ name: "b",
333
+ kind: "function",
334
+ file: "b.ts",
335
+ line: 1,
336
+ endLine: 1,
337
+ packageName: "app",
338
+ }),
339
+ makeSymbolNode({
340
+ id: "c",
341
+ name: "c",
342
+ kind: "function",
343
+ file: "c.ts",
344
+ line: 1,
345
+ endLine: 1,
346
+ packageName: "app",
347
+ }),
348
+ ],
349
+ calls: [
350
+ makeCallEdge({ callerSymbolId: "a", callerName: "a", calleeRaw: "b", file: "a.ts", line: 1 }),
351
+ makeCallEdge({ callerSymbolId: "b", callerName: "b", calleeRaw: "c", file: "b.ts", line: 1 }),
352
+ ],
353
+ });
354
+ const tree = dependencyTree(graph, "a", 1);
355
+ expect(tree.children).toHaveLength(1);
356
+ expect(tree.children[0].children).toHaveLength(0);
357
+ });
358
+ });
359
+ //# sourceMappingURL=analysis.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analysis.test.js","sourceRoot":"","sources":["../../src/analysis/analysis.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { Graph, SymbolNode } from "../graph/types.js";
2
+ export declare function cyclomaticComplexity(sourceCode: string): number;
3
+ export interface ComplexityResult {
4
+ symbol: SymbolNode;
5
+ complexity: number;
6
+ }
7
+ export declare function analyzeComplexity(graph: Graph, fileFilter?: string): ComplexityResult[];
8
+ //# sourceMappingURL=complexity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"complexity.d.ts","sourceRoot":"","sources":["../../src/analysis/complexity.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AA+C3D,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAwB/D;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,KAAK,EACZ,UAAU,CAAC,EAAE,MAAM,GAClB,gBAAgB,EAAE,CAuBpB"}