@flaid/devmap 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/README.md +2 -2
  2. package/dist/analyzers/analysis/tsMorphAnalyzer.d.ts.map +1 -1
  3. package/dist/analyzers/analysis/tsMorphAnalyzer.js +94 -1
  4. package/dist/analyzers/analysis/tsMorphAnalyzer.js.map +1 -1
  5. package/dist/analyzers/detectors/astUtils.d.ts +11 -0
  6. package/dist/analyzers/detectors/astUtils.d.ts.map +1 -0
  7. package/dist/analyzers/detectors/astUtils.js +47 -0
  8. package/dist/analyzers/detectors/astUtils.js.map +1 -0
  9. package/dist/analyzers/detectors/databaseDetector.d.ts +3 -0
  10. package/dist/analyzers/detectors/databaseDetector.d.ts.map +1 -1
  11. package/dist/analyzers/detectors/databaseDetector.js +101 -13
  12. package/dist/analyzers/detectors/databaseDetector.js.map +1 -1
  13. package/dist/analyzers/detectors/expoRouteDetector.d.ts +4 -0
  14. package/dist/analyzers/detectors/expoRouteDetector.d.ts.map +1 -0
  15. package/dist/analyzers/detectors/expoRouteDetector.js +119 -0
  16. package/dist/analyzers/detectors/expoRouteDetector.js.map +1 -0
  17. package/dist/analyzers/detectors/frameworkDetector.d.ts +2 -2
  18. package/dist/analyzers/detectors/frameworkDetector.d.ts.map +1 -1
  19. package/dist/analyzers/detectors/frameworkDetector.js +58 -3
  20. package/dist/analyzers/detectors/frameworkDetector.js.map +1 -1
  21. package/dist/analyzers/detectors/honoRouteDetector.d.ts +4 -0
  22. package/dist/analyzers/detectors/honoRouteDetector.d.ts.map +1 -0
  23. package/dist/analyzers/detectors/honoRouteDetector.js +337 -0
  24. package/dist/analyzers/detectors/honoRouteDetector.js.map +1 -0
  25. package/dist/analyzers/detectors/reactRouterRouteDetector.d.ts +4 -0
  26. package/dist/analyzers/detectors/reactRouterRouteDetector.d.ts.map +1 -0
  27. package/dist/analyzers/detectors/reactRouterRouteDetector.js +142 -0
  28. package/dist/analyzers/detectors/reactRouterRouteDetector.js.map +1 -0
  29. package/dist/analyzers/detectors/remixRouteDetector.d.ts +42 -0
  30. package/dist/analyzers/detectors/remixRouteDetector.d.ts.map +1 -0
  31. package/dist/analyzers/detectors/remixRouteDetector.js +123 -0
  32. package/dist/analyzers/detectors/remixRouteDetector.js.map +1 -0
  33. package/dist/analyzers/detectors/routeDetector.d.ts.map +1 -1
  34. package/dist/analyzers/detectors/routeDetector.js +15 -61
  35. package/dist/analyzers/detectors/routeDetector.js.map +1 -1
  36. package/dist/analyzers/detectors/routeUtils.d.ts +29 -0
  37. package/dist/analyzers/detectors/routeUtils.d.ts.map +1 -0
  38. package/dist/analyzers/detectors/routeUtils.js +111 -0
  39. package/dist/analyzers/detectors/routeUtils.js.map +1 -0
  40. package/dist/analyzers/detectors/tanstackRouteDetector.d.ts +4 -0
  41. package/dist/analyzers/detectors/tanstackRouteDetector.d.ts.map +1 -0
  42. package/dist/analyzers/detectors/tanstackRouteDetector.js +100 -0
  43. package/dist/analyzers/detectors/tanstackRouteDetector.js.map +1 -0
  44. package/dist/analyzers/graph/aliasResolver.d.ts.map +1 -1
  45. package/dist/analyzers/graph/aliasResolver.js +61 -0
  46. package/dist/analyzers/graph/aliasResolver.js.map +1 -1
  47. package/dist/analyzers/graph/bundlerAliases.d.ts +12 -0
  48. package/dist/analyzers/graph/bundlerAliases.d.ts.map +1 -0
  49. package/dist/analyzers/graph/bundlerAliases.js +328 -0
  50. package/dist/analyzers/graph/bundlerAliases.js.map +1 -0
  51. package/dist/analyzers/graph/dependencyGraph.d.ts.map +1 -1
  52. package/dist/analyzers/graph/dependencyGraph.js +37 -53
  53. package/dist/analyzers/graph/dependencyGraph.js.map +1 -1
  54. package/dist/analyzers/graph/entryPoints.d.ts +8 -1
  55. package/dist/analyzers/graph/entryPoints.d.ts.map +1 -1
  56. package/dist/analyzers/graph/entryPoints.js +75 -5
  57. package/dist/analyzers/graph/entryPoints.js.map +1 -1
  58. package/dist/analyzers/graph/index.d.ts +2 -0
  59. package/dist/analyzers/graph/index.d.ts.map +1 -1
  60. package/dist/analyzers/graph/index.js +1 -0
  61. package/dist/analyzers/graph/index.js.map +1 -1
  62. package/dist/analyzers/graph/localPaths.d.ts +4 -0
  63. package/dist/analyzers/graph/localPaths.d.ts.map +1 -0
  64. package/dist/analyzers/graph/localPaths.js +50 -0
  65. package/dist/analyzers/graph/localPaths.js.map +1 -0
  66. package/dist/analyzers/graph/nuxtAutoImports.d.ts +33 -0
  67. package/dist/analyzers/graph/nuxtAutoImports.d.ts.map +1 -0
  68. package/dist/analyzers/graph/nuxtAutoImports.js +222 -0
  69. package/dist/analyzers/graph/nuxtAutoImports.js.map +1 -0
  70. package/dist/analyzers/graph/packageManifests.d.ts +49 -0
  71. package/dist/analyzers/graph/packageManifests.d.ts.map +1 -0
  72. package/dist/analyzers/graph/packageManifests.js +322 -0
  73. package/dist/analyzers/graph/packageManifests.js.map +1 -0
  74. package/dist/analyzers/pipeline/projectMap.d.ts.map +1 -1
  75. package/dist/analyzers/pipeline/projectMap.js +2 -2
  76. package/dist/analyzers/pipeline/projectMap.js.map +1 -1
  77. package/dist/analyzers/pipeline/projectMetadata.js +6 -0
  78. package/dist/analyzers/pipeline/projectMetadata.js.map +1 -1
  79. package/dist/commands/analyze.js +3 -0
  80. package/dist/commands/analyze.js.map +1 -1
  81. package/package.json +1 -1
@@ -1,10 +1,14 @@
1
1
  import { parseJsonText } from "../analysis/index.js";
2
2
  import { isArchitectureSource } from "../graph/index.js";
3
+ // Order is priority: the first detected framework of a category wins. The
4
+ // meta-frameworks come before plain `react` because they all ship React too.
3
5
  export const FRONTEND_FRAMEWORKS = [
4
- "nextjs", "nuxt", "sveltekit", "astro", "react", "vue", "svelte"
6
+ "nextjs", "nuxt", "sveltekit", "astro",
7
+ "remix", "react-router", "tanstack-start", "tanstack-router", "expo",
8
+ "react", "vue", "svelte"
5
9
  ];
6
10
  export const BACKEND_FRAMEWORKS = [
7
- "nestjs", "fastify", "express", "koa"
11
+ "nestjs", "fastify", "express", "hono", "koa"
8
12
  ];
9
13
  export const FRONTEND_FRAMEWORK_SET = new Set(FRONTEND_FRAMEWORKS);
10
14
  export const BACKEND_FRAMEWORK_SET = new Set(BACKEND_FRAMEWORKS);
@@ -42,6 +46,23 @@ export function detectFrameworks(files) {
42
46
  }
43
47
  if ("@sveltejs/kit" in dependencies)
44
48
  detected.add("sveltekit");
49
+ if ("hono" in dependencies)
50
+ detected.add("hono");
51
+ // Remix v2 lives under `@remix-run/*`; `@remix-run/router` is React Router's
52
+ // own internal package and says nothing about Remix.
53
+ if (REMIX_PACKAGES.some((name) => name in dependencies))
54
+ detected.add("remix");
55
+ // React Router v7 "framework mode" (the Remix successor) is the dev tooling;
56
+ // `react-router-dom` alone is just a client-side router inside a React app.
57
+ if ("@react-router/dev" in dependencies)
58
+ detected.add("react-router");
59
+ if (Object.keys(dependencies).some(isTanStackStartPackage))
60
+ detected.add("tanstack-start");
61
+ if (TANSTACK_ROUTER_PACKAGES.some((name) => name in dependencies))
62
+ detected.add("tanstack-router");
63
+ // Expo Router is what makes `app/` a route tree; bare Expo is just React Native.
64
+ if ("expo-router" in dependencies)
65
+ detected.add("expo");
45
66
  const hasReactRuntime = "react-dom" in dependencies
46
67
  || "react-scripts" in dependencies
47
68
  || "@vitejs/plugin-react" in dependencies
@@ -75,7 +96,9 @@ export function detectFrameworks(files) {
75
96
  // (Astro uses the same folder for endpoints), so it is deliberately excluded
76
97
  // from the Pages Router signal here.
77
98
  if (files.some((file) => /(^|\/)next\.config\.[cm]?[jt]s$/.test(file.path))
78
- || sourceFiles.some((file) => /(^|\/)(?:src\/)?app\/(?:.+\/)?(?:page|layout|route)\.[jt]sx?$/.test(file.path)
99
+ || sourceFiles.some((file) =>
100
+ // `app/routes/blog/route.tsx` is a Remix route folder, not a Next route handler.
101
+ /(^|\/)(?:src\/)?app\/(?!routes\/)(?:.+\/)?(?:page|layout|route)\.[jt]sx?$/.test(file.path)
79
102
  || /(^|\/)(?:src\/)?pages\/(?:_app|_document)/.test(file.path))) {
80
103
  detected.add("nextjs");
81
104
  }
@@ -123,11 +146,43 @@ export function detectFrameworks(files) {
123
146
  if (files.some((file) => /(^|\/)nest-cli\.json$/.test(file.path))) {
124
147
  detected.add("nestjs");
125
148
  }
149
+ // Remix / React Router v7: their config files are specific to each tool.
150
+ if (files.some((file) => /(^|\/)remix\.config\.[cm]?js$/.test(file.path))) {
151
+ detected.add("remix");
152
+ }
153
+ if (files.some((file) => /(^|\/)react-router\.config\.[cm]?[jt]s$/.test(file.path))) {
154
+ detected.add("react-router");
155
+ }
156
+ // TanStack Router writes `routeTree.gen.ts` (or the name set in `tsr.config.json`).
157
+ if (files.some((file) => /(^|\/)(?:routeTree\.gen\.[jt]sx?|tsr\.config\.json)$/.test(file.path))) {
158
+ detected.add("tanstack-router");
159
+ }
160
+ // Expo Router: the config plugin is declared in app.json / app.config.*.
161
+ if (files.some((file) => /(^|\/)app(?:\.config\.[cm]?[jt]s|\.json)$/.test(file.path) && file.content.includes("expo-router"))) {
162
+ detected.add("expo");
163
+ }
164
+ // Hono: like Express, the import is only trusted when no manifest can confirm it.
165
+ if (!hasReliableManifest && sourceFiles.some((file) => /from\s+["']hono["']/.test(file.content))) {
166
+ detected.add("hono");
167
+ }
126
168
  return [
127
169
  FRONTEND_FRAMEWORKS.find((framework) => detected.has(framework)),
128
170
  BACKEND_FRAMEWORKS.find((framework) => detected.has(framework)),
129
171
  ].filter((framework) => Boolean(framework));
130
172
  }
173
+ const REMIX_PACKAGES = [
174
+ "@remix-run/dev", "@remix-run/react", "@remix-run/serve",
175
+ "@remix-run/node", "@remix-run/cloudflare", "@remix-run/deno"
176
+ ];
177
+ const TANSTACK_ROUTER_PACKAGES = [
178
+ "@tanstack/react-router", "@tanstack/solid-router",
179
+ "@tanstack/router-plugin", "@tanstack/router-vite-plugin", "@tanstack/router-cli"
180
+ ];
181
+ // `@tanstack/react-start`, `@tanstack/solid-start`, and the pre-1.0 `@tanstack/start`
182
+ // (plus its `start-*` helper packages).
183
+ function isTanStackStartPackage(name) {
184
+ return /^@tanstack\/(?:react-start|solid-start|start)(?:-|$)/.test(name);
185
+ }
131
186
  function isParseableJson(content) {
132
187
  try {
133
188
  parseJsonText(content);
@@ -1 +1 @@
1
- {"version":3,"file":"frameworkDetector.js","sourceRoot":"","sources":["../../../src/analyzers/detectors/frameworkDetector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"frameworkDetector.js","sourceRoot":"","sources":["../../../src/analyzers/detectors/frameworkDetector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ScannedFile } from "../analysis/index.js";
2
+ import type { RouteInfo } from "./routeDetector.js";
3
+ export declare function detectHonoRoutes(files: ScannedFile[], graph?: Record<string, string[]>): RouteInfo[];
4
+ //# sourceMappingURL=honoRouteDetector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"honoRouteDetector.d.ts","sourceRoot":"","sources":["../../../src/analyzers/detectors/honoRouteDetector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAIxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAgDpD,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,WAAW,EAAE,EACpB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAC/B,SAAS,EAAE,CA2Ob"}
@@ -0,0 +1,337 @@
1
+ import { posix } from "node:path";
2
+ import { ts } from "ts-morph";
3
+ import { isArchitectureSource } from "../graph/index.js";
4
+ import { matchLocalPath, normalizePath } from "../graph/localPaths.js";
5
+ import { parseSource, propertyKeyName, stringValue, unwrapExpression } from "./astUtils.js";
6
+ import { joinRoutePaths, sortRoutes } from "./routeUtils.js";
7
+ /**
8
+ * Hono apps are plain values, so they are followed the way the runtime builds
9
+ * them instead of by pattern:
10
+ *
11
+ * const book = new Hono() one app per `new Hono()`
12
+ * book.get('/', h).post('/', h) chains hand back the same app
13
+ * const v1 = app.basePath('/v1') a view of the same app with a prefix
14
+ * app.route('/book', book) book's routes join app under /book
15
+ * app.route('/api', api) // import api from './api' ...also across files
16
+ * app.openapi(createRoute({ method, path }), h) @hono/zod-openapi
17
+ *
18
+ * Only apps nobody mounts are walked from the top, so each endpoint is listed
19
+ * once, under its full URL. Handlers must be registered on a value this module
20
+ * can trace to `new Hono()`: apps built by a factory function are not followed.
21
+ */
22
+ const HONO_MODULE = /^(?:hono|hono\/.+|@hono\/.+)$/;
23
+ const HONO_CLASSES = new Set(["Hono", "OpenAPIHono"]);
24
+ const VERB_METHODS = new Set(["get", "post", "put", "patch", "delete", "options", "all"]);
25
+ export function detectHonoRoutes(files, graph) {
26
+ const sources = files.filter((file) => isArchitectureSource(file.path) && /\.[cm]?[jt]sx?$/.test(file.path));
27
+ const byPath = new Map(sources.map((file) => [file.path, file]));
28
+ const localPaths = new Set(byPath.keys());
29
+ const models = new Map();
30
+ const model = (path) => {
31
+ const cached = models.get(path);
32
+ if (cached)
33
+ return cached;
34
+ const file = byPath.get(path);
35
+ if (!file)
36
+ return undefined;
37
+ const built = buildModel(file);
38
+ models.set(path, built);
39
+ return built;
40
+ };
41
+ const apps = new Map();
42
+ const handles = new Map();
43
+ const resolving = new Set();
44
+ const appAt = (file, node) => {
45
+ const key = `${file}@${node.getStart()}-${node.end}`;
46
+ let app = apps.get(key);
47
+ if (!app) {
48
+ app = { routes: [], mounts: [], mounted: false };
49
+ apps.set(key, app);
50
+ }
51
+ return app;
52
+ };
53
+ const resolveImport = (from, specifier) => {
54
+ if (specifier.startsWith(".")) {
55
+ const target = normalizePath(posix.join(posix.dirname(from), specifier));
56
+ return target === null ? undefined : matchLocalPath(target, localPaths) ?? undefined;
57
+ }
58
+ // Aliased specifier (`@/server/api`): pick the one graph edge it can be.
59
+ const tail = specifier.replace(/^[@~#$][^/]*\//, "").replace(/^\/+/, "");
60
+ if (!tail || tail === specifier)
61
+ return undefined;
62
+ const matches = (graph?.[from] ?? []).filter((path) => {
63
+ const bare = path.replace(/\.[cm]?[jt]sx?$/, "").replace(/\/index$/, "");
64
+ return bare === tail || bare.endsWith(`/${tail}`);
65
+ });
66
+ return matches.length === 1 ? matches[0] : undefined;
67
+ };
68
+ /** Follow identifiers (and imports) until an expression that is not a name. */
69
+ const resolveValue = (path, expression, seen = new Set()) => {
70
+ const node = unwrapExpression(expression);
71
+ if (!ts.isIdentifier(node))
72
+ return { path, expression: node };
73
+ const key = `${path}#${node.text}`;
74
+ if (seen.has(key))
75
+ return undefined;
76
+ seen.add(key);
77
+ const current = model(path);
78
+ if (!current)
79
+ return undefined;
80
+ const local = current.variables.get(node.text);
81
+ if (local)
82
+ return resolveValue(path, local, seen);
83
+ const imported = current.imports.get(node.text);
84
+ if (!imported)
85
+ return undefined;
86
+ const targetPath = resolveImport(path, imported.specifier);
87
+ const target = targetPath ? model(targetPath) : undefined;
88
+ if (!targetPath || !target)
89
+ return undefined;
90
+ if (imported.imported === "default") {
91
+ return target.defaultExport ? resolveValue(targetPath, target.defaultExport, seen) : undefined;
92
+ }
93
+ const localName = target.exports.get(imported.imported);
94
+ const initializer = localName ? target.variables.get(localName) : undefined;
95
+ return initializer ? resolveValue(targetPath, initializer, seen) : undefined;
96
+ };
97
+ /** Which app (and base path) an expression evaluates to, if any. */
98
+ const handleOf = (path, expression) => {
99
+ const resolved = resolveValue(path, expression);
100
+ if (!resolved)
101
+ return undefined;
102
+ const node = resolved.expression;
103
+ // `new Hono().basePath("/x")` starts where `new Hono()` does: key on the span.
104
+ const key = `${resolved.path}@${node.getStart()}-${node.end}`;
105
+ const cached = handles.get(key);
106
+ if (cached !== undefined)
107
+ return cached ?? undefined;
108
+ if (resolving.has(key))
109
+ return undefined;
110
+ resolving.add(key);
111
+ let handle;
112
+ const home = model(resolved.path);
113
+ if (home && ts.isNewExpression(node) && ts.isIdentifier(node.expression) && home.honoClasses.has(node.expression.text)) {
114
+ handle = { app: appAt(resolved.path, node), base: "" };
115
+ }
116
+ else if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression)) {
117
+ const method = node.expression.name.text;
118
+ if (method === "createApp" && /\bcreateFactory\b/.test(node.expression.expression.getText())) {
119
+ handle = { app: appAt(resolved.path, node), base: "" };
120
+ }
121
+ else {
122
+ const receiver = handleOf(resolved.path, node.expression.expression);
123
+ if (receiver) {
124
+ handle = method === "basePath"
125
+ ? { app: receiver.app, base: joinRoutePaths(receiver.base, stringValue(node.arguments[0]) ?? "") }
126
+ : receiver;
127
+ }
128
+ }
129
+ }
130
+ resolving.delete(key);
131
+ handles.set(key, handle ?? null);
132
+ return handle;
133
+ };
134
+ /** `{ method, path }` of an `@hono/zod-openapi` route definition. */
135
+ const openApiRoute = (path, expression) => {
136
+ const resolved = resolveValue(path, expression);
137
+ let node = resolved?.expression;
138
+ if (node && ts.isCallExpression(node) && node.arguments[0]) {
139
+ node = unwrapExpression(node.arguments[0]);
140
+ }
141
+ if (!node || !ts.isObjectLiteralExpression(node))
142
+ return undefined;
143
+ let method;
144
+ let routePath;
145
+ for (const property of node.properties) {
146
+ if (!ts.isPropertyAssignment(property))
147
+ continue;
148
+ const name = propertyKeyName(property.name);
149
+ if (name === "method")
150
+ method = stringValue(property.initializer)?.toUpperCase();
151
+ if (name === "path")
152
+ routePath = stringValue(property.initializer);
153
+ }
154
+ return routePath === undefined ? undefined : { path: routePath, ...(method ? { method } : {}) };
155
+ };
156
+ const candidates = sources.filter((file) => /hono/i.test(file.content));
157
+ // Every call is judged on its own: `handleOf` resolves the receiver without
158
+ // side effects, so a chain like `app.get().post()` registers each call once.
159
+ for (const file of candidates) {
160
+ const current = model(file.path);
161
+ if (!current)
162
+ continue;
163
+ walk(current.source, (node) => {
164
+ if (!ts.isCallExpression(node) || !ts.isPropertyAccessExpression(node.expression))
165
+ return;
166
+ const method = node.expression.name.text;
167
+ const isVerb = VERB_METHODS.has(method);
168
+ if (!isVerb && method !== "on" && method !== "route" && method !== "openapi")
169
+ return;
170
+ const receiver = handleOf(file.path, node.expression.expression);
171
+ if (!receiver)
172
+ return;
173
+ const args = node.arguments;
174
+ if (method === "route") {
175
+ const prefix = stringValue(args[0]);
176
+ const child = args[1] ? handleOf(file.path, args[1]) : undefined;
177
+ if (prefix === undefined || !child || child.app === receiver.app)
178
+ return;
179
+ child.app.mounted = true;
180
+ receiver.app.mounts.push({ prefix: joinRoutePaths(receiver.base, prefix), target: child.app });
181
+ return;
182
+ }
183
+ if (method === "openapi") {
184
+ const definition = args[0] ? openApiRoute(file.path, args[0]) : undefined;
185
+ if (!definition)
186
+ return;
187
+ receiver.app.routes.push({
188
+ path: joinRoutePaths(receiver.base, openApiPath(definition.path)),
189
+ ...(definition.method ? { method: definition.method } : {}),
190
+ file: file.path
191
+ });
192
+ return;
193
+ }
194
+ if (method === "on") {
195
+ const methods = stringList(args[0]);
196
+ const paths = stringList(args[1]);
197
+ for (const path of paths) {
198
+ for (const verb of methods.length > 0 ? methods : [undefined]) {
199
+ receiver.app.routes.push({
200
+ path: joinRoutePaths(receiver.base, path),
201
+ ...(verb ? { method: verb.toUpperCase() } : {}),
202
+ file: file.path
203
+ });
204
+ }
205
+ }
206
+ return;
207
+ }
208
+ // `c.get('user')` and friends take a key, not a path, but never resolve
209
+ // to an app, so anything that gets here is a route.
210
+ const path = stringValue(args[0]);
211
+ if (path === undefined)
212
+ return;
213
+ receiver.app.routes.push({
214
+ path: joinRoutePaths(receiver.base, path),
215
+ ...(method === "all" ? {} : { method: method.toUpperCase() }),
216
+ file: file.path
217
+ });
218
+ });
219
+ }
220
+ const routes = new Map();
221
+ const emit = (app, prefix, trail) => {
222
+ if (trail.has(app))
223
+ return;
224
+ trail.add(app);
225
+ for (const route of app.routes) {
226
+ const path = honoPath(joinRoutePaths(prefix, route.path));
227
+ const key = `${path}\0${route.file}`;
228
+ const existing = routes.get(key);
229
+ if (existing) {
230
+ if (route.method && existing.methods && !existing.methods.includes(route.method)) {
231
+ existing.methods = [...existing.methods, route.method].sort();
232
+ }
233
+ continue;
234
+ }
235
+ routes.set(key, {
236
+ path,
237
+ file: route.file,
238
+ kind: "api",
239
+ ...(route.method ? { methods: [route.method] } : {})
240
+ });
241
+ }
242
+ for (const mount of app.mounts)
243
+ emit(mount.target, joinRoutePaths(prefix, mount.prefix), trail);
244
+ trail.delete(app);
245
+ };
246
+ for (const app of apps.values()) {
247
+ if (!app.mounted)
248
+ emit(app, "/", new Set());
249
+ }
250
+ return sortRoutes([...routes.values()]);
251
+ }
252
+ function buildModel(file) {
253
+ const source = parseSource(file.path, file.content);
254
+ const model = {
255
+ file,
256
+ source,
257
+ honoClasses: new Set(),
258
+ imports: new Map(),
259
+ variables: new Map(),
260
+ exports: new Map()
261
+ };
262
+ for (const statement of source.statements) {
263
+ if (ts.isImportDeclaration(statement)) {
264
+ const specifier = stringValue(statement.moduleSpecifier);
265
+ const clause = statement.importClause;
266
+ if (!specifier || !clause)
267
+ continue;
268
+ if (clause.name)
269
+ model.imports.set(clause.name.text, { specifier, imported: "default" });
270
+ if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {
271
+ for (const element of clause.namedBindings.elements) {
272
+ const imported = (element.propertyName ?? element.name).text;
273
+ model.imports.set(element.name.text, { specifier, imported });
274
+ if (HONO_MODULE.test(specifier) && HONO_CLASSES.has(imported)) {
275
+ model.honoClasses.add(element.name.text);
276
+ }
277
+ }
278
+ }
279
+ }
280
+ else if (ts.isVariableStatement(statement)) {
281
+ const exported = statement.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
282
+ for (const declaration of statement.declarationList.declarations) {
283
+ if (!ts.isIdentifier(declaration.name) || !declaration.initializer)
284
+ continue;
285
+ model.variables.set(declaration.name.text, declaration.initializer);
286
+ if (exported)
287
+ model.exports.set(declaration.name.text, declaration.name.text);
288
+ }
289
+ }
290
+ else if (ts.isExportAssignment(statement) && !statement.isExportEquals) {
291
+ model.defaultExport = statement.expression;
292
+ }
293
+ else if (ts.isExportDeclaration(statement)
294
+ && !statement.moduleSpecifier
295
+ && statement.exportClause
296
+ && ts.isNamedExports(statement.exportClause)) {
297
+ for (const element of statement.exportClause.elements) {
298
+ const local = (element.propertyName ?? element.name).text;
299
+ if (element.name.text === "default") {
300
+ const initializer = model.variables.get(local);
301
+ if (initializer)
302
+ model.defaultExport = initializer;
303
+ }
304
+ else {
305
+ model.exports.set(element.name.text, local);
306
+ }
307
+ }
308
+ }
309
+ }
310
+ return model;
311
+ }
312
+ function walk(node, visit) {
313
+ visit(node);
314
+ ts.forEachChild(node, (child) => walk(child, visit));
315
+ }
316
+ /** `'GET'` or `['GET', 'POST']`. */
317
+ function stringList(node) {
318
+ if (!node)
319
+ return [];
320
+ const unwrapped = unwrapExpression(node);
321
+ const single = stringValue(unwrapped);
322
+ if (single !== undefined)
323
+ return [single];
324
+ if (ts.isArrayLiteralExpression(unwrapped)) {
325
+ return unwrapped.elements.flatMap((element) => stringValue(element) ?? []);
326
+ }
327
+ return [];
328
+ }
329
+ /** OpenAPI writes `/users/{id}`; Hono routes use `/users/:id`. */
330
+ function openApiPath(path) {
331
+ return path.replace(/\{([^}]+)\}/g, ":$1");
332
+ }
333
+ /** `:id{[0-9]+}` is a constrained param; show it as `:id`. */
334
+ function honoPath(path) {
335
+ return path.replace(/(:[A-Za-z_]\w*)\{[^}]*\}/g, "$1");
336
+ }
337
+ //# sourceMappingURL=honoRouteDetector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"honoRouteDetector.js","sourceRoot":"","sources":["../../../src/analyzers/detectors/honoRouteDetector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ScannedFile } from "../analysis/index.js";
2
+ import type { RouteInfo } from "./routeDetector.js";
3
+ export declare function detectReactRouterRoutes(files: ScannedFile[]): RouteInfo[];
4
+ //# sourceMappingURL=reactRouterRouteDetector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactRouterRouteDetector.d.ts","sourceRoot":"","sources":["../../../src/analyzers/detectors/reactRouterRouteDetector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAqCpD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,SAAS,EAAE,CAyCzE"}
@@ -0,0 +1,142 @@
1
+ import { posix } from "node:path";
2
+ import { ts } from "ts-morph";
3
+ import { parseSource, stringValue, unwrapExpression } from "./astUtils.js";
4
+ import { detectFlatFileRoutes, readRouteModule } from "./remixRouteDetector.js";
5
+ import { dropShadowedLayouts, joinRoutePaths, sortRoutes } from "./routeUtils.js";
6
+ /**
7
+ * React Router v7 framework mode declares its routes in `app/routes.ts`:
8
+ *
9
+ * export default [
10
+ * index("routes/home.tsx"),
11
+ * route("teams/:teamId", "routes/team.tsx", [index("routes/team-home.tsx")]),
12
+ * layout("layouts/auth.tsx", [route("login", "routes/login.tsx")]),
13
+ * ...prefix("api", [route("users", "routes/api/users.ts")]),
14
+ * ...(await flatRoutes()) // file-name convention, see remixRouteDetector
15
+ * ] satisfies RouteConfig;
16
+ *
17
+ * The array is a plain value, so it is read from the AST rather than matched
18
+ * with regexes: nesting, `prefix()` and identifiers pointing at other arrays
19
+ * all compose the way React Router composes them.
20
+ */
21
+ const ROUTES_MODULE = "@react-router/dev/routes";
22
+ export function detectReactRouterRoutes(files) {
23
+ const configs = files.filter((file) => /(^|\/)routes\.[cm]?[jt]s$/.test(file.path) && file.content.includes(ROUTES_MODULE));
24
+ const byPath = new Map(files.map((file) => [file.path, file]));
25
+ const routes = [];
26
+ for (const config of configs) {
27
+ const appDir = posix.dirname(config.path) === "." ? "" : posix.dirname(config.path);
28
+ const parsed = parseRouteConfig(config);
29
+ const entries = [];
30
+ collect(parsed.nodes, "/", (node, path) => {
31
+ if (!node.file || node.layout || node.group)
32
+ return;
33
+ const file = byPath.get(posix.normalize(posix.join(appDir, node.file)));
34
+ const module = file ? readRouteModule(file) : undefined;
35
+ if (!file)
36
+ return;
37
+ entries.push({
38
+ path,
39
+ file: file.path,
40
+ kind: module?.kind ?? "page",
41
+ ...(module?.methods ? { methods: module.methods } : {}),
42
+ isIndex: Boolean(node.index),
43
+ isLayout: node.children.length > 0
44
+ });
45
+ });
46
+ routes.push(...dropShadowedLayouts(entries).map((entry) => ({
47
+ path: entry.path,
48
+ file: entry.file,
49
+ kind: entry.kind,
50
+ ...(entry.methods ? { methods: entry.methods } : {})
51
+ })));
52
+ if (parsed.usesFlatRoutes) {
53
+ routes.push(...detectFlatFileRoutes(files, appDir === "" ? "routes/" : `${appDir}/routes/`));
54
+ }
55
+ }
56
+ return sortRoutes(routes);
57
+ }
58
+ function collect(nodes, base, visit) {
59
+ for (const node of nodes) {
60
+ const path = node.layout ? base : joinRoutePaths(base, node.path);
61
+ visit(node, path);
62
+ collect(node.children, path, visit);
63
+ }
64
+ }
65
+ function parseRouteConfig(file) {
66
+ const source = parseSource(file.path, file.content);
67
+ const helpers = new Map();
68
+ const variables = new Map();
69
+ let defaultExport;
70
+ let usesFlatRoutes = false;
71
+ for (const statement of source.statements) {
72
+ if (ts.isImportDeclaration(statement)) {
73
+ const module = stringValue(statement.moduleSpecifier);
74
+ const bindings = statement.importClause?.namedBindings;
75
+ if (bindings && ts.isNamedImports(bindings)) {
76
+ for (const element of bindings.elements) {
77
+ const imported = (element.propertyName ?? element.name).text;
78
+ if (module === ROUTES_MODULE)
79
+ helpers.set(element.name.text, imported);
80
+ if (imported === "flatRoutes")
81
+ helpers.set(element.name.text, "flatRoutes");
82
+ }
83
+ }
84
+ }
85
+ else if (ts.isVariableStatement(statement)) {
86
+ for (const declaration of statement.declarationList.declarations) {
87
+ if (ts.isIdentifier(declaration.name) && declaration.initializer) {
88
+ variables.set(declaration.name.text, declaration.initializer);
89
+ }
90
+ }
91
+ }
92
+ else if (ts.isExportAssignment(statement) && !statement.isExportEquals) {
93
+ defaultExport = statement.expression;
94
+ }
95
+ }
96
+ const seen = new Set();
97
+ const evaluate = (expression) => {
98
+ const node = unwrapExpression(expression);
99
+ if (ts.isArrayLiteralExpression(node)) {
100
+ return node.elements.flatMap((element) => evaluate(ts.isSpreadElement(element) ? element.expression : element));
101
+ }
102
+ if (ts.isIdentifier(node)) {
103
+ const initializer = variables.get(node.text);
104
+ if (!initializer || seen.has(node.text))
105
+ return [];
106
+ seen.add(node.text);
107
+ const result = evaluate(initializer);
108
+ seen.delete(node.text);
109
+ return result;
110
+ }
111
+ if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
112
+ return evaluateHelper(helpers.get(node.expression.text), node.arguments);
113
+ }
114
+ return [];
115
+ };
116
+ const lastChildren = (args, from) => {
117
+ const candidate = args.slice(from).reverse().find((arg) => {
118
+ const unwrapped = unwrapExpression(arg);
119
+ return !ts.isObjectLiteralExpression(unwrapped) && !stringValue(unwrapped);
120
+ });
121
+ return candidate ? evaluate(candidate) : [];
122
+ };
123
+ const evaluateHelper = (helper, args) => {
124
+ switch (helper) {
125
+ case "index":
126
+ return [{ path: "", index: true, file: stringValue(args[0]), children: [] }];
127
+ case "route":
128
+ return [{ path: stringValue(args[0]) ?? "", file: stringValue(args[1]), children: lastChildren(args, 2) }];
129
+ case "layout":
130
+ return [{ path: "", file: stringValue(args[0]), layout: true, children: lastChildren(args, 1) }];
131
+ case "prefix":
132
+ return [{ path: stringValue(args[0]) ?? "", group: true, children: args[1] ? evaluate(args[1]) : [] }];
133
+ case "flatRoutes":
134
+ usesFlatRoutes = true;
135
+ return [];
136
+ default:
137
+ return [];
138
+ }
139
+ };
140
+ return { nodes: defaultExport ? evaluate(defaultExport) : [], usesFlatRoutes };
141
+ }
142
+ //# sourceMappingURL=reactRouterRouteDetector.js.map