depwire-cli 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,9 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  buildGraph,
4
+ calculateHealthScore,
4
5
  createEmptyState,
5
6
  generateDocs,
6
7
  getArchitectureSummary,
8
+ getHealthTrend,
7
9
  getImpact,
8
10
  parseProject,
9
11
  prepareVizData,
@@ -12,7 +14,7 @@ import {
12
14
  startVizServer,
13
15
  updateFileInGraph,
14
16
  watchProject
15
- } from "./chunk-Q733EWFA.js";
17
+ } from "./chunk-S3RUBXRF.js";
16
18
 
17
19
  // src/index.ts
18
20
  import { Command } from "commander";
@@ -86,6 +88,121 @@ function importFromJSON(json) {
86
88
  return graph;
87
89
  }
88
90
 
91
+ // src/health/display.ts
92
+ function formatHealthReport(report, trend, verbose) {
93
+ let output = "";
94
+ output += `
95
+ ${bold("Depwire Health Score")}
96
+
97
+ `;
98
+ const gradeColor = getGradeColor(report.grade);
99
+ let overallLine = `${bold("Overall:")} ${report.overall}/100 (${gradeColor(bold(`Grade: ${report.grade}`))})`;
100
+ if (trend) {
101
+ const trendColor = trend.startsWith("\u2191") ? green : trend.startsWith("\u2193") ? red : gray;
102
+ overallLine += ` ${trendColor(trend)} from last check`;
103
+ }
104
+ output += overallLine + "\n\n";
105
+ output += formatDimensionsTable(report.dimensions);
106
+ output += `
107
+ ${bold("Summary:")}
108
+ ${report.summary}
109
+
110
+ `;
111
+ if (report.recommendations.length > 0) {
112
+ output += `${yellow(bold("\u26A0\uFE0F Recommendations:"))}
113
+ `;
114
+ for (const rec of report.recommendations) {
115
+ output += ` \u2022 ${rec}
116
+ `;
117
+ }
118
+ output += "\n";
119
+ }
120
+ if (verbose) {
121
+ output += `${bold("Dimension Details:")}
122
+
123
+ `;
124
+ for (const dim of report.dimensions) {
125
+ output += `${bold(dim.name)} (${dim.score}/100, Grade: ${getGradeColor(dim.grade)(dim.grade)})
126
+ `;
127
+ output += ` ${dim.details}
128
+ `;
129
+ output += ` Metrics: ${JSON.stringify(dim.metrics, null, 2)}
130
+
131
+ `;
132
+ }
133
+ }
134
+ output += `${gray(`Parsed ${report.projectStats.files} files, ${report.projectStats.symbols} symbols, ${report.projectStats.edges} edges`)}
135
+ `;
136
+ return output;
137
+ }
138
+ function formatDimensionsTable(dimensions) {
139
+ const headers = ["Dimension", "Score", "Grade", "Weight"];
140
+ const widths = [25, 8, 8, 8];
141
+ let output = "";
142
+ output += "\u250C" + widths.map((w) => "\u2500".repeat(w)).join("\u252C") + "\u2510\n";
143
+ output += "\u2502";
144
+ headers.forEach((h, i) => {
145
+ output += " " + h.padEnd(widths[i] - 1);
146
+ output += "\u2502";
147
+ });
148
+ output += "\n";
149
+ output += "\u251C" + widths.map((w) => "\u2500".repeat(w)).join("\u253C") + "\u2524\n";
150
+ for (const dim of dimensions) {
151
+ output += "\u2502";
152
+ const gradeColor = getGradeColor(dim.grade);
153
+ output += " " + dim.name.padEnd(widths[0] - 1);
154
+ output += "\u2502";
155
+ output += " " + dim.score.toString().padEnd(widths[1] - 1);
156
+ output += "\u2502";
157
+ const gradePadded = dim.grade.padEnd(widths[2] - 1);
158
+ output += " " + gradeColor(gradePadded);
159
+ output += "\u2502";
160
+ const weightStr = `${(dim.weight * 100).toFixed(0)}%`;
161
+ output += " " + weightStr.padEnd(widths[3] - 1);
162
+ output += "\u2502";
163
+ output += "\n";
164
+ }
165
+ output += "\u2514" + widths.map((w) => "\u2500".repeat(w)).join("\u2534") + "\u2518\n";
166
+ return output;
167
+ }
168
+ function getGradeColor(grade) {
169
+ switch (grade) {
170
+ case "A":
171
+ return green;
172
+ case "B":
173
+ return cyan;
174
+ case "C":
175
+ return yellow;
176
+ case "D":
177
+ return magenta;
178
+ case "F":
179
+ return red;
180
+ default:
181
+ return gray;
182
+ }
183
+ }
184
+ function bold(text) {
185
+ return `\x1B[1m${text}\x1B[0m`;
186
+ }
187
+ function green(text) {
188
+ return `\x1B[32m${text}\x1B[0m`;
189
+ }
190
+ function cyan(text) {
191
+ return `\x1B[36m${text}\x1B[0m`;
192
+ }
193
+ function yellow(text) {
194
+ return `\x1B[33m${text}\x1B[0m`;
195
+ }
196
+ function magenta(text) {
197
+ return `\x1B[35m${text}\x1B[0m`;
198
+ }
199
+ function red(text) {
200
+ return `\x1B[31m${text}\x1B[0m`;
201
+ }
202
+ function gray(text) {
203
+ return `\x1B[90m${text}\x1B[0m`;
204
+ }
205
+
89
206
  // src/index.ts
90
207
  import { readFileSync as readFileSyncNode, appendFileSync, existsSync as existsSyncNode } from "fs";
91
208
  import { createInterface } from "readline";
@@ -354,4 +471,27 @@ ${pattern}
354
471
  console.error(`Warning: Failed to update .gitignore: ${err}`);
355
472
  }
356
473
  }
474
+ program.command("health <dir>").description("Analyze dependency architecture health (0-100 score)").option("--json", "Output as JSON").option("--verbose", "Show detailed breakdown").action(async (dir, options) => {
475
+ try {
476
+ const projectRoot = resolve(dir);
477
+ const startTime = Date.now();
478
+ const parsedFiles = await parseProject(projectRoot);
479
+ const graph = buildGraph(parsedFiles);
480
+ const parseTime = Date.now() - startTime;
481
+ const report = calculateHealthScore(graph, projectRoot);
482
+ const trend = getHealthTrend(projectRoot, report.overall);
483
+ if (options.json) {
484
+ console.log(JSON.stringify(report, null, 2));
485
+ } else {
486
+ const formatted = formatHealthReport(report, trend, options.verbose || false);
487
+ console.log(formatted);
488
+ const totalTime = Date.now() - startTime;
489
+ console.log(`Analysis completed in ${(totalTime / 1e3).toFixed(2)}s (parse: ${(parseTime / 1e3).toFixed(2)}s)
490
+ `);
491
+ }
492
+ } catch (err) {
493
+ console.error("Error analyzing health:", err);
494
+ process.exit(1);
495
+ }
496
+ });
357
497
  program.parse();
@@ -6,7 +6,7 @@ import {
6
6
  startMcpServer,
7
7
  updateFileInGraph,
8
8
  watchProject
9
- } from "./chunk-Q733EWFA.js";
9
+ } from "./chunk-S3RUBXRF.js";
10
10
 
11
11
  // src/mcpb-entry.ts
12
12
  import { resolve } from "path";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "depwire-cli",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "description": "Code cross-reference visualization and AI context engine for TypeScript, JavaScript, Python, and Go. Zero native dependencies — works on Windows, macOS, and Linux.",
5
5
  "type": "module",
6
6
  "bin": {