pushwork 2.0.0-a.sub.0 → 2.0.0-preview

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 (251) hide show
  1. package/dist/branches.d.ts +19 -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 +238 -272
  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 +34 -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 +115 -0
  30. package/dist/pushwork.d.ts.map +1 -0
  31. package/dist/pushwork.js +918 -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 +37 -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 +88 -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/flake.lock +128 -0
  66. package/flake.nix +66 -0
  67. package/package.json +15 -48
  68. package/patches/@automerge__automerge-repo@2.6.0-subduction.15.patch +26 -0
  69. package/pnpm-workspace.yaml +5 -0
  70. package/src/branches.ts +93 -0
  71. package/src/cli.ts +258 -408
  72. package/src/config.ts +64 -0
  73. package/src/fs-tree.ts +70 -0
  74. package/src/ignore.ts +33 -0
  75. package/src/index.ts +38 -4
  76. package/src/log.ts +8 -0
  77. package/src/pushwork.ts +1055 -0
  78. package/src/repo.ts +76 -0
  79. package/src/shapes/custom.ts +29 -0
  80. package/src/shapes/file.ts +115 -0
  81. package/src/shapes/index.ts +19 -0
  82. package/src/shapes/patchwork-folder.ts +156 -0
  83. package/src/shapes/types.ts +79 -0
  84. package/src/shapes/vfs.ts +93 -0
  85. package/src/stash.ts +106 -0
  86. package/test/integration/branches.test.ts +389 -0
  87. package/test/integration/pushwork.test.ts +547 -0
  88. package/test/setup.ts +29 -0
  89. package/test/unit/doc-shape.test.ts +612 -0
  90. package/tsconfig.json +2 -3
  91. package/vitest.config.ts +14 -0
  92. package/ARCHITECTURE-ACCORDING-TO-CLAUDE.md +0 -248
  93. package/CLAUDE.md +0 -141
  94. package/README.md +0 -221
  95. package/babel.config.js +0 -5
  96. package/dist/cli/commands.d.ts +0 -71
  97. package/dist/cli/commands.d.ts.map +0 -1
  98. package/dist/cli/commands.js +0 -794
  99. package/dist/cli/commands.js.map +0 -1
  100. package/dist/cli/index.d.ts +0 -2
  101. package/dist/cli/index.d.ts.map +0 -1
  102. package/dist/cli/index.js +0 -19
  103. package/dist/cli/index.js.map +0 -1
  104. package/dist/commands.d.ts +0 -61
  105. package/dist/commands.d.ts.map +0 -1
  106. package/dist/commands.js +0 -861
  107. package/dist/commands.js.map +0 -1
  108. package/dist/config/index.d.ts +0 -71
  109. package/dist/config/index.d.ts.map +0 -1
  110. package/dist/config/index.js +0 -314
  111. package/dist/config/index.js.map +0 -1
  112. package/dist/core/change-detection.d.ts +0 -80
  113. package/dist/core/change-detection.d.ts.map +0 -1
  114. package/dist/core/change-detection.js +0 -523
  115. package/dist/core/change-detection.js.map +0 -1
  116. package/dist/core/config.d.ts +0 -81
  117. package/dist/core/config.d.ts.map +0 -1
  118. package/dist/core/config.js +0 -258
  119. package/dist/core/config.js.map +0 -1
  120. package/dist/core/index.d.ts +0 -6
  121. package/dist/core/index.d.ts.map +0 -1
  122. package/dist/core/index.js +0 -6
  123. package/dist/core/index.js.map +0 -1
  124. package/dist/core/move-detection.d.ts +0 -34
  125. package/dist/core/move-detection.d.ts.map +0 -1
  126. package/dist/core/move-detection.js +0 -121
  127. package/dist/core/move-detection.js.map +0 -1
  128. package/dist/core/snapshot.d.ts +0 -105
  129. package/dist/core/snapshot.d.ts.map +0 -1
  130. package/dist/core/snapshot.js +0 -217
  131. package/dist/core/snapshot.js.map +0 -1
  132. package/dist/core/sync-engine.d.ts +0 -151
  133. package/dist/core/sync-engine.d.ts.map +0 -1
  134. package/dist/core/sync-engine.js +0 -1346
  135. package/dist/core/sync-engine.js.map +0 -1
  136. package/dist/types/config.d.ts +0 -99
  137. package/dist/types/config.d.ts.map +0 -1
  138. package/dist/types/config.js +0 -5
  139. package/dist/types/config.js.map +0 -1
  140. package/dist/types/documents.d.ts +0 -88
  141. package/dist/types/documents.d.ts.map +0 -1
  142. package/dist/types/documents.js +0 -20
  143. package/dist/types/documents.js.map +0 -1
  144. package/dist/types/index.d.ts +0 -4
  145. package/dist/types/index.d.ts.map +0 -1
  146. package/dist/types/index.js +0 -4
  147. package/dist/types/index.js.map +0 -1
  148. package/dist/types/snapshot.d.ts +0 -64
  149. package/dist/types/snapshot.d.ts.map +0 -1
  150. package/dist/types/snapshot.js +0 -2
  151. package/dist/types/snapshot.js.map +0 -1
  152. package/dist/utils/content-similarity.d.ts +0 -53
  153. package/dist/utils/content-similarity.d.ts.map +0 -1
  154. package/dist/utils/content-similarity.js +0 -155
  155. package/dist/utils/content-similarity.js.map +0 -1
  156. package/dist/utils/content.d.ts +0 -10
  157. package/dist/utils/content.d.ts.map +0 -1
  158. package/dist/utils/content.js +0 -31
  159. package/dist/utils/content.js.map +0 -1
  160. package/dist/utils/directory.d.ts +0 -24
  161. package/dist/utils/directory.d.ts.map +0 -1
  162. package/dist/utils/directory.js +0 -52
  163. package/dist/utils/directory.js.map +0 -1
  164. package/dist/utils/fs.d.ts +0 -74
  165. package/dist/utils/fs.d.ts.map +0 -1
  166. package/dist/utils/fs.js +0 -248
  167. package/dist/utils/fs.js.map +0 -1
  168. package/dist/utils/index.d.ts +0 -5
  169. package/dist/utils/index.d.ts.map +0 -1
  170. package/dist/utils/index.js +0 -5
  171. package/dist/utils/index.js.map +0 -1
  172. package/dist/utils/mime-types.d.ts +0 -13
  173. package/dist/utils/mime-types.d.ts.map +0 -1
  174. package/dist/utils/mime-types.js +0 -209
  175. package/dist/utils/mime-types.js.map +0 -1
  176. package/dist/utils/network-sync.d.ts +0 -36
  177. package/dist/utils/network-sync.d.ts.map +0 -1
  178. package/dist/utils/network-sync.js +0 -250
  179. package/dist/utils/network-sync.js.map +0 -1
  180. package/dist/utils/node-polyfills.d.ts +0 -9
  181. package/dist/utils/node-polyfills.d.ts.map +0 -1
  182. package/dist/utils/node-polyfills.js +0 -9
  183. package/dist/utils/node-polyfills.js.map +0 -1
  184. package/dist/utils/output.d.ts +0 -129
  185. package/dist/utils/output.d.ts.map +0 -1
  186. package/dist/utils/output.js +0 -368
  187. package/dist/utils/output.js.map +0 -1
  188. package/dist/utils/repo-factory.d.ts +0 -13
  189. package/dist/utils/repo-factory.d.ts.map +0 -1
  190. package/dist/utils/repo-factory.js +0 -46
  191. package/dist/utils/repo-factory.js.map +0 -1
  192. package/dist/utils/string-similarity.d.ts +0 -14
  193. package/dist/utils/string-similarity.d.ts.map +0 -1
  194. package/dist/utils/string-similarity.js +0 -39
  195. package/dist/utils/string-similarity.js.map +0 -1
  196. package/dist/utils/text-diff.d.ts +0 -37
  197. package/dist/utils/text-diff.d.ts.map +0 -1
  198. package/dist/utils/text-diff.js +0 -93
  199. package/dist/utils/text-diff.js.map +0 -1
  200. package/dist/utils/trace.d.ts +0 -19
  201. package/dist/utils/trace.d.ts.map +0 -1
  202. package/dist/utils/trace.js +0 -63
  203. package/dist/utils/trace.js.map +0 -1
  204. package/src/commands.ts +0 -1134
  205. package/src/core/change-detection.ts +0 -712
  206. package/src/core/config.ts +0 -313
  207. package/src/core/index.ts +0 -5
  208. package/src/core/move-detection.ts +0 -169
  209. package/src/core/snapshot.ts +0 -275
  210. package/src/core/sync-engine.ts +0 -1758
  211. package/src/types/config.ts +0 -111
  212. package/src/types/documents.ts +0 -91
  213. package/src/types/index.ts +0 -3
  214. package/src/types/snapshot.ts +0 -67
  215. package/src/utils/content.ts +0 -34
  216. package/src/utils/directory.ts +0 -73
  217. package/src/utils/fs.ts +0 -297
  218. package/src/utils/index.ts +0 -4
  219. package/src/utils/mime-types.ts +0 -244
  220. package/src/utils/network-sync.ts +0 -319
  221. package/src/utils/node-polyfills.ts +0 -8
  222. package/src/utils/output.ts +0 -450
  223. package/src/utils/repo-factory.ts +0 -73
  224. package/src/utils/string-similarity.ts +0 -54
  225. package/src/utils/text-diff.ts +0 -101
  226. package/src/utils/trace.ts +0 -70
  227. package/test/integration/README.md +0 -328
  228. package/test/integration/clone-test.sh +0 -310
  229. package/test/integration/conflict-resolution-test.sh +0 -309
  230. package/test/integration/debug-both-nested.sh +0 -74
  231. package/test/integration/debug-concurrent-nested.sh +0 -87
  232. package/test/integration/debug-nested.sh +0 -73
  233. package/test/integration/deletion-behavior-test.sh +0 -487
  234. package/test/integration/deletion-sync-test-simple.sh +0 -193
  235. package/test/integration/deletion-sync-test.sh +0 -297
  236. package/test/integration/exclude-patterns.test.ts +0 -144
  237. package/test/integration/full-integration-test.sh +0 -363
  238. package/test/integration/fuzzer.test.ts +0 -818
  239. package/test/integration/in-memory-sync.test.ts +0 -830
  240. package/test/integration/init-sync.test.ts +0 -89
  241. package/test/integration/manual-sync-test.sh +0 -84
  242. package/test/integration/sync-deletion.test.ts +0 -280
  243. package/test/integration/sync-flow.test.ts +0 -291
  244. package/test/jest.setup.ts +0 -34
  245. package/test/run-tests.sh +0 -225
  246. package/test/unit/deletion-behavior.test.ts +0 -249
  247. package/test/unit/enhanced-mime-detection.test.ts +0 -244
  248. package/test/unit/snapshot.test.ts +0 -404
  249. package/test/unit/sync-convergence.test.ts +0 -298
  250. package/test/unit/sync-timing.test.ts +0 -134
  251. package/test/unit/utils.test.ts +0 -366
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "pushwork",
3
- "version": "2.0.0-a.sub.0",
3
+ "version": "2.0.0-preview",
4
4
  "description": "Bidirectional directory synchronization using Automerge CRDTs",
5
- "type": "module",
6
5
  "main": "dist/index.js",
7
6
  "exports": {
8
7
  ".": "./dist/index.js"
@@ -10,7 +9,6 @@
10
9
  "bin": {
11
10
  "pushwork": "./dist/cli.js"
12
11
  },
13
- "packageManager": "pnpm@8.15.0",
14
12
  "engines": {
15
13
  "node": ">=24.0.0",
16
14
  "pnpm": ">=8.0.0"
@@ -25,72 +23,41 @@
25
23
  "author": "Peter van Hardenberg",
26
24
  "license": "MIT",
27
25
  "dependencies": {
28
- "@automerge/automerge": "^3.2.4",
29
- "@automerge/automerge-repo": "2.6.0-subduction.3",
30
- "@automerge/automerge-repo-storage-nodefs": "2.6.0-subduction.3",
31
- "@automerge/automerge-repo-subduction-bridge": "2.6.0-subduction.3",
32
- "@automerge/automerge-subduction": "*",
26
+ "@automerge/automerge": "^3.2.6",
27
+ "@automerge/automerge-repo": "2.6.0-subduction.15",
28
+ "@automerge/automerge-repo-network-websocket": "2.6.0-subduction.15",
29
+ "@automerge/automerge-repo-storage-nodefs": "2.6.0-subduction.15",
30
+ "@automerge/automerge-subduction": "0.8.1",
33
31
  "@commander-js/extra-typings": "^14.0.0",
34
32
  "chalk": "^5.3.0",
35
33
  "commander": "^14.0.2",
34
+ "debug": "^4.4.3",
36
35
  "diff": "^8.0.2",
37
- "fake-indexeddb": "^6.2.5",
38
36
  "glob": "^10.3.0",
39
37
  "ignore": "^5.3.0",
40
38
  "mime-types": "^2.1.35",
41
39
  "ora": "^7.0.1"
42
40
  },
43
41
  "devDependencies": {
44
- "@babel/core": "^7.28.6",
45
- "@babel/preset-env": "^7.28.6",
42
+ "@types/debug": "^4.1.13",
46
43
  "@types/diff": "^5.0.3",
47
- "@types/jest": "^29.5.0",
48
44
  "@types/mime-types": "^2.1.1",
49
45
  "@types/node": "^20.0.0",
50
46
  "@types/tmp": "^0.2.4",
51
- "babel-jest": "^30.2.0",
47
+ "@vitest/coverage-v8": "^2.1.0",
52
48
  "fast-check": "^4.3.0",
53
- "jest": "^29.7.0",
54
49
  "tmp": "^0.2.1",
55
- "ts-jest": "^29.1.0",
56
50
  "tsx": "^4.19.2",
57
- "typescript": "^5.2.0"
58
- },
59
- "jest": {
60
- "preset": "ts-jest",
61
- "testEnvironment": "node",
62
- "roots": [
63
- "<rootDir>/src",
64
- "<rootDir>/test"
65
- ],
66
- "testMatch": [
67
- "**/__tests__/**/*.ts",
68
- "**/*.(test|spec).ts"
69
- ],
70
- "collectCoverageFrom": [
71
- "src/**/*.ts",
72
- "!src/**/*.d.ts"
73
- ],
74
- "setupFilesAfterEnv": [
75
- "<rootDir>/test/jest.setup.ts"
76
- ],
77
- "maxWorkers": "75%",
78
- "maxConcurrency": 10,
79
- "transformIgnorePatterns": [
80
- "node_modules/(?!.*@automerge)"
81
- ],
82
- "transform": {
83
- "^.+\\.tsx?$": "ts-jest",
84
- "^.+\\.jsx?$": "babel-jest"
85
- }
51
+ "typescript": "^5.2.0",
52
+ "vitest": "^2.1.0"
86
53
  },
87
54
  "scripts": {
88
55
  "build": "tsc",
89
56
  "dev": "tsc --watch",
90
- "test": "jest",
91
- "test:bail": "jest --bail",
92
- "test:watch": "jest --watch",
93
- "test:coverage": "jest --coverage",
57
+ "test": "vitest run",
58
+ "test:bail": "vitest run --bail 1",
59
+ "test:watch": "vitest",
60
+ "test:coverage": "vitest run --coverage",
94
61
  "lint": "eslint src --ext .ts",
95
62
  "lint:fix": "eslint src --ext .ts --fix",
96
63
  "clean": "rm -rf dist",
@@ -0,0 +1,26 @@
1
+ diff --git a/dist/helpers/throttle.js b/dist/helpers/throttle.js
2
+ index 92f3cc8ed8b0c870aa9f52fa6e3605d736364534..8822b477e3800f163b58a153e747f2a7090c0d38 100644
3
+ --- a/dist/helpers/throttle.js
4
+ +++ b/dist/helpers/throttle.js
5
+ @@ -31,7 +31,7 @@ export const throttle = (fn, delay) => {
6
+ let pendingArgs;
7
+ const throttled = function (...args) {
8
+ pendingArgs = args;
9
+ - wait = lastCall + delay - Date.now();
10
+ + wait = Math.max(0, lastCall + delay - Date.now());
11
+ clearTimeout(timeout);
12
+ timeout = setTimeout(() => {
13
+ timeout = undefined;
14
+ diff --git a/src/helpers/throttle.ts b/src/helpers/throttle.ts
15
+ index a0933cdc809ed9944f2129c943ac0c9e90bcd195..43050dc0375031bc4490162a7314e3b3541a3f40 100644
16
+ --- a/src/helpers/throttle.ts
17
+ +++ b/src/helpers/throttle.ts
18
+ @@ -42,7 +42,7 @@ export const throttle = <F extends (...args: any[]) => any>(
19
+
20
+ const throttled = function (...args: Parameters<F>) {
21
+ pendingArgs = args
22
+ - wait = lastCall + delay - Date.now()
23
+ + wait = Math.max(0, lastCall + delay - Date.now())
24
+ clearTimeout(timeout)
25
+ timeout = setTimeout(() => {
26
+ timeout = undefined
@@ -0,0 +1,5 @@
1
+ allowBuilds:
2
+ cbor-extract: true
3
+ esbuild: true
4
+ patchedDependencies:
5
+ '@automerge/automerge-repo@2.6.0-subduction.15': patches/@automerge__automerge-repo@2.6.0-subduction.15.patch
@@ -0,0 +1,93 @@
1
+ import * as fs from "fs/promises";
2
+ import * as path from "path";
3
+ import {
4
+ type AutomergeUrl,
5
+ type DocHandle,
6
+ type Repo,
7
+ } from "@automerge/automerge-repo";
8
+ import { log } from "./log.js";
9
+
10
+ const dlog = log("branches");
11
+
12
+ export const META = "@patchwork";
13
+ export const DEFAULT_BRANCH = "default";
14
+
15
+ export type BranchesDoc = {
16
+ "@patchwork": { type: "branches" };
17
+ branches: { [name: string]: AutomergeUrl };
18
+ };
19
+
20
+ export const isBranchesDoc = (doc: unknown): doc is BranchesDoc => {
21
+ if (!doc || typeof doc !== "object") return false;
22
+ const meta = (doc as Record<string, unknown>)[META];
23
+ return (
24
+ !!meta &&
25
+ typeof meta === "object" &&
26
+ (meta as Record<string, unknown>).type === "branches"
27
+ );
28
+ };
29
+
30
+ export function detectDocType(
31
+ doc: unknown,
32
+ ): "branches" | "folder" | "directory" | "unknown" {
33
+ if (!doc || typeof doc !== "object") return "unknown";
34
+ const meta = (doc as Record<string, unknown>)[META];
35
+ if (!meta || typeof meta !== "object") return "unknown";
36
+ const t = (meta as Record<string, unknown>).type;
37
+ if (t === "branches" || t === "folder" || t === "directory") return t;
38
+ return "unknown";
39
+ }
40
+
41
+ export async function resolveEffectiveRoot(
42
+ repo: Repo,
43
+ rootHandle: DocHandle<unknown>,
44
+ branchName: string | null,
45
+ ): Promise<DocHandle<unknown>> {
46
+ const doc = rootHandle.doc();
47
+ if (!isBranchesDoc(doc)) return rootHandle;
48
+ if (!branchName) {
49
+ throw new Error(
50
+ "pushwork repo uses branches but no branch name is set",
51
+ );
52
+ }
53
+ const url = doc.branches?.[branchName];
54
+ if (!url) {
55
+ throw new Error(
56
+ `branch "${branchName}" not found in branches doc ${rootHandle.url}`,
57
+ );
58
+ }
59
+ dlog("resolveEffectiveRoot branch=%s → %s", branchName, url);
60
+ return repo.find<unknown>(url);
61
+ }
62
+
63
+ export function listBranchNames(branchesDoc: BranchesDoc): string[] {
64
+ return Object.keys(branchesDoc.branches ?? {}).sort();
65
+ }
66
+
67
+ const BRANCH_FILE = path.join(".pushwork", "branch");
68
+
69
+ export async function readBranchFile(root: string): Promise<string | null> {
70
+ try {
71
+ const text = await fs.readFile(path.join(root, BRANCH_FILE), "utf8");
72
+ return text.trim() || null;
73
+ } catch (err) {
74
+ if ((err as NodeJS.ErrnoException).code === "ENOENT") return null;
75
+ throw err;
76
+ }
77
+ }
78
+
79
+ export async function writeBranchFile(
80
+ root: string,
81
+ branchName: string,
82
+ ): Promise<void> {
83
+ await fs.mkdir(path.join(root, ".pushwork"), { recursive: true });
84
+ await fs.writeFile(path.join(root, BRANCH_FILE), branchName + "\n");
85
+ }
86
+
87
+ export async function deleteBranchFile(root: string): Promise<void> {
88
+ try {
89
+ await fs.unlink(path.join(root, BRANCH_FILE));
90
+ } catch (err) {
91
+ if ((err as NodeJS.ErrnoException).code !== "ENOENT") throw err;
92
+ }
93
+ }