@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.
- package/AGENTS.md +64 -0
- package/README.md +128 -0
- package/TODOS.md +61 -0
- package/dist/analysis/analysis.test.d.ts +2 -0
- package/dist/analysis/analysis.test.d.ts.map +1 -0
- package/dist/analysis/analysis.test.js +359 -0
- package/dist/analysis/analysis.test.js.map +1 -0
- package/dist/analysis/complexity.d.ts +8 -0
- package/dist/analysis/complexity.d.ts.map +1 -0
- package/dist/analysis/complexity.js +88 -0
- package/dist/analysis/complexity.js.map +1 -0
- package/dist/analysis/coupling.d.ts +17 -0
- package/dist/analysis/coupling.d.ts.map +1 -0
- package/dist/analysis/coupling.js +71 -0
- package/dist/analysis/coupling.js.map +1 -0
- package/dist/analysis/hotspot.d.ts +10 -0
- package/dist/analysis/hotspot.d.ts.map +1 -0
- package/dist/analysis/hotspot.js +33 -0
- package/dist/analysis/hotspot.js.map +1 -0
- package/dist/analysis/index.d.ts +9 -0
- package/dist/analysis/index.d.ts.map +1 -0
- package/dist/analysis/index.js +5 -0
- package/dist/analysis/index.js.map +1 -0
- package/dist/boundaries/index.d.ts +25 -0
- package/dist/boundaries/index.d.ts.map +1 -0
- package/dist/boundaries/index.js +103 -0
- package/dist/boundaries/index.js.map +1 -0
- package/dist/boundaries/index.test.d.ts +2 -0
- package/dist/boundaries/index.test.d.ts.map +1 -0
- package/dist/boundaries/index.test.js +293 -0
- package/dist/boundaries/index.test.js.map +1 -0
- package/dist/changes/index.d.ts +28 -0
- package/dist/changes/index.d.ts.map +1 -0
- package/dist/changes/index.js +48 -0
- package/dist/changes/index.js.map +1 -0
- package/dist/changes/index.test.d.ts +2 -0
- package/dist/changes/index.test.d.ts.map +1 -0
- package/dist/changes/index.test.js +104 -0
- package/dist/changes/index.test.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +659 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/git/index.d.ts +16 -0
- package/dist/git/index.d.ts.map +1 -0
- package/dist/git/index.js +73 -0
- package/dist/git/index.js.map +1 -0
- package/dist/git/index.test.d.ts +2 -0
- package/dist/git/index.test.d.ts.map +1 -0
- package/dist/git/index.test.js +78 -0
- package/dist/git/index.test.js.map +1 -0
- package/dist/graph/types.d.ts +156 -0
- package/dist/graph/types.d.ts.map +1 -0
- package/dist/graph/types.js +166 -0
- package/dist/graph/types.js.map +1 -0
- package/dist/graph/types.test.d.ts +2 -0
- package/dist/graph/types.test.d.ts.map +1 -0
- package/dist/graph/types.test.js +326 -0
- package/dist/graph/types.test.js.map +1 -0
- package/dist/mcp/mcp.test.d.ts +2 -0
- package/dist/mcp/mcp.test.d.ts.map +1 -0
- package/dist/mcp/mcp.test.js +151 -0
- package/dist/mcp/mcp.test.js.map +1 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +209 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/nextjs/index.d.ts +8 -0
- package/dist/nextjs/index.d.ts.map +1 -0
- package/dist/nextjs/index.js +16 -0
- package/dist/nextjs/index.js.map +1 -0
- package/dist/nextjs/nextjs.test.d.ts +2 -0
- package/dist/nextjs/nextjs.test.d.ts.map +1 -0
- package/dist/nextjs/nextjs.test.js +190 -0
- package/dist/nextjs/nextjs.test.js.map +1 -0
- package/dist/nextjs/pages.d.ts +4 -0
- package/dist/nextjs/pages.d.ts.map +1 -0
- package/dist/nextjs/pages.js +36 -0
- package/dist/nextjs/pages.js.map +1 -0
- package/dist/nextjs/react.d.ts +3 -0
- package/dist/nextjs/react.d.ts.map +1 -0
- package/dist/nextjs/react.js +86 -0
- package/dist/nextjs/react.js.map +1 -0
- package/dist/nextjs/router.d.ts +4 -0
- package/dist/nextjs/router.d.ts.map +1 -0
- package/dist/nextjs/router.js +86 -0
- package/dist/nextjs/router.js.map +1 -0
- package/dist/nextjs/routes.d.ts +4 -0
- package/dist/nextjs/routes.d.ts.map +1 -0
- package/dist/nextjs/routes.js +58 -0
- package/dist/nextjs/routes.js.map +1 -0
- package/dist/opencode/index.d.ts +7 -0
- package/dist/opencode/index.d.ts.map +1 -0
- package/dist/opencode/index.js +71 -0
- package/dist/opencode/index.js.map +1 -0
- package/dist/opencode/index.test.d.ts +2 -0
- package/dist/opencode/index.test.d.ts.map +1 -0
- package/dist/opencode/index.test.js +71 -0
- package/dist/opencode/index.test.js.map +1 -0
- package/dist/parser/index.d.ts +4 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +282 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/parser.test.d.ts +2 -0
- package/dist/parser/parser.test.d.ts.map +1 -0
- package/dist/parser/parser.test.js +225 -0
- package/dist/parser/parser.test.js.map +1 -0
- package/dist/plan/index.d.ts +32 -0
- package/dist/plan/index.d.ts.map +1 -0
- package/dist/plan/index.js +107 -0
- package/dist/plan/index.js.map +1 -0
- package/dist/plan/index.test.d.ts +2 -0
- package/dist/plan/index.test.d.ts.map +1 -0
- package/dist/plan/index.test.js +143 -0
- package/dist/plan/index.test.js.map +1 -0
- package/dist/report/index.d.ts +9 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +108 -0
- package/dist/report/index.js.map +1 -0
- package/dist/scanner/index.d.ts +13 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +78 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/scanner.test.d.ts +2 -0
- package/dist/scanner/scanner.test.d.ts.map +1 -0
- package/dist/scanner/scanner.test.js +113 -0
- package/dist/scanner/scanner.test.js.map +1 -0
- package/dist/search/index.d.ts +32 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +97 -0
- package/dist/search/index.js.map +1 -0
- package/dist/search/search.test.d.ts +2 -0
- package/dist/search/search.test.d.ts.map +1 -0
- package/dist/search/search.test.js +446 -0
- package/dist/search/search.test.js.map +1 -0
- package/dist/traversal/index.d.ts +5 -0
- package/dist/traversal/index.d.ts.map +1 -0
- package/dist/traversal/index.js +3 -0
- package/dist/traversal/index.js.map +1 -0
- package/dist/traversal/traversal.d.ts +31 -0
- package/dist/traversal/traversal.d.ts.map +1 -0
- package/dist/traversal/traversal.js +130 -0
- package/dist/traversal/traversal.js.map +1 -0
- package/dist/traversal/traversal.test.d.ts +2 -0
- package/dist/traversal/traversal.test.d.ts.map +1 -0
- package/dist/traversal/traversal.test.js +224 -0
- package/dist/traversal/traversal.test.js.map +1 -0
- package/opencode.json +24 -0
- package/package.json +29 -0
- package/src/analysis/analysis.test.ts +405 -0
- package/src/analysis/complexity.ts +107 -0
- package/src/analysis/coupling.ts +106 -0
- package/src/analysis/hotspot.ts +52 -0
- package/src/analysis/index.ts +17 -0
- package/src/boundaries/index.test.ts +335 -0
- package/src/boundaries/index.ts +137 -0
- package/src/changes/index.test.ts +114 -0
- package/src/changes/index.ts +95 -0
- package/src/cli/index.ts +736 -0
- package/src/git/index.test.ts +92 -0
- package/src/git/index.ts +86 -0
- package/src/graph/types.test.ts +383 -0
- package/src/graph/types.ts +353 -0
- package/src/mcp/mcp.test.ts +176 -0
- package/src/mcp/server.ts +217 -0
- package/src/nextjs/index.ts +23 -0
- package/src/nextjs/nextjs.test.ts +233 -0
- package/src/nextjs/pages.ts +43 -0
- package/src/nextjs/react.ts +100 -0
- package/src/nextjs/router.ts +102 -0
- package/src/nextjs/routes.ts +69 -0
- package/src/opencode/index.test.ts +90 -0
- package/src/opencode/index.ts +83 -0
- package/src/parser/index.ts +339 -0
- package/src/parser/parser.test.ts +282 -0
- package/src/plan/index.test.ts +162 -0
- package/src/plan/index.ts +161 -0
- package/src/report/index.ts +128 -0
- package/src/scanner/index.ts +97 -0
- package/src/scanner/scanner.test.ts +135 -0
- package/src/search/index.ts +163 -0
- package/src/search/search.test.ts +512 -0
- package/src/traversal/index.ts +5 -0
- package/src/traversal/traversal.test.ts +266 -0
- package/src/traversal/traversal.ts +185 -0
- package/tsconfig.json +20 -0
- package/vitest.config.ts +7 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import { z } from "zod/v4";
|
|
6
|
+
import { deserialize } from "../graph/types.js";
|
|
7
|
+
import { findCallers, findCallees, findNode, querySymbols, findImports, findPublic, context } from "../search/index.js";
|
|
8
|
+
import { impact, findPath, findOrphans, trace } from "../traversal/index.js";
|
|
9
|
+
import { analyzeComplexity, findHotspots, analyzeCoupling } from "../analysis/index.js";
|
|
10
|
+
function loadGraph(rootDir) {
|
|
11
|
+
const graphPath = path.join(rootDir, ".tsgraph", "graph.json");
|
|
12
|
+
const raw = fs.readFileSync(graphPath, "utf-8");
|
|
13
|
+
return deserialize(raw);
|
|
14
|
+
}
|
|
15
|
+
function text(text) {
|
|
16
|
+
return { content: [{ type: "text", text }] };
|
|
17
|
+
}
|
|
18
|
+
function error(msg) {
|
|
19
|
+
return { content: [{ type: "text", text: msg }], isError: true };
|
|
20
|
+
}
|
|
21
|
+
function withGraph(rootDir, fn) {
|
|
22
|
+
try {
|
|
23
|
+
const graph = loadGraph(rootDir);
|
|
24
|
+
return fn(graph);
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
throw new Error(`Failed to load graph: ${err.message}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export async function startMcpServer(rootDir) {
|
|
31
|
+
const server = new McpServer({
|
|
32
|
+
name: "tsgraph",
|
|
33
|
+
version: "0.1.0",
|
|
34
|
+
});
|
|
35
|
+
server.resource("graph.json", `file://${path.join(rootDir, ".tsgraph", "graph.json")}`, { mimeType: "application/json" }, async (uri) => ({
|
|
36
|
+
contents: [{
|
|
37
|
+
uri: uri.href,
|
|
38
|
+
mimeType: "application/json",
|
|
39
|
+
text: fs.readFileSync(new URL(uri.href), "utf-8"),
|
|
40
|
+
}],
|
|
41
|
+
}));
|
|
42
|
+
server.registerTool("callers", {
|
|
43
|
+
description: "Find which functions call a given symbol",
|
|
44
|
+
inputSchema: z.object({ symbol: z.string() }),
|
|
45
|
+
}, async ({ symbol }) => {
|
|
46
|
+
try {
|
|
47
|
+
return text(JSON.stringify(withGraph(rootDir, (g) => findCallers(g, symbol)), null, 2));
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
return error(err.message);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
server.registerTool("callees", {
|
|
54
|
+
description: "Find which functions a given symbol calls",
|
|
55
|
+
inputSchema: z.object({ symbol: z.string() }),
|
|
56
|
+
}, async ({ symbol }) => {
|
|
57
|
+
try {
|
|
58
|
+
return text(JSON.stringify(withGraph(rootDir, (g) => findCallees(g, symbol)), null, 2));
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
return error(err.message);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
server.registerTool("node", {
|
|
65
|
+
description: "Get detailed information about a symbol",
|
|
66
|
+
inputSchema: z.object({ symbol: z.string() }),
|
|
67
|
+
}, async ({ symbol }) => {
|
|
68
|
+
try {
|
|
69
|
+
return text(JSON.stringify(withGraph(rootDir, (g) => findNode(g, symbol)), null, 2));
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
return error(err.message);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
server.registerTool("query", {
|
|
76
|
+
description: "Search for symbols matching a pattern",
|
|
77
|
+
inputSchema: z.object({ pattern: z.string() }),
|
|
78
|
+
}, async ({ pattern }) => {
|
|
79
|
+
try {
|
|
80
|
+
return text(JSON.stringify(withGraph(rootDir, (g) => querySymbols(g, pattern)), null, 2));
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
return error(err.message);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
server.registerTool("context", {
|
|
87
|
+
description: "Bundle node, source, callers, and callees for a symbol",
|
|
88
|
+
inputSchema: z.object({ symbol: z.string() }),
|
|
89
|
+
}, async ({ symbol }) => {
|
|
90
|
+
try {
|
|
91
|
+
return text(JSON.stringify(withGraph(rootDir, (g) => context(g, symbol)), null, 2));
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
return error(err.message);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
server.registerTool("imports", {
|
|
98
|
+
description: "Find all files importing a specific package path",
|
|
99
|
+
inputSchema: z.object({ path: z.string() }),
|
|
100
|
+
}, async ({ path: importPath }) => {
|
|
101
|
+
try {
|
|
102
|
+
return text(JSON.stringify(withGraph(rootDir, (g) => findImports(g, importPath)), null, 2));
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
return error(err.message);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
server.registerTool("public", {
|
|
109
|
+
description: "List exported symbols, optionally scoped to a package",
|
|
110
|
+
inputSchema: z.object({ package: z.string().optional() }),
|
|
111
|
+
}, async ({ package: pkg }) => {
|
|
112
|
+
try {
|
|
113
|
+
return text(JSON.stringify(withGraph(rootDir, (g) => findPublic(g, pkg)), null, 2));
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
return error(err.message);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
server.registerTool("impact", {
|
|
120
|
+
description: "Show downstream blast radius (callers recursively)",
|
|
121
|
+
inputSchema: z.object({ symbol: z.string(), depth: z.number().optional() }),
|
|
122
|
+
}, async ({ symbol, depth }) => {
|
|
123
|
+
try {
|
|
124
|
+
return text(JSON.stringify(withGraph(rootDir, (g) => impact(g, symbol, depth)), null, 2));
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
return error(err.message);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
server.registerTool("path", {
|
|
131
|
+
description: "Find shortest call path between two symbols",
|
|
132
|
+
inputSchema: z.object({ from: z.string(), to: z.string(), depth: z.number().optional() }),
|
|
133
|
+
}, async ({ from, to, depth }) => {
|
|
134
|
+
try {
|
|
135
|
+
return text(JSON.stringify(withGraph(rootDir, (g) => findPath(g, from, to, depth)), null, 2));
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
return error(err.message);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
server.registerTool("orphans", {
|
|
142
|
+
description: "Find dead code — symbols with no callers or tests",
|
|
143
|
+
inputSchema: z.object({}),
|
|
144
|
+
}, async () => {
|
|
145
|
+
try {
|
|
146
|
+
return text(JSON.stringify(withGraph(rootDir, (g) => findOrphans(g)), null, 2));
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
return error(err.message);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
server.registerTool("trace", {
|
|
153
|
+
description: "Find a string literal across symbols and trace callers upstream",
|
|
154
|
+
inputSchema: z.object({ string: z.string(), depth: z.number().optional() }),
|
|
155
|
+
}, async ({ string: searchStr, depth }) => {
|
|
156
|
+
try {
|
|
157
|
+
return text(JSON.stringify(withGraph(rootDir, (g) => trace(g, searchStr, depth)), null, 2));
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
return error(err.message);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
server.registerTool("complexity", {
|
|
164
|
+
description: "Show cyclomatic complexity for functions and methods",
|
|
165
|
+
inputSchema: z.object({ file: z.string().optional(), sort: z.boolean().optional(), min: z.number().optional() }),
|
|
166
|
+
}, async ({ file, sort, min }) => {
|
|
167
|
+
try {
|
|
168
|
+
const graph = loadGraph(rootDir);
|
|
169
|
+
let results = analyzeComplexity(graph, file);
|
|
170
|
+
if (min)
|
|
171
|
+
results = results.filter((r) => r.complexity >= min);
|
|
172
|
+
if (sort)
|
|
173
|
+
results.sort((a, b) => b.complexity - a.complexity);
|
|
174
|
+
return text(JSON.stringify(results, null, 2));
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
return error(err.message);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
server.registerTool("hotspot", {
|
|
181
|
+
description: "Rank files by complexity × size (hotness score)",
|
|
182
|
+
inputSchema: z.object({ top: z.number().optional() }),
|
|
183
|
+
}, async ({ top }) => {
|
|
184
|
+
try {
|
|
185
|
+
return text(JSON.stringify(withGraph(rootDir, (g) => findHotspots(g, top)), null, 2));
|
|
186
|
+
}
|
|
187
|
+
catch (err) {
|
|
188
|
+
return error(err.message);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
server.registerTool("coupling", {
|
|
192
|
+
description: "Show package coupling based on import edges",
|
|
193
|
+
inputSchema: z.object({ package: z.string().optional() }),
|
|
194
|
+
}, async ({ package: pkg }) => {
|
|
195
|
+
try {
|
|
196
|
+
const graph = loadGraph(rootDir);
|
|
197
|
+
let results = analyzeCoupling(graph);
|
|
198
|
+
if (pkg)
|
|
199
|
+
results = results.filter((r) => r.packageName === pkg);
|
|
200
|
+
return text(JSON.stringify(results, null, 2));
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
return error(err.message);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
const transport = new StdioServerTransport();
|
|
207
|
+
await server.connect(transport);
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Graph } from "../graph/types.js";
|
|
2
|
+
import type { ScannedFile } from "../scanner/index.js";
|
|
3
|
+
export { extractAppRouter } from "./router.js";
|
|
4
|
+
export { extractPagesRouter } from "./pages.js";
|
|
5
|
+
export { classifyReactComponents } from "./react.js";
|
|
6
|
+
export { extractAPIRoutes } from "./routes.js";
|
|
7
|
+
export declare function extractNextJs(graph: Graph, rootDir: string, scanned: ScannedFile[]): Graph;
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nextjs/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAMvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,wBAAgB,aAAa,CAC3B,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,WAAW,EAAE,GACrB,KAAK,CAMP"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { extractAppRouter } from "./router.js";
|
|
2
|
+
import { extractPagesRouter } from "./pages.js";
|
|
3
|
+
import { classifyReactComponents } from "./react.js";
|
|
4
|
+
import { extractAPIRoutes } from "./routes.js";
|
|
5
|
+
export { extractAppRouter } from "./router.js";
|
|
6
|
+
export { extractPagesRouter } from "./pages.js";
|
|
7
|
+
export { classifyReactComponents } from "./react.js";
|
|
8
|
+
export { extractAPIRoutes } from "./routes.js";
|
|
9
|
+
export function extractNextJs(graph, rootDir, scanned) {
|
|
10
|
+
let g = extractAppRouter(graph, scanned);
|
|
11
|
+
g = extractPagesRouter(g, scanned);
|
|
12
|
+
g = classifyReactComponents(g, rootDir);
|
|
13
|
+
g = extractAPIRoutes(g, scanned, rootDir);
|
|
14
|
+
return g;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/nextjs/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,UAAU,aAAa,CAC3B,KAAY,EACZ,OAAe,EACf,OAAsB;IAEtB,IAAI,CAAC,GAAG,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC,GAAG,kBAAkB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC,GAAG,uBAAuB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC,GAAG,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextjs.test.d.ts","sourceRoot":"","sources":["../../src/nextjs/nextjs.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,190 @@
|
|
|
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 { scanFiles } from "../scanner/index.js";
|
|
6
|
+
import { parseProject } from "../parser/index.js";
|
|
7
|
+
import { extractAppRouter } from "./router.js";
|
|
8
|
+
import { extractPagesRouter } from "./pages.js";
|
|
9
|
+
import { extractAPIRoutes } from "./routes.js";
|
|
10
|
+
import { makeGraph, makeFileNode } from "../graph/types.js";
|
|
11
|
+
function createTempDir() {
|
|
12
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), "tsgraph-test-"));
|
|
13
|
+
}
|
|
14
|
+
function writeFile(dir, relativePath, content) {
|
|
15
|
+
const fullPath = path.join(dir, relativePath);
|
|
16
|
+
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
17
|
+
fs.writeFileSync(fullPath, content, "utf-8");
|
|
18
|
+
}
|
|
19
|
+
describe("extractAppRouter", () => {
|
|
20
|
+
it("builds tree with page, layout, loading", () => {
|
|
21
|
+
const dir = createTempDir();
|
|
22
|
+
writeFile(dir, "app/page.tsx", "export default function Home() {}");
|
|
23
|
+
writeFile(dir, "app/layout.tsx", "export default function RootLayout() {}");
|
|
24
|
+
writeFile(dir, "app/loading.tsx", "export default function Loading() {}");
|
|
25
|
+
const { files } = scanFiles(dir);
|
|
26
|
+
const graph = makeGraph({ root: dir, files: files.map((f) => makeFileNode({ path: f.relativePath })) });
|
|
27
|
+
const result = extractAppRouter(graph, files);
|
|
28
|
+
expect(result.appRouter).toBeTruthy();
|
|
29
|
+
expect(result.appRouter.path).toBe("/");
|
|
30
|
+
expect(result.appRouter.files.page).toMatch(/app\/page\.tsx$/);
|
|
31
|
+
expect(result.appRouter.files.layout).toMatch(/app\/layout\.tsx$/);
|
|
32
|
+
expect(result.appRouter.files.loading).toMatch(/app\/loading\.tsx$/);
|
|
33
|
+
expect(result.appRouter.files.error).toBeUndefined();
|
|
34
|
+
fs.rmSync(dir, { recursive: true });
|
|
35
|
+
});
|
|
36
|
+
it("detects nested route segments", () => {
|
|
37
|
+
const dir = createTempDir();
|
|
38
|
+
writeFile(dir, "app/layout.tsx", "export default function Root() {}");
|
|
39
|
+
writeFile(dir, "app/dashboard/page.tsx", "export default function Dashboard() {}");
|
|
40
|
+
writeFile(dir, "app/dashboard/layout.tsx", "export default function DashLayout() {}");
|
|
41
|
+
writeFile(dir, "app/dashboard/settings/page.tsx", "export default function Settings() {}");
|
|
42
|
+
const { files } = scanFiles(dir);
|
|
43
|
+
const graph = makeGraph({ root: dir, files: files.map((f) => makeFileNode({ path: f.relativePath })) });
|
|
44
|
+
const result = extractAppRouter(graph, files);
|
|
45
|
+
expect(result.appRouter).toBeTruthy();
|
|
46
|
+
expect(result.appRouter.children).toHaveLength(1);
|
|
47
|
+
expect(result.appRouter.children[0].path).toBe("/dashboard");
|
|
48
|
+
expect(result.appRouter.children[0].files.page).toMatch(/dashboard\/page\.tsx$/);
|
|
49
|
+
expect(result.appRouter.children[0].children).toHaveLength(1);
|
|
50
|
+
expect(result.appRouter.children[0].children[0].path).toBe("/dashboard/settings");
|
|
51
|
+
fs.rmSync(dir, { recursive: true });
|
|
52
|
+
});
|
|
53
|
+
it("returns undefined when no app directory", () => {
|
|
54
|
+
const dir = createTempDir();
|
|
55
|
+
writeFile(dir, "src/index.ts", "const x = 1;");
|
|
56
|
+
const { files } = scanFiles(dir);
|
|
57
|
+
const graph = makeGraph({ root: dir });
|
|
58
|
+
const result = extractAppRouter(graph, files);
|
|
59
|
+
expect(result.appRouter).toBeUndefined();
|
|
60
|
+
fs.rmSync(dir, { recursive: true });
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe("extractPagesRouter", () => {
|
|
64
|
+
it("detects index and nested pages", () => {
|
|
65
|
+
const dir = createTempDir();
|
|
66
|
+
writeFile(dir, "pages/index.tsx", "export default function Home() {}");
|
|
67
|
+
writeFile(dir, "pages/about.tsx", "export default function About() {}");
|
|
68
|
+
writeFile(dir, "pages/blog/[slug].tsx", "export default function Post() {}");
|
|
69
|
+
const { files } = scanFiles(dir);
|
|
70
|
+
const graph = makeGraph({ root: dir });
|
|
71
|
+
const result = extractPagesRouter(graph, files);
|
|
72
|
+
expect(result.routes).toHaveLength(3);
|
|
73
|
+
const paths = result.routes.map((r) => r.path).sort();
|
|
74
|
+
expect(paths).toEqual(["/", "/about", "/blog/:slug"]);
|
|
75
|
+
expect(result.routes[0].method).toBe("GET");
|
|
76
|
+
fs.rmSync(dir, { recursive: true });
|
|
77
|
+
});
|
|
78
|
+
it("ignores non-page files", () => {
|
|
79
|
+
const dir = createTempDir();
|
|
80
|
+
writeFile(dir, "pages/api/users.ts", "export default function handler() {}");
|
|
81
|
+
writeFile(dir, "pages/_app.tsx", "export default function App() {}");
|
|
82
|
+
writeFile(dir, "pages/_document.tsx", "");
|
|
83
|
+
const { files } = scanFiles(dir);
|
|
84
|
+
const graph = makeGraph({ root: dir });
|
|
85
|
+
const result = extractPagesRouter(graph, files);
|
|
86
|
+
const paths = result.routes.map((r) => r.path);
|
|
87
|
+
expect(paths).toContain("/api/users");
|
|
88
|
+
fs.rmSync(dir, { recursive: true });
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe("classifyReactComponents", () => {
|
|
92
|
+
it("sets isClientComponent from 'use client' directive", () => {
|
|
93
|
+
const dir = createTempDir();
|
|
94
|
+
writeFile(dir, "component.tsx", `"use client";
|
|
95
|
+
export function Button() { return null; }`);
|
|
96
|
+
const { files } = scanFiles(dir);
|
|
97
|
+
const graph = parseProject(dir, files);
|
|
98
|
+
const button = graph.symbols.find((s) => s.name === "Button");
|
|
99
|
+
expect(button).toBeTruthy();
|
|
100
|
+
expect(button.isClientComponent).toBe(true);
|
|
101
|
+
fs.rmSync(dir, { recursive: true });
|
|
102
|
+
});
|
|
103
|
+
it("sets isServerComponent from 'use server' directive", () => {
|
|
104
|
+
const dir = createTempDir();
|
|
105
|
+
writeFile(dir, "action.ts", `"use server";
|
|
106
|
+
export async function submit() { return null; }`);
|
|
107
|
+
const { files } = scanFiles(dir);
|
|
108
|
+
const graph = parseProject(dir, files);
|
|
109
|
+
const submit = graph.symbols.find((s) => s.name === "submit");
|
|
110
|
+
expect(submit).toBeTruthy();
|
|
111
|
+
expect(submit.isServerComponent).toBe(true);
|
|
112
|
+
fs.rmSync(dir, { recursive: true });
|
|
113
|
+
});
|
|
114
|
+
it("detects hooks in tsx functions", () => {
|
|
115
|
+
const dir = createTempDir();
|
|
116
|
+
writeFile(dir, "counter.tsx", `
|
|
117
|
+
import { useState } from "react";
|
|
118
|
+
export function Counter() {
|
|
119
|
+
const [count, setCount] = useState(0);
|
|
120
|
+
return null;
|
|
121
|
+
}`);
|
|
122
|
+
const { files } = scanFiles(dir);
|
|
123
|
+
const graph = parseProject(dir, files);
|
|
124
|
+
const counter = graph.symbols.find((s) => s.name === "Counter");
|
|
125
|
+
expect(counter).toBeTruthy();
|
|
126
|
+
expect(counter.isClientComponent).toBe(true);
|
|
127
|
+
fs.rmSync(dir, { recursive: true });
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
describe("extractAPIRoutes", () => {
|
|
131
|
+
it("extracts HTTP methods from route.ts", () => {
|
|
132
|
+
const dir = createTempDir();
|
|
133
|
+
writeFile(dir, "app/api/users/route.ts", `
|
|
134
|
+
export async function GET() { return Response.json({}); }
|
|
135
|
+
export async function POST(req: Request) { return Response.json({}); }
|
|
136
|
+
`);
|
|
137
|
+
const { files } = scanFiles(dir);
|
|
138
|
+
const graph = makeGraph({ root: dir });
|
|
139
|
+
const result = extractAPIRoutes(graph, files, dir);
|
|
140
|
+
const routes = result.routes.sort((a, b) => a.method.localeCompare(b.method));
|
|
141
|
+
expect(routes).toHaveLength(2);
|
|
142
|
+
expect(routes[0].method).toBe("GET");
|
|
143
|
+
expect(routes[0].path).toBe("/api/users");
|
|
144
|
+
expect(routes[1].method).toBe("POST");
|
|
145
|
+
expect(routes[1].path).toBe("/api/users");
|
|
146
|
+
fs.rmSync(dir, { recursive: true });
|
|
147
|
+
});
|
|
148
|
+
it("handles dynamic route params", () => {
|
|
149
|
+
const dir = createTempDir();
|
|
150
|
+
writeFile(dir, "app/api/items/[id]/route.ts", `
|
|
151
|
+
export async function GET(req: Request, { params }: { params: { id: string } }) {
|
|
152
|
+
return Response.json({});
|
|
153
|
+
}
|
|
154
|
+
`);
|
|
155
|
+
const { files } = scanFiles(dir);
|
|
156
|
+
const graph = makeGraph({ root: dir });
|
|
157
|
+
const result = extractAPIRoutes(graph, files, dir);
|
|
158
|
+
expect(result.routes).toHaveLength(1);
|
|
159
|
+
expect(result.routes[0].path).toBe("/api/items/:id");
|
|
160
|
+
fs.rmSync(dir, { recursive: true });
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
describe("end-to-end: parseProject with Next.js", () => {
|
|
164
|
+
it("produces appRouter and routes from a Next.js project", () => {
|
|
165
|
+
const dir = createTempDir();
|
|
166
|
+
writeFile(dir, "package.json", JSON.stringify({ name: "my-app", dependencies: { "next": "^14" } }));
|
|
167
|
+
writeFile(dir, "app/layout.tsx", "export default function Root({ children }: { children: React.ReactNode }) { return null; }");
|
|
168
|
+
writeFile(dir, "app/page.tsx", `"use client";
|
|
169
|
+
import { useState } from "react";
|
|
170
|
+
export default function Home() {
|
|
171
|
+
const [count, setCount] = useState(0);
|
|
172
|
+
return null;
|
|
173
|
+
}`);
|
|
174
|
+
writeFile(dir, "app/api/hello/route.ts", "export async function GET() { return Response.json({}); }");
|
|
175
|
+
writeFile(dir, "pages/about.tsx", "export default function About() { return null; }");
|
|
176
|
+
const { files } = scanFiles(dir);
|
|
177
|
+
const graph = parseProject(dir, files);
|
|
178
|
+
expect(graph.appRouter).toBeTruthy();
|
|
179
|
+
expect(graph.appRouter.files.layout).toBeTruthy();
|
|
180
|
+
expect(graph.appRouter.files.page).toBeTruthy();
|
|
181
|
+
const home = graph.symbols.find((s) => s.name === "Home");
|
|
182
|
+
expect(home).toBeTruthy();
|
|
183
|
+
expect(home.isClientComponent).toBe(true);
|
|
184
|
+
const routePaths = graph.routes.map((r) => r.path);
|
|
185
|
+
expect(routePaths).toContain("/api/hello");
|
|
186
|
+
expect(routePaths).toContain("/about");
|
|
187
|
+
fs.rmSync(dir, { recursive: true });
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
//# sourceMappingURL=nextjs.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextjs.test.js","sourceRoot":"","sources":["../../src/nextjs/nextjs.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../src/nextjs/pages.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAa,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAcvD,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,WAAW,EAAE,GACrB,KAAK,CAuBP"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
function pagePathToRoute(relativePath) {
|
|
3
|
+
let p = relativePath
|
|
4
|
+
.replace(/^pages[/\\]/, "")
|
|
5
|
+
.replace(/\.[jt]sx?$/, "")
|
|
6
|
+
.replace(/index$/, "")
|
|
7
|
+
.replace(/\[\.\.\.(.+?)\]/, "*$1")
|
|
8
|
+
.replace(/\[(.+?)\]/g, ":$1");
|
|
9
|
+
if (!p.startsWith("/"))
|
|
10
|
+
p = "/" + p;
|
|
11
|
+
return p === "/" ? "/" : p.replace(/\/$/, "");
|
|
12
|
+
}
|
|
13
|
+
export function extractPagesRouter(graph, scanned) {
|
|
14
|
+
const newRoutes = [...graph.routes];
|
|
15
|
+
for (const sf of scanned) {
|
|
16
|
+
const rel = sf.relativePath;
|
|
17
|
+
if (!rel.startsWith("pages/") && !rel.startsWith("pages\\"))
|
|
18
|
+
continue;
|
|
19
|
+
const ext = path.extname(rel);
|
|
20
|
+
if (ext !== ".ts" && ext !== ".tsx" && ext !== ".js" && ext !== ".jsx")
|
|
21
|
+
continue;
|
|
22
|
+
const route = pagePathToRoute(rel);
|
|
23
|
+
if (!route)
|
|
24
|
+
continue;
|
|
25
|
+
const isApi = route.startsWith("/api");
|
|
26
|
+
newRoutes.push({
|
|
27
|
+
method: "GET",
|
|
28
|
+
path: route,
|
|
29
|
+
handler: isApi ? `pages${route}` : rel,
|
|
30
|
+
file: rel,
|
|
31
|
+
line: 1,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return { ...graph, routes: newRoutes };
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=pages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pages.js","sourceRoot":"","sources":["../../src/nextjs/pages.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,SAAS,eAAe,CAAC,YAAoB;IAC3C,IAAI,CAAC,GAAG,YAAY;SACjB,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;SAC1B,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC;SACzB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;SACrB,OAAO,CAAC,iBAAiB,EAAE,KAAK,CAAC;SACjC,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IAEhC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;IACpC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,KAAY,EACZ,OAAsB;IAEtB,MAAM,SAAS,GAAgB,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAEjD,KAAK,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC;QAC5B,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,SAAS;QACtE,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM;YAAE,SAAS;QAEjF,MAAM,KAAK,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACvC,SAAS,CAAC,IAAI,CAAC;YACb,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,KAAK;YACX,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG;YACtC,IAAI,EAAE,GAAG;YACT,IAAI,EAAE,CAAC;SACR,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/nextjs/react.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAc,MAAM,mBAAmB,CAAC;AA4D3D,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,MAAM,GACd,KAAK,CAkCP"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const REACT_HOOKS = new Set([
|
|
4
|
+
"useState", "useEffect", "useContext", "useReducer", "useCallback",
|
|
5
|
+
"useMemo", "useRef", "useImperativeHandle", "useLayoutEffect",
|
|
6
|
+
"useDebugValue", "useTransition", "useDeferredValue", "useId",
|
|
7
|
+
"useSyncExternalStore", "useInsertionEffect", "useActionState",
|
|
8
|
+
"useOptimistic",
|
|
9
|
+
]);
|
|
10
|
+
function getDirectives(filePath) {
|
|
11
|
+
try {
|
|
12
|
+
const fd = fs.openSync(filePath, "r");
|
|
13
|
+
const buffer = Buffer.alloc(512);
|
|
14
|
+
const bytesRead = fs.readSync(fd, buffer, 0, 512, 0);
|
|
15
|
+
fs.closeSync(fd);
|
|
16
|
+
const head = buffer.toString("utf-8", 0, bytesRead);
|
|
17
|
+
const lines = head.split("\n").slice(0, 5);
|
|
18
|
+
const trimmed = lines.map((l) => l.trim().replace(/;$/, ""));
|
|
19
|
+
return {
|
|
20
|
+
isClient: trimmed.some((l) => l === `"use client"` || l === `'use client'`),
|
|
21
|
+
isServer: trimmed.some((l) => l === `"use server"` || l === `'use server'`),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return { isClient: false, isServer: false };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function checkHookUsage(filePath, symbols) {
|
|
29
|
+
const updated = [];
|
|
30
|
+
try {
|
|
31
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
32
|
+
for (const sym of symbols) {
|
|
33
|
+
const lines = content.split("\n");
|
|
34
|
+
const snippet = lines.slice(sym.line - 1, sym.endLine).join("\n");
|
|
35
|
+
const usesHooks = [...REACT_HOOKS].some((hook) => {
|
|
36
|
+
const idx = snippet.indexOf(hook);
|
|
37
|
+
if (idx === -1)
|
|
38
|
+
return false;
|
|
39
|
+
const before = snippet[idx - 1];
|
|
40
|
+
if (before && (before === "." || /[a-zA-Z0-9]/.test(before)))
|
|
41
|
+
return false;
|
|
42
|
+
return true;
|
|
43
|
+
});
|
|
44
|
+
if (usesHooks) {
|
|
45
|
+
updated.push({ ...sym, isClientComponent: true });
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
updated.push(sym);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return symbols;
|
|
54
|
+
}
|
|
55
|
+
return updated;
|
|
56
|
+
}
|
|
57
|
+
export function classifyReactComponents(graph, rootDir) {
|
|
58
|
+
const symByFile = new Map();
|
|
59
|
+
for (const sym of graph.symbols) {
|
|
60
|
+
const list = symByFile.get(sym.file) ?? [];
|
|
61
|
+
list.push(sym);
|
|
62
|
+
symByFile.set(sym.file, list);
|
|
63
|
+
}
|
|
64
|
+
const updatedSymbols = [];
|
|
65
|
+
for (const [fileRel, symbols] of symByFile) {
|
|
66
|
+
const filePath = path.join(rootDir, fileRel);
|
|
67
|
+
const { isClient, isServer } = getDirectives(filePath);
|
|
68
|
+
if (isClient || isServer) {
|
|
69
|
+
updatedSymbols.push(...symbols.map((s) => ({
|
|
70
|
+
...s,
|
|
71
|
+
isClientComponent: isClient || s.isClientComponent,
|
|
72
|
+
isServerComponent: isServer || s.isServerComponent,
|
|
73
|
+
})));
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (fileRel.endsWith(".tsx")) {
|
|
77
|
+
const checked = checkHookUsage(filePath, symbols);
|
|
78
|
+
updatedSymbols.push(...checked);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
updatedSymbols.push(...symbols);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return { ...graph, symbols: updatedSymbols };
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.js","sourceRoot":"","sources":["../../src/nextjs/react.ts"],"names":[],"mappings":"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"}
|