pushwork 1.0.4 → 1.0.7

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 (195) hide show
  1. package/README.md +87 -328
  2. package/dist/.pushwork/automerge/3P/Dm3ekE2pmjGnWvDaG3vSR7ww98/snapshot/aa2349c94955ea561f698720142f9d884a6872d9f82dc332d578c216beb0df0e +0 -0
  3. package/dist/.pushwork/automerge/st/orage-adapter-id +1 -0
  4. package/dist/.pushwork/config.json +15 -0
  5. package/dist/.pushwork/snapshot.json +7 -0
  6. package/dist/cli.js +231 -170
  7. package/dist/cli.js.map +1 -1
  8. package/dist/commands.d.ts +51 -0
  9. package/dist/commands.d.ts.map +1 -0
  10. package/dist/commands.js +799 -0
  11. package/dist/commands.js.map +1 -0
  12. package/dist/core/change-detection.d.ts +6 -19
  13. package/dist/core/change-detection.d.ts.map +1 -1
  14. package/dist/core/change-detection.js +101 -80
  15. package/dist/core/change-detection.js.map +1 -1
  16. package/dist/{config/index.d.ts → core/config.d.ts} +13 -3
  17. package/dist/core/config.d.ts.map +1 -0
  18. package/dist/{config/index.js → core/config.js} +55 -73
  19. package/dist/core/config.js.map +1 -0
  20. package/dist/core/index.d.ts +1 -0
  21. package/dist/core/index.d.ts.map +1 -1
  22. package/dist/core/index.js +1 -1
  23. package/dist/core/index.js.map +1 -1
  24. package/dist/core/move-detection.d.ts +12 -50
  25. package/dist/core/move-detection.d.ts.map +1 -1
  26. package/dist/core/move-detection.js +58 -139
  27. package/dist/core/move-detection.js.map +1 -1
  28. package/dist/core/snapshot.d.ts +0 -4
  29. package/dist/core/snapshot.d.ts.map +1 -1
  30. package/dist/core/snapshot.js +2 -11
  31. package/dist/core/snapshot.js.map +1 -1
  32. package/dist/core/sync-engine.d.ts +5 -11
  33. package/dist/core/sync-engine.d.ts.map +1 -1
  34. package/dist/core/sync-engine.js +220 -362
  35. package/dist/core/sync-engine.js.map +1 -1
  36. package/dist/index.d.ts +0 -1
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +0 -6
  39. package/dist/index.js.map +1 -1
  40. package/dist/types/config.d.ts +43 -67
  41. package/dist/types/config.d.ts.map +1 -1
  42. package/dist/types/config.js +6 -0
  43. package/dist/types/config.js.map +1 -1
  44. package/dist/types/documents.d.ts +15 -3
  45. package/dist/types/documents.d.ts.map +1 -1
  46. package/dist/types/documents.js.map +1 -1
  47. package/dist/types/index.d.ts.map +1 -1
  48. package/dist/types/index.js +0 -3
  49. package/dist/types/index.js.map +1 -1
  50. package/dist/types/snapshot.d.ts +3 -21
  51. package/dist/types/snapshot.d.ts.map +1 -1
  52. package/dist/types/snapshot.js +0 -14
  53. package/dist/types/snapshot.js.map +1 -1
  54. package/dist/utils/content.d.ts.map +1 -1
  55. package/dist/utils/content.js +2 -6
  56. package/dist/utils/content.js.map +1 -1
  57. package/dist/utils/directory.d.ts +10 -0
  58. package/dist/utils/directory.d.ts.map +1 -0
  59. package/dist/utils/directory.js +37 -0
  60. package/dist/utils/directory.js.map +1 -0
  61. package/dist/utils/fs.d.ts +15 -2
  62. package/dist/utils/fs.d.ts.map +1 -1
  63. package/dist/utils/fs.js +63 -53
  64. package/dist/utils/fs.js.map +1 -1
  65. package/dist/utils/index.d.ts +1 -1
  66. package/dist/utils/index.d.ts.map +1 -1
  67. package/dist/utils/index.js +1 -4
  68. package/dist/utils/index.js.map +1 -1
  69. package/dist/utils/mime-types.d.ts.map +1 -1
  70. package/dist/utils/mime-types.js +11 -4
  71. package/dist/utils/mime-types.js.map +1 -1
  72. package/dist/utils/network-sync.d.ts +0 -6
  73. package/dist/utils/network-sync.d.ts.map +1 -1
  74. package/dist/utils/network-sync.js +55 -99
  75. package/dist/utils/network-sync.js.map +1 -1
  76. package/dist/utils/output.d.ts +129 -0
  77. package/dist/utils/output.d.ts.map +1 -0
  78. package/dist/utils/output.js +375 -0
  79. package/dist/utils/output.js.map +1 -0
  80. package/dist/utils/repo-factory.d.ts +2 -6
  81. package/dist/utils/repo-factory.d.ts.map +1 -1
  82. package/dist/utils/repo-factory.js +8 -22
  83. package/dist/utils/repo-factory.js.map +1 -1
  84. package/dist/utils/string-similarity.d.ts +14 -0
  85. package/dist/utils/string-similarity.d.ts.map +1 -0
  86. package/dist/utils/string-similarity.js +43 -0
  87. package/dist/utils/string-similarity.js.map +1 -0
  88. package/dist/utils/trace.d.ts +19 -0
  89. package/dist/utils/trace.d.ts.map +1 -0
  90. package/dist/utils/trace.js +68 -0
  91. package/dist/utils/trace.js.map +1 -0
  92. package/package.json +17 -12
  93. package/src/cli.ts +326 -252
  94. package/src/commands.ts +988 -0
  95. package/src/core/change-detection.ts +199 -162
  96. package/src/{config/index.ts → core/config.ts} +65 -82
  97. package/src/core/index.ts +1 -1
  98. package/src/core/move-detection.ts +74 -180
  99. package/src/core/snapshot.ts +2 -12
  100. package/src/core/sync-engine.ts +248 -499
  101. package/src/index.ts +0 -10
  102. package/src/types/config.ts +50 -72
  103. package/src/types/documents.ts +16 -3
  104. package/src/types/index.ts +0 -5
  105. package/src/types/snapshot.ts +1 -23
  106. package/src/utils/content.ts +2 -6
  107. package/src/utils/directory.ts +50 -0
  108. package/src/utils/fs.ts +67 -56
  109. package/src/utils/index.ts +1 -6
  110. package/src/utils/mime-types.ts +12 -4
  111. package/src/utils/network-sync.ts +79 -137
  112. package/src/utils/output.ts +450 -0
  113. package/src/utils/repo-factory.ts +13 -31
  114. package/src/utils/string-similarity.ts +54 -0
  115. package/src/utils/trace.ts +70 -0
  116. package/test/integration/exclude-patterns.test.ts +6 -15
  117. package/test/integration/fuzzer.test.ts +308 -391
  118. package/test/integration/init-sync.test.ts +89 -0
  119. package/test/integration/sync-deletion.test.ts +2 -61
  120. package/test/integration/sync-flow.test.ts +4 -24
  121. package/test/jest.setup.ts +34 -0
  122. package/test/unit/deletion-behavior.test.ts +3 -14
  123. package/test/unit/enhanced-mime-detection.test.ts +0 -22
  124. package/test/unit/snapshot.test.ts +2 -29
  125. package/test/unit/sync-convergence.test.ts +3 -198
  126. package/test/unit/sync-timing.test.ts +0 -44
  127. package/test/unit/utils.test.ts +0 -2
  128. package/tsconfig.json +3 -3
  129. package/dist/browser/browser-sync-engine.d.ts +0 -64
  130. package/dist/browser/browser-sync-engine.d.ts.map +0 -1
  131. package/dist/browser/browser-sync-engine.js +0 -303
  132. package/dist/browser/browser-sync-engine.js.map +0 -1
  133. package/dist/browser/filesystem-adapter.d.ts +0 -84
  134. package/dist/browser/filesystem-adapter.d.ts.map +0 -1
  135. package/dist/browser/filesystem-adapter.js +0 -413
  136. package/dist/browser/filesystem-adapter.js.map +0 -1
  137. package/dist/browser/index.d.ts +0 -36
  138. package/dist/browser/index.d.ts.map +0 -1
  139. package/dist/browser/index.js +0 -90
  140. package/dist/browser/index.js.map +0 -1
  141. package/dist/browser/types.d.ts +0 -70
  142. package/dist/browser/types.d.ts.map +0 -1
  143. package/dist/browser/types.js +0 -6
  144. package/dist/browser/types.js.map +0 -1
  145. package/dist/cli/commands.d.ts +0 -77
  146. package/dist/cli/commands.d.ts.map +0 -1
  147. package/dist/cli/commands.js +0 -904
  148. package/dist/cli/commands.js.map +0 -1
  149. package/dist/cli/index.d.ts +0 -2
  150. package/dist/cli/index.d.ts.map +0 -1
  151. package/dist/cli/index.js +0 -19
  152. package/dist/cli/index.js.map +0 -1
  153. package/dist/config/index.d.ts.map +0 -1
  154. package/dist/config/index.js.map +0 -1
  155. package/dist/core/isomorphic-snapshot.d.ts +0 -58
  156. package/dist/core/isomorphic-snapshot.d.ts.map +0 -1
  157. package/dist/core/isomorphic-snapshot.js +0 -204
  158. package/dist/core/isomorphic-snapshot.js.map +0 -1
  159. package/dist/platform/browser-filesystem.d.ts +0 -26
  160. package/dist/platform/browser-filesystem.d.ts.map +0 -1
  161. package/dist/platform/browser-filesystem.js +0 -91
  162. package/dist/platform/browser-filesystem.js.map +0 -1
  163. package/dist/platform/filesystem.d.ts +0 -29
  164. package/dist/platform/filesystem.d.ts.map +0 -1
  165. package/dist/platform/filesystem.js +0 -65
  166. package/dist/platform/filesystem.js.map +0 -1
  167. package/dist/platform/node-filesystem.d.ts +0 -21
  168. package/dist/platform/node-filesystem.d.ts.map +0 -1
  169. package/dist/platform/node-filesystem.js +0 -93
  170. package/dist/platform/node-filesystem.js.map +0 -1
  171. package/dist/utils/content-similarity.d.ts +0 -53
  172. package/dist/utils/content-similarity.d.ts.map +0 -1
  173. package/dist/utils/content-similarity.js +0 -155
  174. package/dist/utils/content-similarity.js.map +0 -1
  175. package/dist/utils/fs-browser.d.ts +0 -57
  176. package/dist/utils/fs-browser.d.ts.map +0 -1
  177. package/dist/utils/fs-browser.js +0 -311
  178. package/dist/utils/fs-browser.js.map +0 -1
  179. package/dist/utils/fs-node.d.ts +0 -53
  180. package/dist/utils/fs-node.d.ts.map +0 -1
  181. package/dist/utils/fs-node.js +0 -220
  182. package/dist/utils/fs-node.js.map +0 -1
  183. package/dist/utils/isomorphic.d.ts +0 -29
  184. package/dist/utils/isomorphic.d.ts.map +0 -1
  185. package/dist/utils/isomorphic.js +0 -139
  186. package/dist/utils/isomorphic.js.map +0 -1
  187. package/dist/utils/pure.d.ts +0 -25
  188. package/dist/utils/pure.d.ts.map +0 -1
  189. package/dist/utils/pure.js +0 -112
  190. package/dist/utils/pure.js.map +0 -1
  191. package/src/cli/commands.ts +0 -1207
  192. package/src/cli/index.ts +0 -2
  193. package/src/utils/content-similarity.ts +0 -194
  194. package/test/README-TESTING-GAPS.md +0 -174
  195. package/test/unit/content-similarity.test.ts +0 -236
@@ -0,0 +1,89 @@
1
+ import * as fs from "fs/promises";
2
+ import * as path from "path";
3
+ import * as tmp from "tmp";
4
+ import { execSync } from "child_process";
5
+ import { SnapshotManager } from "../../src/core";
6
+
7
+ describe("Init Command Integration", () => {
8
+ let tmpDir: string;
9
+ let cleanup: () => void;
10
+ const pushworkCmd = `node "${path.join(__dirname, "../../dist/cli.js")}"`;
11
+
12
+ beforeAll(() => {
13
+ // Build the project before running tests
14
+ execSync("pnpm build", { cwd: path.join(__dirname, "../.."), stdio: "pipe" });
15
+ });
16
+
17
+ beforeEach(() => {
18
+ const tmpObj = tmp.dirSync({ unsafeCleanup: true });
19
+ tmpDir = tmpObj.name;
20
+ cleanup = tmpObj.removeCallback;
21
+ });
22
+
23
+ afterEach(async () => {
24
+ cleanup();
25
+ });
26
+
27
+ describe("Initial Sync", () => {
28
+ it("should sync existing files during init", async () => {
29
+ // Create some files before initializing
30
+ await fs.writeFile(path.join(tmpDir, "file1.txt"), "Hello, World!");
31
+ await fs.writeFile(path.join(tmpDir, "file2.txt"), "Another file");
32
+ await fs.mkdir(path.join(tmpDir, "subdir"));
33
+ await fs.writeFile(
34
+ path.join(tmpDir, "subdir", "nested.txt"),
35
+ "Nested content"
36
+ );
37
+
38
+ // Run pushwork init
39
+ execSync(`${pushworkCmd} init "${tmpDir}"`, { stdio: "pipe" });
40
+
41
+ // Verify snapshot was created with file entries
42
+ const snapshotManager = new SnapshotManager(tmpDir);
43
+ const snapshot = await snapshotManager.load();
44
+ expect(snapshot).not.toBeNull();
45
+ expect(snapshot!.files.size).toBeGreaterThanOrEqual(3);
46
+ expect(snapshot!.files.has("file1.txt")).toBe(true);
47
+ expect(snapshot!.files.has("file2.txt")).toBe(true);
48
+ expect(snapshot!.files.has("subdir/nested.txt")).toBe(true);
49
+ });
50
+
51
+ it("should handle empty directory during init", async () => {
52
+ // Run pushwork init on empty directory
53
+ execSync(`${pushworkCmd} init "${tmpDir}"`, { stdio: "pipe" });
54
+
55
+ // Verify snapshot was created (even if empty)
56
+ const snapshotManager = new SnapshotManager(tmpDir);
57
+ const snapshot = await snapshotManager.load();
58
+ expect(snapshot).not.toBeNull();
59
+ expect(snapshot!.files.size).toBe(0);
60
+ });
61
+
62
+ it("should respect exclude patterns during initial sync", async () => {
63
+ // Create files, including some that should be excluded by default
64
+ await fs.writeFile(path.join(tmpDir, "included.txt"), "Include me");
65
+ await fs.mkdir(path.join(tmpDir, "node_modules"));
66
+ await fs.writeFile(
67
+ path.join(tmpDir, "node_modules", "package.json"),
68
+ "{}"
69
+ );
70
+ await fs.mkdir(path.join(tmpDir, ".git"));
71
+ await fs.writeFile(
72
+ path.join(tmpDir, ".git", "config"),
73
+ "[core]"
74
+ );
75
+
76
+ // Run pushwork init
77
+ execSync(`${pushworkCmd} init "${tmpDir}"`, { stdio: "pipe" });
78
+
79
+ // Verify snapshot only contains included file
80
+ const snapshotManager = new SnapshotManager(tmpDir);
81
+ const snapshot = await snapshotManager.load();
82
+ expect(snapshot).not.toBeNull();
83
+ expect(snapshot!.files.has("included.txt")).toBe(true);
84
+ // node_modules and .git should be excluded by default
85
+ expect(snapshot!.files.has("node_modules/package.json")).toBe(false);
86
+ expect(snapshot!.files.has(".git/config")).toBe(false);
87
+ });
88
+ });
89
+ });
@@ -8,8 +8,6 @@ import {
8
8
  pathExists,
9
9
  } from "../../src/utils";
10
10
  import { SnapshotManager } from "../../src/core/snapshot";
11
- import { ChangeDetector } from "../../src/core/change-detection";
12
- import { ChangeType } from "../../src/types";
13
11
 
14
12
  describe("Sync Engine Deletion Integration", () => {
15
13
  let testDir: string;
@@ -26,8 +24,6 @@ describe("Sync Engine Deletion Integration", () => {
26
24
 
27
25
  describe("Deletion Detection Logic", () => {
28
26
  it("should properly detect local file deletions", async () => {
29
- console.log("\n🧪 Testing Local File Deletion Detection");
30
-
31
27
  // Create initial state
32
28
  const filePath = path.join(testDir, "will-be-deleted.ts");
33
29
  const content = "interface ToDelete { id: number; }";
@@ -43,27 +39,19 @@ describe("Sync Engine Deletion Integration", () => {
43
39
  mimeType: "text/typescript",
44
40
  });
45
41
 
46
- console.log(`📄 Created file: ${filePath}`);
47
- console.log(`📸 Snapshot has ${snapshot.files.size} files`);
48
-
49
42
  // Verify initial state
50
43
  expect(await pathExists(filePath)).toBe(true);
51
44
  expect(snapshot.files.has("will-be-deleted.ts")).toBe(true);
52
45
 
53
46
  // Simulate user deleting the file
54
47
  await removePath(filePath);
55
- console.log(`🗑️ File deleted from filesystem`);
56
48
 
57
49
  // File should be gone from filesystem but still in snapshot
58
50
  expect(await pathExists(filePath)).toBe(false);
59
51
  expect(snapshot.files.has("will-be-deleted.ts")).toBe(true);
60
-
61
- console.log(`✅ Deletion properly detected`);
62
52
  });
63
53
 
64
54
  it("should handle multiple file deletions correctly", async () => {
65
- console.log("\n🧪 Testing Multiple File Deletions");
66
-
67
55
  const testFiles = [
68
56
  { name: "delete1.ts", content: "interface One { x: number; }" },
69
57
  { name: "delete2.js", content: "const two = 'value';" },
@@ -86,8 +74,6 @@ describe("Sync Engine Deletion Integration", () => {
86
74
  ? "text/typescript"
87
75
  : "text/plain",
88
76
  });
89
-
90
- console.log(`📄 Created: ${file.name}`);
91
77
  }
92
78
 
93
79
  expect(snapshot.files.size).toBe(3);
@@ -96,7 +82,6 @@ describe("Sync Engine Deletion Integration", () => {
96
82
  for (const file of testFiles) {
97
83
  const filePath = path.join(testDir, file.name);
98
84
  await removePath(filePath);
99
- console.log(`🗑️ Deleted: ${file.name}`);
100
85
  }
101
86
 
102
87
  // Verify all files are gone from filesystem
@@ -111,28 +96,21 @@ describe("Sync Engine Deletion Integration", () => {
111
96
  // Simulate sync engine processing the deletions
112
97
  for (const file of testFiles) {
113
98
  snapshotManager.removeFileEntry(snapshot, file.name);
114
- console.log(`📸 Removed from snapshot: ${file.name}`);
115
99
  }
116
100
 
117
101
  expect(snapshot.files.size).toBe(0);
118
- console.log(`✅ Multiple deletions handled correctly`);
119
102
  });
120
103
  });
121
104
 
122
105
  describe("Deletion Timing and Race Conditions", () => {
123
106
  it("should handle rapid create-modify-delete sequences", async () => {
124
- console.log("\n🧪 Testing Rapid Create-Modify-Delete Sequences");
125
-
126
107
  const filePath = path.join(testDir, "rapid-changes.ts");
127
108
  const snapshot = snapshotManager.createEmpty();
128
109
 
129
110
  for (let i = 0; i < 3; i++) {
130
- console.log(`\n--- Cycle ${i + 1} ---`);
131
-
132
111
  // Create
133
112
  const content = `interface Cycle${i} { value: ${i}; }`;
134
113
  await writeFileContent(filePath, content);
135
- console.log(`📄 Created with content: "${content}"`);
136
114
 
137
115
  // Add to snapshot
138
116
  snapshotManager.updateFileEntry(snapshot, "rapid-changes.ts", {
@@ -146,11 +124,9 @@ describe("Sync Engine Deletion Integration", () => {
146
124
  // Modify
147
125
  const modifiedContent = content + `\n// Modified in cycle ${i}`;
148
126
  await writeFileContent(filePath, modifiedContent);
149
- console.log(`📝 Modified content`);
150
127
 
151
128
  // Delete
152
129
  await removePath(filePath);
153
- console.log(`🗑️ Deleted`);
154
130
 
155
131
  // Verify deletion
156
132
  expect(await pathExists(filePath)).toBe(false);
@@ -158,19 +134,14 @@ describe("Sync Engine Deletion Integration", () => {
158
134
  // Clean up snapshot
159
135
  snapshotManager.removeFileEntry(snapshot, "rapid-changes.ts");
160
136
  }
161
-
162
- console.log(`✅ Rapid sequences handled without errors`);
163
137
  });
164
138
 
165
139
  it("should handle deletion during content modification attempts", async () => {
166
- console.log("\n🧪 Testing Deletion During Modification");
167
-
168
140
  const filePath = path.join(testDir, "modify-delete-race.ts");
169
141
  const initialContent = "interface Race { test: boolean; }";
170
142
 
171
143
  // Create initial file
172
144
  await writeFileContent(filePath, initialContent);
173
- console.log(`📄 Created file with initial content`);
174
145
 
175
146
  // Start modification and deletion concurrently
176
147
  const modifyPromise = writeFileContent(
@@ -188,14 +159,11 @@ describe("Sync Engine Deletion Integration", () => {
188
159
 
189
160
  // File should be deleted regardless of modification timing
190
161
  expect(await pathExists(filePath)).toBe(false);
191
- console.log(`✅ File properly deleted despite concurrent modification`);
192
162
  });
193
163
  });
194
164
 
195
165
  describe("Directory Structure Impact", () => {
196
166
  it("should handle deletion of files in nested directories", async () => {
197
- console.log("\n🧪 Testing Nested Directory File Deletion");
198
-
199
167
  // Create nested structure
200
168
  const nestedDir = path.join(testDir, "src", "components");
201
169
  const filePath = path.join(nestedDir, "Button.tsx");
@@ -213,12 +181,8 @@ describe("Sync Engine Deletion Integration", () => {
213
181
  mimeType: "text/tsx",
214
182
  });
215
183
 
216
- console.log(`📁 Created nested structure: ${nestedDir}`);
217
- console.log(`📄 Created file: src/components/Button.tsx`);
218
-
219
184
  // Delete just the file (not the directories)
220
185
  await removePath(filePath);
221
- console.log(`🗑️ Deleted file, kept directory structure`);
222
186
 
223
187
  // File should be gone, directories should remain
224
188
  expect(await pathExists(filePath)).toBe(false);
@@ -228,13 +192,9 @@ describe("Sync Engine Deletion Integration", () => {
228
192
  // Simulate snapshot cleanup
229
193
  snapshotManager.removeFileEntry(snapshot, "src/components/Button.tsx");
230
194
  expect(snapshot.files.size).toBe(0);
231
-
232
- console.log(`✅ Nested file deletion handled correctly`);
233
195
  });
234
196
 
235
197
  it("should handle deletion of entire directory trees", async () => {
236
- console.log("\n🧪 Testing Directory Tree Deletion");
237
-
238
198
  // Create multiple files in nested structure
239
199
  const testStructure = [
240
200
  "src/utils/helpers.ts",
@@ -258,15 +218,12 @@ describe("Sync Engine Deletion Integration", () => {
258
218
  extension: path.extname(relativePath).slice(1),
259
219
  mimeType: "text/typescript",
260
220
  });
261
-
262
- console.log(`📄 Created: ${relativePath}`);
263
221
  }
264
222
 
265
223
  expect(snapshot.files.size).toBe(5);
266
224
 
267
225
  // Delete entire src directory
268
226
  await removePath(path.join(testDir, "src"));
269
- console.log(`🗑️ Deleted entire src/ directory tree`);
270
227
 
271
228
  // Verify all files and directories are gone
272
229
  for (const relativePath of testStructure) {
@@ -278,58 +235,42 @@ describe("Sync Engine Deletion Integration", () => {
278
235
  // Simulate snapshot cleanup for all files
279
236
  for (const relativePath of testStructure) {
280
237
  snapshotManager.removeFileEntry(snapshot, relativePath);
281
- console.log(`📸 Removed from snapshot: ${relativePath}`);
282
238
  }
283
239
 
284
240
  expect(snapshot.files.size).toBe(0);
285
- console.log(`✅ Directory tree deletion handled correctly`);
286
241
  });
287
242
  });
288
243
 
289
244
  describe("Error Recovery and Edge Cases", () => {
290
245
  it("should handle deletion of non-existent files gracefully", async () => {
291
- console.log("\n🧪 Testing Non-Existent File Deletion");
292
-
293
246
  const nonExistentPath = path.join(testDir, "never-existed.ts");
294
247
 
295
248
  // Attempt to delete non-existent file (should not throw)
296
249
  await expect(removePath(nonExistentPath)).resolves.not.toThrow();
297
- console.log(`✅ Non-existent file deletion handled gracefully`);
298
250
 
299
251
  // Attempt to remove from snapshot (should not throw)
300
252
  const snapshot = snapshotManager.createEmpty();
301
253
  expect(() => {
302
254
  snapshotManager.removeFileEntry(snapshot, "never-existed.ts");
303
255
  }).not.toThrow();
304
- console.log(`✅ Non-existent snapshot entry removal handled gracefully`);
305
256
  });
306
257
 
307
258
  it("should provide debugging info for deletion failures", async () => {
308
- console.log("\n🧪 Deletion Debugging Information");
309
-
310
259
  const debugFilePath = path.join(testDir, "debug-deletion.ts");
311
260
  const content = "interface Debug { info: string; }";
312
261
 
313
262
  try {
314
263
  // Create file
315
264
  await writeFileContent(debugFilePath, content);
316
- console.log(`📄 File created: ${debugFilePath}`);
317
- console.log(`📏 File size: ${content.length} characters`);
318
265
 
319
266
  // Verify file exists and is readable
320
267
  const readBack = await readFileContent(debugFilePath);
321
- console.log(`📖 File readable: ${typeof readBack === "string"}`);
322
- console.log(`✅ Content matches: ${readBack === content}`);
268
+ expect(readBack).toBe(content);
323
269
 
324
270
  // Delete file
325
- const deleteStart = Date.now();
326
271
  await removePath(debugFilePath);
327
- const deleteTime = Date.now() - deleteStart;
328
272
 
329
- console.log(`🗑️ Deletion completed in ${deleteTime}ms`);
330
- console.log(
331
- `🔍 File exists after deletion: ${await pathExists(debugFilePath)}`
332
- );
273
+ expect(await pathExists(debugFilePath)).toBe(false);
333
274
  } catch (error) {
334
275
  console.error(`❌ Deletion test failed:`, error);
335
276
  throw error;
@@ -1,7 +1,7 @@
1
1
  import * as fs from "fs/promises";
2
2
  import * as path from "path";
3
3
  import * as tmp from "tmp";
4
- import { ConfigManager } from "../../src/config";
4
+ import { ConfigManager } from "../../src/core";
5
5
  import { DirectoryConfig } from "../../src/types";
6
6
 
7
7
  describe("Sync Flow Integration", () => {
@@ -26,18 +26,9 @@ describe("Sync Flow Integration", () => {
26
26
  const testConfig: DirectoryConfig = {
27
27
  sync_server: "wss://test.server.com",
28
28
  sync_enabled: true,
29
- defaults: {
30
- exclude_patterns: [".git", "*.tmp"],
31
- large_file_threshold: "1MB",
32
- },
33
- diff: {
34
- show_binary: false,
35
- },
29
+ exclude_patterns: [".git", "*.tmp"],
36
30
  sync: {
37
31
  move_detection_threshold: 0.8,
38
- prompt_threshold: 0.5,
39
- auto_sync: false,
40
- parallel_operations: 2,
41
32
  },
42
33
  };
43
34
 
@@ -57,18 +48,9 @@ describe("Sync Flow Integration", () => {
57
48
  const localConfig: DirectoryConfig = {
58
49
  sync_server: "wss://local.server.com",
59
50
  sync_enabled: true,
60
- defaults: {
61
- exclude_patterns: [".git", "*.tmp"],
62
- large_file_threshold: "5MB",
63
- },
64
- diff: {
65
- show_binary: true,
66
- },
51
+ exclude_patterns: [".git", "*.tmp"],
67
52
  sync: {
68
53
  move_detection_threshold: 0.9,
69
- prompt_threshold: 0.6,
70
- auto_sync: true,
71
- parallel_operations: 1,
72
54
  },
73
55
  };
74
56
 
@@ -77,9 +59,7 @@ describe("Sync Flow Integration", () => {
77
59
  // Verify merged config
78
60
  const mergedConfig = await configManager.getMerged();
79
61
  expect(mergedConfig.sync_server).toBe("wss://local.server.com");
80
- expect(mergedConfig.defaults?.exclude_patterns).toContain(".git");
81
- expect(mergedConfig.defaults?.large_file_threshold).toBe("5MB");
82
- expect(mergedConfig.diff?.show_binary).toBe(true);
62
+ expect(mergedConfig.exclude_patterns).toContain(".git");
83
63
  expect(mergedConfig.sync?.move_detection_threshold).toBe(0.9);
84
64
  });
85
65
  });
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Jest setup file to mock ESM modules that don't work well with Jest
3
+ */
4
+
5
+ // Mock chalk (ESM-only module)
6
+ jest.mock("chalk", () => ({
7
+ __esModule: true,
8
+ default: new Proxy(
9
+ {},
10
+ {
11
+ get: (target, prop) => {
12
+ if (prop === "default") return target;
13
+ // Return a function that returns the input string unchanged
14
+ return (str: string) => str;
15
+ },
16
+ }
17
+ ),
18
+ }));
19
+
20
+ // Mock ora (ESM-only module)
21
+ jest.mock("ora", () => ({
22
+ __esModule: true,
23
+ default: jest.fn(() => ({
24
+ start: jest.fn().mockReturnThis(),
25
+ stop: jest.fn().mockReturnThis(),
26
+ succeed: jest.fn().mockReturnThis(),
27
+ fail: jest.fn().mockReturnThis(),
28
+ warn: jest.fn().mockReturnThis(),
29
+ info: jest.fn().mockReturnThis(),
30
+ clear: jest.fn().mockReturnThis(),
31
+ text: "",
32
+ })),
33
+ }));
34
+
@@ -9,18 +9,16 @@ import {
9
9
  } from "../../src/utils";
10
10
  import { SnapshotManager } from "../../src/core/snapshot";
11
11
  import { ChangeDetector } from "../../src/core/change-detection";
12
- import { ChangeType } from "../../src/types";
13
12
 
14
13
  describe("File Deletion Behavior", () => {
15
14
  let testDir: string;
16
15
  let snapshotManager: SnapshotManager;
17
- let changeDetector: ChangeDetector;
18
16
 
19
17
  beforeEach(async () => {
20
18
  testDir = await fs.mkdtemp(path.join(tmpdir(), "deletion-test-"));
21
19
  snapshotManager = new SnapshotManager(testDir);
22
20
  // Create a minimal change detector for testing (without Automerge repo)
23
- changeDetector = new ChangeDetector(null as any, testDir, []);
21
+ new ChangeDetector(null as any, testDir, []);
24
22
  });
25
23
 
26
24
  afterEach(async () => {
@@ -230,31 +228,22 @@ describe("File Deletion Behavior", () => {
230
228
 
231
229
  describe("Debug Information", () => {
232
230
  it("should provide detailed info about deletion behavior", async () => {
233
- console.log("\n=== Deletion Behavior Debug Info ===");
234
-
235
231
  const filePath = path.join(testDir, "debug.txt");
236
232
  const content = "Debug test content";
237
233
 
238
- console.log(`Test directory: ${testDir}`);
239
- console.log(`File path: ${filePath}`);
240
-
241
234
  // Create file
242
235
  await writeFileContent(filePath, content);
243
- console.log(`✅ File created successfully`);
244
236
 
245
237
  // Verify file content
246
238
  const readBack = await readFileContent(filePath);
247
- console.log(`✅ File content verified: "${readBack}"`);
239
+ expect(readBack).toBe(content);
248
240
 
249
241
  // Delete file
250
242
  await removePath(filePath);
251
- console.log(`✅ File deleted successfully`);
252
243
 
253
244
  // Verify deletion
254
245
  const exists = await pathExists(filePath);
255
- console.log(`✅ File deletion verified: exists=${exists}`);
256
-
257
- console.log("=== End Debug Info ===\n");
246
+ expect(exists).toBe(false);
258
247
  });
259
248
  });
260
249
  });
@@ -6,7 +6,6 @@ import {
6
6
  isEnhancedTextFile,
7
7
  shouldForceAsText,
8
8
  getMimeType,
9
- isTextFile,
10
9
  } from "../../src/utils";
11
10
 
12
11
  describe("Enhanced MIME Detection", () => {
@@ -27,19 +26,12 @@ describe("Enhanced MIME Detection", () => {
27
26
 
28
27
  // Standard MIME detection (broken)
29
28
  const standardMime = getMimeType(tsFile);
30
- const standardIsText = await isTextFile(tsFile);
31
29
 
32
30
  // Enhanced MIME detection (fixed)
33
31
  const enhancedMime = getEnhancedMimeType(tsFile);
34
32
  const enhancedIsText = await isEnhancedTextFile(tsFile);
35
33
  const shouldForce = shouldForceAsText(tsFile);
36
34
 
37
- console.log("TypeScript file (.ts) detection:");
38
- console.log(` Standard MIME: ${standardMime}, Text: ${standardIsText}`);
39
- console.log(
40
- ` Enhanced MIME: ${enhancedMime}, Text: ${enhancedIsText}, Force: ${shouldForce}`
41
- );
42
-
43
35
  // Verify the fix
44
36
  expect(enhancedMime).toBe("text/typescript"); // Fixed!
45
37
  expect(enhancedIsText).toBe(true); // Fixed!
@@ -57,10 +49,6 @@ describe("Enhanced MIME Detection", () => {
57
49
  const enhancedMime = getEnhancedMimeType(tsxFile);
58
50
  const enhancedIsText = await isEnhancedTextFile(tsxFile);
59
51
 
60
- console.log("TSX file detection:");
61
- console.log(` Standard MIME: ${standardMime}`);
62
- console.log(` Enhanced MIME: ${enhancedMime}, Text: ${enhancedIsText}`);
63
-
64
52
  expect(enhancedMime).toBe("text/tsx"); // Fixed!
65
53
  expect(enhancedIsText).toBe(true); // Fixed!
66
54
  expect(standardMime).toBe("application/octet-stream"); // Original problem
@@ -180,9 +168,6 @@ div { color: blue; }
180
168
  { name: "font.woff2", mime: "font/woff2", text: false },
181
169
  ];
182
170
 
183
- console.log("\nComprehensive Developer File Detection:");
184
- console.log("=====================================");
185
-
186
171
  for (const file of developerFiles) {
187
172
  const filePath = path.join(testDir, file.name);
188
173
 
@@ -195,13 +180,6 @@ div { color: blue; }
195
180
 
196
181
  const enhancedMime = getEnhancedMimeType(filePath);
197
182
  const enhancedIsText = await isEnhancedTextFile(filePath);
198
- const forced = shouldForceAsText(filePath);
199
-
200
- console.log(
201
- `${file.name.padEnd(20)} | MIME: ${enhancedMime.padEnd(
202
- 25
203
- )} | Text: ${enhancedIsText} | Forced: ${forced}`
204
- );
205
183
 
206
184
  expect(enhancedMime).toBe(file.mime);
207
185
  expect(enhancedIsText).toBe(file.text);
@@ -1,12 +1,7 @@
1
- import * as fs from "fs/promises";
2
1
  import * as path from "path";
3
2
  import * as tmp from "tmp";
4
3
  import { SnapshotManager } from "../../src/core/snapshot";
5
- import {
6
- SyncSnapshot,
7
- SnapshotFileEntry,
8
- SnapshotDirectoryEntry,
9
- } from "../../src/types";
4
+ import { SnapshotFileEntry, SnapshotDirectoryEntry } from "../../src/types";
10
5
  import { UrlHeads } from "@automerge/automerge-repo";
11
6
 
12
7
  describe("SnapshotManager", () => {
@@ -352,28 +347,6 @@ describe("SnapshotManager", () => {
352
347
  });
353
348
  });
354
349
 
355
- describe("backup", () => {
356
- it("should create backup of existing snapshot", async () => {
357
- const snapshot = snapshotManager.createEmpty();
358
- await snapshotManager.save(snapshot);
359
-
360
- await snapshotManager.backup();
361
-
362
- // Check that backup file exists
363
- const syncToolDir = path.join(tmpDir, ".pushwork");
364
- const files = await fs.readdir(syncToolDir);
365
- const backupFiles = files.filter((f) =>
366
- f.startsWith("snapshot.json.backup.")
367
- );
368
-
369
- expect(backupFiles.length).toBe(1);
370
- });
371
-
372
- it("should not fail when no snapshot exists", async () => {
373
- await snapshotManager.backup(); // Should not throw
374
- });
375
- });
376
-
377
350
  describe("clone", () => {
378
351
  it("should create independent copy of snapshot", () => {
379
352
  const originalSnapshot = snapshotManager.createEmpty();
@@ -419,7 +392,7 @@ describe("SnapshotManager", () => {
419
392
  const originalTimestamp = snapshot.timestamp;
420
393
 
421
394
  // Add small delay to ensure timestamp difference
422
- await new Promise((resolve) => setTimeout(resolve, 1));
395
+ await new Promise((resolve) => setTimeout(resolve, 10));
423
396
 
424
397
  snapshotManager.clear(snapshot);
425
398