@girardelli/architect-core 8.1.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/dist/src/core/analyzer.d.ts +42 -0
- package/dist/src/core/analyzer.js +431 -0
- package/dist/src/core/analyzer.js.map +1 -0
- package/dist/src/core/analyzers/forecast.d.ts +84 -0
- package/dist/src/core/analyzers/forecast.js +338 -0
- package/dist/src/core/analyzers/forecast.js.map +1 -0
- package/dist/src/core/analyzers/index.d.ts +9 -0
- package/dist/src/core/analyzers/index.js +7 -0
- package/dist/src/core/analyzers/index.js.map +1 -0
- package/dist/src/core/analyzers/temporal-scorer.d.ts +71 -0
- package/dist/src/core/analyzers/temporal-scorer.js +141 -0
- package/dist/src/core/analyzers/temporal-scorer.js.map +1 -0
- package/dist/src/core/anti-patterns.d.ts +28 -0
- package/dist/src/core/anti-patterns.js +264 -0
- package/dist/src/core/anti-patterns.js.map +1 -0
- package/dist/src/core/ast/ast-parser.interface.d.ts +20 -0
- package/dist/src/core/ast/ast-parser.interface.js +2 -0
- package/dist/src/core/ast/ast-parser.interface.js.map +1 -0
- package/dist/src/core/ast/path-resolver.d.ts +13 -0
- package/dist/src/core/ast/path-resolver.js +54 -0
- package/dist/src/core/ast/path-resolver.js.map +1 -0
- package/dist/src/core/ast/tree-sitter-parser.d.ts +10 -0
- package/dist/src/core/ast/tree-sitter-parser.js +142 -0
- package/dist/src/core/ast/tree-sitter-parser.js.map +1 -0
- package/dist/src/core/config.d.ts +11 -0
- package/dist/src/core/config.js +112 -0
- package/dist/src/core/config.js.map +1 -0
- package/dist/src/core/diagram.d.ts +9 -0
- package/dist/src/core/diagram.js +101 -0
- package/dist/src/core/diagram.js.map +1 -0
- package/dist/src/core/i18n.d.ts +14 -0
- package/dist/src/core/i18n.js +54 -0
- package/dist/src/core/i18n.js.map +1 -0
- package/dist/src/core/locales/en.d.ts +2 -0
- package/dist/src/core/locales/en.js +337 -0
- package/dist/src/core/locales/en.js.map +1 -0
- package/dist/src/core/locales/pt-BR.d.ts +172 -0
- package/dist/src/core/locales/pt-BR.js +337 -0
- package/dist/src/core/locales/pt-BR.js.map +1 -0
- package/dist/src/core/locales/types.d.ts +86 -0
- package/dist/src/core/locales/types.js +2 -0
- package/dist/src/core/locales/types.js.map +1 -0
- package/dist/src/core/plugin-loader.d.ts +11 -0
- package/dist/src/core/plugin-loader.js +67 -0
- package/dist/src/core/plugin-loader.js.map +1 -0
- package/dist/src/core/project-summarizer.d.ts +16 -0
- package/dist/src/core/project-summarizer.js +37 -0
- package/dist/src/core/project-summarizer.js.map +1 -0
- package/dist/src/core/refactor-engine.d.ts +18 -0
- package/dist/src/core/refactor-engine.js +87 -0
- package/dist/src/core/refactor-engine.js.map +1 -0
- package/dist/src/core/rules/barrel-optimizer.d.ts +13 -0
- package/dist/src/core/rules/barrel-optimizer.js +76 -0
- package/dist/src/core/rules/barrel-optimizer.js.map +1 -0
- package/dist/src/core/rules/dead-code-detector.d.ts +21 -0
- package/dist/src/core/rules/dead-code-detector.js +116 -0
- package/dist/src/core/rules/dead-code-detector.js.map +1 -0
- package/dist/src/core/rules/hub-splitter.d.ts +13 -0
- package/dist/src/core/rules/hub-splitter.js +117 -0
- package/dist/src/core/rules/hub-splitter.js.map +1 -0
- package/dist/src/core/rules/import-organizer.d.ts +13 -0
- package/dist/src/core/rules/import-organizer.js +84 -0
- package/dist/src/core/rules/import-organizer.js.map +1 -0
- package/dist/src/core/rules/module-grouper.d.ts +13 -0
- package/dist/src/core/rules/module-grouper.js +116 -0
- package/dist/src/core/rules/module-grouper.js.map +1 -0
- package/dist/src/core/rules-engine.d.ts +7 -0
- package/dist/src/core/rules-engine.js +89 -0
- package/dist/src/core/rules-engine.js.map +1 -0
- package/dist/src/core/scorer.d.ts +15 -0
- package/dist/src/core/scorer.js +165 -0
- package/dist/src/core/scorer.js.map +1 -0
- package/dist/src/core/summarizer/keyword-extractor.d.ts +6 -0
- package/dist/src/core/summarizer/keyword-extractor.js +38 -0
- package/dist/src/core/summarizer/keyword-extractor.js.map +1 -0
- package/dist/src/core/summarizer/module-inferrer.d.ts +11 -0
- package/dist/src/core/summarizer/module-inferrer.js +171 -0
- package/dist/src/core/summarizer/module-inferrer.js.map +1 -0
- package/dist/src/core/summarizer/package-reader.d.ts +3 -0
- package/dist/src/core/summarizer/package-reader.js +33 -0
- package/dist/src/core/summarizer/package-reader.js.map +1 -0
- package/dist/src/core/summarizer/purpose-inferrer.d.ts +8 -0
- package/dist/src/core/summarizer/purpose-inferrer.js +179 -0
- package/dist/src/core/summarizer/purpose-inferrer.js.map +1 -0
- package/dist/src/core/summarizer/readme-reader.d.ts +3 -0
- package/dist/src/core/summarizer/readme-reader.js +24 -0
- package/dist/src/core/summarizer/readme-reader.js.map +1 -0
- package/dist/src/core/types/architect-rules.d.ts +27 -0
- package/dist/src/core/types/architect-rules.js +2 -0
- package/dist/src/core/types/architect-rules.js.map +1 -0
- package/dist/src/core/types/core.d.ts +87 -0
- package/dist/src/core/types/core.js +2 -0
- package/dist/src/core/types/core.js.map +1 -0
- package/dist/src/core/types/infrastructure.d.ts +38 -0
- package/dist/src/core/types/infrastructure.js +2 -0
- package/dist/src/core/types/infrastructure.js.map +1 -0
- package/dist/src/core/types/plugin.d.ts +12 -0
- package/dist/src/core/types/plugin.js +2 -0
- package/dist/src/core/types/plugin.js.map +1 -0
- package/dist/src/core/types/rules.d.ts +53 -0
- package/dist/src/core/types/rules.js +2 -0
- package/dist/src/core/types/rules.js.map +1 -0
- package/dist/src/core/types/summarizer.d.ts +12 -0
- package/dist/src/core/types/summarizer.js +2 -0
- package/dist/src/core/types/summarizer.js.map +1 -0
- package/dist/src/infrastructure/git-cache.d.ts +6 -0
- package/dist/src/infrastructure/git-cache.js +41 -0
- package/dist/src/infrastructure/git-cache.js.map +1 -0
- package/dist/src/infrastructure/git-history.d.ts +112 -0
- package/dist/src/infrastructure/git-history.js +340 -0
- package/dist/src/infrastructure/git-history.js.map +1 -0
- package/dist/src/infrastructure/logger.d.ts +20 -0
- package/dist/src/infrastructure/logger.js +57 -0
- package/dist/src/infrastructure/logger.js.map +1 -0
- package/dist/src/infrastructure/scanner.d.ts +31 -0
- package/dist/src/infrastructure/scanner.js +334 -0
- package/dist/src/infrastructure/scanner.js.map +1 -0
- package/dist/tests/analyzers-integration.test.d.ts +7 -0
- package/dist/tests/analyzers-integration.test.js +140 -0
- package/dist/tests/analyzers-integration.test.js.map +1 -0
- package/dist/tests/anti-patterns.test.d.ts +1 -0
- package/dist/tests/anti-patterns.test.js +81 -0
- package/dist/tests/anti-patterns.test.js.map +1 -0
- package/dist/tests/ast-parser.test.d.ts +1 -0
- package/dist/tests/ast-parser.test.js +94 -0
- package/dist/tests/ast-parser.test.js.map +1 -0
- package/dist/tests/fixtures/monorepo/packages/app/src/index.d.ts +1 -0
- package/dist/tests/fixtures/monorepo/packages/app/src/index.js +9 -0
- package/dist/tests/fixtures/monorepo/packages/app/src/index.js.map +1 -0
- package/dist/tests/fixtures/monorepo/packages/core/src/index.d.ts +2 -0
- package/dist/tests/fixtures/monorepo/packages/core/src/index.js +11 -0
- package/dist/tests/fixtures/monorepo/packages/core/src/index.js.map +1 -0
- package/dist/tests/forecast.test.d.ts +7 -0
- package/dist/tests/forecast.test.js +380 -0
- package/dist/tests/forecast.test.js.map +1 -0
- package/dist/tests/git-history.test.d.ts +7 -0
- package/dist/tests/git-history.test.js +193 -0
- package/dist/tests/git-history.test.js.map +1 -0
- package/dist/tests/i18n.test.d.ts +1 -0
- package/dist/tests/i18n.test.js +39 -0
- package/dist/tests/i18n.test.js.map +1 -0
- package/dist/tests/monorepo-scan.test.d.ts +11 -0
- package/dist/tests/monorepo-scan.test.js +143 -0
- package/dist/tests/monorepo-scan.test.js.map +1 -0
- package/dist/tests/plugin-loader.test.d.ts +1 -0
- package/dist/tests/plugin-loader.test.js +31 -0
- package/dist/tests/plugin-loader.test.js.map +1 -0
- package/dist/tests/rules-engine.test.d.ts +1 -0
- package/dist/tests/rules-engine.test.js +112 -0
- package/dist/tests/rules-engine.test.js.map +1 -0
- package/dist/tests/scanner.test.d.ts +1 -0
- package/dist/tests/scanner.test.js +44 -0
- package/dist/tests/scanner.test.js.map +1 -0
- package/dist/tests/scorer.test.d.ts +1 -0
- package/dist/tests/scorer.test.js +610 -0
- package/dist/tests/scorer.test.js.map +1 -0
- package/dist/tests/temporal-scorer.test.d.ts +7 -0
- package/dist/tests/temporal-scorer.test.js +239 -0
- package/dist/tests/temporal-scorer.test.js.map +1 -0
- package/package.json +29 -0
- package/src/core/analyzer.ts +499 -0
- package/src/core/analyzers/forecast.ts +497 -0
- package/src/core/analyzers/index.ts +33 -0
- package/src/core/analyzers/temporal-scorer.ts +227 -0
- package/src/core/anti-patterns.ts +324 -0
- package/src/core/ast/ast-parser.interface.ts +21 -0
- package/src/core/ast/path-resolver.ts +61 -0
- package/src/core/ast/tree-sitter-parser.ts +158 -0
- package/src/core/config.ts +125 -0
- package/src/core/diagram.ts +129 -0
- package/src/core/i18n.ts +64 -0
- package/src/core/locales/en.ts +340 -0
- package/src/core/locales/pt-BR.ts +341 -0
- package/src/core/locales/types.ts +95 -0
- package/src/core/plugin-loader.ts +80 -0
- package/src/core/project-summarizer.ts +42 -0
- package/src/core/refactor-engine.ts +112 -0
- package/src/core/rules/barrel-optimizer.ts +99 -0
- package/src/core/rules/dead-code-detector.ts +134 -0
- package/src/core/rules/hub-splitter.ts +135 -0
- package/src/core/rules/import-organizer.ts +100 -0
- package/src/core/rules/module-grouper.ts +133 -0
- package/src/core/rules-engine.ts +100 -0
- package/src/core/scorer.ts +181 -0
- package/src/core/summarizer/keyword-extractor.ts +53 -0
- package/src/core/summarizer/module-inferrer.ts +194 -0
- package/src/core/summarizer/package-reader.ts +34 -0
- package/src/core/summarizer/purpose-inferrer.ts +197 -0
- package/src/core/summarizer/readme-reader.ts +24 -0
- package/src/core/types/architect-rules.ts +29 -0
- package/src/core/types/core.ts +94 -0
- package/src/core/types/infrastructure.ts +41 -0
- package/src/core/types/plugin.ts +19 -0
- package/src/core/types/rules.ts +51 -0
- package/src/core/types/summarizer.ts +8 -0
- package/src/infrastructure/git-cache.ts +52 -0
- package/src/infrastructure/git-history.ts +496 -0
- package/src/infrastructure/logger.ts +68 -0
- package/src/infrastructure/scanner.ts +349 -0
- package/tests/analyzers-integration.test.ts +174 -0
- package/tests/anti-patterns.test.ts +95 -0
- package/tests/ast-parser.test.ts +102 -0
- package/tests/fixtures/monorepo/package.json +6 -0
- package/tests/fixtures/monorepo/packages/app/package.json +12 -0
- package/tests/fixtures/monorepo/packages/app/src/index.ts +6 -0
- package/tests/fixtures/monorepo/packages/core/package.json +7 -0
- package/tests/fixtures/monorepo/packages/core/src/index.ts +7 -0
- package/tests/forecast.test.ts +504 -0
- package/tests/git-history.test.ts +254 -0
- package/tests/i18n.test.ts +47 -0
- package/tests/monorepo-scan.test.ts +170 -0
- package/tests/plugin-loader.test.ts +40 -0
- package/tests/rules-engine.test.ts +131 -0
- package/tests/scanner.test.ts +54 -0
- package/tests/scorer.test.ts +675 -0
- package/tests/temporal-scorer.test.ts +306 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-loader.js","sourceRoot":"","sources":["../../../src/core/plugin-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AnalysisReport } from './types/core.js';
|
|
2
|
+
import { ProjectSummary } from './types/summarizer.js';
|
|
3
|
+
/**
|
|
4
|
+
* ProjectSummarizer — infers what a project does from its metadata,
|
|
5
|
+
* structure, README, package.json, and file naming conventions.
|
|
6
|
+
*
|
|
7
|
+
* Refactored via Facade pattern in v5.0.0
|
|
8
|
+
*/
|
|
9
|
+
export declare class ProjectSummarizer {
|
|
10
|
+
private packageReader;
|
|
11
|
+
private readmeReader;
|
|
12
|
+
private keywordExtractor;
|
|
13
|
+
private purposeInferrer;
|
|
14
|
+
private moduleInferrer;
|
|
15
|
+
summarize(projectPath: string, report: AnalysisReport): ProjectSummary;
|
|
16
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { PackageReader } from './summarizer/package-reader.js';
|
|
2
|
+
import { ReadmeReader } from './summarizer/readme-reader.js';
|
|
3
|
+
import { KeywordExtractor } from './summarizer/keyword-extractor.js';
|
|
4
|
+
import { PurposeInferrer } from './summarizer/purpose-inferrer.js';
|
|
5
|
+
import { ModuleInferrer } from './summarizer/module-inferrer.js';
|
|
6
|
+
/**
|
|
7
|
+
* ProjectSummarizer — infers what a project does from its metadata,
|
|
8
|
+
* structure, README, package.json, and file naming conventions.
|
|
9
|
+
*
|
|
10
|
+
* Refactored via Facade pattern in v5.0.0
|
|
11
|
+
*/
|
|
12
|
+
export class ProjectSummarizer {
|
|
13
|
+
packageReader = new PackageReader();
|
|
14
|
+
readmeReader = new ReadmeReader();
|
|
15
|
+
keywordExtractor = new KeywordExtractor();
|
|
16
|
+
purposeInferrer = new PurposeInferrer();
|
|
17
|
+
moduleInferrer = new ModuleInferrer();
|
|
18
|
+
summarize(projectPath, report) {
|
|
19
|
+
const packageInfo = this.packageReader.readPackageJson(projectPath);
|
|
20
|
+
const readmeContent = this.readmeReader.readReadme(projectPath);
|
|
21
|
+
const modules = this.moduleInferrer.inferModules(report, projectPath);
|
|
22
|
+
const entryPoints = this.purposeInferrer.findEntryPoints(report, projectPath);
|
|
23
|
+
const keywords = this.keywordExtractor.extractKeywords(packageInfo, readmeContent, modules, report);
|
|
24
|
+
const techStack = this.purposeInferrer.buildTechStack(report, packageInfo);
|
|
25
|
+
const description = this.purposeInferrer.buildDescription(packageInfo, readmeContent, report);
|
|
26
|
+
const purpose = this.purposeInferrer.inferPurpose(keywords, modules, report);
|
|
27
|
+
return {
|
|
28
|
+
description,
|
|
29
|
+
purpose,
|
|
30
|
+
modules,
|
|
31
|
+
techStack,
|
|
32
|
+
entryPoints,
|
|
33
|
+
keywords,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=project-summarizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-summarizer.js","sourceRoot":"","sources":["../../../src/core/project-summarizer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE;;;;;GAKG;AACH,MAAM,OAAO,iBAAiB;IACpB,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;IACpC,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC;IAClC,gBAAgB,GAAG,IAAI,gBAAgB,EAAE,CAAC;IAC1C,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;IACxC,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC;IAE9C,SAAS,CAAC,WAAmB,EAAE,MAAsB;QACnD,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;QACpE,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAChE,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACtE,MAAM,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAC9E,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,eAAe,CAAC,WAAW,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QACpG,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAC3E,MAAM,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,WAAW,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;QAC9F,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAE7E,OAAO;YACL,WAAW;YACX,OAAO;YACP,OAAO;YACP,SAAS;YACT,WAAW;YACX,QAAQ;SACT,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { AnalysisReport } from './types/core.js';
|
|
2
|
+
import { RefactoringPlan } from './types/rules.js';
|
|
3
|
+
/**
|
|
4
|
+
* Refactoring Engine v2.0
|
|
5
|
+
* Orchestrates Tier 1 (rule-based) and Tier 2 (AST) refactoring rules.
|
|
6
|
+
*/
|
|
7
|
+
export declare class RefactorEngine {
|
|
8
|
+
private rules;
|
|
9
|
+
constructor();
|
|
10
|
+
/**
|
|
11
|
+
* Analyze a project and generate a refactoring plan.
|
|
12
|
+
*/
|
|
13
|
+
analyze(report: AnalysisReport, projectPath: string): RefactoringPlan;
|
|
14
|
+
/**
|
|
15
|
+
* Estimates the architecture score after applying all refactoring steps.
|
|
16
|
+
*/
|
|
17
|
+
private estimateScoreAfter;
|
|
18
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// ── Tier 1 Rules ──
|
|
2
|
+
import { HubSplitterRule } from './rules/hub-splitter.js';
|
|
3
|
+
import { BarrelOptimizerRule } from './rules/barrel-optimizer.js';
|
|
4
|
+
import { ImportOrganizerRule } from './rules/import-organizer.js';
|
|
5
|
+
import { ModuleGrouperRule } from './rules/module-grouper.js';
|
|
6
|
+
import { DeadCodeDetectorRule } from './rules/dead-code-detector.js';
|
|
7
|
+
/**
|
|
8
|
+
* Refactoring Engine v2.0
|
|
9
|
+
* Orchestrates Tier 1 (rule-based) and Tier 2 (AST) refactoring rules.
|
|
10
|
+
*/
|
|
11
|
+
export class RefactorEngine {
|
|
12
|
+
rules;
|
|
13
|
+
constructor() {
|
|
14
|
+
this.rules = [
|
|
15
|
+
// Tier 1: Rule Engine (pattern matching)
|
|
16
|
+
new HubSplitterRule(),
|
|
17
|
+
new BarrelOptimizerRule(),
|
|
18
|
+
new ImportOrganizerRule(),
|
|
19
|
+
new ModuleGrouperRule(),
|
|
20
|
+
new DeadCodeDetectorRule(),
|
|
21
|
+
];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Analyze a project and generate a refactoring plan.
|
|
25
|
+
*/
|
|
26
|
+
analyze(report, projectPath) {
|
|
27
|
+
const allSteps = [];
|
|
28
|
+
let stepId = 1;
|
|
29
|
+
// Run each rule
|
|
30
|
+
for (const rule of this.rules) {
|
|
31
|
+
const steps = rule.analyze(report, projectPath);
|
|
32
|
+
for (const step of steps) {
|
|
33
|
+
step.id = stepId++;
|
|
34
|
+
allSteps.push(step);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Sort by priority
|
|
38
|
+
const priorityOrder = {
|
|
39
|
+
CRITICAL: 0,
|
|
40
|
+
HIGH: 1,
|
|
41
|
+
MEDIUM: 2,
|
|
42
|
+
LOW: 3,
|
|
43
|
+
};
|
|
44
|
+
allSteps.sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]);
|
|
45
|
+
// Re-number after sorting
|
|
46
|
+
allSteps.forEach((s, i) => (s.id = i + 1));
|
|
47
|
+
// Calculate total operations
|
|
48
|
+
const totalOperations = allSteps.reduce((sum, s) => sum + s.operations.length, 0);
|
|
49
|
+
// Estimate score after refactoring
|
|
50
|
+
const estimatedScoreAfter = this.estimateScoreAfter(report, allSteps);
|
|
51
|
+
return {
|
|
52
|
+
timestamp: new Date().toISOString(),
|
|
53
|
+
projectPath,
|
|
54
|
+
currentScore: report.score,
|
|
55
|
+
estimatedScoreAfter,
|
|
56
|
+
steps: allSteps,
|
|
57
|
+
totalOperations,
|
|
58
|
+
tier1Steps: allSteps.filter((s) => s.tier === 1).length,
|
|
59
|
+
tier2Steps: allSteps.filter((s) => s.tier === 2).length,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Estimates the architecture score after applying all refactoring steps.
|
|
64
|
+
*/
|
|
65
|
+
estimateScoreAfter(report, steps) {
|
|
66
|
+
const breakdown = { ...report.score.breakdown };
|
|
67
|
+
for (const step of steps) {
|
|
68
|
+
for (const impact of step.scoreImpact) {
|
|
69
|
+
if (impact.metric in breakdown) {
|
|
70
|
+
// Use estimated after value, capped at 95
|
|
71
|
+
const key = impact.metric;
|
|
72
|
+
breakdown[key] = Math.min(95, Math.max(breakdown[key], impact.after));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Recalculate overall with same weights
|
|
77
|
+
const overall = Math.round(breakdown.modularity * 0.4 +
|
|
78
|
+
breakdown.coupling * 0.25 +
|
|
79
|
+
breakdown.cohesion * 0.2 +
|
|
80
|
+
breakdown.layering * 0.15);
|
|
81
|
+
return {
|
|
82
|
+
overall: Math.min(100, overall),
|
|
83
|
+
breakdown,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=refactor-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refactor-engine.js","sourceRoot":"","sources":["../../../src/core/refactor-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AnalysisReport } from '../types/core.js';
|
|
2
|
+
import { RefactorRule, RefactorStep } from '../types/rules.js';
|
|
3
|
+
/**
|
|
4
|
+
* Barrel Optimizer Rule (Tier 1)
|
|
5
|
+
* Analyzes barrel files (__init__.py, index.ts) and suggests optimization.
|
|
6
|
+
* Barrel files that re-export everything create unnecessary coupling.
|
|
7
|
+
*/
|
|
8
|
+
export declare class BarrelOptimizerRule implements RefactorRule {
|
|
9
|
+
name: string;
|
|
10
|
+
tier: 1;
|
|
11
|
+
private static readonly BARREL_FILES;
|
|
12
|
+
analyze(report: AnalysisReport, _projectPath: string): RefactorStep[];
|
|
13
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { basename, dirname } from 'path';
|
|
2
|
+
/**
|
|
3
|
+
* Barrel Optimizer Rule (Tier 1)
|
|
4
|
+
* Analyzes barrel files (__init__.py, index.ts) and suggests optimization.
|
|
5
|
+
* Barrel files that re-export everything create unnecessary coupling.
|
|
6
|
+
*/
|
|
7
|
+
export class BarrelOptimizerRule {
|
|
8
|
+
name = 'barrel-optimizer';
|
|
9
|
+
tier = 1;
|
|
10
|
+
static BARREL_FILES = new Set([
|
|
11
|
+
'__init__.py', 'index.ts', 'index.js', 'index.tsx', 'index.jsx',
|
|
12
|
+
]);
|
|
13
|
+
analyze(report, _projectPath) {
|
|
14
|
+
const steps = [];
|
|
15
|
+
// Find barrel files in the dependency graph
|
|
16
|
+
const barrelNodes = report.dependencyGraph.nodes.filter((n) => BarrelOptimizerRule.BARREL_FILES.has(basename(n)));
|
|
17
|
+
for (const barrel of barrelNodes) {
|
|
18
|
+
// Count how many things this barrel re-exports (outgoing edges)
|
|
19
|
+
const outgoing = report.dependencyGraph.edges.filter((e) => e.from === barrel);
|
|
20
|
+
const incoming = report.dependencyGraph.edges.filter((e) => e.to === barrel);
|
|
21
|
+
if (outgoing.length < 3)
|
|
22
|
+
continue;
|
|
23
|
+
// Check for "pass-through" pattern: files import from barrel
|
|
24
|
+
// but barrel just re-exports from siblings
|
|
25
|
+
const siblingDir = dirname(barrel);
|
|
26
|
+
const siblingExports = outgoing.filter((e) => dirname(e.to) === siblingDir);
|
|
27
|
+
const operations = [];
|
|
28
|
+
// Suggest direct imports instead of barrel
|
|
29
|
+
for (const consumer of incoming) {
|
|
30
|
+
const consumedModules = outgoing
|
|
31
|
+
.filter((e) => {
|
|
32
|
+
// Check if consumer actually needs this module
|
|
33
|
+
return report.dependencyGraph.edges.some((edge) => edge.from === consumer.from && edge.to === e.to);
|
|
34
|
+
})
|
|
35
|
+
.map((e) => e.to);
|
|
36
|
+
if (consumedModules.length > 0) {
|
|
37
|
+
operations.push({
|
|
38
|
+
type: 'MODIFY',
|
|
39
|
+
path: consumer.from,
|
|
40
|
+
description: `Replace barrel import from \`${basename(barrel)}\` with direct imports: ${consumedModules.map((m) => basename(m)).join(', ')}`,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Suggest simplifying the barrel
|
|
45
|
+
if (siblingExports.length > 5) {
|
|
46
|
+
operations.push({
|
|
47
|
+
type: 'MODIFY',
|
|
48
|
+
path: barrel,
|
|
49
|
+
description: `Simplify ${basename(barrel)}: only re-export public API (${siblingExports.length} re-exports detected, consider reducing)`,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
if (operations.length > 0) {
|
|
53
|
+
steps.push({
|
|
54
|
+
id: 0,
|
|
55
|
+
tier: 1,
|
|
56
|
+
rule: this.name,
|
|
57
|
+
priority: outgoing.length >= 8 ? 'HIGH' : 'MEDIUM',
|
|
58
|
+
title: `Optimize barrel: ${barrel}`,
|
|
59
|
+
description: `\`${barrel}\` re-exports ${outgoing.length} modules. ` +
|
|
60
|
+
`This creates a "Shotgun Surgery" risk — any change propagates widely.`,
|
|
61
|
+
rationale: `Barrel files that re-export everything make it hard to tree-shake unused code ` +
|
|
62
|
+
`and create implicit dependencies. Direct imports make dependency relationships explicit ` +
|
|
63
|
+
`and reduce the blast radius of changes.`,
|
|
64
|
+
operations,
|
|
65
|
+
scoreImpact: [
|
|
66
|
+
{ metric: 'coupling', before: report.score.breakdown.coupling, after: Math.min(95, report.score.breakdown.coupling + 10) },
|
|
67
|
+
{ metric: 'layering', before: report.score.breakdown.layering, after: Math.min(95, report.score.breakdown.layering + 5) },
|
|
68
|
+
],
|
|
69
|
+
aiPrompt: `Analyze the barrel file \`${barrel}\` which re-exports ${outgoing.length} modules. This is creating a "Shotgun Surgery" risk.\nPlease optimize it by:\n1. Removing wildcard exports (e.g., \`export *\`) if any.\n2. Only re-exporting the public API interfaces/classes meant for consumers outside this module.\n3. Updating consumers (${incoming.map(i => basename(i.from)).join(', ')}) to import from the specific files directly instead of passing through this barrel file where appropriate.`,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return steps;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=barrel-optimizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"barrel-optimizer.js","sourceRoot":"","sources":["../../../../src/core/rules/barrel-optimizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AnalysisReport } from '../types/core.js';
|
|
2
|
+
import { RefactorRule, RefactorStep } from '../types/rules.js';
|
|
3
|
+
/**
|
|
4
|
+
* Dead Code Detector Rule (Tier 1)
|
|
5
|
+
* Finds files with no incoming edges (nobody imports them)
|
|
6
|
+
* and exports that are never used.
|
|
7
|
+
*
|
|
8
|
+
* Handles both path-style (deepguard/report.py) and
|
|
9
|
+
* dot-notation (deepguard.report) references.
|
|
10
|
+
*/
|
|
11
|
+
export declare class DeadCodeDetectorRule implements RefactorRule {
|
|
12
|
+
name: string;
|
|
13
|
+
tier: 1;
|
|
14
|
+
private static readonly ENTRY_POINTS;
|
|
15
|
+
analyze(report: AnalysisReport, _projectPath: string): RefactorStep[];
|
|
16
|
+
/**
|
|
17
|
+
* Generate dot-notation variants for a file path.
|
|
18
|
+
* "deepguard/report.py" → ["deepguard.report", ".report"]
|
|
19
|
+
*/
|
|
20
|
+
private getDotVariants;
|
|
21
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { basename } from 'path';
|
|
2
|
+
/**
|
|
3
|
+
* Dead Code Detector Rule (Tier 1)
|
|
4
|
+
* Finds files with no incoming edges (nobody imports them)
|
|
5
|
+
* and exports that are never used.
|
|
6
|
+
*
|
|
7
|
+
* Handles both path-style (deepguard/report.py) and
|
|
8
|
+
* dot-notation (deepguard.report) references.
|
|
9
|
+
*/
|
|
10
|
+
export class DeadCodeDetectorRule {
|
|
11
|
+
name = 'dead-code-detector';
|
|
12
|
+
tier = 1;
|
|
13
|
+
static ENTRY_POINTS = new Set([
|
|
14
|
+
'main.py', 'cli.py', 'app.py', 'manage.py', 'wsgi.py', 'asgi.py',
|
|
15
|
+
'main.ts', 'main.js', 'app.ts', 'app.js', 'server.ts', 'server.js',
|
|
16
|
+
'index.html', 'setup.py', 'setup.cfg', 'pyproject.toml',
|
|
17
|
+
]);
|
|
18
|
+
analyze(report, _projectPath) {
|
|
19
|
+
const steps = [];
|
|
20
|
+
const edges = report.dependencyGraph.edges;
|
|
21
|
+
// Build a set of ALL referenced targets (both path and dot-notation)
|
|
22
|
+
const allTargets = new Set();
|
|
23
|
+
const allSources = new Set();
|
|
24
|
+
for (const edge of edges) {
|
|
25
|
+
allTargets.add(edge.to);
|
|
26
|
+
allSources.add(edge.from);
|
|
27
|
+
}
|
|
28
|
+
// Only consider actual files (with path separators) as candidates
|
|
29
|
+
const fileNodes = report.dependencyGraph.nodes.filter((n) => n.includes('/') || n.includes('\\'));
|
|
30
|
+
// Build incoming edge count considering dot-notation matches
|
|
31
|
+
const incomingCount = {};
|
|
32
|
+
for (const file of fileNodes) {
|
|
33
|
+
incomingCount[file] = 0;
|
|
34
|
+
// Direct incoming edges
|
|
35
|
+
for (const edge of edges) {
|
|
36
|
+
if (edge.to === file) {
|
|
37
|
+
incomingCount[file]++;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Check dot-notation references:
|
|
41
|
+
// deepguard/report.py might be referenced as deepguard.report or .report
|
|
42
|
+
const dotVariants = this.getDotVariants(file);
|
|
43
|
+
for (const variant of dotVariants) {
|
|
44
|
+
if (allTargets.has(variant)) {
|
|
45
|
+
incomingCount[file]++;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Find orphan files
|
|
50
|
+
const orphans = [];
|
|
51
|
+
for (const [file, count] of Object.entries(incomingCount)) {
|
|
52
|
+
const fileName = basename(file);
|
|
53
|
+
// Skip entry points and config files
|
|
54
|
+
if (DeadCodeDetectorRule.ENTRY_POINTS.has(fileName))
|
|
55
|
+
continue;
|
|
56
|
+
if (fileName.startsWith('__'))
|
|
57
|
+
continue;
|
|
58
|
+
if (fileName.startsWith('.'))
|
|
59
|
+
continue;
|
|
60
|
+
if (fileName.endsWith('.test.ts') || fileName.endsWith('.spec.ts'))
|
|
61
|
+
continue;
|
|
62
|
+
if (fileName.endsWith('_test.py') || fileName.endsWith('.test.py'))
|
|
63
|
+
continue;
|
|
64
|
+
// Also skip if the file has outgoing edges (it's active code)
|
|
65
|
+
if (allSources.has(file))
|
|
66
|
+
continue;
|
|
67
|
+
if (count === 0) {
|
|
68
|
+
orphans.push(file);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (orphans.length > 0) {
|
|
72
|
+
const operations = orphans.map((file) => ({
|
|
73
|
+
type: 'DELETE',
|
|
74
|
+
path: file,
|
|
75
|
+
description: `\`${basename(file)}\` has no incoming dependencies — verify if still needed`,
|
|
76
|
+
}));
|
|
77
|
+
steps.push({
|
|
78
|
+
id: 0,
|
|
79
|
+
tier: 1,
|
|
80
|
+
rule: this.name,
|
|
81
|
+
priority: orphans.length >= 3 ? 'MEDIUM' : 'LOW',
|
|
82
|
+
title: `Review ${orphans.length} potentially unused file(s)`,
|
|
83
|
+
description: `Found ${orphans.length} file(s) with no incoming dependencies: ` +
|
|
84
|
+
`${orphans.map((f) => `\`${basename(f)}\``).join(', ')}. ` +
|
|
85
|
+
`These may be dead code or missing from the module's public API.`,
|
|
86
|
+
rationale: `Files with zero incoming edges are either entry points (already excluded), ` +
|
|
87
|
+
`or potentially dead code. Removing dead code reduces maintenance burden ` +
|
|
88
|
+
`and improves modularity scores.`,
|
|
89
|
+
operations,
|
|
90
|
+
scoreImpact: [
|
|
91
|
+
{ metric: 'modularity', before: report.score.breakdown.modularity, after: Math.min(95, report.score.breakdown.modularity + 5) },
|
|
92
|
+
],
|
|
93
|
+
aiPrompt: `Analyze the following files: ${orphans.map(f => `\`${f}\``).join(', ')}.\nThese files currently have zero incoming dependencies across the architecture, meaning they might be dead code.\nPlease review them:\n1. If they are unused, explicitly delete them to shrink the blast radius.\n2. If they are entry points that the Architect missed, add them to the ignore list or document their usage.\n3. Make sure to remove any vestigial exports or imports pointing to them from the rest of the codebase.`,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return steps;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Generate dot-notation variants for a file path.
|
|
100
|
+
* "deepguard/report.py" → ["deepguard.report", ".report"]
|
|
101
|
+
*/
|
|
102
|
+
getDotVariants(filePath) {
|
|
103
|
+
const variants = [];
|
|
104
|
+
const withoutExt = filePath.replace(/\.[^.]+$/, '');
|
|
105
|
+
const dotPath = withoutExt.replace(/[/\\]/g, '.');
|
|
106
|
+
variants.push(dotPath);
|
|
107
|
+
// Relative dot-notation: .report
|
|
108
|
+
const parts = filePath.split('/');
|
|
109
|
+
if (parts.length >= 2) {
|
|
110
|
+
const lastPart = parts[parts.length - 1].replace(/\.[^.]+$/, '');
|
|
111
|
+
variants.push(`.${lastPart}`);
|
|
112
|
+
}
|
|
113
|
+
return variants;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=dead-code-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dead-code-detector.js","sourceRoot":"","sources":["../../../../src/core/rules/dead-code-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AnalysisReport } from '../types/core.js';
|
|
2
|
+
import { RefactorRule, RefactorStep } from '../types/rules.js';
|
|
3
|
+
/**
|
|
4
|
+
* Hub Splitter Rule (Tier 1)
|
|
5
|
+
* Detects files with many connections and generates split plans.
|
|
6
|
+
* A "hub" is a file that many other files depend on, creating tight coupling.
|
|
7
|
+
*/
|
|
8
|
+
export declare class HubSplitterRule implements RefactorRule {
|
|
9
|
+
name: string;
|
|
10
|
+
tier: 1;
|
|
11
|
+
analyze(report: AnalysisReport, _projectPath: string): RefactorStep[];
|
|
12
|
+
private groupDependents;
|
|
13
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { basename, dirname } from 'path';
|
|
2
|
+
/**
|
|
3
|
+
* Hub Splitter Rule (Tier 1)
|
|
4
|
+
* Detects files with many connections and generates split plans.
|
|
5
|
+
* A "hub" is a file that many other files depend on, creating tight coupling.
|
|
6
|
+
*/
|
|
7
|
+
export class HubSplitterRule {
|
|
8
|
+
name = 'hub-splitter';
|
|
9
|
+
tier = 1;
|
|
10
|
+
analyze(report, _projectPath) {
|
|
11
|
+
const steps = [];
|
|
12
|
+
// Count connections per node
|
|
13
|
+
const connectionCount = {};
|
|
14
|
+
for (const edge of report.dependencyGraph.edges) {
|
|
15
|
+
if (!connectionCount[edge.from])
|
|
16
|
+
connectionCount[edge.from] = { incoming: [], outgoing: [] };
|
|
17
|
+
if (!connectionCount[edge.to])
|
|
18
|
+
connectionCount[edge.to] = { incoming: [], outgoing: [] };
|
|
19
|
+
connectionCount[edge.from].outgoing.push(edge.to);
|
|
20
|
+
connectionCount[edge.to].incoming.push(edge.from);
|
|
21
|
+
}
|
|
22
|
+
// Find hubs (5+ incoming connections, not barrel files)
|
|
23
|
+
const barrelFiles = new Set(['__init__.py', 'index.ts', 'index.js', 'index.tsx', 'mod.rs']);
|
|
24
|
+
for (const [file, connections] of Object.entries(connectionCount)) {
|
|
25
|
+
const fileName = basename(file);
|
|
26
|
+
if (barrelFiles.has(fileName))
|
|
27
|
+
continue;
|
|
28
|
+
// Ignora Tipos base/DTOs - Alto acoplamento em tipos é sinal de maturidade, não gargalo
|
|
29
|
+
const lowerFile = file.toLowerCase();
|
|
30
|
+
if (lowerFile.includes('types') || lowerFile.includes('interface') || lowerFile.includes('/types/')) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
// Tolerância Arquitetural: Eleva de 5 pra 8 dependentes pra engatilhar quebra (Módulos Coesos maduros)
|
|
34
|
+
if (connections.incoming.length < 8)
|
|
35
|
+
continue;
|
|
36
|
+
const operations = [];
|
|
37
|
+
// Determine if this is a dot-notation module or a real file
|
|
38
|
+
const isDotNotation = !file.includes('/') && !file.includes('\\');
|
|
39
|
+
const moduleName = isDotNotation
|
|
40
|
+
? file.split('.').pop() || file
|
|
41
|
+
: fileName.replace(/\.[^.]+$/, '');
|
|
42
|
+
const moduleDir = isDotNotation
|
|
43
|
+
? file.split('.').slice(0, -1).join('/')
|
|
44
|
+
: dirname(file);
|
|
45
|
+
const ext = isDotNotation ? 'py' : (fileName.split('.').pop() || 'py');
|
|
46
|
+
// Analyze what dependents import to suggest groupings
|
|
47
|
+
const dependentGroups = this.groupDependents(connections.incoming);
|
|
48
|
+
// Suggest splitting into domain modules
|
|
49
|
+
if (dependentGroups.length >= 2) {
|
|
50
|
+
for (const group of dependentGroups) {
|
|
51
|
+
const newFileName = `${moduleName}_${group.name}.${ext}`;
|
|
52
|
+
const newPath = moduleDir ? `${moduleDir}/${newFileName}` : newFileName;
|
|
53
|
+
operations.push({
|
|
54
|
+
type: 'CREATE',
|
|
55
|
+
path: newPath,
|
|
56
|
+
description: `Create \`${newFileName}\` with functionality used by: ${group.dependents.join(', ')}`,
|
|
57
|
+
content: ext === 'py'
|
|
58
|
+
? `"""${moduleName}_${group.name} — extracted from ${moduleName}."""\n# Used by: ${group.dependents.join(', ')}\n`
|
|
59
|
+
: `// ${moduleName}_${group.name} — extracted from ${moduleName}\n// Used by: ${group.dependents.join(', ')}\n`,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
// Update imports in all dependents
|
|
63
|
+
for (const dependent of connections.incoming) {
|
|
64
|
+
operations.push({
|
|
65
|
+
type: 'MODIFY',
|
|
66
|
+
path: dependent,
|
|
67
|
+
description: `Update imports in \`${basename(dependent)}\` to use new split modules`,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
// Mark original for refactoring
|
|
71
|
+
operations.push({
|
|
72
|
+
type: 'MODIFY',
|
|
73
|
+
path: isDotNotation ? `${moduleDir}/${moduleName}.${ext}` : file,
|
|
74
|
+
description: `Refactor \`${moduleName}.${ext}\` — extract grouped functionality to new modules`,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
if (operations.length > 0) {
|
|
78
|
+
steps.push({
|
|
79
|
+
id: 0,
|
|
80
|
+
tier: 1,
|
|
81
|
+
rule: this.name,
|
|
82
|
+
priority: connections.incoming.length >= 8 ? 'CRITICAL' : 'HIGH',
|
|
83
|
+
title: `Split hub file: ${moduleName}.${ext}`,
|
|
84
|
+
description: `\`${file}\` has ${connections.incoming.length} incoming connections. ` +
|
|
85
|
+
`Split into ${dependentGroups.length} focused modules to reduce coupling.`,
|
|
86
|
+
rationale: `High fan-in (${connections.incoming.length} files depend on this) creates a bottleneck. ` +
|
|
87
|
+
`Changes to this file ripple to ${connections.incoming.length} other files. ` +
|
|
88
|
+
`Splitting by usage pattern reduces blast radius.`,
|
|
89
|
+
operations,
|
|
90
|
+
scoreImpact: [
|
|
91
|
+
{ metric: 'coupling', before: report.score.breakdown.coupling, after: Math.min(95, report.score.breakdown.coupling + 15) },
|
|
92
|
+
],
|
|
93
|
+
aiPrompt: `Analyze the file \`${file}\`. Based on its incoming connections, it acts as a coupling bottleneck. Please split this file into the following smaller modules:\n` +
|
|
94
|
+
dependentGroups.map(g => `- \`${moduleName}_${g.name}.${ext}\`: Extract functionality specific to these dependents: ${g.dependents.join(', ')}`).join('\n') +
|
|
95
|
+
`\n\nAfter splitting, securely and automatically update all ${connections.incoming.length} dependent files to import from the new specific modules instead of the monolithic \`${moduleName}.${ext}\`. DO NOT remove any functionality, only move it.`,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return steps;
|
|
100
|
+
}
|
|
101
|
+
groupDependents(dependents) {
|
|
102
|
+
// Group by top-level directory
|
|
103
|
+
const groups = {};
|
|
104
|
+
for (const dep of dependents) {
|
|
105
|
+
const parts = dep.includes('/') ? dep.split('/') : dep.split('.');
|
|
106
|
+
const groupName = parts.length >= 2 ? parts[parts.length - 2] : 'core';
|
|
107
|
+
if (!groups[groupName])
|
|
108
|
+
groups[groupName] = [];
|
|
109
|
+
groups[groupName].push(basename(dep));
|
|
110
|
+
}
|
|
111
|
+
return Object.entries(groups).map(([name, deps]) => ({
|
|
112
|
+
name,
|
|
113
|
+
dependents: deps,
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=hub-splitter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hub-splitter.js","sourceRoot":"","sources":["../../../../src/core/rules/hub-splitter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AnalysisReport } from '../types/core.js';
|
|
2
|
+
import { RefactorRule, RefactorStep } from '../types/rules.js';
|
|
3
|
+
/**
|
|
4
|
+
* Import Organizer Rule (Tier 1)
|
|
5
|
+
* Detects files that import from too many different modules (cross-boundary).
|
|
6
|
+
* Suggests dependency injection or facade patterns.
|
|
7
|
+
*/
|
|
8
|
+
export declare class ImportOrganizerRule implements RefactorRule {
|
|
9
|
+
name: string;
|
|
10
|
+
tier: 1;
|
|
11
|
+
analyze(report: AnalysisReport, _projectPath: string): RefactorStep[];
|
|
12
|
+
private generateFacadeContent;
|
|
13
|
+
}
|