pushwork 2.0.0-a.sub.1 → 2.0.0-preview.2

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 (234) hide show
  1. package/dist/branches.d.ts +20 -0
  2. package/dist/branches.d.ts.map +1 -0
  3. package/dist/branches.js +111 -0
  4. package/dist/branches.js.map +1 -0
  5. package/dist/cli.d.ts +1 -1
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +245 -270
  8. package/dist/cli.js.map +1 -1
  9. package/dist/config.d.ts +17 -0
  10. package/dist/config.d.ts.map +1 -0
  11. package/dist/config.js +84 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/fs-tree.d.ts +6 -0
  14. package/dist/fs-tree.d.ts.map +1 -0
  15. package/dist/fs-tree.js +99 -0
  16. package/dist/fs-tree.js.map +1 -0
  17. package/dist/ignore.d.ts +6 -0
  18. package/dist/ignore.d.ts.map +1 -0
  19. package/dist/ignore.js +74 -0
  20. package/dist/ignore.js.map +1 -0
  21. package/dist/index.d.ts +8 -4
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +35 -4
  24. package/dist/index.js.map +1 -1
  25. package/dist/log.d.ts +3 -0
  26. package/dist/log.d.ts.map +1 -0
  27. package/dist/log.js +14 -0
  28. package/dist/log.js.map +1 -0
  29. package/dist/pushwork.d.ts +129 -0
  30. package/dist/pushwork.d.ts.map +1 -0
  31. package/dist/pushwork.js +1062 -0
  32. package/dist/pushwork.js.map +1 -0
  33. package/dist/repo.d.ts +14 -0
  34. package/dist/repo.d.ts.map +1 -0
  35. package/dist/repo.js +60 -0
  36. package/dist/repo.js.map +1 -0
  37. package/dist/shapes/custom.d.ts +3 -0
  38. package/dist/shapes/custom.d.ts.map +1 -0
  39. package/dist/shapes/custom.js +57 -0
  40. package/dist/shapes/custom.js.map +1 -0
  41. package/dist/shapes/file.d.ts +20 -0
  42. package/dist/shapes/file.d.ts.map +1 -0
  43. package/dist/shapes/file.js +140 -0
  44. package/dist/shapes/file.js.map +1 -0
  45. package/dist/shapes/index.d.ts +10 -0
  46. package/dist/shapes/index.d.ts.map +1 -0
  47. package/dist/shapes/index.js +35 -0
  48. package/dist/shapes/index.js.map +1 -0
  49. package/dist/shapes/patchwork-folder.d.ts +3 -0
  50. package/dist/shapes/patchwork-folder.d.ts.map +1 -0
  51. package/dist/shapes/patchwork-folder.js +160 -0
  52. package/dist/shapes/patchwork-folder.js.map +1 -0
  53. package/dist/shapes/types.d.ts +38 -0
  54. package/dist/shapes/types.d.ts.map +1 -0
  55. package/dist/shapes/types.js +52 -0
  56. package/dist/shapes/types.js.map +1 -0
  57. package/dist/shapes/vfs.d.ts +3 -0
  58. package/dist/shapes/vfs.d.ts.map +1 -0
  59. package/dist/shapes/vfs.js +92 -0
  60. package/dist/shapes/vfs.js.map +1 -0
  61. package/dist/stash.d.ts +23 -0
  62. package/dist/stash.d.ts.map +1 -0
  63. package/dist/stash.js +118 -0
  64. package/dist/stash.js.map +1 -0
  65. package/dist/version.d.ts +11 -0
  66. package/dist/version.d.ts.map +1 -0
  67. package/dist/version.js +93 -0
  68. package/dist/version.js.map +1 -0
  69. package/package.json +19 -48
  70. package/patches/@automerge__automerge-repo@2.6.0-subduction.15.patch +26 -0
  71. package/.prettierrc +0 -9
  72. package/ARCHITECTURE-ACCORDING-TO-CLAUDE.md +0 -248
  73. package/CLAUDE.md +0 -141
  74. package/README.md +0 -221
  75. package/babel.config.js +0 -5
  76. package/dist/cli/commands.d.ts +0 -71
  77. package/dist/cli/commands.d.ts.map +0 -1
  78. package/dist/cli/commands.js +0 -794
  79. package/dist/cli/commands.js.map +0 -1
  80. package/dist/cli/index.d.ts +0 -2
  81. package/dist/cli/index.d.ts.map +0 -1
  82. package/dist/cli/index.js +0 -19
  83. package/dist/cli/index.js.map +0 -1
  84. package/dist/commands.d.ts +0 -61
  85. package/dist/commands.d.ts.map +0 -1
  86. package/dist/commands.js +0 -861
  87. package/dist/commands.js.map +0 -1
  88. package/dist/config/index.d.ts +0 -71
  89. package/dist/config/index.d.ts.map +0 -1
  90. package/dist/config/index.js +0 -314
  91. package/dist/config/index.js.map +0 -1
  92. package/dist/core/change-detection.d.ts +0 -80
  93. package/dist/core/change-detection.d.ts.map +0 -1
  94. package/dist/core/change-detection.js +0 -523
  95. package/dist/core/change-detection.js.map +0 -1
  96. package/dist/core/config.d.ts +0 -81
  97. package/dist/core/config.d.ts.map +0 -1
  98. package/dist/core/config.js +0 -258
  99. package/dist/core/config.js.map +0 -1
  100. package/dist/core/index.d.ts +0 -6
  101. package/dist/core/index.d.ts.map +0 -1
  102. package/dist/core/index.js +0 -6
  103. package/dist/core/index.js.map +0 -1
  104. package/dist/core/move-detection.d.ts +0 -34
  105. package/dist/core/move-detection.d.ts.map +0 -1
  106. package/dist/core/move-detection.js +0 -121
  107. package/dist/core/move-detection.js.map +0 -1
  108. package/dist/core/snapshot.d.ts +0 -105
  109. package/dist/core/snapshot.d.ts.map +0 -1
  110. package/dist/core/snapshot.js +0 -217
  111. package/dist/core/snapshot.js.map +0 -1
  112. package/dist/core/sync-engine.d.ts +0 -157
  113. package/dist/core/sync-engine.d.ts.map +0 -1
  114. package/dist/core/sync-engine.js +0 -1379
  115. package/dist/core/sync-engine.js.map +0 -1
  116. package/dist/types/config.d.ts +0 -99
  117. package/dist/types/config.d.ts.map +0 -1
  118. package/dist/types/config.js +0 -5
  119. package/dist/types/config.js.map +0 -1
  120. package/dist/types/documents.d.ts +0 -88
  121. package/dist/types/documents.d.ts.map +0 -1
  122. package/dist/types/documents.js +0 -20
  123. package/dist/types/documents.js.map +0 -1
  124. package/dist/types/index.d.ts +0 -4
  125. package/dist/types/index.d.ts.map +0 -1
  126. package/dist/types/index.js +0 -4
  127. package/dist/types/index.js.map +0 -1
  128. package/dist/types/snapshot.d.ts +0 -64
  129. package/dist/types/snapshot.d.ts.map +0 -1
  130. package/dist/types/snapshot.js +0 -2
  131. package/dist/types/snapshot.js.map +0 -1
  132. package/dist/utils/content-similarity.d.ts +0 -53
  133. package/dist/utils/content-similarity.d.ts.map +0 -1
  134. package/dist/utils/content-similarity.js +0 -155
  135. package/dist/utils/content-similarity.js.map +0 -1
  136. package/dist/utils/content.d.ts +0 -10
  137. package/dist/utils/content.d.ts.map +0 -1
  138. package/dist/utils/content.js +0 -31
  139. package/dist/utils/content.js.map +0 -1
  140. package/dist/utils/directory.d.ts +0 -24
  141. package/dist/utils/directory.d.ts.map +0 -1
  142. package/dist/utils/directory.js +0 -52
  143. package/dist/utils/directory.js.map +0 -1
  144. package/dist/utils/fs.d.ts +0 -74
  145. package/dist/utils/fs.d.ts.map +0 -1
  146. package/dist/utils/fs.js +0 -248
  147. package/dist/utils/fs.js.map +0 -1
  148. package/dist/utils/index.d.ts +0 -5
  149. package/dist/utils/index.d.ts.map +0 -1
  150. package/dist/utils/index.js +0 -5
  151. package/dist/utils/index.js.map +0 -1
  152. package/dist/utils/mime-types.d.ts +0 -13
  153. package/dist/utils/mime-types.d.ts.map +0 -1
  154. package/dist/utils/mime-types.js +0 -209
  155. package/dist/utils/mime-types.js.map +0 -1
  156. package/dist/utils/network-sync.d.ts +0 -36
  157. package/dist/utils/network-sync.d.ts.map +0 -1
  158. package/dist/utils/network-sync.js +0 -250
  159. package/dist/utils/network-sync.js.map +0 -1
  160. package/dist/utils/node-polyfills.d.ts +0 -9
  161. package/dist/utils/node-polyfills.d.ts.map +0 -1
  162. package/dist/utils/node-polyfills.js +0 -9
  163. package/dist/utils/node-polyfills.js.map +0 -1
  164. package/dist/utils/output.d.ts +0 -129
  165. package/dist/utils/output.d.ts.map +0 -1
  166. package/dist/utils/output.js +0 -368
  167. package/dist/utils/output.js.map +0 -1
  168. package/dist/utils/repo-factory.d.ts +0 -13
  169. package/dist/utils/repo-factory.d.ts.map +0 -1
  170. package/dist/utils/repo-factory.js +0 -46
  171. package/dist/utils/repo-factory.js.map +0 -1
  172. package/dist/utils/string-similarity.d.ts +0 -14
  173. package/dist/utils/string-similarity.d.ts.map +0 -1
  174. package/dist/utils/string-similarity.js +0 -39
  175. package/dist/utils/string-similarity.js.map +0 -1
  176. package/dist/utils/text-diff.d.ts +0 -37
  177. package/dist/utils/text-diff.d.ts.map +0 -1
  178. package/dist/utils/text-diff.js +0 -93
  179. package/dist/utils/text-diff.js.map +0 -1
  180. package/dist/utils/trace.d.ts +0 -19
  181. package/dist/utils/trace.d.ts.map +0 -1
  182. package/dist/utils/trace.js +0 -63
  183. package/dist/utils/trace.js.map +0 -1
  184. package/src/cli.ts +0 -442
  185. package/src/commands.ts +0 -1134
  186. package/src/core/change-detection.ts +0 -712
  187. package/src/core/config.ts +0 -313
  188. package/src/core/index.ts +0 -5
  189. package/src/core/move-detection.ts +0 -169
  190. package/src/core/snapshot.ts +0 -275
  191. package/src/core/sync-engine.ts +0 -1795
  192. package/src/index.ts +0 -4
  193. package/src/types/config.ts +0 -111
  194. package/src/types/documents.ts +0 -91
  195. package/src/types/index.ts +0 -3
  196. package/src/types/snapshot.ts +0 -67
  197. package/src/utils/content.ts +0 -34
  198. package/src/utils/directory.ts +0 -73
  199. package/src/utils/fs.ts +0 -297
  200. package/src/utils/index.ts +0 -4
  201. package/src/utils/mime-types.ts +0 -244
  202. package/src/utils/network-sync.ts +0 -319
  203. package/src/utils/node-polyfills.ts +0 -8
  204. package/src/utils/output.ts +0 -450
  205. package/src/utils/repo-factory.ts +0 -73
  206. package/src/utils/string-similarity.ts +0 -54
  207. package/src/utils/text-diff.ts +0 -101
  208. package/src/utils/trace.ts +0 -70
  209. package/test/integration/README.md +0 -328
  210. package/test/integration/clone-test.sh +0 -310
  211. package/test/integration/conflict-resolution-test.sh +0 -309
  212. package/test/integration/debug-both-nested.sh +0 -74
  213. package/test/integration/debug-concurrent-nested.sh +0 -87
  214. package/test/integration/debug-nested.sh +0 -73
  215. package/test/integration/deletion-behavior-test.sh +0 -487
  216. package/test/integration/deletion-sync-test-simple.sh +0 -193
  217. package/test/integration/deletion-sync-test.sh +0 -297
  218. package/test/integration/exclude-patterns.test.ts +0 -144
  219. package/test/integration/full-integration-test.sh +0 -363
  220. package/test/integration/fuzzer.test.ts +0 -818
  221. package/test/integration/in-memory-sync.test.ts +0 -830
  222. package/test/integration/init-sync.test.ts +0 -89
  223. package/test/integration/manual-sync-test.sh +0 -84
  224. package/test/integration/sync-deletion.test.ts +0 -280
  225. package/test/integration/sync-flow.test.ts +0 -291
  226. package/test/jest.setup.ts +0 -34
  227. package/test/run-tests.sh +0 -225
  228. package/test/unit/deletion-behavior.test.ts +0 -249
  229. package/test/unit/enhanced-mime-detection.test.ts +0 -244
  230. package/test/unit/snapshot.test.ts +0 -404
  231. package/test/unit/sync-convergence.test.ts +0 -298
  232. package/test/unit/sync-timing.test.ts +0 -134
  233. package/test/unit/utils.test.ts +0 -366
  234. package/tsconfig.json +0 -23
@@ -1,249 +0,0 @@
1
- import * as fs from "fs/promises";
2
- import * as path from "path";
3
- import { tmpdir } from "os";
4
- import {
5
- readFileContent,
6
- writeFileContent,
7
- removePath,
8
- pathExists,
9
- } from "../../src/utils";
10
- import { SnapshotManager } from "../../src/core/snapshot";
11
- import { ChangeDetector } from "../../src/core/change-detection";
12
-
13
- describe("File Deletion Behavior", () => {
14
- let testDir: string;
15
- let snapshotManager: SnapshotManager;
16
-
17
- beforeEach(async () => {
18
- testDir = await fs.mkdtemp(path.join(tmpdir(), "deletion-test-"));
19
- snapshotManager = new SnapshotManager(testDir);
20
- // Create a minimal change detector for testing (without Automerge repo)
21
- new ChangeDetector(null as any, testDir, []);
22
- });
23
-
24
- afterEach(async () => {
25
- await fs.rm(testDir, { recursive: true, force: true });
26
- });
27
-
28
- describe("Basic File Deletion", () => {
29
- it("should read TypeScript files correctly before deletion", async () => {
30
- const tsFile = path.join(testDir, "component.ts");
31
- const content = "interface User { name: string; }";
32
- await writeFileContent(tsFile, content);
33
-
34
- const result = await readFileContent(tsFile);
35
- expect(typeof result).toBe("string");
36
- expect(result).toBe(content);
37
- });
38
-
39
- it("should handle file deletion through removePath", async () => {
40
- const filePath = path.join(testDir, "test.txt");
41
- await writeFileContent(filePath, "test content");
42
-
43
- expect(await pathExists(filePath)).toBe(true);
44
-
45
- await removePath(filePath);
46
-
47
- expect(await pathExists(filePath)).toBe(false);
48
- });
49
-
50
- it("should handle directory deletion through removePath", async () => {
51
- const dirPath = path.join(testDir, "subdir");
52
- const filePath = path.join(dirPath, "file.txt");
53
-
54
- await fs.mkdir(dirPath);
55
- await writeFileContent(filePath, "content");
56
-
57
- expect(await pathExists(dirPath)).toBe(true);
58
- expect(await pathExists(filePath)).toBe(true);
59
-
60
- await removePath(dirPath);
61
-
62
- expect(await pathExists(dirPath)).toBe(false);
63
- expect(await pathExists(filePath)).toBe(false);
64
- });
65
- });
66
-
67
- describe("Snapshot Deletion Behavior", () => {
68
- it("should properly remove files from snapshot", () => {
69
- const snapshot = snapshotManager.createEmpty();
70
-
71
- // Add a file to snapshot
72
- snapshotManager.updateFileEntry(snapshot, "test.txt", {
73
- path: path.join(testDir, "test.txt"),
74
- url: "automerge:test-url" as any,
75
- head: ["test-head"] as any,
76
- extension: "txt",
77
- mimeType: "text/plain",
78
- });
79
-
80
- expect(snapshot.files.has("test.txt")).toBe(true);
81
-
82
- // Remove file from snapshot
83
- snapshotManager.removeFileEntry(snapshot, "test.txt");
84
-
85
- expect(snapshot.files.has("test.txt")).toBe(false);
86
- expect(snapshot.files.size).toBe(0);
87
- });
88
-
89
- it("should handle removing non-existent files gracefully", () => {
90
- const snapshot = snapshotManager.createEmpty();
91
-
92
- // Should not throw when removing non-existent file
93
- expect(() => {
94
- snapshotManager.removeFileEntry(snapshot, "nonexistent.txt");
95
- }).not.toThrow();
96
-
97
- expect(snapshot.files.size).toBe(0);
98
- });
99
- });
100
-
101
- describe("Deletion Scenario Simulation", () => {
102
- it("should simulate local file deletion scenario", async () => {
103
- // Create a file
104
- const filePath = path.join(testDir, "deleteme.txt");
105
- const content = "This file will be deleted";
106
- await writeFileContent(filePath, content);
107
-
108
- // Verify file exists
109
- expect(await pathExists(filePath)).toBe(true);
110
- const readContent = await readFileContent(filePath);
111
- expect(readContent).toBe(content);
112
-
113
- // Create snapshot with this file
114
- const snapshot = snapshotManager.createEmpty();
115
- snapshotManager.updateFileEntry(snapshot, "deleteme.txt", {
116
- path: filePath,
117
- url: "automerge:delete-test" as any,
118
- head: ["initial-head"] as any,
119
- extension: "txt",
120
- mimeType: "text/plain",
121
- });
122
-
123
- // Simulate local deletion (user deletes file)
124
- await removePath(filePath);
125
-
126
- // Verify file is gone
127
- expect(await pathExists(filePath)).toBe(false);
128
-
129
- // Snapshot should still have the file entry (until sync processes the deletion)
130
- expect(snapshot.files.has("deleteme.txt")).toBe(true);
131
-
132
- // Simulate sync engine processing the deletion
133
- snapshotManager.removeFileEntry(snapshot, "deleteme.txt");
134
-
135
- // Now snapshot should not have the file
136
- expect(snapshot.files.has("deleteme.txt")).toBe(false);
137
- });
138
-
139
- it("should handle rapid create-delete cycles", async () => {
140
- const filePath = path.join(testDir, "rapid.txt");
141
-
142
- // Rapid create-delete cycle
143
- for (let i = 0; i < 5; i++) {
144
- await writeFileContent(filePath, `content ${i}`);
145
- expect(await pathExists(filePath)).toBe(true);
146
-
147
- await removePath(filePath);
148
- expect(await pathExists(filePath)).toBe(false);
149
- }
150
- });
151
-
152
- it("should handle deletion of different file types", async () => {
153
- const testFiles = [
154
- { name: "text.txt", content: "text content" },
155
- { name: "code.ts", content: "interface Test { x: number; }" },
156
- { name: "config.json", content: '{"key": "value"}' },
157
- { name: "binary.bin", content: new Uint8Array([0x00, 0x01, 0x02]) },
158
- ];
159
-
160
- // Create all files
161
- for (const file of testFiles) {
162
- const filePath = path.join(testDir, file.name);
163
- await writeFileContent(filePath, file.content);
164
- expect(await pathExists(filePath)).toBe(true);
165
- }
166
-
167
- // Delete all files
168
- for (const file of testFiles) {
169
- const filePath = path.join(testDir, file.name);
170
- await removePath(filePath);
171
- expect(await pathExists(filePath)).toBe(false);
172
- }
173
- });
174
- });
175
-
176
- describe("Edge Cases and Error Conditions", () => {
177
- it("should handle deletion of files with special characters", async () => {
178
- const specialFiles = [
179
- "file with spaces.txt",
180
- "file-with-dashes.txt",
181
- "file_with_underscores.txt",
182
- "file.with.multiple.dots.txt",
183
- ];
184
-
185
- for (const fileName of specialFiles) {
186
- const filePath = path.join(testDir, fileName);
187
- await writeFileContent(filePath, "test content");
188
- expect(await pathExists(filePath)).toBe(true);
189
-
190
- await removePath(filePath);
191
- expect(await pathExists(filePath)).toBe(false);
192
- }
193
- });
194
-
195
- it("should handle deletion of nested directory structures", async () => {
196
- // Create nested structure
197
- const nestedPath = path.join(testDir, "level1", "level2", "level3");
198
- const filePath = path.join(nestedPath, "deep.txt");
199
-
200
- await fs.mkdir(nestedPath, { recursive: true });
201
- await writeFileContent(filePath, "deep content");
202
-
203
- expect(await pathExists(filePath)).toBe(true);
204
-
205
- // Delete entire structure from top level
206
- await removePath(path.join(testDir, "level1"));
207
-
208
- expect(await pathExists(path.join(testDir, "level1"))).toBe(false);
209
- expect(await pathExists(filePath)).toBe(false);
210
- });
211
-
212
- it("should handle concurrent deletion attempts", async () => {
213
- const filePath = path.join(testDir, "concurrent.txt");
214
- await writeFileContent(filePath, "content");
215
-
216
- // Multiple deletion attempts (should not cause errors)
217
- const deletions = [
218
- removePath(filePath),
219
- removePath(filePath),
220
- removePath(filePath),
221
- ];
222
-
223
- await Promise.all(deletions);
224
-
225
- expect(await pathExists(filePath)).toBe(false);
226
- });
227
- });
228
-
229
- describe("Debug Information", () => {
230
- it("should provide detailed info about deletion behavior", async () => {
231
- const filePath = path.join(testDir, "debug.txt");
232
- const content = "Debug test content";
233
-
234
- // Create file
235
- await writeFileContent(filePath, content);
236
-
237
- // Verify file content
238
- const readBack = await readFileContent(filePath);
239
- expect(readBack).toBe(content);
240
-
241
- // Delete file
242
- await removePath(filePath);
243
-
244
- // Verify deletion
245
- const exists = await pathExists(filePath);
246
- expect(exists).toBe(false);
247
- });
248
- });
249
- });
@@ -1,244 +0,0 @@
1
- import * as fs from "fs/promises";
2
- import * as path from "path";
3
- import { tmpdir } from "os";
4
- import {
5
- getEnhancedMimeType,
6
- isEnhancedTextFile,
7
- shouldForceAsText,
8
- getMimeType,
9
- } from "../../src/utils";
10
-
11
- describe("Enhanced MIME Detection", () => {
12
- let testDir: string;
13
-
14
- beforeEach(async () => {
15
- testDir = await fs.mkdtemp(path.join(tmpdir(), "enhanced-mime-test-"));
16
- });
17
-
18
- afterEach(async () => {
19
- await fs.rm(testDir, { recursive: true, force: true });
20
- });
21
-
22
- describe("Enhanced vs Standard MIME Detection", () => {
23
- it("should fix TypeScript file MIME detection", async () => {
24
- const tsFile = path.join(testDir, "test.ts");
25
- await fs.writeFile(tsFile, "interface User { name: string; }");
26
-
27
- // Standard MIME detection (broken)
28
- const standardMime = getMimeType(tsFile);
29
-
30
- // Enhanced MIME detection (fixed)
31
- const enhancedMime = getEnhancedMimeType(tsFile);
32
- const enhancedIsText = await isEnhancedTextFile(tsFile);
33
- const shouldForce = shouldForceAsText(tsFile);
34
-
35
- // Verify the fix
36
- expect(enhancedMime).toBe("text/typescript"); // Fixed!
37
- expect(enhancedIsText).toBe(true); // Fixed!
38
- expect(shouldForce).toBe(true); // Force TypeScript as text
39
-
40
- // Show the original problem still exists with standard detection
41
- expect(standardMime).toBe("video/mp2t"); // The original problem
42
- });
43
-
44
- it("should fix TSX file MIME detection", async () => {
45
- const tsxFile = path.join(testDir, "Component.tsx");
46
- await fs.writeFile(tsxFile, "export const App = () => <div>Hello</div>;");
47
-
48
- const standardMime = getMimeType(tsxFile);
49
- const enhancedMime = getEnhancedMimeType(tsxFile);
50
- const enhancedIsText = await isEnhancedTextFile(tsxFile);
51
-
52
- expect(enhancedMime).toBe("text/tsx"); // Fixed!
53
- expect(enhancedIsText).toBe(true); // Fixed!
54
- expect(standardMime).toBe("application/octet-stream"); // Original problem
55
- });
56
-
57
- it("should handle Vue.js single file components", async () => {
58
- const vueFile = path.join(testDir, "App.vue");
59
- await fs.writeFile(
60
- vueFile,
61
- `
62
- <template>
63
- <div>{{ message }}</div>
64
- </template>
65
-
66
- <script>
67
- export default {
68
- data() {
69
- return { message: 'Hello Vue!' }
70
- }
71
- }
72
- </script>
73
-
74
- <style scoped>
75
- div { color: blue; }
76
- </style>
77
- `
78
- );
79
-
80
- const enhancedMime = getEnhancedMimeType(vueFile);
81
- const enhancedIsText = await isEnhancedTextFile(vueFile);
82
-
83
- expect(enhancedMime).toBe("text/vue");
84
- expect(enhancedIsText).toBe(true);
85
- });
86
-
87
- it("should handle modern CSS preprocessors correctly", async () => {
88
- const testCases = [
89
- { file: "styles.scss", expectedMime: "text/scss" },
90
- { file: "styles.sass", expectedMime: "text/sass" },
91
- { file: "styles.less", expectedMime: "text/less" },
92
- { file: "styles.styl", expectedMime: "text/stylus" },
93
- ];
94
-
95
- for (const testCase of testCases) {
96
- const filePath = path.join(testDir, testCase.file);
97
- await fs.writeFile(
98
- filePath,
99
- "$primary-color: #007bff;\n.button { color: $primary-color; }"
100
- );
101
-
102
- const enhancedMime = getEnhancedMimeType(filePath);
103
- const enhancedIsText = await isEnhancedTextFile(filePath);
104
-
105
- expect(enhancedMime).toBe(testCase.expectedMime);
106
- expect(enhancedIsText).toBe(true);
107
- }
108
- });
109
-
110
- it("should handle configuration files by filename", async () => {
111
- const configFiles = [
112
- { filename: "Dockerfile", expectedMime: "text/plain" },
113
- { filename: "package.json", expectedMime: "application/json" },
114
- { filename: "tsconfig.json", expectedMime: "application/json" },
115
- {
116
- filename: "webpack.config.js",
117
- expectedMime: "application/javascript",
118
- },
119
- ];
120
-
121
- for (const config of configFiles) {
122
- const filePath = path.join(testDir, config.filename);
123
- await fs.writeFile(filePath, "# Configuration content");
124
-
125
- const enhancedMime = getEnhancedMimeType(filePath);
126
- const enhancedIsText = await isEnhancedTextFile(filePath);
127
-
128
- expect(enhancedMime).toBe(config.expectedMime);
129
- expect(enhancedIsText).toBe(true);
130
- }
131
- });
132
- });
133
-
134
- describe("Comprehensive Developer File Support", () => {
135
- it("should correctly handle all common developer file types", async () => {
136
- const developerFiles = [
137
- // JavaScript/TypeScript ecosystem
138
- { name: "app.js", mime: "application/javascript", text: true },
139
- { name: "app.ts", mime: "text/typescript", text: true },
140
- { name: "Component.tsx", mime: "text/tsx", text: true },
141
- { name: "Component.jsx", mime: "text/jsx", text: true },
142
- { name: "types.d.ts", mime: "text/typescript", text: true },
143
- { name: "bundle.mjs", mime: "application/javascript", text: true },
144
- { name: "server.cjs", mime: "application/javascript", text: true },
145
-
146
- // Frontend frameworks
147
- { name: "App.vue", mime: "text/vue", text: true },
148
- { name: "Button.svelte", mime: "text/svelte", text: true },
149
-
150
- // Stylesheets
151
- { name: "styles.scss", mime: "text/scss", text: true },
152
- { name: "main.css", mime: "text/css", text: true },
153
-
154
- // Documentation
155
- { name: "README.md", mime: "text/markdown", text: true },
156
- { name: "docs.mdx", mime: "text/markdown", text: true },
157
-
158
- // Config files
159
- { name: ".env", mime: "text/plain", text: true },
160
- { name: ".gitignore", mime: "text/plain", text: true },
161
- { name: "config.toml", mime: "application/toml", text: true },
162
-
163
- // Source maps and build artifacts
164
- { name: "app.js.map", mime: "application/json", text: true },
165
-
166
- // Binary files (should not be forced as text)
167
- { name: "image.png", mime: "image/png", text: false },
168
- { name: "font.woff2", mime: "font/woff2", text: false },
169
- ];
170
-
171
- for (const file of developerFiles) {
172
- const filePath = path.join(testDir, file.name);
173
-
174
- // Create appropriate content
175
- const content = file.text
176
- ? `// Content for ${file.name}\nconst test = true;`
177
- : Buffer.from([0x89, 0x50, 0x4e, 0x47]); // PNG-like header
178
-
179
- await fs.writeFile(filePath, content);
180
-
181
- const enhancedMime = getEnhancedMimeType(filePath);
182
- const enhancedIsText = await isEnhancedTextFile(filePath);
183
-
184
- expect(enhancedMime).toBe(file.mime);
185
- expect(enhancedIsText).toBe(file.text);
186
- }
187
- });
188
- });
189
-
190
- describe("Edge Cases and Fallbacks", () => {
191
- it("should handle files without extensions", async () => {
192
- const noExtFile = path.join(testDir, "README");
193
- await fs.writeFile(noExtFile, "# This is a README file");
194
-
195
- const enhancedMime = getEnhancedMimeType(noExtFile);
196
- const enhancedIsText = await isEnhancedTextFile(noExtFile);
197
-
198
- // Should fall back to content-based detection
199
- expect(enhancedMime).toBe("application/octet-stream");
200
- expect(enhancedIsText).toBe(true); // Detected as text by content
201
- });
202
-
203
- it("should prioritize custom definitions over standard library", async () => {
204
- // .ts files are wrongly detected as video/mp2t by standard library
205
- const tsFile = path.join(testDir, "test.ts");
206
- await fs.writeFile(tsFile, "const x: string = 'test';");
207
-
208
- const standardMime = getMimeType(tsFile);
209
- const enhancedMime = getEnhancedMimeType(tsFile);
210
-
211
- expect(standardMime).toBe("video/mp2t"); // Wrong
212
- expect(enhancedMime).toBe("text/typescript"); // Corrected by our custom definitions
213
- });
214
-
215
- it("should handle empty files correctly", async () => {
216
- const emptyFile = path.join(testDir, "empty.ts");
217
- await fs.writeFile(emptyFile, "");
218
-
219
- const enhancedMime = getEnhancedMimeType(emptyFile);
220
- const enhancedIsText = await isEnhancedTextFile(emptyFile);
221
-
222
- expect(enhancedMime).toBe("text/typescript");
223
- expect(enhancedIsText).toBe(true); // Empty files should be treated as text
224
- });
225
-
226
- it("should ensure TypeScript files are read as strings (integration test)", async () => {
227
- const tsFile = path.join(testDir, "integration.ts");
228
- const tsContent = "interface Config { apiUrl: string; timeout: number; }";
229
- await fs.writeFile(tsFile, tsContent);
230
-
231
- // Import readFileContent here to test integration
232
- const { readFileContent } = await import("../../src/utils");
233
-
234
- const result = await readFileContent(tsFile);
235
-
236
- // Critical: TypeScript files MUST be read as strings
237
- expect(typeof result).toBe("string");
238
- expect(result).toBe(tsContent);
239
-
240
- // This test would have FAILED before our fix when readFileContent
241
- // used isTextFile() instead of isEnhancedTextFile()
242
- });
243
- });
244
- });