@zergai/zergbox-client 0.1.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 ADDED
@@ -0,0 +1,86 @@
1
+ # `@zergai/zergbox-client`
2
+
3
+ Node 22.19+ API and local sync client for a single, explicitly selected ZergBox
4
+ folder tree. The selected `rootFolderId` is presented as `/` locally; the
5
+ workspace root and sibling boxes are never scanned.
6
+
7
+ The `@zergai` release is being prepared. The registry installation below becomes
8
+ available after the first verified publication; until then, use the repository
9
+ checkout and `npm run client:build` from `zapps/zergbox`.
10
+
11
+ ```bash
12
+ npm install @zergai/zergbox-client
13
+ ```
14
+
15
+ ```js
16
+ import { createSyncSession } from '@zergai/zergbox-client/sync'
17
+
18
+ const session = createSyncSession({
19
+ client,
20
+ organizationId,
21
+ rootFolderId,
22
+ localRoot,
23
+ statePath,
24
+ deviceId,
25
+ afterSync: async (result) => {
26
+ await reconcileCloudProjection(result)
27
+ }
28
+ })
29
+
30
+ await session.syncOnce()
31
+ await session.close()
32
+ ```
33
+
34
+ Pass either an authenticated `ZergBoxClient` or `baseUrl` plus a
35
+ `tokenProvider`. The provider is called for each sync cycle so short-lived
36
+ credentials do not need to be persisted by this package.
37
+ `afterSync(result)` is awaited by the session's internal sync lifecycle, so it
38
+ runs for both direct `syncOnce()` calls and scheduler-triggered `watch()`
39
+ cycles. Embedders should use this hook instead of wrapping the returned
40
+ `syncOnce` method.
41
+
42
+ For a server-side projection that already owns bytes, use the root-scoped API
43
+ directly:
44
+
45
+ ```js
46
+ import {
47
+ ZergBoxClient,
48
+ ZergBoxSyncConflictError
49
+ } from '@zergai/zergbox-client'
50
+
51
+ const page = await client.listChanges(rootFolderId, { cursor, limit: 100 })
52
+ await client.uploadBytes({
53
+ orgId,
54
+ folderId,
55
+ filename: 'notes.md',
56
+ bytes,
57
+ mediaType: 'text/markdown',
58
+ expectedAbsent: true
59
+ })
60
+ await client.updateFileBytes({ fileId, bytes, expectedRevision })
61
+ const downloaded = await client.downloadFile(fileId, { maxBytes: 1_048_576 })
62
+ ```
63
+
64
+ `ZergBoxClient` bounds metadata, feed, mutation, and error bodies to 1 MiB by
65
+ default and downloads to 64 MiB. Configure `maxResponseBytes` and
66
+ `maxDownloadBytes` on the constructor, or pass a smaller per-download
67
+ `maxBytes`. Oversized streams are cancelled before further bytes are buffered.
68
+
69
+ Folder and byte creates always send `If-None-Match: *`; update, move, and delete
70
+ methods require `expectedRevision` and send a strong `If-Match` ETag. A `409`
71
+ create collision or `412` stale revision becomes a recoverable
72
+ `ZergBoxSyncConflictError` with resource identity/path and the failed
73
+ precondition. Re-read the remote tree or change feed before planning again.
74
+ `uploadBytes` intentionally has no last-writer-wins mode; use
75
+ `updateFileBytes` with an observed revision.
76
+
77
+ `watch()` combines filesystem notifications with periodic reconciliation.
78
+ `pause()`, `resume()`, `status()`, `stopWatching()`, and `close()` provide a
79
+ non-daemon lifecycle that embedding CLIs can own directly. `stopWatching()`
80
+ leaves the session open so a caller can perform a final `syncOnce()` before
81
+ closing.
82
+
83
+ The package supports Node `>=22.19.0 <25` and npm `>=10.9.2 <12`. Releases are
84
+ published from the repository's protected GitHub workflow with npm trusted
85
+ publishing and provenance; no long-lived registry credential is part of that
86
+ workflow.