pm-orchestrator-enhancement
Version:
PM Orchestrator Enhancement - Multi-agent parallel execution system
158 lines • 6.14 kB
JavaScript
;
/**
* PM Orchestrator Enhancement - Rollback Strategy
*
* ロールバック戦略を実装します。バックアップの作成・復元・クリーンアップ機能を提供します。
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RollbackStrategy = void 0;
const fs_1 = require("fs");
const path_1 = __importDefault(require("path"));
/**
* RollbackStrategyクラス
*
* バックアップとロールバック機能を提供します。
*/
class RollbackStrategy {
/**
* コンストラクタ
*
* @param baseDir ベースディレクトリ(デフォルト: カレントディレクトリ)
*/
constructor(baseDir = process.cwd()) {
this.backupDir = path_1.default.join(baseDir, '.pm-orchestrator', 'backups');
}
/**
* バックアップを作成します
*
* @param sourceDir バックアップ元のディレクトリ
* @returns バックアップID
*/
async createBackup(sourceDir = process.cwd()) {
const backupId = `backup-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
const backupPath = path_1.default.join(this.backupDir, backupId);
// バックアップディレクトリを作成
await fs_1.promises.mkdir(backupPath, { recursive: true });
// ソースディレクトリの内容を再帰的にコピー
await this.copyDirectory(sourceDir, backupPath);
// バックアップメタデータを保存
const metadata = {
id: backupId,
sourceDir,
createdAt: new Date().toISOString()
};
await fs_1.promises.writeFile(path_1.default.join(backupPath, '.backup-metadata.json'), JSON.stringify(metadata, null, 2), 'utf-8');
return backupId;
}
/**
* バックアップから復元します
*
* @param backupId バックアップID
* @param targetDir 復元先ディレクトリ(省略時はバックアップ元に復元)
*/
async restoreFromBackup(backupId, targetDir) {
const backupPath = path_1.default.join(this.backupDir, backupId);
// バックアップが存在するか確認
try {
await fs_1.promises.access(backupPath);
}
catch {
throw new Error(`Backup not found: ${backupId}`);
}
// メタデータを読み込み
const metadataPath = path_1.default.join(backupPath, '.backup-metadata.json');
const metadataContent = await fs_1.promises.readFile(metadataPath, 'utf-8');
const metadata = JSON.parse(metadataContent);
// 復元先を決定
const destination = targetDir || metadata.sourceDir;
// 復元先ディレクトリをクリア(.pm-orchestratorは除く)
await this.clearDirectory(destination);
// バックアップから復元
await this.copyDirectory(backupPath, destination, ['.backup-metadata.json']);
}
/**
* バックアップをクリーンアップします
*
* @param backupId バックアップID
*/
async cleanupBackup(backupId) {
const backupPath = path_1.default.join(this.backupDir, backupId);
try {
await fs_1.promises.rm(backupPath, { recursive: true, force: true });
}
catch (error) {
// バックアップが存在しない場合は無視
}
}
/**
* 全てのバックアップIDを取得します
*
* @returns バックアップIDの配列
*/
async listBackups() {
try {
await fs_1.promises.access(this.backupDir);
const entries = await fs_1.promises.readdir(this.backupDir, { withFileTypes: true });
return entries
.filter(entry => entry.isDirectory())
.map(entry => entry.name);
}
catch {
return [];
}
}
/**
* ディレクトリを再帰的にコピーします(プライベートメソッド)
*
* @param source コピー元
* @param destination コピー先
* @param exclude 除外するファイル名の配列
*/
async copyDirectory(source, destination, exclude = []) {
await fs_1.promises.mkdir(destination, { recursive: true });
const entries = await fs_1.promises.readdir(source, { withFileTypes: true });
for (const entry of entries) {
// .pm-orchestrator、node_modules、.git は除外
if (entry.name === '.pm-orchestrator' ||
entry.name === 'node_modules' ||
entry.name === '.git' ||
exclude.includes(entry.name)) {
continue;
}
const sourcePath = path_1.default.join(source, entry.name);
const destPath = path_1.default.join(destination, entry.name);
if (entry.isDirectory()) {
await this.copyDirectory(sourcePath, destPath);
}
else {
await fs_1.promises.copyFile(sourcePath, destPath);
}
}
}
/**
* ディレクトリの内容をクリアします(プライベートメソッド)
*
* @param dir クリアするディレクトリ
*/
async clearDirectory(dir) {
const entries = await fs_1.promises.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
// .pm-orchestratorは削除しない
if (entry.name === '.pm-orchestrator') {
continue;
}
const entryPath = path_1.default.join(dir, entry.name);
if (entry.isDirectory()) {
await fs_1.promises.rm(entryPath, { recursive: true, force: true });
}
else {
await fs_1.promises.unlink(entryPath);
}
}
}
}
exports.RollbackStrategy = RollbackStrategy;
//# sourceMappingURL=rollback-strategy.js.map