modviz 0.1.2

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 (109) hide show
  1. package/README.md +261 -0
  2. package/dist/client/_shell.html +0 -0
  3. package/dist/client/android-chrome-192x192.png +0 -0
  4. package/dist/client/android-chrome-512x512.png +0 -0
  5. package/dist/client/apple-touch-icon.png +0 -0
  6. package/dist/client/assets/app-Sjrldkrg.css +2 -0
  7. package/dist/client/assets/button-aOWckyNs.js +1 -0
  8. package/dist/client/assets/check-C0EQe2S8.js +1 -0
  9. package/dist/client/assets/chevron-down-DrspihmT.js +1 -0
  10. package/dist/client/assets/chevron-right-DIJHr8AN.js +1 -0
  11. package/dist/client/assets/colors-CQoWjU5E.js +1 -0
  12. package/dist/client/assets/command-kkF7_wdz.js +45 -0
  13. package/dist/client/assets/compare-K6jVFsiI.js +1 -0
  14. package/dist/client/assets/compare-TOnoe1EP.js +2 -0
  15. package/dist/client/assets/configure-DnlSnhtN.js +1 -0
  16. package/dist/client/assets/explorer-C7NclVKg.js +2 -0
  17. package/dist/client/assets/explorer-Xu2X6XXF.js +1 -0
  18. package/dist/client/assets/external-link-B9eNA-li.js +1 -0
  19. package/dist/client/assets/flamegraph-CRVZSAlj.js +13 -0
  20. package/dist/client/assets/floating-ui.dom-DLIT5tPE.js +1 -0
  21. package/dist/client/assets/formatting-CiC0SYI8.js +1 -0
  22. package/dist/client/assets/graph-6Vr74V1k.js +2 -0
  23. package/dist/client/assets/graph-CVzypIGU.js +2 -0
  24. package/dist/client/assets/graph-command-menu-D2MoVT2B.js +4 -0
  25. package/dist/client/assets/graph-command-menu-VWiiW3qy.css +1 -0
  26. package/dist/client/assets/hierarchy-C8xxGb_u.js +2 -0
  27. package/dist/client/assets/hierarchy-iO7d4oSK.js +2 -0
  28. package/dist/client/assets/import-display-D-jRyyjM.js +5 -0
  29. package/dist/client/assets/imports-CPggnrs-.js +2 -0
  30. package/dist/client/assets/imports-CodbPyUJ.js +1 -0
  31. package/dist/client/assets/index-Dj_rhLdR.js +12 -0
  32. package/dist/client/assets/input-BCFMF0aR.js +1 -0
  33. package/dist/client/assets/jsx-runtime-DWSWI4JT.js +1 -0
  34. package/dist/client/assets/lazyRouteComponent-PTSyFp1J.js +1 -0
  35. package/dist/client/assets/loading-state-CyC_hrTF.js +1 -0
  36. package/dist/client/assets/modviz-data-BiRqoDI5.js +1 -0
  37. package/dist/client/assets/modviz-layout-Do93E-IB.js +1 -0
  38. package/dist/client/assets/modviz-sigma-Xl8qHaxK.js +312 -0
  39. package/dist/client/assets/portal-BgAm3V3j.js +1 -0
  40. package/dist/client/assets/routes-DBtN8hrZ.js +1 -0
  41. package/dist/client/assets/schemas-B4zfTepZ.js +39 -0
  42. package/dist/client/assets/search-BYHxNrYn.js +1 -0
  43. package/dist/client/assets/search-params-BaZRBvGI.js +1 -0
  44. package/dist/client/assets/setup-view-j1o0TuZz.js +1 -0
  45. package/dist/client/assets/summary-D703Zh3x.js +1 -0
  46. package/dist/client/assets/tooltip-B1VDU9HG.js +1 -0
  47. package/dist/client/assets/trace-B67CM5s2.js +2 -0
  48. package/dist/client/assets/trace-Bwwdw3AM.js +1 -0
  49. package/dist/client/assets/treemap-BZf2shzY.js +5 -0
  50. package/dist/client/assets/treemap-Csroy8Gy.js +2 -0
  51. package/dist/client/assets/utils-DkkZd0ys.js +1 -0
  52. package/dist/client/favicon-16x16.png +0 -0
  53. package/dist/client/favicon-32x32.png +0 -0
  54. package/dist/client/favicon.ico +0 -0
  55. package/dist/client/favicon.png +0 -0
  56. package/dist/client/site.webmanifest +19 -0
  57. package/dist/mod/cli-options.js +225 -0
  58. package/dist/mod/cli.js +519 -0
  59. package/dist/mod/index.js +3 -0
  60. package/dist/mod/llm-analysis.js +29 -0
  61. package/dist/mod/llm-output.js +742 -0
  62. package/dist/mod/module-graph-plugins.js +60 -0
  63. package/dist/mod/production-server.js +103 -0
  64. package/dist/mod/runtime-host.js +217 -0
  65. package/dist/mod/snapshot-history.js +73 -0
  66. package/dist/mod/types.js +3 -0
  67. package/dist/server/assets/__23tanstack-start-plugin-adapters-3QxJs4a0.js +5 -0
  68. package/dist/server/assets/_tanstack-start-manifest_v-DMytuIue.js +188 -0
  69. package/dist/server/assets/button-Bqnnid5i.js +41 -0
  70. package/dist/server/assets/colors-DhAxrYua.js +100 -0
  71. package/dist/server/assets/command-SdxShIbL.js +138 -0
  72. package/dist/server/assets/compare-BFMiiUsB.js +562 -0
  73. package/dist/server/assets/compare-CpOqTpYu.js +10 -0
  74. package/dist/server/assets/configure-Bvd45DTI.js +288 -0
  75. package/dist/server/assets/explorer-C7dODpSv.js +379 -0
  76. package/dist/server/assets/explorer-CpSb0JTa.js +20 -0
  77. package/dist/server/assets/flamegraph-CdW-VG6I.js +198 -0
  78. package/dist/server/assets/formatting-iDlL4tA-.js +4 -0
  79. package/dist/server/assets/graph-C1G9H5O4.js +438 -0
  80. package/dist/server/assets/graph-DAGFGioS.js +45 -0
  81. package/dist/server/assets/graph-command-menu-BV5GtOWx.js +249 -0
  82. package/dist/server/assets/hierarchy-B4K-Zfn9.js +16 -0
  83. package/dist/server/assets/hierarchy-BGpWSG-f.js +104 -0
  84. package/dist/server/assets/import-display-BVIOWcsm.js +124 -0
  85. package/dist/server/assets/imports-B6JBDl_h.js +379 -0
  86. package/dist/server/assets/imports-BGe5tZJT.js +28 -0
  87. package/dist/server/assets/input-C5r-hBix.js +19 -0
  88. package/dist/server/assets/loading-state-CrvCWTtw.js +23 -0
  89. package/dist/server/assets/modviz-data-CUyTorv0.js +197 -0
  90. package/dist/server/assets/modviz-layout-BAH2ogse.js +253 -0
  91. package/dist/server/assets/modviz-server-DoMlAyFW.js +195 -0
  92. package/dist/server/assets/modviz-sigma-XYxARWqd.js +1441 -0
  93. package/dist/server/assets/rolldown-runtime-rSIU-vHC.js +13 -0
  94. package/dist/server/assets/router-DYJ-zDbU.js +353 -0
  95. package/dist/server/assets/routes-DInCacpY.js +244 -0
  96. package/dist/server/assets/search-params-BNApPgkX.js +26 -0
  97. package/dist/server/assets/setup-view-DjI49Iqr.js +91 -0
  98. package/dist/server/assets/start-Ba3KII43.js +4 -0
  99. package/dist/server/assets/summary-z3lXkLCQ.js +208 -0
  100. package/dist/server/assets/tooltip-Ck0DDfF7.js +24 -0
  101. package/dist/server/assets/trace-ColKOf9g.js +16 -0
  102. package/dist/server/assets/trace-eVs-hIZO.js +578 -0
  103. package/dist/server/assets/treemap-BbZ9M4GF.js +17 -0
  104. package/dist/server/assets/treemap-CrgWFoCF.js +912 -0
  105. package/dist/server/assets/utils-BQZm0uva.js +8 -0
  106. package/dist/server/server.js +5259 -0
  107. package/dist/shared/modviz-compare.js +120 -0
  108. package/dist/shared/modviz-trace.js +244 -0
  109. package/package.json +135 -0
@@ -0,0 +1,13 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, no_symbols) => {
4
+ let target = {};
5
+ for (var name in all) __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true
8
+ });
9
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
+ return target;
11
+ };
12
+ //#endregion
13
+ export { __exportAll as t };
@@ -0,0 +1,353 @@
1
+ import { n as fetchModvizBundle } from "./modviz-data-CUyTorv0.js";
2
+ import { t as Route$9 } from "./treemap-BbZ9M4GF.js";
3
+ import { t as Route$10 } from "./trace-ColKOf9g.js";
4
+ import { t as Route$11 } from "./imports-BGe5tZJT.js";
5
+ import { t as Route$12 } from "./hierarchy-B4K-Zfn9.js";
6
+ import { t as Route$13 } from "./graph-DAGFGioS.js";
7
+ import { t as Route$14 } from "./explorer-CpSb0JTa.js";
8
+ import { t as Route$15 } from "./compare-CpOqTpYu.js";
9
+ import { a as loadSnapshotGraph, i as listSnapshotHistory, n as loadModvizBundle, t as getModvizJsonStatus } from "./modviz-server-DoMlAyFW.js";
10
+ import "react";
11
+ import { ErrorComponent, HeadContent, Link, Scripts, createFileRoute, createRootRoute, createRouter, lazyRouteComponent, rootRouteId, useMatch, useRouter } from "@tanstack/react-router";
12
+ import { jsx, jsxs } from "react/jsx-runtime";
13
+ //#region src/components/DefaultCatchBoundary.tsx
14
+ function DefaultCatchBoundary({ error }) {
15
+ const router = useRouter();
16
+ const isRoot = useMatch({
17
+ strict: false,
18
+ select: (state) => state.id === rootRouteId
19
+ });
20
+ console.error("DefaultCatchBoundary Error:", error);
21
+ return /* @__PURE__ */ jsxs("div", {
22
+ className: "min-w-0 flex-1 p-4 flex flex-col items-center justify-center gap-6",
23
+ children: [/* @__PURE__ */ jsx(ErrorComponent, { error }), /* @__PURE__ */ jsxs("div", {
24
+ className: "flex gap-2 items-center flex-wrap",
25
+ children: [/* @__PURE__ */ jsx("button", {
26
+ onClick: () => {
27
+ router.invalidate();
28
+ },
29
+ className: `px-2 py-1 bg-gray-600 dark:bg-gray-700 rounded text-white uppercase font-extrabold`,
30
+ children: "Try Again"
31
+ }), isRoot ? /* @__PURE__ */ jsx(Link, {
32
+ to: "/",
33
+ className: `px-2 py-1 bg-gray-600 dark:bg-gray-700 rounded text-white uppercase font-extrabold`,
34
+ children: "Home"
35
+ }) : /* @__PURE__ */ jsx(Link, {
36
+ to: "/",
37
+ className: `px-2 py-1 bg-gray-600 dark:bg-gray-700 rounded text-white uppercase font-extrabold`,
38
+ onClick: (e) => {
39
+ e.preventDefault();
40
+ window.history.back();
41
+ },
42
+ children: "Go Back"
43
+ })]
44
+ })]
45
+ });
46
+ }
47
+ //#endregion
48
+ //#region src/components/NotFound.tsx
49
+ function NotFound({ children }) {
50
+ return /* @__PURE__ */ jsxs("div", {
51
+ className: "space-y-2 p-2",
52
+ children: [/* @__PURE__ */ jsx("div", {
53
+ className: "text-gray-600 dark:text-gray-400",
54
+ children: children || /* @__PURE__ */ jsx("p", { children: "The page you are looking for does not exist." })
55
+ }), /* @__PURE__ */ jsxs("p", {
56
+ className: "flex items-center gap-2 flex-wrap",
57
+ children: [/* @__PURE__ */ jsx("button", {
58
+ onClick: () => window.history.back(),
59
+ className: "bg-emerald-500 text-white px-2 py-1 rounded uppercase font-black text-sm",
60
+ children: "Go back"
61
+ }), /* @__PURE__ */ jsx(Link, {
62
+ to: "/",
63
+ className: "bg-cyan-600 text-white px-2 py-1 rounded uppercase font-black text-sm",
64
+ children: "Start Over"
65
+ })]
66
+ })]
67
+ });
68
+ }
69
+ //#endregion
70
+ //#region src/styles/app.css?url
71
+ var app_default = "/assets/app-Sjrldkrg.css";
72
+ //#endregion
73
+ //#region src/utils/seo.ts
74
+ var seo = ({ title, description, keywords, image }) => {
75
+ return [
76
+ { title },
77
+ {
78
+ name: "description",
79
+ content: description
80
+ },
81
+ {
82
+ name: "keywords",
83
+ content: keywords
84
+ },
85
+ {
86
+ name: "twitter:title",
87
+ content: title
88
+ },
89
+ {
90
+ name: "twitter:description",
91
+ content: description
92
+ },
93
+ {
94
+ name: "twitter:creator",
95
+ content: "@astahmer"
96
+ },
97
+ {
98
+ name: "twitter:site",
99
+ content: "@astahmer"
100
+ },
101
+ {
102
+ name: "og:type",
103
+ content: "website"
104
+ },
105
+ {
106
+ name: "og:title",
107
+ content: title
108
+ },
109
+ {
110
+ name: "og:description",
111
+ content: description
112
+ },
113
+ ...image ? [
114
+ {
115
+ name: "twitter:image",
116
+ content: image
117
+ },
118
+ {
119
+ name: "twitter:card",
120
+ content: "summary_large_image"
121
+ },
122
+ {
123
+ name: "og:image",
124
+ content: image
125
+ }
126
+ ] : []
127
+ ];
128
+ };
129
+ //#endregion
130
+ //#region src/routes/__root.tsx
131
+ var Route$8 = createRootRoute({
132
+ ssr: false,
133
+ loader: () => fetchModvizBundle(),
134
+ head: () => ({
135
+ meta: [
136
+ { charSet: "utf-8" },
137
+ {
138
+ name: "viewport",
139
+ content: "width=device-width, initial-scale=1"
140
+ },
141
+ ...seo({
142
+ title: "modviz",
143
+ description: `visualization for module-graph`
144
+ })
145
+ ],
146
+ links: [
147
+ {
148
+ rel: "stylesheet",
149
+ href: app_default
150
+ },
151
+ {
152
+ rel: "apple-touch-icon",
153
+ sizes: "180x180",
154
+ href: "/apple-touch-icon.png"
155
+ },
156
+ {
157
+ rel: "manifest",
158
+ href: "/site.webmanifest",
159
+ color: "#fffff"
160
+ }
161
+ ]
162
+ }),
163
+ errorComponent: DefaultCatchBoundary,
164
+ notFoundComponent: () => /* @__PURE__ */ jsx(NotFound, {}),
165
+ shellComponent: RootDocument
166
+ });
167
+ function RootDocument({ children }) {
168
+ return /* @__PURE__ */ jsxs("html", { children: [/* @__PURE__ */ jsx("head", { children: /* @__PURE__ */ jsx(HeadContent, {}) }), /* @__PURE__ */ jsxs("body", {
169
+ className: "h-[100vh] flex flex-col",
170
+ children: [children, /* @__PURE__ */ jsx(Scripts, {})]
171
+ })] });
172
+ }
173
+ //#endregion
174
+ //#region src/routes/summary.tsx
175
+ var $$splitComponentImporter$2 = () => import("./summary-z3lXkLCQ.js");
176
+ var Route$7 = createFileRoute("/summary")({
177
+ ssr: false,
178
+ component: lazyRouteComponent($$splitComponentImporter$2, "component")
179
+ });
180
+ //#endregion
181
+ //#region src/routes/configure.tsx
182
+ var $$splitComponentImporter$1 = () => import("./configure-Bvd45DTI.js");
183
+ var Route$6 = createFileRoute("/configure")({
184
+ ssr: false,
185
+ component: lazyRouteComponent($$splitComponentImporter$1, "component")
186
+ });
187
+ //#endregion
188
+ //#region src/routes/index.tsx
189
+ var $$splitComponentImporter = () => import("./routes-DInCacpY.js");
190
+ var Route$5 = createFileRoute("/")({
191
+ ssr: false,
192
+ component: lazyRouteComponent($$splitComponentImporter, "component")
193
+ });
194
+ //#endregion
195
+ //#region src/routes/api/snapshot-history.ts
196
+ var Route$4 = createFileRoute("/api/snapshot-history")({ server: { handlers: { GET: async () => Response.json(listSnapshotHistory()) } } });
197
+ //#endregion
198
+ //#region src/routes/api/modviz-bundle.ts
199
+ var Route$3 = createFileRoute("/api/modviz-bundle")({ server: { handlers: { GET: async ({ request }) => {
200
+ try {
201
+ const url = new URL(request.url);
202
+ return Response.json(loadModvizBundle({
203
+ graphPath: url.searchParams.get("graphPath"),
204
+ snapshotId: url.searchParams.get("snapshotId")
205
+ }));
206
+ } catch (error) {
207
+ return Response.json({ error: error instanceof Error ? error.message : "Failed to load modviz bundle." }, { status: 500 });
208
+ }
209
+ } } } });
210
+ //#endregion
211
+ //#region src/routes/api/json-status.ts
212
+ var Route$2 = createFileRoute("/api/json-status")({ server: { handlers: { GET: async ({ request }) => {
213
+ const url = new URL(request.url);
214
+ return Response.json(getModvizJsonStatus({
215
+ graphPath: url.searchParams.get("graphPath"),
216
+ snapshotId: url.searchParams.get("snapshotId")
217
+ }));
218
+ } } } });
219
+ //#endregion
220
+ //#region src/routes/api/users.$userId.ts
221
+ var Route$1 = createFileRoute("/api/users/$userId")({ server: { handlers: { GET: async ({ params, request }) => {
222
+ console.info(`Fetching users by id=${params.userId}... @`, request.url);
223
+ try {
224
+ const res = await fetch("https://jsonplaceholder.typicode.com/users/" + params.userId);
225
+ if (!res.ok) throw new Error("Failed to fetch user");
226
+ const user = await res.json();
227
+ return Response.json({
228
+ id: user.id,
229
+ name: user.name,
230
+ email: user.email
231
+ });
232
+ } catch (error) {
233
+ console.error(error);
234
+ return Response.json({ error: "User not found" }, { status: 404 });
235
+ }
236
+ } } } });
237
+ //#endregion
238
+ //#region src/routes/api/snapshot-history.$snapshotId.ts
239
+ var Route = createFileRoute("/api/snapshot-history/$snapshotId")({ server: { handlers: { GET: async ({ params }) => {
240
+ try {
241
+ return Response.json(loadSnapshotGraph(params.snapshotId));
242
+ } catch (error) {
243
+ return Response.json({ error: error instanceof Error ? error.message : `Failed to load snapshot ${params.snapshotId}.` }, { status: 404 });
244
+ }
245
+ } } } });
246
+ //#endregion
247
+ //#region src/routeTree.gen.ts
248
+ var TreemapRoute = Route$9.update({
249
+ id: "/treemap",
250
+ path: "/treemap",
251
+ getParentRoute: () => Route$8
252
+ });
253
+ var TraceRoute = Route$10.update({
254
+ id: "/trace",
255
+ path: "/trace",
256
+ getParentRoute: () => Route$8
257
+ });
258
+ var SummaryRoute = Route$7.update({
259
+ id: "/summary",
260
+ path: "/summary",
261
+ getParentRoute: () => Route$8
262
+ });
263
+ var ImportsRoute = Route$11.update({
264
+ id: "/imports",
265
+ path: "/imports",
266
+ getParentRoute: () => Route$8
267
+ });
268
+ var HierarchyRoute = Route$12.update({
269
+ id: "/hierarchy",
270
+ path: "/hierarchy",
271
+ getParentRoute: () => Route$8
272
+ });
273
+ var GraphRoute = Route$13.update({
274
+ id: "/graph",
275
+ path: "/graph",
276
+ getParentRoute: () => Route$8
277
+ });
278
+ var ExplorerRoute = Route$14.update({
279
+ id: "/explorer",
280
+ path: "/explorer",
281
+ getParentRoute: () => Route$8
282
+ });
283
+ var ConfigureRoute = Route$6.update({
284
+ id: "/configure",
285
+ path: "/configure",
286
+ getParentRoute: () => Route$8
287
+ });
288
+ var CompareRoute = Route$15.update({
289
+ id: "/compare",
290
+ path: "/compare",
291
+ getParentRoute: () => Route$8
292
+ });
293
+ var IndexRoute = Route$5.update({
294
+ id: "/",
295
+ path: "/",
296
+ getParentRoute: () => Route$8
297
+ });
298
+ var ApiSnapshotHistoryRoute = Route$4.update({
299
+ id: "/api/snapshot-history",
300
+ path: "/api/snapshot-history",
301
+ getParentRoute: () => Route$8
302
+ });
303
+ var ApiModvizBundleRoute = Route$3.update({
304
+ id: "/api/modviz-bundle",
305
+ path: "/api/modviz-bundle",
306
+ getParentRoute: () => Route$8
307
+ });
308
+ var ApiJsonStatusRoute = Route$2.update({
309
+ id: "/api/json-status",
310
+ path: "/api/json-status",
311
+ getParentRoute: () => Route$8
312
+ });
313
+ var ApiUsersUserIdRoute = Route$1.update({
314
+ id: "/api/users/$userId",
315
+ path: "/api/users/$userId",
316
+ getParentRoute: () => Route$8
317
+ });
318
+ var ApiSnapshotHistoryRouteChildren = { ApiSnapshotHistorySnapshotIdRoute: Route.update({
319
+ id: "/$snapshotId",
320
+ path: "/$snapshotId",
321
+ getParentRoute: () => ApiSnapshotHistoryRoute
322
+ }) };
323
+ var rootRouteChildren = {
324
+ IndexRoute,
325
+ CompareRoute,
326
+ ConfigureRoute,
327
+ ExplorerRoute,
328
+ GraphRoute,
329
+ HierarchyRoute,
330
+ ImportsRoute,
331
+ SummaryRoute,
332
+ TraceRoute,
333
+ TreemapRoute,
334
+ ApiJsonStatusRoute,
335
+ ApiModvizBundleRoute,
336
+ ApiSnapshotHistoryRoute: ApiSnapshotHistoryRoute._addFileChildren(ApiSnapshotHistoryRouteChildren),
337
+ ApiUsersUserIdRoute
338
+ };
339
+ var routeTree = Route$8._addFileChildren(rootRouteChildren)._addFileTypes();
340
+ //#endregion
341
+ //#region src/router.tsx
342
+ function getRouter() {
343
+ return createRouter({
344
+ routeTree,
345
+ defaultPreload: "intent",
346
+ defaultErrorComponent: DefaultCatchBoundary,
347
+ defaultNotFoundComponent: () => /* @__PURE__ */ jsx(NotFound, {}),
348
+ scrollRestoration: true
349
+ });
350
+ }
351
+ var createRouterInstance = getRouter;
352
+ //#endregion
353
+ export { createRouterInstance, getRouter };
@@ -0,0 +1,244 @@
1
+ import { f as isModvizBundleReady, m as useModvizBundle } from "./modviz-data-CUyTorv0.js";
2
+ import { t as formatNumber } from "./formatting-iDlL4tA-.js";
3
+ import { t as ModvizLayout } from "./modviz-layout-BAH2ogse.js";
4
+ import { t as SetupView } from "./setup-view-DjI49Iqr.js";
5
+ import { Link } from "@tanstack/react-router";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ import { ArrowRight, BarChart3, FolderTree, GitBranchPlus, Network, SquareStack } from "lucide-react";
8
+ //#region src/components/modviz/dashboard-view.tsx
9
+ var routes = [
10
+ {
11
+ to: "/explorer",
12
+ title: "File explorer",
13
+ description: "Browse folders and files directly, then inspect imports and imported-by lists from the selected path.",
14
+ icon: FolderTree,
15
+ search: void 0
16
+ },
17
+ {
18
+ to: "/summary",
19
+ title: "Summary",
20
+ description: "Read hotspots, top importers, top imported modules, and package-level distribution without rendering Sigma.",
21
+ icon: BarChart3,
22
+ search: void 0
23
+ },
24
+ {
25
+ to: "/imports",
26
+ title: "Import search",
27
+ description: "Search for imports by module or symbol and narrow results to specific monorepo packages, folders, or files.",
28
+ icon: GitBranchPlus,
29
+ search: void 0
30
+ },
31
+ {
32
+ to: "/compare",
33
+ title: "Snapshot compare",
34
+ description: "Load a baseline graph JSON beside the currently served snapshot and inspect node, edge, and package deltas.",
35
+ icon: GitBranchPlus,
36
+ search: void 0
37
+ },
38
+ {
39
+ to: "/hierarchy",
40
+ title: "Hierarchy",
41
+ description: "Inspect the dependency tree as a flamegraph-style hierarchy for entrypoint-focused analysis.",
42
+ icon: SquareStack,
43
+ search: void 0
44
+ }
45
+ ];
46
+ function StatCard(props) {
47
+ return /* @__PURE__ */ jsxs("div", {
48
+ className: "rounded-[24px] border border-slate-200/70 bg-white/90 p-5 shadow-[0_16px_50px_-32px_rgba(15,23,42,0.55)] dark:border-slate-800 dark:bg-slate-950/70",
49
+ children: [/* @__PURE__ */ jsx("p", {
50
+ className: "text-xs font-semibold uppercase tracking-[0.2em] text-slate-500 dark:text-slate-400",
51
+ children: props.label
52
+ }), /* @__PURE__ */ jsxs("div", {
53
+ className: "mt-3 flex items-end justify-between gap-4",
54
+ children: [/* @__PURE__ */ jsx("p", {
55
+ className: "text-3xl font-semibold text-slate-900 dark:text-slate-100",
56
+ children: formatNumber.format(props.value)
57
+ }), /* @__PURE__ */ jsx("p", {
58
+ className: "max-w-[14rem] text-right text-xs leading-5 text-slate-500 dark:text-slate-400",
59
+ children: props.detail
60
+ })]
61
+ })]
62
+ });
63
+ }
64
+ function RankingList(props) {
65
+ return /* @__PURE__ */ jsxs("section", {
66
+ className: "rounded-[24px] border border-slate-200/70 bg-white/90 p-5 shadow-[0_16px_50px_-32px_rgba(15,23,42,0.55)] dark:border-slate-800 dark:bg-slate-950/70",
67
+ children: [/* @__PURE__ */ jsx("div", {
68
+ className: "flex items-start justify-between gap-4",
69
+ children: /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h2", {
70
+ className: "text-lg font-semibold text-slate-900 dark:text-slate-100",
71
+ children: props.title
72
+ }), /* @__PURE__ */ jsx("p", {
73
+ className: "mt-1 text-sm text-slate-500 dark:text-slate-400",
74
+ children: props.description
75
+ })] })
76
+ }), /* @__PURE__ */ jsx("div", {
77
+ className: "mt-4 space-y-3",
78
+ children: props.items.map((item, index) => {
79
+ const link = props.getLink(item);
80
+ return /* @__PURE__ */ jsxs(Link, {
81
+ to: link.to,
82
+ search: link.search,
83
+ className: "flex items-start justify-between gap-4 rounded-2xl bg-slate-50/80 px-4 py-3 transition hover:bg-sky-50 dark:bg-slate-900/80 dark:hover:bg-sky-500/10",
84
+ children: [/* @__PURE__ */ jsxs("div", {
85
+ className: "min-w-0",
86
+ children: [
87
+ /* @__PURE__ */ jsx("p", {
88
+ className: "truncate text-sm font-medium text-slate-800 dark:text-slate-100",
89
+ children: item.label
90
+ }),
91
+ /* @__PURE__ */ jsx("p", {
92
+ className: "truncate text-xs text-slate-500 dark:text-slate-400",
93
+ children: item.path
94
+ }),
95
+ item.description ? /* @__PURE__ */ jsx("p", {
96
+ className: "mt-1 text-xs text-slate-500 dark:text-slate-400",
97
+ children: item.description
98
+ }) : null
99
+ ]
100
+ }), /* @__PURE__ */ jsx("div", {
101
+ className: "rounded-full bg-slate-900 px-3 py-1 text-xs font-semibold text-white dark:bg-slate-100 dark:text-slate-950",
102
+ children: formatNumber.format(item.value)
103
+ })]
104
+ }, `${item.path}-${index}`);
105
+ })
106
+ })]
107
+ });
108
+ }
109
+ function DashboardView(props) {
110
+ const { graph, summary } = props.bundle;
111
+ return /* @__PURE__ */ jsxs("div", {
112
+ className: "space-y-6",
113
+ children: [
114
+ /* @__PURE__ */ jsx("section", {
115
+ className: "grid gap-4 lg:grid-cols-2 xl:grid-cols-4",
116
+ children: [...presetRoutes, ...routes].map((route) => {
117
+ const Icon = route.icon;
118
+ return /* @__PURE__ */ jsxs(Link, {
119
+ to: route.to,
120
+ search: route.search,
121
+ className: "group rounded-[16px] border border-slate-200/70 bg-white/90 p-4 shadow-[0_16px_50px_-32px_rgba(15,23,42,0.55)] transition hover:border-sky-300 hover:shadow-[0_24px_70px_-34px_rgba(14,165,233,0.45)] dark:border-slate-800 dark:bg-slate-950/70",
122
+ children: [
123
+ /* @__PURE__ */ jsxs("div", {
124
+ className: "flex items-start justify-between gap-3",
125
+ children: [/* @__PURE__ */ jsx("div", {
126
+ className: "rounded-lg bg-sky-100 p-2 text-sky-700 dark:bg-sky-500/15 dark:text-sky-300",
127
+ children: /* @__PURE__ */ jsx(Icon, { className: "size-4" })
128
+ }), /* @__PURE__ */ jsx(ArrowRight, { className: "size-3.5 text-slate-400 transition group-hover:text-sky-600 dark:group-hover:text-sky-300" })]
129
+ }),
130
+ /* @__PURE__ */ jsx("h3", {
131
+ className: "mt-3 text-sm font-semibold text-slate-900 dark:text-slate-100",
132
+ children: route.title
133
+ }),
134
+ /* @__PURE__ */ jsx("p", {
135
+ className: "mt-1 text-xs leading-5 text-slate-500 dark:text-slate-400",
136
+ children: route.description
137
+ })
138
+ ]
139
+ }, `${route.to}-${route.title}`);
140
+ })
141
+ }),
142
+ /* @__PURE__ */ jsxs("section", {
143
+ className: "grid gap-3 md:grid-cols-2 lg:grid-cols-4",
144
+ children: [
145
+ /* @__PURE__ */ jsx(StatCard, {
146
+ label: "Total nodes",
147
+ value: summary.overview.totalNodes,
148
+ detail: `${formatNumber.format(summary.overview.workspaceNodes)} workspace, ${formatNumber.format(summary.overview.externalNodes)} external`
149
+ }),
150
+ /* @__PURE__ */ jsx(StatCard, {
151
+ label: "Workspace packages",
152
+ value: summary.overview.workspacePackages,
153
+ detail: `+${formatNumber.format(summary.overview.externalPackages)} external packages`
154
+ }),
155
+ /* @__PURE__ */ jsx(StatCard, {
156
+ label: "Barrel files",
157
+ value: summary.overview.barrelFiles,
158
+ detail: "Re-export hubs in the analyzer."
159
+ }),
160
+ /* @__PURE__ */ jsx(StatCard, {
161
+ label: "Entrypoints",
162
+ value: summary.overview.entrypoints,
163
+ detail: graph.metadata.entrypoints.slice(0, 2).join(" • ") || "No metadata"
164
+ })
165
+ ]
166
+ }),
167
+ /* @__PURE__ */ jsxs("section", {
168
+ className: "grid gap-4 xl:grid-cols-3",
169
+ children: [
170
+ /* @__PURE__ */ jsx(RankingList, {
171
+ title: "Hotspots",
172
+ description: summary.hasLlm ? "Reachable-module hotspots from the companion report." : "Graph-derived hotspots ranked by transitive reach.",
173
+ items: summary.hotspots.slice(0, 6),
174
+ getLink: getExplorerSummaryLink
175
+ }),
176
+ /* @__PURE__ */ jsx(RankingList, {
177
+ title: "Most imported by",
178
+ description: "Files or modules with the most inbound edges.",
179
+ items: summary.topImportedBy.slice(0, 6),
180
+ getLink: getExplorerSummaryLink
181
+ }),
182
+ /* @__PURE__ */ jsx(RankingList, {
183
+ title: "Top clusters",
184
+ description: "Largest package or cluster groupings in the loaded graph.",
185
+ items: summary.topClusters.slice(0, 6),
186
+ getLink: (item) => ({
187
+ to: "/graph",
188
+ search: {
189
+ cluster: item.label,
190
+ externalGrouping: "package"
191
+ }
192
+ })
193
+ })
194
+ ]
195
+ })
196
+ ]
197
+ });
198
+ }
199
+ var getExplorerSummaryLink = (item) => ({
200
+ to: "/explorer",
201
+ search: {
202
+ selected: item.path,
203
+ scope: item.path.includes("node_modules") ? "external" : "workspace"
204
+ }
205
+ });
206
+ var presetRoutes = [
207
+ {
208
+ to: "/graph",
209
+ search: { scope: "workspace" },
210
+ title: "Monorepo graph",
211
+ description: "Start from workspace files only when external noise is getting in the way.",
212
+ icon: Network
213
+ },
214
+ {
215
+ to: "/graph",
216
+ search: {
217
+ scope: "external",
218
+ externalGrouping: "package"
219
+ },
220
+ title: "node_modules graph",
221
+ description: "Open a dependency-package view where external files are grouped by package instead of one big node_modules blob.",
222
+ icon: Network
223
+ },
224
+ {
225
+ to: "/imports",
226
+ search: { scope: "external" },
227
+ title: "External import hunt",
228
+ description: "Jump straight into package-focused search when you are tracking third-party usage.",
229
+ icon: GitBranchPlus
230
+ }
231
+ ];
232
+ //#endregion
233
+ //#region src/routes/index.tsx?tsr-split=component
234
+ function Home() {
235
+ const bundle = useModvizBundle();
236
+ return /* @__PURE__ */ jsx(ModvizLayout, {
237
+ projectTitle: bundle.projectTitle,
238
+ title: "Overview",
239
+ description: "Start from a lightweight dashboard, then choose the graph, summary, import-search, or hierarchy view based on the question you are asking.",
240
+ children: isModvizBundleReady(bundle) ? /* @__PURE__ */ jsx(DashboardView, { bundle }) : /* @__PURE__ */ jsx(SetupView, { bundle })
241
+ });
242
+ }
243
+ //#endregion
244
+ export { Home as component };
@@ -0,0 +1,26 @@
1
+ //#region src/utils/search-params.ts
2
+ /**
3
+ * Shared URL search parameter parsing utilities
4
+ * Used across routes for consistent validation and fallback handling
5
+ */
6
+ var parseSearchParam = {
7
+ boolean: (value, fallback) => {
8
+ if (value === void 0 || value === null || value === "") return fallback;
9
+ if (typeof value === "boolean") return value;
10
+ return value === "true";
11
+ },
12
+ number: (value, fallback) => {
13
+ if (value === void 0 || value === null || value === "") return fallback;
14
+ const parsed = Number(value);
15
+ return Number.isFinite(parsed) ? parsed : fallback;
16
+ },
17
+ string: (value, fallback = "") => {
18
+ if (typeof value === "string") return value;
19
+ return fallback;
20
+ },
21
+ stringOrUndefined: (value) => {
22
+ return typeof value === "string" ? value : void 0;
23
+ }
24
+ };
25
+ //#endregion
26
+ export { parseSearchParam as t };