codesight 1.1.1 → 1.3.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 +114 -31
- package/dist/ast/extract-components.d.ts +12 -0
- package/dist/ast/extract-components.js +180 -0
- package/dist/ast/extract-routes.d.ts +13 -0
- package/dist/ast/extract-routes.js +271 -0
- package/dist/ast/extract-schema.d.ts +15 -0
- package/dist/ast/extract-schema.js +302 -0
- package/dist/ast/loader.d.ts +20 -0
- package/dist/ast/loader.js +105 -0
- package/dist/detectors/blast-radius.d.ts +11 -0
- package/dist/detectors/blast-radius.js +102 -0
- package/dist/detectors/components.js +11 -0
- package/dist/detectors/routes.js +91 -15
- package/dist/detectors/schema.js +20 -0
- package/dist/generators/ai-config.d.ts +5 -0
- package/dist/generators/ai-config.js +97 -0
- package/dist/index.js +60 -2
- package/dist/mcp-server.js +288 -30
- package/dist/types.d.ts +21 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
### Your AI assistant wastes thousands of tokens every conversation just figuring out your project. codesight fixes that in one command.
|
|
4
4
|
|
|
5
|
-
**Zero dependencies. 25+ framework detectors.
|
|
5
|
+
**Zero dependencies. AST precision. 25+ framework detectors. 8 ORM parsers. 8 MCP tools. Blast radius analysis. One `npx` call.**
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/codesight)
|
|
8
8
|
[](https://www.npmjs.com/package/codesight)
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
---
|
|
27
27
|
|
|
28
28
|
```
|
|
29
|
-
0 dependencies · Node.js >= 18 · 27 tests · MIT
|
|
29
|
+
0 dependencies · Node.js >= 18 · 27 tests · 8 MCP tools · MIT
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
## Works With
|
|
@@ -42,10 +42,12 @@ npx codesight
|
|
|
42
42
|
That's it. Run it in any project root. No config, no setup, no API keys.
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
|
-
npx codesight --init
|
|
46
|
-
npx codesight --open
|
|
47
|
-
npx codesight --mcp
|
|
48
|
-
npx codesight --
|
|
45
|
+
npx codesight --init # Generate CLAUDE.md, .cursorrules, codex.md, AGENTS.md
|
|
46
|
+
npx codesight --open # Open interactive HTML report in browser
|
|
47
|
+
npx codesight --mcp # Start as MCP server (8 tools) for Claude Code / Cursor
|
|
48
|
+
npx codesight --blast src/lib/db.ts # Show blast radius for a file
|
|
49
|
+
npx codesight --profile claude-code # Generate optimized config for a specific AI tool
|
|
50
|
+
npx codesight --benchmark # Show detailed token savings breakdown
|
|
49
51
|
```
|
|
50
52
|
|
|
51
53
|
## What It Does
|
|
@@ -54,6 +56,8 @@ Every AI coding conversation starts the same way. Your assistant reads files, gr
|
|
|
54
56
|
|
|
55
57
|
codesight scans your codebase once and generates a structured context map. Routes, database schema, components, dependencies, environment variables, middleware, all condensed into ~3,000 to 5,000 tokens of structured markdown. Your AI reads one file and knows the entire project.
|
|
56
58
|
|
|
59
|
+
**v1.3.0: AST-level precision.** When TypeScript is available in your project, codesight uses the TypeScript compiler API for structural parsing instead of regex. This gives exact route paths, proper controller prefix combining (NestJS), accurate tRPC procedure nesting, precise Drizzle field types, and React prop extraction from type annotations. Zero new dependencies — borrows TypeScript from your project's node_modules. Falls back to regex when TypeScript is not available.
|
|
60
|
+
|
|
57
61
|
```
|
|
58
62
|
Output size: ~3,200 tokens
|
|
59
63
|
Exploration cost: ~52,000 tokens (without codesight)
|
|
@@ -75,6 +79,27 @@ Saved: ~48,800 tokens per conversation
|
|
|
75
79
|
report.html Interactive visual dashboard (with --html or --open)
|
|
76
80
|
```
|
|
77
81
|
|
|
82
|
+
## AST Precision
|
|
83
|
+
|
|
84
|
+
When TypeScript is installed in the project being scanned, codesight uses the actual TypeScript compiler API to parse your code structurally. No regex guessing.
|
|
85
|
+
|
|
86
|
+
| What AST enables | Regex alone |
|
|
87
|
+
|---|---|
|
|
88
|
+
| Follows `router.use('/prefix', subRouter)` chains | Misses nested routers |
|
|
89
|
+
| Combines `@Controller('users')` + `@Get(':id')` into `/users/:id` | May miss prefix |
|
|
90
|
+
| Parses `router({ users: userRouter })` tRPC nesting | Line-by-line matching |
|
|
91
|
+
| Extracts exact Drizzle field types from `.primaryKey().notNull()` chains | Pattern matching |
|
|
92
|
+
| Gets React props from TypeScript interfaces and destructuring | Regex on `{ prop }` |
|
|
93
|
+
| Detects middleware in route chains: `app.get('/path', auth, handler)` | Not captured |
|
|
94
|
+
|
|
95
|
+
AST detection is indicated in the output:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
Analyzing... done (AST: 65 routes, 18 models, 16 components)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
No configuration needed. If TypeScript is in your `node_modules`, AST kicks in automatically. Works with npm, yarn, and pnpm (including strict mode). Falls back to regex for non-TypeScript projects or frameworks without AST support.
|
|
102
|
+
|
|
78
103
|
## Routes
|
|
79
104
|
|
|
80
105
|
Not just paths. Methods, URL parameters, what each route touches (auth, database, cache, payments, AI, email, queues), and where the handler lives. Detects routes across 25+ frameworks automatically.
|
|
@@ -117,6 +142,35 @@ The files imported the most are the ones that break the most things when changed
|
|
|
117
142
|
- `apps/api/src/lib/auth.ts` — imported by **7** files
|
|
118
143
|
```
|
|
119
144
|
|
|
145
|
+
## Blast Radius
|
|
146
|
+
|
|
147
|
+
See exactly what breaks if you change a file. BFS through the import graph finds all transitively affected files, routes, models, and middleware.
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
npx codesight --blast src/lib/db.ts
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
Blast Radius: src/lib/db.ts
|
|
155
|
+
Depth: 3 hops
|
|
156
|
+
|
|
157
|
+
Affected files (10):
|
|
158
|
+
src/routes/users.ts
|
|
159
|
+
src/routes/projects.ts
|
|
160
|
+
src/routes/billing.ts
|
|
161
|
+
...
|
|
162
|
+
|
|
163
|
+
Affected routes (33):
|
|
164
|
+
POST /auth/login — src/routes/auth.ts
|
|
165
|
+
GET /api/users — src/routes/users.ts
|
|
166
|
+
...
|
|
167
|
+
|
|
168
|
+
Affected models: users, projects, subscriptions
|
|
169
|
+
Affected middleware: authMiddleware
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Your AI can also query blast radius through the MCP server before making changes.
|
|
173
|
+
|
|
120
174
|
## Environment Audit
|
|
121
175
|
|
|
122
176
|
Every env var across your codebase, flagged as required or has default, with the exact file where it is referenced.
|
|
@@ -157,7 +211,7 @@ npx codesight --benchmark
|
|
|
157
211
|
| Category | Supported |
|
|
158
212
|
|---|---|
|
|
159
213
|
| **Routes** | Hono, Express, Fastify, Next.js (App + Pages), Koa, NestJS, tRPC, Elysia, AdonisJS, SvelteKit, Remix, Nuxt, FastAPI, Flask, Django, Go (net/http, Gin, Fiber, Echo, Chi), Rails, Phoenix, Spring Boot, Actix, Axum, raw http.createServer |
|
|
160
|
-
| **Schema** | Drizzle, Prisma, TypeORM, Mongoose, Sequelize, SQLAlchemy, ActiveRecord, Ecto |
|
|
214
|
+
| **Schema** | Drizzle, Prisma, TypeORM, Mongoose, Sequelize, SQLAlchemy, ActiveRecord, Ecto (8 ORMs) |
|
|
161
215
|
| **Components** | React, Vue, Svelte (auto-filters shadcn/ui and Radix primitives) |
|
|
162
216
|
| **Libraries** | TypeScript, JavaScript, Python, Go, Ruby, Elixir, Java, Kotlin, Rust (exports with function signatures) |
|
|
163
217
|
| **Middleware** | Auth, rate limiting, CORS, validation, logging, error handlers |
|
|
@@ -184,7 +238,7 @@ Generates ready-to-use instruction files for every major AI coding tool at once:
|
|
|
184
238
|
|
|
185
239
|
Each file is pre-filled with your project's stack, architecture, high-impact files, and required env vars. Your AI reads it on startup and starts with full context from the first message.
|
|
186
240
|
|
|
187
|
-
## MCP Server
|
|
241
|
+
## MCP Server (8 Tools)
|
|
188
242
|
|
|
189
243
|
```bash
|
|
190
244
|
npx codesight --mcp
|
|
@@ -203,7 +257,32 @@ Runs as a Model Context Protocol server. Claude Code and Cursor call it directly
|
|
|
203
257
|
}
|
|
204
258
|
```
|
|
205
259
|
|
|
206
|
-
Exposes
|
|
260
|
+
Exposes 8 specialized tools, each returning only what your AI needs:
|
|
261
|
+
|
|
262
|
+
| Tool | What it does |
|
|
263
|
+
|---|---|
|
|
264
|
+
| `codesight_scan` | Full project scan (~3K-5K tokens) |
|
|
265
|
+
| `codesight_get_summary` | Compact overview (~500 tokens) |
|
|
266
|
+
| `codesight_get_routes` | Routes filtered by prefix, tag, or method |
|
|
267
|
+
| `codesight_get_schema` | Schema filtered by model name |
|
|
268
|
+
| `codesight_get_blast_radius` | Impact analysis before changing a file |
|
|
269
|
+
| `codesight_get_env` | Environment variables (filter: required only) |
|
|
270
|
+
| `codesight_get_hot_files` | Most imported files with configurable limit |
|
|
271
|
+
| `codesight_refresh` | Force re-scan (results are cached per session) |
|
|
272
|
+
|
|
273
|
+
Your AI asks for exactly what it needs instead of loading the entire context map. Session caching means the first call scans, subsequent calls return instantly.
|
|
274
|
+
|
|
275
|
+
## AI Tool Profiles
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
npx codesight --profile claude-code
|
|
279
|
+
npx codesight --profile cursor
|
|
280
|
+
npx codesight --profile codex
|
|
281
|
+
npx codesight --profile copilot
|
|
282
|
+
npx codesight --profile windsurf
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Generates an optimized config file for a specific AI tool. Each profile includes your project summary, stack info, high-impact files, required env vars, and tool-specific instructions on how to use codesight outputs. For Claude Code, this includes MCP tool usage instructions. For Cursor, it points to the right codesight files. Each profile writes to the correct file for that tool.
|
|
207
286
|
|
|
208
287
|
## Visual Report
|
|
209
288
|
|
|
@@ -254,34 +333,38 @@ Context stays fresh without thinking about it.
|
|
|
254
333
|
## All Options
|
|
255
334
|
|
|
256
335
|
```bash
|
|
257
|
-
npx codesight
|
|
258
|
-
npx codesight ./my-project
|
|
259
|
-
npx codesight --init
|
|
260
|
-
npx codesight --open
|
|
261
|
-
npx codesight --html
|
|
262
|
-
npx codesight --mcp
|
|
263
|
-
npx codesight --
|
|
264
|
-
npx codesight --
|
|
265
|
-
npx codesight --
|
|
266
|
-
npx codesight --
|
|
267
|
-
npx codesight
|
|
268
|
-
npx codesight
|
|
336
|
+
npx codesight # Scan current directory
|
|
337
|
+
npx codesight ./my-project # Scan specific directory
|
|
338
|
+
npx codesight --init # Generate AI config files
|
|
339
|
+
npx codesight --open # Open visual HTML report
|
|
340
|
+
npx codesight --html # Generate HTML report without opening
|
|
341
|
+
npx codesight --mcp # Start MCP server (8 tools)
|
|
342
|
+
npx codesight --blast src/lib/db.ts # Show blast radius for a file
|
|
343
|
+
npx codesight --profile claude-code # Optimized config for specific tool
|
|
344
|
+
npx codesight --watch # Watch mode
|
|
345
|
+
npx codesight --hook # Install git pre-commit hook
|
|
346
|
+
npx codesight --benchmark # Detailed token savings breakdown
|
|
347
|
+
npx codesight --json # Output as JSON
|
|
348
|
+
npx codesight -o .ai-context # Custom output directory
|
|
349
|
+
npx codesight -d 5 # Limit directory depth
|
|
269
350
|
```
|
|
270
351
|
|
|
271
352
|
## How It Compares
|
|
272
353
|
|
|
273
354
|
Most AI context tools dump your entire codebase into one file. codesight takes a different approach: it **parses** your code to extract structured information.
|
|
274
355
|
|
|
275
|
-
| | codesight | File concatenation tools |
|
|
276
|
-
|
|
277
|
-
| **
|
|
278
|
-
| **
|
|
279
|
-
| **
|
|
280
|
-
| **
|
|
281
|
-
| **
|
|
282
|
-
| **
|
|
283
|
-
| **
|
|
284
|
-
| **
|
|
356
|
+
| | codesight | File concatenation tools | AST-based tools |
|
|
357
|
+
|---|---|---|---|
|
|
358
|
+
| **Parsing** | AST when available, regex fallback | None | Tree-sitter / custom |
|
|
359
|
+
| **Output** | Structured routes, schema, components, deps | Raw file contents | Call graphs, class diagrams |
|
|
360
|
+
| **Token cost** | ~3,000-5,000 tokens | 50,000-500,000+ tokens | Varies |
|
|
361
|
+
| **Route detection** | 25+ frameworks auto-detected | None | Limited |
|
|
362
|
+
| **Schema parsing** | 8 ORMs with relations | None | Varies |
|
|
363
|
+
| **Blast radius** | BFS through import graph | None | Some |
|
|
364
|
+
| **AI tool profiles** | 5 tools (Claude, Cursor, Codex, Copilot, Windsurf) | None | None |
|
|
365
|
+
| **MCP server** | 8 specialized tools with session caching | None | Some |
|
|
366
|
+
| **Setup** | `npx codesight` (zero deps, zero config) | Copy/paste | Install compilers, runtimes |
|
|
367
|
+
| **Dependencies** | Zero (borrows TS from your project) | Varies | Tree-sitter, SQLite, etc. |
|
|
285
368
|
|
|
286
369
|
## Contributing
|
|
287
370
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AST-based component extraction for React.
|
|
3
|
+
* Provides higher accuracy than regex for:
|
|
4
|
+
* - Component name detection from function/arrow function declarations
|
|
5
|
+
* - Prop extraction from destructured parameters and Props interface/type
|
|
6
|
+
* - Distinguishes client/server components via directive detection
|
|
7
|
+
*/
|
|
8
|
+
import type { ComponentInfo } from "../types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Extract React components from a file using AST.
|
|
11
|
+
*/
|
|
12
|
+
export declare function extractReactComponentsAST(ts: any, filePath: string, content: string, relPath: string): ComponentInfo[];
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { parseSourceFile, getText } from "./loader.js";
|
|
2
|
+
/**
|
|
3
|
+
* Extract React components from a file using AST.
|
|
4
|
+
*/
|
|
5
|
+
export function extractReactComponentsAST(ts, filePath, content, relPath) {
|
|
6
|
+
try {
|
|
7
|
+
const sf = parseSourceFile(ts, filePath, content);
|
|
8
|
+
return extractComponents(ts, sf, content, relPath);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function extractComponents(ts, sf, content, relPath) {
|
|
15
|
+
const components = [];
|
|
16
|
+
const SK = ts.SyntaxKind;
|
|
17
|
+
const isClient = content.slice(0, 80).includes("use client");
|
|
18
|
+
const isServer = content.slice(0, 80).includes("use server");
|
|
19
|
+
// Collect all Props interfaces/types in the file
|
|
20
|
+
const propsTypes = new Map(); // type name -> prop names
|
|
21
|
+
function collectPropsTypes(node) {
|
|
22
|
+
// interface FooProps { ... } or type FooProps = { ... }
|
|
23
|
+
if (node.kind === SK.InterfaceDeclaration || node.kind === SK.TypeAliasDeclaration) {
|
|
24
|
+
const name = node.name ? getText(sf, node.name) : "";
|
|
25
|
+
if (!name.includes("Props") && !name.includes("props")) {
|
|
26
|
+
ts.forEachChild(node, collectPropsTypes);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const props = [];
|
|
30
|
+
// For interfaces: node.members
|
|
31
|
+
if (node.members) {
|
|
32
|
+
for (const member of node.members) {
|
|
33
|
+
if (member.kind === SK.PropertySignature && member.name) {
|
|
34
|
+
const propName = getText(sf, member.name);
|
|
35
|
+
if (propName !== "children")
|
|
36
|
+
props.push(propName);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// For type aliases: node.type might be TypeLiteral
|
|
41
|
+
if (node.type?.kind === SK.TypeLiteral && node.type.members) {
|
|
42
|
+
for (const member of node.type.members) {
|
|
43
|
+
if (member.kind === SK.PropertySignature && member.name) {
|
|
44
|
+
const propName = getText(sf, member.name);
|
|
45
|
+
if (propName !== "children")
|
|
46
|
+
props.push(propName);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (props.length > 0)
|
|
51
|
+
propsTypes.set(name, props);
|
|
52
|
+
}
|
|
53
|
+
ts.forEachChild(node, collectPropsTypes);
|
|
54
|
+
}
|
|
55
|
+
collectPropsTypes(sf);
|
|
56
|
+
// Find exported functions/consts that start with uppercase (components)
|
|
57
|
+
function findComponents(node) {
|
|
58
|
+
// export function ComponentName(...) or export default function ComponentName(...)
|
|
59
|
+
if (node.kind === SK.FunctionDeclaration) {
|
|
60
|
+
const name = node.name ? getText(sf, node.name) : "";
|
|
61
|
+
if (!name || !/^[A-Z]/.test(name)) {
|
|
62
|
+
ts.forEachChild(node, findComponents);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
// Check if exported
|
|
66
|
+
const isExported = node.modifiers?.some((m) => m.kind === SK.ExportKeyword || m.kind === SK.DefaultKeyword);
|
|
67
|
+
if (!isExported) {
|
|
68
|
+
ts.forEachChild(node, findComponents);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const props = extractPropsFromParams(ts, sf, node.parameters, propsTypes);
|
|
72
|
+
components.push({
|
|
73
|
+
name,
|
|
74
|
+
file: relPath,
|
|
75
|
+
props: props.slice(0, 10),
|
|
76
|
+
isClient,
|
|
77
|
+
isServer,
|
|
78
|
+
confidence: "ast",
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
// export const ComponentName = (...) => { ... }
|
|
82
|
+
if (node.kind === SK.VariableStatement) {
|
|
83
|
+
const isExported = node.modifiers?.some((m) => m.kind === SK.ExportKeyword);
|
|
84
|
+
if (!isExported) {
|
|
85
|
+
ts.forEachChild(node, findComponents);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
for (const decl of node.declarationList?.declarations || []) {
|
|
89
|
+
if (decl.kind !== SK.VariableDeclaration)
|
|
90
|
+
continue;
|
|
91
|
+
const name = decl.name ? getText(sf, decl.name) : "";
|
|
92
|
+
if (!name || !/^[A-Z]/.test(name))
|
|
93
|
+
continue;
|
|
94
|
+
// Check if the initializer is an arrow function or function expression
|
|
95
|
+
const init = decl.initializer;
|
|
96
|
+
if (!init)
|
|
97
|
+
continue;
|
|
98
|
+
let params = null;
|
|
99
|
+
if (init.kind === SK.ArrowFunction || init.kind === SK.FunctionExpression) {
|
|
100
|
+
params = init.parameters;
|
|
101
|
+
}
|
|
102
|
+
// React.forwardRef((...) => { ... })
|
|
103
|
+
if (init.kind === SK.CallExpression) {
|
|
104
|
+
const callee = init.expression;
|
|
105
|
+
const calleeName = callee?.kind === SK.PropertyAccessExpression
|
|
106
|
+
? getText(sf, callee.name)
|
|
107
|
+
: callee?.kind === SK.Identifier ? getText(sf, callee) : "";
|
|
108
|
+
if (calleeName === "forwardRef" || calleeName === "memo") {
|
|
109
|
+
const innerFn = init.arguments?.[0];
|
|
110
|
+
if (innerFn && (innerFn.kind === SK.ArrowFunction || innerFn.kind === SK.FunctionExpression)) {
|
|
111
|
+
params = innerFn.parameters;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (params) {
|
|
116
|
+
const props = extractPropsFromParams(ts, sf, params, propsTypes);
|
|
117
|
+
components.push({
|
|
118
|
+
name,
|
|
119
|
+
file: relPath,
|
|
120
|
+
props: props.slice(0, 10),
|
|
121
|
+
isClient,
|
|
122
|
+
isServer,
|
|
123
|
+
confidence: "ast",
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
ts.forEachChild(node, findComponents);
|
|
129
|
+
}
|
|
130
|
+
findComponents(sf);
|
|
131
|
+
return components;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Extract prop names from function parameters.
|
|
135
|
+
* Handles: ({ prop1, prop2 }: Props) and (props: Props)
|
|
136
|
+
*/
|
|
137
|
+
function extractPropsFromParams(ts, sf, params, propsTypes) {
|
|
138
|
+
if (!params || params.length === 0)
|
|
139
|
+
return [];
|
|
140
|
+
const SK = ts.SyntaxKind;
|
|
141
|
+
const firstParam = params[0];
|
|
142
|
+
// Destructured: ({ prop1, prop2, ...rest }: Props)
|
|
143
|
+
if (firstParam.name?.kind === SK.ObjectBindingPattern) {
|
|
144
|
+
const props = [];
|
|
145
|
+
for (const element of firstParam.name.elements || []) {
|
|
146
|
+
if (element.dotDotDotToken)
|
|
147
|
+
continue; // skip ...rest
|
|
148
|
+
const propName = element.name ? getText(sf, element.name) : "";
|
|
149
|
+
if (propName && propName !== "children")
|
|
150
|
+
props.push(propName);
|
|
151
|
+
}
|
|
152
|
+
// If we got props from destructuring, great
|
|
153
|
+
if (props.length > 0)
|
|
154
|
+
return props;
|
|
155
|
+
// Fall back to type annotation if destructuring is empty
|
|
156
|
+
}
|
|
157
|
+
// Type annotation: (props: FooProps) or ({ ... }: FooProps)
|
|
158
|
+
if (firstParam.type) {
|
|
159
|
+
// TypeReference: FooProps
|
|
160
|
+
if (firstParam.type.kind === SK.TypeReference) {
|
|
161
|
+
const typeName = firstParam.type.typeName ? getText(sf, firstParam.type.typeName) : "";
|
|
162
|
+
const typeProps = propsTypes.get(typeName);
|
|
163
|
+
if (typeProps)
|
|
164
|
+
return typeProps;
|
|
165
|
+
}
|
|
166
|
+
// TypeLiteral: { prop1: string; prop2: number }
|
|
167
|
+
if (firstParam.type.kind === SK.TypeLiteral) {
|
|
168
|
+
const props = [];
|
|
169
|
+
for (const member of firstParam.type.members || []) {
|
|
170
|
+
if (member.kind === SK.PropertySignature && member.name) {
|
|
171
|
+
const propName = getText(sf, member.name);
|
|
172
|
+
if (propName !== "children")
|
|
173
|
+
props.push(propName);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return props;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return [];
|
|
180
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AST-based route extraction for TypeScript/JavaScript frameworks.
|
|
3
|
+
* Provides higher accuracy than regex for:
|
|
4
|
+
* - Express/Hono/Fastify/Koa/Elysia: method calls with path strings
|
|
5
|
+
* - NestJS: decorator-based routes with controller prefix combining
|
|
6
|
+
* - tRPC: router object with procedure chains and nesting
|
|
7
|
+
*/
|
|
8
|
+
import type { RouteInfo, Framework } from "../types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Try AST-based route extraction for a single file.
|
|
11
|
+
* Returns routes with confidence: 'ast', or empty array if AST cannot handle this file.
|
|
12
|
+
*/
|
|
13
|
+
export declare function extractRoutesAST(ts: any, filePath: string, content: string, framework: Framework, tags: string[]): RouteInfo[];
|