pushwork 1.0.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 (184) hide show
  1. package/README.md +460 -0
  2. package/dist/browser/browser-sync-engine.d.ts +64 -0
  3. package/dist/browser/browser-sync-engine.d.ts.map +1 -0
  4. package/dist/browser/browser-sync-engine.js +303 -0
  5. package/dist/browser/browser-sync-engine.js.map +1 -0
  6. package/dist/browser/filesystem-adapter.d.ts +84 -0
  7. package/dist/browser/filesystem-adapter.d.ts.map +1 -0
  8. package/dist/browser/filesystem-adapter.js +413 -0
  9. package/dist/browser/filesystem-adapter.js.map +1 -0
  10. package/dist/browser/index.d.ts +36 -0
  11. package/dist/browser/index.d.ts.map +1 -0
  12. package/dist/browser/index.js +90 -0
  13. package/dist/browser/index.js.map +1 -0
  14. package/dist/browser/types.d.ts +70 -0
  15. package/dist/browser/types.d.ts.map +1 -0
  16. package/dist/browser/types.js +6 -0
  17. package/dist/browser/types.js.map +1 -0
  18. package/dist/cli/commands.d.ts +71 -0
  19. package/dist/cli/commands.d.ts.map +1 -0
  20. package/dist/cli/commands.js +794 -0
  21. package/dist/cli/commands.js.map +1 -0
  22. package/dist/cli/index.d.ts +2 -0
  23. package/dist/cli/index.d.ts.map +1 -0
  24. package/dist/cli/index.js +19 -0
  25. package/dist/cli/index.js.map +1 -0
  26. package/dist/cli.d.ts +3 -0
  27. package/dist/cli.d.ts.map +1 -0
  28. package/dist/cli.js +199 -0
  29. package/dist/cli.js.map +1 -0
  30. package/dist/config/index.d.ts +71 -0
  31. package/dist/config/index.d.ts.map +1 -0
  32. package/dist/config/index.js +314 -0
  33. package/dist/config/index.js.map +1 -0
  34. package/dist/core/change-detection.d.ts +78 -0
  35. package/dist/core/change-detection.d.ts.map +1 -0
  36. package/dist/core/change-detection.js +370 -0
  37. package/dist/core/change-detection.js.map +1 -0
  38. package/dist/core/index.d.ts +5 -0
  39. package/dist/core/index.d.ts.map +1 -0
  40. package/dist/core/index.js +22 -0
  41. package/dist/core/index.js.map +1 -0
  42. package/dist/core/isomorphic-snapshot.d.ts +58 -0
  43. package/dist/core/isomorphic-snapshot.d.ts.map +1 -0
  44. package/dist/core/isomorphic-snapshot.js +204 -0
  45. package/dist/core/isomorphic-snapshot.js.map +1 -0
  46. package/dist/core/move-detection.d.ts +72 -0
  47. package/dist/core/move-detection.d.ts.map +1 -0
  48. package/dist/core/move-detection.js +200 -0
  49. package/dist/core/move-detection.js.map +1 -0
  50. package/dist/core/snapshot.d.ts +109 -0
  51. package/dist/core/snapshot.d.ts.map +1 -0
  52. package/dist/core/snapshot.js +263 -0
  53. package/dist/core/snapshot.js.map +1 -0
  54. package/dist/core/sync-engine.d.ts +110 -0
  55. package/dist/core/sync-engine.d.ts.map +1 -0
  56. package/dist/core/sync-engine.js +817 -0
  57. package/dist/core/sync-engine.js.map +1 -0
  58. package/dist/index.d.ts +6 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +27 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/platform/browser-filesystem.d.ts +26 -0
  63. package/dist/platform/browser-filesystem.d.ts.map +1 -0
  64. package/dist/platform/browser-filesystem.js +91 -0
  65. package/dist/platform/browser-filesystem.js.map +1 -0
  66. package/dist/platform/filesystem.d.ts +29 -0
  67. package/dist/platform/filesystem.d.ts.map +1 -0
  68. package/dist/platform/filesystem.js +65 -0
  69. package/dist/platform/filesystem.js.map +1 -0
  70. package/dist/platform/node-filesystem.d.ts +21 -0
  71. package/dist/platform/node-filesystem.d.ts.map +1 -0
  72. package/dist/platform/node-filesystem.js +93 -0
  73. package/dist/platform/node-filesystem.js.map +1 -0
  74. package/dist/types/config.d.ts +119 -0
  75. package/dist/types/config.d.ts.map +1 -0
  76. package/dist/types/config.js +3 -0
  77. package/dist/types/config.js.map +1 -0
  78. package/dist/types/documents.d.ts +70 -0
  79. package/dist/types/documents.d.ts.map +1 -0
  80. package/dist/types/documents.js +23 -0
  81. package/dist/types/documents.js.map +1 -0
  82. package/dist/types/index.d.ts +4 -0
  83. package/dist/types/index.d.ts.map +1 -0
  84. package/dist/types/index.js +23 -0
  85. package/dist/types/index.js.map +1 -0
  86. package/dist/types/snapshot.d.ts +81 -0
  87. package/dist/types/snapshot.d.ts.map +1 -0
  88. package/dist/types/snapshot.js +17 -0
  89. package/dist/types/snapshot.js.map +1 -0
  90. package/dist/utils/content-similarity.d.ts +53 -0
  91. package/dist/utils/content-similarity.d.ts.map +1 -0
  92. package/dist/utils/content-similarity.js +155 -0
  93. package/dist/utils/content-similarity.js.map +1 -0
  94. package/dist/utils/content.d.ts +5 -0
  95. package/dist/utils/content.d.ts.map +1 -0
  96. package/dist/utils/content.js +30 -0
  97. package/dist/utils/content.js.map +1 -0
  98. package/dist/utils/fs-browser.d.ts +57 -0
  99. package/dist/utils/fs-browser.d.ts.map +1 -0
  100. package/dist/utils/fs-browser.js +311 -0
  101. package/dist/utils/fs-browser.js.map +1 -0
  102. package/dist/utils/fs-node.d.ts +53 -0
  103. package/dist/utils/fs-node.d.ts.map +1 -0
  104. package/dist/utils/fs-node.js +220 -0
  105. package/dist/utils/fs-node.js.map +1 -0
  106. package/dist/utils/fs.d.ts +62 -0
  107. package/dist/utils/fs.d.ts.map +1 -0
  108. package/dist/utils/fs.js +293 -0
  109. package/dist/utils/fs.js.map +1 -0
  110. package/dist/utils/index.d.ts +4 -0
  111. package/dist/utils/index.d.ts.map +1 -0
  112. package/dist/utils/index.js +23 -0
  113. package/dist/utils/index.js.map +1 -0
  114. package/dist/utils/isomorphic.d.ts +29 -0
  115. package/dist/utils/isomorphic.d.ts.map +1 -0
  116. package/dist/utils/isomorphic.js +139 -0
  117. package/dist/utils/isomorphic.js.map +1 -0
  118. package/dist/utils/mime-types.d.ts +13 -0
  119. package/dist/utils/mime-types.d.ts.map +1 -0
  120. package/dist/utils/mime-types.js +240 -0
  121. package/dist/utils/mime-types.js.map +1 -0
  122. package/dist/utils/network-sync.d.ts +12 -0
  123. package/dist/utils/network-sync.d.ts.map +1 -0
  124. package/dist/utils/network-sync.js +149 -0
  125. package/dist/utils/network-sync.js.map +1 -0
  126. package/dist/utils/pure.d.ts +25 -0
  127. package/dist/utils/pure.d.ts.map +1 -0
  128. package/dist/utils/pure.js +112 -0
  129. package/dist/utils/pure.js.map +1 -0
  130. package/dist/utils/repo-factory.d.ts +11 -0
  131. package/dist/utils/repo-factory.d.ts.map +1 -0
  132. package/dist/utils/repo-factory.js +77 -0
  133. package/dist/utils/repo-factory.js.map +1 -0
  134. package/package.json +83 -0
  135. package/src/cli/commands.ts +1053 -0
  136. package/src/cli/index.ts +2 -0
  137. package/src/cli.ts +287 -0
  138. package/src/config/index.ts +334 -0
  139. package/src/core/change-detection.ts +484 -0
  140. package/src/core/index.ts +5 -0
  141. package/src/core/move-detection.ts +269 -0
  142. package/src/core/snapshot.ts +285 -0
  143. package/src/core/sync-engine.ts +1167 -0
  144. package/src/index.ts +14 -0
  145. package/src/types/config.ts +130 -0
  146. package/src/types/documents.ts +72 -0
  147. package/src/types/index.ts +8 -0
  148. package/src/types/snapshot.ts +88 -0
  149. package/src/utils/content-similarity.ts +194 -0
  150. package/src/utils/content.ts +28 -0
  151. package/src/utils/fs.ts +289 -0
  152. package/src/utils/index.ts +8 -0
  153. package/src/utils/mime-types.ts +236 -0
  154. package/src/utils/network-sync.ts +153 -0
  155. package/src/utils/repo-factory.ts +58 -0
  156. package/test/README-TESTING-GAPS.md +174 -0
  157. package/test/integration/README.md +328 -0
  158. package/test/integration/clone-test.sh +310 -0
  159. package/test/integration/conflict-resolution-test.sh +309 -0
  160. package/test/integration/deletion-behavior-test.sh +487 -0
  161. package/test/integration/deletion-sync-test-simple.sh +193 -0
  162. package/test/integration/deletion-sync-test.sh +297 -0
  163. package/test/integration/exclude-patterns.test.ts +152 -0
  164. package/test/integration/full-integration-test.sh +363 -0
  165. package/test/integration/sync-deletion.test.ts +339 -0
  166. package/test/integration/sync-flow.test.ts +309 -0
  167. package/test/run-tests.sh +225 -0
  168. package/test/unit/content-similarity.test.ts +236 -0
  169. package/test/unit/deletion-behavior.test.ts +260 -0
  170. package/test/unit/enhanced-mime-detection.test.ts +266 -0
  171. package/test/unit/snapshot.test.ts +431 -0
  172. package/test/unit/sync-timing.test.ts +178 -0
  173. package/test/unit/utils.test.ts +368 -0
  174. package/tools/browser-sync/README.md +116 -0
  175. package/tools/browser-sync/package.json +44 -0
  176. package/tools/browser-sync/patchwork.json +1 -0
  177. package/tools/browser-sync/pnpm-lock.yaml +4202 -0
  178. package/tools/browser-sync/src/components/BrowserSyncTool.tsx +599 -0
  179. package/tools/browser-sync/src/index.ts +20 -0
  180. package/tools/browser-sync/src/polyfills.ts +31 -0
  181. package/tools/browser-sync/src/styles.css +290 -0
  182. package/tools/browser-sync/src/types.ts +27 -0
  183. package/tools/browser-sync/vite.config.ts +25 -0
  184. package/tsconfig.json +22 -0
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ /**
3
+ * Isomorphic snapshot manager that works in both Node.js and browser
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.IsomorphicSnapshotManager = exports.IndexedDBSnapshotStorage = exports.FileSnapshotStorage = void 0;
7
+ const isomorphic_1 = require("../utils/isomorphic");
8
+ /**
9
+ * File-based snapshot storage (for Node.js and browser with file system access)
10
+ */
11
+ class FileSnapshotStorage {
12
+ constructor(rootPath) {
13
+ this.rootPath = rootPath;
14
+ }
15
+ getSnapshotPath(key = "current") {
16
+ return `${this.rootPath}/${FileSnapshotStorage.SYNC_TOOL_DIR}/${key}-${FileSnapshotStorage.SNAPSHOT_FILENAME}`;
17
+ }
18
+ getSyncToolDir() {
19
+ return `${this.rootPath}/${FileSnapshotStorage.SYNC_TOOL_DIR}`;
20
+ }
21
+ async save(snapshot, key = "current") {
22
+ await (0, isomorphic_1.ensureDirectoryExists)(this.getSyncToolDir());
23
+ const serializable = this.toSerializable(snapshot);
24
+ const content = JSON.stringify(serializable, null, 2);
25
+ await (0, isomorphic_1.writeFileContent)(this.getSnapshotPath(key), content);
26
+ }
27
+ async load(key = "current") {
28
+ const snapshotPath = this.getSnapshotPath(key);
29
+ if (!(await (0, isomorphic_1.pathExists)(snapshotPath))) {
30
+ return null;
31
+ }
32
+ try {
33
+ const content = await (0, isomorphic_1.readFileContent)(snapshotPath);
34
+ const contentStr = typeof content === "string"
35
+ ? content
36
+ : new TextDecoder().decode(content);
37
+ const serializable = JSON.parse(contentStr);
38
+ return this.fromSerializable(serializable);
39
+ }
40
+ catch (error) {
41
+ throw new Error(`Failed to load snapshot from ${snapshotPath}: ${error}`);
42
+ }
43
+ }
44
+ async backup(key = "current") {
45
+ const snapshot = await this.load(key);
46
+ if (snapshot) {
47
+ const backupKey = `${key}-backup-${Date.now()}`;
48
+ await this.save(snapshot, backupKey);
49
+ }
50
+ }
51
+ toSerializable(snapshot) {
52
+ return {
53
+ rootPath: snapshot.rootPath,
54
+ timestamp: new Date(snapshot.timestamp).toISOString(),
55
+ files: Array.from(snapshot.files.entries()),
56
+ directories: Array.from(snapshot.directories.entries()),
57
+ };
58
+ }
59
+ fromSerializable(serializable) {
60
+ return {
61
+ rootPath: serializable.rootPath,
62
+ timestamp: new Date(serializable.timestamp).getTime(),
63
+ files: new Map(serializable.files),
64
+ directories: new Map(serializable.directories),
65
+ };
66
+ }
67
+ }
68
+ exports.FileSnapshotStorage = FileSnapshotStorage;
69
+ FileSnapshotStorage.SNAPSHOT_FILENAME = "snapshot.json";
70
+ FileSnapshotStorage.SYNC_TOOL_DIR = ".pushwork";
71
+ /**
72
+ * IndexedDB-based snapshot storage (for browser environments)
73
+ */
74
+ class IndexedDBSnapshotStorage {
75
+ constructor() {
76
+ this.dbName = "pushwork-snapshots";
77
+ this.storeName = "snapshots";
78
+ this.version = 1;
79
+ }
80
+ async save(snapshot, key = "current") {
81
+ const db = await this.openDB();
82
+ const transaction = db.transaction([this.storeName], "readwrite");
83
+ const store = transaction.objectStore(this.storeName);
84
+ const serializable = this.toSerializable(snapshot);
85
+ const putRequest = store.put({
86
+ key,
87
+ snapshot: JSON.stringify(serializable),
88
+ timestamp: Date.now(),
89
+ });
90
+ await new Promise((resolve, reject) => {
91
+ putRequest.onsuccess = () => resolve(undefined);
92
+ putRequest.onerror = () => reject(putRequest.error);
93
+ });
94
+ db.close();
95
+ }
96
+ async load(key = "current") {
97
+ try {
98
+ const db = await this.openDB();
99
+ const transaction = db.transaction([this.storeName], "readonly");
100
+ const store = transaction.objectStore(this.storeName);
101
+ const request = store.get(key);
102
+ const result = await new Promise((resolve, reject) => {
103
+ request.onsuccess = () => resolve(request.result);
104
+ request.onerror = () => reject(request.error);
105
+ });
106
+ db.close();
107
+ if (result) {
108
+ const serializable = JSON.parse(result.snapshot);
109
+ return this.fromSerializable(serializable);
110
+ }
111
+ return null;
112
+ }
113
+ catch (error) {
114
+ console.warn("Failed to load snapshot from IndexedDB:", error);
115
+ return null;
116
+ }
117
+ }
118
+ async backup(key = "current") {
119
+ const snapshot = await this.load(key);
120
+ if (snapshot) {
121
+ await this.save(snapshot, `${key}-backup-${Date.now()}`);
122
+ }
123
+ }
124
+ async openDB() {
125
+ return new Promise((resolve, reject) => {
126
+ const request = indexedDB.open(this.dbName, this.version);
127
+ request.onerror = () => reject(request.error);
128
+ request.onsuccess = () => resolve(request.result);
129
+ request.onupgradeneeded = (event) => {
130
+ const db = event.target.result;
131
+ if (!db.objectStoreNames.contains(this.storeName)) {
132
+ db.createObjectStore(this.storeName, { keyPath: "key" });
133
+ }
134
+ };
135
+ });
136
+ }
137
+ toSerializable(snapshot) {
138
+ return {
139
+ rootPath: snapshot.rootPath,
140
+ timestamp: new Date(snapshot.timestamp).toISOString(),
141
+ files: Array.from(snapshot.files.entries()),
142
+ directories: Array.from(snapshot.directories.entries()),
143
+ };
144
+ }
145
+ fromSerializable(serializable) {
146
+ return {
147
+ rootPath: serializable.rootPath,
148
+ timestamp: new Date(serializable.timestamp).getTime(),
149
+ files: new Map(serializable.files),
150
+ directories: new Map(serializable.directories),
151
+ };
152
+ }
153
+ }
154
+ exports.IndexedDBSnapshotStorage = IndexedDBSnapshotStorage;
155
+ /**
156
+ * Isomorphic snapshot manager that uses appropriate storage for the platform
157
+ */
158
+ class IsomorphicSnapshotManager {
159
+ constructor(rootPath, useIndexedDB = false) {
160
+ if (useIndexedDB ||
161
+ (typeof window !== "undefined" && typeof indexedDB !== "undefined")) {
162
+ this.storage = new IndexedDBSnapshotStorage();
163
+ }
164
+ else {
165
+ this.storage = new FileSnapshotStorage(rootPath);
166
+ }
167
+ }
168
+ async save(snapshot) {
169
+ return this.storage.save(snapshot);
170
+ }
171
+ async load() {
172
+ return this.storage.load();
173
+ }
174
+ async backup() {
175
+ return this.storage.backup();
176
+ }
177
+ async createEmptySnapshot(rootPath) {
178
+ return {
179
+ rootPath,
180
+ timestamp: Date.now(),
181
+ files: new Map(),
182
+ directories: new Map(),
183
+ };
184
+ }
185
+ updateFileEntry(snapshot, relativePath, entry) {
186
+ snapshot.files.set(relativePath, entry);
187
+ }
188
+ updateDirectoryEntry(snapshot, relativePath, entry) {
189
+ snapshot.directories.set(relativePath, entry);
190
+ }
191
+ removeFileEntry(snapshot, relativePath) {
192
+ snapshot.files.delete(relativePath);
193
+ }
194
+ createEmpty() {
195
+ return {
196
+ rootPath: "",
197
+ timestamp: Date.now(),
198
+ files: new Map(),
199
+ directories: new Map(),
200
+ };
201
+ }
202
+ }
203
+ exports.IsomorphicSnapshotManager = IsomorphicSnapshotManager;
204
+ //# sourceMappingURL=isomorphic-snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isomorphic-snapshot.js","sourceRoot":"","sources":["../../src/core/isomorphic-snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ import { SyncSnapshot, MoveCandidate } from "../types";
2
+ import { DetectedChange } from "./change-detection";
3
+ /**
4
+ * Move detection engine
5
+ */
6
+ export declare class MoveDetector {
7
+ private static readonly AUTO_THRESHOLD;
8
+ private static readonly PROMPT_THRESHOLD;
9
+ /**
10
+ * Detect file moves by analyzing deleted and created files
11
+ */
12
+ detectMoves(changes: DetectedChange[], snapshot: SyncSnapshot, rootPath: string): Promise<{
13
+ moves: MoveCandidate[];
14
+ remainingChanges: DetectedChange[];
15
+ }>;
16
+ /**
17
+ * Get content of a deleted file from snapshot
18
+ */
19
+ private getDeletedFileContent;
20
+ /**
21
+ * Group moves by confidence level
22
+ */
23
+ groupMovesByConfidence(moves: MoveCandidate[]): {
24
+ autoMoves: MoveCandidate[];
25
+ promptMoves: MoveCandidate[];
26
+ lowConfidenceMoves: MoveCandidate[];
27
+ };
28
+ /**
29
+ * Validate move candidates to avoid conflicts
30
+ */
31
+ validateMoves(moves: MoveCandidate[]): {
32
+ validMoves: MoveCandidate[];
33
+ conflicts: Array<{
34
+ moves: MoveCandidate[];
35
+ reason: string;
36
+ }>;
37
+ };
38
+ /**
39
+ * Apply move detection heuristics
40
+ */
41
+ applyHeuristics(moves: MoveCandidate[]): MoveCandidate[];
42
+ /**
43
+ * Get directory path from file path
44
+ */
45
+ private getDirectoryPath;
46
+ /**
47
+ * Get file extension from file path
48
+ */
49
+ private getFileExtension;
50
+ /**
51
+ * Check if a move should be auto-applied
52
+ */
53
+ shouldAutoApply(move: MoveCandidate): boolean;
54
+ /**
55
+ * Check if a move should prompt the user
56
+ */
57
+ shouldPromptUser(move: MoveCandidate): boolean;
58
+ /**
59
+ * Format move for display
60
+ */
61
+ formatMove(move: MoveCandidate): string;
62
+ /**
63
+ * Calculate move statistics
64
+ */
65
+ calculateStats(moves: MoveCandidate[]): {
66
+ total: number;
67
+ auto: number;
68
+ prompt: number;
69
+ averageSimilarity: number;
70
+ };
71
+ }
72
+ //# sourceMappingURL=move-detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"move-detection.d.ts","sourceRoot":"","sources":["../../src/core/move-detection.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,aAAa,EAGd,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,cAAc,EAAc,MAAM,oBAAoB,CAAC;AAEhE;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAO;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAO;IAE/C;;OAEG;IACG,WAAW,CACf,OAAO,EAAE,cAAc,EAAE,EACzB,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAAC,gBAAgB,EAAE,cAAc,EAAE,CAAA;KAAE,CAAC;IA8E1E;;OAEG;YACW,qBAAqB;IAWnC;;OAEG;IACH,sBAAsB,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG;QAC9C,SAAS,EAAE,aAAa,EAAE,CAAC;QAC3B,WAAW,EAAE,aAAa,EAAE,CAAC;QAC7B,kBAAkB,EAAE,aAAa,EAAE,CAAC;KACrC;IAQD;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG;QACrC,UAAU,EAAE,aAAa,EAAE,CAAC;QAC5B,SAAS,EAAE,KAAK,CAAC;YAAE,KAAK,EAAE,aAAa,EAAE,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC9D;IA4CD;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,aAAa,EAAE;IAwBxD;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAKxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO;IAI7C;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO;IAI9C;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM;IAKvC;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG;QACtC,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,iBAAiB,EAAE,MAAM,CAAC;KAC3B;CASF"}
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MoveDetector = void 0;
4
+ const utils_1 = require("../utils");
5
+ const change_detection_1 = require("./change-detection");
6
+ /**
7
+ * Move detection engine
8
+ */
9
+ class MoveDetector {
10
+ /**
11
+ * Detect file moves by analyzing deleted and created files
12
+ */
13
+ async detectMoves(changes, snapshot, rootPath) {
14
+ // Separate deletions and creations
15
+ const deletedFiles = changes.filter((c) => !c.localContent && c.changeType === change_detection_1.ChangeType.LOCAL_ONLY);
16
+ const createdFiles = changes.filter((c) => c.localContent &&
17
+ c.changeType === change_detection_1.ChangeType.LOCAL_ONLY &&
18
+ !snapshot.files.has(c.path));
19
+ if (deletedFiles.length === 0 || createdFiles.length === 0) {
20
+ return { moves: [], remainingChanges: changes };
21
+ }
22
+ const moves = [];
23
+ const usedCreations = new Set();
24
+ const usedDeletions = new Set();
25
+ // Find potential moves by comparing content
26
+ for (const deletedFile of deletedFiles) {
27
+ const deletedContent = await this.getDeletedFileContent(deletedFile, snapshot);
28
+ if (!deletedContent)
29
+ continue;
30
+ let bestMatch = null;
31
+ for (const createdFile of createdFiles) {
32
+ if (usedCreations.has(createdFile.path))
33
+ continue;
34
+ if (!createdFile.localContent)
35
+ continue;
36
+ const similarity = await utils_1.ContentSimilarity.calculateSimilarity(deletedContent, createdFile.localContent);
37
+ if (similarity >= MoveDetector.PROMPT_THRESHOLD) {
38
+ if (!bestMatch || similarity > bestMatch.similarity) {
39
+ bestMatch = { file: createdFile, similarity };
40
+ }
41
+ }
42
+ }
43
+ if (bestMatch) {
44
+ const confidence = utils_1.ContentSimilarity.getConfidenceLevel(bestMatch.similarity);
45
+ // Always report the potential move (for logging/prompting)
46
+ moves.push({
47
+ fromPath: deletedFile.path,
48
+ toPath: bestMatch.file.path,
49
+ similarity: bestMatch.similarity,
50
+ confidence,
51
+ });
52
+ // Only consume the deletion/creation pair when we would auto-apply the move.
53
+ // If we only want to prompt, leave the original changes in place so
54
+ // sync can still proceed as delete+create (avoids infinite warning loop).
55
+ if (bestMatch.similarity >= MoveDetector.AUTO_THRESHOLD) {
56
+ usedCreations.add(bestMatch.file.path);
57
+ usedDeletions.add(deletedFile.path);
58
+ }
59
+ }
60
+ }
61
+ // Filter out changes that are part of moves
62
+ const remainingChanges = changes.filter((change) => !usedCreations.has(change.path) && !usedDeletions.has(change.path));
63
+ return { moves, remainingChanges };
64
+ }
65
+ /**
66
+ * Get content of a deleted file from snapshot
67
+ */
68
+ async getDeletedFileContent(deletedFile, snapshot) {
69
+ const snapshotEntry = snapshot.files.get(deletedFile.path);
70
+ if (!snapshotEntry)
71
+ return null;
72
+ // Return remote content if available, otherwise null
73
+ return deletedFile.remoteContent || null;
74
+ }
75
+ /**
76
+ * Group moves by confidence level
77
+ */
78
+ groupMovesByConfidence(moves) {
79
+ const autoMoves = moves.filter((m) => m.confidence === "auto");
80
+ const promptMoves = moves.filter((m) => m.confidence === "prompt");
81
+ const lowConfidenceMoves = moves.filter((m) => m.confidence === "low");
82
+ return { autoMoves, promptMoves, lowConfidenceMoves };
83
+ }
84
+ /**
85
+ * Validate move candidates to avoid conflicts
86
+ */
87
+ validateMoves(moves) {
88
+ const validMoves = [];
89
+ const conflicts = [];
90
+ // Check for multiple sources mapping to same destination
91
+ const destinationMap = new Map();
92
+ for (const move of moves) {
93
+ if (!destinationMap.has(move.toPath)) {
94
+ destinationMap.set(move.toPath, []);
95
+ }
96
+ destinationMap.get(move.toPath).push(move);
97
+ }
98
+ // Check for multiple destinations from same source
99
+ const sourceMap = new Map();
100
+ for (const move of moves) {
101
+ if (!sourceMap.has(move.fromPath)) {
102
+ sourceMap.set(move.fromPath, []);
103
+ }
104
+ sourceMap.get(move.fromPath).push(move);
105
+ }
106
+ for (const move of moves) {
107
+ const destinationConflicts = destinationMap.get(move.toPath);
108
+ const sourceConflicts = sourceMap.get(move.fromPath);
109
+ if (destinationConflicts.length > 1) {
110
+ conflicts.push({
111
+ moves: destinationConflicts,
112
+ reason: `Multiple files moving to ${move.toPath}`,
113
+ });
114
+ }
115
+ else if (sourceConflicts.length > 1) {
116
+ conflicts.push({
117
+ moves: sourceConflicts,
118
+ reason: `File ${move.fromPath} has multiple potential destinations`,
119
+ });
120
+ }
121
+ else {
122
+ validMoves.push(move);
123
+ }
124
+ }
125
+ return { validMoves, conflicts };
126
+ }
127
+ /**
128
+ * Apply move detection heuristics
129
+ */
130
+ applyHeuristics(moves) {
131
+ return moves
132
+ .filter((move) => {
133
+ // Filter out moves within the same directory unless similarity is very high
134
+ const fromDir = this.getDirectoryPath(move.fromPath);
135
+ const toDir = this.getDirectoryPath(move.toPath);
136
+ if (fromDir === toDir && move.similarity < 0.9) {
137
+ return false;
138
+ }
139
+ // Filter out moves with very different file extensions unless similarity is perfect
140
+ const fromExt = this.getFileExtension(move.fromPath);
141
+ const toExt = this.getFileExtension(move.toPath);
142
+ if (fromExt !== toExt && move.similarity < 1.0) {
143
+ return false;
144
+ }
145
+ return true;
146
+ })
147
+ .sort((a, b) => b.similarity - a.similarity); // Sort by similarity descending
148
+ }
149
+ /**
150
+ * Get directory path from file path
151
+ */
152
+ getDirectoryPath(filePath) {
153
+ const lastSlash = filePath.lastIndexOf("/");
154
+ return lastSlash >= 0 ? filePath.substring(0, lastSlash) : "";
155
+ }
156
+ /**
157
+ * Get file extension from file path
158
+ */
159
+ getFileExtension(filePath) {
160
+ const lastDot = filePath.lastIndexOf(".");
161
+ const lastSlash = filePath.lastIndexOf("/");
162
+ if (lastDot > lastSlash && lastDot >= 0) {
163
+ return filePath.substring(lastDot + 1).toLowerCase();
164
+ }
165
+ return "";
166
+ }
167
+ /**
168
+ * Check if a move should be auto-applied
169
+ */
170
+ shouldAutoApply(move) {
171
+ return move.confidence === "auto";
172
+ }
173
+ /**
174
+ * Check if a move should prompt the user
175
+ */
176
+ shouldPromptUser(move) {
177
+ return move.confidence === "prompt";
178
+ }
179
+ /**
180
+ * Format move for display
181
+ */
182
+ formatMove(move) {
183
+ const percentage = Math.round(move.similarity * 100);
184
+ return `${move.fromPath} → ${move.toPath} (${percentage}% similar)`;
185
+ }
186
+ /**
187
+ * Calculate move statistics
188
+ */
189
+ calculateStats(moves) {
190
+ const total = moves.length;
191
+ const auto = moves.filter((m) => m.confidence === "auto").length;
192
+ const prompt = moves.filter((m) => m.confidence === "prompt").length;
193
+ const averageSimilarity = total > 0 ? moves.reduce((sum, m) => sum + m.similarity, 0) / total : 0;
194
+ return { total, auto, prompt, averageSimilarity };
195
+ }
196
+ }
197
+ exports.MoveDetector = MoveDetector;
198
+ MoveDetector.AUTO_THRESHOLD = 0.8;
199
+ MoveDetector.PROMPT_THRESHOLD = 0.5;
200
+ //# sourceMappingURL=move-detection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"move-detection.js","sourceRoot":"","sources":["../../src/core/move-detection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * pvh TODO: the files & directories could be unified into a single map of entries with a type field
3
+ */
4
+ import { SyncSnapshot, SnapshotFileEntry, SnapshotDirectoryEntry } from "../types";
5
+ /**
6
+ * Manages sync snapshots for local state tracking
7
+ */
8
+ export declare class SnapshotManager {
9
+ private rootPath;
10
+ private static readonly SNAPSHOT_FILENAME;
11
+ private static readonly SYNC_TOOL_DIR;
12
+ constructor(rootPath: string);
13
+ /**
14
+ * Get path to sync tool directory
15
+ */
16
+ private getSyncToolDir;
17
+ /**
18
+ * Get path to snapshot file
19
+ */
20
+ private getSnapshotPath;
21
+ /**
22
+ * Check if snapshot exists
23
+ */
24
+ exists(): Promise<boolean>;
25
+ /**
26
+ * Load snapshot from disk
27
+ */
28
+ load(): Promise<SyncSnapshot | null>;
29
+ /**
30
+ * Save snapshot to disk
31
+ */
32
+ save(snapshot: SyncSnapshot): Promise<void>;
33
+ /**
34
+ * Create empty snapshot
35
+ */
36
+ createEmpty(): SyncSnapshot;
37
+ /**
38
+ * Update file entry in snapshot
39
+ */
40
+ updateFileEntry(snapshot: SyncSnapshot, relativePath: string, entry: SnapshotFileEntry): void;
41
+ /**
42
+ * Update directory entry in snapshot
43
+ */
44
+ updateDirectoryEntry(snapshot: SyncSnapshot, relativePath: string, entry: SnapshotDirectoryEntry): void;
45
+ /**
46
+ * Remove file entry from snapshot
47
+ */
48
+ removeFileEntry(snapshot: SyncSnapshot, relativePath: string): void;
49
+ /**
50
+ * Remove directory entry from snapshot
51
+ */
52
+ removeDirectoryEntry(snapshot: SyncSnapshot, relativePath: string): void;
53
+ /**
54
+ * Get all file paths in snapshot
55
+ */
56
+ getFilePaths(snapshot: SyncSnapshot): string[];
57
+ /**
58
+ * Get all directory paths in snapshot
59
+ */
60
+ getDirectoryPaths(snapshot: SyncSnapshot): string[];
61
+ /**
62
+ * Get file entry by path
63
+ */
64
+ getFileEntry(snapshot: SyncSnapshot, relativePath: string): SnapshotFileEntry | undefined;
65
+ /**
66
+ * Get directory entry by path
67
+ */
68
+ getDirectoryEntry(snapshot: SyncSnapshot, relativePath: string): SnapshotDirectoryEntry | undefined;
69
+ /**
70
+ * Check if path is tracked in snapshot
71
+ */
72
+ isTracked(snapshot: SyncSnapshot, relativePath: string): boolean;
73
+ /**
74
+ * Get snapshot statistics
75
+ */
76
+ getStats(snapshot: SyncSnapshot): {
77
+ files: number;
78
+ directories: number;
79
+ timestamp: Date;
80
+ };
81
+ /**
82
+ * Backup current snapshot
83
+ */
84
+ backup(): Promise<void>;
85
+ /**
86
+ * Validate snapshot integrity
87
+ */
88
+ validate(snapshot: SyncSnapshot): {
89
+ valid: boolean;
90
+ errors: string[];
91
+ };
92
+ /**
93
+ * Convert snapshot to serializable format
94
+ */
95
+ private serializeSnapshot;
96
+ /**
97
+ * Convert serializable format back to snapshot
98
+ */
99
+ private deserializeSnapshot;
100
+ /**
101
+ * Clear all snapshot data
102
+ */
103
+ clear(snapshot: SyncSnapshot): void;
104
+ /**
105
+ * Clone snapshot for safe manipulation
106
+ */
107
+ clone(snapshot: SyncSnapshot): SyncSnapshot;
108
+ }
109
+ //# sourceMappingURL=snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/core/snapshot.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EACL,YAAY,EAEZ,iBAAiB,EACjB,sBAAsB,EACvB,MAAM,UAAU,CAAC;AAGlB;;GAEG;AACH,qBAAa,eAAe;IAId,OAAO,CAAC,QAAQ;IAH5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAmB;IAC5D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAe;gBAEhC,QAAQ,EAAE,MAAM;IAEpC;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACH,OAAO,CAAC,eAAe;IAIvB;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAIhC;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAiB1C;;OAEG;IACG,IAAI,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAajD;;OAEG;IACH,WAAW,IAAI,YAAY;IAU3B;;OAEG;IACH,eAAe,CACb,QAAQ,EAAE,YAAY,EACtB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,iBAAiB,GACvB,IAAI;IAKP;;OAEG;IACH,oBAAoB,CAClB,QAAQ,EAAE,YAAY,EACtB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,sBAAsB,GAC5B,IAAI;IAKP;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAKnE;;OAEG;IACH,oBAAoB,CAAC,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAKxE;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,EAAE;IAI9C;;OAEG;IACH,iBAAiB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,EAAE;IAInD;;OAEG;IACH,YAAY,CACV,QAAQ,EAAE,YAAY,EACtB,YAAY,EAAE,MAAM,GACnB,iBAAiB,GAAG,SAAS;IAIhC;;OAEG;IACH,iBAAiB,CACf,QAAQ,EAAE,YAAY,EACtB,YAAY,EAAE,MAAM,GACnB,sBAAsB,GAAG,SAAS;IAIrC;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO;IAMhE;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG;QAChC,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,IAAI,CAAC;KACjB;IAQD;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ7B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;IA8BtE;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAUzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAY3B;;OAEG;IACH,KAAK,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;IAMnC;;OAEG;IACH,KAAK,CAAC,QAAQ,EAAE,YAAY,GAAG,YAAY;CAS5C"}