@girardelli/architect 1.3.0 → 2.2.0
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 +111 -112
- package/dist/agent-generator.d.ts +106 -0
- package/dist/agent-generator.d.ts.map +1 -0
- package/dist/agent-generator.js +1398 -0
- package/dist/agent-generator.js.map +1 -0
- package/dist/cli.js +132 -15
- package/dist/cli.js.map +1 -1
- package/dist/html-reporter.d.ts +8 -2
- package/dist/html-reporter.d.ts.map +1 -1
- package/dist/html-reporter.js +773 -50
- package/dist/html-reporter.js.map +1 -1
- package/dist/index.d.ts +26 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -1
- package/dist/index.js.map +1 -1
- package/dist/refactor-engine.d.ts +18 -0
- package/dist/refactor-engine.d.ts.map +1 -0
- package/dist/refactor-engine.js +86 -0
- package/dist/refactor-engine.js.map +1 -0
- package/dist/refactor-reporter.d.ts +20 -0
- package/dist/refactor-reporter.d.ts.map +1 -0
- package/dist/refactor-reporter.js +389 -0
- package/dist/refactor-reporter.js.map +1 -0
- package/dist/rules/barrel-optimizer.d.ts +13 -0
- package/dist/rules/barrel-optimizer.d.ts.map +1 -0
- package/dist/rules/barrel-optimizer.js +77 -0
- package/dist/rules/barrel-optimizer.js.map +1 -0
- package/dist/rules/dead-code-detector.d.ts +21 -0
- package/dist/rules/dead-code-detector.d.ts.map +1 -0
- package/dist/rules/dead-code-detector.js +117 -0
- package/dist/rules/dead-code-detector.js.map +1 -0
- package/dist/rules/hub-splitter.d.ts +13 -0
- package/dist/rules/hub-splitter.d.ts.map +1 -0
- package/dist/rules/hub-splitter.js +110 -0
- package/dist/rules/hub-splitter.js.map +1 -0
- package/dist/rules/import-organizer.d.ts +13 -0
- package/dist/rules/import-organizer.d.ts.map +1 -0
- package/dist/rules/import-organizer.js +85 -0
- package/dist/rules/import-organizer.js.map +1 -0
- package/dist/rules/module-grouper.d.ts +13 -0
- package/dist/rules/module-grouper.d.ts.map +1 -0
- package/dist/rules/module-grouper.js +110 -0
- package/dist/rules/module-grouper.js.map +1 -0
- package/dist/types.d.ts +51 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/agent-generator.ts +1526 -0
- package/src/cli.ts +150 -15
- package/src/html-reporter.ts +799 -51
- package/src/index.ts +39 -1
- package/src/refactor-engine.ts +117 -0
- package/src/refactor-reporter.ts +408 -0
- package/src/rules/barrel-optimizer.ts +97 -0
- package/src/rules/dead-code-detector.ts +132 -0
- package/src/rules/hub-splitter.ts +123 -0
- package/src/rules/import-organizer.ts +98 -0
- package/src/rules/module-grouper.ts +124 -0
- package/src/types.ts +52 -0
package/src/cli.ts
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import { architect } from './index.js';
|
|
17
17
|
import { ReportGenerator } from './reporter.js';
|
|
18
18
|
import { HtmlReportGenerator } from './html-reporter.js';
|
|
19
|
+
import { RefactorReportGenerator } from './refactor-reporter.js';
|
|
19
20
|
import { writeFileSync } from 'fs';
|
|
20
21
|
import { resolve, basename } from 'path';
|
|
21
22
|
|
|
@@ -28,6 +29,45 @@ interface CliOptions {
|
|
|
28
29
|
output?: string;
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
/**
|
|
33
|
+
* CLI Progress Logger — mostra estágio atual e tempo decorrido
|
|
34
|
+
* Usa output síncrono (console.log) porque as operações do Architect bloqueiam o event loop.
|
|
35
|
+
*/
|
|
36
|
+
class ProgressLogger {
|
|
37
|
+
private startTime: number;
|
|
38
|
+
private stageStart: number;
|
|
39
|
+
private currentStage = '';
|
|
40
|
+
|
|
41
|
+
constructor() {
|
|
42
|
+
this.startTime = Date.now();
|
|
43
|
+
this.stageStart = Date.now();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
start(stage: string): void {
|
|
47
|
+
this.currentStage = stage;
|
|
48
|
+
this.stageStart = Date.now();
|
|
49
|
+
// Print immediately so user sees it BEFORE the blocking operation
|
|
50
|
+
console.log(`⏳ ${stage}`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
complete(message?: string): void {
|
|
54
|
+
const elapsed = ((Date.now() - this.stageStart) / 1000).toFixed(1);
|
|
55
|
+
const total = ((Date.now() - this.startTime) / 1000).toFixed(1);
|
|
56
|
+
const displayMsg = message || this.currentStage;
|
|
57
|
+
console.log(`✅ ${displayMsg} (${elapsed}s | total: ${total}s)`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
fail(message: string): void {
|
|
61
|
+
const elapsed = ((Date.now() - this.stageStart) / 1000).toFixed(1);
|
|
62
|
+
console.log(`⚠️ ${message} (${elapsed}s)`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
summary(lines: string[]): void {
|
|
66
|
+
const total = ((Date.now() - this.startTime) / 1000).toFixed(1);
|
|
67
|
+
console.log(`\n⏱️ Completed in ${total}s`);
|
|
68
|
+
lines.forEach(l => console.log(l));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
31
71
|
function parseArgs(args: string[]): CliOptions {
|
|
32
72
|
const command = args[0] || 'analyze';
|
|
33
73
|
const pathArg = args.find((a) => !a.startsWith('--') && a !== command) || '.';
|
|
@@ -48,6 +88,8 @@ Usage:
|
|
|
48
88
|
|
|
49
89
|
Commands:
|
|
50
90
|
analyze Full architecture analysis (default)
|
|
91
|
+
refactor Generate refactoring plan with actionable steps
|
|
92
|
+
agents Generate/audit .agent/ directory with AI agents
|
|
51
93
|
diagram Generate architecture diagram only
|
|
52
94
|
score Calculate quality score only
|
|
53
95
|
anti-patterns Detect anti-patterns only
|
|
@@ -84,39 +126,132 @@ async function main(): Promise<void> {
|
|
|
84
126
|
try {
|
|
85
127
|
switch (options.command) {
|
|
86
128
|
case 'analyze': {
|
|
129
|
+
const progress = new ProgressLogger();
|
|
130
|
+
|
|
131
|
+
progress.start('Scanning files & analyzing architecture...');
|
|
87
132
|
const report = await architect.analyze(options.path);
|
|
133
|
+
progress.complete(`Scanned ${report.projectInfo.totalFiles} files (${report.projectInfo.totalLines.toLocaleString()} lines)`);
|
|
134
|
+
|
|
135
|
+
progress.start('Generating refactoring plan...');
|
|
136
|
+
const plan = architect.refactor(report, options.path);
|
|
137
|
+
progress.complete(`Refactoring plan: ${plan.steps.length} steps, ${plan.totalOperations} operations`);
|
|
138
|
+
|
|
139
|
+
progress.start('Analyzing agent system...');
|
|
140
|
+
const agentSuggestion = architect.suggestAgents(report, plan, options.path);
|
|
141
|
+
progress.complete(`Agents: ${agentSuggestion.suggestedAgents.length} suggested${agentSuggestion.hasExistingAgents ? ' (existing .agent/ audited)' : ''}`);
|
|
142
|
+
|
|
88
143
|
const projectName = report.projectInfo.name || basename(options.path);
|
|
89
144
|
|
|
90
145
|
if (options.format === 'html') {
|
|
146
|
+
progress.start('Building HTML report...');
|
|
91
147
|
const htmlGenerator = new HtmlReportGenerator();
|
|
92
|
-
const html = htmlGenerator.generateHtml(report);
|
|
148
|
+
const html = htmlGenerator.generateHtml(report, plan, agentSuggestion);
|
|
93
149
|
const outputPath = options.output || `architect-report-${projectName}.html`;
|
|
94
150
|
writeFileSync(outputPath, html);
|
|
95
|
-
|
|
96
|
-
console.log(`📊 Score: ${report.score.overall}/100`);
|
|
97
|
-
console.log(`⚠️ Anti-patterns: ${report.antiPatterns.length}`);
|
|
151
|
+
progress.complete(`HTML report saved: ${outputPath}`);
|
|
98
152
|
} else if (options.format === 'markdown') {
|
|
153
|
+
progress.start('Building Markdown report...');
|
|
99
154
|
const mdGenerator = new ReportGenerator();
|
|
100
155
|
const markdown = mdGenerator.generateMarkdownReport(report);
|
|
101
156
|
const outputPath = options.output || `architect-report-${projectName}.md`;
|
|
102
157
|
writeFileSync(outputPath, markdown);
|
|
103
|
-
|
|
158
|
+
progress.complete(`Markdown report saved: ${outputPath}`);
|
|
104
159
|
} else {
|
|
160
|
+
progress.start('Building JSON report...');
|
|
105
161
|
const outputPath = options.output || `architect-report-${projectName}.json`;
|
|
106
|
-
writeFileSync(outputPath, JSON.stringify(report, null, 2));
|
|
107
|
-
|
|
162
|
+
writeFileSync(outputPath, JSON.stringify({ report, plan, agentSuggestion }, null, 2));
|
|
163
|
+
progress.complete(`JSON report saved: ${outputPath}`);
|
|
108
164
|
}
|
|
109
165
|
|
|
110
|
-
// Print summary
|
|
166
|
+
// Print summary
|
|
167
|
+
progress.summary([
|
|
168
|
+
``,
|
|
169
|
+
`═══════════════════════════════════════`,
|
|
170
|
+
` SCORE: ${report.score.overall}/100`,
|
|
171
|
+
`═══════════════════════════════════════`,
|
|
172
|
+
`├─ Modularity: ${report.score.breakdown.modularity}`,
|
|
173
|
+
`├─ Coupling: ${report.score.breakdown.coupling}`,
|
|
174
|
+
`├─ Cohesion: ${report.score.breakdown.cohesion}`,
|
|
175
|
+
`└─ Layering: ${report.score.breakdown.layering}`,
|
|
176
|
+
``,
|
|
177
|
+
`📁 Files: ${report.projectInfo.totalFiles} | 📝 Lines: ${report.projectInfo.totalLines.toLocaleString()}`,
|
|
178
|
+
`⚠️ Anti-patterns: ${report.antiPatterns.length}`,
|
|
179
|
+
`🔧 Refactoring: ${plan.steps.length} steps (${plan.totalOperations} ops)`,
|
|
180
|
+
`🤖 Agents: ${agentSuggestion.suggestedAgents.length} suggested`,
|
|
181
|
+
]);
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
case 'refactor': {
|
|
186
|
+
const report = await architect.analyze(options.path);
|
|
187
|
+
const plan = architect.refactor(report, options.path);
|
|
188
|
+
const projectName = report.projectInfo.name || basename(options.path);
|
|
189
|
+
|
|
190
|
+
if (options.format === 'json') {
|
|
191
|
+
const outputPath = options.output || `refactor-plan-${projectName}.json`;
|
|
192
|
+
writeFileSync(outputPath, JSON.stringify(plan, null, 2));
|
|
193
|
+
console.log(`✅ JSON refactoring plan saved to: ${outputPath}`);
|
|
194
|
+
} else {
|
|
195
|
+
const refactorReporter = new RefactorReportGenerator();
|
|
196
|
+
const html = refactorReporter.generateHtml(plan);
|
|
197
|
+
const outputPath = options.output || `refactor-plan-${projectName}.html`;
|
|
198
|
+
writeFileSync(outputPath, html);
|
|
199
|
+
console.log(`✅ Refactoring plan saved to: ${outputPath}`);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
console.log(`\n═══════════════════════════════════════`);
|
|
203
|
+
console.log(` REFACTORING PLAN`);
|
|
204
|
+
console.log(`═══════════════════════════════════════`);
|
|
205
|
+
console.log(`├─ Steps: ${plan.steps.length}`);
|
|
206
|
+
console.log(`├─ Operations: ${plan.totalOperations}`);
|
|
207
|
+
console.log(`├─ Tier 1: ${plan.tier1Steps} (rule-based)`);
|
|
208
|
+
console.log(`├─ Tier 2: ${plan.tier2Steps} (AST-based)`);
|
|
209
|
+
console.log(`├─ Current: ${plan.currentScore.overall}/100`);
|
|
210
|
+
console.log(`└─ Estimated: ${plan.estimatedScoreAfter.overall}/100 (+${plan.estimatedScoreAfter.overall - plan.currentScore.overall})`);
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
case 'agents': {
|
|
215
|
+
const report = await architect.analyze(options.path);
|
|
216
|
+
const plan = architect.refactor(report, options.path);
|
|
217
|
+
const outputDir = options.output || undefined;
|
|
218
|
+
const result = architect.agents(report, plan, options.path, outputDir);
|
|
219
|
+
|
|
111
220
|
console.log(`\n═══════════════════════════════════════`);
|
|
112
|
-
console.log(`
|
|
221
|
+
console.log(` 🤖 AGENT SYSTEM`);
|
|
113
222
|
console.log(`═══════════════════════════════════════`);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
223
|
+
|
|
224
|
+
if (result.generated.length > 0) {
|
|
225
|
+
console.log(`\n✅ Generated ${result.generated.length} files:`);
|
|
226
|
+
for (const file of result.generated) {
|
|
227
|
+
console.log(` 📄 ${file}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (result.audit.length > 0) {
|
|
232
|
+
const missing = result.audit.filter(f => f.type === 'MISSING');
|
|
233
|
+
const improvements = result.audit.filter(f => f.type === 'IMPROVEMENT');
|
|
234
|
+
const ok = result.audit.filter(f => f.type === 'OK');
|
|
235
|
+
|
|
236
|
+
if (ok.length > 0) {
|
|
237
|
+
console.log(`\n✅ ${ok.length} checks passed`);
|
|
238
|
+
}
|
|
239
|
+
if (missing.length > 0) {
|
|
240
|
+
console.log(`\n❌ ${missing.length} missing (auto-generated):`);
|
|
241
|
+
for (const f of missing) {
|
|
242
|
+
console.log(` 📄 ${f.file} — ${f.description}`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (improvements.length > 0) {
|
|
246
|
+
console.log(`\n💡 ${improvements.length} improvement suggestions:`);
|
|
247
|
+
for (const f of improvements) {
|
|
248
|
+
console.log(` ⚡ ${f.description}`);
|
|
249
|
+
if (f.suggestion) console.log(` → ${f.suggestion}`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
console.log(`\n📊 Score: ${report.score.overall}/100`);
|
|
120
255
|
break;
|
|
121
256
|
}
|
|
122
257
|
|