aspect-sync 0.1.16 → 0.1.17
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 +135 -67
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,15 +4,14 @@ A CLI tool to sync files from external services (via rclone) to the Aspect platf
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **Rclone
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **Session
|
|
14
|
-
- **Automatic
|
|
15
|
-
- **Retry Logic**: Automatic retry for failed uploads (part-level and file-level)
|
|
7
|
+
- **Rclone integration**: Lists and downloads from any rclone-supported remote.
|
|
8
|
+
- **Aspect-compatible path planning**: Preserves source hierarchy while sanitizing names that Aspect rejects.
|
|
9
|
+
- **Duplicate preservation when supported**: Preserves duplicate file and folder names when the rclone provider exposes stable IDs.
|
|
10
|
+
- **Idempotent reruns**: Reuses existing directories and skips assets that are already uploaded.
|
|
11
|
+
- **Batched migrations**: Downloads and uploads large remotes in size-limited batches.
|
|
12
|
+
- **Progress display**: Shows download, upload, skip, and failure progress in the terminal.
|
|
13
|
+
- **Session isolation**: Uses unique session directories so concurrent syncs do not collide.
|
|
14
|
+
- **Automatic cleanup**: Removes local staged files after successful upload unless `--keep-local` is set.
|
|
16
15
|
|
|
17
16
|
## Prerequisites
|
|
18
17
|
|
|
@@ -61,19 +60,19 @@ my-s3:
|
|
|
61
60
|
**Important:** The remote names are shown **with a colon** (`:`) but you use them **without the colon** in the `--remote` parameter.
|
|
62
61
|
|
|
63
62
|
Examples:
|
|
64
|
-
- If you see `dropbox
|
|
65
|
-
- If you see `my-dropbox
|
|
66
|
-
- If you see `gdrive
|
|
63
|
+
- If you see `dropbox:`, use `--remote dropbox`
|
|
64
|
+
- If you see `my-dropbox:`, use `--remote my-dropbox`
|
|
65
|
+
- If you see `gdrive:`, use `--remote gdrive`
|
|
67
66
|
|
|
68
67
|
### Test Your Remote
|
|
69
68
|
|
|
70
69
|
Before syncing, test that your remote works:
|
|
71
70
|
```bash
|
|
72
71
|
# List files in the root of your remote
|
|
73
|
-
rclone
|
|
72
|
+
rclone lsjson dropbox: --recursive
|
|
74
73
|
|
|
75
74
|
# List files in a specific folder
|
|
76
|
-
rclone
|
|
75
|
+
rclone lsjson dropbox:my-folder --recursive
|
|
77
76
|
```
|
|
78
77
|
|
|
79
78
|
This should list files in your cloud storage. If you see files listed, your remote is configured correctly!
|
|
@@ -112,24 +111,58 @@ npx aspect-sync \
|
|
|
112
111
|
|
|
113
112
|
### Command Options
|
|
114
113
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
|
118
|
-
|
|
119
|
-
| `--
|
|
120
|
-
| `--
|
|
121
|
-
| `--
|
|
122
|
-
| `--
|
|
123
|
-
| `--
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
|
128
|
-
|
|
129
|
-
| `--
|
|
130
|
-
| `--
|
|
131
|
-
|
|
132
|
-
|
|
114
|
+
Required:
|
|
115
|
+
|
|
116
|
+
| Option | Description |
|
|
117
|
+
|--------|-------------|
|
|
118
|
+
| `--remote <name>` | rclone remote name from your rclone config, without the trailing colon. |
|
|
119
|
+
| `--path <path>` | Remote path to sync from. |
|
|
120
|
+
| `--directory-id <id>` | Aspect directory ID to upload into. |
|
|
121
|
+
| `--project-id <id>` | Aspect project ID. |
|
|
122
|
+
| `--api-key <key>` | Aspect API key. Can also be set with `ASPECT_API_KEY`. |
|
|
123
|
+
|
|
124
|
+
Aspect API options:
|
|
125
|
+
|
|
126
|
+
| Option | Description | Default |
|
|
127
|
+
|--------|-------------|---------|
|
|
128
|
+
| `--api-url <url>` | Aspect API URL. Can also be set with `ASPECT_API_URL`. | `https://api.aspect.inc` |
|
|
129
|
+
| `--edge-worker-url <url>` | Aspect edge worker URL. Can also be set with `ASPECT_EDGE_WORKER_URL`. | `https://mackinac.aspect.inc` |
|
|
130
|
+
|
|
131
|
+
Sync behavior:
|
|
132
|
+
|
|
133
|
+
| Option | Description | Default |
|
|
134
|
+
|--------|-------------|---------|
|
|
135
|
+
| `--upload-concurrent <number>` | Maximum concurrent chunk uploads to Aspect. | `16` |
|
|
136
|
+
| `--batch-size <size>` | Enables batched mode with a maximum batch size, for example `500GB` or `1TB`. | Disabled |
|
|
137
|
+
| `--keep-local` | Keep local staged files after upload for debugging. | `false` |
|
|
138
|
+
| `--check` | Check remote files against Aspect without downloading or uploading. | `false` |
|
|
139
|
+
| `--temp-dir <path>` | Base temporary directory for sync sessions. | `~/.aspect/sync` |
|
|
140
|
+
| `--session <name>` | Session name. If omitted, a nanosecond-precision timestamp is generated. | Auto-generated |
|
|
141
|
+
|
|
142
|
+
rclone tuning:
|
|
143
|
+
|
|
144
|
+
| Option | Description | Default |
|
|
145
|
+
|--------|-------------|---------|
|
|
146
|
+
| `--rclone-transfers <number>` | Parallel file transfers for bulk rclone sync. Also controls rclone checkers. | `4` |
|
|
147
|
+
| `--rclone-multi-thread-streams <number>` | Streams per large file for rclone transfers. | `4` |
|
|
148
|
+
| `--rclone-multi-thread-chunk-size <size>` | rclone multi-thread chunk size. | `64MiB` |
|
|
149
|
+
| `--rclone-multi-thread-cutoff <size>` | Minimum file size for rclone multi-threading. | `64MiB` |
|
|
150
|
+
| `--rclone-buffer-size <size>` | rclone buffer size per transfer. | `64M` |
|
|
151
|
+
| `--rclone-no-mmap` | Disable rclone memory-mapped I/O. | `false` |
|
|
152
|
+
| `--rclone-extra <arg>` | Extra rclone argument. Repeat for multiple args. | Not set |
|
|
153
|
+
|
|
154
|
+
Repeat `--rclone-extra` for each passthrough value. Example:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
aspect-sync \
|
|
158
|
+
--remote gdrive \
|
|
159
|
+
--path /Videos \
|
|
160
|
+
--directory-id <directory-id> \
|
|
161
|
+
--project-id <project-id> \
|
|
162
|
+
--api-key <api-key> \
|
|
163
|
+
--rclone-extra --drive-root-folder-id \
|
|
164
|
+
--rclone-extra <folder-id>
|
|
165
|
+
```
|
|
133
166
|
|
|
134
167
|
### Environment Variables
|
|
135
168
|
|
|
@@ -147,6 +180,8 @@ aspect-sync \
|
|
|
147
180
|
--project-id <project-id>
|
|
148
181
|
```
|
|
149
182
|
|
|
183
|
+
Analytics is enabled only when a PostHog key is available at build time or runtime. Runtime values can be supplied with `ASPECT_POSTHOG_KEY`/`ASPECT_POSTHOG_HOST` or `POSTHOG_KEY`/`POSTHOG_HOST`. Set `ASPECT_DISABLE_POSTHOG=true` or `POSTHOG_DISABLED=true` to disable analytics.
|
|
184
|
+
|
|
150
185
|
## Examples
|
|
151
186
|
|
|
152
187
|
### Sync from Dropbox
|
|
@@ -173,6 +208,19 @@ aspect-sync \
|
|
|
173
208
|
--rclone-extra --drive-shared-with-me
|
|
174
209
|
```
|
|
175
210
|
|
|
211
|
+
### Sync a Specific Google Drive Folder by ID
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
aspect-sync \
|
|
215
|
+
--remote gdrive \
|
|
216
|
+
--path / \
|
|
217
|
+
--directory-id abc-123-def \
|
|
218
|
+
--project-id xyz-789-uvw \
|
|
219
|
+
--api-key your-api-key \
|
|
220
|
+
--rclone-extra --drive-root-folder-id \
|
|
221
|
+
--rclone-extra 1truv6wvzgXM3CkGMzuC8c-hrpMk5RAAs
|
|
222
|
+
```
|
|
223
|
+
|
|
176
224
|
### Sync from S3 Bucket
|
|
177
225
|
|
|
178
226
|
```bash
|
|
@@ -223,41 +271,67 @@ Sessions are stored in `~/.aspect/sync/{session-name}` by default. The full path
|
|
|
223
271
|
|
|
224
272
|
## How It Works
|
|
225
273
|
|
|
226
|
-
1. **Session
|
|
227
|
-
2. **
|
|
228
|
-
3. **
|
|
229
|
-
4. **Directory
|
|
230
|
-
5. **Asset
|
|
231
|
-
6. **
|
|
232
|
-
7. **
|
|
233
|
-
8. **Cleanup**: Deletes local files after successful upload
|
|
274
|
+
1. **Session creation**: Creates an isolated local session directory.
|
|
275
|
+
2. **Remote listing**: Uses `rclone lsjson` to list files and directories with IDs when the remote exposes them.
|
|
276
|
+
3. **Path planning**: Sanitizes names for Aspect and assigns unique targets for duplicate files and folders.
|
|
277
|
+
4. **Directory planning**: Fetches the existing Aspect directory tree and creates only missing directories.
|
|
278
|
+
5. **Asset existence check**: Skips assets that already exist and are fully uploaded.
|
|
279
|
+
6. **Download**: Downloads unchanged files with bulk `rclone sync --files-from`; downloads renamed or duplicate files by ID when needed.
|
|
280
|
+
7. **Upload**: Uploads staged files through `@aspect/upload-core` and the Aspect edge worker.
|
|
281
|
+
8. **Cleanup**: Deletes local staged files after successful upload unless `--keep-local` is set.
|
|
282
|
+
|
|
283
|
+
Aspect upload chunk size is controlled by the server. There is no CLI flag for upload chunk size.
|
|
284
|
+
|
|
285
|
+
## Name Sanitization And Duplicates
|
|
286
|
+
|
|
287
|
+
Aspect enforces cross-platform file and folder names. Sanitization works for all rclone providers because it happens inside `aspect-sync` after remote listing. During planning, each path segment is sanitized before upload:
|
|
288
|
+
|
|
289
|
+
- forbidden characters such as `:`, `*`, `?`, `"`, `<`, `>`, and `|` are replaced with `_`
|
|
290
|
+
- trailing dots/spaces are trimmed
|
|
291
|
+
- reserved Windows names such as `CON`, `AUX`, and `COM1` are prefixed with `_`
|
|
292
|
+
- names are truncated to the backend byte limit
|
|
293
|
+
|
|
294
|
+
Some providers, especially Google Drive, allow duplicate names in the same folder. `aspect-sync` preserves those without changing the source when rclone exposes stable IDs:
|
|
295
|
+
|
|
296
|
+
- duplicate files use parenthesized suffixes, for example `IMG_1891.MOV`, `IMG_1891 (2).MOV`
|
|
297
|
+
- duplicate folders use numeric suffixes, for example `Shoot`, `Shoot 2`
|
|
298
|
+
|
|
299
|
+
Provider behavior:
|
|
300
|
+
|
|
301
|
+
- Providers without duplicate folder ambiguity work normally.
|
|
302
|
+
- Duplicate files are preserved when rclone exposes stable file IDs. If identity is required but no file ID is available, the sync fails instead of guessing.
|
|
303
|
+
- Duplicate folders are preserved when rclone exposes stable folder IDs and supports querying children by folder ID. Google Drive is the primary supported provider for this flow.
|
|
304
|
+
- Duplicate folders without stable folder IDs fail with a clear error instead of silently merging folders.
|
|
305
|
+
|
|
306
|
+
When a duplicate Google Drive folder is detected, `aspect-sync` queries each folder by its Drive ID and downloads descendants by file ID so the source folder identity is preserved.
|
|
234
307
|
|
|
235
308
|
## Idempotent Behavior
|
|
236
309
|
|
|
237
310
|
The syncer is **fully idempotent** - you can safely re-run the same sync multiple times:
|
|
238
311
|
|
|
239
|
-
|
|
312
|
+
**Existing directories are reused** - The tool fetches the directory tree first and only creates missing directories.
|
|
240
313
|
|
|
241
|
-
|
|
314
|
+
**Existing assets are skipped** - Before uploading, checks if an asset with the same name, size, and location already exists.
|
|
242
315
|
- If found and fully uploaded: Skips upload
|
|
243
316
|
- If found but incomplete: Deletes incomplete asset and re-uploads
|
|
244
317
|
- If not found: Proceeds with upload
|
|
245
318
|
|
|
246
|
-
|
|
247
|
-
```bash
|
|
248
|
-
# First run - uploads 50 of 100 files then crashes
|
|
249
|
-
aspect-sync --remote dropbox --path /videos --directory-id abc --project-id xyz --api-key key
|
|
319
|
+
**Clean re-runs** - If a sync fails halfway:
|
|
250
320
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
321
|
+
```bash
|
|
322
|
+
# First run - uploads 50 of 100 files then crashes
|
|
323
|
+
aspect-sync --remote dropbox --path /videos --directory-id abc --project-id xyz --api-key key
|
|
324
|
+
|
|
325
|
+
# Re-run - skips the 50 uploaded files, uploads remaining 50
|
|
326
|
+
aspect-sync --remote dropbox --path /videos --directory-id abc --project-id xyz --api-key key
|
|
327
|
+
```
|
|
254
328
|
|
|
255
329
|
**Output on re-run:**
|
|
256
330
|
```
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
331
|
+
video1.mp4 (100%)
|
|
332
|
+
video2.mp4 (Skipped - already uploaded)
|
|
333
|
+
video3.mp4 (Skipped - already uploaded)
|
|
334
|
+
video4.mp4 (45%)
|
|
261
335
|
|
|
262
336
|
Total: 100 | Success: 1 | Failed: 0 | Skipped: 98 | In Progress: 1 | Queued: 0
|
|
263
337
|
```
|
|
@@ -267,29 +341,23 @@ Total: 100 | Success: 1 | Failed: 0 | Skipped: 98 | In Progress: 1 | Queued: 0
|
|
|
267
341
|
The tool shows dynamic, in-place progress updates:
|
|
268
342
|
|
|
269
343
|
```
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
344
|
+
video1.mp4 (100%)
|
|
345
|
+
video2.mp4 (100%)
|
|
346
|
+
video3.mp4 (Skipped - already uploaded)
|
|
347
|
+
video4.mp4 (47%)
|
|
348
|
+
video5.mp4 (23%)
|
|
275
349
|
|
|
276
350
|
Total: 10 | Success: 2 | Failed: 0 | Skipped: 1 | In Progress: 2 | Queued: 5 | Speed: 45.3 Mbps | Time remaining: 2m 15s
|
|
277
351
|
```
|
|
278
352
|
|
|
279
|
-
**Status Indicators:**
|
|
280
|
-
- `✓` = Successfully uploaded
|
|
281
|
-
- `✗` = Failed upload
|
|
282
|
-
- `⊘` = Skipped (already exists on server)
|
|
283
|
-
- `↑` = Currently uploading
|
|
284
|
-
|
|
285
353
|
Only files that are actively uploading are shown (not the entire queue).
|
|
286
354
|
|
|
287
355
|
## Error Handling
|
|
288
356
|
|
|
289
357
|
### Retry Logic
|
|
290
358
|
|
|
291
|
-
- **
|
|
292
|
-
- **File
|
|
359
|
+
- **Chunk retries**: Upload chunks are retried on transient failures.
|
|
360
|
+
- **File retries**: Failed files can be retried by rerunning the sync.
|
|
293
361
|
- **Exponential backoff**: Delays increase exponentially between retries
|
|
294
362
|
|
|
295
363
|
### Common Errors
|
|
@@ -348,7 +416,7 @@ Verify your rclone remote is configured:
|
|
|
348
416
|
|
|
349
417
|
```bash
|
|
350
418
|
rclone listremotes
|
|
351
|
-
rclone
|
|
419
|
+
rclone lsjson dropbox: --recursive
|
|
352
420
|
```
|
|
353
421
|
|
|
354
422
|
## License
|