ownkey 0.6.0 → 0.8.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 (62) hide show
  1. package/README.md +105 -151
  2. package/dist/ai/factory.d.ts.map +1 -1
  3. package/dist/ai/factory.js +5 -1
  4. package/dist/ai/factory.js.map +1 -1
  5. package/dist/ai/ollama.d.ts +30 -0
  6. package/dist/ai/ollama.d.ts.map +1 -0
  7. package/dist/ai/ollama.js +175 -0
  8. package/dist/ai/ollama.js.map +1 -0
  9. package/dist/commands/apply.d.ts.map +1 -1
  10. package/dist/commands/apply.js +63 -14
  11. package/dist/commands/apply.js.map +1 -1
  12. package/dist/commands/suggest.d.ts.map +1 -1
  13. package/dist/commands/suggest.js +4 -0
  14. package/dist/commands/suggest.js.map +1 -1
  15. package/dist/commands/undo.d.ts +3 -0
  16. package/dist/commands/undo.d.ts.map +1 -0
  17. package/dist/commands/undo.js +197 -0
  18. package/dist/commands/undo.js.map +1 -0
  19. package/dist/core/apply/engine.d.ts +36 -0
  20. package/dist/core/apply/engine.d.ts.map +1 -0
  21. package/dist/core/apply/engine.js +179 -0
  22. package/dist/core/apply/engine.js.map +1 -0
  23. package/dist/core/apply/index.d.ts +3 -0
  24. package/dist/core/apply/index.d.ts.map +1 -0
  25. package/dist/core/apply/index.js +3 -0
  26. package/dist/core/apply/index.js.map +1 -0
  27. package/dist/core/apply/interactive.d.ts +53 -0
  28. package/dist/core/apply/interactive.d.ts.map +1 -0
  29. package/dist/core/apply/interactive.js +188 -0
  30. package/dist/core/apply/interactive.js.map +1 -0
  31. package/dist/core/backup/index.d.ts +2 -0
  32. package/dist/core/backup/index.d.ts.map +1 -0
  33. package/dist/core/backup/index.js +2 -0
  34. package/dist/core/backup/index.js.map +1 -0
  35. package/dist/core/backup/manager.d.ts +49 -0
  36. package/dist/core/backup/manager.d.ts.map +1 -0
  37. package/dist/core/backup/manager.js +133 -0
  38. package/dist/core/backup/manager.js.map +1 -0
  39. package/dist/core/diff/applier.d.ts +22 -0
  40. package/dist/core/diff/applier.d.ts.map +1 -0
  41. package/dist/core/diff/applier.js +98 -0
  42. package/dist/core/diff/applier.js.map +1 -0
  43. package/dist/core/diff/index.d.ts +4 -0
  44. package/dist/core/diff/index.d.ts.map +1 -0
  45. package/dist/core/diff/index.js +4 -0
  46. package/dist/core/diff/index.js.map +1 -0
  47. package/dist/core/diff/parser.d.ts +32 -0
  48. package/dist/core/diff/parser.d.ts.map +1 -0
  49. package/dist/core/diff/parser.js +108 -0
  50. package/dist/core/diff/parser.js.map +1 -0
  51. package/dist/core/diff/validator.d.ts +21 -0
  52. package/dist/core/diff/validator.d.ts.map +1 -0
  53. package/dist/core/diff/validator.js +86 -0
  54. package/dist/core/diff/validator.js.map +1 -0
  55. package/dist/db/client.d.ts +2 -0
  56. package/dist/db/client.d.ts.map +1 -1
  57. package/dist/db/client.js +14 -5
  58. package/dist/db/client.js.map +1 -1
  59. package/dist/db/migrations/002_applies.sql +32 -0
  60. package/dist/index.js +3 -1
  61. package/dist/index.js.map +1 -1
  62. package/package.json +2 -2
@@ -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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../src/core/backup/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { ParsedDiff } from './parser.js';
2
+ export interface ApplyResult {
3
+ success: boolean;
4
+ filePath: string;
5
+ linesChanged: number;
6
+ error?: string;
7
+ }
8
+ export declare class DiffApplier {
9
+ /**
10
+ * Apply a parsed diff to a file
11
+ */
12
+ static apply(diff: ParsedDiff, targetPath: string): Promise<ApplyResult>;
13
+ /**
14
+ * Apply a single hunk to file lines
15
+ */
16
+ private static applyHunk;
17
+ /**
18
+ * Dry run - show what would change without actually applying
19
+ */
20
+ static dryRun(diff: ParsedDiff, targetPath: string): Promise<string[]>;
21
+ }
22
+ //# sourceMappingURL=applier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applier.d.ts","sourceRoot":"","sources":["../../../src/core/diff/applier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAQ,MAAM,aAAa,CAAC;AAI/C,MAAM,WAAW,WAAW;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,WAAW;IACpB;;OAEG;WACU,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IA6C9E;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS;IA0CxB;;OAEG;WACU,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAY/E"}
@@ -0,0 +1,98 @@
1
+ import { readFile, writeFile } from 'fs/promises';
2
+ import { DiffValidator } from './validator.js';
3
+ export class DiffApplier {
4
+ /**
5
+ * Apply a parsed diff to a file
6
+ */
7
+ static async apply(diff, targetPath) {
8
+ try {
9
+ // Validate first
10
+ const validation = await DiffValidator.validate(diff, targetPath);
11
+ if (!validation.valid) {
12
+ return {
13
+ success: false,
14
+ filePath: targetPath,
15
+ linesChanged: 0,
16
+ error: `Validation failed: ${validation.errors.join(', ')}`,
17
+ };
18
+ }
19
+ // Read file
20
+ const fileContent = await readFile(targetPath, 'utf-8');
21
+ const lines = fileContent.split('\n');
22
+ // Apply hunks
23
+ let linesChanged = 0;
24
+ let offset = 0; // Track line number shifts
25
+ for (const hunk of diff.hunks) {
26
+ const result = this.applyHunk(hunk, lines, offset);
27
+ linesChanged += result.linesChanged;
28
+ offset += result.offset;
29
+ }
30
+ // Write back
31
+ await writeFile(targetPath, lines.join('\n'), 'utf-8');
32
+ return {
33
+ success: true,
34
+ filePath: targetPath,
35
+ linesChanged,
36
+ };
37
+ }
38
+ catch (error) {
39
+ return {
40
+ success: false,
41
+ filePath: targetPath,
42
+ linesChanged: 0,
43
+ error: error.message,
44
+ };
45
+ }
46
+ }
47
+ /**
48
+ * Apply a single hunk to file lines
49
+ */
50
+ static applyHunk(hunk, lines, offset) {
51
+ let linesChanged = 0;
52
+ let currentOffset = offset;
53
+ let fileLineIndex = hunk.oldStart - 1 + offset;
54
+ // Collect changes to apply
55
+ const toRemove = [];
56
+ const toAdd = [];
57
+ for (const change of hunk.changes) {
58
+ if (change.type === 'remove') {
59
+ toRemove.push(fileLineIndex);
60
+ fileLineIndex++;
61
+ linesChanged++;
62
+ }
63
+ else if (change.type === 'add') {
64
+ toAdd.push({ index: fileLineIndex, content: change.content });
65
+ fileLineIndex++;
66
+ currentOffset++;
67
+ linesChanged++;
68
+ }
69
+ else if (change.type === 'context') {
70
+ fileLineIndex++;
71
+ }
72
+ }
73
+ // Apply removals (in reverse to maintain indices)
74
+ for (let i = toRemove.length - 1; i >= 0; i--) {
75
+ lines.splice(toRemove[i], 1);
76
+ currentOffset--;
77
+ }
78
+ // Apply additions
79
+ for (const add of toAdd) {
80
+ lines.splice(add.index, 0, add.content);
81
+ }
82
+ return { linesChanged, offset: currentOffset - offset };
83
+ }
84
+ /**
85
+ * Dry run - show what would change without actually applying
86
+ */
87
+ static async dryRun(diff, targetPath) {
88
+ const fileContent = await readFile(targetPath, 'utf-8');
89
+ const lines = fileContent.split('\n').slice(); // Copy
90
+ let offset = 0;
91
+ for (const hunk of diff.hunks) {
92
+ const result = this.applyHunk(hunk, lines, offset);
93
+ offset += result.offset;
94
+ }
95
+ return lines;
96
+ }
97
+ }
98
+ //# sourceMappingURL=applier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applier.js","sourceRoot":"","sources":["../../../src/core/diff/applier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { DiffParser, ParsedDiff, Hunk, Change } from './parser.js';
2
+ export { DiffValidator, ValidationResult } from './validator.js';
3
+ export { DiffApplier, ApplyResult } from './applier.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/diff/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { DiffParser } from './parser.js';
2
+ export { DiffValidator } from './validator.js';
3
+ export { DiffApplier } from './applier.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/diff/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA4B,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,aAAa,EAAoB,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAe,MAAM,cAAc,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Diff Parser - Parse unified diff format
3
+ */
4
+ export interface ParsedDiff {
5
+ filePath: string;
6
+ oldPath?: string;
7
+ newPath?: string;
8
+ hunks: Hunk[];
9
+ }
10
+ export interface Hunk {
11
+ oldStart: number;
12
+ oldLines: number;
13
+ newStart: number;
14
+ newLines: number;
15
+ changes: Change[];
16
+ }
17
+ export interface Change {
18
+ type: 'add' | 'remove' | 'context';
19
+ content: string;
20
+ lineNumber: number;
21
+ }
22
+ export declare class DiffParser {
23
+ /**
24
+ * Parse unified diff format into structured data
25
+ */
26
+ static parse(diffText: string): ParsedDiff[];
27
+ /**
28
+ * Generate unified diff format from structured data
29
+ */
30
+ static generate(diff: ParsedDiff): string;
31
+ }
32
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../src/core/diff/parser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,UAAU;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,IAAI,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,IAAI;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,MAAM;IACnB,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,UAAU;IACnB;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,EAAE;IAwF5C;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM;CAiB5C"}