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,253 @@
1
+ import { t as cn } from "./utils-BQZm0uva.js";
2
+ import { m as useModvizBundle, p as setActiveSnapshotSelection, r as fetchModvizJsonStatus, s as getActiveSnapshotSelection } from "./modviz-data-CUyTorv0.js";
3
+ import { startTransition, useEffect, useMemo, useRef, useState } from "react";
4
+ import { Link, useRouter } from "@tanstack/react-router";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { ArrowLeftRight, BarChart3, Boxes, FolderTree, GitBranchPlus, LayoutGrid, Network, RefreshCw, Route, Settings, SquareStack } from "lucide-react";
7
+ //#region src/hooks/use-json-updates.ts
8
+ function useJsonUpdates(intervalMs = 2500) {
9
+ const router = useRouter();
10
+ const lastModifiedRef = useRef(null);
11
+ const graphPathRef = useRef(null);
12
+ const isRefreshingRef = useRef(false);
13
+ const [status, setStatus] = useState(null);
14
+ const [isRefreshing, setIsRefreshing] = useState(false);
15
+ useEffect(() => {
16
+ let isDisposed = false;
17
+ const poll = async () => {
18
+ try {
19
+ const nextStatus = await fetchModvizJsonStatus();
20
+ if (isDisposed) return;
21
+ setStatus(nextStatus);
22
+ if (graphPathRef.current !== nextStatus.graphPath) {
23
+ graphPathRef.current = nextStatus.graphPath;
24
+ lastModifiedRef.current = nextStatus.lastModified;
25
+ return;
26
+ }
27
+ if (nextStatus.lastModified == null) return;
28
+ if (lastModifiedRef.current == null) {
29
+ lastModifiedRef.current = nextStatus.lastModified;
30
+ return;
31
+ }
32
+ if (nextStatus.lastModified > lastModifiedRef.current && !isRefreshingRef.current) {
33
+ lastModifiedRef.current = nextStatus.lastModified;
34
+ isRefreshingRef.current = true;
35
+ setIsRefreshing(true);
36
+ startTransition(() => {
37
+ router.invalidate().finally(() => {
38
+ if (isDisposed) return;
39
+ isRefreshingRef.current = false;
40
+ setIsRefreshing(false);
41
+ });
42
+ });
43
+ }
44
+ } catch {
45
+ if (isDisposed) return;
46
+ isRefreshingRef.current = false;
47
+ setIsRefreshing(false);
48
+ }
49
+ };
50
+ poll();
51
+ const intervalId = window.setInterval(() => {
52
+ poll();
53
+ }, intervalMs);
54
+ return () => {
55
+ isDisposed = true;
56
+ window.clearInterval(intervalId);
57
+ };
58
+ }, [intervalMs, router]);
59
+ return {
60
+ isRefreshing,
61
+ status
62
+ };
63
+ }
64
+ //#endregion
65
+ //#region src/components/modviz/modviz-layout.tsx
66
+ var navigationItems = [
67
+ {
68
+ to: "/",
69
+ label: "Overview",
70
+ icon: Boxes
71
+ },
72
+ {
73
+ to: "/graph",
74
+ label: "Bubble graph",
75
+ icon: Network
76
+ },
77
+ {
78
+ to: "/compare",
79
+ label: "Compare",
80
+ icon: ArrowLeftRight
81
+ },
82
+ {
83
+ to: "/summary",
84
+ label: "Summary",
85
+ icon: BarChart3
86
+ },
87
+ {
88
+ to: "/imports",
89
+ label: "Import search",
90
+ icon: GitBranchPlus
91
+ },
92
+ {
93
+ to: "/trace",
94
+ label: "Trace",
95
+ icon: Route
96
+ },
97
+ {
98
+ to: "/explorer",
99
+ label: "Explorer",
100
+ icon: FolderTree
101
+ },
102
+ {
103
+ to: "/hierarchy",
104
+ label: "Hierarchy",
105
+ icon: SquareStack
106
+ },
107
+ {
108
+ to: "/treemap",
109
+ label: "Treemap",
110
+ icon: LayoutGrid
111
+ }
112
+ ];
113
+ function ModvizLayout(props) {
114
+ const bundle = useModvizBundle();
115
+ const router = useRouter();
116
+ const { isRefreshing, status } = useJsonUpdates();
117
+ const activeSelection = getActiveSnapshotSelection();
118
+ const [customGraphPath, setCustomGraphPath] = useState(activeSelection.graphPath);
119
+ const activeGraphPath = status?.graphPath ?? bundle.setup.graphPath;
120
+ const graphFileName = activeGraphPath.split(/[\\/]/).at(-1) ?? "modviz.json";
121
+ const activeHistorySnapshot = useMemo(() => bundle.history.find((snapshot) => snapshot.graphPath === activeGraphPath) ?? null, [bundle.history, activeGraphPath]);
122
+ const liveSyncLabel = isRefreshing ? "Refreshing graph data" : "Live JSON sync";
123
+ const liveSyncTone = isRefreshing ? "border-sky-300 bg-sky-100 text-sky-700 dark:border-sky-500/40 dark:bg-sky-500/10 dark:text-sky-200" : "border-emerald-300 bg-emerald-100 text-emerald-700 dark:border-emerald-500/40 dark:bg-emerald-500/10 dark:text-emerald-200";
124
+ const applySelection = async (selection) => {
125
+ setActiveSnapshotSelection(selection);
126
+ await router.invalidate();
127
+ };
128
+ useEffect(() => {
129
+ setCustomGraphPath(activeSelection.snapshotId ? "" : activeSelection.graphPath);
130
+ }, [activeSelection.graphPath, activeSelection.snapshotId]);
131
+ return /* @__PURE__ */ jsx("div", {
132
+ className: "min-h-screen bg-[radial-gradient(circle_at_top_left,_rgba(14,165,233,0.14),_transparent_24%),radial-gradient(circle_at_top_right,_rgba(249,115,22,0.12),_transparent_22%),linear-gradient(180deg,_rgba(255,255,255,0.96),_rgba(248,250,252,0.96))] dark:bg-[radial-gradient(circle_at_top_left,_rgba(14,165,233,0.18),_transparent_22%),radial-gradient(circle_at_top_right,_rgba(249,115,22,0.16),_transparent_20%),linear-gradient(180deg,_rgba(2,6,23,0.98),_rgba(15,23,42,0.98))]",
133
+ children: /* @__PURE__ */ jsxs("div", {
134
+ className: "mx-auto flex min-h-screen w-full max-w-7xl flex-col px-4 py-4 sm:px-6 lg:px-8",
135
+ children: [/* @__PURE__ */ jsxs("header", {
136
+ className: "rounded-[28px] border border-white/60 bg-white/80 p-5 shadow-[0_20px_80px_-45px_rgba(15,23,42,0.65)] backdrop-blur dark:border-white/10 dark:bg-slate-950/70",
137
+ children: [
138
+ /* @__PURE__ */ jsxs("div", {
139
+ className: "flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between",
140
+ children: [
141
+ /* @__PURE__ */ jsx("div", {
142
+ className: "space-y-2",
143
+ children: /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("h1", {
144
+ className: "text-3xl font-semibold tracking-tight text-slate-900 dark:text-slate-100",
145
+ children: ["Modviz ", props.projectTitle ? `- ${props.projectTitle}` : ""]
146
+ }), /* @__PURE__ */ jsx("p", {
147
+ className: "mt-2 max-w-3xl text-sm leading-6 text-slate-600 dark:text-slate-300",
148
+ children: props.description
149
+ })] })
150
+ }),
151
+ props.actions ? /* @__PURE__ */ jsx("div", {
152
+ className: "shrink-0",
153
+ children: props.actions
154
+ }) : null,
155
+ /* @__PURE__ */ jsxs(Link, {
156
+ to: "/configure",
157
+ className: "absolute right-4 top-5 inline-flex items-center gap-2 rounded-full border border-slate-200/70 bg-slate-50/90 px-4 py-2 text-sm font-medium whitespace-nowrap text-slate-600 transition hover:border-sky-300 hover:text-sky-700 dark:border-slate-700 dark:bg-slate-900/70 dark:text-slate-300 dark:hover:border-sky-500/70 dark:hover:text-sky-200",
158
+ activeProps: { className: "inline-flex items-center gap-2 rounded-full border border-sky-200 bg-sky-50 px-4 py-2 text-sm font-medium whitespace-nowrap text-sky-700 shadow-sm dark:border-sky-500/40 dark:bg-sky-500/10 dark:text-sky-200" },
159
+ children: [/* @__PURE__ */ jsx(Settings, { className: "size-4" }), /* @__PURE__ */ jsx("span", { children: "Configure" })]
160
+ })
161
+ ]
162
+ }),
163
+ /* @__PURE__ */ jsx("section", {
164
+ className: "mt-5 rounded-[24px] border border-slate-200/70 bg-slate-50/70 p-4 dark:border-slate-800 dark:bg-slate-900/40",
165
+ children: /* @__PURE__ */ jsxs("div", {
166
+ className: "grid gap-3 xl:grid-cols-[minmax(0,1.2fr)_minmax(0,1.3fr)_auto]",
167
+ children: [
168
+ /* @__PURE__ */ jsxs("label", {
169
+ className: "space-y-2 text-sm font-medium text-slate-700 dark:text-slate-200",
170
+ children: [/* @__PURE__ */ jsx("span", { children: "Active snapshot" }), /* @__PURE__ */ jsxs("select", {
171
+ className: "flex h-10 w-full rounded-md border border-input bg-transparent px-3 text-sm shadow-xs outline-none",
172
+ value: activeHistorySnapshot?.id ?? "",
173
+ onChange: (event) => {
174
+ const value = event.currentTarget.value;
175
+ setCustomGraphPath("");
176
+ applySelection(value ? { snapshotId: value } : void 0);
177
+ },
178
+ children: [/* @__PURE__ */ jsx("option", {
179
+ value: "",
180
+ children: "Default watched file"
181
+ }), bundle.history.map((snapshot) => /* @__PURE__ */ jsx("option", {
182
+ value: snapshot.id,
183
+ children: snapshot.label || snapshot.id
184
+ }, snapshot.id))]
185
+ })]
186
+ }),
187
+ /* @__PURE__ */ jsxs("label", {
188
+ className: "space-y-2 text-sm font-medium text-slate-700 dark:text-slate-200",
189
+ children: [/* @__PURE__ */ jsx("span", { children: "Custom graph path" }), /* @__PURE__ */ jsx("input", {
190
+ className: "flex h-10 w-full rounded-md border border-input bg-transparent px-3 text-sm shadow-xs outline-none",
191
+ placeholder: "/absolute/path/to/another-modviz.json",
192
+ value: customGraphPath,
193
+ onChange: (event) => setCustomGraphPath(event.currentTarget.value)
194
+ })]
195
+ }),
196
+ /* @__PURE__ */ jsxs("div", {
197
+ className: "flex items-end gap-2",
198
+ children: [/* @__PURE__ */ jsx("button", {
199
+ type: "button",
200
+ className: "inline-flex h-10 items-center justify-center rounded-md border border-input px-4 text-sm font-medium shadow-xs",
201
+ onClick: () => void applySelection({ graphPath: customGraphPath }),
202
+ disabled: !customGraphPath.trim(),
203
+ children: "Use path"
204
+ }), /* @__PURE__ */ jsx("button", {
205
+ type: "button",
206
+ className: "inline-flex h-10 items-center justify-center rounded-md border border-input px-4 text-sm font-medium shadow-xs",
207
+ onClick: () => {
208
+ setCustomGraphPath("");
209
+ applySelection();
210
+ },
211
+ children: "Reset"
212
+ })]
213
+ })
214
+ ]
215
+ })
216
+ }),
217
+ /* @__PURE__ */ jsx("nav", {
218
+ className: "mt-5 flex flex-wrap gap-2",
219
+ children: navigationItems.map((item) => {
220
+ const Icon = item.icon;
221
+ return /* @__PURE__ */ jsxs(Link, {
222
+ to: item.to,
223
+ className: cn("inline-flex items-center gap-2 rounded-full border border-slate-200/70 px-4 py-2 text-sm font-medium whitespace-nowrap text-slate-600 transition hover:border-sky-300 hover:text-sky-700 dark:border-slate-700 dark:text-slate-300 dark:hover:border-sky-500/70 dark:hover:text-sky-200"),
224
+ activeProps: { className: "inline-flex items-center gap-2 rounded-full border border-sky-500/40 bg-sky-500 text-white shadow-sm whitespace-nowrap dark:border-sky-400 dark:bg-sky-500 dark:text-slate-950" },
225
+ children: [/* @__PURE__ */ jsx(Icon, { className: "size-4" }), /* @__PURE__ */ jsx("span", { children: item.label })]
226
+ }, item.to);
227
+ })
228
+ }),
229
+ /* @__PURE__ */ jsxs("div", {
230
+ className: "mt-3 flex flex-wrap items-center gap-2 text-xs text-slate-500 dark:text-slate-400",
231
+ children: [
232
+ /* @__PURE__ */ jsxs("div", {
233
+ className: cn("inline-flex items-center gap-2 rounded-full border px-3 py-1 font-medium", liveSyncTone),
234
+ children: [/* @__PURE__ */ jsx(RefreshCw, { className: cn("size-3.5", isRefreshing ? "animate-spin" : "") }), /* @__PURE__ */ jsx("span", { children: liveSyncLabel })]
235
+ }),
236
+ /* @__PURE__ */ jsxs("span", { children: [
237
+ "Watching ",
238
+ graphFileName,
239
+ status?.hasLlm ? " with LLM companion data." : "."
240
+ ] }),
241
+ activeHistorySnapshot ? /* @__PURE__ */ jsxs("span", { children: ["Active history snapshot: ", activeHistorySnapshot.id] }) : activeSelection.graphPath ? /* @__PURE__ */ jsx("span", { children: "Custom path override active." }) : null
242
+ ]
243
+ })
244
+ ]
245
+ }), /* @__PURE__ */ jsx("main", {
246
+ className: "min-h-0 flex-1 py-6",
247
+ children: props.children
248
+ })]
249
+ })
250
+ });
251
+ }
252
+ //#endregion
253
+ export { ModvizLayout as t };
@@ -0,0 +1,195 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-rSIU-vHC.js";
2
+ import { t as buildModvizSummary } from "./modviz-data-CUyTorv0.js";
3
+ import fs, { readFileSync, readdirSync, statSync } from "node:fs";
4
+ import path from "node:path";
5
+ //#region mod/snapshot-history.ts
6
+ var resolveSnapshotHistoryDir = () => path.resolve(process.env.MODVIZ_HISTORY_DIR ?? (process.env.MODVIZ_PATH ? path.join(path.dirname(path.resolve(process.env.MODVIZ_PATH)), ".modviz", "history") : path.join(process.cwd(), ".modviz", "history")));
7
+ var resolveSnapshotPaths = (snapshotId) => {
8
+ const historyDir = resolveSnapshotHistoryDir();
9
+ return {
10
+ historyDir,
11
+ graphPath: path.join(historyDir, `${snapshotId}.json`),
12
+ llmPath: path.join(historyDir, `${snapshotId}.llm.json`)
13
+ };
14
+ };
15
+ var readSnapshotItem = (graphPath) => {
16
+ try {
17
+ const raw = JSON.parse(readFileSync(graphPath, "utf-8"));
18
+ const fileStats = statSync(graphPath);
19
+ const snapshotId = path.basename(graphPath, ".json");
20
+ const llmPath = graphPath.replace(/\.json$/, ".llm.json");
21
+ return {
22
+ id: snapshotId,
23
+ label: snapshotId.replace(/^\d{4}-\d{2}-\d{2}t/i, "").replace(/-/g, " "),
24
+ graphPath,
25
+ llmPath,
26
+ generatedAt: raw.metadata.generatedAt ?? null,
27
+ lastModified: fileStats.mtimeMs,
28
+ totalNodes: raw.nodes.length,
29
+ entrypoints: raw.metadata.entrypoints
30
+ };
31
+ } catch {
32
+ return null;
33
+ }
34
+ };
35
+ var listSnapshotHistory = () => {
36
+ const historyDir = resolveSnapshotHistoryDir();
37
+ try {
38
+ return readdirSync(historyDir).filter((fileName) => fileName.endsWith(".json") && !fileName.endsWith(".llm.json")).map((fileName) => readSnapshotItem(path.join(historyDir, fileName))).filter((item) => Boolean(item)).sort((left, right) => right.lastModified - left.lastModified);
39
+ } catch {
40
+ return [];
41
+ }
42
+ };
43
+ var loadSnapshotGraph = (snapshotId) => {
44
+ const { graphPath } = resolveSnapshotPaths(snapshotId);
45
+ return JSON.parse(readFileSync(graphPath, "utf-8"));
46
+ };
47
+ //#endregion
48
+ //#region src/utils/modviz-server.ts
49
+ var modviz_server_exports = /* @__PURE__ */ __exportAll({
50
+ getModvizJsonStatus: () => getModvizJsonStatus,
51
+ loadModvizBundle: () => loadModvizBundle,
52
+ resolveProjectTitle: () => resolveProjectTitle
53
+ });
54
+ var resolveGraphPath = () => path.resolve(process.env.MODVIZ_PATH ?? path.join(process.cwd(), "modviz.json"));
55
+ var resolveLlmPath = (graphPath) => {
56
+ if (graphPath.endsWith(".llm.json")) return graphPath;
57
+ const parsed = path.parse(graphPath);
58
+ return path.join(parsed.dir, `${parsed.name}.llm.json`);
59
+ };
60
+ var parseJsonError = (error, filePath) => {
61
+ if (!(error instanceof SyntaxError) || !("message" in error)) return `Unable to parse JSON from ${filePath}.`;
62
+ const positionMatch = error.message.match(/position\s+(\d+)/i);
63
+ if (!positionMatch) return `Unable to parse JSON from ${filePath}: ${error.message}`;
64
+ const source = fs.readFileSync(filePath, "utf-8");
65
+ const position = Number(positionMatch[1]);
66
+ const prefix = source.slice(0, position);
67
+ return `Unable to parse JSON from ${filePath} at line ${prefix.split("\n").length}, column ${prefix.length - prefix.lastIndexOf("\n")}: ${error.message}`;
68
+ };
69
+ var readJsonFile = (filePath) => {
70
+ try {
71
+ return JSON.parse(fs.readFileSync(filePath, "utf-8"));
72
+ } catch (error) {
73
+ throw new Error(parseJsonError(error, filePath));
74
+ }
75
+ };
76
+ var findClosestPackageJson = (startPath) => {
77
+ let currentPath = startPath;
78
+ while (true) {
79
+ const packageJsonPath = path.join(currentPath, "package.json");
80
+ if (fs.existsSync(packageJsonPath)) return packageJsonPath;
81
+ const parentPath = path.dirname(currentPath);
82
+ if (parentPath === currentPath) return null;
83
+ currentPath = parentPath;
84
+ }
85
+ };
86
+ var resolveProjectTitle = (graph) => {
87
+ const firstEntrypoint = graph.metadata.entrypoints[0];
88
+ if (!firstEntrypoint) return graph.metadata.packages[0]?.name ?? null;
89
+ const entrypointPath = path.isAbsolute(firstEntrypoint) ? firstEntrypoint : path.resolve(graph.metadata.basePath, firstEntrypoint);
90
+ const packageJsonPath = findClosestPackageJson(path.dirname(entrypointPath));
91
+ if (!packageJsonPath) return graph.metadata.packages[0]?.name ?? null;
92
+ try {
93
+ const packageJson = readJsonFile(packageJsonPath);
94
+ return packageJson.title ?? packageJson.name ?? graph.metadata.packages[0]?.name ?? null;
95
+ } catch {
96
+ return graph.metadata.packages[0]?.name ?? null;
97
+ }
98
+ };
99
+ var resolveSelectedGraphPath = (history, selection) => {
100
+ if (selection?.snapshotId?.trim()) {
101
+ const snapshot = history.find((item) => item.id === selection.snapshotId?.trim());
102
+ if (!snapshot) throw new Error(`Named snapshot \"${selection.snapshotId}\" was not found.`);
103
+ return snapshot.graphPath;
104
+ }
105
+ if (selection?.graphPath?.trim()) return path.resolve(selection.graphPath.trim());
106
+ return resolveGraphPath();
107
+ };
108
+ var loadModvizBundle = (selection) => {
109
+ const history = listSnapshotHistory();
110
+ let graphPath;
111
+ try {
112
+ graphPath = resolveSelectedGraphPath(history, selection);
113
+ } catch (error) {
114
+ return {
115
+ graph: null,
116
+ llm: null,
117
+ projectTitle: null,
118
+ summary: null,
119
+ history,
120
+ setup: {
121
+ status: "missing",
122
+ graphPath: selection?.graphPath?.trim() ?? resolveGraphPath(),
123
+ message: error instanceof Error ? error.message : "The selected snapshot could not be resolved."
124
+ }
125
+ };
126
+ }
127
+ const llmPath = resolveLlmPath(graphPath);
128
+ if (!fs.existsSync(graphPath)) return {
129
+ graph: null,
130
+ llm: null,
131
+ projectTitle: null,
132
+ summary: null,
133
+ history,
134
+ setup: {
135
+ status: "missing",
136
+ graphPath,
137
+ message: `No graph snapshot exists at ${graphPath}. Generate one with modviz analyze <entryFile> or choose a named snapshot from history.`
138
+ }
139
+ };
140
+ try {
141
+ const graph = readJsonFile(graphPath);
142
+ const llm = fs.existsSync(llmPath) ? readJsonFile(llmPath) : null;
143
+ return {
144
+ graph,
145
+ llm,
146
+ projectTitle: resolveProjectTitle(graph),
147
+ summary: buildModvizSummary(graph, llm),
148
+ history,
149
+ setup: {
150
+ status: "ready",
151
+ graphPath
152
+ }
153
+ };
154
+ } catch (error) {
155
+ return {
156
+ graph: null,
157
+ llm: null,
158
+ projectTitle: null,
159
+ summary: null,
160
+ history,
161
+ setup: {
162
+ status: "invalid",
163
+ graphPath,
164
+ message: error instanceof Error ? error.message : `Failed to read ${graphPath}.`
165
+ }
166
+ };
167
+ }
168
+ };
169
+ var getModvizJsonStatus = (selection) => {
170
+ const history = listSnapshotHistory();
171
+ let graphPath;
172
+ try {
173
+ graphPath = resolveSelectedGraphPath(history, selection);
174
+ } catch {
175
+ graphPath = selection?.graphPath?.trim() ?? resolveGraphPath();
176
+ }
177
+ const llmPath = resolveLlmPath(graphPath);
178
+ if (!fs.existsSync(graphPath)) return {
179
+ exists: false,
180
+ graphPath,
181
+ hasLlm: fs.existsSync(llmPath),
182
+ lastModified: null,
183
+ llmPath
184
+ };
185
+ const stat = fs.statSync(graphPath);
186
+ return {
187
+ exists: true,
188
+ graphPath,
189
+ hasLlm: fs.existsSync(llmPath),
190
+ lastModified: stat.mtimeMs,
191
+ llmPath
192
+ };
193
+ };
194
+ //#endregion
195
+ export { loadSnapshotGraph as a, listSnapshotHistory as i, loadModvizBundle as n, modviz_server_exports as r, getModvizJsonStatus as t };