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/src/config.ts ADDED
@@ -0,0 +1,64 @@
1
+ import * as fs from "fs/promises";
2
+ import * as path from "path";
3
+ import type { AutomergeUrl } from "@automerge/automerge-repo";
4
+
5
+ export type Backend = "legacy" | "subduction";
6
+
7
+ export const CONFIG_VERSION = 3;
8
+
9
+ export interface PushworkConfig {
10
+ version: typeof CONFIG_VERSION;
11
+ rootUrl: AutomergeUrl;
12
+ backend: Backend;
13
+ shape: string;
14
+ artifactDirectories: string[];
15
+ branches: boolean;
16
+ }
17
+
18
+ const DIR = ".pushwork";
19
+ const CONFIG = "config.json";
20
+ const STORAGE = "storage";
21
+
22
+ export const pushworkDir = (root: string) => path.join(root, DIR);
23
+ export const storageDir = (root: string) => path.join(root, DIR, STORAGE);
24
+
25
+ export async function readConfig(root: string): Promise<PushworkConfig> {
26
+ const text = await fs.readFile(path.join(root, DIR, CONFIG), "utf8");
27
+ const parsed = JSON.parse(text) as Partial<PushworkConfig>;
28
+ if (parsed.version !== CONFIG_VERSION) {
29
+ throw new Error(
30
+ `pushwork config version mismatch: expected ${CONFIG_VERSION}, got ${parsed.version ?? "(missing)"}`,
31
+ );
32
+ }
33
+ if (!parsed.rootUrl) throw new Error("pushwork config missing rootUrl");
34
+ if (!parsed.backend) throw new Error("pushwork config missing backend");
35
+ if (!parsed.shape) throw new Error("pushwork config missing shape");
36
+ return {
37
+ version: CONFIG_VERSION,
38
+ rootUrl: parsed.rootUrl,
39
+ backend: parsed.backend,
40
+ shape: parsed.shape,
41
+ artifactDirectories: parsed.artifactDirectories ?? [],
42
+ branches: parsed.branches ?? true,
43
+ };
44
+ }
45
+
46
+ export async function writeConfig(
47
+ root: string,
48
+ config: PushworkConfig,
49
+ ): Promise<void> {
50
+ await fs.mkdir(path.join(root, DIR), { recursive: true });
51
+ await fs.writeFile(
52
+ path.join(root, DIR, CONFIG),
53
+ JSON.stringify(config, null, 2) + "\n",
54
+ );
55
+ }
56
+
57
+ export async function configExists(root: string): Promise<boolean> {
58
+ try {
59
+ await fs.access(path.join(root, DIR, CONFIG));
60
+ return true;
61
+ } catch {
62
+ return false;
63
+ }
64
+ }
package/src/fs-tree.ts ADDED
@@ -0,0 +1,70 @@
1
+ import * as fs from "fs/promises";
2
+ import * as path from "path";
3
+ import type { Ignore } from "ignore";
4
+ import { isIgnored } from "./ignore.js";
5
+ import { log } from "./log.js";
6
+
7
+ const dlog = log("fs-tree");
8
+
9
+ export type FileTree = Map<string, Uint8Array>;
10
+
11
+ const toPosix = (p: string) => p.split(path.sep).join("/");
12
+
13
+ export async function walkDir(root: string, ig: Ignore): Promise<FileTree> {
14
+ dlog("walkDir root=%s", root);
15
+ const tree: FileTree = new Map();
16
+ await walk(root, root, ig, tree);
17
+ dlog("walkDir done: %d files", tree.size);
18
+ return tree;
19
+ }
20
+
21
+ async function walk(
22
+ root: string,
23
+ current: string,
24
+ ig: Ignore,
25
+ tree: FileTree,
26
+ ): Promise<void> {
27
+ let names: string[];
28
+ try {
29
+ names = await fs.readdir(current);
30
+ } catch {
31
+ return;
32
+ }
33
+ for (const name of names) {
34
+ const full = path.join(current, name);
35
+ const rel = toPosix(path.relative(root, full));
36
+ if (isIgnored(ig, rel)) {
37
+ dlog("skip ignored: %s", rel);
38
+ continue;
39
+ }
40
+ let stat;
41
+ try {
42
+ stat = await fs.lstat(full);
43
+ } catch {
44
+ continue;
45
+ }
46
+ if (stat.isSymbolicLink()) continue;
47
+ if (stat.isDirectory()) {
48
+ await walk(root, full, ig, tree);
49
+ } else if (stat.isFile()) {
50
+ const bytes = await fs.readFile(full);
51
+ tree.set(rel, new Uint8Array(bytes));
52
+ }
53
+ }
54
+ }
55
+
56
+ export function byteEq(a: Uint8Array | undefined, b: Uint8Array): boolean {
57
+ if (!a) return false;
58
+ if (a.length !== b.length) return false;
59
+ for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
60
+ return true;
61
+ }
62
+
63
+ export async function writeFileAtomic(
64
+ target: string,
65
+ bytes: Uint8Array,
66
+ ): Promise<void> {
67
+ await fs.mkdir(path.dirname(target), { recursive: true });
68
+ await fs.writeFile(target, bytes);
69
+ }
70
+
package/src/ignore.ts ADDED
@@ -0,0 +1,33 @@
1
+ import * as fs from "fs/promises";
2
+ import * as path from "path";
3
+ import ignore, { type Ignore } from "ignore";
4
+ import { log } from "./log.js";
5
+
6
+ const dlog = log("ignore");
7
+
8
+ export const ALWAYS_IGNORE = [".pushwork", ".git", "node_modules"];
9
+ export const IGNORE_FILE = ".pushworkignore";
10
+
11
+ export async function loadIgnore(root: string): Promise<Ignore> {
12
+ const ig = ignore().add(ALWAYS_IGNORE);
13
+ dlog("always-ignored: %o", ALWAYS_IGNORE);
14
+ try {
15
+ const text = await fs.readFile(path.join(root, IGNORE_FILE), "utf8");
16
+ const patterns = text
17
+ .split(/\r?\n/)
18
+ .map((l) => l.trim())
19
+ .filter((l) => l && !l.startsWith("#"));
20
+ ig.add(patterns);
21
+ dlog("loaded %d patterns from %s", patterns.length, IGNORE_FILE);
22
+ } catch (err) {
23
+ const e = err as NodeJS.ErrnoException;
24
+ if (e.code !== "ENOENT") throw err;
25
+ dlog("no %s in %s", IGNORE_FILE, root);
26
+ }
27
+ return ig;
28
+ }
29
+
30
+ export function isIgnored(ig: Ignore, relativePath: string): boolean {
31
+ if (relativePath === "" || relativePath === ".") return false;
32
+ return ig.ignores(relativePath);
33
+ }
package/src/index.ts CHANGED
@@ -1,4 +1,38 @@
1
- export * from "./core/index.js";
2
- export * from "./utils/index.js";
3
- export * from "./types/index.js";
4
- export * from "./cli.js";
1
+ export {
2
+ init,
3
+ clone,
4
+ sync,
5
+ save,
6
+ status,
7
+ diff,
8
+ url,
9
+ currentBranch,
10
+ createBranch,
11
+ switchBranch,
12
+ listBranches,
13
+ mergeBranch,
14
+ previewMerge,
15
+ cutWorkdir,
16
+ pasteStash,
17
+ showStashes,
18
+ } from "./pushwork.js";
19
+ export type { MergeReport, MergePreview, MergePreviewEntry } from "./pushwork.js";
20
+ export type { Stash, StashEntry } from "./stash.js";
21
+ export type { Backend, PushworkConfig } from "./config.js";
22
+ export { CONFIG_VERSION } from "./config.js";
23
+ export type { Shape, VfsNode, UnixFileEntry } from "./shapes/index.js";
24
+ export {
25
+ vfsShape,
26
+ patchworkFolderShape,
27
+ isInArtifactDir,
28
+ normalizeArtifactDir,
29
+ pinUrl,
30
+ stripHeads,
31
+ } from "./shapes/index.js";
32
+ export {
33
+ DEFAULT_BRANCH,
34
+ detectDocType,
35
+ isBranchesDoc,
36
+ resolveEffectiveRoot,
37
+ type BranchesDoc,
38
+ } from "./branches.js";
package/src/log.ts ADDED
@@ -0,0 +1,8 @@
1
+ import debug from "debug";
2
+
3
+ if (process.env.DEBUG === "true") {
4
+ process.env.DEBUG = "*";
5
+ debug.enable("*");
6
+ }
7
+
8
+ export const log = (ns: string) => debug(`pushwork:${ns}`);