undoai 0.1.0-beta.1

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 (46) hide show
  1. package/README.md +243 -0
  2. package/dist/cli/commands/restore.d.ts +11 -0
  3. package/dist/cli/commands/restore.d.ts.map +1 -0
  4. package/dist/cli/commands/restore.js +188 -0
  5. package/dist/cli/commands/restore.js.map +1 -0
  6. package/dist/cli/commands/status.d.ts +5 -0
  7. package/dist/cli/commands/status.d.ts.map +1 -0
  8. package/dist/cli/commands/status.js +46 -0
  9. package/dist/cli/commands/status.js.map +1 -0
  10. package/dist/cli/commands/stop.d.ts +5 -0
  11. package/dist/cli/commands/stop.d.ts.map +1 -0
  12. package/dist/cli/commands/stop.js +21 -0
  13. package/dist/cli/commands/stop.js.map +1 -0
  14. package/dist/cli/commands/watch.d.ts +5 -0
  15. package/dist/cli/commands/watch.d.ts.map +1 -0
  16. package/dist/cli/commands/watch.js +138 -0
  17. package/dist/cli/commands/watch.js.map +1 -0
  18. package/dist/cli/index.d.ts +3 -0
  19. package/dist/cli/index.d.ts.map +1 -0
  20. package/dist/cli/index.js +45 -0
  21. package/dist/cli/index.js.map +1 -0
  22. package/dist/core/daemon.d.ts +35 -0
  23. package/dist/core/daemon.d.ts.map +1 -0
  24. package/dist/core/daemon.js +94 -0
  25. package/dist/core/daemon.js.map +1 -0
  26. package/dist/core/snapshot.d.ts +39 -0
  27. package/dist/core/snapshot.d.ts.map +1 -0
  28. package/dist/core/snapshot.js +119 -0
  29. package/dist/core/snapshot.js.map +1 -0
  30. package/dist/core/storage.d.ts +92 -0
  31. package/dist/core/storage.d.ts.map +1 -0
  32. package/dist/core/storage.js +198 -0
  33. package/dist/core/storage.js.map +1 -0
  34. package/dist/example.d.ts +2 -0
  35. package/dist/example.d.ts.map +1 -0
  36. package/dist/example.js +30 -0
  37. package/dist/example.js.map +1 -0
  38. package/dist/utils/logger.d.ts +42 -0
  39. package/dist/utils/logger.d.ts.map +1 -0
  40. package/dist/utils/logger.js +61 -0
  41. package/dist/utils/logger.js.map +1 -0
  42. package/dist/watcher.d.ts +55 -0
  43. package/dist/watcher.d.ts.map +1 -0
  44. package/dist/watcher.js +122 -0
  45. package/dist/watcher.js.map +1 -0
  46. package/package.json +59 -0
@@ -0,0 +1,198 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { homedir } from 'os';
4
+ import zlib from 'zlib';
5
+ /**
6
+ * Storage paths configuration
7
+ */
8
+ export const STORAGE_PATHS = {
9
+ root: path.join(homedir(), '.undoai'),
10
+ snapshots: path.join(homedir(), '.undoai', 'snapshots'),
11
+ daemonPid: path.join(homedir(), '.undoai', 'daemon.pid'),
12
+ config: path.join(homedir(), '.undoai', 'config.json'),
13
+ };
14
+ /**
15
+ * Storage manager for undoai snapshots
16
+ */
17
+ export class Storage {
18
+ /**
19
+ * Initialize storage directory structure
20
+ */
21
+ static init() {
22
+ // Create root directory
23
+ if (!fs.existsSync(STORAGE_PATHS.root)) {
24
+ fs.mkdirSync(STORAGE_PATHS.root, { recursive: true });
25
+ }
26
+ // Create snapshots directory
27
+ if (!fs.existsSync(STORAGE_PATHS.snapshots)) {
28
+ fs.mkdirSync(STORAGE_PATHS.snapshots, { recursive: true });
29
+ }
30
+ }
31
+ /**
32
+ * Check if storage is initialized
33
+ */
34
+ static isInitialized() {
35
+ return fs.existsSync(STORAGE_PATHS.root) && fs.existsSync(STORAGE_PATHS.snapshots);
36
+ }
37
+ /**
38
+ * Check if a file exists
39
+ */
40
+ static fileExists(filePath) {
41
+ try {
42
+ return fs.existsSync(filePath) && fs.statSync(filePath).isFile();
43
+ }
44
+ catch {
45
+ return false;
46
+ }
47
+ }
48
+ /**
49
+ * Get all snapshot IDs (sorted by timestamp, newest first)
50
+ */
51
+ static getSnapshotIds() {
52
+ if (!fs.existsSync(STORAGE_PATHS.snapshots)) {
53
+ return [];
54
+ }
55
+ const entries = fs.readdirSync(STORAGE_PATHS.snapshots, { withFileTypes: true });
56
+ const snapshotIds = entries
57
+ .filter((entry) => entry.isDirectory())
58
+ .map((entry) => entry.name)
59
+ .sort((a, b) => parseInt(b) - parseInt(a)); // Newest first
60
+ return snapshotIds;
61
+ }
62
+ /**
63
+ * Get snapshot metadata
64
+ */
65
+ static getSnapshotMetadata(snapshotId) {
66
+ const metadataPath = path.join(STORAGE_PATHS.snapshots, snapshotId, 'metadata.json');
67
+ if (!fs.existsSync(metadataPath)) {
68
+ return null;
69
+ }
70
+ try {
71
+ const content = fs.readFileSync(metadataPath, 'utf-8');
72
+ return JSON.parse(content);
73
+ }
74
+ catch (error) {
75
+ console.error(`Failed to read metadata for snapshot ${snapshotId}:`, error);
76
+ return null;
77
+ }
78
+ }
79
+ /**
80
+ * Get snapshot directory path
81
+ */
82
+ static getSnapshotDir(snapshotId) {
83
+ return path.join(STORAGE_PATHS.snapshots, snapshotId);
84
+ }
85
+ /**
86
+ * Get snapshot files directory path
87
+ */
88
+ static getSnapshotFilesDir(snapshotId) {
89
+ return path.join(STORAGE_PATHS.snapshots, snapshotId, 'files');
90
+ }
91
+ /**
92
+ * Create a new snapshot directory
93
+ */
94
+ static createSnapshotDir(snapshotId) {
95
+ const snapshotDir = this.getSnapshotDir(snapshotId);
96
+ const filesDir = this.getSnapshotFilesDir(snapshotId);
97
+ fs.mkdirSync(snapshotDir, { recursive: true });
98
+ fs.mkdirSync(filesDir, { recursive: true });
99
+ return snapshotDir;
100
+ }
101
+ /**
102
+ * Save snapshot metadata
103
+ */
104
+ static saveMetadata(snapshotId, metadata) {
105
+ const metadataPath = path.join(STORAGE_PATHS.snapshots, snapshotId, 'metadata.json');
106
+ fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2), 'utf-8');
107
+ }
108
+ /**
109
+ * Convert file path to safe filename (replace / with __)
110
+ * Example: /home/user/project/src/auth.ts -> src__auth.ts
111
+ */
112
+ static pathToSafeFilename(filePath, projectRoot) {
113
+ const relativePath = path.relative(projectRoot, filePath);
114
+ return relativePath.replace(/\//g, '__').replace(/\\/g, '__');
115
+ }
116
+ /**
117
+ * Convert safe filename back to relative path
118
+ * Example: src__auth.ts -> src/auth.ts
119
+ */
120
+ static safeFilenameToPath(safeFilename) {
121
+ return safeFilename.replace(/__/g, path.sep);
122
+ }
123
+ /**
124
+ * Copy file to snapshot with compression
125
+ */
126
+ static copyFileToSnapshot(sourceFile, snapshotId, projectRoot) {
127
+ const safeFilename = this.pathToSafeFilename(sourceFile, projectRoot);
128
+ const destPath = path.join(this.getSnapshotFilesDir(snapshotId), safeFilename + '.gz');
129
+ // Read, compress, and save file
130
+ const fileContent = fs.readFileSync(sourceFile);
131
+ const compressed = zlib.gzipSync(fileContent);
132
+ fs.writeFileSync(destPath, compressed);
133
+ }
134
+ /**
135
+ * Restore file from snapshot with decompression
136
+ */
137
+ static restoreFileFromSnapshot(originalPath, snapshotId, projectRoot) {
138
+ const safeFilename = this.pathToSafeFilename(originalPath, projectRoot);
139
+ const sourcePath = path.join(this.getSnapshotFilesDir(snapshotId), safeFilename + '.gz');
140
+ if (!fs.existsSync(sourcePath)) {
141
+ throw new Error(`Snapshot file not found: ${safeFilename}.gz`);
142
+ }
143
+ // Ensure target directory exists
144
+ const targetDir = path.dirname(originalPath);
145
+ if (!fs.existsSync(targetDir)) {
146
+ fs.mkdirSync(targetDir, { recursive: true });
147
+ }
148
+ // Decompress and restore file
149
+ const compressed = fs.readFileSync(sourcePath);
150
+ const decompressed = zlib.gunzipSync(compressed);
151
+ fs.writeFileSync(originalPath, decompressed);
152
+ }
153
+ /**
154
+ * Delete a snapshot
155
+ */
156
+ static deleteSnapshot(snapshotId) {
157
+ const snapshotDir = this.getSnapshotDir(snapshotId);
158
+ if (fs.existsSync(snapshotDir)) {
159
+ fs.rmSync(snapshotDir, { recursive: true, force: true });
160
+ }
161
+ }
162
+ /**
163
+ * Get total storage size in bytes
164
+ */
165
+ static getStorageSize() {
166
+ if (!fs.existsSync(STORAGE_PATHS.snapshots)) {
167
+ return 0;
168
+ }
169
+ let totalSize = 0;
170
+ const calculateDirSize = (dirPath) => {
171
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
172
+ for (const entry of entries) {
173
+ const fullPath = path.join(dirPath, entry.name);
174
+ if (entry.isDirectory()) {
175
+ calculateDirSize(fullPath);
176
+ }
177
+ else {
178
+ const stats = fs.statSync(fullPath);
179
+ totalSize += stats.size;
180
+ }
181
+ }
182
+ };
183
+ calculateDirSize(STORAGE_PATHS.snapshots);
184
+ return totalSize;
185
+ }
186
+ /**
187
+ * Format bytes to human readable string
188
+ */
189
+ static formatBytes(bytes) {
190
+ if (bytes === 0)
191
+ return '0 Bytes';
192
+ const k = 1024;
193
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
194
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
195
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
196
+ }
197
+ }
198
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/core/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IACzB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC;IACrC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,WAAW,CAAC;IACvD,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,YAAY,CAAC;IACxD,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,aAAa,CAAC;CAChD,CAAC;AAcX;;GAEG;AACH,MAAM,OAAO,OAAO;IAChB;;OAEG;IACH,MAAM,CAAC,IAAI;QACP,wBAAwB;QACxB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACrC,EAAE,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,CAAC;QAED,6BAA6B;QAC7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1C,EAAE,CAAC,SAAS,CAAC,aAAa,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/D,CAAC;IACL,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,aAAa;QAChB,OAAO,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IACvF,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,QAAgB;QAC9B,IAAI,CAAC;YACD,OAAO,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;QACrE,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAGD;;OAEG;IACH,MAAM,CAAC,cAAc;QACjB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1C,OAAO,EAAE,CAAC;QACd,CAAC;QAED,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,aAAa,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACjF,MAAM,WAAW,GAAG,OAAO;aACtB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;aACtC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;aAC1B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe;QAE/D,OAAO,WAAW,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,UAAkB;QACzC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;QAErF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,IAAI,CAAC;YACD,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;YACvD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,wCAAwC,UAAU,GAAG,EAAE,KAAK,CAAC,CAAC;YAC5E,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,UAAkB;QACpC,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAC1D,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,UAAkB;QACzC,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACnE,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,UAAkB;QACvC,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;QAEtD,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE5C,OAAO,WAAW,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,UAAkB,EAAE,QAA0B;QAC9D,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;QACrF,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC/E,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,kBAAkB,CAAC,QAAgB,EAAE,WAAmB;QAC3D,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC1D,OAAO,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAClE,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,kBAAkB,CAAC,YAAoB;QAC1C,OAAO,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IACjD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,kBAAkB,CACrB,UAAkB,EAClB,UAAkB,EAClB,WAAmB;QAEnB,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,YAAY,GAAG,KAAK,CAAC,CAAC;QAEvF,gCAAgC;QAChC,MAAM,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QAChD,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC9C,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC3C,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,uBAAuB,CAC1B,YAAoB,EACpB,UAAkB,EAClB,WAAmB;QAEnB,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;QACxE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,YAAY,GAAG,KAAK,CAAC,CAAC;QAEzF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,4BAA4B,YAAY,KAAK,CAAC,CAAC;QACnE,CAAC;QAED,iCAAiC;QACjC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAC7C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5B,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,CAAC;QAED,8BAA8B;QAC9B,MAAM,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QAC/C,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QACjD,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IACjD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,UAAkB;QACpC,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QAEpD,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,CAAC;IACL,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,cAAc;QACjB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1C,OAAO,CAAC,CAAC;QACb,CAAC;QAED,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,MAAM,gBAAgB,GAAG,CAAC,OAAe,EAAQ,EAAE;YAC/C,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YAEjE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBAEhD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;oBACtB,gBAAgB,CAAC,QAAQ,CAAC,CAAC;gBAC/B,CAAC;qBAAM,CAAC;oBACJ,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBACpC,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC;gBAC5B,CAAC;YACL,CAAC;QACL,CAAC,CAAC;QAEF,gBAAgB,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QAC1C,OAAO,SAAS,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,KAAa;QAC5B,IAAI,KAAK,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QAElC,MAAM,CAAC,GAAG,IAAI,CAAC;QACf,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAC1C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAEpD,OAAO,UAAU,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5E,CAAC;CACJ"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=example.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example.d.ts","sourceRoot":"","sources":["../src/example.ts"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
1
+ import { FileWatcher } from './watcher.js';
2
+ /**
3
+ * Example usage of the FileWatcher
4
+ */
5
+ function main() {
6
+ // Initialize the watcher
7
+ const watcher = new FileWatcher({
8
+ watchPath: process.cwd(), // Watch current directory
9
+ onBurstChange: (changedFiles) => {
10
+ console.log(`\n🔥 Burst detected! ${changedFiles.size} files changed:`);
11
+ changedFiles.forEach((file) => {
12
+ console.log(` - ${file}`);
13
+ });
14
+ },
15
+ burstThreshold: 5, // Trigger when ≥5 files change
16
+ debounceDelay: 2000, // After 2000ms of no changes
17
+ });
18
+ // Start watching
19
+ console.log('👀 Watching for file changes...');
20
+ console.log('💡 Make changes to ≥5 files, then wait 2 seconds\n');
21
+ watcher.start();
22
+ // Handle graceful shutdown
23
+ process.on('SIGINT', async () => {
24
+ console.log('\n\n👋 Stopping watcher...');
25
+ await watcher.stop();
26
+ process.exit(0);
27
+ });
28
+ }
29
+ main();
30
+ //# sourceMappingURL=example.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example.js","sourceRoot":"","sources":["../src/example.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C;;GAEG;AACH,SAAS,IAAI;IACT,yBAAyB;IACzB,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC;QAC5B,SAAS,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,0BAA0B;QACpD,aAAa,EAAE,CAAC,YAAY,EAAE,EAAE;YAC5B,OAAO,CAAC,GAAG,CAAC,wBAAwB,YAAY,CAAC,IAAI,iBAAiB,CAAC,CAAC;YACxE,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC1B,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;YAC/B,CAAC,CAAC,CAAC;QACP,CAAC;QACD,cAAc,EAAE,CAAC,EAAK,+BAA+B;QACrD,aAAa,EAAE,IAAI,EAAG,6BAA6B;KACtD,CAAC,CAAC;IAEH,iBAAiB;IACjB,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAC/C,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;IAClE,OAAO,CAAC,KAAK,EAAE,CAAC;IAEhB,2BAA2B;IAC3B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC5B,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;AACP,CAAC;AAED,IAAI,EAAE,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Logger utility with colored output
3
+ */
4
+ export declare class Logger {
5
+ /**
6
+ * Success message (green with checkmark)
7
+ */
8
+ static success(message: string): void;
9
+ /**
10
+ * Error message (red with cross)
11
+ */
12
+ static error(message: string): void;
13
+ /**
14
+ * Warning message (yellow with warning icon)
15
+ */
16
+ static warn(message: string): void;
17
+ /**
18
+ * Info message (blue with info icon)
19
+ */
20
+ static info(message: string): void;
21
+ /**
22
+ * Snapshot message (camera icon)
23
+ */
24
+ static snapshot(message: string): void;
25
+ /**
26
+ * Watch message (eyes icon)
27
+ */
28
+ static watch(message: string): void;
29
+ /**
30
+ * Plain message (no icon or color)
31
+ */
32
+ static plain(message: string): void;
33
+ /**
34
+ * Dim/subtle message
35
+ */
36
+ static dim(message: string): void;
37
+ /**
38
+ * Bold message
39
+ */
40
+ static bold(message: string): void;
41
+ }
42
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,qBAAa,MAAM;IACf;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIrC;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAInC;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIlC;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIlC;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAItC;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAInC;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAInC;;OAEG;IACH,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIjC;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAGrC"}
@@ -0,0 +1,61 @@
1
+ import chalk from 'chalk';
2
+ /**
3
+ * Logger utility with colored output
4
+ */
5
+ export class Logger {
6
+ /**
7
+ * Success message (green with checkmark)
8
+ */
9
+ static success(message) {
10
+ console.log(chalk.green('✅ ' + message));
11
+ }
12
+ /**
13
+ * Error message (red with cross)
14
+ */
15
+ static error(message) {
16
+ console.log(chalk.red('❌ ' + message));
17
+ }
18
+ /**
19
+ * Warning message (yellow with warning icon)
20
+ */
21
+ static warn(message) {
22
+ console.log(chalk.yellow('⚠️ ' + message));
23
+ }
24
+ /**
25
+ * Info message (blue with info icon)
26
+ */
27
+ static info(message) {
28
+ console.log(chalk.blue('ℹ️ ' + message));
29
+ }
30
+ /**
31
+ * Snapshot message (camera icon)
32
+ */
33
+ static snapshot(message) {
34
+ console.log(chalk.cyan('📸 ' + message));
35
+ }
36
+ /**
37
+ * Watch message (eyes icon)
38
+ */
39
+ static watch(message) {
40
+ console.log(chalk.magenta('👀 ' + message));
41
+ }
42
+ /**
43
+ * Plain message (no icon or color)
44
+ */
45
+ static plain(message) {
46
+ console.log(message);
47
+ }
48
+ /**
49
+ * Dim/subtle message
50
+ */
51
+ static dim(message) {
52
+ console.log(chalk.dim(message));
53
+ }
54
+ /**
55
+ * Bold message
56
+ */
57
+ static bold(message) {
58
+ console.log(chalk.bold(message));
59
+ }
60
+ }
61
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;GAEG;AACH,MAAM,OAAO,MAAM;IACf;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,OAAe;QAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,OAAe;QACxB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,OAAe;QACvB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,OAAe;QACvB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAe;QAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,OAAe;QACxB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,OAAe;QACxB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,GAAG,CAAC,OAAe;QACtB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IACpC,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,OAAe;QACvB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACrC,CAAC;CACJ"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Configuration options for the file watcher
3
+ */
4
+ export interface WatcherOptions {
5
+ /** Directory to watch for file changes */
6
+ watchPath: string;
7
+ /** Callback triggered when burst threshold is met */
8
+ onBurstChange: (changedFiles: Set<string>) => void;
9
+ /** Minimum number of files that must change to trigger burst (default: 5) */
10
+ burstThreshold?: number;
11
+ /** Debounce delay in milliseconds (default: 2000ms) */
12
+ debounceDelay?: number;
13
+ }
14
+ /**
15
+ * File watcher that monitors directory changes and triggers callbacks
16
+ * when a burst of changes occurs (≥5 files, no changes for ≥2000ms)
17
+ */
18
+ export declare class FileWatcher {
19
+ private watcher;
20
+ private changedFiles;
21
+ private debounceTimer;
22
+ private readonly watchPath;
23
+ private readonly onBurstChange;
24
+ private readonly burstThreshold;
25
+ private readonly debounceDelay;
26
+ constructor(options: WatcherOptions);
27
+ /**
28
+ * Start watching the directory for file changes
29
+ */
30
+ start(): void;
31
+ /**
32
+ * Handle a file change event
33
+ * Debounce Logic:
34
+ * 1. Add the file path to the Set (automatically prevents duplicates)
35
+ * 2. Clear any existing debounce timer
36
+ * 3. Start a new timer
37
+ * 4. If timer expires (no new changes for debounceDelay ms):
38
+ * - Check if we have ≥ burstThreshold unique files
39
+ * - If yes, trigger the callback and reset the buffer
40
+ */
41
+ private handleFileChange;
42
+ /**
43
+ * Stop watching and clean up resources
44
+ */
45
+ stop(): Promise<void>;
46
+ /**
47
+ * Get the current count of changed files in the buffer
48
+ */
49
+ getChangedFilesCount(): number;
50
+ /**
51
+ * Manually clear the changed files buffer
52
+ */
53
+ clearBuffer(): void;
54
+ }
55
+ //# sourceMappingURL=watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,aAAa,EAAE,CAAC,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IACnD,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uDAAuD;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,qBAAa,WAAW;IACpB,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,aAAa,CAA+B;IAEpD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsC;IACpE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;gBAE3B,OAAO,EAAE,cAAc;IAOnC;;OAEG;IACI,KAAK,IAAI,IAAI;IA4CpB;;;;;;;;;OASG;IACH,OAAO,CAAC,gBAAgB;IAkCxB;;OAEG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBlC;;OAEG;IACI,oBAAoB,IAAI,MAAM;IAIrC;;OAEG;IACI,WAAW,IAAI,IAAI;CAG7B"}
@@ -0,0 +1,122 @@
1
+ import chokidar from 'chokidar';
2
+ /**
3
+ * File watcher that monitors directory changes and triggers callbacks
4
+ * when a burst of changes occurs (≥5 files, no changes for ≥2000ms)
5
+ */
6
+ export class FileWatcher {
7
+ constructor(options) {
8
+ this.watcher = null;
9
+ this.changedFiles = new Set();
10
+ this.debounceTimer = null;
11
+ this.watchPath = options.watchPath;
12
+ this.onBurstChange = options.onBurstChange;
13
+ this.burstThreshold = options.burstThreshold ?? 5;
14
+ this.debounceDelay = options.debounceDelay ?? 2000;
15
+ }
16
+ /**
17
+ * Start watching the directory for file changes
18
+ */
19
+ start() {
20
+ this.watcher = chokidar.watch(this.watchPath, {
21
+ // Watch configuration
22
+ persistent: true,
23
+ ignoreInitial: true, // Don't trigger events for existing files on startup
24
+ // Ignored paths - use glob patterns
25
+ ignored: [
26
+ '**/node_modules/**',
27
+ '**/.git/**',
28
+ '**/dist/**',
29
+ '**/build/**',
30
+ '**/_tmp_*', // Temp files
31
+ '**/*.tmp', // Temp extensions
32
+ '**/pnpm-lock.yaml.*', // pnpm temp lock files
33
+ '**/package.json.*', // npm/pnpm temp package files
34
+ ],
35
+ });
36
+ // Handle file addition
37
+ this.watcher.on('add', (filePath) => {
38
+ this.handleFileChange(filePath, 'add');
39
+ });
40
+ // Handle file modification
41
+ this.watcher.on('change', (filePath) => {
42
+ this.handleFileChange(filePath, 'change');
43
+ });
44
+ // Handle file deletion
45
+ this.watcher.on('unlink', (filePath) => {
46
+ this.handleFileChange(filePath, 'unlink');
47
+ });
48
+ // Handle file rename - chokidar treats this as unlink (old) + add (new)
49
+ // We handle both events separately, so no special handling needed
50
+ // The rename effectively becomes two separate events in our changedFiles Set
51
+ // Error handling
52
+ this.watcher.on('error', (error) => {
53
+ console.error('Watcher error:', error);
54
+ });
55
+ }
56
+ /**
57
+ * Handle a file change event
58
+ * Debounce Logic:
59
+ * 1. Add the file path to the Set (automatically prevents duplicates)
60
+ * 2. Clear any existing debounce timer
61
+ * 3. Start a new timer
62
+ * 4. If timer expires (no new changes for debounceDelay ms):
63
+ * - Check if we have ≥ burstThreshold unique files
64
+ * - If yes, trigger the callback and reset the buffer
65
+ */
66
+ handleFileChange(filePath, eventType) {
67
+ // Debug: log individual file changes
68
+ console.log(` 📝 [${eventType}] ${filePath}`);
69
+ // Add file to the set of changed files (Set automatically prevents duplicates)
70
+ this.changedFiles.add(filePath);
71
+ // Clear the existing debounce timer if any
72
+ if (this.debounceTimer) {
73
+ clearTimeout(this.debounceTimer);
74
+ }
75
+ // Start a new debounce timer
76
+ this.debounceTimer = setTimeout(() => {
77
+ // Timer expired - no new changes for debounceDelay ms
78
+ // ALWAYS trigger callback if there are ANY changes
79
+ // Let the callback (smart detection in watch.ts) decide whether to snapshot
80
+ if (this.changedFiles.size > 0) {
81
+ // Create a copy of the changed files set for the callback
82
+ const filesSnapshot = new Set(this.changedFiles);
83
+ // Clear the buffer before triggering callback
84
+ this.changedFiles.clear();
85
+ // Trigger callback - smart detection will decide if snapshot needed
86
+ this.onBurstChange(filesSnapshot);
87
+ }
88
+ // Clear the timer reference
89
+ this.debounceTimer = null;
90
+ }, this.debounceDelay);
91
+ }
92
+ /**
93
+ * Stop watching and clean up resources
94
+ */
95
+ async stop() {
96
+ // Clear any pending debounce timer
97
+ if (this.debounceTimer) {
98
+ clearTimeout(this.debounceTimer);
99
+ this.debounceTimer = null;
100
+ }
101
+ // Close the watcher
102
+ if (this.watcher) {
103
+ await this.watcher.close();
104
+ this.watcher = null;
105
+ }
106
+ // Clear the changed files buffer
107
+ this.changedFiles.clear();
108
+ }
109
+ /**
110
+ * Get the current count of changed files in the buffer
111
+ */
112
+ getChangedFilesCount() {
113
+ return this.changedFiles.size;
114
+ }
115
+ /**
116
+ * Manually clear the changed files buffer
117
+ */
118
+ clearBuffer() {
119
+ this.changedFiles.clear();
120
+ }
121
+ }
122
+ //# sourceMappingURL=watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "undoai",
3
+ "version": "0.1.0-beta.1",
4
+ "description": "Free, local undo button for AI coding - automatic snapshots and instant restore",
5
+ "main": "dist/cli/index.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "undoai": "./dist/cli/index.js"
9
+ },
10
+ "files": [
11
+ "dist/",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "dev": "tsc --watch",
18
+ "start": "node dist/cli/index.js",
19
+ "test": "node dist/cli/index.js",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "keywords": [
23
+ "cli",
24
+ "undo",
25
+ "ai",
26
+ "snapshot",
27
+ "restore",
28
+ "mrq",
29
+ "cursor",
30
+ "vibe-coding",
31
+ "ai-safety",
32
+ "development-tools"
33
+ ],
34
+ "author": "",
35
+ "license": "MIT",
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "https://github.com/yourusername/undo-ai.git"
39
+ },
40
+ "bugs": {
41
+ "url": "https://github.com/yourusername/undo-ai/issues"
42
+ },
43
+ "homepage": "https://github.com/yourusername/undo-ai#readme",
44
+ "engines": {
45
+ "node": ">=18.0.0"
46
+ },
47
+ "dependencies": {
48
+ "chalk": "^5.6.2",
49
+ "chokidar": "^3.5.3",
50
+ "commander": "^14.0.2",
51
+ "minimatch": "^10.1.1"
52
+ },
53
+ "devDependencies": {
54
+ "@types/inquirer": "^9.0.9",
55
+ "@types/node": "^20.10.0",
56
+ "inquirer": "^9.3.8",
57
+ "typescript": "^5.3.0"
58
+ }
59
+ }