@flaid/devmap 0.7.0 → 0.8.1

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 (105) hide show
  1. package/README.md +13 -2
  2. package/dist/analyzers/analysis/extractors/fallbackExtractor.d.ts.map +1 -1
  3. package/dist/analyzers/analysis/extractors/fallbackExtractor.js +15 -0
  4. package/dist/analyzers/analysis/extractors/fallbackExtractor.js.map +1 -1
  5. package/dist/analyzers/detectors/adonisRouteDetector.d.ts +4 -0
  6. package/dist/analyzers/detectors/adonisRouteDetector.d.ts.map +1 -0
  7. package/dist/analyzers/detectors/adonisRouteDetector.js +242 -0
  8. package/dist/analyzers/detectors/adonisRouteDetector.js.map +1 -0
  9. package/dist/analyzers/detectors/angularRouteDetector.d.ts +4 -0
  10. package/dist/analyzers/detectors/angularRouteDetector.d.ts.map +1 -0
  11. package/dist/analyzers/detectors/angularRouteDetector.js +186 -0
  12. package/dist/analyzers/detectors/angularRouteDetector.js.map +1 -0
  13. package/dist/analyzers/detectors/astUtils.d.ts +20 -0
  14. package/dist/analyzers/detectors/astUtils.d.ts.map +1 -1
  15. package/dist/analyzers/detectors/astUtils.js +38 -0
  16. package/dist/analyzers/detectors/astUtils.js.map +1 -1
  17. package/dist/analyzers/detectors/capabilityDetector.d.ts.map +1 -1
  18. package/dist/analyzers/detectors/capabilityDetector.js +3 -0
  19. package/dist/analyzers/detectors/capabilityDetector.js.map +1 -1
  20. package/dist/analyzers/detectors/clientRouteDetector.d.ts +4 -0
  21. package/dist/analyzers/detectors/clientRouteDetector.d.ts.map +1 -0
  22. package/dist/analyzers/detectors/clientRouteDetector.js +417 -0
  23. package/dist/analyzers/detectors/clientRouteDetector.js.map +1 -0
  24. package/dist/analyzers/detectors/elysiaRouteDetector.d.ts +4 -0
  25. package/dist/analyzers/detectors/elysiaRouteDetector.d.ts.map +1 -0
  26. package/dist/analyzers/detectors/elysiaRouteDetector.js +186 -0
  27. package/dist/analyzers/detectors/elysiaRouteDetector.js.map +1 -0
  28. package/dist/analyzers/detectors/frameworkDetector.d.ts +2 -2
  29. package/dist/analyzers/detectors/frameworkDetector.d.ts.map +1 -1
  30. package/dist/analyzers/detectors/frameworkDetector.js +29 -1
  31. package/dist/analyzers/detectors/frameworkDetector.js.map +1 -1
  32. package/dist/analyzers/detectors/frontendFeatureDetector.d.ts +3 -0
  33. package/dist/analyzers/detectors/frontendFeatureDetector.d.ts.map +1 -1
  34. package/dist/analyzers/detectors/frontendFeatureDetector.js +61 -13
  35. package/dist/analyzers/detectors/frontendFeatureDetector.js.map +1 -1
  36. package/dist/analyzers/detectors/honoRouteDetector.d.ts.map +1 -1
  37. package/dist/analyzers/detectors/honoRouteDetector.js +230 -82
  38. package/dist/analyzers/detectors/honoRouteDetector.js.map +1 -1
  39. package/dist/analyzers/detectors/koaRouteDetector.d.ts +4 -0
  40. package/dist/analyzers/detectors/koaRouteDetector.d.ts.map +1 -0
  41. package/dist/analyzers/detectors/koaRouteDetector.js +216 -0
  42. package/dist/analyzers/detectors/koaRouteDetector.js.map +1 -0
  43. package/dist/analyzers/detectors/moduleBindings.d.ts +52 -0
  44. package/dist/analyzers/detectors/moduleBindings.d.ts.map +1 -0
  45. package/dist/analyzers/detectors/moduleBindings.js +295 -0
  46. package/dist/analyzers/detectors/moduleBindings.js.map +1 -0
  47. package/dist/analyzers/detectors/nonResourceSegments.d.ts +9 -0
  48. package/dist/analyzers/detectors/nonResourceSegments.d.ts.map +1 -0
  49. package/dist/analyzers/detectors/nonResourceSegments.js +22 -0
  50. package/dist/analyzers/detectors/nonResourceSegments.js.map +1 -0
  51. package/dist/analyzers/detectors/qwikRouteDetector.d.ts +4 -0
  52. package/dist/analyzers/detectors/qwikRouteDetector.d.ts.map +1 -0
  53. package/dist/analyzers/detectors/qwikRouteDetector.js +53 -0
  54. package/dist/analyzers/detectors/qwikRouteDetector.js.map +1 -0
  55. package/dist/analyzers/detectors/routeDetector.d.ts.map +1 -1
  56. package/dist/analyzers/detectors/routeDetector.js +46 -5
  57. package/dist/analyzers/detectors/routeDetector.js.map +1 -1
  58. package/dist/analyzers/detectors/routeUtils.d.ts +15 -1
  59. package/dist/analyzers/detectors/routeUtils.d.ts.map +1 -1
  60. package/dist/analyzers/detectors/routeUtils.js +51 -0
  61. package/dist/analyzers/detectors/routeUtils.js.map +1 -1
  62. package/dist/analyzers/detectors/solidStartRouteDetector.d.ts +4 -0
  63. package/dist/analyzers/detectors/solidStartRouteDetector.d.ts.map +1 -0
  64. package/dist/analyzers/detectors/solidStartRouteDetector.js +59 -0
  65. package/dist/analyzers/detectors/solidStartRouteDetector.js.map +1 -0
  66. package/dist/analyzers/features/featureCandidates.d.ts +6 -0
  67. package/dist/analyzers/features/featureCandidates.d.ts.map +1 -1
  68. package/dist/analyzers/features/featureCandidates.js +48 -1
  69. package/dist/analyzers/features/featureCandidates.js.map +1 -1
  70. package/dist/analyzers/features/featureDetector.d.ts.map +1 -1
  71. package/dist/analyzers/features/featureDetector.js +69 -13
  72. package/dist/analyzers/features/featureDetector.js.map +1 -1
  73. package/dist/analyzers/graph/entryPoints.d.ts.map +1 -1
  74. package/dist/analyzers/graph/entryPoints.js +13 -1
  75. package/dist/analyzers/graph/entryPoints.js.map +1 -1
  76. package/dist/analyzers/graph/sourceScope.d.ts.map +1 -1
  77. package/dist/analyzers/graph/sourceScope.js +3 -0
  78. package/dist/analyzers/graph/sourceScope.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 +5 -0
  83. package/dist/analyzers/pipeline/projectMetadata.js.map +1 -1
  84. package/dist/analyzers/registry/analytics.js +1 -1
  85. package/dist/analyzers/registry/analytics.js.map +1 -1
  86. package/dist/analyzers/registry/background-jobs.d.ts.map +1 -1
  87. package/dist/analyzers/registry/background-jobs.js +2 -0
  88. package/dist/analyzers/registry/background-jobs.js.map +1 -1
  89. package/dist/analyzers/registry/cms-content.d.ts.map +1 -1
  90. package/dist/analyzers/registry/cms-content.js +2 -1
  91. package/dist/analyzers/registry/cms-content.js.map +1 -1
  92. package/dist/analyzers/registry/file-upload.d.ts.map +1 -1
  93. package/dist/analyzers/registry/file-upload.js +2 -1
  94. package/dist/analyzers/registry/file-upload.js.map +1 -1
  95. package/dist/analyzers/registry/index.d.ts +2 -0
  96. package/dist/analyzers/registry/index.d.ts.map +1 -1
  97. package/dist/analyzers/registry/index.js +4 -0
  98. package/dist/analyzers/registry/index.js.map +1 -1
  99. package/dist/analyzers/registry/notifications.js +1 -1
  100. package/dist/analyzers/registry/notifications.js.map +1 -1
  101. package/dist/analyzers/registry/search.js +1 -1
  102. package/dist/analyzers/registry/search.js.map +1 -1
  103. package/dist/analyzers/registry/types.d.ts +5 -0
  104. package/dist/analyzers/registry/types.d.ts.map +1 -1
  105. package/package.json +15 -4
package/README.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # DevMap
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@flaid/devmap)](https://www.npmjs.com/package/@flaid/devmap)
4
+ [![license](https://img.shields.io/npm/l/@flaid/devmap)](https://github.com/itsflaid/devmap/blob/main/LICENSE)
5
+ [![node](https://img.shields.io/node/v/@flaid/devmap)](https://nodejs.org)
6
+
7
+ **Analyze once. Reuse context everywhere.** A CLI that maps your codebase for
8
+ developers and AI agents: entry points, critical files, features and routes.
9
+
10
+ [Documentation](https://devmap-web.vercel.app/docs) ·
11
+ [Website](https://devmap-web.vercel.app) ·
12
+ [GitHub](https://github.com/itsflaid/devmap)
13
+
3
14
  Every new AI chat about your code starts from zero — you re-explain
4
15
  the same codebase every time. DevMap fixes that.
5
16
 
@@ -150,8 +161,8 @@ terminal decoration, or streamed partial output.
150
161
 
151
162
  ## Supported Stacks
152
163
 
153
- - Frontend: Next.js, Astro, SvelteKit, Nuxt, Remix, React Router v7, TanStack Router/Start, Expo Router, React, Vue, Svelte
154
- - Backend: Express, NestJS, Fastify, Hono, Koa
164
+ - Frontend: Next.js, Astro, SvelteKit, Nuxt, Remix, React Router v7, TanStack Router/Start, Expo Router, SolidStart, Qwik City, Angular, React, Vue, Svelte
165
+ - Backend: Express, NestJS, Fastify, Hono, Elysia, Koa, AdonisJS
155
166
 
156
167
  Detection covers the full list above; Next.js and Express receive the deepest
157
168
  analysis. Multi-package workspaces are classified per project type, so a
@@ -1 +1 @@
1
- {"version":3,"file":"fallbackExtractor.d.ts","sourceRoot":"","sources":["../../../../src/analyzers/analysis/extractors/fallbackExtractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAsCtE;;;;;;;;;;;GAWG;AACH,qBAAa,sBAAuB,YAAW,uBAAuB;IACpE,QAAQ,CAAC,IAAI,oBAAoB;IAEjC,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,UAAU,EAAE;CAoC3C;AAMD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA4BhD"}
1
+ {"version":3,"file":"fallbackExtractor.d.ts","sourceRoot":"","sources":["../../../../src/analyzers/analysis/extractors/fallbackExtractor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAkDtE;;;;;;;;;;;GAWG;AACH,qBAAa,sBAAuB,YAAW,uBAAuB;IACpE,QAAQ,CAAC,IAAI,oBAAoB;IAEjC,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,UAAU,EAAE;CAqC3C;AAMD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA4BhD"}
@@ -1,3 +1,4 @@
1
+ import { isOperationalSegment } from "../../detectors/nonResourceSegments.js";
1
2
  // ---------------------------------------------------------------------------
2
3
  // Constants
3
4
  // ---------------------------------------------------------------------------
@@ -26,6 +27,18 @@ const IRREGULAR_SINGULAR = new Map([
26
27
  ["feet", "foot"],
27
28
  ["mice", "mouse"],
28
29
  ["geese", "goose"],
30
+ // Plural-looking words that are already the singular name of a page or resource.
31
+ ["settings", "settings"],
32
+ ["analytics", "analytics"],
33
+ ["metrics", "metrics"],
34
+ ["statistics", "statistics"],
35
+ ["news", "news"],
36
+ ["series", "series"],
37
+ ["species", "species"],
38
+ ["status", "status"],
39
+ ["analysis", "analysis"],
40
+ ["bonus", "bonus"],
41
+ ["campus", "campus"],
29
42
  ]);
30
43
  // ---------------------------------------------------------------------------
31
44
  // Extractor
@@ -67,6 +80,8 @@ export class RouteFallbackExtractor {
67
80
  // Skip common non-entity prefixes
68
81
  if (ROUTE_NON_ENTITY_SEGMENTS.has(segment.toLowerCase()))
69
82
  continue;
83
+ if (isOperationalSegment(segment))
84
+ continue;
70
85
  entityNames.add(singularize(segment));
71
86
  prevWasDynamic = false;
72
87
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fallbackExtractor.js","sourceRoot":"","sources":["../../../../src/analyzers/analysis/extractors/fallbackExtractor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fallbackExtractor.js","sourceRoot":"","sources":["../../../../src/analyzers/analysis/extractors/fallbackExtractor.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 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":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAE9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAe,gBAAgB,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC1G,OAAO,EAAE,iBAAiB,EAAmB,MAAM,qBAAqB,CAAC;AAEzE,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElF;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,aAAa,GAAG,0BAA0B,CAAC;AACjD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;IACxB,WAAW,EAAE,eAAe,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY;IACtE,aAAa,EAAE,kBAAkB,EAAE,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ;CAClH,CAAC,CAAC;AAMH,MAAM,UAAU,mBAAmB,CAAC,KAAoB,EAAE,KAAgC;IACxF,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAClC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAClG,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElC,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAwB,CAAC;IAE9C,2HAA2H;IAC3H,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAgB,EAAE;QAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAC1B,MAAM,KAAK,GAAiB,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAChE,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;gBAC3B,IAAI,EAAE,CAAC,wBAAwB,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC3F,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACzD,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvB,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,IAAI,GAAG,CACpB,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAA2B,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CACtH,CAAC;IAEF,gHAAgH;IAChH,MAAM,WAAW,GAAG,CAAC,MAAkB,EAAE,MAAqB,EAAgB,EAAE;QAC9E,MAAM,SAAS,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACtF,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,CAAC;QAEvB,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,CAAC,IAAY,EAAgB,EAAE;YAC1C,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC5B,MAAM,KAAK,GAAG,MAAM,IAAI,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAClG,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;QACzC,CAAC,CAAC;QAEF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5B,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,MAAM,CAAC;QACrC,OAAO,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC,CAAC;IAEF,gFAAgF;IAChF,MAAM,IAAI,GAAG,IAAI,GAAG,EAA6B,CAAC;IAClD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;QACnC,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE;gBACxB,IAAI,CAAC,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC;oBAAE,OAAO;gBAChD,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;gBACnD,IAAI,MAAM;oBAAE,KAAK,MAAM,MAAM,IAAI,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC;wBAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC5F,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAY,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,IAAI,GAAG,EAA6B,CAAC;IAEnD,MAAM,MAAM,GAAG,CAAC,MAAkB,EAAE,SAAoC,EAAE,MAAiC,EAAU,EAAE;QACrH,MAAM,SAAS,GAAG,MAAM;YACtB,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC;YAC7B,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,YAAY,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;gBACzD,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAE,gBAAgB,CAAC,SAAS,CAAmB,CAAC,IAAI,CAAC,EAAE,SAAS;gBACpF,CAAC,CAAC,SAAS,CAAC;QAChB,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC;IACjG,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,CAAC,MAAkB,EAAE,KAAgC,EAAE,IAAY,EAAQ,EAAE;QAC7F,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,OAAO;QAC7B,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAEjB,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACrC,MAAM,IAAI,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;YACvC,IAAI,CAAC,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC;gBAAE,SAAS;YAElD,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;YACjE,IAAI,IAAI,KAAK,SAAS;gBAAE,SAAS;YACjC,MAAM,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAE7D,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YACnD,MAAM,aAAa,GAAG,aAAa,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;YAC3D,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YACjD,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;YACzD,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,IAAI,YAAY,CAAC,CAAC;YAEtD,IAAI,SAAS,IAAI,aAAa,EAAE,CAAC;gBAC/B,OAAO,CAAC,IAAI,CAAC;oBACX,IAAI,EAAE,IAAI;oBACV,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,CAAC;oBAC9C,OAAO,EAAE,IAAI,KAAK,EAAE,IAAI,CAAC,WAAW;oBACpC,QAAQ,EAAE,WAAW;iBACtB,CAAC,CAAC;YACL,CAAC;YAED,IAAI,QAAQ,IAAI,EAAE,CAAC,wBAAwB,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;gBACxE,SAAS,CAAC,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAA8B,EAAE,IAAI,CAAC,CAAC;YACnF,CAAC;YACD,IAAI,YAAY,EAAE,CAAC;gBACjB,KAAK,MAAM,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC;oBAAE,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACtG,CAAC;QACH,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;QACnC,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiB,CAAC;IACxC,KAAK,MAAM,KAAK,IAAI,mBAAmB,CAAC,OAAO,CAAC;QAAE,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC;IAEpG,OAAO,UAAU,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,MAAe,EAAE,CAAC,CAAC,CAAC,CAAC;AAC1H,CAAC;AAED,SAAS,aAAa,CAAC,IAAgC,EAAE,GAAW;IAClE,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACvC,IAAI,EAAE,CAAC,oBAAoB,CAAC,QAAQ,CAAC,IAAI,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YAChF,OAAO,gBAAgB,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,2EAA2E;AAC3E,SAAS,eAAe,CAAC,KAAgC;IACvD,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QACnG,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CACvC,CAAC,EAAE,CAAC,oBAAoB,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,6BAA6B,CAAC,QAAQ,CAAC,CAAC;eAC9E,SAAS,CAAC,GAAG,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAgC;IACzD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5B,OAAO,EAAE,CAAC,oBAAoB,CAAC,MAAM,CAAC,IAAI,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC;AACxF,CAAC;AAED,kDAAkD;AAClD,SAAS,YAAY,CAAC,KAAgC;IACpD,IAAI,MAAM,GAAY,KAAK,CAAC,MAAM,CAAC;IACnC,OAAO,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,qBAAqB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,yBAAyB,CAAC,MAAM,CAAC;QAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IACrI,OAAO,EAAE,CAAC,qBAAqB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACzG,CAAC;AAED,0EAA0E;AAC1E,SAAS,UAAU,CAAC,MAAqB;IACvC,IAAI,KAAyB,CAAC;IAC9B,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACpB,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC/E,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC1C,MAAM,IAAI,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAqB,CAAC,CAAC;QAC1D,IACE,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC;eACvB,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC;eACnC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC;eAChC,IAAI,CAAC,UAAU,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI,EAC1C,CAAC;YACD,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QACzB,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -8,4 +8,24 @@ export declare function unwrapExpression(node: ts.Expression): ts.Expression;
8
8
  export declare function walk(node: ts.Node, visit: (node: ts.Node) => void): void;
9
9
  /** Name of a property key written as an identifier or a string. */
10
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;
11
31
  //# sourceMappingURL=astUtils.d.ts.map
@@ -1 +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"}
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"}