@flaid/devmap 0.6.0 → 0.8.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 (84) hide show
  1. package/README.md +2 -2
  2. package/dist/analyzers/detectors/adonisRouteDetector.d.ts +4 -0
  3. package/dist/analyzers/detectors/adonisRouteDetector.d.ts.map +1 -0
  4. package/dist/analyzers/detectors/adonisRouteDetector.js +242 -0
  5. package/dist/analyzers/detectors/adonisRouteDetector.js.map +1 -0
  6. package/dist/analyzers/detectors/angularRouteDetector.d.ts +4 -0
  7. package/dist/analyzers/detectors/angularRouteDetector.d.ts.map +1 -0
  8. package/dist/analyzers/detectors/angularRouteDetector.js +186 -0
  9. package/dist/analyzers/detectors/angularRouteDetector.js.map +1 -0
  10. package/dist/analyzers/detectors/astUtils.d.ts +31 -0
  11. package/dist/analyzers/detectors/astUtils.d.ts.map +1 -0
  12. package/dist/analyzers/detectors/astUtils.js +85 -0
  13. package/dist/analyzers/detectors/astUtils.js.map +1 -0
  14. package/dist/analyzers/detectors/clientRouteDetector.d.ts +4 -0
  15. package/dist/analyzers/detectors/clientRouteDetector.d.ts.map +1 -0
  16. package/dist/analyzers/detectors/clientRouteDetector.js +417 -0
  17. package/dist/analyzers/detectors/clientRouteDetector.js.map +1 -0
  18. package/dist/analyzers/detectors/elysiaRouteDetector.d.ts +4 -0
  19. package/dist/analyzers/detectors/elysiaRouteDetector.d.ts.map +1 -0
  20. package/dist/analyzers/detectors/elysiaRouteDetector.js +186 -0
  21. package/dist/analyzers/detectors/elysiaRouteDetector.js.map +1 -0
  22. package/dist/analyzers/detectors/expoRouteDetector.d.ts +4 -0
  23. package/dist/analyzers/detectors/expoRouteDetector.d.ts.map +1 -0
  24. package/dist/analyzers/detectors/expoRouteDetector.js +119 -0
  25. package/dist/analyzers/detectors/expoRouteDetector.js.map +1 -0
  26. package/dist/analyzers/detectors/frameworkDetector.d.ts +2 -2
  27. package/dist/analyzers/detectors/frameworkDetector.d.ts.map +1 -1
  28. package/dist/analyzers/detectors/frameworkDetector.js +86 -3
  29. package/dist/analyzers/detectors/frameworkDetector.js.map +1 -1
  30. package/dist/analyzers/detectors/honoRouteDetector.d.ts +4 -0
  31. package/dist/analyzers/detectors/honoRouteDetector.d.ts.map +1 -0
  32. package/dist/analyzers/detectors/honoRouteDetector.js +485 -0
  33. package/dist/analyzers/detectors/honoRouteDetector.js.map +1 -0
  34. package/dist/analyzers/detectors/koaRouteDetector.d.ts +4 -0
  35. package/dist/analyzers/detectors/koaRouteDetector.d.ts.map +1 -0
  36. package/dist/analyzers/detectors/koaRouteDetector.js +216 -0
  37. package/dist/analyzers/detectors/koaRouteDetector.js.map +1 -0
  38. package/dist/analyzers/detectors/moduleBindings.d.ts +52 -0
  39. package/dist/analyzers/detectors/moduleBindings.d.ts.map +1 -0
  40. package/dist/analyzers/detectors/moduleBindings.js +295 -0
  41. package/dist/analyzers/detectors/moduleBindings.js.map +1 -0
  42. package/dist/analyzers/detectors/qwikRouteDetector.d.ts +4 -0
  43. package/dist/analyzers/detectors/qwikRouteDetector.d.ts.map +1 -0
  44. package/dist/analyzers/detectors/qwikRouteDetector.js +53 -0
  45. package/dist/analyzers/detectors/qwikRouteDetector.js.map +1 -0
  46. package/dist/analyzers/detectors/reactRouterRouteDetector.d.ts +4 -0
  47. package/dist/analyzers/detectors/reactRouterRouteDetector.d.ts.map +1 -0
  48. package/dist/analyzers/detectors/reactRouterRouteDetector.js +142 -0
  49. package/dist/analyzers/detectors/reactRouterRouteDetector.js.map +1 -0
  50. package/dist/analyzers/detectors/remixRouteDetector.d.ts +42 -0
  51. package/dist/analyzers/detectors/remixRouteDetector.d.ts.map +1 -0
  52. package/dist/analyzers/detectors/remixRouteDetector.js +123 -0
  53. package/dist/analyzers/detectors/remixRouteDetector.js.map +1 -0
  54. package/dist/analyzers/detectors/routeDetector.d.ts.map +1 -1
  55. package/dist/analyzers/detectors/routeDetector.js +61 -66
  56. package/dist/analyzers/detectors/routeDetector.js.map +1 -1
  57. package/dist/analyzers/detectors/routeUtils.d.ts +43 -0
  58. package/dist/analyzers/detectors/routeUtils.d.ts.map +1 -0
  59. package/dist/analyzers/detectors/routeUtils.js +162 -0
  60. package/dist/analyzers/detectors/routeUtils.js.map +1 -0
  61. package/dist/analyzers/detectors/solidStartRouteDetector.d.ts +4 -0
  62. package/dist/analyzers/detectors/solidStartRouteDetector.d.ts.map +1 -0
  63. package/dist/analyzers/detectors/solidStartRouteDetector.js +59 -0
  64. package/dist/analyzers/detectors/solidStartRouteDetector.js.map +1 -0
  65. package/dist/analyzers/detectors/tanstackRouteDetector.d.ts +4 -0
  66. package/dist/analyzers/detectors/tanstackRouteDetector.d.ts.map +1 -0
  67. package/dist/analyzers/detectors/tanstackRouteDetector.js +100 -0
  68. package/dist/analyzers/detectors/tanstackRouteDetector.js.map +1 -0
  69. package/dist/analyzers/graph/aliasResolver.d.ts.map +1 -1
  70. package/dist/analyzers/graph/aliasResolver.js +3 -0
  71. package/dist/analyzers/graph/aliasResolver.js.map +1 -1
  72. package/dist/analyzers/graph/bundlerAliases.d.ts +12 -0
  73. package/dist/analyzers/graph/bundlerAliases.d.ts.map +1 -0
  74. package/dist/analyzers/graph/bundlerAliases.js +328 -0
  75. package/dist/analyzers/graph/bundlerAliases.js.map +1 -0
  76. package/dist/analyzers/graph/entryPoints.d.ts.map +1 -1
  77. package/dist/analyzers/graph/entryPoints.js +34 -3
  78. package/dist/analyzers/graph/entryPoints.js.map +1 -1
  79. package/dist/analyzers/pipeline/projectMap.d.ts.map +1 -1
  80. package/dist/analyzers/pipeline/projectMap.js +17 -6
  81. package/dist/analyzers/pipeline/projectMap.js.map +1 -1
  82. package/dist/analyzers/pipeline/projectMetadata.js +11 -0
  83. package/dist/analyzers/pipeline/projectMetadata.js.map +1 -1
  84. package/package.json +1 -1
package/README.md CHANGED
@@ -150,8 +150,8 @@ terminal decoration, or streamed partial output.
150
150
 
151
151
  ## Supported Stacks
152
152
 
153
- - Frontend: Next.js, Astro, SvelteKit, Nuxt, React, Vue, Svelte
154
- - Backend: Express, NestJS, Fastify, Koa
153
+ - Frontend: Next.js, Astro, SvelteKit, Nuxt, Remix, React Router v7, TanStack Router/Start, Expo Router, SolidStart, Qwik City, Angular, React, Vue, Svelte
154
+ - Backend: Express, NestJS, Fastify, Hono, Elysia, Koa, AdonisJS
155
155
 
156
156
  Detection covers the full list above; Next.js and Express receive the deepest
157
157
  analysis. Multi-package workspaces are classified per project type, so a
@@ -0,0 +1,4 @@
1
+ import type { ScannedFile } from "../analysis/index.js";
2
+ import type { RouteInfo } from "./routeDetector.js";
3
+ export declare function detectAdonisRoutes(files: ScannedFile[], graph?: Record<string, string[]>): RouteInfo[];
4
+ //# sourceMappingURL=adonisRouteDetector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adonisRouteDetector.d.ts","sourceRoot":"","sources":["../../../src/analyzers/detectors/adonisRouteDetector.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAOxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAsCpD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,EAAE,CA8GtG"}
@@ -0,0 +1,242 @@
1
+ import { ts } from "ts-morph";
2
+ import { isArchitectureSource } from "../graph/index.js";
3
+ import { importCallSpecifier, isChainTop, stringValue, unwindChain, unwrapExpression } from "./astUtils.js";
4
+ import { createModuleIndex, isShadowed, walkOutsideShadow } from "./moduleBindings.js";
5
+ import { joinRoutePaths, sortRoutes } from "./routeUtils.js";
6
+ /**
7
+ * AdonisJS declares every URL in `start/routes.ts` (or files it imports):
8
+ *
9
+ * router.get("/", [HomeController, "index"])
10
+ * router.group(() => { ... }).prefix("/api")
11
+ * router.resource("posts", PostsController).apiOnly()
12
+ * router.on("/").render("pages/home")
13
+ *
14
+ * Groups compose their prefix, `resource()` expands to the REST actions it
15
+ * registers (minus `apiOnly`, `only` and `except`), and the listed file is the
16
+ * controller that handles the route when it can be found.
17
+ */
18
+ const ROUTER_MODULES = new Set(["@adonisjs/core/services/router", "@ioc:Adonis/Core/Route"]);
19
+ const GATE = /@adonisjs\/core\/services\/router|@ioc:Adonis\/Core\/Route|\buse\(\s*["']Route["']\s*\)/;
20
+ const VERBS = new Map([
21
+ ["get", "GET"], ["post", "POST"], ["put", "PUT"], ["patch", "PATCH"], ["delete", "DELETE"], ["any", undefined]
22
+ ]);
23
+ const RESOURCE_ACTIONS = [
24
+ { name: "index", methods: ["GET"], path: "" },
25
+ { name: "create", methods: ["GET"], path: "/create" },
26
+ { name: "store", methods: ["POST"], path: "" },
27
+ { name: "show", methods: ["GET"], path: "/:id" },
28
+ { name: "edit", methods: ["GET"], path: "/:id/edit" },
29
+ { name: "update", methods: ["PATCH", "PUT"], path: "/:id" },
30
+ { name: "destroy", methods: ["DELETE"], path: "/:id" }
31
+ ];
32
+ // What a handler that answers with a page calls.
33
+ const PAGE_SIGNAL = /\b(?:view|inertia)\.render|\brenderInertia\b|\.view\.render|\bview\.make\b|\binertia\.render\b|<!doctype|<html\b|<body\b/i;
34
+ export function detectAdonisRoutes(files, graph) {
35
+ const gated = files.filter((file) => /\.[cm]?[jt]sx?$/.test(file.path) && isArchitectureSource(file.path) && GATE.test(file.content));
36
+ if (gated.length === 0)
37
+ return [];
38
+ const index = createModuleIndex(files, graph);
39
+ const routes = new Map();
40
+ const paths = files.map((file) => file.path);
41
+ for (const file of gated) {
42
+ const module = index.get(file.path);
43
+ if (!module)
44
+ continue;
45
+ // v6 / v5 import the router; v4 reads it from the container: `const Route = use("Route")`.
46
+ const names = new Set([...module.imports].filter(([, value]) => ROUTER_MODULES.has(value.specifier)).map(([name]) => name));
47
+ for (const [name, initializer] of module.variables) {
48
+ if (ts.isCallExpression(initializer) && ts.isIdentifier(initializer.expression) && initializer.expression.text === "use"
49
+ && stringValue(initializer.arguments[0]) === "Route") {
50
+ names.add(name);
51
+ }
52
+ }
53
+ if (names.size === 0)
54
+ continue;
55
+ const visit = (scope, base) => {
56
+ const step = (node) => {
57
+ if (!ts.isCallExpression(node) || !isChainTop(node))
58
+ return;
59
+ const { root, calls } = unwindChain(node);
60
+ if (calls.length === 0 || !ts.isIdentifier(root) || !names.has(root.text) || isShadowed(node, root.text))
61
+ return;
62
+ processChain(calls, base);
63
+ return false;
64
+ };
65
+ walkOutsideShadow(scope, undefined, step);
66
+ };
67
+ const emit = (base, path, methods, handler) => {
68
+ const full = joinRoutePaths(base, path);
69
+ const kind = handler.kind ?? classify(full, methods, handler.signal);
70
+ const sorted = methods ? [...methods].sort() : undefined;
71
+ routes.set(`${sorted?.join(",") ?? "*"} ${full} ${handler.file}`, {
72
+ path: full,
73
+ file: handler.file,
74
+ kind,
75
+ ...(sorted ? { methods: sorted } : {})
76
+ });
77
+ };
78
+ const processChain = (calls, base) => {
79
+ for (let i = 0; i < calls.length; i += 1) {
80
+ const call = calls[i];
81
+ let end = i + 1;
82
+ while (end < calls.length && !isPrimary(calls[end].name))
83
+ end += 1;
84
+ const modifiers = calls.slice(i + 1, end);
85
+ if (call.name === "group") {
86
+ const callback = call.args.find((arg) => ts.isArrowFunction(unwrapExpression(arg)) || ts.isFunctionExpression(unwrapExpression(arg)));
87
+ const prefix = modifiers.filter((item) => item.name === "prefix").map((item) => index.stringOf(item.args[0], module) ?? "").join("/");
88
+ const body = callback && unwrapExpression(callback).body;
89
+ if (body)
90
+ visit(body, joinRoutePaths(base, prefix));
91
+ }
92
+ else if (VERBS.has(call.name)) {
93
+ const path = index.stringOf(call.args[0], module);
94
+ if (path !== undefined) {
95
+ const method = VERBS.get(call.name);
96
+ emit(base, path, method ? [method] : undefined, handlerOf(call.args[1], module, index, paths));
97
+ }
98
+ }
99
+ else if (call.name === "route") {
100
+ const path = index.stringOf(call.args[0], module);
101
+ const methods = methodList(call.args[1]);
102
+ if (path !== undefined)
103
+ emit(base, path, methods, handlerOf(call.args[2], module, index, paths));
104
+ }
105
+ else if (call.name === "on") {
106
+ const path = index.stringOf(call.args[0], module);
107
+ const renders = modifiers.some((item) => item.name === "render" || item.name === "renderInertia");
108
+ if (path !== undefined && renders)
109
+ emit(base, path, ["GET"], { file: module.path, kind: "page" });
110
+ }
111
+ else if (call.name === "resource" || call.name === "shallowResource") {
112
+ expandResource(call, modifiers, base);
113
+ }
114
+ i = end - 1;
115
+ }
116
+ };
117
+ const expandResource = (call, modifiers, base) => {
118
+ const name = index.stringOf(call.args[0], module);
119
+ if (!name)
120
+ return;
121
+ const handler = handlerOf(call.args[1], module, index, paths);
122
+ const apiOnly = modifiers.some((item) => item.name === "apiOnly");
123
+ const only = modifiers.find((item) => item.name === "only");
124
+ const except = modifiers.find((item) => item.name === "except");
125
+ const listed = (item) => new Set(arrayStrings(item?.args[0]));
126
+ const segments = name.split(".");
127
+ const prefix = segments.map((segment, position) => position === segments.length - 1 ? segment : `${segment}/:${singular(segment)}_id`).join("/");
128
+ for (const action of RESOURCE_ACTIONS) {
129
+ if (apiOnly && (action.name === "create" || action.name === "edit"))
130
+ continue;
131
+ if (only && !listed(only).has(action.name))
132
+ continue;
133
+ if (except && listed(except).has(action.name))
134
+ continue;
135
+ const signal = handler.controller ? methodSignal(handler.controller, action.name, index) : handler.signal;
136
+ const kind = apiOnly ? "api" : action.name === "create" || action.name === "edit" ? "page" : undefined;
137
+ emit(base, `${prefix}${action.path}`, action.methods, { ...handler, signal, ...(kind ? { kind } : {}) });
138
+ }
139
+ };
140
+ visit(module.source, "/");
141
+ }
142
+ return sortRoutes([...routes.values()]);
143
+ }
144
+ const PRIMARY = new Set([...VERBS.keys(), "route", "on", "resource", "shallowResource", "group"]);
145
+ function isPrimary(name) {
146
+ return PRIMARY.has(name);
147
+ }
148
+ /** Where a route is handled: `[Controller, "method"]`, `"#controllers/x.method"`, a class, or a closure. */
149
+ function handlerOf(expression, module, index, paths) {
150
+ const fallback = { file: module.path };
151
+ if (!expression)
152
+ return fallback;
153
+ const node = unwrapExpression(expression);
154
+ if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
155
+ return { ...fallback, signal: PAGE_SIGNAL.test(node.getText()) };
156
+ }
157
+ let target;
158
+ let method;
159
+ if (ts.isArrayLiteralExpression(node) && node.elements[0]) {
160
+ target = unwrapExpression(node.elements[0]);
161
+ method = node.elements[1] ? stringValue(unwrapExpression(node.elements[1])) : undefined;
162
+ }
163
+ else if (ts.isIdentifier(node)) {
164
+ target = node;
165
+ }
166
+ let file;
167
+ if (target && ts.isIdentifier(target)) {
168
+ file = controllerFile(target.text, module, index);
169
+ }
170
+ else if (target) {
171
+ const specifier = importCallSpecifier(target);
172
+ file = specifier ? index.resolveSpecifier(module.path, specifier) : undefined;
173
+ }
174
+ const text = target === undefined ? stringValue(node) : undefined;
175
+ if (text !== undefined) {
176
+ // "#controllers/users_controller.index" (v6) or "UsersController.index" (v5)
177
+ const [controllerPath, action] = splitHandlerString(text);
178
+ method = action;
179
+ file = controllerPath.startsWith("#") || controllerPath.startsWith(".")
180
+ ? index.resolveSpecifier(module.path, controllerPath)
181
+ : paths.find((path) => /(?:^|\/)Controllers\//.test(path) && new RegExp(`/${escapeSlash(controllerPath)}\\.[cm]?[jt]s$`).test(path));
182
+ }
183
+ const controller = file ? index.get(file) : undefined;
184
+ if (!file || !controller)
185
+ return fallback;
186
+ return { file, controller, signal: method ? methodSignal(controller, method, index) : PAGE_SIGNAL.test(controller.source.text) };
187
+ }
188
+ function controllerFile(name, module, index) {
189
+ const lazy = module.variables.get(name);
190
+ const specifier = lazy ? importCallSpecifier(lazy) : undefined;
191
+ if (specifier)
192
+ return index.resolveSpecifier(module.path, specifier);
193
+ const imported = module.imports.get(name);
194
+ return imported ? index.resolveSpecifier(module.path, imported.specifier) : undefined;
195
+ }
196
+ function splitHandlerString(text) {
197
+ const match = /^(.*[^./])\.(\w+)$/.exec(text);
198
+ return match && !match[1].endsWith("/") ? [match[1], match[2]] : [text, undefined];
199
+ }
200
+ function escapeSlash(value) {
201
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
202
+ }
203
+ /** Does the controller action `method` render a page? Falls back to the whole file. */
204
+ function methodSignal(controller, method, _index) {
205
+ let text;
206
+ const visit = (node) => {
207
+ if (text !== undefined)
208
+ return;
209
+ if (ts.isMethodDeclaration(node) && ts.isIdentifier(node.name) && node.name.text === method) {
210
+ text = node.getText();
211
+ return;
212
+ }
213
+ ts.forEachChild(node, visit);
214
+ };
215
+ visit(controller.source);
216
+ return PAGE_SIGNAL.test(text ?? controller.source.text);
217
+ }
218
+ function classify(path, methods, signal) {
219
+ if (/^\/api(?:\/|$)/.test(path))
220
+ return "api";
221
+ if (methods && methods.some((method) => method !== "GET"))
222
+ return "api";
223
+ return signal ? "page" : "api";
224
+ }
225
+ function methodList(expression) {
226
+ const methods = arrayStrings(expression).map((method) => method.toUpperCase());
227
+ return methods.length > 0 ? methods : undefined;
228
+ }
229
+ function arrayStrings(expression) {
230
+ const node = expression ? unwrapExpression(expression) : undefined;
231
+ if (!node || !ts.isArrayLiteralExpression(node))
232
+ return [];
233
+ return node.elements.flatMap((element) => stringValue(unwrapExpression(element)) ?? []);
234
+ }
235
+ function singular(name) {
236
+ if (/ies$/.test(name))
237
+ return `${name.slice(0, -3)}y`;
238
+ if (/(?:ss|us)$/.test(name))
239
+ return name;
240
+ return name.replace(/s$/, "");
241
+ }
242
+ //# sourceMappingURL=adonisRouteDetector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adonisRouteDetector.js","sourceRoot":"","sources":["../../../src/analyzers/detectors/adonisRouteDetector.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 detectAngularRoutes(files: ScannedFile[], graph?: Record<string, string[]>): RouteInfo[];
4
+ //# sourceMappingURL=angularRouteDetector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"angularRouteDetector.d.ts","sourceRoot":"","sources":["../../../src/analyzers/detectors/angularRouteDetector.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAIxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAgCpD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,EAAE,CAuHvG"}
@@ -0,0 +1,186 @@
1
+ import { ts } from "ts-morph";
2
+ import { isArchitectureSource } from "../graph/index.js";
3
+ import { importCallSpecifier, propertyKeyName, unwrapExpression, walk } from "./astUtils.js";
4
+ import { createModuleIndex } from "./moduleBindings.js";
5
+ import { dropShadowedLayouts, joinRoutePaths, sortRoutes } from "./routeUtils.js";
6
+ /**
7
+ * Angular routes are arrays of `{ path, component }` objects:
8
+ *
9
+ * export const routes: Routes = [
10
+ * { path: "", component: HomeComponent },
11
+ * { path: "users/:id", loadComponent: () => import("./user").then((m) => m.UserComponent) },
12
+ * { path: "admin", loadChildren: () => import("./admin/admin.routes").then((m) => m.ADMIN_ROUTES) },
13
+ * { path: "docs", component: DocsShell, children: [{ path: "intro", component: Intro }] },
14
+ * { path: "old", redirectTo: "new" },
15
+ * { path: "**", component: NotFound }
16
+ * ];
17
+ *
18
+ * `children` and `loadChildren` (a routes file, or an NgModule whose routing
19
+ * module calls `RouterModule.forChild`) compose their path onto the parent's.
20
+ * Redirects render nothing and are not listed; a shell route with an empty
21
+ * path gives way to the index route at the same URL. The listed file is the
22
+ * component, resolved through its import or lazy `import()`.
23
+ */
24
+ const ROUTER_MODULE = /["']@angular\/router["']/;
25
+ const HINT_KEYS = new Set([
26
+ "component", "loadComponent", "loadChildren", "children", "redirectTo",
27
+ "canActivate", "canActivateChild", "canMatch", "canDeactivate", "resolve", "title", "data", "pathMatch", "outlet"
28
+ ]);
29
+ export function detectAngularRoutes(files, graph) {
30
+ const gated = files.filter((file) => /\.ts$/.test(file.path) && isArchitectureSource(file.path) && ROUTER_MODULE.test(file.content));
31
+ if (gated.length === 0)
32
+ return [];
33
+ const index = createModuleIndex(files, graph);
34
+ const cache = new Map();
35
+ /** Route arrays declared in a file. Lazy route files often skip the `@angular/router` import, so any file can be asked. */
36
+ const arraysIn = (path) => {
37
+ const cached = cache.get(path);
38
+ if (cached)
39
+ return cached;
40
+ const found = [];
41
+ const module = /\.ts$/.test(path) ? index.get(path) : undefined;
42
+ if (module) {
43
+ walk(module.source, (node) => {
44
+ if (ts.isArrayLiteralExpression(node) && looksLikeRoutes(node) && !isChildrenOfRoute(node)) {
45
+ found.push({ module, node, name: declaredName(node) });
46
+ }
47
+ });
48
+ }
49
+ cache.set(path, found);
50
+ return found;
51
+ };
52
+ const arrays = new Map(gated.map((file) => [file.path, arraysIn(file.path)]).filter(([, list]) => list.length > 0));
53
+ /** Route arrays a `loadChildren` loads: the named export, else the file's arrays, else its routing module's. */
54
+ const lazyTargets = (module, loader) => {
55
+ const specifier = importCallSpecifier(loader);
56
+ const target = specifier ? index.resolveSpecifier(module.path, specifier) : undefined;
57
+ if (!target)
58
+ return [];
59
+ const member = memberName(loader);
60
+ const pick = (path) => {
61
+ const here = arraysIn(path);
62
+ const named = member && member !== "default" ? here.filter((entry) => entry.name === member) : [];
63
+ return named.length > 0 ? named : here;
64
+ };
65
+ const direct = pick(target);
66
+ if (direct.length > 0)
67
+ return direct;
68
+ return (graph?.[target] ?? []).flatMap(pick);
69
+ };
70
+ // Arrays that some route loads lazily are walked from there, with their prefix.
71
+ const lazy = new Set();
72
+ for (const list of arrays.values()) {
73
+ for (const entry of list) {
74
+ walk(entry.node, (node) => {
75
+ if (!ts.isObjectLiteralExpression(node))
76
+ return;
77
+ const loader = propertyValue(node, "loadChildren");
78
+ if (loader)
79
+ for (const target of lazyTargets(entry.module, loader))
80
+ lazy.add(target.node);
81
+ });
82
+ }
83
+ }
84
+ const entries = [];
85
+ const stack = new Set();
86
+ const locate = (module, component, loader) => {
87
+ const specifier = loader
88
+ ? importCallSpecifier(loader)
89
+ : component && ts.isIdentifier(unwrapExpression(component))
90
+ ? module.imports.get(unwrapExpression(component).text)?.specifier
91
+ : undefined;
92
+ return (specifier ? index.resolveSpecifier(module.path, specifier) : undefined) ?? module.path;
93
+ };
94
+ const walkArray = (module, array, base) => {
95
+ if (stack.has(array))
96
+ return;
97
+ stack.add(array);
98
+ for (const element of array.elements) {
99
+ const item = unwrapExpression(element);
100
+ if (!ts.isObjectLiteralExpression(item))
101
+ continue;
102
+ const path = index.stringOf(propertyValue(item, "path"), module);
103
+ if (path === undefined)
104
+ continue;
105
+ const full = path === "" ? base : joinRoutePaths(base, path);
106
+ const component = propertyValue(item, "component");
107
+ const loadComponent = propertyValue(item, "loadComponent");
108
+ const children = propertyValue(item, "children");
109
+ const loadChildren = propertyValue(item, "loadChildren");
110
+ const hasChildren = Boolean(children || loadChildren);
111
+ if (component || loadComponent) {
112
+ entries.push({
113
+ path: full,
114
+ file: locate(module, component, loadComponent),
115
+ isIndex: path === "" && !hasChildren,
116
+ isLayout: hasChildren
117
+ });
118
+ }
119
+ if (children && ts.isArrayLiteralExpression(unwrapExpression(children))) {
120
+ walkArray(module, unwrapExpression(children), full);
121
+ }
122
+ if (loadChildren) {
123
+ for (const target of lazyTargets(module, loadChildren))
124
+ walkArray(target.module, target.node, full);
125
+ }
126
+ }
127
+ stack.delete(array);
128
+ };
129
+ for (const list of arrays.values()) {
130
+ for (const entry of list) {
131
+ if (!lazy.has(entry.node))
132
+ walkArray(entry.module, entry.node, "/");
133
+ }
134
+ }
135
+ const unique = new Map();
136
+ for (const entry of dropShadowedLayouts(entries))
137
+ unique.set(`${entry.path}\0${entry.file}`, entry);
138
+ return sortRoutes([...unique.values()].map((entry) => ({ path: entry.path, file: entry.file, kind: "page" })));
139
+ }
140
+ function propertyValue(node, key) {
141
+ for (const property of node.properties) {
142
+ if (ts.isPropertyAssignment(property) && propertyKeyName(property.name) === key) {
143
+ return unwrapExpression(property.initializer);
144
+ }
145
+ }
146
+ return undefined;
147
+ }
148
+ /** An array holding at least one `{ path: "...", <route key> }` object. */
149
+ function looksLikeRoutes(array) {
150
+ return array.elements.some((element) => {
151
+ const item = unwrapExpression(element);
152
+ if (!ts.isObjectLiteralExpression(item) || propertyValue(item, "path") === undefined)
153
+ return false;
154
+ return item.properties.some((property) => (ts.isPropertyAssignment(property) || ts.isShorthandPropertyAssignment(property))
155
+ && HINT_KEYS.has(propertyKeyName(property.name) ?? ""));
156
+ });
157
+ }
158
+ function isChildrenOfRoute(array) {
159
+ const parent = array.parent;
160
+ return ts.isPropertyAssignment(parent) && propertyKeyName(parent.name) === "children";
161
+ }
162
+ /** `export const ADMIN_ROUTES: Routes = [...]` */
163
+ function declaredName(array) {
164
+ let parent = array.parent;
165
+ while (ts.isAsExpression(parent) || ts.isSatisfiesExpression(parent) || ts.isParenthesizedExpression(parent))
166
+ parent = parent.parent;
167
+ return ts.isVariableDeclaration(parent) && ts.isIdentifier(parent.name) ? parent.name.text : undefined;
168
+ }
169
+ /** `() => import("./x").then((m) => m.ADMIN_ROUTES)` → `ADMIN_ROUTES`. */
170
+ function memberName(loader) {
171
+ let found;
172
+ walk(loader, (node) => {
173
+ if (found || !ts.isArrowFunction(node) || node.parameters.length !== 1)
174
+ return;
175
+ const parameter = node.parameters[0].name;
176
+ const body = unwrapExpression(node.body);
177
+ if (ts.isIdentifier(parameter)
178
+ && ts.isPropertyAccessExpression(body)
179
+ && ts.isIdentifier(body.expression)
180
+ && body.expression.text === parameter.text) {
181
+ found = body.name.text;
182
+ }
183
+ });
184
+ return found;
185
+ }
186
+ //# sourceMappingURL=angularRouteDetector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"angularRouteDetector.js","sourceRoot":"","sources":["../../../src/analyzers/detectors/angularRouteDetector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { ts } from "ts-morph";
2
+ /** Parse one source file without building a ts-morph Project. */
3
+ export declare function parseSource(path: string, content: string): ts.SourceFile;
4
+ /** The text of a plain string or an interpolation-free template literal. */
5
+ export declare function stringValue(node: ts.Node | undefined): string | undefined;
6
+ /** Strip `( )`, `as T`, `satisfies T`, `x!` and `await` wrappers. */
7
+ export declare function unwrapExpression(node: ts.Expression): ts.Expression;
8
+ export declare function walk(node: ts.Node, visit: (node: ts.Node) => void): void;
9
+ /** Name of a property key written as an identifier or a string. */
10
+ export declare function propertyKeyName(name: ts.PropertyName): string | undefined;
11
+ /** `() => import("./x")` or `import("./x")`: the specifier of the first dynamic import inside. */
12
+ export declare function importCallSpecifier(expression: ts.Node): string | undefined;
13
+ export type ChainCall = {
14
+ name: string;
15
+ args: readonly ts.Expression[];
16
+ node: ts.CallExpression;
17
+ };
18
+ /**
19
+ * Unwind `root.a(x).b(y)` into the root expression and the calls in source
20
+ * order. A call whose callee is not `something.name` ends the chain, and the
21
+ * expression holding it is the root.
22
+ */
23
+ export declare function unwindChain(expression: ts.Expression): {
24
+ root: ts.Expression;
25
+ calls: ChainCall[];
26
+ };
27
+ /** The outermost call of a chain: the parent is not another call on its result. */
28
+ export declare function isChainTop(node: ts.CallExpression): boolean;
29
+ /** A route path written as a plain string. */
30
+ export declare function pathArgument(node: ts.Expression | undefined): string | undefined;
31
+ //# sourceMappingURL=astUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"astUtils.d.ts","sourceRoot":"","sources":["../../../src/analyzers/detectors/astUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAE9B,iEAAiE;AACjE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC,UAAU,CASxE;AAED,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAKzE;AAED,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,GAAG,EAAE,CAAC,UAAU,CAgBnE;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,IAAI,GAAG,IAAI,CAGxE;AAED,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,GAAG,MAAM,GAAG,SAAS,CAKzE;AAED,kGAAkG;AAClG,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,GAAG,MAAM,GAAG,SAAS,CAY3E;AAED,MAAM,MAAM,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,SAAS,EAAE,CAAC,UAAU,EAAE,CAAC;IAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAA;CAAE,CAAC;AAElG;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG;IAAE,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC;IAAC,KAAK,EAAE,SAAS,EAAE,CAAA;CAAE,CAUlG;AAED,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,GAAG,OAAO,CAQ3D;AAED,8CAA8C;AAC9C,wBAAgB,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAEhF"}
@@ -0,0 +1,85 @@
1
+ import { ts } from "ts-morph";
2
+ /** Parse one source file without building a ts-morph Project. */
3
+ export function parseSource(path, content) {
4
+ const kind = /\.tsx$/.test(path)
5
+ ? ts.ScriptKind.TSX
6
+ : /\.jsx$/.test(path)
7
+ ? ts.ScriptKind.JSX
8
+ : /\.[cm]?js$/.test(path)
9
+ ? ts.ScriptKind.JS
10
+ : ts.ScriptKind.TS;
11
+ return ts.createSourceFile(path, content, ts.ScriptTarget.Latest, true, kind);
12
+ }
13
+ /** The text of a plain string or an interpolation-free template literal. */
14
+ export function stringValue(node) {
15
+ if (node && (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node))) {
16
+ return node.text;
17
+ }
18
+ return undefined;
19
+ }
20
+ /** Strip `( )`, `as T`, `satisfies T`, `x!` and `await` wrappers. */
21
+ export function unwrapExpression(node) {
22
+ let current = node;
23
+ for (;;) {
24
+ if (ts.isParenthesizedExpression(current)
25
+ || ts.isAsExpression(current)
26
+ || ts.isSatisfiesExpression(current)
27
+ || ts.isNonNullExpression(current)
28
+ || ts.isAwaitExpression(current)
29
+ || ts.isTypeAssertionExpression(current)) {
30
+ current = current.expression;
31
+ continue;
32
+ }
33
+ return current;
34
+ }
35
+ }
36
+ export function walk(node, visit) {
37
+ visit(node);
38
+ ts.forEachChild(node, (child) => walk(child, visit));
39
+ }
40
+ /** Name of a property key written as an identifier or a string. */
41
+ export function propertyKeyName(name) {
42
+ if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNoSubstitutionTemplateLiteral(name)) {
43
+ return name.text;
44
+ }
45
+ return undefined;
46
+ }
47
+ /** `() => import("./x")` or `import("./x")`: the specifier of the first dynamic import inside. */
48
+ export function importCallSpecifier(expression) {
49
+ let found;
50
+ walk(expression, (node) => {
51
+ if (found === undefined
52
+ && ts.isCallExpression(node)
53
+ && node.expression.kind === ts.SyntaxKind.ImportKeyword) {
54
+ found = stringValue(node.arguments[0]);
55
+ }
56
+ });
57
+ return found;
58
+ }
59
+ /**
60
+ * Unwind `root.a(x).b(y)` into the root expression and the calls in source
61
+ * order. A call whose callee is not `something.name` ends the chain, and the
62
+ * expression holding it is the root.
63
+ */
64
+ export function unwindChain(expression) {
65
+ const calls = [];
66
+ let current = unwrapExpression(expression);
67
+ while (ts.isCallExpression(current) && ts.isPropertyAccessExpression(current.expression)) {
68
+ calls.push({ name: current.expression.name.text, args: current.arguments, node: current });
69
+ current = unwrapExpression(current.expression.expression);
70
+ }
71
+ return { root: current, calls: calls.reverse() };
72
+ }
73
+ /** The outermost call of a chain: the parent is not another call on its result. */
74
+ export function isChainTop(node) {
75
+ const parent = node.parent;
76
+ return !(ts.isPropertyAccessExpression(parent)
77
+ && parent.expression === node
78
+ && ts.isCallExpression(parent.parent)
79
+ && parent.parent.expression === parent);
80
+ }
81
+ /** A route path written as a plain string. */
82
+ export function pathArgument(node) {
83
+ return node ? stringValue(unwrapExpression(node)) : undefined;
84
+ }
85
+ //# sourceMappingURL=astUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"astUtils.js","sourceRoot":"","sources":["../../../src/analyzers/detectors/astUtils.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 detectClientRoutes(files: ScannedFile[], graph?: Record<string, string[]>): RouteInfo[];
4
+ //# sourceMappingURL=clientRouteDetector.d.ts.map