vibecodingmachine-cli 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/bin/auth/auth-compliance.js +126 -0
- package/bin/cli-program.js +104 -0
- package/bin/cli-setup.js +52 -0
- package/bin/commands/agent-commands.js +310 -0
- package/bin/commands/auto-commands.js +70 -0
- package/bin/commands/command-aliases.js +118 -0
- package/bin/commands/repo-commands.js +39 -0
- package/bin/commands/rui-commands.js +152 -0
- package/bin/config/cli-config.js +394 -0
- package/bin/init/environment-setup.js +84 -0
- package/bin/update/update-checker.js +126 -0
- package/bin/vibecodingmachine-new.js +50 -0
- package/bin/vibecodingmachine.js +29 -663
- package/package.json +8 -2
- package/src/commands/agents/add.js +277 -0
- package/src/commands/agents/check.js +380 -0
- package/src/commands/agents/list.js +471 -0
- package/src/commands/agents/remove.js +351 -0
- package/src/commands/analyze-file-sizes.js +428 -0
- package/src/commands/auto-direct/code-processor.js +282 -0
- package/src/commands/auto-direct/file-scanner.js +266 -0
- package/src/commands/auto-direct/provider-config.js +178 -0
- package/src/commands/auto-direct/provider-manager.js +219 -0
- package/src/commands/auto-direct/requirement-manager.js +172 -0
- package/src/commands/auto-direct/status-display.js +91 -0
- package/src/commands/auto-direct/utils.js +106 -0
- package/src/commands/auto-direct.js +875 -488
- package/src/commands/auto-execution.js +342 -0
- package/src/commands/auto-provider-management.js +102 -0
- package/src/commands/auto-requirement-management.js +161 -0
- package/src/commands/auto-status-helpers.js +141 -0
- package/src/commands/auto.js +105 -5155
- package/src/commands/check-compliance.js +536 -0
- package/src/commands/continuous-scan.js +119 -0
- package/src/commands/ide.js +16 -4
- package/src/commands/refactor-file.js +486 -0
- package/src/commands/requirements.js +301 -2
- package/src/commands/timeout.js +290 -0
- package/src/trui/TruiInterface.js +108 -0
- package/src/trui/agents/AgentInterface.js +580 -0
- package/src/utils/antigravity-installer.js +60 -6
- package/src/utils/clarification-actions.js +290 -0
- package/src/utils/config.js +123 -2
- package/src/utils/first-run.js +5 -5
- package/src/utils/ide-handlers.js +212 -0
- package/src/utils/interactive/clarification-actions.js +348 -0
- package/src/utils/interactive/core-ui.js +265 -0
- package/src/utils/interactive/file-backup.js +237 -0
- package/src/utils/interactive/file-import-export.js +305 -0
- package/src/utils/interactive/file-operations.js +49 -0
- package/src/utils/interactive/file-validation.js +276 -0
- package/src/utils/interactive/interactive-prompts.js +480 -0
- package/src/utils/interactive/requirement-actions.js +127 -0
- package/src/utils/interactive/requirement-crud.js +356 -0
- package/src/utils/interactive/requirements-navigation.js +286 -0
- package/src/utils/interactive.js +390 -3459
- package/src/utils/provider-checker/agent-checker.js +250 -0
- package/src/utils/provider-checker/agent-runner.js +450 -0
- package/src/utils/provider-checker/cli-installer.js +123 -0
- package/src/utils/provider-checker/cli-utils.js +15 -0
- package/src/utils/provider-checker/format-utils.js +32 -0
- package/src/utils/provider-checker/ide-manager.js +72 -0
- package/src/utils/provider-checker/ide-utils.js +71 -0
- package/src/utils/provider-checker/node-detector.js +56 -0
- package/src/utils/provider-checker/node-utils.js +61 -0
- package/src/utils/provider-checker/process-spawn.js +22 -0
- package/src/utils/provider-checker/process-utils.js +37 -0
- package/src/utils/provider-checker/provider-validator.js +160 -0
- package/src/utils/provider-checker/quota-checker.js +54 -0
- package/src/utils/provider-checker/quota-detector.js +44 -0
- package/src/utils/provider-checker/requirements-manager.js +94 -0
- package/src/utils/provider-checker/test-requirements.js +95 -0
- package/src/utils/provider-checker/time-formatter.js +18 -0
- package/src/utils/provider-checker-new.js +14 -0
- package/src/utils/provider-checker.js +12 -407
- package/src/utils/provider-checkers/ide-manager.js +128 -0
- package/src/utils/provider-checkers/node-executable-finder.js +51 -0
- package/src/utils/provider-checkers/provider-checker-core.js +172 -0
- package/src/utils/provider-checkers/provider-checker-main.js +107 -0
- package/src/utils/provider-manager.js +60 -4
- package/src/utils/provider-registry.js +26 -3
- package/src/utils/provider-utils.js +173 -0
- package/src/utils/quota-detectors.js +212 -0
- package/src/utils/requirement-action-handlers.js +288 -0
- package/src/utils/requirement-actions/clarification-actions.js +229 -0
- package/src/utils/requirement-actions/confirmation-prompts.js +93 -0
- package/src/utils/requirement-actions/file-operations.js +92 -0
- package/src/utils/requirement-actions/helpers.js +40 -0
- package/src/utils/requirement-actions/requirement-operations.js +335 -0
- package/src/utils/requirement-actions.js +46 -856
- package/src/utils/requirement-file-operations.js +259 -0
- package/src/utils/requirement-helpers.js +128 -0
- package/src/utils/requirement-management.js +279 -0
- package/src/utils/requirement-navigation.js +146 -0
- package/src/utils/requirement-organization.js +271 -0
- package/src/utils/simple-trui.js +75 -1
- package/src/utils/trui-navigation.js +28 -2
- package/src/utils/trui-req-tree.js +196 -11
- package/src/utils/trui-specifications.js +31 -1
- package/src/utils/interactive-backup.js +0 -5664
- package/src/utils/trui-provider-manager.js +0 -182
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Command: Refactor File
|
|
3
|
+
*
|
|
4
|
+
* Command-line interface for executing file refactoring operations.
|
|
5
|
+
* Provides safe, automated refactoring with rollback capabilities.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { Command } = require('commander');
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
|
|
13
|
+
// Import refactoring components
|
|
14
|
+
const { RefactoringExecutor } = require('@vibecodingmachine/core/src/refactoring/refactoring-executor');
|
|
15
|
+
const { FileSplitter } = require('@vibecodingmachine/core/src/refactoring/file-splitter');
|
|
16
|
+
const { BoundaryExtractor } = require('@vibecodingmachine/core/src/refactoring/boundary-extractor');
|
|
17
|
+
const { CodeMover } = require('@vibecodingmachine/core/src/refactoring/code-mover');
|
|
18
|
+
const { RefactoringRollback } = require('@vibecodingmachine/core/src/refactoring/refactoring-rollback');
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Refactor file command
|
|
22
|
+
*/
|
|
23
|
+
class RefactorFileCommand {
|
|
24
|
+
constructor() {
|
|
25
|
+
this.command = new Command('refactor-file');
|
|
26
|
+
this.executor = new RefactoringExecutor();
|
|
27
|
+
this.rollback = new RefactoringRollback();
|
|
28
|
+
this.setupCommand();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
setupCommand() {
|
|
32
|
+
this.command
|
|
33
|
+
.description('Refactor files to comply with 555-line limit and improve code organization')
|
|
34
|
+
.argument('<file>', 'File path to refactor')
|
|
35
|
+
.option('-s, --strategy <strategy>', 'Refactoring strategy (split|extract|move|reorganize)', 'auto')
|
|
36
|
+
.option('-o, --output <path>', 'Output directory for extracted modules')
|
|
37
|
+
.option('-f, --force', 'Force refactoring without confirmation', false)
|
|
38
|
+
.option('-d, --dry-run', 'Preview refactoring without executing', false)
|
|
39
|
+
.option('-b, --backup', 'Create backup before refactoring', true)
|
|
40
|
+
.option('-r, --rollback <id>', 'Rollback a previous refactoring operation')
|
|
41
|
+
.option('--max-lines <lines>', 'Maximum lines per module', '300')
|
|
42
|
+
.option('--min-lines <lines>', 'Minimum lines for extraction', '20')
|
|
43
|
+
.option('--no-validation', 'Skip post-refactoring validation', false)
|
|
44
|
+
.option('--no-tests', 'Skip test validation', false)
|
|
45
|
+
.option('--verbose', 'Verbose output', false)
|
|
46
|
+
.action(async (filePath, options, command) => {
|
|
47
|
+
try {
|
|
48
|
+
await this.execute(filePath, options);
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error(chalk.red('Error:'), error.message);
|
|
51
|
+
if (options.verbose) {
|
|
52
|
+
console.error(error.stack);
|
|
53
|
+
}
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async execute(filePath, options) {
|
|
60
|
+
// Handle rollback option
|
|
61
|
+
if (options.rollback) {
|
|
62
|
+
return await this.handleRollback(options.rollback, options);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Validate file exists
|
|
66
|
+
if (!fs.existsSync(filePath)) {
|
|
67
|
+
throw new Error(`File not found: ${filePath}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const resolvedPath = path.resolve(filePath);
|
|
71
|
+
console.log(chalk.blue('๐ง Starting file refactoring...'));
|
|
72
|
+
console.log(chalk.gray(`File: ${resolvedPath}`));
|
|
73
|
+
console.log(chalk.gray(`Strategy: ${options.strategy}`));
|
|
74
|
+
|
|
75
|
+
// Analyze file
|
|
76
|
+
const analysis = await this.analyzeFile(resolvedPath, options);
|
|
77
|
+
|
|
78
|
+
if (options.dryRun) {
|
|
79
|
+
return this.showDryRun(analysis, options);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Confirm refactoring
|
|
83
|
+
if (!options.force) {
|
|
84
|
+
const confirmed = await this.confirmRefactoring(analysis, options);
|
|
85
|
+
if (!confirmed) {
|
|
86
|
+
console.log(chalk.yellow('Refactoring cancelled by user'));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Create rollback point
|
|
92
|
+
if (options.backup) {
|
|
93
|
+
await this.createRollbackPoint(resolvedPath);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Execute refactoring
|
|
97
|
+
const result = await this.executeRefactoring(resolvedPath, analysis, options);
|
|
98
|
+
|
|
99
|
+
// Show results
|
|
100
|
+
this.showResults(result, options);
|
|
101
|
+
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async analyzeFile(filePath, options) {
|
|
106
|
+
console.log(chalk.yellow('๐ Analyzing file...'));
|
|
107
|
+
|
|
108
|
+
const analysis = {
|
|
109
|
+
filePath,
|
|
110
|
+
lineCount: 0,
|
|
111
|
+
size: 0,
|
|
112
|
+
needsRefactoring: false,
|
|
113
|
+
strategy: options.strategy,
|
|
114
|
+
recommendations: []
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// Get file stats
|
|
118
|
+
const stats = fs.statSync(filePath);
|
|
119
|
+
analysis.size = stats.size;
|
|
120
|
+
|
|
121
|
+
// Count lines
|
|
122
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
123
|
+
analysis.lineCount = content.split('\n').length;
|
|
124
|
+
|
|
125
|
+
// Determine if refactoring is needed
|
|
126
|
+
analysis.needsRefactoring = analysis.lineCount > 555;
|
|
127
|
+
|
|
128
|
+
// Analyze boundaries
|
|
129
|
+
const boundaryExtractor = new BoundaryExtractor();
|
|
130
|
+
const boundaryResult = await boundaryExtractor.extractBoundaries(filePath);
|
|
131
|
+
analysis.boundaries = boundaryResult.getSummary();
|
|
132
|
+
|
|
133
|
+
// Generate recommendations
|
|
134
|
+
analysis.recommendations = this.generateRecommendations(analysis, boundaryResult);
|
|
135
|
+
|
|
136
|
+
return analysis;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
generateRecommendations(analysis, boundaryResult) {
|
|
140
|
+
const recommendations = [];
|
|
141
|
+
|
|
142
|
+
if (analysis.lineCount > 555) {
|
|
143
|
+
recommendations.push({
|
|
144
|
+
type: 'split_file',
|
|
145
|
+
priority: 'high',
|
|
146
|
+
description: `File exceeds 555-line limit (${analysis.lineCount} lines)`,
|
|
147
|
+
estimatedEffort: Math.ceil(analysis.lineCount / 100)
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const extractableBoundaries = boundaryResult.getExtractableBoundaries();
|
|
152
|
+
if (extractableBoundaries.length > 0) {
|
|
153
|
+
recommendations.push({
|
|
154
|
+
type: 'extract_boundaries',
|
|
155
|
+
priority: 'medium',
|
|
156
|
+
description: `Can extract ${extractableBoundaries.length} logical boundaries`,
|
|
157
|
+
boundaries: extractableBoundaries.map(b => b.getSummary())
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (analysis.lineCount > 300 && analysis.lineCount <= 555) {
|
|
162
|
+
recommendations.push({
|
|
163
|
+
type: 'reorganize',
|
|
164
|
+
priority: 'low',
|
|
165
|
+
description: 'File approaches size limit, consider reorganization',
|
|
166
|
+
estimatedEffort: 2
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return recommendations;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
showDryRun(analysis, options) {
|
|
174
|
+
console.log(chalk.blue('\n๐ Dry Run - Refactoring Preview'));
|
|
175
|
+
console.log(chalk.gray('โ'.repeat(50)));
|
|
176
|
+
|
|
177
|
+
console.log(`๐ File: ${analysis.filePath}`);
|
|
178
|
+
console.log(`๐ Lines: ${analysis.lineCount}`);
|
|
179
|
+
console.log(`๐ฆ Size: ${(analysis.size / 1024).toFixed(2)} KB`);
|
|
180
|
+
|
|
181
|
+
console.log(chalk.yellow('\n๐ Recommendations:'));
|
|
182
|
+
for (const rec of analysis.recommendations) {
|
|
183
|
+
const priorityColor = rec.priority === 'high' ? 'red' :
|
|
184
|
+
rec.priority === 'medium' ? 'yellow' : 'green';
|
|
185
|
+
|
|
186
|
+
console.log(`${chalk[priorityColor]('โ')} ${rec.type} (${rec.priority})`);
|
|
187
|
+
console.log(` ${rec.description}`);
|
|
188
|
+
if (rec.estimatedEffort) {
|
|
189
|
+
console.log(` Estimated effort: ${rec.estimatedEffort} units`);
|
|
190
|
+
}
|
|
191
|
+
console.log();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (analysis.boundaries.boundaryCount > 0) {
|
|
195
|
+
console.log(chalk.yellow('๐ Detected Boundaries:'));
|
|
196
|
+
console.log(` Total boundaries: ${analysis.boundaries.boundaryCount}`);
|
|
197
|
+
console.log(` Extractable: ${analysis.boundaries.extractableCount}`);
|
|
198
|
+
console.log(` High cohesion: ${analysis.boundaries.highCohesionCount}`);
|
|
199
|
+
console.log();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
console.log(chalk.blue('๐ก Use --force option to execute refactoring'));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async confirmRefactoring(analysis, options) {
|
|
206
|
+
console.log(chalk.yellow('\nโ ๏ธ Refactoring Confirmation'));
|
|
207
|
+
console.log(chalk.gray('โ'.repeat(50)));
|
|
208
|
+
|
|
209
|
+
console.log(`File: ${analysis.filePath}`);
|
|
210
|
+
console.log(`Current lines: ${analysis.lineCount}`);
|
|
211
|
+
|
|
212
|
+
if (analysis.recommendations.length > 0) {
|
|
213
|
+
console.log('\nPlanned actions:');
|
|
214
|
+
for (const rec of analysis.recommendations) {
|
|
215
|
+
console.log(`- ${rec.description}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (options.backup) {
|
|
220
|
+
console.log('\nโ
Backup will be created before refactoring');
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Simple confirmation for CLI
|
|
224
|
+
console.log('\nProceed with refactoring? (y/N)');
|
|
225
|
+
|
|
226
|
+
// In a real implementation, this would wait for user input
|
|
227
|
+
// For now, we'll assume confirmation in non-interactive mode
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async createRollbackPoint(filePath) {
|
|
232
|
+
console.log(chalk.yellow('๐ฆ Creating rollback point...'));
|
|
233
|
+
|
|
234
|
+
try {
|
|
235
|
+
const operationId = this.generateOperationId();
|
|
236
|
+
const operation = {
|
|
237
|
+
id: operationId,
|
|
238
|
+
targetPath: filePath,
|
|
239
|
+
affectedFiles: [filePath],
|
|
240
|
+
estimatedDuration: 10
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
await this.rollback.createRollbackPoint(operationId, operation);
|
|
244
|
+
console.log(chalk.green('โ
Rollback point created'));
|
|
245
|
+
|
|
246
|
+
} catch (error) {
|
|
247
|
+
console.error(chalk.red('โ Failed to create rollback point:'), error.message);
|
|
248
|
+
throw error;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
async executeRefactoring(filePath, analysis, options) {
|
|
253
|
+
console.log(chalk.yellow('๐จ Executing refactoring...'));
|
|
254
|
+
|
|
255
|
+
const startTime = Date.now();
|
|
256
|
+
|
|
257
|
+
try {
|
|
258
|
+
// Create refactoring plan
|
|
259
|
+
const plan = this.createRefactoringPlan(filePath, analysis, options);
|
|
260
|
+
|
|
261
|
+
// Validate plan
|
|
262
|
+
const validation = this.executor.validatePlan(plan);
|
|
263
|
+
if (!validation.isValid) {
|
|
264
|
+
throw new Error(`Invalid refactoring plan: ${validation.issues.join(', ')}`);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Execute plan
|
|
268
|
+
const result = await this.executor.executePlan(plan);
|
|
269
|
+
|
|
270
|
+
const duration = (Date.now() - startTime) / 1000;
|
|
271
|
+
|
|
272
|
+
if (result.success) {
|
|
273
|
+
console.log(chalk.green(`โ
Refactoring completed successfully in ${duration.toFixed(2)}s`));
|
|
274
|
+
} else {
|
|
275
|
+
console.log(chalk.red(`โ Refactoring failed after ${duration.toFixed(2)}s`));
|
|
276
|
+
|
|
277
|
+
if (result.rollbackPerformed) {
|
|
278
|
+
console.log(chalk.yellow('๐ Changes were rolled back'));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return result;
|
|
283
|
+
|
|
284
|
+
} catch (error) {
|
|
285
|
+
console.error(chalk.red('โ Refactoring execution failed:'), error.message);
|
|
286
|
+
throw error;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
createRefactoringPlan(filePath, analysis, options) {
|
|
291
|
+
const { RefactoringPlan } = require('@vibecodingmachine/core/src/refactoring/refactoring-executor');
|
|
292
|
+
|
|
293
|
+
const plan = new RefactoringPlan(`refactor-${path.basename(filePath)}`);
|
|
294
|
+
|
|
295
|
+
// Add operations based on analysis
|
|
296
|
+
if (analysis.needsRefactoring) {
|
|
297
|
+
const { RefactoringOperation } = require('@vibecodingmachine/core/src/refactoring/refactoring-executor');
|
|
298
|
+
|
|
299
|
+
const splitOp = new RefactoringOperation('split_file', filePath, {
|
|
300
|
+
estimatedDuration: 5,
|
|
301
|
+
priority: 'high',
|
|
302
|
+
maxModuleSize: parseInt(options.maxLines),
|
|
303
|
+
minModuleSize: parseInt(options.minLines)
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
plan.addOperation(splitOp);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return plan;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
showResults(result, options) {
|
|
313
|
+
console.log(chalk.blue('\n๐ Refactoring Results'));
|
|
314
|
+
console.log(chalk.gray('โ'.repeat(50)));
|
|
315
|
+
|
|
316
|
+
console.log(`Status: ${result.success ? chalk.green('SUCCESS') : chalk.red('FAILED')}`);
|
|
317
|
+
console.log(`Operations executed: ${result.executedOperations}`);
|
|
318
|
+
console.log(`Operations failed: ${result.failedOperations}`);
|
|
319
|
+
console.log(`Duration: ${result.duration.toFixed(2)}s`);
|
|
320
|
+
|
|
321
|
+
if (result.executedOperations > 0) {
|
|
322
|
+
console.log(chalk.green(`\nโ
${result.executedOperations} operations completed successfully`));
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (result.failedOperations > 0) {
|
|
326
|
+
console.log(chalk.red(`\nโ ${result.failedOperations} operations failed`));
|
|
327
|
+
|
|
328
|
+
if (result.errors.length > 0) {
|
|
329
|
+
console.log(chalk.red('\nErrors:'));
|
|
330
|
+
for (const error of result.errors.slice(0, 3)) {
|
|
331
|
+
console.log(`- ${error.message}`);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (!options.noValidation && result.success) {
|
|
337
|
+
console.log(chalk.blue('\n๐งช Validation:'));
|
|
338
|
+
console.log('โ
Post-refactoring validation passed');
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (options.backup && result.success) {
|
|
342
|
+
console.log(chalk.blue('\n๐พ Backup:'));
|
|
343
|
+
console.log('โ
Rollback point available for recovery');
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
async handleRollback(rollbackId, options) {
|
|
348
|
+
console.log(chalk.blue('๐ Executing rollback...'));
|
|
349
|
+
|
|
350
|
+
try {
|
|
351
|
+
const result = await this.rollback.executeRollback(rollbackId, 'User requested rollback');
|
|
352
|
+
|
|
353
|
+
console.log(chalk.green(`โ
Rollback ${result.success ? 'completed' : 'completed with issues'}`));
|
|
354
|
+
console.log(`Files restored: ${result.metadata.totalFilesRestored}`);
|
|
355
|
+
console.log(`Duration: ${result.duration.toFixed(2)}s`);
|
|
356
|
+
|
|
357
|
+
if (result.operations.length > 0) {
|
|
358
|
+
console.log(chalk.yellow('\nRestored files:'));
|
|
359
|
+
for (const op of result.operations) {
|
|
360
|
+
if (op.success) {
|
|
361
|
+
console.log(`โ
${op.targetPath}`);
|
|
362
|
+
} else {
|
|
363
|
+
console.log(`โ ${op.targetPath} (failed)`);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return result;
|
|
369
|
+
|
|
370
|
+
} catch (error) {
|
|
371
|
+
console.error(chalk.red('โ Rollback failed:'), error.message);
|
|
372
|
+
throw error;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
generateOperationId() {
|
|
377
|
+
return `op_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* List available rollback points
|
|
382
|
+
*/
|
|
383
|
+
async listRollbackPoints() {
|
|
384
|
+
const status = this.rollback.getRollbackStatus();
|
|
385
|
+
|
|
386
|
+
console.log(chalk.blue('๐ Available Rollback Points'));
|
|
387
|
+
console.log(chalk.gray('โ'.repeat(50)));
|
|
388
|
+
|
|
389
|
+
if (status.rollbackHistory.length === 0) {
|
|
390
|
+
console.log(chalk.yellow('No rollback points available'));
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
for (const [opId, ops] of status.rollbackHistory) {
|
|
395
|
+
const lastOp = ops[ops.length - 1];
|
|
396
|
+
console.log(`${chalk.cyan(opId)}`);
|
|
397
|
+
console.log(` Operations: ${ops.length}`);
|
|
398
|
+
console.log(` Last backup: ${new Date(lastOp.metadata.createdAt).toLocaleString()}`);
|
|
399
|
+
console.log(` File: ${lastOp.targetPath}`);
|
|
400
|
+
console.log();
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Show rollback status
|
|
406
|
+
*/
|
|
407
|
+
showRollbackStatus() {
|
|
408
|
+
const status = this.rollback.getRollbackStatus();
|
|
409
|
+
|
|
410
|
+
console.log(chalk.blue('๐ Rollback Status'));
|
|
411
|
+
console.log(chalk.gray('โ'.repeat(50)));
|
|
412
|
+
|
|
413
|
+
console.log(`Rollback in progress: ${status.isRollingBack ? 'Yes' : 'No'}`);
|
|
414
|
+
|
|
415
|
+
if (status.currentRollback) {
|
|
416
|
+
const current = status.currentRollback;
|
|
417
|
+
console.log(`Current rollback: ${current.rollbackId}`);
|
|
418
|
+
console.log(`Status: ${current.status}`);
|
|
419
|
+
console.log(`Files affected: ${current.metadata.affectedFiles}`);
|
|
420
|
+
console.log(`Files restored: ${current.metadata.totalFilesRestored}`);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
console.log(`Total rollback points: ${status.rollbackHistory.length}`);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Register command with CLI
|
|
429
|
+
*/
|
|
430
|
+
function registerCommand(program) {
|
|
431
|
+
const command = new RefactorFileCommand();
|
|
432
|
+
|
|
433
|
+
// Add subcommands
|
|
434
|
+
const rollbackCmd = new Command('rollback')
|
|
435
|
+
.description('Rollback a refactoring operation')
|
|
436
|
+
.argument('<id>', 'Rollback operation ID')
|
|
437
|
+
.option('-f, --force', 'Force rollback without confirmation', false)
|
|
438
|
+
.action(async (id, options) => {
|
|
439
|
+
try {
|
|
440
|
+
const cmd = new RefactorFileCommand();
|
|
441
|
+
await cmd.handleRollback(id, options);
|
|
442
|
+
} catch (error) {
|
|
443
|
+
console.error(chalk.red('Error:'), error.message);
|
|
444
|
+
process.exit(1);
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
const listCmd = new Command('list')
|
|
449
|
+
.description('List available rollback points')
|
|
450
|
+
.action(async () => {
|
|
451
|
+
try {
|
|
452
|
+
const cmd = new RefactorFileCommand();
|
|
453
|
+
await cmd.listRollbackPoints();
|
|
454
|
+
} catch (error) {
|
|
455
|
+
console.error(chalk.red('Error:'), error.message);
|
|
456
|
+
process.exit(1);
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
const statusCmd = new Command('status')
|
|
461
|
+
.description('Show rollback status')
|
|
462
|
+
.action(async () => {
|
|
463
|
+
try {
|
|
464
|
+
const cmd = new RefactorFileCommand();
|
|
465
|
+
cmd.showRollbackStatus();
|
|
466
|
+
} catch (error) {
|
|
467
|
+
console.error(chalk.red('Error:'), error.message);
|
|
468
|
+
process.exit(1);
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
command.addCommand(rollbackCmd);
|
|
473
|
+
command.addCommand(listCmd);
|
|
474
|
+
command.addCommand(statusCmd);
|
|
475
|
+
|
|
476
|
+
program.addCommand(command.command);
|
|
477
|
+
return command;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Export for direct use
|
|
482
|
+
*/
|
|
483
|
+
module.exports = {
|
|
484
|
+
RefactorFileCommand,
|
|
485
|
+
registerCommand
|
|
486
|
+
};
|