vibecodingmachine-core 2026.2.26-1739 → 2026.3.9-850
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/package.json +1 -1
- package/src/agents/AgentCheckDiscoveryService.js +180 -0
- package/src/agents/AgentCheckService.js +18 -261
- package/src/agents/AgentCheckStatisticsService.js +195 -0
- package/src/agents/EnvironmentConfigurationManager.js +31 -380
- package/src/agents/InstallationType.js +19 -6
- package/src/agents/SimpleAgentCheckService.js +472 -0
- package/src/agents/config-managers/ConfigUtils.js +72 -0
- package/src/agents/config-managers/DefaultConfig.js +58 -0
- package/src/agents/config-managers/EnvVarLoader.js +66 -0
- package/src/agents/config-managers/FileConfigLoader.js +124 -0
- package/src/agents/config-managers/TypeConverters.js +61 -0
- package/src/agents/config-managers/VariableMappings.js +92 -0
- package/src/agents/discovery/AgentDiscoveryService-refactored.js +272 -0
- package/src/agents/discovery/AgentDiscoveryService.js +29 -403
- package/src/agents/discovery/agent-validator.js +262 -0
- package/src/agents/discovery/discovery-results.js +176 -0
- package/src/agents/discovery/discovery-scanner.js +268 -0
- package/src/agents/discovery/discovery-utils.js +161 -0
- package/src/agents/discovery/executable-analyzer.js +290 -0
- package/src/agents/discovery/history-manager.js +310 -0
- package/src/agents/verification/ResultAnalyzer-refactored.js +341 -0
- package/src/agents/verification/ResultAnalyzer.js +30 -431
- package/src/agents/verification/analysis-utils.js +310 -0
- package/src/agents/verification/batch-analyzer.js +440 -0
- package/src/agents/verification/pattern-recognizer.js +369 -0
- package/src/agents/verification/report-generator.js +320 -0
- package/src/agents/verification/test-analyzer.js +290 -0
- package/src/agents/windows/InstallerFactory.js +4 -0
- package/src/agents/windows/VSCodeExtensionInstaller.js +404 -0
- package/src/analysis/analysis-engine.js +314 -0
- package/src/analysis/ast-analyzer.js +342 -0
- package/src/analysis/boundary-detector-refactored.js +378 -0
- package/src/analysis/boundary-detector.js +200 -603
- package/src/analysis/boundary-scanner.js +609 -0
- package/src/analysis/boundary-types.js +118 -0
- package/src/analysis/boundary-utils.js +293 -0
- package/src/analysis/deadline-priority-calculator.js +18 -0
- package/src/analysis/detection-methods.js +347 -0
- package/src/analysis/importance-priority-calculator.js +18 -0
- package/src/analysis/priority/factor-calculators.js +204 -0
- package/src/analysis/priority/factor-helpers.js +71 -0
- package/src/analysis/priority/priority-constants.js +73 -0
- package/src/analysis/priority/priority-factor-calculators.js +301 -0
- package/src/analysis/priority/reasons-generator.js +44 -0
- package/src/analysis/priority-calculator.js +15 -580
- package/src/analysis/strategy-generator.js +16 -66
- package/src/analysis/type-priority-calculator.js +18 -0
- package/src/analysis/urgency-priority-calculator.js +18 -0
- package/src/auto-mode/AutoModeBusinessLogic.js +2 -40
- package/src/commands/disable-requirement.js +60 -0
- package/src/commands/disable-spec.js +60 -0
- package/src/commands/enable-requirement.js +60 -0
- package/src/commands/enable-spec.js +60 -0
- package/src/commands/registry.js +1 -6
- package/src/commands/requirements.js +8 -2
- package/src/ide-integration/applescript-manager.cjs +9 -24
- package/src/ide-integration/cdp-handlers/chat-reader.js +44 -0
- package/src/ide-integration/cdp-handlers/connection-handler.js +88 -0
- package/src/ide-integration/cdp-handlers/continuation-handler.js +314 -0
- package/src/ide-integration/cdp-handlers/message-submitter.js +75 -0
- package/src/ide-integration/cdp-handlers/text-sender.js +138 -0
- package/src/ide-integration/cdp-manager.js +28 -573
- package/src/ide-integration/claude-code-cli-manager.cjs +48 -12
- package/src/ide-integration/ide-openers/claude-opener.js +171 -0
- package/src/ide-integration/ide-openers/cursor-opener.js +53 -0
- package/src/ide-integration/ide-openers/other-ides-opener.js +230 -0
- package/src/ide-integration/ide-openers/vscode-opener.js +147 -0
- package/src/ide-integration/macos-ide-manager.js +20 -582
- package/src/ide-integration/macos-quota-checker.js +164 -0
- package/src/ide-integration/macos-text-sender.js +19 -38
- package/src/ide-integration/provider-manager.cjs +52 -7
- package/src/index.cjs +6 -0
- package/src/index.js +10 -0
- package/src/llm/direct-llm-manager.cjs +501 -0
- package/src/localization/translations/en-part1.js +363 -0
- package/src/localization/translations/en-part2.js +320 -0
- package/src/localization/translations/en.js +4 -687
- package/src/localization/translations/es-part1.js +363 -0
- package/src/localization/translations/es-part2.js +320 -0
- package/src/localization/translations/es.js +4 -688
- package/src/models/file-analysis-collection.js +139 -0
- package/src/models/file-analysis-metrics.js +50 -0
- package/src/models/file-analysis.js +15 -262
- package/src/models/plan-manager.js +410 -0
- package/src/models/refactoring-models.js +380 -0
- package/src/models/refactoring-plan-refactored.js +81 -0
- package/src/models/refactoring-plan.js +2 -663
- package/src/monitoring/alert-system.js +4 -45
- package/src/monitoring/continuous-scan-notifications.js +37 -191
- package/src/monitoring/notification-handlers/base-handler.js +58 -0
- package/src/monitoring/notification-handlers/error-handler.js +36 -0
- package/src/monitoring/notification-handlers/index.js +21 -0
- package/src/monitoring/notification-handlers/new-violation-handler.js +91 -0
- package/src/monitoring/notification-handlers/progress-handler.js +48 -0
- package/src/monitoring/notification-handlers/resolved-violation-handler.js +54 -0
- package/src/monitoring/notification-handlers/threshold-handler.js +36 -0
- package/src/provider-registry.js +8 -0
- package/src/refactoring/boundary/boundary-detector-refactored.js +58 -0
- package/src/refactoring/boundary/boundary-detector.js +26 -596
- package/src/refactoring/boundary/detectors/boundary-analyzers.js +281 -0
- package/src/refactoring/boundary/detectors/boundary-core.js +167 -0
- package/src/refactoring/boundary/detectors/class-detector.js +247 -0
- package/src/refactoring/boundary/detectors/config-detector.js +270 -0
- package/src/refactoring/boundary/detectors/constant-detector.js +269 -0
- package/src/refactoring/boundary/detectors/function-detector.js +248 -0
- package/src/refactoring/boundary/detectors/module-detector.js +249 -0
- package/src/refactoring/boundary/detectors/object-detector.js +247 -0
- package/src/refactoring/boundary/detectors/type-detectors.js +338 -0
- package/src/refactoring/boundary/detectors/utility-detector.js +270 -0
- package/src/refactoring/circular-dependency-resolver-original.js +16 -76
- package/src/refactoring/code-mover-refactored.js +309 -0
- package/src/refactoring/code-mover.js +48 -355
- package/src/refactoring/execution-status.js +18 -0
- package/src/refactoring/execution-strategies.js +172 -0
- package/src/refactoring/file-splitter-core.js +568 -0
- package/src/refactoring/file-splitter-types.js +136 -0
- package/src/refactoring/file-splitter.js +2 -682
- package/src/refactoring/functionality-validator.js +11 -51
- package/src/refactoring/import-manager-refactored.js +385 -0
- package/src/refactoring/import-manager.js +112 -487
- package/src/refactoring/import-models.js +189 -0
- package/src/refactoring/import-parser.js +306 -0
- package/src/refactoring/move-executor.js +431 -0
- package/src/refactoring/move-utils.js +368 -0
- package/src/refactoring/operation-executor.js +76 -0
- package/src/refactoring/plan-creator.js +36 -0
- package/src/refactoring/plan-executor.js +143 -0
- package/src/refactoring/plan-validator.js +68 -0
- package/src/refactoring/refactoring-executor-result.js +70 -0
- package/src/refactoring/refactoring-executor.js +34 -569
- package/src/refactoring/refactoring-operation.js +94 -0
- package/src/refactoring/refactoring-plan.js +69 -0
- package/src/refactoring/refactoring-rollback.js +22 -527
- package/src/refactoring/rollback-handlers/RollbackExecutor.js +107 -0
- package/src/refactoring/rollback-handlers/RollbackManager.js +265 -0
- package/src/refactoring/rollback-handlers/RollbackOperation.js +105 -0
- package/src/refactoring/rollback-handlers/RollbackResult.js +109 -0
- package/src/refactoring/rollback-handlers/RollbackStatistics.js +77 -0
- package/src/refactoring/test-validator.js +32 -448
- package/src/refactoring/validation/baseline-runner.js +71 -0
- package/src/refactoring/validation/report-generator.js +136 -0
- package/src/refactoring/validation/result-comparator.js +92 -0
- package/src/refactoring/validation/test-suite.js +59 -0
- package/src/refactoring/validation/test-validation-result.js +83 -0
- package/src/refactoring/validation/validation-runner.js +95 -0
- package/src/refactoring/validation/validation-status.js +18 -0
- package/src/rui/commands/AgentCommandParser.js +60 -369
- package/src/rui/commands/AgentResponseFormatter.js +7 -47
- package/src/rui/commands/parsers/CommandMapper.js +148 -0
- package/src/rui/commands/parsers/CommandValidator.js +228 -0
- package/src/rui/commands/parsers/ComponentExtractor.js +100 -0
- package/src/rui/commands/parsers/TokenParser.js +69 -0
- package/src/rui/commands/parsers/tokenizer.js +153 -0
- package/src/utils/current-requirement-operations.js +50 -1
- package/src/utils/report-generator.js +18 -514
- package/src/utils/report-generators/analysis-generator.js +115 -0
- package/src/utils/report-generators/base-generator.js +141 -0
- package/src/utils/report-generators/compliance-generator.js +41 -0
- package/src/utils/report-generators/format-handlers.js +185 -0
- package/src/utils/report-generators/refactoring-generator.js +46 -0
- package/src/utils/report-generators/validation-generator.js +63 -0
- package/src/utils/requirement-enable-disable.js +265 -0
- package/src/utils/requirement-helpers/requirement-file-ops.js +69 -1
- package/src/utils/requirement-helpers/requirement-mover.js +88 -1
- package/src/utils/requirement-helpers.js +5 -2
- package/src/utils/smoke-test-cli.js +45 -8
- package/src/utils/specification-enable-disable.js +122 -0
- package/src/utils/specification-helpers.js +30 -4
- package/src/utils/specification-migration.js +5 -5
- package/src/utils/test-comparator.js +118 -0
- package/src/utils/test-config.js +54 -0
- package/src/utils/test-executor.js +133 -0
- package/src/utils/test-parser.js +215 -0
- package/src/utils/test-runner-baseline.js +63 -0
- package/src/utils/test-runner-core.js +98 -0
- package/src/utils/test-runner-report.js +39 -0
- package/src/utils/test-runner-validation.js +71 -0
- package/src/utils/test-runner.js +11 -535
- package/src/validation/comparison-analyzer.js +333 -0
- package/src/validation/compliance-reporter-new.js +282 -0
- package/src/validation/compliance-reporter-refactored.js +344 -0
- package/src/validation/compliance-reporter.js +278 -591
- package/src/validation/compliance-utils.js +278 -0
- package/src/validation/html-generator.js +446 -0
- package/src/validation/metrics/category-calculator.js +137 -0
- package/src/validation/metrics/metrics-helpers.js +155 -0
- package/src/validation/metrics/overview-calculator.js +85 -0
- package/src/validation/metrics/overview-metrics.js +41 -0
- package/src/validation/metrics/quality-calculator.js +166 -0
- package/src/validation/metrics/size-calculator.js +69 -0
- package/src/validation/metrics-calculator.js +27 -551
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rollback Executor
|
|
3
|
+
*
|
|
4
|
+
* Handles execution of rollback operations.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const { ROLLBACK_STATUS } = require('./RollbackOperation');
|
|
10
|
+
|
|
11
|
+
class RollbackExecutor {
|
|
12
|
+
constructor(options = {}) {
|
|
13
|
+
this.options = {
|
|
14
|
+
validateAfterRollback: true,
|
|
15
|
+
...options
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Execute individual rollback operation
|
|
21
|
+
*/
|
|
22
|
+
async executeRollbackOperation(rollbackOp) {
|
|
23
|
+
console.log(`Executing rollback operation: ${rollbackOp.id}`);
|
|
24
|
+
rollbackOp.setStatus(ROLLBACK_STATUS.RUNNING);
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
if (!rollbackOp.metadata.backupPath || !fs.existsSync(rollbackOp.metadata.backupPath)) {
|
|
28
|
+
throw new Error(`Backup file not found: ${rollbackOp.metadata.backupPath}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Restore file from backup
|
|
32
|
+
const targetDir = path.dirname(rollbackOp.targetPath);
|
|
33
|
+
if (!fs.existsSync(targetDir)) {
|
|
34
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
fs.copyFileSync(rollbackOp.metadata.backupPath, rollbackOp.targetPath);
|
|
38
|
+
|
|
39
|
+
// Verify restoration
|
|
40
|
+
if (fs.existsSync(rollbackOp.targetPath)) {
|
|
41
|
+
const restoredSize = fs.statSync(rollbackOp.targetPath).size;
|
|
42
|
+
rollbackOp.setRestoredSize(restoredSize);
|
|
43
|
+
|
|
44
|
+
// Check if size matches (basic integrity check)
|
|
45
|
+
if (Math.abs(restoredSize - rollbackOp.metadata.originalSize) > 100) {
|
|
46
|
+
rollbackOp.addWarning('File size difference detected after restoration');
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
throw new Error('Failed to restore file');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
rollbackOp.setStatus(ROLLBACK_STATUS.COMPLETED);
|
|
53
|
+
rollbackOp.setSuccess(true);
|
|
54
|
+
|
|
55
|
+
console.log(`Rollback operation completed: ${rollbackOp.id}`);
|
|
56
|
+
|
|
57
|
+
} catch (error) {
|
|
58
|
+
rollbackOp.addError(error);
|
|
59
|
+
rollbackOp.setStatus(ROLLBACK_STATUS.FAILED);
|
|
60
|
+
rollbackOp.setSuccess(false);
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Validate rollback results
|
|
67
|
+
*/
|
|
68
|
+
async validateRollback(result) {
|
|
69
|
+
console.log('Validating rollback results...');
|
|
70
|
+
|
|
71
|
+
for (const operation of result.operations) {
|
|
72
|
+
if (operation.success) {
|
|
73
|
+
try {
|
|
74
|
+
// Basic file existence check
|
|
75
|
+
if (!fs.existsSync(operation.targetPath)) {
|
|
76
|
+
operation.addWarning('Target file does not exist after rollback');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Basic syntax check for JavaScript files
|
|
80
|
+
if (operation.targetPath.endsWith('.js') && fs.existsSync(operation.targetPath)) {
|
|
81
|
+
const content = fs.readFileSync(operation.targetPath, 'utf8');
|
|
82
|
+
this.validateJavaScriptSyntax(content);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
} catch (error) {
|
|
86
|
+
operation.addError(error);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Validate JavaScript syntax
|
|
94
|
+
*/
|
|
95
|
+
validateJavaScriptSyntax(content) {
|
|
96
|
+
try {
|
|
97
|
+
const vm = require('vm');
|
|
98
|
+
new vm.Script(content, { filename: 'validation' });
|
|
99
|
+
} catch (error) {
|
|
100
|
+
throw new Error(`JavaScript syntax validation failed: ${error.message}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = {
|
|
106
|
+
RollbackExecutor
|
|
107
|
+
};
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rollback Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages rollback points, history, and cleanup operations.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const { RollbackManager: BaseRollbackManager } = require('../../utils/rollback-manager');
|
|
9
|
+
const { RollbackOperation, ROLLBACK_STATUS } = require('./RollbackOperation');
|
|
10
|
+
const { RollbackResult } = require('./RollbackResult');
|
|
11
|
+
const { RollbackExecutor } = require('./RollbackExecutor');
|
|
12
|
+
|
|
13
|
+
class RollbackManager {
|
|
14
|
+
constructor(options = {}) {
|
|
15
|
+
this.options = {
|
|
16
|
+
createBackups: true,
|
|
17
|
+
validateAfterRollback: true,
|
|
18
|
+
preserveRollbackLogs: true,
|
|
19
|
+
maxRollbackAttempts: 3,
|
|
20
|
+
...options
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
this.rollbackManager = new BaseRollbackManager();
|
|
24
|
+
this.rollbackHistory = new Map();
|
|
25
|
+
this.currentRollback = null;
|
|
26
|
+
this.isRollingBack = false;
|
|
27
|
+
this.executor = new RollbackExecutor(options);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Create rollback point for a refactoring operation
|
|
32
|
+
*/
|
|
33
|
+
async createRollbackPoint(operationId, operation) {
|
|
34
|
+
console.log(`Creating rollback point for operation: ${operationId}`);
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const rollbackOp = new RollbackOperation(operationId, 'create_backup', operation.targetPath);
|
|
38
|
+
|
|
39
|
+
// Create backup for each affected file
|
|
40
|
+
for (const affectedFile of operation.affectedFiles || [operation.targetPath]) {
|
|
41
|
+
if (fs.existsSync(affectedFile)) {
|
|
42
|
+
const backupPath = this.rollbackManager.backupFile(affectedFile);
|
|
43
|
+
rollbackOp.setBackupPath(backupPath);
|
|
44
|
+
rollbackOp.setOriginalSize(fs.statSync(affectedFile).size);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
rollbackOp.setStatus(ROLLBACK_STATUS.COMPLETED);
|
|
49
|
+
rollbackOp.setSuccess(true);
|
|
50
|
+
|
|
51
|
+
// Store rollback operation
|
|
52
|
+
if (!this.rollbackHistory.has(operationId)) {
|
|
53
|
+
this.rollbackHistory.set(operationId, []);
|
|
54
|
+
}
|
|
55
|
+
this.rollbackHistory.get(operationId).push(rollbackOp);
|
|
56
|
+
|
|
57
|
+
console.log(`Rollback point created for ${operationId}`);
|
|
58
|
+
|
|
59
|
+
return rollbackOp;
|
|
60
|
+
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error(`Failed to create rollback point for ${operationId}:`, error.message);
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Execute rollback for a failed operation
|
|
69
|
+
*/
|
|
70
|
+
async executeRollback(operationId, reason = 'Operation failed') {
|
|
71
|
+
if (this.isRollingBack) {
|
|
72
|
+
throw new Error('Rollback already in progress');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
this.isRollingBack = true;
|
|
76
|
+
const rollbackId = this.generateRollbackId();
|
|
77
|
+
const result = new RollbackResult(rollbackId);
|
|
78
|
+
result.setTriggerReason(reason);
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
console.log(`Executing rollback for operation: ${operationId}`);
|
|
82
|
+
result.setStatus(ROLLBACK_STATUS.RUNNING);
|
|
83
|
+
|
|
84
|
+
// Get rollback operations for the operation
|
|
85
|
+
const rollbackOps = this.rollbackHistory.get(operationId) || [];
|
|
86
|
+
|
|
87
|
+
if (rollbackOps.length === 0) {
|
|
88
|
+
throw new Error(`No rollback point found for operation: ${operationId}`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Execute rollback operations in reverse order
|
|
92
|
+
const reversedOps = rollbackOps.reverse();
|
|
93
|
+
|
|
94
|
+
for (const rollbackOp of reversedOps) {
|
|
95
|
+
try {
|
|
96
|
+
await this.executor.executeRollbackOperation(rollbackOp);
|
|
97
|
+
result.addOperation(rollbackOp);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
rollbackOp.addError(error);
|
|
100
|
+
rollbackOp.setStatus(ROLLBACK_STATUS.FAILED);
|
|
101
|
+
rollbackOp.setSuccess(false);
|
|
102
|
+
result.addOperation(rollbackOp);
|
|
103
|
+
|
|
104
|
+
// Continue with other operations even if one fails
|
|
105
|
+
console.warn(`Rollback operation failed: ${rollbackOp.id}`, error.message);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Validate rollback if enabled
|
|
110
|
+
if (this.options.validateAfterRollback) {
|
|
111
|
+
await this.executor.validateRollback(result);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
result.calculateSummary();
|
|
115
|
+
|
|
116
|
+
console.log(`Rollback completed: ${result.success ? 'SUCCESS' : 'PARTIAL/FAILED'}`);
|
|
117
|
+
|
|
118
|
+
} catch (error) {
|
|
119
|
+
result.addError(error);
|
|
120
|
+
result.setStatus(ROLLBACK_STATUS.FAILED);
|
|
121
|
+
result.setSuccess(false);
|
|
122
|
+
console.error(`Rollback execution failed:`, error.message);
|
|
123
|
+
} finally {
|
|
124
|
+
this.isRollingBack = false;
|
|
125
|
+
this.currentRollback = result;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Cancel current rollback
|
|
133
|
+
*/
|
|
134
|
+
async cancelRollback() {
|
|
135
|
+
if (!this.isRollingBack || !this.currentRollback) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
this.currentRollback.setStatus(ROLLBACK_STATUS.FAILED);
|
|
140
|
+
this.currentRollback.addError(new Error('Rollback cancelled by user'));
|
|
141
|
+
this.isRollingBack = false;
|
|
142
|
+
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Get rollback status
|
|
148
|
+
*/
|
|
149
|
+
getRollbackStatus() {
|
|
150
|
+
return {
|
|
151
|
+
isRollingBack: this.isRollingBack,
|
|
152
|
+
currentRollback: this.currentRollback ? this.currentRollback.getSummary() : null,
|
|
153
|
+
rollbackHistory: Array.from(this.rollbackHistory.entries()).map(([opId, ops]) => ({
|
|
154
|
+
operationId: opId,
|
|
155
|
+
rollbackOperations: ops.length,
|
|
156
|
+
lastRollback: ops[ops.length - 1]?.getSummary()
|
|
157
|
+
}))
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Clean up old rollback points
|
|
163
|
+
*/
|
|
164
|
+
async cleanup(maxAge = 7 * 24 * 60 * 60 * 1000) { // 7 days default
|
|
165
|
+
console.log('Cleaning up old rollback points...');
|
|
166
|
+
|
|
167
|
+
let cleaned = 0;
|
|
168
|
+
const now = Date.now();
|
|
169
|
+
|
|
170
|
+
for (const [operationId, rollbackOps] of this.rollbackHistory.entries()) {
|
|
171
|
+
const recentOps = rollbackOps.filter(op => {
|
|
172
|
+
const createdAt = new Date(op.metadata.createdAt).getTime();
|
|
173
|
+
return (now - createdAt) < maxAge;
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
if (recentOps.length < rollbackOps.length) {
|
|
177
|
+
this.rollbackHistory.set(operationId, recentOps);
|
|
178
|
+
cleaned += rollbackOps.length - recentOps.length;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Clean up rollback manager backups
|
|
183
|
+
const backupCleaned = this.rollbackManager.cleanup(maxAge);
|
|
184
|
+
|
|
185
|
+
console.log(`Cleanup completed: ${cleaned} rollback operations, ${backupCleaned} backup files`);
|
|
186
|
+
|
|
187
|
+
return { rollbackOperations: cleaned, backupFiles: backupCleaned };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Check if rollback is available for an operation
|
|
192
|
+
*/
|
|
193
|
+
hasRollbackPoint(operationId) {
|
|
194
|
+
const rollbackOps = this.rollbackHistory.get(operationId);
|
|
195
|
+
return rollbackOps && rollbackOps.length > 0;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Get rollback operations for an operation
|
|
200
|
+
*/
|
|
201
|
+
getRollbackOperations(operationId) {
|
|
202
|
+
return this.rollbackHistory.get(operationId) || [];
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Remove rollback point for an operation
|
|
207
|
+
*/
|
|
208
|
+
removeRollbackPoint(operationId) {
|
|
209
|
+
const rollbackOps = this.rollbackHistory.get(operationId);
|
|
210
|
+
if (rollbackOps) {
|
|
211
|
+
// Clean up backup files
|
|
212
|
+
for (const op of rollbackOps) {
|
|
213
|
+
if (op.metadata.backupPath && fs.existsSync(op.metadata.backupPath)) {
|
|
214
|
+
try {
|
|
215
|
+
fs.unlinkSync(op.metadata.backupPath);
|
|
216
|
+
} catch (error) {
|
|
217
|
+
console.warn(`Failed to cleanup backup file: ${op.metadata.backupPath}`, error.message);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
this.rollbackHistory.delete(operationId);
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Reset all rollback data
|
|
231
|
+
*/
|
|
232
|
+
reset() {
|
|
233
|
+
console.log('Resetting all rollback data...');
|
|
234
|
+
|
|
235
|
+
// Clean up all backup files
|
|
236
|
+
for (const rollbackOps of this.rollbackHistory.values()) {
|
|
237
|
+
for (const op of rollbackOps) {
|
|
238
|
+
if (op.metadata.backupPath && fs.existsSync(op.metadata.backupPath)) {
|
|
239
|
+
try {
|
|
240
|
+
fs.unlinkSync(op.metadata.backupPath);
|
|
241
|
+
} catch (error) {
|
|
242
|
+
console.warn(`Failed to cleanup backup file: ${op.metadata.backupPath}`, error.message);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
this.rollbackHistory.clear();
|
|
249
|
+
this.currentRollback = null;
|
|
250
|
+
this.isRollingBack = false;
|
|
251
|
+
|
|
252
|
+
console.log('Rollback data reset completed');
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Generate rollback ID
|
|
257
|
+
*/
|
|
258
|
+
generateRollbackId() {
|
|
259
|
+
return `rollback_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
module.exports = {
|
|
264
|
+
RollbackManager
|
|
265
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rollback Operation Handler
|
|
3
|
+
*
|
|
4
|
+
* Manages individual rollback operation tracking and execution.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const ROLLBACK_STATUS = {
|
|
8
|
+
PENDING: 'pending',
|
|
9
|
+
RUNNING: 'running',
|
|
10
|
+
COMPLETED: 'completed',
|
|
11
|
+
FAILED: 'failed',
|
|
12
|
+
PARTIAL: 'partial'
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Rollback operation class
|
|
17
|
+
*/
|
|
18
|
+
class RollbackOperation {
|
|
19
|
+
constructor(operationId, type, targetPath) {
|
|
20
|
+
this.id = this.generateId();
|
|
21
|
+
this.operationId = operationId;
|
|
22
|
+
this.type = type;
|
|
23
|
+
this.targetPath = targetPath;
|
|
24
|
+
this.status = ROLLBACK_STATUS.PENDING;
|
|
25
|
+
this.startTime = null;
|
|
26
|
+
this.endTime = null;
|
|
27
|
+
this.duration = 0;
|
|
28
|
+
this.success = false;
|
|
29
|
+
this.errors = [];
|
|
30
|
+
this.warnings = [];
|
|
31
|
+
this.metadata = {
|
|
32
|
+
createdAt: new Date().toISOString(),
|
|
33
|
+
backupPath: null,
|
|
34
|
+
originalSize: 0,
|
|
35
|
+
restoredSize: 0
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
generateId() {
|
|
40
|
+
return `rollback_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
setStatus(status) {
|
|
44
|
+
this.status = status;
|
|
45
|
+
if (status === ROLLBACK_STATUS.RUNNING && !this.startTime) {
|
|
46
|
+
this.startTime = new Date().toISOString();
|
|
47
|
+
}
|
|
48
|
+
if ([ROLLBACK_STATUS.COMPLETED, ROLLBACK_STATUS.FAILED, ROLLBACK_STATUS.PARTIAL].includes(status)) {
|
|
49
|
+
this.endTime = new Date().toISOString();
|
|
50
|
+
this.duration = this.endTime && this.startTime ?
|
|
51
|
+
(new Date(this.endTime) - new Date(this.startTime)) / 1000 : 0;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
setSuccess(success) {
|
|
56
|
+
this.success = success;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
addError(error) {
|
|
60
|
+
this.errors.push({
|
|
61
|
+
message: error.message,
|
|
62
|
+
timestamp: new Date().toISOString(),
|
|
63
|
+
stack: error.stack
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
addWarning(warning) {
|
|
68
|
+
this.warnings.push({
|
|
69
|
+
message: warning,
|
|
70
|
+
timestamp: new Date().toISOString()
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
setBackupPath(backupPath) {
|
|
75
|
+
this.metadata.backupPath = backupPath;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
setOriginalSize(size) {
|
|
79
|
+
this.metadata.originalSize = size;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
setRestoredSize(size) {
|
|
83
|
+
this.metadata.restoredSize = size;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
getSummary() {
|
|
87
|
+
return {
|
|
88
|
+
id: this.id,
|
|
89
|
+
operationId: this.operationId,
|
|
90
|
+
type: this.type,
|
|
91
|
+
targetPath: this.targetPath,
|
|
92
|
+
status: this.status,
|
|
93
|
+
success: this.success,
|
|
94
|
+
duration: this.duration,
|
|
95
|
+
errorCount: this.errors.length,
|
|
96
|
+
warningCount: this.warnings.length,
|
|
97
|
+
backupPath: this.metadata.backupPath
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
module.exports = {
|
|
103
|
+
RollbackOperation,
|
|
104
|
+
ROLLBACK_STATUS
|
|
105
|
+
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rollback Result Handler
|
|
3
|
+
*
|
|
4
|
+
* Manages rollback results and aggregation.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { ROLLBACK_STATUS } = require('./RollbackOperation');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Rollback result class
|
|
11
|
+
*/
|
|
12
|
+
class RollbackResult {
|
|
13
|
+
constructor(rollbackId) {
|
|
14
|
+
this.rollbackId = rollbackId;
|
|
15
|
+
this.operations = [];
|
|
16
|
+
this.status = ROLLBACK_STATUS.PENDING;
|
|
17
|
+
this.success = false;
|
|
18
|
+
this.startTime = null;
|
|
19
|
+
this.endTime = null;
|
|
20
|
+
this.duration = 0;
|
|
21
|
+
this.errors = [];
|
|
22
|
+
this.warnings = [];
|
|
23
|
+
this.metadata = {
|
|
24
|
+
createdAt: new Date().toISOString(),
|
|
25
|
+
triggerReason: '',
|
|
26
|
+
affectedFiles: 0,
|
|
27
|
+
totalFilesRestored: 0
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
addOperation(operation) {
|
|
32
|
+
this.operations.push(operation);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
setStatus(status) {
|
|
36
|
+
this.status = status;
|
|
37
|
+
if (status === ROLLBACK_STATUS.RUNNING && !this.startTime) {
|
|
38
|
+
this.startTime = new Date().toISOString();
|
|
39
|
+
}
|
|
40
|
+
if ([ROLLBACK_STATUS.COMPLETED, ROLLBACK_STATUS.FAILED, ROLLBACK_STATUS.PARTIAL].includes(status)) {
|
|
41
|
+
this.endTime = new Date().toISOString();
|
|
42
|
+
this.duration = this.endTime && this.startTime ?
|
|
43
|
+
(new Date(this.endTime) - new Date(this.startTime)) / 1000 : 0;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
setSuccess(success) {
|
|
48
|
+
this.success = success;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
setTriggerReason(reason) {
|
|
52
|
+
this.metadata.triggerReason = reason;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
addError(error) {
|
|
56
|
+
this.errors.push({
|
|
57
|
+
message: error.message,
|
|
58
|
+
timestamp: new Date().toISOString(),
|
|
59
|
+
stack: error.stack
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
addWarning(warning) {
|
|
64
|
+
this.warnings.push({
|
|
65
|
+
message: warning,
|
|
66
|
+
timestamp: new Date().toISOString()
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
calculateSummary() {
|
|
71
|
+
const successfulOps = this.operations.filter(op => op.success).length;
|
|
72
|
+
const failedOps = this.operations.filter(op => !op.success).length;
|
|
73
|
+
|
|
74
|
+
if (failedOps === 0) {
|
|
75
|
+
this.setStatus(ROLLBACK_STATUS.COMPLETED);
|
|
76
|
+
this.setSuccess(true);
|
|
77
|
+
} else if (successfulOps > 0) {
|
|
78
|
+
this.setStatus(ROLLBACK_STATUS.PARTIAL);
|
|
79
|
+
this.setSuccess(false);
|
|
80
|
+
} else {
|
|
81
|
+
this.setStatus(ROLLBACK_STATUS.FAILED);
|
|
82
|
+
this.setSuccess(false);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
this.metadata.affectedFiles = this.operations.length;
|
|
86
|
+
this.metadata.totalFilesRestored = successfulOps;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
getSummary() {
|
|
90
|
+
this.calculateSummary();
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
rollbackId: this.rollbackId,
|
|
94
|
+
status: this.status,
|
|
95
|
+
success: this.success,
|
|
96
|
+
duration: this.duration,
|
|
97
|
+
triggerReason: this.metadata.triggerReason,
|
|
98
|
+
affectedFiles: this.metadata.affectedFiles,
|
|
99
|
+
totalFilesRestored: this.metadata.totalFilesRestored,
|
|
100
|
+
operations: this.operations.map(op => op.getSummary()),
|
|
101
|
+
errorCount: this.errors.length,
|
|
102
|
+
warningCount: this.warnings.length
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
module.exports = {
|
|
108
|
+
RollbackResult
|
|
109
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rollback Statistics Handler
|
|
3
|
+
*
|
|
4
|
+
* Manages statistics and data export for rollback operations.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
class RollbackStatistics {
|
|
8
|
+
constructor(rollbackHistory) {
|
|
9
|
+
this.rollbackHistory = rollbackHistory;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get rollback statistics
|
|
14
|
+
*/
|
|
15
|
+
getStatistics() {
|
|
16
|
+
const stats = {
|
|
17
|
+
totalRollbackPoints: 0,
|
|
18
|
+
totalRollbacks: 0,
|
|
19
|
+
successfulRollbacks: 0,
|
|
20
|
+
failedRollbacks: 0,
|
|
21
|
+
partialRollbacks: 0,
|
|
22
|
+
averageRollbackTime: 0,
|
|
23
|
+
commonFailureReasons: {},
|
|
24
|
+
oldestRollback: null,
|
|
25
|
+
newestRollback: null
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
let oldestTime = null;
|
|
29
|
+
let newestTime = null;
|
|
30
|
+
|
|
31
|
+
for (const rollbackOps of this.rollbackHistory.values()) {
|
|
32
|
+
stats.totalRollbackPoints += rollbackOps.length;
|
|
33
|
+
|
|
34
|
+
for (const op of rollbackOps) {
|
|
35
|
+
if (op.endTime) {
|
|
36
|
+
const opTime = new Date(op.endTime);
|
|
37
|
+
if (!oldestTime || opTime < oldestTime) oldestTime = opTime;
|
|
38
|
+
if (!newestTime || opTime > newestTime) newestTime = opTime;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
stats.oldestRollback = oldestTime ? oldestTime.toISOString() : null;
|
|
44
|
+
stats.newestRollback = newestTime ? newestTime.toISOString() : null;
|
|
45
|
+
|
|
46
|
+
return stats;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Export rollback data
|
|
51
|
+
*/
|
|
52
|
+
exportRollbackData(options, currentRollback, format = 'json') {
|
|
53
|
+
const exportData = {
|
|
54
|
+
metadata: {
|
|
55
|
+
exportedAt: new Date().toISOString(),
|
|
56
|
+
version: '1.0.0',
|
|
57
|
+
options: options
|
|
58
|
+
},
|
|
59
|
+
rollbackHistory: Array.from(this.rollbackHistory.entries()).map(([opId, ops]) => ({
|
|
60
|
+
operationId: opId,
|
|
61
|
+
operations: ops.map(op => op.getSummary())
|
|
62
|
+
})),
|
|
63
|
+
currentRollback: currentRollback ? currentRollback.getSummary() : null,
|
|
64
|
+
statistics: this.getStatistics()
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
if (format === 'json') {
|
|
68
|
+
return JSON.stringify(exportData, null, 2);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return exportData;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = {
|
|
76
|
+
RollbackStatistics
|
|
77
|
+
};
|