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.
- package/README.md +261 -0
- package/dist/client/_shell.html +0 -0
- package/dist/client/android-chrome-192x192.png +0 -0
- package/dist/client/android-chrome-512x512.png +0 -0
- package/dist/client/apple-touch-icon.png +0 -0
- package/dist/client/assets/app-Sjrldkrg.css +2 -0
- package/dist/client/assets/button-aOWckyNs.js +1 -0
- package/dist/client/assets/check-C0EQe2S8.js +1 -0
- package/dist/client/assets/chevron-down-DrspihmT.js +1 -0
- package/dist/client/assets/chevron-right-DIJHr8AN.js +1 -0
- package/dist/client/assets/colors-CQoWjU5E.js +1 -0
- package/dist/client/assets/command-kkF7_wdz.js +45 -0
- package/dist/client/assets/compare-K6jVFsiI.js +1 -0
- package/dist/client/assets/compare-TOnoe1EP.js +2 -0
- package/dist/client/assets/configure-DnlSnhtN.js +1 -0
- package/dist/client/assets/explorer-C7NclVKg.js +2 -0
- package/dist/client/assets/explorer-Xu2X6XXF.js +1 -0
- package/dist/client/assets/external-link-B9eNA-li.js +1 -0
- package/dist/client/assets/flamegraph-CRVZSAlj.js +13 -0
- package/dist/client/assets/floating-ui.dom-DLIT5tPE.js +1 -0
- package/dist/client/assets/formatting-CiC0SYI8.js +1 -0
- package/dist/client/assets/graph-6Vr74V1k.js +2 -0
- package/dist/client/assets/graph-CVzypIGU.js +2 -0
- package/dist/client/assets/graph-command-menu-D2MoVT2B.js +4 -0
- package/dist/client/assets/graph-command-menu-VWiiW3qy.css +1 -0
- package/dist/client/assets/hierarchy-C8xxGb_u.js +2 -0
- package/dist/client/assets/hierarchy-iO7d4oSK.js +2 -0
- package/dist/client/assets/import-display-D-jRyyjM.js +5 -0
- package/dist/client/assets/imports-CPggnrs-.js +2 -0
- package/dist/client/assets/imports-CodbPyUJ.js +1 -0
- package/dist/client/assets/index-Dj_rhLdR.js +12 -0
- package/dist/client/assets/input-BCFMF0aR.js +1 -0
- package/dist/client/assets/jsx-runtime-DWSWI4JT.js +1 -0
- package/dist/client/assets/lazyRouteComponent-PTSyFp1J.js +1 -0
- package/dist/client/assets/loading-state-CyC_hrTF.js +1 -0
- package/dist/client/assets/modviz-data-BiRqoDI5.js +1 -0
- package/dist/client/assets/modviz-layout-Do93E-IB.js +1 -0
- package/dist/client/assets/modviz-sigma-Xl8qHaxK.js +312 -0
- package/dist/client/assets/portal-BgAm3V3j.js +1 -0
- package/dist/client/assets/routes-DBtN8hrZ.js +1 -0
- package/dist/client/assets/schemas-B4zfTepZ.js +39 -0
- package/dist/client/assets/search-BYHxNrYn.js +1 -0
- package/dist/client/assets/search-params-BaZRBvGI.js +1 -0
- package/dist/client/assets/setup-view-j1o0TuZz.js +1 -0
- package/dist/client/assets/summary-D703Zh3x.js +1 -0
- package/dist/client/assets/tooltip-B1VDU9HG.js +1 -0
- package/dist/client/assets/trace-B67CM5s2.js +2 -0
- package/dist/client/assets/trace-Bwwdw3AM.js +1 -0
- package/dist/client/assets/treemap-BZf2shzY.js +5 -0
- package/dist/client/assets/treemap-Csroy8Gy.js +2 -0
- package/dist/client/assets/utils-DkkZd0ys.js +1 -0
- package/dist/client/favicon-16x16.png +0 -0
- package/dist/client/favicon-32x32.png +0 -0
- package/dist/client/favicon.ico +0 -0
- package/dist/client/favicon.png +0 -0
- package/dist/client/site.webmanifest +19 -0
- package/dist/mod/cli-options.js +225 -0
- package/dist/mod/cli.js +519 -0
- package/dist/mod/index.js +3 -0
- package/dist/mod/llm-analysis.js +29 -0
- package/dist/mod/llm-output.js +742 -0
- package/dist/mod/module-graph-plugins.js +60 -0
- package/dist/mod/production-server.js +103 -0
- package/dist/mod/runtime-host.js +217 -0
- package/dist/mod/snapshot-history.js +73 -0
- package/dist/mod/types.js +3 -0
- package/dist/server/assets/__23tanstack-start-plugin-adapters-3QxJs4a0.js +5 -0
- package/dist/server/assets/_tanstack-start-manifest_v-DMytuIue.js +188 -0
- package/dist/server/assets/button-Bqnnid5i.js +41 -0
- package/dist/server/assets/colors-DhAxrYua.js +100 -0
- package/dist/server/assets/command-SdxShIbL.js +138 -0
- package/dist/server/assets/compare-BFMiiUsB.js +562 -0
- package/dist/server/assets/compare-CpOqTpYu.js +10 -0
- package/dist/server/assets/configure-Bvd45DTI.js +288 -0
- package/dist/server/assets/explorer-C7dODpSv.js +379 -0
- package/dist/server/assets/explorer-CpSb0JTa.js +20 -0
- package/dist/server/assets/flamegraph-CdW-VG6I.js +198 -0
- package/dist/server/assets/formatting-iDlL4tA-.js +4 -0
- package/dist/server/assets/graph-C1G9H5O4.js +438 -0
- package/dist/server/assets/graph-DAGFGioS.js +45 -0
- package/dist/server/assets/graph-command-menu-BV5GtOWx.js +249 -0
- package/dist/server/assets/hierarchy-B4K-Zfn9.js +16 -0
- package/dist/server/assets/hierarchy-BGpWSG-f.js +104 -0
- package/dist/server/assets/import-display-BVIOWcsm.js +124 -0
- package/dist/server/assets/imports-B6JBDl_h.js +379 -0
- package/dist/server/assets/imports-BGe5tZJT.js +28 -0
- package/dist/server/assets/input-C5r-hBix.js +19 -0
- package/dist/server/assets/loading-state-CrvCWTtw.js +23 -0
- package/dist/server/assets/modviz-data-CUyTorv0.js +197 -0
- package/dist/server/assets/modviz-layout-BAH2ogse.js +253 -0
- package/dist/server/assets/modviz-server-DoMlAyFW.js +195 -0
- package/dist/server/assets/modviz-sigma-XYxARWqd.js +1441 -0
- package/dist/server/assets/rolldown-runtime-rSIU-vHC.js +13 -0
- package/dist/server/assets/router-DYJ-zDbU.js +353 -0
- package/dist/server/assets/routes-DInCacpY.js +244 -0
- package/dist/server/assets/search-params-BNApPgkX.js +26 -0
- package/dist/server/assets/setup-view-DjI49Iqr.js +91 -0
- package/dist/server/assets/start-Ba3KII43.js +4 -0
- package/dist/server/assets/summary-z3lXkLCQ.js +208 -0
- package/dist/server/assets/tooltip-Ck0DDfF7.js +24 -0
- package/dist/server/assets/trace-ColKOf9g.js +16 -0
- package/dist/server/assets/trace-eVs-hIZO.js +578 -0
- package/dist/server/assets/treemap-BbZ9M4GF.js +17 -0
- package/dist/server/assets/treemap-CrgWFoCF.js +912 -0
- package/dist/server/assets/utils-BQZm0uva.js +8 -0
- package/dist/server/server.js +5259 -0
- package/dist/shared/modviz-compare.js +120 -0
- package/dist/shared/modviz-trace.js +244 -0
- 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 };
|