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,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "",
|
|
3
|
+
"short_name": "",
|
|
4
|
+
"icons": [
|
|
5
|
+
{
|
|
6
|
+
"src": "/android-chrome-192x192.png",
|
|
7
|
+
"sizes": "192x192",
|
|
8
|
+
"type": "image/png"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"src": "/android-chrome-512x512.png",
|
|
12
|
+
"sizes": "512x512",
|
|
13
|
+
"type": "image/png"
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"theme_color": "#ffffff",
|
|
17
|
+
"background_color": "#ffffff",
|
|
18
|
+
"display": "standalone"
|
|
19
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
const valueOptionNames = new Set([
|
|
2
|
+
"--port",
|
|
3
|
+
"--llm-base-url",
|
|
4
|
+
"--llm-model",
|
|
5
|
+
"--output-file",
|
|
6
|
+
"--barrel-threshold",
|
|
7
|
+
"--exclude",
|
|
8
|
+
"--history-dir",
|
|
9
|
+
"--include",
|
|
10
|
+
"--package",
|
|
11
|
+
"--node",
|
|
12
|
+
"--limit",
|
|
13
|
+
"--graph-file",
|
|
14
|
+
"--snapshot-name",
|
|
15
|
+
"--snapshot",
|
|
16
|
+
]);
|
|
17
|
+
const parseOptionTokens = (args) => {
|
|
18
|
+
const flags = new Set();
|
|
19
|
+
const values = new Map();
|
|
20
|
+
const missingValueOptions = [];
|
|
21
|
+
const positionals = [];
|
|
22
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
23
|
+
const currentArg = args[index];
|
|
24
|
+
if (!currentArg) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (currentArg === "--") {
|
|
28
|
+
positionals.push(...args.slice(index + 1));
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
if (!currentArg.startsWith("--")) {
|
|
32
|
+
positionals.push(currentArg);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (currentArg.startsWith("--no-")) {
|
|
36
|
+
flags.add(currentArg);
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const equalSignIndex = currentArg.indexOf("=");
|
|
40
|
+
const optionName = equalSignIndex === -1 ? currentArg : currentArg.slice(0, equalSignIndex);
|
|
41
|
+
if (equalSignIndex !== -1) {
|
|
42
|
+
values.set(optionName, currentArg.slice(equalSignIndex + 1));
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (valueOptionNames.has(optionName)) {
|
|
46
|
+
const nextArg = args[index + 1];
|
|
47
|
+
if (nextArg && nextArg !== "--" && !nextArg.startsWith("--")) {
|
|
48
|
+
values.set(optionName, nextArg);
|
|
49
|
+
index += 1;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
missingValueOptions.push(optionName);
|
|
53
|
+
}
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
flags.add(optionName);
|
|
57
|
+
}
|
|
58
|
+
return { flags, values, missingValueOptions, positionals };
|
|
59
|
+
};
|
|
60
|
+
export function parseCliArgs(args) {
|
|
61
|
+
const [firstArg, ...restArgs] = args;
|
|
62
|
+
const command = firstArg === "analyze" || firstArg === "serve" || firstArg === "report" || firstArg === "diff"
|
|
63
|
+
? firstArg
|
|
64
|
+
: "analyze";
|
|
65
|
+
const commandArgs = command === "analyze" && firstArg !== "analyze" ? args : restArgs;
|
|
66
|
+
const { flags: parsedFlags, values: parsedValues, missingValueOptions, positionals, } = parseOptionTokens(commandArgs);
|
|
67
|
+
const serve = args.includes("--serve");
|
|
68
|
+
const effectiveServe = command === "serve" || serve;
|
|
69
|
+
const getOptionValue = (name) => parsedValues.get(name);
|
|
70
|
+
const hasFlag = (name) => parsedFlags.has(name);
|
|
71
|
+
return {
|
|
72
|
+
command,
|
|
73
|
+
entryFile: effectiveServe || command === "report" ? undefined : positionals[0],
|
|
74
|
+
serveDataFile: effectiveServe ? positionals[0] : undefined,
|
|
75
|
+
flags: {
|
|
76
|
+
port: getOptionValue("--port") ?? "3628",
|
|
77
|
+
open: !hasFlag("--no-open"),
|
|
78
|
+
ui: hasFlag("--ui"),
|
|
79
|
+
barrelThreshold: Number.parseInt(getOptionValue("--barrel-threshold") ?? "3", 10),
|
|
80
|
+
exclude: getOptionValue("--exclude"),
|
|
81
|
+
historyDir: getOptionValue("--history-dir"),
|
|
82
|
+
include: getOptionValue("--include"),
|
|
83
|
+
llmAnalyze: hasFlag("--llm-analyze"),
|
|
84
|
+
llmBaseUrl: getOptionValue("--llm-base-url"),
|
|
85
|
+
llmModel: getOptionValue("--llm-model"),
|
|
86
|
+
outputFile: getOptionValue("--output-file") ?? "./modviz.json",
|
|
87
|
+
nodeModules: hasFlag("--node-modules"),
|
|
88
|
+
ignoreDynamic: hasFlag("--ignore-dynamic"),
|
|
89
|
+
ignoreTypeOnly: hasFlag("--ignore-type-only"),
|
|
90
|
+
serve: effectiveServe,
|
|
91
|
+
help: commandArgs.includes("--help") || commandArgs.includes("-h"),
|
|
92
|
+
llm: hasFlag("--llm"),
|
|
93
|
+
packageQuery: getOptionValue("--package"),
|
|
94
|
+
nodeQuery: getOptionValue("--node"),
|
|
95
|
+
limit: Number.parseInt(getOptionValue("--limit") ?? "20", 10),
|
|
96
|
+
summary: hasFlag("--summary"),
|
|
97
|
+
graphFile: getOptionValue("--graph-file"),
|
|
98
|
+
snapshotName: getOptionValue("--snapshot-name"),
|
|
99
|
+
snapshot: getOptionValue("--snapshot"),
|
|
100
|
+
listSnapshots: hasFlag("--list-snapshots"),
|
|
101
|
+
},
|
|
102
|
+
missingValueOptions,
|
|
103
|
+
positionals,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
export function validateCliArgs(parsedArgs) {
|
|
107
|
+
const { command, entryFile, flags, missingValueOptions = [] } = parsedArgs;
|
|
108
|
+
if (missingValueOptions.length > 0) {
|
|
109
|
+
return `Missing value for ${missingValueOptions[0]}`;
|
|
110
|
+
}
|
|
111
|
+
if (command === "analyze" && !flags.serve && !entryFile && !flags.help) {
|
|
112
|
+
return "Entry file is required when not using --serve.";
|
|
113
|
+
}
|
|
114
|
+
if (command === "report" &&
|
|
115
|
+
!flags.summary &&
|
|
116
|
+
!flags.packageQuery &&
|
|
117
|
+
!flags.nodeQuery &&
|
|
118
|
+
!flags.listSnapshots &&
|
|
119
|
+
!flags.help) {
|
|
120
|
+
return "Report command requires --summary, --package, --node, or --list-snapshots.";
|
|
121
|
+
}
|
|
122
|
+
if (command === "diff" && !flags.help && (parsedArgs.positionals?.length ?? 0) < 2) {
|
|
123
|
+
return "Diff command requires <baseline> and <current> graph targets.";
|
|
124
|
+
}
|
|
125
|
+
if (flags.port && Number.isNaN(Number.parseInt(flags.port, 10))) {
|
|
126
|
+
return `Invalid --port value: ${flags.port}`;
|
|
127
|
+
}
|
|
128
|
+
if (!Number.isFinite(flags.limit) || flags.limit < 1) {
|
|
129
|
+
return `Invalid --limit value: ${flags.limit}`;
|
|
130
|
+
}
|
|
131
|
+
if (!Number.isFinite(flags.barrelThreshold) || flags.barrelThreshold < 1) {
|
|
132
|
+
return `Invalid --barrel-threshold value: ${flags.barrelThreshold}`;
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
export function buildCliHelpText() {
|
|
137
|
+
return `
|
|
138
|
+
modviz - Module dependency graph visualizer and import analysis CLI
|
|
139
|
+
|
|
140
|
+
Usage:
|
|
141
|
+
modviz analyze <entryFile> Generate graph JSON for the UI
|
|
142
|
+
modviz serve [dataFile] Launch the web UI with existing graph data
|
|
143
|
+
modviz report --summary Print a concise terminal summary from an existing graph file
|
|
144
|
+
modviz diff <baseline> <current> Print graph deltas between two graph files or snapshot:<id> targets
|
|
145
|
+
modviz report --package=zod Print origin traces for one external package
|
|
146
|
+
modviz report --node=src/foo.ts Print origin traces for one node
|
|
147
|
+
modviz report --list-snapshots Show named snapshot history
|
|
148
|
+
modviz <entryFile> Legacy shorthand for analyze <entryFile>
|
|
149
|
+
|
|
150
|
+
Options:
|
|
151
|
+
--output-file=<file> Base JSON output path for the UI graph (default: ./modviz.json)
|
|
152
|
+
--graph-file=<file> Existing graph file used by report (default: ./modviz.json)
|
|
153
|
+
--port=<port> Port for the web server (default: 3628)
|
|
154
|
+
--no-open Do not open a browser window when launching the UI
|
|
155
|
+
--ui Launch the browser UI after generating the graph
|
|
156
|
+
--barrel-threshold=<n> Export count that marks a file as a barrel file (default: 3)
|
|
157
|
+
--include=<glob,...> Keep only matching paths in the generated graph
|
|
158
|
+
--exclude=<glob,...> Drop matching paths from the generated graph
|
|
159
|
+
--history-dir=<dir> Override the snapshot history directory for report, diff, and saved snapshots
|
|
160
|
+
--serve Launch the UI server using an existing graph JSON file
|
|
161
|
+
--llm Also emit <output>.llm.json and <output>.llm.md focused on import origins and barrel-file impact
|
|
162
|
+
--llm-analyze Use the Vercel AI SDK to turn the structured LLM report into <output>.llm.ai.md
|
|
163
|
+
--llm-model=<model> Override the OpenAI-compatible model used by --llm-analyze
|
|
164
|
+
--llm-base-url=<url> Override the OpenAI-compatible base URL used by --llm-analyze
|
|
165
|
+
--package=<name> Focus outputs and drilldowns on one external package
|
|
166
|
+
--node=<path> Focus outputs and drilldowns on one node path or display path
|
|
167
|
+
--limit=<n> Limit printed drilldown lists and cap stored origin chains per node (default: 5)
|
|
168
|
+
--summary Print a terminal summary of the generated graph
|
|
169
|
+
--snapshot-name=<name> Save the generated snapshot into history under a named run
|
|
170
|
+
--snapshot=<id> Load a named history snapshot for report
|
|
171
|
+
--list-snapshots List available named snapshots
|
|
172
|
+
--node-modules Keep node_modules in the analyzed graph instead of excluding them
|
|
173
|
+
--ignore-dynamic Ignore dynamic imports
|
|
174
|
+
--ignore-type-only Ignore type-only imports
|
|
175
|
+
--help, -h Show this help message
|
|
176
|
+
|
|
177
|
+
Examples:
|
|
178
|
+
modviz analyze src/index.ts --ui --port=4000
|
|
179
|
+
modviz analyze src/index.ts --llm --snapshot-name=before-refactor
|
|
180
|
+
modviz analyze src/index.ts --barrel-threshold=5
|
|
181
|
+
modviz analyze src/index.ts --include='src/routes/**,src/components/**' --exclude='**/*.test.ts'
|
|
182
|
+
modviz analyze src/index.ts --node-modules --package=googleapis
|
|
183
|
+
modviz serve ./modviz.json
|
|
184
|
+
modviz report --summary
|
|
185
|
+
modviz diff snapshot:before-refactor ./modviz.json
|
|
186
|
+
modviz report --snapshot=2026-04-01t12-00-00-before-refactor --package=googleapis
|
|
187
|
+
modviz report --list-snapshots
|
|
188
|
+
`;
|
|
189
|
+
}
|
|
190
|
+
const getExternalPackageName = (node) => {
|
|
191
|
+
const segments = node.path.split(/[\\/]/).filter(Boolean);
|
|
192
|
+
const nodeModulesIndex = segments.lastIndexOf("node_modules");
|
|
193
|
+
if (nodeModulesIndex === -1) {
|
|
194
|
+
return node.package?.name ?? "external";
|
|
195
|
+
}
|
|
196
|
+
const scopeOrName = segments[nodeModulesIndex + 1];
|
|
197
|
+
const maybeName = segments[nodeModulesIndex + 2];
|
|
198
|
+
if (!scopeOrName) {
|
|
199
|
+
return "node_modules";
|
|
200
|
+
}
|
|
201
|
+
return scopeOrName.startsWith("@") && maybeName ? `${scopeOrName}/${maybeName}` : scopeOrName;
|
|
202
|
+
};
|
|
203
|
+
export function buildCliSummary(output) {
|
|
204
|
+
const workspaceNodes = output.nodes.filter((node) => node.type !== "external");
|
|
205
|
+
const externalNodes = output.nodes.filter((node) => node.type === "external");
|
|
206
|
+
const externalPackages = new Set(externalNodes.map((node) => getExternalPackageName(node)));
|
|
207
|
+
return [
|
|
208
|
+
"",
|
|
209
|
+
"Graph summary",
|
|
210
|
+
`- Nodes: ${output.nodes.length} total (${workspaceNodes.length} workspace, ${externalNodes.length} external)`,
|
|
211
|
+
`- Edges: ${output.imports.length}`,
|
|
212
|
+
`- Workspace packages: ${output.metadata.packages.length}`,
|
|
213
|
+
`- External packages: ${externalPackages.size}`,
|
|
214
|
+
`- Barrel files: ${output.nodes.filter((node) => node.isBarrelFile).length}`,
|
|
215
|
+
`- Entrypoints: ${output.metadata.entrypoints.join(", ") || "none"}`,
|
|
216
|
+
].join("\n");
|
|
217
|
+
}
|
|
218
|
+
export function buildSnapshotList(history) {
|
|
219
|
+
if (history.length === 0) {
|
|
220
|
+
return "No named snapshots found.\n";
|
|
221
|
+
}
|
|
222
|
+
return `${history
|
|
223
|
+
.map((snapshot) => `- ${snapshot.id} (${snapshot.totalNodes} nodes${snapshot.generatedAt ? `, generated ${snapshot.generatedAt}` : ""})`)
|
|
224
|
+
.join("\n")}\n`;
|
|
225
|
+
}
|