vibecodingmachine-core 2026.2.20-438 → 2026.2.26-1739
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 +240 -0
- package/package.json +10 -2
- package/src/agents/Agent.js +300 -0
- package/src/agents/AgentAdditionService.js +311 -0
- package/src/agents/AgentCheckService.js +690 -0
- package/src/agents/AgentInstallationService.js +140 -0
- package/src/agents/AgentSetupService.js +467 -0
- package/src/agents/AgentStatus.js +183 -0
- package/src/agents/AgentVerificationService.js +634 -0
- package/src/agents/ConfigurationSchemaValidator.js +543 -0
- package/src/agents/EnvironmentConfigurationManager.js +602 -0
- package/src/agents/InstallationErrorHandler.js +372 -0
- package/src/agents/InstallationLog.js +363 -0
- package/src/agents/InstallationMethod.js +510 -0
- package/src/agents/InstallationOrchestrator.js +352 -0
- package/src/agents/InstallationProgressReporter.js +372 -0
- package/src/agents/InstallationRetryManager.js +322 -0
- package/src/agents/InstallationType.js +254 -0
- package/src/agents/OperationTypes.js +310 -0
- package/src/agents/PerformanceMetricsCollector.js +493 -0
- package/src/agents/SecurityValidationService.js +534 -0
- package/src/agents/VerificationTest.js +354 -0
- package/src/agents/VerificationType.js +226 -0
- package/src/agents/WindowsPermissionHandler.js +518 -0
- package/src/agents/config/AgentConfigManager.js +393 -0
- package/src/agents/config/AgentDefaultsRegistry.js +373 -0
- package/src/agents/config/ConfigValidator.js +281 -0
- package/src/agents/discovery/AgentDiscoveryService.js +707 -0
- package/src/agents/logging/AgentLogger.js +511 -0
- package/src/agents/status/AgentStatusManager.js +481 -0
- package/src/agents/storage/FileManager.js +454 -0
- package/src/agents/verification/AgentCommunicationTester.js +474 -0
- package/src/agents/verification/BaseVerifier.js +430 -0
- package/src/agents/verification/CommandVerifier.js +480 -0
- package/src/agents/verification/FileOperationVerifier.js +453 -0
- package/src/agents/verification/ResultAnalyzer.js +707 -0
- package/src/agents/verification/TestRequirementManager.js +495 -0
- package/src/agents/verification/VerificationRunner.js +433 -0
- package/src/agents/windows/BaseWindowsInstaller.js +441 -0
- package/src/agents/windows/ChocolateyInstaller.js +509 -0
- package/src/agents/windows/DirectInstaller.js +443 -0
- package/src/agents/windows/InstallerFactory.js +391 -0
- package/src/agents/windows/NpmInstaller.js +505 -0
- package/src/agents/windows/PowerShellInstaller.js +458 -0
- package/src/agents/windows/WinGetInstaller.js +390 -0
- package/src/analysis/analysis-reporter.js +132 -0
- package/src/analysis/boundary-detector.js +712 -0
- package/src/analysis/categorizer.js +340 -0
- package/src/analysis/codebase-scanner.js +384 -0
- package/src/analysis/line-counter.js +513 -0
- package/src/analysis/priority-calculator.js +679 -0
- package/src/analysis/report/analysis-report.js +250 -0
- package/src/analysis/report/package-analyzer.js +278 -0
- package/src/analysis/report/recommendation-generator.js +382 -0
- package/src/analysis/report/statistics-generator.js +515 -0
- package/src/analysis/reports/analysis-report-model.js +101 -0
- package/src/analysis/reports/recommendation-generator.js +283 -0
- package/src/analysis/reports/report-generators.js +191 -0
- package/src/analysis/reports/statistics-calculator.js +231 -0
- package/src/analysis/reports/trend-analyzer.js +219 -0
- package/src/analysis/strategy-generator.js +814 -0
- package/src/auto-mode/AutoModeBusinessLogic.js +836 -0
- package/src/config/refactoring-config.js +307 -0
- package/src/health-tracking/json-storage.js +38 -2
- package/src/ide-integration/applescript-manager-core.js +233 -0
- package/src/ide-integration/applescript-manager.cjs +357 -28
- package/src/ide-integration/applescript-manager.js +89 -3599
- package/src/ide-integration/cdp-manager.js +306 -0
- package/src/ide-integration/claude-code-cli-manager.cjs +1 -1
- package/src/ide-integration/continuation-handler.js +337 -0
- package/src/ide-integration/ide-status-checker.js +292 -0
- package/src/ide-integration/macos-ide-manager.js +627 -0
- package/src/ide-integration/macos-text-sender.js +528 -0
- package/src/ide-integration/response-reader.js +548 -0
- package/src/ide-integration/windows-automation-manager.js +121 -0
- package/src/ide-integration/windows-ide-manager.js +373 -0
- package/src/index.cjs +25 -3
- package/src/index.js +15 -1
- package/src/llm/direct-llm-manager.cjs +90 -2
- package/src/models/compliance-report.js +538 -0
- package/src/models/file-analysis.js +681 -0
- package/src/models/refactoring-plan.js +770 -0
- package/src/monitoring/alert-system.js +834 -0
- package/src/monitoring/compliance-progress-tracker.js +437 -0
- package/src/monitoring/continuous-scan-notifications.js +661 -0
- package/src/monitoring/continuous-scanner.js +279 -0
- package/src/monitoring/file-monitor/file-analyzer.js +262 -0
- package/src/monitoring/file-monitor/file-monitor.js +237 -0
- package/src/monitoring/file-monitor/watcher.js +194 -0
- package/src/monitoring/file-monitor.js +17 -0
- package/src/monitoring/notification-manager.js +437 -0
- package/src/monitoring/scanner-core.js +368 -0
- package/src/monitoring/scanner-events.js +214 -0
- package/src/monitoring/violation-notification-system.js +515 -0
- package/src/refactoring/boundaries/cohesion-analyzer.js +316 -0
- package/src/refactoring/boundaries/extraction-result.js +285 -0
- package/src/refactoring/boundaries/extraction-strategies.js +392 -0
- package/src/refactoring/boundaries/module-boundary.js +209 -0
- package/src/refactoring/boundary/boundary-detector.js +741 -0
- package/src/refactoring/boundary/boundary-types.js +405 -0
- package/src/refactoring/boundary/extraction-strategies.js +554 -0
- package/src/refactoring/boundary-extraction-result.js +77 -0
- package/src/refactoring/boundary-extraction-strategies.js +330 -0
- package/src/refactoring/boundary-extractor.js +384 -0
- package/src/refactoring/boundary-types.js +46 -0
- package/src/refactoring/circular/circular-dependency.js +88 -0
- package/src/refactoring/circular/cycle-detection.js +147 -0
- package/src/refactoring/circular/dependency-node.js +82 -0
- package/src/refactoring/circular/dependency-result.js +107 -0
- package/src/refactoring/circular/dependency-types.js +58 -0
- package/src/refactoring/circular/graph-builder.js +213 -0
- package/src/refactoring/circular/resolution-strategy.js +72 -0
- package/src/refactoring/circular/strategy-generator.js +229 -0
- package/src/refactoring/circular-dependency-resolver-original.js +809 -0
- package/src/refactoring/circular-dependency-resolver.js +200 -0
- package/src/refactoring/code-mover.js +761 -0
- package/src/refactoring/file-splitter.js +696 -0
- package/src/refactoring/functionality-validator.js +816 -0
- package/src/refactoring/import-manager.js +774 -0
- package/src/refactoring/module-boundary.js +107 -0
- package/src/refactoring/refactoring-executor.js +672 -0
- package/src/refactoring/refactoring-rollback.js +614 -0
- package/src/refactoring/test-validator.js +631 -0
- package/src/requirement-management/default-requirement-manager.js +321 -0
- package/src/requirement-management/requirement-file-parser.js +159 -0
- package/src/requirement-management/requirement-sequencer.js +221 -0
- package/src/rui/commands/AgentCommandParser.js +600 -0
- package/src/rui/commands/AgentCommands.js +487 -0
- package/src/rui/commands/AgentResponseFormatter.js +832 -0
- package/src/scripts/verify-full-compliance.js +269 -0
- package/src/sync/sync-engine-core.js +1 -0
- package/src/sync/sync-engine-remote-handlers.js +135 -0
- package/src/task-generation/automated-task-generator.js +351 -0
- package/src/task-generation/prioritizer.js +287 -0
- package/src/task-generation/task-list-updater.js +215 -0
- package/src/task-generation/task-management-integration.js +480 -0
- package/src/task-generation/task-manager-integration.js +270 -0
- package/src/task-generation/violation-task-generator.js +474 -0
- package/src/task-management/continuous-scan-integration.js +342 -0
- package/src/timeout-management/index.js +12 -3
- package/src/timeout-management/response-time-tracker.js +167 -0
- package/src/timeout-management/timeout-calculator.js +159 -0
- package/src/timeout-management/timeout-config-manager.js +172 -0
- package/src/utils/ast-analyzer.js +417 -0
- package/src/utils/current-requirement-manager.js +276 -0
- package/src/utils/current-requirement-operations.js +472 -0
- package/src/utils/dependency-mapper.js +456 -0
- package/src/utils/download-with-progress.js +4 -2
- package/src/utils/electron-update-checker.js +4 -1
- package/src/utils/file-size-analyzer.js +272 -0
- package/src/utils/import-updater.js +280 -0
- package/src/utils/refactoring-tools.js +512 -0
- package/src/utils/report-generator.js +569 -0
- package/src/utils/reports/report-analysis.js +218 -0
- package/src/utils/reports/report-types.js +55 -0
- package/src/utils/reports/summary-generators.js +102 -0
- package/src/utils/requirement-file-management.js +157 -0
- package/src/utils/requirement-helpers/requirement-file-ops.js +392 -0
- package/src/utils/requirement-helpers/requirement-mover.js +414 -0
- package/src/utils/requirement-helpers/requirement-parser.js +326 -0
- package/src/utils/requirement-helpers/requirement-status.js +320 -0
- package/src/utils/requirement-helpers-new.js +55 -0
- package/src/utils/requirement-helpers-refactored.js +367 -0
- package/src/utils/requirement-helpers.js +291 -1191
- package/src/utils/requirement-movement-operations.js +450 -0
- package/src/utils/requirement-movement.js +312 -0
- package/src/utils/requirement-parsing-helpers.js +56 -0
- package/src/utils/requirement-statistics.js +200 -0
- package/src/utils/requirement-text-utils.js +58 -0
- package/src/utils/rollback/rollback-handlers.js +125 -0
- package/src/utils/rollback/rollback-operation.js +63 -0
- package/src/utils/rollback/rollback-recorder.js +166 -0
- package/src/utils/rollback/rollback-state-manager.js +175 -0
- package/src/utils/rollback/rollback-types.js +33 -0
- package/src/utils/rollback/rollback-utils.js +110 -0
- package/src/utils/rollback-manager-original.js +569 -0
- package/src/utils/rollback-manager.js +202 -0
- package/src/utils/smoke-test-cli.js +362 -0
- package/src/utils/smoke-test-gui.js +351 -0
- package/src/utils/smoke-test-orchestrator.js +321 -0
- package/src/utils/smoke-test-runner.js +60 -0
- package/src/utils/smoke-test-web.js +347 -0
- package/src/utils/specification-helpers.js +39 -13
- package/src/utils/specification-migration.js +97 -0
- package/src/utils/test-runner.js +579 -0
- package/src/utils/validation-framework.js +518 -0
- package/src/validation/compliance-analyzer.js +197 -0
- package/src/validation/compliance-report-generator.js +343 -0
- package/src/validation/compliance-reporter.js +711 -0
- package/src/validation/compliance-rules.js +127 -0
- package/src/validation/constitution-validator-new.js +196 -0
- package/src/validation/constitution-validator.js +17 -0
- package/src/validation/file-validators.js +170 -0
- package/src/validation/line-limit/file-analyzer.js +201 -0
- package/src/validation/line-limit/line-limit-validator.js +208 -0
- package/src/validation/line-limit/validation-result.js +144 -0
- package/src/validation/line-limit-core.js +225 -0
- package/src/validation/line-limit-reporter.js +134 -0
- package/src/validation/line-limit-result.js +125 -0
- package/src/validation/line-limit-validator.js +41 -0
- package/src/validation/metrics-calculator.js +660 -0
- package/src/sync/sync-engine-backup.js +0 -559
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Refactoring Tools Utility
|
|
3
|
+
* Core utilities for safe code refactoring operations
|
|
4
|
+
* Part of specs/010-555-max-file-size implementation (Task T004)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Safely split a file into multiple modules
|
|
12
|
+
* @param {string} filePath - Path to file to split
|
|
13
|
+
* @param {Object} splitPlan - Plan for how to split the file
|
|
14
|
+
* @returns {Object} Split results
|
|
15
|
+
*/
|
|
16
|
+
function splitFile(filePath, splitPlan) {
|
|
17
|
+
try {
|
|
18
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
19
|
+
const lines = content.split('\n');
|
|
20
|
+
|
|
21
|
+
const results = {
|
|
22
|
+
originalFile: filePath,
|
|
23
|
+
totalLines: lines.length,
|
|
24
|
+
modules: [],
|
|
25
|
+
errors: [],
|
|
26
|
+
warnings: []
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// Validate split plan
|
|
30
|
+
const validation = validateSplitPlan(splitPlan, lines.length);
|
|
31
|
+
if (!validation.isValid) {
|
|
32
|
+
results.errors.push(...validation.errors);
|
|
33
|
+
return results;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Create each module
|
|
37
|
+
splitPlan.modules.forEach((modulePlan, index) => {
|
|
38
|
+
const moduleResult = createModule(filePath, modulePlan, lines, index);
|
|
39
|
+
results.modules.push(moduleResult);
|
|
40
|
+
|
|
41
|
+
if (moduleResult.error) {
|
|
42
|
+
results.errors.push(moduleResult.error);
|
|
43
|
+
}
|
|
44
|
+
if (moduleResult.warnings) {
|
|
45
|
+
results.warnings.push(...moduleResult.warnings);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return results;
|
|
50
|
+
} catch (error) {
|
|
51
|
+
return {
|
|
52
|
+
originalFile: filePath,
|
|
53
|
+
error: error.message,
|
|
54
|
+
modules: []
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Validate a split plan
|
|
61
|
+
* @param {Object} splitPlan - Split plan to validate
|
|
62
|
+
* @param {number} totalLines - Total lines in source file
|
|
63
|
+
* @returns {Object} Validation results
|
|
64
|
+
*/
|
|
65
|
+
function validateSplitPlan(splitPlan, totalLines) {
|
|
66
|
+
const errors = [];
|
|
67
|
+
const warnings = [];
|
|
68
|
+
|
|
69
|
+
if (!splitPlan.modules || !Array.isArray(splitPlan.modules)) {
|
|
70
|
+
errors.push('Split plan must contain modules array');
|
|
71
|
+
return { isValid: false, errors, warnings };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (splitPlan.modules.length === 0) {
|
|
75
|
+
errors.push('Split plan must contain at least one module');
|
|
76
|
+
return { isValid: false, errors, warnings };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let coveredLines = 0;
|
|
80
|
+
const lineRanges = [];
|
|
81
|
+
|
|
82
|
+
splitPlan.modules.forEach((module, index) => {
|
|
83
|
+
if (!module.startLine || !module.endLine) {
|
|
84
|
+
errors.push(`Module ${index} missing startLine or endLine`);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (module.startLine < 1 || module.endLine > totalLines) {
|
|
89
|
+
errors.push(`Module ${index} line range out of bounds`);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (module.startLine > module.endLine) {
|
|
94
|
+
errors.push(`Module ${index} startLine > endLine`);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Check for overlaps
|
|
99
|
+
const range = [module.startLine, module.endLine];
|
|
100
|
+
for (const existingRange of lineRanges) {
|
|
101
|
+
if (rangesOverlap(range, existingRange)) {
|
|
102
|
+
errors.push(`Module ${index} line range overlaps with another module`);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
lineRanges.push(range);
|
|
107
|
+
|
|
108
|
+
coveredLines += (module.endLine - module.startLine + 1);
|
|
109
|
+
|
|
110
|
+
// Check module size
|
|
111
|
+
const moduleSize = module.endLine - module.startLine + 1;
|
|
112
|
+
if (moduleSize > 555) {
|
|
113
|
+
warnings.push(`Module ${index} exceeds 555 lines (${moduleSize} lines)`);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Check if all lines are covered
|
|
118
|
+
if (coveredLines < totalLines) {
|
|
119
|
+
warnings.push(`${totalLines - coveredLines} lines are not included in any module`);
|
|
120
|
+
} else if (coveredLines > totalLines) {
|
|
121
|
+
errors.push('Split plan covers more lines than exist in file');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
isValid: errors.length === 0,
|
|
126
|
+
errors,
|
|
127
|
+
warnings
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Check if two ranges overlap
|
|
133
|
+
* @param {Array} range1 - First range [start, end]
|
|
134
|
+
* @param {Array} range2 - Second range [start, end]
|
|
135
|
+
* @returns {boolean}
|
|
136
|
+
*/
|
|
137
|
+
function rangesOverlap(range1, range2) {
|
|
138
|
+
const [start1, end1] = range1;
|
|
139
|
+
const [start2, end2] = range2;
|
|
140
|
+
return !(end1 < start2 || end2 < start1);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Create a module file
|
|
145
|
+
* @param {string} sourceFile - Source file path
|
|
146
|
+
* @param {Object} modulePlan - Module plan
|
|
147
|
+
* @param {Array} lines - All lines from source file
|
|
148
|
+
* @param {number} index - Module index
|
|
149
|
+
* @returns {Object} Module creation result
|
|
150
|
+
*/
|
|
151
|
+
function createModule(sourceFile, modulePlan, lines, index) {
|
|
152
|
+
const result = {
|
|
153
|
+
moduleName: modulePlan.name || `module-${index + 1}`,
|
|
154
|
+
filePath: null,
|
|
155
|
+
content: null,
|
|
156
|
+
lines: [],
|
|
157
|
+
imports: [],
|
|
158
|
+
exports: [],
|
|
159
|
+
error: null,
|
|
160
|
+
warnings: []
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
// Extract lines for this module
|
|
165
|
+
const startIdx = modulePlan.startLine - 1; // Convert to 0-based
|
|
166
|
+
const endIdx = modulePlan.endLine; // endLine is 1-based, slice is exclusive
|
|
167
|
+
result.lines = lines.slice(startIdx, endIdx);
|
|
168
|
+
result.content = result.lines.join('\n');
|
|
169
|
+
|
|
170
|
+
// Determine output file path
|
|
171
|
+
const sourceDir = path.dirname(sourceFile);
|
|
172
|
+
const sourceExt = path.extname(sourceFile);
|
|
173
|
+
const moduleFileName = `${result.moduleName}${sourceExt}`;
|
|
174
|
+
result.filePath = path.join(sourceDir, moduleFileName);
|
|
175
|
+
|
|
176
|
+
// Analyze imports and exports
|
|
177
|
+
result.imports = extractImports(result.lines);
|
|
178
|
+
result.exports = extractExports(result.lines);
|
|
179
|
+
|
|
180
|
+
// Add warnings for potential issues
|
|
181
|
+
if (result.imports.length === 0 && result.exports.length === 0) {
|
|
182
|
+
result.warnings.push('Module has no imports or exports - may be isolated');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (result.lines.length > 555) {
|
|
186
|
+
result.warnings.push(`Module exceeds 555 lines (${result.lines.length} lines)`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
} catch (error) {
|
|
190
|
+
result.error = error.message;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return result;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Extract imports from lines
|
|
198
|
+
* @param {Array} lines - Array of code lines
|
|
199
|
+
* @returns {Array} Array of import objects
|
|
200
|
+
*/
|
|
201
|
+
function extractImports(lines) {
|
|
202
|
+
const imports = [];
|
|
203
|
+
|
|
204
|
+
lines.forEach((line, index) => {
|
|
205
|
+
const trimmed = line.trim();
|
|
206
|
+
|
|
207
|
+
// ES6 imports
|
|
208
|
+
const es6Match = trimmed.match(/^import\s+.+from\s+['"]([^'"]+)['"]/);
|
|
209
|
+
if (es6Match) {
|
|
210
|
+
imports.push({
|
|
211
|
+
type: 'es6',
|
|
212
|
+
module: es6Match[1],
|
|
213
|
+
line: index + 1,
|
|
214
|
+
statement: trimmed
|
|
215
|
+
});
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// CommonJS requires
|
|
220
|
+
const cjsMatch = trimmed.match(/require\(['"]([^'"]+)['"]\)/);
|
|
221
|
+
if (cjsMatch) {
|
|
222
|
+
imports.push({
|
|
223
|
+
type: 'commonjs',
|
|
224
|
+
module: cjsMatch[1],
|
|
225
|
+
line: index + 1,
|
|
226
|
+
statement: trimmed
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
return imports;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Extract exports from lines
|
|
236
|
+
* @param {Array} lines - Array of code lines
|
|
237
|
+
* @returns {Array} Array of export objects
|
|
238
|
+
*/
|
|
239
|
+
function extractExports(lines) {
|
|
240
|
+
const exports = [];
|
|
241
|
+
|
|
242
|
+
lines.forEach((line, index) => {
|
|
243
|
+
const trimmed = line.trim();
|
|
244
|
+
|
|
245
|
+
// ES6 exports
|
|
246
|
+
if (trimmed.startsWith('export ')) {
|
|
247
|
+
exports.push({
|
|
248
|
+
type: 'es6',
|
|
249
|
+
line: index + 1,
|
|
250
|
+
statement: trimmed
|
|
251
|
+
});
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// CommonJS exports
|
|
256
|
+
if (trimmed.startsWith('module.exports')) {
|
|
257
|
+
exports.push({
|
|
258
|
+
type: 'commonjs',
|
|
259
|
+
line: index + 1,
|
|
260
|
+
statement: trimmed
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
return exports;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Move code segment to new file
|
|
270
|
+
* @param {string} sourceFile - Source file path
|
|
271
|
+
* @param {Object} segment - Code segment to move
|
|
272
|
+
* @param {string} targetFile - Target file path
|
|
273
|
+
* @returns {Object} Move result
|
|
274
|
+
*/
|
|
275
|
+
function moveCodeSegment(sourceFile, segment, targetFile) {
|
|
276
|
+
try {
|
|
277
|
+
const sourceContent = fs.readFileSync(sourceFile, 'utf8');
|
|
278
|
+
const lines = sourceContent.split('\n');
|
|
279
|
+
|
|
280
|
+
const result = {
|
|
281
|
+
sourceFile,
|
|
282
|
+
targetFile,
|
|
283
|
+
segment,
|
|
284
|
+
linesMoved: 0,
|
|
285
|
+
sourceUpdated: false,
|
|
286
|
+
targetCreated: false,
|
|
287
|
+
error: null
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
// Validate segment
|
|
291
|
+
if (segment.startLine < 1 || segment.endLine > lines.length) {
|
|
292
|
+
result.error = 'Segment line range out of bounds';
|
|
293
|
+
return result;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (segment.startLine > segment.endLine) {
|
|
297
|
+
result.error = 'Invalid segment line range';
|
|
298
|
+
return result;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Extract segment
|
|
302
|
+
const startIdx = segment.startLine - 1;
|
|
303
|
+
const endIdx = segment.endLine;
|
|
304
|
+
const segmentLines = lines.slice(startIdx, endIdx);
|
|
305
|
+
result.linesMoved = segmentLines.length;
|
|
306
|
+
|
|
307
|
+
// Create target file
|
|
308
|
+
const targetDir = path.dirname(targetFile);
|
|
309
|
+
if (!fs.existsSync(targetDir)) {
|
|
310
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
fs.writeFileSync(targetFile, segmentLines.join('\n'));
|
|
314
|
+
result.targetCreated = true;
|
|
315
|
+
|
|
316
|
+
// Remove segment from source
|
|
317
|
+
const remainingLines = [
|
|
318
|
+
...lines.slice(0, startIdx),
|
|
319
|
+
...lines.slice(endIdx)
|
|
320
|
+
];
|
|
321
|
+
|
|
322
|
+
fs.writeFileSync(sourceFile, remainingLines.join('\n'));
|
|
323
|
+
result.sourceUpdated = true;
|
|
324
|
+
|
|
325
|
+
return result;
|
|
326
|
+
} catch (error) {
|
|
327
|
+
return {
|
|
328
|
+
sourceFile,
|
|
329
|
+
targetFile,
|
|
330
|
+
segment,
|
|
331
|
+
error: error.message
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Update import statements after refactoring
|
|
338
|
+
* @param {string} filePath - File to update
|
|
339
|
+
* @param {Array} importUpdates - Array of import updates
|
|
340
|
+
* @returns {Object} Update result
|
|
341
|
+
*/
|
|
342
|
+
function updateImportStatements(filePath, importUpdates) {
|
|
343
|
+
try {
|
|
344
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
345
|
+
const lines = content.split('\n');
|
|
346
|
+
|
|
347
|
+
const result = {
|
|
348
|
+
filePath,
|
|
349
|
+
updates: importUpdates,
|
|
350
|
+
appliedUpdates: [],
|
|
351
|
+
failedUpdates: [],
|
|
352
|
+
error: null
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
// Apply updates in reverse order to maintain line numbers
|
|
356
|
+
const sortedUpdates = importUpdates
|
|
357
|
+
.filter(update => update.line && update.newStatement)
|
|
358
|
+
.sort((a, b) => b.line - a.line);
|
|
359
|
+
|
|
360
|
+
sortedUpdates.forEach(update => {
|
|
361
|
+
try {
|
|
362
|
+
const lineIdx = update.line - 1;
|
|
363
|
+
if (lineIdx >= 0 && lineIdx < lines.length) {
|
|
364
|
+
lines[lineIdx] = update.newStatement;
|
|
365
|
+
result.appliedUpdates.push(update);
|
|
366
|
+
} else {
|
|
367
|
+
result.failedUpdates.push({
|
|
368
|
+
...update,
|
|
369
|
+
reason: 'Line number out of range'
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
} catch (error) {
|
|
373
|
+
result.failedUpdates.push({
|
|
374
|
+
...update,
|
|
375
|
+
reason: error.message
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
// Write updated content
|
|
381
|
+
if (result.appliedUpdates.length > 0) {
|
|
382
|
+
fs.writeFileSync(filePath, lines.join('\n'));
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return result;
|
|
386
|
+
} catch (error) {
|
|
387
|
+
return {
|
|
388
|
+
filePath,
|
|
389
|
+
error: error.message,
|
|
390
|
+
appliedUpdates: [],
|
|
391
|
+
failedUpdates: importUpdates
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Validate refactoring preserves functionality
|
|
398
|
+
* @param {string} originalFile - Original file path
|
|
399
|
+
* @param {Array} refactoredFiles - Array of refactored file paths
|
|
400
|
+
* @returns {Object} Validation result
|
|
401
|
+
*/
|
|
402
|
+
function validateFunctionality(originalFile, refactoredFiles) {
|
|
403
|
+
const result = {
|
|
404
|
+
originalFile,
|
|
405
|
+
refactoredFiles,
|
|
406
|
+
isValid: true,
|
|
407
|
+
errors: [],
|
|
408
|
+
warnings: [],
|
|
409
|
+
missingExports: [],
|
|
410
|
+
orphanedImports: []
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
try {
|
|
414
|
+
// Analyze original file
|
|
415
|
+
const originalContent = fs.readFileSync(originalFile, 'utf8');
|
|
416
|
+
const originalLines = originalContent.split('\n');
|
|
417
|
+
const originalExports = extractExports(originalLines);
|
|
418
|
+
|
|
419
|
+
// Check each refactored file
|
|
420
|
+
let allExports = [];
|
|
421
|
+
let allImports = [];
|
|
422
|
+
|
|
423
|
+
refactoredFiles.forEach(filePath => {
|
|
424
|
+
try {
|
|
425
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
426
|
+
const lines = content.split('\n');
|
|
427
|
+
|
|
428
|
+
const fileExports = extractExports(lines);
|
|
429
|
+
const fileImports = extractImports(lines);
|
|
430
|
+
|
|
431
|
+
allExports.push(...fileExports.map(e => ({ ...e, file: filePath })));
|
|
432
|
+
allImports.push(...fileImports.map(i => ({ ...i, file: filePath })));
|
|
433
|
+
} catch (error) {
|
|
434
|
+
result.errors.push(`Failed to read ${filePath}: ${error.message}`);
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
// Check for missing exports
|
|
439
|
+
originalExports.forEach(originalExport => {
|
|
440
|
+
const found = allExports.some(refactoredExport =>
|
|
441
|
+
originalExport.statement === refactoredExport.statement
|
|
442
|
+
);
|
|
443
|
+
|
|
444
|
+
if (!found) {
|
|
445
|
+
result.missingExports.push(originalExport);
|
|
446
|
+
result.isValid = false;
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
// Check for orphaned imports (imports that don't have corresponding exports)
|
|
451
|
+
allImports.forEach(importObj => {
|
|
452
|
+
if (importObj.module.startsWith('./') || importObj.module.startsWith('../')) {
|
|
453
|
+
// This is a relative import - check if target file exists and has exports
|
|
454
|
+
const targetPath = path.resolve(path.dirname(importObj.file), importObj.module);
|
|
455
|
+
if (!fs.existsSync(targetPath)) {
|
|
456
|
+
result.orphanedImports.push(importObj);
|
|
457
|
+
result.warnings.push(`Orphaned import: ${importObj.module} in ${importObj.file}`);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
} catch (error) {
|
|
463
|
+
result.error = error.message;
|
|
464
|
+
result.isValid = false;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return result;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Generate refactoring summary
|
|
472
|
+
* @param {Object} refactoringResult - Result from splitFile or other refactoring operation
|
|
473
|
+
* @returns {Object} Summary report
|
|
474
|
+
*/
|
|
475
|
+
function generateRefactoringSummary(refactoringResult) {
|
|
476
|
+
const summary = {
|
|
477
|
+
operation: refactoringResult.originalFile ? 'file-split' : 'unknown',
|
|
478
|
+
originalFile: refactoringResult.originalFile,
|
|
479
|
+
success: !refactoringResult.error,
|
|
480
|
+
totalLines: refactoringResult.totalLines || 0,
|
|
481
|
+
modulesCreated: refactoringResult.modules ? refactoringResult.modules.length : 0,
|
|
482
|
+
errors: refactoringResult.errors || [],
|
|
483
|
+
warnings: refactoringResult.warnings || [],
|
|
484
|
+
moduleDetails: []
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
if (refactoringResult.modules) {
|
|
488
|
+
refactoringResult.modules.forEach(module => {
|
|
489
|
+
summary.moduleDetails.push({
|
|
490
|
+
name: module.moduleName,
|
|
491
|
+
path: module.filePath,
|
|
492
|
+
lines: module.lines ? module.lines.length : 0,
|
|
493
|
+
imports: module.imports ? module.imports.length : 0,
|
|
494
|
+
exports: module.exports ? module.exports.length : 0,
|
|
495
|
+
hasError: !!module.error
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
return summary;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
module.exports = {
|
|
504
|
+
splitFile,
|
|
505
|
+
moveCodeSegment,
|
|
506
|
+
updateImportStatements,
|
|
507
|
+
validateFunctionality,
|
|
508
|
+
generateRefactoringSummary,
|
|
509
|
+
validateSplitPlan,
|
|
510
|
+
extractImports,
|
|
511
|
+
extractExports
|
|
512
|
+
};
|