@vrtmrz/livesync-commonlib 0.1.16 → 0.1.18
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/dist/common/ConnectionString.js +9 -1
- package/dist/common/models/setting.const.d.ts +18 -0
- package/dist/common/models/setting.const.defaults.js +10 -1
- package/dist/common/models/setting.const.js +12 -0
- package/dist/common/models/setting.const.qr.js +3 -1
- package/dist/common/models/setting.p2p.d.ts +21 -0
- package/dist/common/models/setting.p2p.js +35 -0
- package/dist/common/models/setting.type.d.ts +11 -1
- package/dist/common/models/shared.definition.configNames.js +8 -0
- package/dist/common/models/tweak.definition.d.ts +2 -0
- package/dist/common/settingConstants.d.ts +2 -0
- package/dist/common/types.d.ts +5 -3
- package/dist/common/types.js +17 -1
- package/dist/common/utils.js +4 -1
- package/dist/interfaces/DatabaseFileAccess.d.ts +10 -0
- package/dist/managers/EntryManager/EntryManager.d.ts +1 -0
- package/dist/managers/EntryManager/EntryManager.js +4 -0
- package/dist/managers/EntryManager/EntryManagerImpls.d.ts +7 -0
- package/dist/managers/EntryManager/EntryManagerImpls.js +21 -3
- package/dist/pouchdb/LiveSyncLocalDB.d.ts +1 -0
- package/dist/pouchdb/LiveSyncLocalDB.js +3 -0
- package/dist/replication/trystero/LiveSyncTrysteroReplicator.d.ts +8 -0
- package/dist/replication/trystero/LiveSyncTrysteroReplicator.js +36 -8
- package/dist/replication/trystero/TrysteroReplicatorP2PServer.js +2 -2
- package/dist/rpc/transports/TrysteroTransport.d.ts +2 -0
- package/dist/rpc/transports/TrysteroTransport.js +18 -2
- package/dist/rpc/transports/trysteroUtils.js +12 -1
- package/dist/serviceModules/ServiceDatabaseFileAccessBase.d.ts +1 -0
- package/dist/serviceModules/ServiceDatabaseFileAccessBase.js +22 -4
- package/dist/worker/bgWorker.js +1 -1
- package/docs/conflict-resolution.md +2 -0
- package/docs/development.md +1 -1
- package/docs/p2p-transport-lifecycle.md +4 -2
- package/docs/proven-in-use.md +3 -1
- package/docs/releasing.md +2 -0
- package/docs/remote-configurations.md +2 -0
- package/package.json +1 -1
|
@@ -80,6 +80,8 @@ The record is updated only after a successful database-to-storage reflection or
|
|
|
80
80
|
|
|
81
81
|
User-directed reconciliation may select any exact current live revision, including a conflict leaf rather than the deterministic winner. `dbToStorageWithSpecificRev()` rechecks that the selected revision is still live before reflecting its content. `storeFileToDBWithBaseRevision()` performs the same live check before storing current storage content as a child of that revision. If the content already matches the selected non-deleted revision, it records that revision directly without creating a child. A host can set `createIfDifferent` to `false` when it intends only to record an exact content match; differing content then fails instead of changing the revision tree. A host may also create a logical deletion on an explicitly selected branch with `deleteRevisionFromDB()` after performing its own current-live-revision check. This leaves storage unchanged and clears device-local provenance only when that record names the deleted revision.
|
|
82
82
|
|
|
83
|
+
`storeWithBaseRevision()` is the force-write primitive for deliberately preserving a branch below an exact revision, including a revision which is no longer a leaf. It must not be used when an operation means 'advance this revision only if it is still current'. For that compare-and-store boundary, `storeWithLiveBaseRevision()` uses PouchDB's ordinary revision check and returns `false` if the supplied base has already been advanced. Any current revision-tree leaf is eligible, including a non-winning conflict leaf or a logical-deletion leaf. The caller must refresh its state after refusal rather than silently falling back to the deterministic winner.
|
|
84
|
+
|
|
83
85
|
A successful non-deleted reconciliation records the exact selected or newly created revision as provenance. Applying a logical deletion removes the storage item and its provenance record. Deletion provenance is not retained indefinitely: an absent storage item and a current logical-deletion winner already agree and need no further reconciliation.
|
|
84
86
|
|
|
85
87
|
Hosts may construct the namespaced store handle during service composition, before its backing database is open. Store operations begin only after the host's storage lifecycle is ready. They fail rather than wait when that lifecycle contract is violated, because an implicit readiness wait could hang after failed initialisation or wait on its own initialisation handler. Database reset is a transient unavailable boundary; the host must avoid file processing during it and reconstruct derived provenance after reopening.
|
package/docs/development.md
CHANGED
|
@@ -59,7 +59,7 @@ The multiple-remote profile contract has focused unit coverage in `src/serviceFe
|
|
|
59
59
|
|
|
60
60
|
The full offline scanner applies both the host's target-file policy and Commonlib's built-in `shouldBeIgnored` policy before constructing storage/database pairs. This keeps legacy LiveSync log files and flag files outside ordinary create, restore, and delete decisions even when a host accepts their file extension. Lower-level write guards remain a defence for direct calls; they are not the normal full-scan filter. The complete pair-state decision matrix and database-to-storage reflection result contract are documented in [Full offline scan](offline-scanner.md). Extend that document, the Cartesian action test, and both collection-side tests whenever the policy changes.
|
|
61
61
|
|
|
62
|
-
The revision-tree safety rules are documented in [Conflict resolution and file provenance](conflict-resolution.md). `ConflictManager.unit.spec.ts` owns common-ancestor and conservative merge behaviour, deterministic pair selection for multiple live leaves, and reconstruction from the committed tree between stages. `ServiceDatabaseFileAccessBase.unit.spec.ts` owns all-branch content discovery, short-circuiting history existence checks after an exact match,
|
|
62
|
+
The revision-tree safety rules are documented in [Conflict resolution and file provenance](conflict-resolution.md). `ConflictManager.unit.spec.ts` owns common-ancestor and conservative merge behaviour, deterministic pair selection for multiple live leaves, and reconstruction from the committed tree between stages. `EntryManagerImpls.unit.spec.ts` owns the distinction between force-writing below an exact revision and conditionally advancing a current live leaf through PouchDB's ordinary revision check. `ServiceDatabaseFileAccessBase.unit.spec.ts` owns all-branch content discovery, short-circuiting history existence checks after an exact match, exact-revision logical deletion, and the public live-base result and event boundary. `ServiceFileHandlerBase.unit.spec.ts` owns the injected provenance policy for edit, deletion, and rename operations, together with user-selected reflection, child creation, strict matching, matching-provenance cleanup after exact branch deletion, and stale-revision refusal. `LiveSyncLocalDB.unit.spec.ts` owns chunk reachability across current winners, shared chunks, live conflicts, available merge ancestry, conflict resolution, and PouchDB replication of collection and recreation. Extend the relevant sides when changing conflict resolution, compaction handling, provenance, chunk collection, or database-to-storage overwrite protection.
|
|
63
63
|
|
|
64
64
|
`LiveSyncReplicator.unit.spec.ts` owns the CouchDB remote-chunk batch contract: a mixed `_all_docs` result must return each available document even when another keyed row reports an error. `ChunkFetcher.unit.spec.ts` owns the consumer behaviour: it writes valid returned chunks and emits `missingChunkRemote` only for requested IDs which are absent from the returned set. Extend both sides when changing remote chunk acquisition or missing-chunk delivery.
|
|
65
65
|
|
|
@@ -31,7 +31,9 @@ It is therefore a logical LiveSync disconnection and a physical signalling-serve
|
|
|
31
31
|
|
|
32
32
|
## Reconnection and replacement
|
|
33
33
|
|
|
34
|
-
An explicit open resumes Trystero relay reconnection before joining the configured room. Settings application may change the relay URLs, room ID, passphrase, or TURN configuration, so the owning service closes and discards the former LiveSync instance before constructing the replacement. Concurrent replacement requests share the same in-flight replacement and receive the same new owner.
|
|
34
|
+
An explicit open resumes Trystero relay reconnection before joining the configured room. Settings application may change the relay URLs, room ID, passphrase, or TURN configuration, so the owning service normally closes and discards the former LiveSync instance before constructing the replacement. Concurrent replacement requests share the same in-flight replacement and receive the same new owner.
|
|
35
|
+
|
|
36
|
+
A retained `LiveSyncTrysteroReplicator` also compares the effective outgoing message bound and connection path on every open. An unchanged signature keeps the serving transport, while a changed signature serialises closure of that transport before opening its replacement. This prevents a selected compatibility profile from appearing to take effect while the former room binding is still active. No fixed close-to-open delay is required: lifecycle operations are serialised, and peer readiness is observed through discovery.
|
|
35
37
|
|
|
36
38
|
Saving settings with P2P or automatic start disabled always requests `close()`, even when the room has not started serving. This cancels an in-flight open through the same lifecycle queue, so a connection cannot appear after the disabling setting has been applied.
|
|
37
39
|
|
|
@@ -53,7 +55,7 @@ Commonlib consequently does not expose a forced physical-disconnection command.
|
|
|
53
55
|
|
|
54
56
|
Maintain all five boundaries when this lifecycle changes:
|
|
55
57
|
|
|
56
|
-
- Commonlib unit tests must prove that normal close leaves the room without directly closing Trystero-owned peers, that disabling settings cancel a pending open,
|
|
58
|
+
- Commonlib unit tests must prove that normal close leaves the room without directly closing Trystero-owned peers, that disabling settings cancel a pending open, that concurrent replacement requests leave one current owner, and that a changed compatibility signature replaces a serving transport while an unchanged signature remains idempotent;
|
|
57
59
|
- Commonlib rebuild tests must prove that first-device P2P initialisation does not reset a remote database and that an additional-device P2P Fetch performs one explicit peer-selection pass before resuming reflection;
|
|
58
60
|
- the Self-hosted LiveSync Compose P2P lifecycle test must replace a current replicator, rediscover the same real peer, perform bidirectional RPC, and verify transferred content from a separate process;
|
|
59
61
|
- the Self-hosted LiveSync real-Obsidian P2P Setup URI workflow must generate the second-device URI on the first device, accept both peer directions visibly, and verify a two-way note round-trip; and
|
package/docs/proven-in-use.md
CHANGED
|
@@ -14,7 +14,7 @@ The consumer contract in `test/contracts/serviceContext.ts` checks shared result
|
|
|
14
14
|
|
|
15
15
|
Commonlib supplies the two sleep preferences and preserves them through Setup URI encoding. Self-hosted LiveSync applies those values once at its injected bounded-activity runner, so remote operations and downloaded-document application share the same host-owned Wake Lock policy. Focused downstream tests cover the platform preference table and both activity categories; operating-system suspend behaviour remains real-platform integration evidence rather than a Commonlib guarantee.
|
|
16
16
|
|
|
17
|
-
Commonlib's real-PouchDB and injected-boundary unit tests prove that conservative merge uses the nearest revision actually shared by both conflict leaves, multiple remaining leaves are selected in a deterministic order, each completed pair is reconstructed from the committed tree, storage content from a deleted losing branch remains recognisable after resolution, and conflict-time operations retain the exact displayed branch or preserve every branch when that identity cannot be proved. They also verify that a boolean history check stops after its first exact content match without reading an older unavailable revision, while revision enumeration still returns every match. A local edit remains a readable sibling branch when the winning body is unavailable but its exact revision and parent metadata remain, a generation-one revision without a parent is left unresolved, and a separately confirmed exact deletion of that unreadable live leaf permits a replacement to be stored without reading the missing chunk. Exact reconciliation tests cover reflecting a selected live leaf, storing Vault content as its child, recording a matching leaf without creating a revision, clearing matching provenance after exact branch deletion, and refusing to record a stale revision or a revision whose content differs. Self-hosted LiveSync supplies the host composition, persistent device-local provenance, and the per-revision repair interface. Its optional two-Vault scopes cover post-resolution propagation and edit, logical deletion, case-only rename, and cross-path rename while conflicts remain active. The conflict-operation scope passes in real Obsidian against the exact locally packed Commonlib artefact, including replicated parent revisions and preservation of the other live branches.
|
|
17
|
+
Commonlib's real-PouchDB and injected-boundary unit tests prove that conservative merge uses the nearest revision actually shared by both conflict leaves, multiple remaining leaves are selected in a deterministic order, each completed pair is reconstructed from the committed tree, storage content from a deleted losing branch remains recognisable after resolution, and conflict-time operations retain the exact displayed branch or preserve every branch when that identity cannot be proved. They also verify that a boolean history check stops after its first exact content match without reading an older unavailable revision, while revision enumeration still returns every match. A local edit remains a readable sibling branch when the winning body is unavailable but its exact revision and parent metadata remain, a generation-one revision without a parent is left unresolved, and a separately confirmed exact deletion of that unreadable live leaf permits a replacement to be stored without reading the missing chunk. Exact reconciliation tests cover reflecting a selected live leaf, storing Vault content as its child, recording a matching leaf without creating a revision, clearing matching provenance after exact branch deletion, and refusing to record a stale revision or a revision whose content differs. Separate live-base tests advance a selected conflict leaf or logical-deletion leaf through PouchDB's ordinary revision check, retain the other live leaf, and reject reuse of a stale base. Self-hosted LiveSync supplies the host composition, persistent device-local provenance, and the per-revision repair interface. Its optional two-Vault scopes cover post-resolution propagation and edit, logical deletion, case-only rename, and cross-path rename while conflicts remain active. The conflict-operation scope passes in real Obsidian against the exact locally packed Commonlib artefact, including replicated parent revisions and preservation of the other live branches. Its Document History scenario restores readable historical bytes as a new live successor and reflects that exact revision to the Vault.
|
|
18
18
|
|
|
19
19
|
Commonlib's chunk-reachability tests use real PouchDB revision trees. They verify that an ordinary superseded revision releases its unique chunks, a chunk shared by current files remains reachable, live conflict branches and their nearest available shared ancestor remain protected, and losing-branch ancestry becomes eligible after resolution. They also replicate a collected chunk deletion to another PouchDB database and verify that writing the same content can recreate and replicate the content-addressed chunk. Self-hosted LiveSync owns the CouchDB-specific Garbage Collection V3 workflow, including device checks, confirmation, deletion, push-only replication, and remote compaction.
|
|
20
20
|
|
|
@@ -56,6 +56,8 @@ The browser service composition in `src/apps/browser/createLiveSyncBrowserServic
|
|
|
56
56
|
|
|
57
57
|
The Obsidian plug-in, CLI, WebApp, and WebPeer compose P2P ownership through `useP2PReplicatorFeature`. Commands and views retain its live result object and resolve the current replicator when an action occurs. Downstream Deno and Compose P2P E2E cover headless peer discovery and synchronisation, including the WebApp-to-WebPeer-to-CLI journey. Application-owned Chromium checks cover the browser UI flows, and the public Pages deployment has separate post-deployment smoke validation. The real-Obsidian Setup URI workflow additionally covers first-device local initialisation, one-pass additional-device Fetch, explicit peer approval, Vault reflection, and a two-way note round-trip.
|
|
58
58
|
|
|
59
|
+
Commonlib's focused P2P compatibility tests establish legacy defaulting, bounded outgoing message sizes, connection-string and QR-setting round trips, application of the configured bound across its Trystero server and client surfaces, relay-only ICE mapping when a valid TURN URL is present, and replacement of a serving transport when an effective compatibility value changes. They do not prove that a particular network path requires a smaller preset or that a configured TURN service can allocate a relay. Self-hosted LiveSync owns profile selection, user-facing controls, and real-Obsidian composition; device- and network-specific connectivity remains downstream or reporter-environment evidence.
|
|
60
|
+
|
|
59
61
|
This is evidence that the current package boundary can be consumed without the Obsidian host, but it is not yet a recommended standalone Commonlib client factory. The high-level lifecycle, readiness, error, and disposal contract remains future package work after Self-hosted LiveSync 1.0 rather than a gate for that release.
|
|
60
62
|
|
|
61
63
|
## LiveSync Bridge
|
package/docs/releasing.md
CHANGED
|
@@ -13,6 +13,8 @@ npm run verify:package
|
|
|
13
13
|
|
|
14
14
|
The gate type-checks Commonlib, runs its complete unit suite, verifies the source boundary, builds the distributable package, installs its exact tarball into a clean consumer, and bundles representative browser and Node entry points. The source `package.json` remains private to prevent publishing the repository root. Only the generated `.package` directory is publishable, and its manifest defaults to public publication on the `next` dist-tag.
|
|
15
15
|
|
|
16
|
+
The package builder normalises generated directories to `0755`, ordinary files to `0644`, and declared `bin` targets to `0755` before validation. `test:package` uses a restrictive umask and verifies the packed modes, so local and hosted builds do not differ only because their caller environments use different umasks.
|
|
17
|
+
|
|
16
18
|
### Lockfile reproducibility
|
|
17
19
|
|
|
18
20
|
Regenerate `package-lock.json` with the reviewed npm CLI version pinned by the `Use the reviewed npm CLI` step in `.github/workflows/publish-npm.yml`. Do this after adding, removing, or updating a dependency, even when an older local npm reports that the lockfile is already up to date. npm minor versions can differ in how they record transitive optional peer dependencies; a lockfile accepted by an older client can otherwise fail the hosted `npm ci` before any tests run.
|
|
@@ -42,6 +42,8 @@ There is no special profile named or identified as `default`. The selected main
|
|
|
42
42
|
- Use `{ activate: true, activateForP2P: true }` when P2P is the main remote.
|
|
43
43
|
- Use `{ activateForP2P: true }` to select a P2P profile without changing the main remote.
|
|
44
44
|
|
|
45
|
+
The outgoing message bound and connection path are ordinary P2P profile properties retained in its connection URI. Separate profiles may intentionally share a Group ID and credentials while selecting different transport compatibility values; only the profile selected by `P2P_ActiveRemoteConfigurationId` supplies the active flat P2P projection.
|
|
46
|
+
|
|
45
47
|
Selecting a profile updates the compatibility fields immediately. Existing replication services may therefore continue to consume those fields while profile-aware hosts treat the profile map and selection IDs as authoritative persisted state.
|
|
46
48
|
|
|
47
49
|
## Import and migration boundary
|
package/package.json
CHANGED