ownkey 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +41 -3
  2. package/dist/commands/apply.d.ts.map +1 -1
  3. package/dist/commands/apply.js +63 -14
  4. package/dist/commands/apply.js.map +1 -1
  5. package/dist/commands/suggest.d.ts.map +1 -1
  6. package/dist/commands/suggest.js +6 -0
  7. package/dist/commands/suggest.js.map +1 -1
  8. package/dist/commands/undo.d.ts +3 -0
  9. package/dist/commands/undo.d.ts.map +1 -0
  10. package/dist/commands/undo.js +197 -0
  11. package/dist/commands/undo.js.map +1 -0
  12. package/dist/core/apply/engine.d.ts +36 -0
  13. package/dist/core/apply/engine.d.ts.map +1 -0
  14. package/dist/core/apply/engine.js +179 -0
  15. package/dist/core/apply/engine.js.map +1 -0
  16. package/dist/core/apply/index.d.ts +3 -0
  17. package/dist/core/apply/index.d.ts.map +1 -0
  18. package/dist/core/apply/index.js +3 -0
  19. package/dist/core/apply/index.js.map +1 -0
  20. package/dist/core/apply/interactive.d.ts +53 -0
  21. package/dist/core/apply/interactive.d.ts.map +1 -0
  22. package/dist/core/apply/interactive.js +188 -0
  23. package/dist/core/apply/interactive.js.map +1 -0
  24. package/dist/core/backup/index.d.ts +2 -0
  25. package/dist/core/backup/index.d.ts.map +1 -0
  26. package/dist/core/backup/index.js +2 -0
  27. package/dist/core/backup/index.js.map +1 -0
  28. package/dist/core/backup/manager.d.ts +49 -0
  29. package/dist/core/backup/manager.d.ts.map +1 -0
  30. package/dist/core/backup/manager.js +133 -0
  31. package/dist/core/backup/manager.js.map +1 -0
  32. package/dist/core/diff/applier.d.ts +22 -0
  33. package/dist/core/diff/applier.d.ts.map +1 -0
  34. package/dist/core/diff/applier.js +98 -0
  35. package/dist/core/diff/applier.js.map +1 -0
  36. package/dist/core/diff/index.d.ts +4 -0
  37. package/dist/core/diff/index.d.ts.map +1 -0
  38. package/dist/core/diff/index.js +4 -0
  39. package/dist/core/diff/index.js.map +1 -0
  40. package/dist/core/diff/parser.d.ts +32 -0
  41. package/dist/core/diff/parser.d.ts.map +1 -0
  42. package/dist/core/diff/parser.js +108 -0
  43. package/dist/core/diff/parser.js.map +1 -0
  44. package/dist/core/diff/validator.d.ts +21 -0
  45. package/dist/core/diff/validator.d.ts.map +1 -0
  46. package/dist/core/diff/validator.js +86 -0
  47. package/dist/core/diff/validator.js.map +1 -0
  48. package/dist/db/client.d.ts +2 -0
  49. package/dist/db/client.d.ts.map +1 -1
  50. package/dist/db/client.js +3 -0
  51. package/dist/db/client.js.map +1 -1
  52. package/dist/db/migrations/002_applies.sql +32 -0
  53. package/dist/index.js +3 -1
  54. package/dist/index.js.map +1 -1
  55. package/package.json +2 -2
@@ -0,0 +1,179 @@
1
+ import { DiffParser, DiffValidator, DiffApplier } from '../diff/index.js';
2
+ import { BackupManager } from '../backup/index.js';
3
+ import { dbClient } from '../../db/client.js';
4
+ import { logger } from '../../utils/logger.js';
5
+ import { join } from 'path';
6
+ export class ApplyEngine {
7
+ backupManager;
8
+ constructor() {
9
+ this.backupManager = new BackupManager();
10
+ }
11
+ /**
12
+ * Apply a suggestion to the codebase
13
+ */
14
+ async applySuggestion(suggestionId, options = {}) {
15
+ const { dryRun = false, force = false, createBackup = true, } = options;
16
+ try {
17
+ logger.verbose(`Applying suggestion: ${suggestionId}`);
18
+ // 1. Load suggestion from database
19
+ const suggestion = await this.loadSuggestion(suggestionId);
20
+ if (!suggestion) {
21
+ return {
22
+ success: false,
23
+ suggestionId,
24
+ filesModified: [],
25
+ error: 'Suggestion not found',
26
+ };
27
+ }
28
+ // 2. Parse diff
29
+ logger.verbose('Parsing diff...');
30
+ const diffs = DiffParser.parse(suggestion.diff);
31
+ if (diffs.length === 0) {
32
+ return {
33
+ success: false,
34
+ suggestionId,
35
+ filesModified: [],
36
+ error: 'No valid diff found in suggestion',
37
+ };
38
+ }
39
+ // 3. Validate all diffs
40
+ logger.verbose('Validating changes...');
41
+ const validationResults = await Promise.all(diffs.map((diff) => {
42
+ const filePath = join(process.cwd(), diff.filePath);
43
+ return DiffValidator.validate(diff, filePath);
44
+ }));
45
+ const allValid = validationResults.every((r) => r.valid);
46
+ const warnings = validationResults.flatMap((r) => r.warnings);
47
+ if (!allValid && !force) {
48
+ const errors = validationResults.flatMap((r) => r.errors);
49
+ return {
50
+ success: false,
51
+ suggestionId,
52
+ filesModified: [],
53
+ error: `Validation failed: ${errors.join(', ')}`,
54
+ warnings,
55
+ };
56
+ }
57
+ // 4. Dry run mode - just show what would change
58
+ if (dryRun) {
59
+ logger.info('Dry run mode - no changes will be made');
60
+ return {
61
+ success: true,
62
+ suggestionId,
63
+ filesModified: diffs.map((d) => d.filePath),
64
+ warnings,
65
+ };
66
+ }
67
+ // 5. Create backup
68
+ let backupId;
69
+ if (createBackup) {
70
+ logger.verbose('Creating backup...');
71
+ const filesToBackup = diffs.map((d) => join(process.cwd(), d.filePath));
72
+ backupId = await this.backupManager.createBackup(filesToBackup, `apply-${suggestionId}`);
73
+ logger.verbose(`Backup created: ${backupId}`);
74
+ }
75
+ // 6. Apply changes
76
+ logger.verbose('Applying changes...');
77
+ const filesModified = [];
78
+ const applyErrors = [];
79
+ for (const diff of diffs) {
80
+ const filePath = join(process.cwd(), diff.filePath);
81
+ const result = await DiffApplier.apply(diff, filePath);
82
+ if (result.success) {
83
+ filesModified.push(result.filePath);
84
+ logger.verbose(`Applied changes to ${result.filePath}`);
85
+ }
86
+ else {
87
+ applyErrors.push(result.error || 'Unknown error');
88
+ logger.error(`Failed to apply changes to ${result.filePath}: ${result.error}`);
89
+ }
90
+ }
91
+ // 7. If any apply failed, rollback
92
+ if (applyErrors.length > 0 && backupId) {
93
+ logger.warn('Some changes failed, rolling back...');
94
+ await this.backupManager.restore(backupId);
95
+ return {
96
+ success: false,
97
+ suggestionId,
98
+ filesModified: [],
99
+ backupId,
100
+ error: `Apply failed: ${applyErrors.join(', ')}`,
101
+ warnings,
102
+ };
103
+ }
104
+ // 8. Record apply in database
105
+ if (dbClient.isConnected()) {
106
+ await this.recordApply(suggestionId, filesModified, backupId);
107
+ }
108
+ logger.success(`Successfully applied suggestion ${suggestionId}`);
109
+ return {
110
+ success: true,
111
+ suggestionId,
112
+ filesModified,
113
+ backupId,
114
+ warnings,
115
+ };
116
+ }
117
+ catch (error) {
118
+ logger.error('Apply engine error:', error);
119
+ return {
120
+ success: false,
121
+ suggestionId,
122
+ filesModified: [],
123
+ error: error.message,
124
+ };
125
+ }
126
+ }
127
+ /**
128
+ * Load suggestion from database
129
+ */
130
+ async loadSuggestion(suggestionId) {
131
+ if (!dbClient.isConnected()) {
132
+ throw new Error('Database not connected. Cannot load suggestion.');
133
+ }
134
+ const sql = dbClient.getClient();
135
+ if (!sql) {
136
+ return null;
137
+ }
138
+ const results = await sql `
139
+ SELECT diff FROM suggestions WHERE id = ${suggestionId}
140
+ `;
141
+ if (results.length === 0) {
142
+ return null;
143
+ }
144
+ return results[0];
145
+ }
146
+ /**
147
+ * Record apply operation in database
148
+ */
149
+ async recordApply(suggestionId, filesModified, backupId) {
150
+ const sql = dbClient.getClient();
151
+ if (!sql) {
152
+ return;
153
+ }
154
+ await sql `
155
+ INSERT INTO applies (
156
+ id,
157
+ suggestion_id,
158
+ files_modified,
159
+ backup_id,
160
+ applied_at,
161
+ status
162
+ ) VALUES (
163
+ gen_random_uuid(),
164
+ ${suggestionId},
165
+ ${JSON.stringify(filesModified)},
166
+ ${backupId || null},
167
+ NOW(),
168
+ 'success'
169
+ )
170
+ `;
171
+ }
172
+ /**
173
+ * Get backup manager instance
174
+ */
175
+ getBackupManager() {
176
+ return this.backupManager;
177
+ }
178
+ }
179
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/core/apply/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { ApplyEngine, ApplyOptions, ApplyEngineResult } from './engine.js';
2
+ export { InteractiveMode, InteractiveOptions, InteractiveResult } from './interactive.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/apply/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { ApplyEngine } from './engine.js';
2
+ export { InteractiveMode } from './interactive.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/apply/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAmC,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAyC,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { ParsedDiff } from '../diff/index.js';
2
+ export interface InteractiveOptions {
3
+ showFullDiff?: boolean;
4
+ allowPartial?: boolean;
5
+ }
6
+ export interface InteractiveResult {
7
+ confirmed: boolean;
8
+ selectedHunks?: number[];
9
+ skipAll?: boolean;
10
+ }
11
+ export declare class InteractiveMode {
12
+ /**
13
+ * Show diff preview and ask for confirmation
14
+ */
15
+ static confirmApply(diff: ParsedDiff, options?: InteractiveOptions): Promise<InteractiveResult>;
16
+ /**
17
+ * Show summary of changes
18
+ */
19
+ private static showSummary;
20
+ /**
21
+ * Show full diff with syntax highlighting
22
+ */
23
+ private static showFullDiff;
24
+ /**
25
+ * Print a single change line with color
26
+ */
27
+ private static printChange;
28
+ /**
29
+ * Let user select which hunks to apply
30
+ */
31
+ private static selectHunks;
32
+ /**
33
+ * Show progress for multiple files
34
+ */
35
+ static showProgress(current: number, total: number, fileName: string): void;
36
+ /**
37
+ * Create a progress bar
38
+ */
39
+ private static createProgressBar;
40
+ /**
41
+ * Show success message
42
+ */
43
+ static showSuccess(filesModified: number, backupId?: string): void;
44
+ /**
45
+ * Show error message
46
+ */
47
+ static showError(error: string): void;
48
+ /**
49
+ * Show warning message
50
+ */
51
+ static showWarnings(warnings: string[]): void;
52
+ }
53
+ //# sourceMappingURL=interactive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../../../src/core/apply/interactive.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,WAAW,kBAAkB;IAC/B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,qBAAa,eAAe;IACxB;;OAEG;WACU,YAAY,CACrB,IAAI,EAAE,UAAU,EAChB,OAAO,GAAE,kBAAuB,GACjC,OAAO,CAAC,iBAAiB,CAAC;IAmD7B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IA+B1B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,YAAY;IAkB3B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAgB1B;;OAEG;mBACkB,WAAW;IA+BhC;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAS3E;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAUhC;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAUlE;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKrC;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI;CAShD"}
@@ -0,0 +1,188 @@
1
+ import inquirer from 'inquirer';
2
+ import chalk from 'chalk';
3
+ export class InteractiveMode {
4
+ /**
5
+ * Show diff preview and ask for confirmation
6
+ */
7
+ static async confirmApply(diff, options = {}) {
8
+ const { showFullDiff = false, allowPartial = false } = options;
9
+ // Show diff preview
10
+ console.log(chalk.bold(`\n📝 Changes to ${chalk.cyan(diff.filePath)}:\n`));
11
+ if (showFullDiff) {
12
+ this.showFullDiff(diff);
13
+ }
14
+ else {
15
+ this.showSummary(diff);
16
+ }
17
+ // Ask for confirmation
18
+ const { action } = await inquirer.prompt([
19
+ {
20
+ type: 'list',
21
+ name: 'action',
22
+ message: 'Apply this change?',
23
+ choices: [
24
+ { name: 'Yes - Apply this change', value: 'yes' },
25
+ { name: 'No - Skip this change', value: 'no' },
26
+ { name: 'View full diff', value: 'diff' },
27
+ ...(allowPartial ? [{ name: 'Select hunks to apply', value: 'partial' }] : []),
28
+ { name: 'Quit - Cancel all changes', value: 'quit' },
29
+ ],
30
+ },
31
+ ]);
32
+ switch (action) {
33
+ case 'yes':
34
+ return { confirmed: true };
35
+ case 'no':
36
+ return { confirmed: false };
37
+ case 'diff':
38
+ this.showFullDiff(diff);
39
+ return this.confirmApply(diff, options);
40
+ case 'partial':
41
+ const selectedHunks = await this.selectHunks(diff);
42
+ return { confirmed: true, selectedHunks };
43
+ case 'quit':
44
+ return { confirmed: false, skipAll: true };
45
+ default:
46
+ return { confirmed: false };
47
+ }
48
+ }
49
+ /**
50
+ * Show summary of changes
51
+ */
52
+ static showSummary(diff) {
53
+ let additions = 0;
54
+ let deletions = 0;
55
+ for (const hunk of diff.hunks) {
56
+ for (const change of hunk.changes) {
57
+ if (change.type === 'add')
58
+ additions++;
59
+ if (change.type === 'remove')
60
+ deletions++;
61
+ }
62
+ }
63
+ console.log(` ${chalk.green(`+${additions}`)} additions, ${chalk.red(`-${deletions}`)} deletions`);
64
+ console.log(` ${diff.hunks.length} hunk(s)\n`);
65
+ // Show first few lines of first hunk
66
+ if (diff.hunks.length > 0) {
67
+ const firstHunk = diff.hunks[0];
68
+ const preview = firstHunk.changes.slice(0, 5);
69
+ console.log(chalk.gray(' Preview:'));
70
+ for (const change of preview) {
71
+ this.printChange(change, ' ');
72
+ }
73
+ if (firstHunk.changes.length > 5) {
74
+ console.log(chalk.gray(` ... and ${firstHunk.changes.length - 5} more lines`));
75
+ }
76
+ console.log();
77
+ }
78
+ }
79
+ /**
80
+ * Show full diff with syntax highlighting
81
+ */
82
+ static showFullDiff(diff) {
83
+ console.log(chalk.bold(`\n--- a/${diff.oldPath || diff.filePath}`));
84
+ console.log(chalk.bold(`+++ b/${diff.newPath || diff.filePath}\n`));
85
+ for (const hunk of diff.hunks) {
86
+ console.log(chalk.cyan(`@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@`));
87
+ for (const change of hunk.changes) {
88
+ this.printChange(change);
89
+ }
90
+ console.log();
91
+ }
92
+ }
93
+ /**
94
+ * Print a single change line with color
95
+ */
96
+ static printChange(change, indent = '') {
97
+ const line = `${indent}${change.content}`;
98
+ switch (change.type) {
99
+ case 'add':
100
+ console.log(chalk.green(`+${line}`));
101
+ break;
102
+ case 'remove':
103
+ console.log(chalk.red(`-${line}`));
104
+ break;
105
+ case 'context':
106
+ console.log(chalk.gray(` ${line}`));
107
+ break;
108
+ }
109
+ }
110
+ /**
111
+ * Let user select which hunks to apply
112
+ */
113
+ static async selectHunks(diff) {
114
+ console.log(chalk.bold('\n📋 Select hunks to apply:\n'));
115
+ const choices = diff.hunks.map((hunk, index) => {
116
+ let additions = 0;
117
+ let deletions = 0;
118
+ for (const change of hunk.changes) {
119
+ if (change.type === 'add')
120
+ additions++;
121
+ if (change.type === 'remove')
122
+ deletions++;
123
+ }
124
+ return {
125
+ name: `Hunk ${index + 1}: Lines ${hunk.oldStart}-${hunk.oldStart + hunk.oldLines} (${chalk.green(`+${additions}`)} ${chalk.red(`-${deletions}`)})`,
126
+ value: index,
127
+ checked: true,
128
+ };
129
+ });
130
+ const { selected } = await inquirer.prompt([
131
+ {
132
+ type: 'checkbox',
133
+ name: 'selected',
134
+ message: 'Select hunks to apply:',
135
+ choices,
136
+ },
137
+ ]);
138
+ return selected;
139
+ }
140
+ /**
141
+ * Show progress for multiple files
142
+ */
143
+ static showProgress(current, total, fileName) {
144
+ const percentage = Math.round((current / total) * 100);
145
+ const bar = this.createProgressBar(percentage, 30);
146
+ console.log(`\n${chalk.cyan(`[${current}/${total}]`)} ${bar} ${percentage}% - ${chalk.gray(fileName)}`);
147
+ }
148
+ /**
149
+ * Create a progress bar
150
+ */
151
+ static createProgressBar(percentage, width) {
152
+ const filled = Math.round((percentage / 100) * width);
153
+ const empty = width - filled;
154
+ return (chalk.green('█'.repeat(filled)) +
155
+ chalk.gray('░'.repeat(empty)));
156
+ }
157
+ /**
158
+ * Show success message
159
+ */
160
+ static showSuccess(filesModified, backupId) {
161
+ console.log(chalk.bold.green('\n✨ Changes applied successfully!\n'));
162
+ console.log(` Files modified: ${chalk.cyan(filesModified)}`);
163
+ if (backupId) {
164
+ console.log(` Backup created: ${chalk.gray(backupId)}`);
165
+ console.log(chalk.yellow(`\n To undo: ${chalk.cyan(`ownkey undo ${backupId}`)}\n`));
166
+ }
167
+ }
168
+ /**
169
+ * Show error message
170
+ */
171
+ static showError(error) {
172
+ console.log(chalk.bold.red('\n❌ Apply failed!\n'));
173
+ console.log(chalk.red(` Error: ${error}\n`));
174
+ }
175
+ /**
176
+ * Show warning message
177
+ */
178
+ static showWarnings(warnings) {
179
+ if (warnings.length === 0)
180
+ return;
181
+ console.log(chalk.bold.yellow('\n⚠️ Warnings:\n'));
182
+ for (const warning of warnings) {
183
+ console.log(chalk.yellow(` • ${warning}`));
184
+ }
185
+ console.log();
186
+ }
187
+ }
188
+ //# sourceMappingURL=interactive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactive.js","sourceRoot":"","sources":["../../../src/core/apply/interactive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { BackupManager, BackupMetadata, BackupInfo } from './manager.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/backup/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { BackupManager } from './manager.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/backup/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA8B,MAAM,cAAc,CAAC"}
@@ -0,0 +1,49 @@
1
+ export interface BackupMetadata {
2
+ id: string;
3
+ timestamp: Date;
4
+ files: string[];
5
+ reason: string;
6
+ }
7
+ export interface BackupInfo {
8
+ id: string;
9
+ timestamp: Date;
10
+ fileCount: number;
11
+ reason: string;
12
+ }
13
+ export declare class BackupManager {
14
+ private backupDir;
15
+ constructor(backupDir?: string);
16
+ /**
17
+ * Create a backup of files before applying changes
18
+ */
19
+ createBackup(files: string[], reason?: string): Promise<string>;
20
+ /**
21
+ * List all available backups
22
+ */
23
+ listBackups(): Promise<BackupInfo[]>;
24
+ /**
25
+ * Get backup metadata
26
+ */
27
+ getBackupMetadata(backupId: string): Promise<BackupMetadata | null>;
28
+ /**
29
+ * Restore files from a backup
30
+ */
31
+ restore(backupId: string, files?: string[]): Promise<void>;
32
+ /**
33
+ * Delete a backup
34
+ */
35
+ deleteBackup(backupId: string): Promise<void>;
36
+ /**
37
+ * Clean old backups (keep last N)
38
+ */
39
+ cleanOldBackups(keep?: number): Promise<number>;
40
+ /**
41
+ * Generate a unique backup ID
42
+ */
43
+ private generateBackupId;
44
+ /**
45
+ * Get backup directory path
46
+ */
47
+ getBackupDir(): string;
48
+ }
49
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../src/core/backup/manager.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,IAAI,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,aAAa;IACtB,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,CAAC,EAAE,MAAM;IAI9B;;OAEG;IACG,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,GAAE,MAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;IAsC9E;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAyB1C;;OAEG;IACG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAUzE;;OAEG;IACG,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBhE;;OAEG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOnD;;OAEG;IACG,eAAe,CAAC,IAAI,GAAE,MAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAezD;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;OAEG;IACH,YAAY,IAAI,MAAM;CAGzB"}
@@ -0,0 +1,133 @@
1
+ import { mkdir, copyFile, readdir, rm, readFile, writeFile } from 'fs/promises';
2
+ import { join, dirname, relative } from 'path';
3
+ import { homedir } from 'os';
4
+ import { existsSync } from 'fs';
5
+ export class BackupManager {
6
+ backupDir;
7
+ constructor(backupDir) {
8
+ this.backupDir = backupDir || join(homedir(), '.ownkey', 'backups');
9
+ }
10
+ /**
11
+ * Create a backup of files before applying changes
12
+ */
13
+ async createBackup(files, reason = 'apply') {
14
+ const backupId = this.generateBackupId();
15
+ const backupPath = join(this.backupDir, backupId);
16
+ // Create backup directory
17
+ await mkdir(backupPath, { recursive: true });
18
+ // Copy each file
19
+ const copiedFiles = [];
20
+ for (const file of files) {
21
+ const relativePath = relative(process.cwd(), file);
22
+ const targetPath = join(backupPath, relativePath);
23
+ // Create parent directories
24
+ await mkdir(dirname(targetPath), { recursive: true });
25
+ // Copy file
26
+ await copyFile(file, targetPath);
27
+ copiedFiles.push(relativePath);
28
+ }
29
+ // Save metadata
30
+ const metadata = {
31
+ id: backupId,
32
+ timestamp: new Date(),
33
+ files: copiedFiles,
34
+ reason,
35
+ };
36
+ await writeFile(join(backupPath, 'metadata.json'), JSON.stringify(metadata, null, 2), 'utf-8');
37
+ return backupId;
38
+ }
39
+ /**
40
+ * List all available backups
41
+ */
42
+ async listBackups() {
43
+ if (!existsSync(this.backupDir)) {
44
+ return [];
45
+ }
46
+ const entries = await readdir(this.backupDir);
47
+ const backups = [];
48
+ for (const entry of entries) {
49
+ const metadataPath = join(this.backupDir, entry, 'metadata.json');
50
+ if (existsSync(metadataPath)) {
51
+ const metadata = JSON.parse(await readFile(metadataPath, 'utf-8'));
52
+ backups.push({
53
+ id: metadata.id,
54
+ timestamp: new Date(metadata.timestamp),
55
+ fileCount: metadata.files.length,
56
+ reason: metadata.reason,
57
+ });
58
+ }
59
+ }
60
+ // Sort by timestamp (newest first)
61
+ return backups.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
62
+ }
63
+ /**
64
+ * Get backup metadata
65
+ */
66
+ async getBackupMetadata(backupId) {
67
+ const metadataPath = join(this.backupDir, backupId, 'metadata.json');
68
+ if (!existsSync(metadataPath)) {
69
+ return null;
70
+ }
71
+ const metadata = JSON.parse(await readFile(metadataPath, 'utf-8'));
72
+ return metadata;
73
+ }
74
+ /**
75
+ * Restore files from a backup
76
+ */
77
+ async restore(backupId, files) {
78
+ const metadata = await this.getBackupMetadata(backupId);
79
+ if (!metadata) {
80
+ throw new Error(`Backup not found: ${backupId}`);
81
+ }
82
+ const backupPath = join(this.backupDir, backupId);
83
+ const filesToRestore = files || metadata.files;
84
+ for (const file of filesToRestore) {
85
+ const sourcePath = join(backupPath, file);
86
+ const targetPath = join(process.cwd(), file);
87
+ if (existsSync(sourcePath)) {
88
+ // Create parent directories
89
+ await mkdir(dirname(targetPath), { recursive: true });
90
+ // Restore file
91
+ await copyFile(sourcePath, targetPath);
92
+ }
93
+ }
94
+ }
95
+ /**
96
+ * Delete a backup
97
+ */
98
+ async deleteBackup(backupId) {
99
+ const backupPath = join(this.backupDir, backupId);
100
+ if (existsSync(backupPath)) {
101
+ await rm(backupPath, { recursive: true, force: true });
102
+ }
103
+ }
104
+ /**
105
+ * Clean old backups (keep last N)
106
+ */
107
+ async cleanOldBackups(keep = 10) {
108
+ const backups = await this.listBackups();
109
+ if (backups.length <= keep) {
110
+ return 0;
111
+ }
112
+ const toDelete = backups.slice(keep);
113
+ for (const backup of toDelete) {
114
+ await this.deleteBackup(backup.id);
115
+ }
116
+ return toDelete.length;
117
+ }
118
+ /**
119
+ * Generate a unique backup ID
120
+ */
121
+ generateBackupId() {
122
+ const now = new Date();
123
+ const timestamp = now.toISOString().replace(/[:.]/g, '-').slice(0, -5);
124
+ return timestamp;
125
+ }
126
+ /**
127
+ * Get backup directory path
128
+ */
129
+ getBackupDir() {
130
+ return this.backupDir;
131
+ }
132
+ }
133
+ //# sourceMappingURL=manager.js.map