pushwork 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +460 -0
- package/dist/browser/browser-sync-engine.d.ts +64 -0
- package/dist/browser/browser-sync-engine.d.ts.map +1 -0
- package/dist/browser/browser-sync-engine.js +303 -0
- package/dist/browser/browser-sync-engine.js.map +1 -0
- package/dist/browser/filesystem-adapter.d.ts +84 -0
- package/dist/browser/filesystem-adapter.d.ts.map +1 -0
- package/dist/browser/filesystem-adapter.js +413 -0
- package/dist/browser/filesystem-adapter.js.map +1 -0
- package/dist/browser/index.d.ts +36 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +90 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/types.d.ts +70 -0
- package/dist/browser/types.d.ts.map +1 -0
- package/dist/browser/types.js +6 -0
- package/dist/browser/types.js.map +1 -0
- package/dist/cli/commands.d.ts +71 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +794 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +19 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +199 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/index.d.ts +71 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +314 -0
- package/dist/config/index.js.map +1 -0
- package/dist/core/change-detection.d.ts +78 -0
- package/dist/core/change-detection.d.ts.map +1 -0
- package/dist/core/change-detection.js +370 -0
- package/dist/core/change-detection.js.map +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +22 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/isomorphic-snapshot.d.ts +58 -0
- package/dist/core/isomorphic-snapshot.d.ts.map +1 -0
- package/dist/core/isomorphic-snapshot.js +204 -0
- package/dist/core/isomorphic-snapshot.js.map +1 -0
- package/dist/core/move-detection.d.ts +72 -0
- package/dist/core/move-detection.d.ts.map +1 -0
- package/dist/core/move-detection.js +200 -0
- package/dist/core/move-detection.js.map +1 -0
- package/dist/core/snapshot.d.ts +109 -0
- package/dist/core/snapshot.d.ts.map +1 -0
- package/dist/core/snapshot.js +263 -0
- package/dist/core/snapshot.js.map +1 -0
- package/dist/core/sync-engine.d.ts +110 -0
- package/dist/core/sync-engine.d.ts.map +1 -0
- package/dist/core/sync-engine.js +817 -0
- package/dist/core/sync-engine.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/platform/browser-filesystem.d.ts +26 -0
- package/dist/platform/browser-filesystem.d.ts.map +1 -0
- package/dist/platform/browser-filesystem.js +91 -0
- package/dist/platform/browser-filesystem.js.map +1 -0
- package/dist/platform/filesystem.d.ts +29 -0
- package/dist/platform/filesystem.d.ts.map +1 -0
- package/dist/platform/filesystem.js +65 -0
- package/dist/platform/filesystem.js.map +1 -0
- package/dist/platform/node-filesystem.d.ts +21 -0
- package/dist/platform/node-filesystem.d.ts.map +1 -0
- package/dist/platform/node-filesystem.js +93 -0
- package/dist/platform/node-filesystem.js.map +1 -0
- package/dist/types/config.d.ts +119 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +3 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/documents.d.ts +70 -0
- package/dist/types/documents.d.ts.map +1 -0
- package/dist/types/documents.js +23 -0
- package/dist/types/documents.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +23 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/snapshot.d.ts +81 -0
- package/dist/types/snapshot.d.ts.map +1 -0
- package/dist/types/snapshot.js +17 -0
- package/dist/types/snapshot.js.map +1 -0
- package/dist/utils/content-similarity.d.ts +53 -0
- package/dist/utils/content-similarity.d.ts.map +1 -0
- package/dist/utils/content-similarity.js +155 -0
- package/dist/utils/content-similarity.js.map +1 -0
- package/dist/utils/content.d.ts +5 -0
- package/dist/utils/content.d.ts.map +1 -0
- package/dist/utils/content.js +30 -0
- package/dist/utils/content.js.map +1 -0
- package/dist/utils/fs-browser.d.ts +57 -0
- package/dist/utils/fs-browser.d.ts.map +1 -0
- package/dist/utils/fs-browser.js +311 -0
- package/dist/utils/fs-browser.js.map +1 -0
- package/dist/utils/fs-node.d.ts +53 -0
- package/dist/utils/fs-node.d.ts.map +1 -0
- package/dist/utils/fs-node.js +220 -0
- package/dist/utils/fs-node.js.map +1 -0
- package/dist/utils/fs.d.ts +62 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +293 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +23 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/isomorphic.d.ts +29 -0
- package/dist/utils/isomorphic.d.ts.map +1 -0
- package/dist/utils/isomorphic.js +139 -0
- package/dist/utils/isomorphic.js.map +1 -0
- package/dist/utils/mime-types.d.ts +13 -0
- package/dist/utils/mime-types.d.ts.map +1 -0
- package/dist/utils/mime-types.js +240 -0
- package/dist/utils/mime-types.js.map +1 -0
- package/dist/utils/network-sync.d.ts +12 -0
- package/dist/utils/network-sync.d.ts.map +1 -0
- package/dist/utils/network-sync.js +149 -0
- package/dist/utils/network-sync.js.map +1 -0
- package/dist/utils/pure.d.ts +25 -0
- package/dist/utils/pure.d.ts.map +1 -0
- package/dist/utils/pure.js +112 -0
- package/dist/utils/pure.js.map +1 -0
- package/dist/utils/repo-factory.d.ts +11 -0
- package/dist/utils/repo-factory.d.ts.map +1 -0
- package/dist/utils/repo-factory.js +77 -0
- package/dist/utils/repo-factory.js.map +1 -0
- package/package.json +83 -0
- package/src/cli/commands.ts +1053 -0
- package/src/cli/index.ts +2 -0
- package/src/cli.ts +287 -0
- package/src/config/index.ts +334 -0
- package/src/core/change-detection.ts +484 -0
- package/src/core/index.ts +5 -0
- package/src/core/move-detection.ts +269 -0
- package/src/core/snapshot.ts +285 -0
- package/src/core/sync-engine.ts +1167 -0
- package/src/index.ts +14 -0
- package/src/types/config.ts +130 -0
- package/src/types/documents.ts +72 -0
- package/src/types/index.ts +8 -0
- package/src/types/snapshot.ts +88 -0
- package/src/utils/content-similarity.ts +194 -0
- package/src/utils/content.ts +28 -0
- package/src/utils/fs.ts +289 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/mime-types.ts +236 -0
- package/src/utils/network-sync.ts +153 -0
- package/src/utils/repo-factory.ts +58 -0
- package/test/README-TESTING-GAPS.md +174 -0
- package/test/integration/README.md +328 -0
- package/test/integration/clone-test.sh +310 -0
- package/test/integration/conflict-resolution-test.sh +309 -0
- package/test/integration/deletion-behavior-test.sh +487 -0
- package/test/integration/deletion-sync-test-simple.sh +193 -0
- package/test/integration/deletion-sync-test.sh +297 -0
- package/test/integration/exclude-patterns.test.ts +152 -0
- package/test/integration/full-integration-test.sh +363 -0
- package/test/integration/sync-deletion.test.ts +339 -0
- package/test/integration/sync-flow.test.ts +309 -0
- package/test/run-tests.sh +225 -0
- package/test/unit/content-similarity.test.ts +236 -0
- package/test/unit/deletion-behavior.test.ts +260 -0
- package/test/unit/enhanced-mime-detection.test.ts +266 -0
- package/test/unit/snapshot.test.ts +431 -0
- package/test/unit/sync-timing.test.ts +178 -0
- package/test/unit/utils.test.ts +368 -0
- package/tools/browser-sync/README.md +116 -0
- package/tools/browser-sync/package.json +44 -0
- package/tools/browser-sync/patchwork.json +1 -0
- package/tools/browser-sync/pnpm-lock.yaml +4202 -0
- package/tools/browser-sync/src/components/BrowserSyncTool.tsx +599 -0
- package/tools/browser-sync/src/index.ts +20 -0
- package/tools/browser-sync/src/polyfills.ts +31 -0
- package/tools/browser-sync/src/styles.css +290 -0
- package/tools/browser-sync/src/types.ts +27 -0
- package/tools/browser-sync/vite.config.ts +25 -0
- package/tsconfig.json +22 -0
package/README.md
ADDED
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
# Pushwork
|
|
2
|
+
|
|
3
|
+
A bidirectional file synchronization system using Automerge CRDTs for conflict-free collaborative editing.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Pushwork enables real-time collaboration on directories and files using **Conflict-free Replicated Data Types (CRDTs)**. Unlike traditional sync tools that require manual conflict resolution, Pushwork automatically merges changes from multiple users while preserving everyone's work.
|
|
8
|
+
|
|
9
|
+
## ✨ Key Features
|
|
10
|
+
|
|
11
|
+
- **🔄 Bidirectional Sync**: Keep local directories synchronized with remote Automerge repositories
|
|
12
|
+
- **🚫 Conflict-Free**: Automatic conflict resolution using Automerge CRDTs - no merge conflicts ever
|
|
13
|
+
- **📱 Real-time Collaboration**: Multiple users can edit the same files simultaneously
|
|
14
|
+
- **🧠 Intelligent Move Detection**: Detects file renames and moves based on content similarity
|
|
15
|
+
- **⚡ Incremental Sync**: Only synchronizes changed files for maximum efficiency
|
|
16
|
+
- **🌐 Network Resilient**: Works offline and gracefully handles network interruptions
|
|
17
|
+
- **🖥️ Cross-Platform**: Runs on Windows, macOS, and Linux
|
|
18
|
+
- **🛠️ Rich CLI**: Full-featured command-line interface with comprehensive tooling
|
|
19
|
+
|
|
20
|
+
## 🚀 Quick Start
|
|
21
|
+
|
|
22
|
+
### Installation
|
|
23
|
+
|
|
24
|
+
Currently, install from source:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pnpm install
|
|
28
|
+
pnpm run build
|
|
29
|
+
pnpm link
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Basic Usage
|
|
33
|
+
|
|
34
|
+
1. **Initialize a new repository:**
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pushwork init ./my-project
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
2. **Clone an existing repository:**
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pushwork clone <automerge-url> ./cloned-project
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
3. **Sync changes:**
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pushwork sync
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
4. **Check status:**
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pushwork status
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## 📚 Commands
|
|
59
|
+
|
|
60
|
+
### `init <path> [options]`
|
|
61
|
+
|
|
62
|
+
Initialize sync in a directory, creating a new Automerge repository.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# Initialize with default sync server
|
|
66
|
+
pushwork init ./my-project
|
|
67
|
+
|
|
68
|
+
# Initialize with custom sync server
|
|
69
|
+
pushwork init ./my-project \
|
|
70
|
+
--sync-server ws://localhost:3030 \
|
|
71
|
+
--sync-server-storage-id your-storage-id
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Options:**
|
|
75
|
+
|
|
76
|
+
- `--sync-server <url>`: Custom sync server URL (requires storage-id)
|
|
77
|
+
- `--sync-server-storage-id <id>`: Custom sync server storage ID (requires server)
|
|
78
|
+
|
|
79
|
+
### `clone <url> <path> [options]`
|
|
80
|
+
|
|
81
|
+
Clone an existing synced directory from an Automerge URL.
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Clone from default sync server
|
|
85
|
+
pushwork clone automerge:abc123... ./cloned-project
|
|
86
|
+
|
|
87
|
+
# Clone with custom sync server
|
|
88
|
+
pushwork clone automerge:abc123... ./cloned-project \
|
|
89
|
+
--sync-server ws://localhost:3030 \
|
|
90
|
+
--sync-server-storage-id your-storage-id
|
|
91
|
+
|
|
92
|
+
# Force overwrite existing directory
|
|
93
|
+
pushwork clone automerge:abc123... ./existing-dir --force
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Options:**
|
|
97
|
+
|
|
98
|
+
- `--force`: Overwrite existing directory
|
|
99
|
+
- `--sync-server <url>`: Custom sync server URL
|
|
100
|
+
- `--sync-server-storage-id <id>`: Custom sync server storage ID
|
|
101
|
+
|
|
102
|
+
### `sync [options]`
|
|
103
|
+
|
|
104
|
+
Run bidirectional synchronization between local files and remote repository.
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Preview changes without applying them
|
|
108
|
+
pushwork sync --dry-run
|
|
109
|
+
|
|
110
|
+
# Apply all changes
|
|
111
|
+
pushwork sync
|
|
112
|
+
|
|
113
|
+
# Verbose output
|
|
114
|
+
pushwork sync --verbose
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Options:**
|
|
118
|
+
|
|
119
|
+
- `--dry-run`: Preview changes without applying them
|
|
120
|
+
- `--verbose`: Show detailed progress information
|
|
121
|
+
|
|
122
|
+
### `diff [path] [options]`
|
|
123
|
+
|
|
124
|
+
Show differences between local and remote state.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# Show all changes
|
|
128
|
+
pushwork diff
|
|
129
|
+
|
|
130
|
+
# Show changes for specific path
|
|
131
|
+
pushwork diff src/
|
|
132
|
+
|
|
133
|
+
# Show only changed file names
|
|
134
|
+
pushwork diff --name-only
|
|
135
|
+
|
|
136
|
+
# Use external diff tool
|
|
137
|
+
pushwork diff --tool meld
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Options:**
|
|
141
|
+
|
|
142
|
+
- `--tool <tool>`: Use external diff tool (meld, vimdiff, etc.)
|
|
143
|
+
- `--name-only`: Show only changed file names
|
|
144
|
+
|
|
145
|
+
### `status`
|
|
146
|
+
|
|
147
|
+
Show current sync status and repository information.
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
pushwork status
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### `log [path] [options]`
|
|
154
|
+
|
|
155
|
+
Show sync history for the repository or specific files.
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Show repository history
|
|
159
|
+
pushwork log
|
|
160
|
+
|
|
161
|
+
# Compact one-line format
|
|
162
|
+
pushwork log --oneline
|
|
163
|
+
|
|
164
|
+
# History for specific path
|
|
165
|
+
pushwork log src/important-file.txt
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**Options:**
|
|
169
|
+
|
|
170
|
+
- `--oneline`: Compact one-line per sync format
|
|
171
|
+
- `--since <date>`: Show syncs since date
|
|
172
|
+
- `--limit <n>`: Limit number of syncs shown (default: 10)
|
|
173
|
+
|
|
174
|
+
### `url [path]`
|
|
175
|
+
|
|
176
|
+
Show the Automerge root URL for sharing with others.
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
# Get URL for current directory
|
|
180
|
+
pushwork url
|
|
181
|
+
|
|
182
|
+
# Get URL for specific directory
|
|
183
|
+
pushwork url ./my-project
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### `commit [path] [options]`
|
|
187
|
+
|
|
188
|
+
Commit local changes without network sync (useful for offline work).
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
# Commit all changes
|
|
192
|
+
pushwork commit
|
|
193
|
+
|
|
194
|
+
# Preview what would be committed
|
|
195
|
+
pushwork commit --dry-run
|
|
196
|
+
|
|
197
|
+
# Commit specific directory
|
|
198
|
+
pushwork commit ./src
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Options:**
|
|
202
|
+
|
|
203
|
+
- `--dry-run`: Show what would be committed without applying changes
|
|
204
|
+
|
|
205
|
+
### `checkout <sync-id> [path] [options]`
|
|
206
|
+
|
|
207
|
+
Restore directory to state from previous sync (not yet implemented).
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
# Restore entire directory
|
|
211
|
+
pushwork checkout sync-123
|
|
212
|
+
|
|
213
|
+
# Force checkout even with uncommitted changes
|
|
214
|
+
pushwork checkout sync-123 --force
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## ⚙️ Configuration
|
|
218
|
+
|
|
219
|
+
### Default Configuration
|
|
220
|
+
|
|
221
|
+
Pushwork uses sensible defaults:
|
|
222
|
+
|
|
223
|
+
- **Sync Server**: `wss://sync3.automerge.org`
|
|
224
|
+
- **Storage ID**: `3760df37-a4c6-4f66-9ecd-732039a9385d`
|
|
225
|
+
- **Excluded Patterns**: `.git`, `node_modules`, `*.tmp`, `.pushwork`
|
|
226
|
+
- **Large File Threshold**: 100MB
|
|
227
|
+
- **Move Detection Threshold**: 80% similarity
|
|
228
|
+
|
|
229
|
+
### Directory Configuration
|
|
230
|
+
|
|
231
|
+
Configuration is stored in `.pushwork/config.json`:
|
|
232
|
+
|
|
233
|
+
```json
|
|
234
|
+
{
|
|
235
|
+
"sync_server": "wss://sync3.automerge.org",
|
|
236
|
+
"sync_server_storage_id": "3760df37-a4c6-4f66-9ecd-732039a9385d",
|
|
237
|
+
"sync_enabled": true,
|
|
238
|
+
"defaults": {
|
|
239
|
+
"exclude_patterns": [".git", "node_modules", "*.tmp", ".pushwork"],
|
|
240
|
+
"large_file_threshold": "100MB"
|
|
241
|
+
},
|
|
242
|
+
"diff": {
|
|
243
|
+
"show_binary": false
|
|
244
|
+
},
|
|
245
|
+
"sync": {
|
|
246
|
+
"move_detection_threshold": 0.8,
|
|
247
|
+
"prompt_threshold": 0.5,
|
|
248
|
+
"auto_sync": false,
|
|
249
|
+
"parallel_operations": 4
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## 🔧 How It Works
|
|
255
|
+
|
|
256
|
+
### CRDT-Based Conflict Resolution
|
|
257
|
+
|
|
258
|
+
Pushwork uses **Automerge CRDTs** to automatically resolve conflicts:
|
|
259
|
+
|
|
260
|
+
- **Text Files**: Character-level merging preserves all changes
|
|
261
|
+
- **Binary Files**: Last-writer-wins with automatic convergence
|
|
262
|
+
- **Directory Structure**: Additive merging supports simultaneous file creation
|
|
263
|
+
- **File Moves**: Intelligent detection prevents data loss during renames
|
|
264
|
+
|
|
265
|
+
### Two-Phase Sync Process
|
|
266
|
+
|
|
267
|
+
1. **Push Phase**: Apply local changes to Automerge documents
|
|
268
|
+
2. **Pull Phase**: Apply remote changes to local filesystem
|
|
269
|
+
3. **Convergence**: All repositories eventually reach identical state
|
|
270
|
+
|
|
271
|
+
### Change Detection
|
|
272
|
+
|
|
273
|
+
- **Content-Based**: Uses Automerge document heads, not timestamps
|
|
274
|
+
- **Efficient**: Only processes actually changed files
|
|
275
|
+
- **Reliable**: Works across time zones and file system differences
|
|
276
|
+
- **Resumable**: Interrupted syncs can be safely resumed
|
|
277
|
+
|
|
278
|
+
### Move Detection Algorithm
|
|
279
|
+
|
|
280
|
+
- Compares content similarity between deleted and created files
|
|
281
|
+
- **Auto-apply**: Moves with >80% similarity (configurable)
|
|
282
|
+
- **User prompt**: Moves with 50-80% similarity (configurable)
|
|
283
|
+
- **Ignore**: Moves with <50% similarity
|
|
284
|
+
|
|
285
|
+
## 📁 Architecture
|
|
286
|
+
|
|
287
|
+
### Document Schema
|
|
288
|
+
|
|
289
|
+
**File Document:**
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
{
|
|
293
|
+
"@patchwork": { type: "file" };
|
|
294
|
+
name: string;
|
|
295
|
+
extension: string;
|
|
296
|
+
mimeType: string;
|
|
297
|
+
content: Text | Uint8Array;
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
**Directory Document:**
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
{
|
|
305
|
+
"@patchwork": { type: "folder" };
|
|
306
|
+
docs: Array<{
|
|
307
|
+
name: string;
|
|
308
|
+
type: "file" | "folder";
|
|
309
|
+
url: AutomergeUrl;
|
|
310
|
+
}>;
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Local State Management
|
|
315
|
+
|
|
316
|
+
- **Snapshot File**: `.pushwork/snapshot.json` tracks sync state
|
|
317
|
+
- **Path Mapping**: Links filesystem paths to Automerge document URLs
|
|
318
|
+
- **Head Tracking**: Enables efficient change detection
|
|
319
|
+
- **Configuration**: `.pushwork/config.json` stores sync settings
|
|
320
|
+
|
|
321
|
+
### Network Architecture
|
|
322
|
+
|
|
323
|
+
- **Sync Server**: Handles real-time synchronization between clients
|
|
324
|
+
- **Storage ID**: Isolates different collaboration groups
|
|
325
|
+
- **WebSocket Connection**: Provides real-time updates
|
|
326
|
+
- **Graceful Degradation**: Works offline with manual sync
|
|
327
|
+
|
|
328
|
+
## 🧪 Testing
|
|
329
|
+
|
|
330
|
+
### Running Tests
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
# Build the project
|
|
334
|
+
npm run build
|
|
335
|
+
|
|
336
|
+
# Run unit tests
|
|
337
|
+
npm test
|
|
338
|
+
|
|
339
|
+
# Run integration tests
|
|
340
|
+
./test/run-tests.sh
|
|
341
|
+
|
|
342
|
+
# Test conflict resolution
|
|
343
|
+
./test/integration/conflict-resolution-test.sh
|
|
344
|
+
|
|
345
|
+
# Test clone functionality
|
|
346
|
+
./test/integration/clone-test.sh
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Test Coverage
|
|
350
|
+
|
|
351
|
+
- **Unit Tests**: Core functionality and utilities
|
|
352
|
+
- **Integration Tests**: End-to-end sync scenarios
|
|
353
|
+
- **Conflict Resolution**: CRDT merging behavior
|
|
354
|
+
- **Clone Operations**: Repository sharing workflows
|
|
355
|
+
|
|
356
|
+
## 🛠️ Development
|
|
357
|
+
|
|
358
|
+
### Prerequisites
|
|
359
|
+
|
|
360
|
+
- Node.js 18+
|
|
361
|
+
- TypeScript 5+
|
|
362
|
+
- pnpm (recommended) or npm
|
|
363
|
+
|
|
364
|
+
### Development Setup
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
git clone <repository-url>
|
|
368
|
+
cd pushwork
|
|
369
|
+
npm install
|
|
370
|
+
npm run build
|
|
371
|
+
|
|
372
|
+
# Development mode
|
|
373
|
+
npm run dev
|
|
374
|
+
|
|
375
|
+
# Watch mode for testing
|
|
376
|
+
npm run test:watch
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### Project Structure
|
|
380
|
+
|
|
381
|
+
```
|
|
382
|
+
src/
|
|
383
|
+
├── cli/ # Command-line interface
|
|
384
|
+
├── core/ # Core sync engine
|
|
385
|
+
├── config/ # Configuration management
|
|
386
|
+
├── types/ # TypeScript type definitions
|
|
387
|
+
└── utils/ # Shared utilities
|
|
388
|
+
|
|
389
|
+
test/
|
|
390
|
+
├── unit/ # Unit tests
|
|
391
|
+
└── integration/ # Integration tests
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## 🤝 Real-World Collaboration Example
|
|
395
|
+
|
|
396
|
+
```bash
|
|
397
|
+
# Alice initializes a project
|
|
398
|
+
alice$ pushwork init ./shared-docs
|
|
399
|
+
alice$ echo "Hello World" > shared-docs/readme.txt
|
|
400
|
+
alice$ pushwork sync
|
|
401
|
+
alice$ pushwork url
|
|
402
|
+
# automerge:2V4w7zv8zkJYJxJsKaYhZ5NPjxA1
|
|
403
|
+
|
|
404
|
+
# Bob clones Alice's project
|
|
405
|
+
bob$ pushwork clone automerge:2V4w7zv8zkJYJxJsKaYhZ5NPjxA1 ./bobs-copy
|
|
406
|
+
|
|
407
|
+
# Both edit the same file simultaneously
|
|
408
|
+
alice$ echo "Alice's changes" >> shared-docs/readme.txt
|
|
409
|
+
bob$ echo "Bob's changes" >> bobs-copy/readme.txt
|
|
410
|
+
|
|
411
|
+
# Both sync - no conflicts!
|
|
412
|
+
alice$ pushwork sync
|
|
413
|
+
bob$ pushwork sync
|
|
414
|
+
alice$ pushwork sync # Gets Bob's changes
|
|
415
|
+
|
|
416
|
+
# Final result contains both changes merged automatically
|
|
417
|
+
alice$ cat shared-docs/readme.txt
|
|
418
|
+
Hello World
|
|
419
|
+
Alice's changes
|
|
420
|
+
Bob's changes
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
## 🐛 Troubleshooting
|
|
424
|
+
|
|
425
|
+
### Common Issues
|
|
426
|
+
|
|
427
|
+
**WebSocket Connection Errors**: Usually safe to ignore during shutdown
|
|
428
|
+
|
|
429
|
+
**"Directory not initialized"**: Run `pushwork init .` first
|
|
430
|
+
|
|
431
|
+
**Network Sync Timeout**: Check internet connection and sync server status
|
|
432
|
+
|
|
433
|
+
**File Permission Errors**: Ensure write access to target directory
|
|
434
|
+
|
|
435
|
+
### Debug Mode
|
|
436
|
+
|
|
437
|
+
```bash
|
|
438
|
+
# Enable verbose logging
|
|
439
|
+
pushwork sync --verbose
|
|
440
|
+
|
|
441
|
+
# Preview changes without applying
|
|
442
|
+
pushwork sync --dry-run
|
|
443
|
+
|
|
444
|
+
# Check repository status
|
|
445
|
+
pushwork status
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
## 📄 License
|
|
449
|
+
|
|
450
|
+
MIT License - see LICENSE file for details.
|
|
451
|
+
|
|
452
|
+
## 🔗 Links
|
|
453
|
+
|
|
454
|
+
- **Issues**: Report bugs and request features
|
|
455
|
+
- **Documentation**: Additional guides and tutorials
|
|
456
|
+
- **Automerge**: Learn more about CRDT technology
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
**🚀 Ready to collaborate conflict-free? Get started with `pushwork init`!**
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-compatible sync engine that adapts the core SyncEngine for browser use
|
|
3
|
+
*/
|
|
4
|
+
import { Repo } from "@automerge/automerge-repo";
|
|
5
|
+
import { SyncSnapshot, SyncResult } from "../types";
|
|
6
|
+
import { BrowserFilesystemAdapter } from "./filesystem-adapter";
|
|
7
|
+
import { BrowserDirectoryHandle, BrowserSyncState } from "./types";
|
|
8
|
+
import "./globals";
|
|
9
|
+
/**
|
|
10
|
+
* Browser-compatible repo factory
|
|
11
|
+
*/
|
|
12
|
+
export declare class BrowserRepoFactory {
|
|
13
|
+
static create(syncServerUrl?: string, storageId?: string): Promise<Repo>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Browser-specific sync engine that adapts filesystem operations
|
|
17
|
+
*/
|
|
18
|
+
export declare class BrowserSyncEngine {
|
|
19
|
+
private repo;
|
|
20
|
+
private filesystem;
|
|
21
|
+
private snapshotManager;
|
|
22
|
+
private coreEngine;
|
|
23
|
+
private rootPath;
|
|
24
|
+
constructor(repo: Repo, filesystem?: BrowserFilesystemAdapter);
|
|
25
|
+
/**
|
|
26
|
+
* Initialize with directory picker
|
|
27
|
+
*/
|
|
28
|
+
initializeWithDirectoryPicker(): Promise<BrowserDirectoryHandle>;
|
|
29
|
+
/**
|
|
30
|
+
* Get current browser sync state
|
|
31
|
+
*/
|
|
32
|
+
getSyncState(): BrowserSyncState;
|
|
33
|
+
/**
|
|
34
|
+
* Commit local changes from browser directory
|
|
35
|
+
*/
|
|
36
|
+
commitLocal(dryRun?: boolean): Promise<SyncResult>;
|
|
37
|
+
/**
|
|
38
|
+
* Full bidirectional sync
|
|
39
|
+
*/
|
|
40
|
+
sync(dryRun?: boolean): Promise<SyncResult>;
|
|
41
|
+
/**
|
|
42
|
+
* Adapted sync that works with browser filesystem
|
|
43
|
+
*/
|
|
44
|
+
private adaptedSync;
|
|
45
|
+
/**
|
|
46
|
+
* Get sync status
|
|
47
|
+
*/
|
|
48
|
+
getStatus(): Promise<{
|
|
49
|
+
snapshot: SyncSnapshot | null;
|
|
50
|
+
hasChanges: boolean;
|
|
51
|
+
changeCount: number;
|
|
52
|
+
lastSync: Date | null;
|
|
53
|
+
browserState: BrowserSyncState;
|
|
54
|
+
}>;
|
|
55
|
+
/**
|
|
56
|
+
* Set root directory URL for sharing
|
|
57
|
+
*/
|
|
58
|
+
setRootDirectoryUrl(url: string): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Get root directory URL for sharing
|
|
61
|
+
*/
|
|
62
|
+
getRootDirectoryUrl(): Promise<string | null>;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=browser-sync-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-sync-engine.d.ts","sourceRoot":"","sources":["../../src/browser/browser-sync-engine.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,2BAA2B,CAAC;AAIjD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAa,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACnE,OAAO,WAAW,CAAC;AA+FnB;;GAEG;AACH,qBAAa,kBAAkB;WAChB,MAAM,CACjB,aAAa,CAAC,EAAE,MAAM,EACtB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;CA6BjB;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,IAAI,CAAO;IACnB,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,eAAe,CAAyB;IAChD,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,QAAQ,CAAO;gBAEX,IAAI,EAAE,IAAI,EAAE,UAAU,GAAE,wBAAoC;IAMxE;;OAEG;IACG,6BAA6B,IAAI,OAAO,CAAC,sBAAsB,CAAC;IAoBtE;;OAEG;IACH,YAAY,IAAI,gBAAgB;IAIhC;;OAEG;IACG,WAAW,CAAC,MAAM,UAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAWtD;;OAEG;IACG,IAAI,CAAC,MAAM,UAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAU/C;;OAEG;YACW,WAAW;IAmEzB;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC;QACzB,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;QAC9B,UAAU,EAAE,OAAO,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;QACtB,YAAY,EAAE,gBAAgB,CAAC;KAChC,CAAC;IAaF;;OAEG;IACG,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAerD;;OAEG;IACG,mBAAmB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAIpD"}
|