@quereus/sync 3.3.0 → 4.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 +17 -7
- package/dist/src/clock/hlc.d.ts +43 -3
- package/dist/src/clock/hlc.d.ts.map +1 -1
- package/dist/src/clock/hlc.js +60 -10
- package/dist/src/clock/hlc.js.map +1 -1
- package/dist/src/create-sync-module.d.ts +46 -9
- package/dist/src/create-sync-module.d.ts.map +1 -1
- package/dist/src/create-sync-module.js +11 -8
- package/dist/src/create-sync-module.js.map +1 -1
- package/dist/src/index.d.ts +10 -8
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +8 -5
- package/dist/src/index.js.map +1 -1
- package/dist/src/metadata/basis-lifecycle.d.ts +180 -0
- package/dist/src/metadata/basis-lifecycle.d.ts.map +1 -0
- package/dist/src/metadata/basis-lifecycle.js +211 -0
- package/dist/src/metadata/basis-lifecycle.js.map +1 -0
- package/dist/src/metadata/change-log.d.ts +1 -1
- package/dist/src/metadata/change-log.d.ts.map +1 -1
- package/dist/src/metadata/change-log.js +6 -6
- package/dist/src/metadata/change-log.js.map +1 -1
- package/dist/src/metadata/column-version.d.ts +14 -5
- package/dist/src/metadata/column-version.d.ts.map +1 -1
- package/dist/src/metadata/column-version.js +22 -12
- package/dist/src/metadata/column-version.js.map +1 -1
- package/dist/src/metadata/index.d.ts +2 -0
- package/dist/src/metadata/index.d.ts.map +1 -1
- package/dist/src/metadata/index.js +2 -0
- package/dist/src/metadata/index.js.map +1 -1
- package/dist/src/metadata/keys.d.ts +52 -2
- package/dist/src/metadata/keys.d.ts.map +1 -1
- package/dist/src/metadata/keys.js +99 -14
- package/dist/src/metadata/keys.js.map +1 -1
- package/dist/src/metadata/peer-state.d.ts +1 -1
- package/dist/src/metadata/peer-state.js +5 -5
- package/dist/src/metadata/quarantine.d.ts +90 -0
- package/dist/src/metadata/quarantine.d.ts.map +1 -0
- package/dist/src/metadata/quarantine.js +167 -0
- package/dist/src/metadata/quarantine.js.map +1 -0
- package/dist/src/metadata/schema-migration.d.ts +1 -1
- package/dist/src/metadata/schema-migration.js +7 -7
- package/dist/src/metadata/schema-version.d.ts +1 -1
- package/dist/src/metadata/schema-version.js +7 -7
- package/dist/src/metadata/tombstones.d.ts +26 -9
- package/dist/src/metadata/tombstones.d.ts.map +1 -1
- package/dist/src/metadata/tombstones.js +42 -19
- package/dist/src/metadata/tombstones.js.map +1 -1
- package/dist/src/sql/basis-lifecycle-tvf.d.ts +34 -0
- package/dist/src/sql/basis-lifecycle-tvf.d.ts.map +1 -0
- package/dist/src/sql/basis-lifecycle-tvf.js +101 -0
- package/dist/src/sql/basis-lifecycle-tvf.js.map +1 -0
- package/dist/src/sync/admission.d.ts +81 -0
- package/dist/src/sync/admission.d.ts.map +1 -0
- package/dist/src/sync/admission.js +94 -0
- package/dist/src/sync/admission.js.map +1 -0
- package/dist/src/sync/change-applicator.d.ts +65 -2
- package/dist/src/sync/change-applicator.d.ts.map +1 -1
- package/dist/src/sync/change-applicator.js +493 -68
- package/dist/src/sync/change-applicator.js.map +1 -1
- package/dist/src/sync/change-grouping.d.ts +43 -0
- package/dist/src/sync/change-grouping.d.ts.map +1 -0
- package/dist/src/sync/change-grouping.js +103 -0
- package/dist/src/sync/change-grouping.js.map +1 -0
- package/dist/src/sync/events.d.ts +159 -1
- package/dist/src/sync/events.d.ts.map +1 -1
- package/dist/src/sync/events.js +50 -0
- package/dist/src/sync/events.js.map +1 -1
- package/dist/src/sync/manager.d.ts +87 -0
- package/dist/src/sync/manager.d.ts.map +1 -1
- package/dist/src/sync/protocol.d.ts +174 -11
- package/dist/src/sync/protocol.d.ts.map +1 -1
- package/dist/src/sync/protocol.js +4 -1
- package/dist/src/sync/protocol.js.map +1 -1
- package/dist/src/sync/snapshot-stream.d.ts.map +1 -1
- package/dist/src/sync/snapshot-stream.js +89 -19
- package/dist/src/sync/snapshot-stream.js.map +1 -1
- package/dist/src/sync/snapshot.d.ts.map +1 -1
- package/dist/src/sync/snapshot.js +63 -44
- package/dist/src/sync/snapshot.js.map +1 -1
- package/dist/src/sync/store-adapter.d.ts +117 -15
- package/dist/src/sync/store-adapter.d.ts.map +1 -1
- package/dist/src/sync/store-adapter.js +247 -91
- package/dist/src/sync/store-adapter.js.map +1 -1
- package/dist/src/sync/sync-context.d.ts +44 -1
- package/dist/src/sync/sync-context.d.ts.map +1 -1
- package/dist/src/sync/sync-context.js +26 -0
- package/dist/src/sync/sync-context.js.map +1 -1
- package/dist/src/sync/sync-manager-impl.d.ts +247 -13
- package/dist/src/sync/sync-manager-impl.d.ts.map +1 -1
- package/dist/src/sync/sync-manager-impl.js +788 -193
- package/dist/src/sync/sync-manager-impl.js.map +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -27,10 +27,19 @@ import { createSyncModule, createStoreAdapter } from '@quereus/sync';
|
|
|
27
27
|
const storeEvents = new StoreEventEmitter();
|
|
28
28
|
const kv = await LevelDBStore.open({ path: './sync-metadata' });
|
|
29
29
|
|
|
30
|
-
// Create sync module (tracks CRDT metadata, emits sync events)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
// Create sync module (tracks CRDT metadata, emits sync events).
|
|
31
|
+
// `db` is the Quereus Database; `storeModule` is the StoreModule the synced
|
|
32
|
+
// tables use — the adapter resolves each table through it, so inbound writes
|
|
33
|
+
// get table-owned key encoding, secondary-index maintenance, and post-apply
|
|
34
|
+
// reporting through the engine (materialized views, Database.watch).
|
|
35
|
+
//
|
|
36
|
+
// `transactionSource: db` wires local-change capture to the engine's
|
|
37
|
+
// transaction-commit boundary: the HLC ticks once per committed transaction and
|
|
38
|
+
// every fact of that transaction shares its base HLC (differing only by opSeq).
|
|
39
|
+
const { syncManager, syncEvents } = await createSyncModule(kv, {
|
|
40
|
+
transactionSource: db,
|
|
41
|
+
applyToStore: createStoreAdapter({ db, storeModule, events: storeEvents }),
|
|
42
|
+
getTableSchema: (schema, table) => db.schemaManager.getTable(schema, table),
|
|
34
43
|
});
|
|
35
44
|
|
|
36
45
|
// Subscribe to sync events for UI
|
|
@@ -154,8 +163,9 @@ This means concurrent updates to *different* columns of the same row both apply,
|
|
|
154
163
|
|
|
155
164
|
### Core Exports
|
|
156
165
|
|
|
157
|
-
- `createSyncModule(kv,
|
|
158
|
-
- `createStoreAdapter(
|
|
166
|
+
- `createSyncModule(kv, options?)` - Factory to create sync manager and event emitter. Pass `transactionSource` (the engine `Database`) to capture local changes at the transaction boundary; omit it for a relay-only deployment (e.g. a coordinator)
|
|
167
|
+
- `createStoreAdapter({ db, storeModule, events, applyForeignKeyActions? })` - Creates an `ApplyToStoreCallback` for applying remote changes. Applies rows through `StoreTable.applyExternalRowChanges` (table-owned keying, secondary-index maintenance) and reports each invocation as one `Database.ingestExternalRowChanges` batch (materialized-view maintenance, `Database.watch` capture, commit-time assertions). `applyForeignKeyActions` (default `false`) opts inbound update/delete into parent-side FK actions — only enable when the replication stream does not already carry the origin's cascade effects; cascaded child writes are recorded as *local* changes and propagate outward. The callback is host-driven: never invoke it from within statement execution, and don't drive it while holding an open explicit transaction on `db`. Inbound **assertion** violations are *detect-and-notify*: a local commit-time global assertion the merged batch trips is reported via `onAssertionViolation` while the data and its derived effects (MV, `Database.watch`) converge on the first apply — no divergence, no throw, no retry (trust-the-origin: the data must land regardless). A genuine per-change **storage** failure still aborts: it is collected in `ApplyToStoreResult.errors`, the consumer leaves CRDT metadata uncommitted, and the next sync attempt re-resolves and converges (value-identical re-application is suppressed)
|
|
168
|
+
- `registerBasisLifecycleTvf(db, syncManager)` - Opt-in: register the `quereus_basis_lifecycle()` introspection TVF against an engine `Database`, so a developer can list legacy / retirement-candidate basis tables from SQL (`select "table", state, "unmappedSince" from quereus_basis_lifecycle() where state = 'derivation-source-only'`). A pure read-only convenience over `SyncManager.getBasisTableLifecycle()`; call once after `createSyncModule(...)`
|
|
159
169
|
- `SyncManager` - Main sync coordination interface
|
|
160
170
|
- `SyncEventEmitter` / `SyncEventEmitterImpl` - Event subscription interface and implementation
|
|
161
171
|
|
|
@@ -173,7 +183,7 @@ This means concurrent updates to *different* columns of the same row both apply,
|
|
|
173
183
|
- `SchemaMigration` - Schema change (CREATE/ALTER/DROP TABLE)
|
|
174
184
|
- `SnapshotChunk` - Streaming snapshot data (header, table-start, column-versions, table-end, schema-migration, footer)
|
|
175
185
|
- `ApplyResult` - Result of applying changes (applied, skipped, conflicts, transactions)
|
|
176
|
-
- `SyncConfig` / `DEFAULT_SYNC_CONFIG` - Configuration (
|
|
186
|
+
- `SyncConfig` / `DEFAULT_SYNC_CONFIG` - Configuration (retentionHorizonMs, allowResurrection, etc.)
|
|
177
187
|
|
|
178
188
|
## Related Packages
|
|
179
189
|
|
package/dist/src/clock/hlc.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* - Causality tracking across distributed nodes
|
|
7
7
|
* - Bounded clock drift tolerance
|
|
8
8
|
*
|
|
9
|
-
* Ordering: (wallTime, counter, siteId) compared lexicographically
|
|
9
|
+
* Ordering: (wallTime, counter, siteId, opSeq) compared lexicographically
|
|
10
10
|
*/
|
|
11
11
|
import type { SiteId } from './site.js';
|
|
12
12
|
/**
|
|
@@ -19,7 +19,25 @@ export interface HLC {
|
|
|
19
19
|
readonly counter: number;
|
|
20
20
|
/** 16-byte UUID identifying the replica */
|
|
21
21
|
readonly siteId: SiteId;
|
|
22
|
+
/**
|
|
23
|
+
* Per-transaction sub-order, 0-based (uint32, 0–4294967295).
|
|
24
|
+
*
|
|
25
|
+
* Discriminates facts produced by the *same* site at the same
|
|
26
|
+
* `(wallTime, counter)` — i.e. the same transaction. It is the *last*
|
|
27
|
+
* tiebreak in the comparison key and is NOT a clock-monotonicity component:
|
|
28
|
+
* it resets every transaction and is never persisted in the `hc:` clock state.
|
|
29
|
+
*/
|
|
30
|
+
readonly opSeq: number;
|
|
22
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Maximum `opSeq` value — a transaction may produce at most 2^32 facts.
|
|
34
|
+
*
|
|
35
|
+
* `opSeq` is serialized as a big-endian uint32 (see {@link serializeHLC}), so a
|
|
36
|
+
* fact count exceeding this would silently wrap. The write side asserts against
|
|
37
|
+
* this bound and throws rather than wrapping; the limit is practically
|
|
38
|
+
* unreachable (4 billion facts in one transaction).
|
|
39
|
+
*/
|
|
40
|
+
export declare const MAX_OPSEQ = 4294967295;
|
|
23
41
|
/**
|
|
24
42
|
* Compare two HLCs for ordering.
|
|
25
43
|
* Returns negative if a < b, positive if a > b, zero if equal.
|
|
@@ -29,13 +47,33 @@ export declare function compareHLC(a: HLC, b: HLC): number;
|
|
|
29
47
|
* Check if two HLCs are equal.
|
|
30
48
|
*/
|
|
31
49
|
export declare function hlcEquals(a: HLC, b: HLC): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Return the maximum HLC from an iterable, or undefined when empty.
|
|
52
|
+
*/
|
|
53
|
+
export declare function maxHLC(hlcs: Iterable<HLC>): HLC | undefined;
|
|
32
54
|
/**
|
|
33
55
|
* Create a new HLC with the given values.
|
|
56
|
+
*
|
|
57
|
+
* `opSeq` defaults to 0 to keep the many call sites that produce the first (or
|
|
58
|
+
* only) fact of a transaction terse — the field remains required on the
|
|
59
|
+
* interface.
|
|
60
|
+
*/
|
|
61
|
+
export declare function createHLC(wallTime: bigint, counter: number, siteId: SiteId, opSeq?: number): HLC;
|
|
62
|
+
/**
|
|
63
|
+
* Derive a deterministic transaction id from a transaction's base HLC.
|
|
64
|
+
*
|
|
65
|
+
* The base HLC `(wallTime, counter, siteId)` is unique among a site's
|
|
66
|
+
* transactions (consecutive {@link HLCManager.tick}s always differ in counter or
|
|
67
|
+
* wallTime), so this id is stable and reproducible: every peer that replays the
|
|
68
|
+
* same transaction's facts derives the *same* id from their shared base, without
|
|
69
|
+
* persisting a separate transaction record. `opSeq` is intentionally excluded —
|
|
70
|
+
* all facts of one transaction share a single id.
|
|
34
71
|
*/
|
|
35
|
-
export declare function
|
|
72
|
+
export declare function deterministicTxnId(base: HLC): string;
|
|
36
73
|
/**
|
|
37
74
|
* Serialize HLC to a Uint8Array for storage.
|
|
38
|
-
* Format: 8 bytes wallTime (BE) + 2 bytes counter (BE) + 16 bytes siteId
|
|
75
|
+
* Format: 8 bytes wallTime (BE) + 2 bytes counter (BE) + 16 bytes siteId
|
|
76
|
+
* + 4 bytes opSeq (BE) = 30 bytes
|
|
39
77
|
*/
|
|
40
78
|
export declare function serializeHLC(hlc: HLC): Uint8Array;
|
|
41
79
|
/**
|
|
@@ -53,6 +91,8 @@ export interface SerializedHLC {
|
|
|
53
91
|
counter: number;
|
|
54
92
|
/** Site ID as 22-character base64url string */
|
|
55
93
|
siteId: string;
|
|
94
|
+
/** Per-transaction sub-order (0-based uint32) */
|
|
95
|
+
opSeq: number;
|
|
56
96
|
}
|
|
57
97
|
/**
|
|
58
98
|
* Convert HLC to a JSON-serializable object.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hlc.d.ts","sourceRoot":"","sources":["../../../src/clock/hlc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,GAAG;IAClB,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"hlc.d.ts","sourceRoot":"","sources":["../../../src/clock/hlc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,GAAG;IAClB,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAOD;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,aAAa,CAAC;AAQpC;;;GAGG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,GAAG,MAAM,CAiBjD;AAcD;;GAEG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,GAAG,OAAO,CAEjD;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,SAAS,CAM3D;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,GAAG,CAE3F;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,UAAU,CAiBjD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,GAAG,CAatD;AAMD;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,aAAa,CAOjD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,GAAG,CAOpD;AAkDD;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAMhF;;OAEG;IACH,SAAS,IAAI,MAAM;IAInB;;OAEG;IACH,QAAQ,IAAI;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAIjD;;;OAGG;IACH,IAAI,IAAI,GAAG;IAoBX;;;;OAIG;IACH,OAAO,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG;IAuCzB;;;OAGG;IACH,GAAG,IAAI,GAAG;CAGX"}
|
package/dist/src/clock/hlc.js
CHANGED
|
@@ -6,12 +6,21 @@
|
|
|
6
6
|
* - Causality tracking across distributed nodes
|
|
7
7
|
* - Bounded clock drift tolerance
|
|
8
8
|
*
|
|
9
|
-
* Ordering: (wallTime, counter, siteId) compared lexicographically
|
|
9
|
+
* Ordering: (wallTime, counter, siteId, opSeq) compared lexicographically
|
|
10
10
|
*/
|
|
11
11
|
/**
|
|
12
12
|
* Maximum counter value before forcing time advancement.
|
|
13
13
|
*/
|
|
14
14
|
const MAX_COUNTER = 0xFFFF;
|
|
15
|
+
/**
|
|
16
|
+
* Maximum `opSeq` value — a transaction may produce at most 2^32 facts.
|
|
17
|
+
*
|
|
18
|
+
* `opSeq` is serialized as a big-endian uint32 (see {@link serializeHLC}), so a
|
|
19
|
+
* fact count exceeding this would silently wrap. The write side asserts against
|
|
20
|
+
* this bound and throws rather than wrapping; the limit is practically
|
|
21
|
+
* unreachable (4 billion facts in one transaction).
|
|
22
|
+
*/
|
|
23
|
+
export const MAX_OPSEQ = 0xFFFFFFFF;
|
|
15
24
|
/**
|
|
16
25
|
* Maximum allowed clock drift in milliseconds (1 minute).
|
|
17
26
|
* Rejects remote timestamps that are too far in the future.
|
|
@@ -33,7 +42,15 @@ export function compareHLC(a, b) {
|
|
|
33
42
|
if (a.counter > b.counter)
|
|
34
43
|
return 1;
|
|
35
44
|
// Same counter: compare site ID lexicographically
|
|
36
|
-
|
|
45
|
+
const siteCmp = compareSiteIds(a.siteId, b.siteId);
|
|
46
|
+
if (siteCmp !== 0)
|
|
47
|
+
return siteCmp;
|
|
48
|
+
// Same site (i.e. same transaction): compare per-transaction sub-order
|
|
49
|
+
if (a.opSeq < b.opSeq)
|
|
50
|
+
return -1;
|
|
51
|
+
if (a.opSeq > b.opSeq)
|
|
52
|
+
return 1;
|
|
53
|
+
return 0;
|
|
37
54
|
}
|
|
38
55
|
/**
|
|
39
56
|
* Compare two site IDs lexicographically.
|
|
@@ -54,18 +71,47 @@ function compareSiteIds(a, b) {
|
|
|
54
71
|
export function hlcEquals(a, b) {
|
|
55
72
|
return compareHLC(a, b) === 0;
|
|
56
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Return the maximum HLC from an iterable, or undefined when empty.
|
|
76
|
+
*/
|
|
77
|
+
export function maxHLC(hlcs) {
|
|
78
|
+
let max;
|
|
79
|
+
for (const hlc of hlcs) {
|
|
80
|
+
if (!max || compareHLC(hlc, max) > 0)
|
|
81
|
+
max = hlc;
|
|
82
|
+
}
|
|
83
|
+
return max;
|
|
84
|
+
}
|
|
57
85
|
/**
|
|
58
86
|
* Create a new HLC with the given values.
|
|
87
|
+
*
|
|
88
|
+
* `opSeq` defaults to 0 to keep the many call sites that produce the first (or
|
|
89
|
+
* only) fact of a transaction terse — the field remains required on the
|
|
90
|
+
* interface.
|
|
91
|
+
*/
|
|
92
|
+
export function createHLC(wallTime, counter, siteId, opSeq = 0) {
|
|
93
|
+
return Object.freeze({ wallTime, counter, siteId, opSeq });
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Derive a deterministic transaction id from a transaction's base HLC.
|
|
97
|
+
*
|
|
98
|
+
* The base HLC `(wallTime, counter, siteId)` is unique among a site's
|
|
99
|
+
* transactions (consecutive {@link HLCManager.tick}s always differ in counter or
|
|
100
|
+
* wallTime), so this id is stable and reproducible: every peer that replays the
|
|
101
|
+
* same transaction's facts derives the *same* id from their shared base, without
|
|
102
|
+
* persisting a separate transaction record. `opSeq` is intentionally excluded —
|
|
103
|
+
* all facts of one transaction share a single id.
|
|
59
104
|
*/
|
|
60
|
-
export function
|
|
61
|
-
return
|
|
105
|
+
export function deterministicTxnId(base) {
|
|
106
|
+
return `${base.wallTime.toString()}:${base.counter}:${siteIdToBase64Local(base.siteId)}`;
|
|
62
107
|
}
|
|
63
108
|
/**
|
|
64
109
|
* Serialize HLC to a Uint8Array for storage.
|
|
65
|
-
* Format: 8 bytes wallTime (BE) + 2 bytes counter (BE) + 16 bytes siteId
|
|
110
|
+
* Format: 8 bytes wallTime (BE) + 2 bytes counter (BE) + 16 bytes siteId
|
|
111
|
+
* + 4 bytes opSeq (BE) = 30 bytes
|
|
66
112
|
*/
|
|
67
113
|
export function serializeHLC(hlc) {
|
|
68
|
-
const buffer = new Uint8Array(
|
|
114
|
+
const buffer = new Uint8Array(30);
|
|
69
115
|
const view = new DataView(buffer.buffer);
|
|
70
116
|
// Wall time as big-endian 64-bit
|
|
71
117
|
view.setBigUint64(0, hlc.wallTime, false);
|
|
@@ -73,20 +119,23 @@ export function serializeHLC(hlc) {
|
|
|
73
119
|
view.setUint16(8, hlc.counter, false);
|
|
74
120
|
// Site ID (16 bytes)
|
|
75
121
|
buffer.set(hlc.siteId, 10);
|
|
122
|
+
// Per-transaction sub-order as big-endian 32-bit
|
|
123
|
+
view.setUint32(26, hlc.opSeq, false);
|
|
76
124
|
return buffer;
|
|
77
125
|
}
|
|
78
126
|
/**
|
|
79
127
|
* Deserialize HLC from a Uint8Array.
|
|
80
128
|
*/
|
|
81
129
|
export function deserializeHLC(buffer) {
|
|
82
|
-
if (buffer.length !==
|
|
83
|
-
throw new Error(`Invalid HLC buffer length: ${buffer.length}, expected
|
|
130
|
+
if (buffer.length !== 30) {
|
|
131
|
+
throw new Error(`Invalid HLC buffer length: ${buffer.length}, expected 30`);
|
|
84
132
|
}
|
|
85
133
|
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
86
134
|
const wallTime = view.getBigUint64(0, false);
|
|
87
135
|
const counter = view.getUint16(8, false);
|
|
88
136
|
const siteId = new Uint8Array(buffer.slice(10, 26));
|
|
89
|
-
|
|
137
|
+
const opSeq = view.getUint32(26, false);
|
|
138
|
+
return createHLC(wallTime, counter, siteId, opSeq);
|
|
90
139
|
}
|
|
91
140
|
/**
|
|
92
141
|
* Convert HLC to a JSON-serializable object.
|
|
@@ -97,13 +146,14 @@ export function hlcToJson(hlc) {
|
|
|
97
146
|
wallTime: hlc.wallTime.toString(),
|
|
98
147
|
counter: hlc.counter,
|
|
99
148
|
siteId: siteIdToBase64Local(hlc.siteId),
|
|
149
|
+
opSeq: hlc.opSeq,
|
|
100
150
|
};
|
|
101
151
|
}
|
|
102
152
|
/**
|
|
103
153
|
* Parse HLC from a JSON-serializable object.
|
|
104
154
|
*/
|
|
105
155
|
export function hlcFromJson(json) {
|
|
106
|
-
return createHLC(BigInt(json.wallTime), json.counter, siteIdFromBase64Local(json.siteId));
|
|
156
|
+
return createHLC(BigInt(json.wallTime), json.counter, siteIdFromBase64Local(json.siteId), json.opSeq ?? 0);
|
|
107
157
|
}
|
|
108
158
|
// Base64url alphabet (RFC 4648 Section 5)
|
|
109
159
|
const BASE64URL_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hlc.js","sourceRoot":"","sources":["../../../src/clock/hlc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"hlc.js","sourceRoot":"","sources":["../../../src/clock/hlc.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,16 +4,29 @@
|
|
|
4
4
|
* This wraps an existing store module (LevelDB or IndexedDB) with
|
|
5
5
|
* CRDT sync capabilities.
|
|
6
6
|
*/
|
|
7
|
-
import type { KVStore
|
|
8
|
-
import type { TableSchema } from '@quereus/quereus';
|
|
7
|
+
import type { KVStore } from '@quereus/store';
|
|
8
|
+
import type { TableSchema, TransactionCommitBatch } from '@quereus/quereus';
|
|
9
9
|
import { SyncEventEmitterImpl } from './sync/events.js';
|
|
10
|
-
import { type SyncConfig, type ApplyToStoreCallback } from './sync/protocol.js';
|
|
10
|
+
import { type SyncConfig, type ApplyToStoreCallback, type DropLocalTableCallback } from './sync/protocol.js';
|
|
11
11
|
import type { SyncManager } from './sync/manager.js';
|
|
12
12
|
/**
|
|
13
13
|
* Function to get table schema by name.
|
|
14
14
|
* Used to map column indices to column names for sync.
|
|
15
15
|
*/
|
|
16
16
|
export type GetTableSchemaCallback = (schemaName: string, tableName: string) => TableSchema | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* The narrow slice of the engine's event surface the sync layer captures local
|
|
19
|
+
* changes from: a subscription to grouped per-transaction commit batches. A
|
|
20
|
+
* Quereus `Database` satisfies this structurally (via `db.onTransactionCommit`),
|
|
21
|
+
* as does a bare `DatabaseEventEmitter`. This is the authoritative
|
|
22
|
+
* "one logical transaction = one group" boundary — see `docs/sync.md`
|
|
23
|
+
* § Transaction-Based Change Grouping — so the sync layer anchors one HLC per
|
|
24
|
+
* delivered batch.
|
|
25
|
+
*/
|
|
26
|
+
export interface TransactionCommitSource {
|
|
27
|
+
/** Subscribe to grouped per-transaction commit batches. Returns an unsubscribe. */
|
|
28
|
+
onTransactionCommit(listener: (batch: TransactionCommitBatch) => void): () => void;
|
|
29
|
+
}
|
|
17
30
|
/**
|
|
18
31
|
* Result of creating a sync module.
|
|
19
32
|
*/
|
|
@@ -49,6 +62,27 @@ export interface CreateSyncModuleOptions extends Partial<SyncConfig> {
|
|
|
49
62
|
* col_1, etc.), which may not match across replicas if table schemas differ.
|
|
50
63
|
*/
|
|
51
64
|
getTableSchema?: GetTableSchemaCallback;
|
|
65
|
+
/**
|
|
66
|
+
* Callback to reclaim a detached basis table's local storage by name, used by
|
|
67
|
+
* the host-driven eviction sweep (`SyncManager.evictExpiredBasisTables`,
|
|
68
|
+
* `docs/migration.md` § 4 Contract). Typically wired to the store module's
|
|
69
|
+
* `reclaimDetachedTable`. When omitted (e.g. a relay-only coordinator with no
|
|
70
|
+
* store) the sweep is a no-op.
|
|
71
|
+
*/
|
|
72
|
+
dropLocalTable?: DropLocalTableCallback;
|
|
73
|
+
/**
|
|
74
|
+
* Engine transaction-commit source for capturing local changes.
|
|
75
|
+
*
|
|
76
|
+
* When provided (typically the Quereus `Database`), the SyncManager
|
|
77
|
+
* subscribes to `onTransactionCommit` and records CRDT metadata for each
|
|
78
|
+
* committed local transaction — ticking the HLC once per transaction and
|
|
79
|
+
* assigning every fact of the transaction an incrementing `opSeq`.
|
|
80
|
+
*
|
|
81
|
+
* Omit for a relay-only deployment (e.g. a sync coordinator) that has no
|
|
82
|
+
* local engine and never produces local DML — it only applies remote changes
|
|
83
|
+
* and serves `getChangesSince`.
|
|
84
|
+
*/
|
|
85
|
+
transactionSource?: TransactionCommitSource;
|
|
52
86
|
}
|
|
53
87
|
/**
|
|
54
88
|
* Create a sync-enabled module.
|
|
@@ -59,18 +93,21 @@ export interface CreateSyncModuleOptions extends Partial<SyncConfig> {
|
|
|
59
93
|
* 3. Returns the sync manager and event emitter for UI integration
|
|
60
94
|
*
|
|
61
95
|
* @param kv - The KV store to use for metadata storage
|
|
62
|
-
* @param
|
|
63
|
-
*
|
|
96
|
+
* @param options - Optional sync configuration, callbacks, and the engine
|
|
97
|
+
* `transactionSource` to capture local changes from
|
|
64
98
|
*
|
|
65
99
|
* @example
|
|
66
100
|
* ```typescript
|
|
67
|
-
* import { LevelDBStore
|
|
101
|
+
* import { LevelDBStore } from '@quereus/store';
|
|
102
|
+
* import { Database } from '@quereus/quereus';
|
|
68
103
|
* import { createSyncModule } from '@quereus/sync';
|
|
69
104
|
*
|
|
70
|
-
* const
|
|
105
|
+
* const db = new Database();
|
|
71
106
|
* const kv = await LevelDBStore.open({ path: './data' });
|
|
72
107
|
*
|
|
73
|
-
* const { syncManager, syncEvents } = await createSyncModule(kv,
|
|
108
|
+
* const { syncManager, syncEvents } = await createSyncModule(kv, {
|
|
109
|
+
* transactionSource: db,
|
|
110
|
+
* });
|
|
74
111
|
*
|
|
75
112
|
* // Subscribe to sync events for UI
|
|
76
113
|
* syncEvents.onRemoteChange((event) => {
|
|
@@ -81,5 +118,5 @@ export interface CreateSyncModuleOptions extends Partial<SyncConfig> {
|
|
|
81
118
|
* const changes = await syncManager.getChangesSince(peerSiteId, lastHLC);
|
|
82
119
|
* ```
|
|
83
120
|
*/
|
|
84
|
-
export declare function createSyncModule(kv: KVStore,
|
|
121
|
+
export declare function createSyncModule(kv: KVStore, options?: CreateSyncModuleOptions): Promise<CreateSyncModuleResult>;
|
|
85
122
|
//# sourceMappingURL=create-sync-module.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-sync-module.d.ts","sourceRoot":"","sources":["../../src/create-sync-module.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"create-sync-module.d.ts","sourceRoot":"","sources":["../../src/create-sync-module.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAuB,KAAK,UAAU,EAAE,KAAK,oBAAoB,EAAE,KAAK,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAClI,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,WAAW,GAAG,SAAS,CAAC;AAExG;;;;;;;;GAQG;AACH,MAAM,WAAW,uBAAuB;IACtC,mFAAmF;IACnF,mBAAmB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACpF;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,2CAA2C;IAC3C,WAAW,EAAE,WAAW,CAAC;IACzB,gDAAgD;IAChD,UAAU,EAAE,oBAAoB,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,uBAAwB,SAAQ,OAAO,CAAC,UAAU,CAAC;IAClE;;;;;;;;;;OAUG;IACH,YAAY,CAAC,EAAE,oBAAoB,CAAC;IAEpC;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,sBAAsB,CAAC;IAExC;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,sBAAsB,CAAC;IAExC;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,EAAE,uBAAuB,CAAC;CAC7C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,OAAO,EACX,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,sBAAsB,CAAC,CAwBjC"}
|
|
@@ -16,18 +16,21 @@ import { DEFAULT_SYNC_CONFIG } from './sync/protocol.js';
|
|
|
16
16
|
* 3. Returns the sync manager and event emitter for UI integration
|
|
17
17
|
*
|
|
18
18
|
* @param kv - The KV store to use for metadata storage
|
|
19
|
-
* @param
|
|
20
|
-
*
|
|
19
|
+
* @param options - Optional sync configuration, callbacks, and the engine
|
|
20
|
+
* `transactionSource` to capture local changes from
|
|
21
21
|
*
|
|
22
22
|
* @example
|
|
23
23
|
* ```typescript
|
|
24
|
-
* import { LevelDBStore
|
|
24
|
+
* import { LevelDBStore } from '@quereus/store';
|
|
25
|
+
* import { Database } from '@quereus/quereus';
|
|
25
26
|
* import { createSyncModule } from '@quereus/sync';
|
|
26
27
|
*
|
|
27
|
-
* const
|
|
28
|
+
* const db = new Database();
|
|
28
29
|
* const kv = await LevelDBStore.open({ path: './data' });
|
|
29
30
|
*
|
|
30
|
-
* const { syncManager, syncEvents } = await createSyncModule(kv,
|
|
31
|
+
* const { syncManager, syncEvents } = await createSyncModule(kv, {
|
|
32
|
+
* transactionSource: db,
|
|
33
|
+
* });
|
|
31
34
|
*
|
|
32
35
|
* // Subscribe to sync events for UI
|
|
33
36
|
* syncEvents.onRemoteChange((event) => {
|
|
@@ -38,14 +41,14 @@ import { DEFAULT_SYNC_CONFIG } from './sync/protocol.js';
|
|
|
38
41
|
* const changes = await syncManager.getChangesSince(peerSiteId, lastHLC);
|
|
39
42
|
* ```
|
|
40
43
|
*/
|
|
41
|
-
export async function createSyncModule(kv,
|
|
42
|
-
const { applyToStore, getTableSchema, ...configOverrides } = options;
|
|
44
|
+
export async function createSyncModule(kv, options = {}) {
|
|
45
|
+
const { applyToStore, getTableSchema, dropLocalTable, transactionSource, ...configOverrides } = options;
|
|
43
46
|
const fullConfig = {
|
|
44
47
|
...DEFAULT_SYNC_CONFIG,
|
|
45
48
|
...configOverrides,
|
|
46
49
|
};
|
|
47
50
|
const syncEvents = new SyncEventEmitterImpl();
|
|
48
|
-
const syncManager = await SyncManagerImpl.create(kv,
|
|
51
|
+
const syncManager = await SyncManagerImpl.create(kv, transactionSource, fullConfig, syncEvents, applyToStore, getTableSchema, dropLocalTable);
|
|
49
52
|
return {
|
|
50
53
|
syncManager,
|
|
51
54
|
syncEvents,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-sync-module.js","sourceRoot":"","sources":["../../src/create-sync-module.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"create-sync-module.js","sourceRoot":"","sources":["../../src/create-sync-module.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAA2E,MAAM,oBAAoB,CAAC;AAqFlI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,EAAW,EACX,UAAmC,EAAE;IAErC,MAAM,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,GAAG,eAAe,EAAE,GAAG,OAAO,CAAC;IAExG,MAAM,UAAU,GAAe;QAC7B,GAAG,mBAAmB;QACtB,GAAG,eAAe;KACnB,CAAC;IAEF,MAAM,UAAU,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE9C,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,MAAM,CAC9C,EAAE,EACF,iBAAiB,EACjB,UAAU,EACV,UAAU,EACV,YAAY,EACZ,cAAc,EACd,cAAc,CACf,CAAC;IAEF,OAAO;QACL,WAAW;QACX,UAAU;KACX,CAAC;AACJ,CAAC"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -12,19 +12,21 @@
|
|
|
12
12
|
*
|
|
13
13
|
* Usage:
|
|
14
14
|
* import { createSyncModule } from '@quereus/sync';
|
|
15
|
-
* import {
|
|
15
|
+
* import { LevelDBStore } from '@quereus/store';
|
|
16
16
|
*
|
|
17
|
-
* const storeEvents = new StoreEventEmitter();
|
|
18
17
|
* const kv = await LevelDBStore.open({ path: './sync-metadata' });
|
|
19
|
-
*
|
|
18
|
+
* // `db` is the engine Database; it captures local changes at the
|
|
19
|
+
* // transaction boundary. Omit transactionSource for a relay-only deployment.
|
|
20
|
+
* const { syncManager, syncEvents } = await createSyncModule(kv, { transactionSource: db });
|
|
20
21
|
*/
|
|
21
|
-
export { type HLC, HLCManager, compareHLC, hlcEquals, createHLC, serializeHLC, deserializeHLC, type SerializedHLC, hlcToJson, hlcFromJson, type SiteId, generateSiteId, siteIdToBase64, siteIdFromBase64, toBase64Url, fromBase64Url, siteIdEquals, type SiteIdentity, serializeSiteIdentity, deserializeSiteIdentity, SITE_ID_KEY, } from './clock/index.js';
|
|
22
|
-
export { type ColumnChange, type RowDeletion, type Change, type SchemaMigrationType, type SchemaMigration, type ChangeSet, type ApplyRejection, type ApplyResult, type ColumnVersionEntry, type TableSnapshot, type Snapshot, type PeerSyncState, type SnapshotChunkType, type SnapshotHeaderChunk, type SnapshotTableStartChunk, type SnapshotColumnVersionsChunk, type SnapshotTableEndChunk, type SnapshotSchemaMigrationChunk, type SnapshotFooterChunk, type SnapshotChunk, type SnapshotProgress, type ApplyToStoreOptions, type DataChangeToApply, type SchemaChangeToApply, type ApplyToStoreResult, type ApplyToStoreCallback, type ConflictContext, type ConflictResolution, type ConflictResolver, type SyncConfig, DEFAULT_SYNC_CONFIG, } from './sync/protocol.js';
|
|
22
|
+
export { type HLC, HLCManager, compareHLC, hlcEquals, maxHLC, createHLC, deterministicTxnId, MAX_OPSEQ, serializeHLC, deserializeHLC, type SerializedHLC, hlcToJson, hlcFromJson, type SiteId, generateSiteId, siteIdToBase64, siteIdFromBase64, toBase64Url, fromBase64Url, siteIdEquals, type SiteIdentity, serializeSiteIdentity, deserializeSiteIdentity, SITE_ID_KEY, } from './clock/index.js';
|
|
23
|
+
export { type ColumnChange, type RowDeletion, type Change, type SchemaMigrationType, type SchemaMigration, type ChangeSet, type ApplyRejection, type ApplyResult, type ColumnVersionEntry, type TableSnapshot, type Snapshot, type PeerSyncState, type SnapshotChunkType, type SnapshotHeaderChunk, type SnapshotTableStartChunk, type SnapshotColumnVersionsChunk, type SnapshotTableEndChunk, type SnapshotSchemaMigrationChunk, type SnapshotFooterChunk, type SnapshotChunk, type SnapshotProgress, type ApplyToStoreOptions, type DataChangeToApply, type SchemaChangeToApply, type ApplyToStoreResult, type ApplyToStoreCallback, type ConflictContext, type ConflictResolution, type ConflictResolver, type UnknownTableDisposition, type BasisEvictionConfig, type DropLocalTableCallback, type SyncConfig, DEFAULT_SYNC_CONFIG, } from './sync/protocol.js';
|
|
23
24
|
export { lwwResolver, localWinsResolver, remoteWinsResolver, } from './sync/conflict-resolvers.js';
|
|
24
25
|
export { type SyncManager, type SnapshotCheckpoint } from './sync/manager.js';
|
|
25
26
|
export { SyncManagerImpl } from './sync/sync-manager-impl.js';
|
|
26
27
|
export { createStoreAdapter, type SyncStoreAdapterOptions } from './sync/store-adapter.js';
|
|
27
|
-
export {
|
|
28
|
-
export {
|
|
29
|
-
export {
|
|
28
|
+
export { registerBasisLifecycleTvf } from './sql/basis-lifecycle-tvf.js';
|
|
29
|
+
export { createSyncModule, type CreateSyncModuleResult, type CreateSyncModuleOptions, type GetTableSchemaCallback, type TransactionCommitSource, } from './create-sync-module.js';
|
|
30
|
+
export { type RemoteChangeEvent, type LocalChangeEvent, type ConflictEvent, type UnknownTableEvent, type AssertionViolationEvent, type BasisTableLifecycleEvent, type BasisTableEvictedEvent, type HeldChangesDrainedEvent, type SyncState, type Unsubscribe, type SyncEventEmitter, SyncEventEmitterImpl, } from './sync/events.js';
|
|
31
|
+
export { SYNC_KEY_PREFIX, buildColumnVersionKey, buildTombstoneKey, buildTransactionKey, buildPeerStateKey, buildSchemaMigrationKey, buildColumnVersionScanBounds, buildTableColumnVersionScanBounds, buildTombstoneScanBounds, buildSchemaMigrationScanBounds, encodePK, decodePK, type ColumnVersion, ColumnVersionStore, serializeColumnVersion, deserializeColumnVersion, encodeSqlValue, decodeSqlValue, type Tombstone, TombstoneStore, serializeTombstone, deserializeTombstone, type QuarantineEntry, QuarantineStore, serializeQuarantineEntry, deserializeQuarantineEntry, buildQuarantineKey, buildQuarantineScanBounds, type BasisLifecycleState, type BasisTableLifecycleRecord, type EvictPolicy, BasisLifecycleStore, classifyBasisLifecycle, parseEvictPolicyTag, effectiveEvictHorizonMs, quietSince, isEvictable, serializeBasisLifecycleRecord, deserializeBasisLifecycleRecord, buildBasisLifecycleKey, buildAllBasisLifecycleScanBounds, type PeerState, PeerStateStore, serializePeerState, deserializePeerState, type SchemaVersion, type SchemaVersionType, type SchemaChangeOperation, SchemaVersionStore, buildSchemaVersionKey, buildSchemaVersionScanBounds, buildAllSchemaVersionsScanBounds, serializeSchemaVersion, deserializeSchemaVersion, parseSchemaVersionKey, getDestructiveness, getOperationDestructiveness, shouldApplySchemaChangeByOperation, } from './metadata/index.js';
|
|
30
32
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EAEL,KAAK,GAAG,EACR,UAAU,EACV,UAAU,EACV,SAAS,EACT,MAAM,EACN,SAAS,EACT,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,cAAc,EAEd,KAAK,aAAa,EAClB,SAAS,EACT,WAAW,EAEX,KAAK,MAAM,EACX,cAAc,EAEd,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,YAAY,EACZ,KAAK,YAAY,EACjB,qBAAqB,EACrB,uBAAuB,EACvB,WAAW,GACZ,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,MAAM,EAEX,KAAK,mBAAmB,EACxB,KAAK,eAAe,EAEpB,KAAK,SAAS,EAEd,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,KAAK,aAAa,EAElB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC1B,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EAErB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EAEzB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EAErB,KAAK,uBAAuB,EAE5B,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAE3B,KAAK,UAAU,EACf,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAG9D,OAAO,EAAE,kBAAkB,EAAE,KAAK,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAG3F,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAGzE,OAAO,EACL,gBAAgB,EAChB,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAEL,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,4BAA4B,EAC5B,iCAAiC,EACjC,wBAAwB,EACxB,8BAA8B,EAC9B,QAAQ,EACR,QAAQ,EAER,KAAK,aAAa,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,wBAAwB,EAExB,cAAc,EACd,cAAc,EAEd,KAAK,SAAS,EACd,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EAEpB,KAAK,eAAe,EACpB,eAAe,EACf,wBAAwB,EACxB,0BAA0B,EAC1B,kBAAkB,EAClB,yBAAyB,EAEzB,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,WAAW,EAChB,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACnB,uBAAuB,EACvB,UAAU,EACV,WAAW,EACX,6BAA6B,EAC7B,+BAA+B,EAC/B,sBAAsB,EACtB,gCAAgC,EAEhC,KAAK,SAAS,EACd,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EAEpB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,kBAAkB,EAClB,qBAAqB,EACrB,4BAA4B,EAC5B,gCAAgC,EAChC,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,EAErB,kBAAkB,EAClB,2BAA2B,EAC3B,kCAAkC,GACnC,MAAM,qBAAqB,CAAC"}
|
package/dist/src/index.js
CHANGED
|
@@ -12,14 +12,15 @@
|
|
|
12
12
|
*
|
|
13
13
|
* Usage:
|
|
14
14
|
* import { createSyncModule } from '@quereus/sync';
|
|
15
|
-
* import {
|
|
15
|
+
* import { LevelDBStore } from '@quereus/store';
|
|
16
16
|
*
|
|
17
|
-
* const storeEvents = new StoreEventEmitter();
|
|
18
17
|
* const kv = await LevelDBStore.open({ path: './sync-metadata' });
|
|
19
|
-
*
|
|
18
|
+
* // `db` is the engine Database; it captures local changes at the
|
|
19
|
+
* // transaction boundary. Omit transactionSource for a relay-only deployment.
|
|
20
|
+
* const { syncManager, syncEvents } = await createSyncModule(kv, { transactionSource: db });
|
|
20
21
|
*/
|
|
21
22
|
// Clock module
|
|
22
|
-
export { HLCManager, compareHLC, hlcEquals, createHLC, serializeHLC, deserializeHLC, hlcToJson, hlcFromJson, generateSiteId,
|
|
23
|
+
export { HLCManager, compareHLC, hlcEquals, maxHLC, createHLC, deterministicTxnId, MAX_OPSEQ, serializeHLC, deserializeHLC, hlcToJson, hlcFromJson, generateSiteId,
|
|
23
24
|
// Base64url encoding
|
|
24
25
|
siteIdToBase64, siteIdFromBase64, toBase64Url, fromBase64Url, siteIdEquals, serializeSiteIdentity, deserializeSiteIdentity, SITE_ID_KEY, } from './clock/index.js';
|
|
25
26
|
// Sync protocol types
|
|
@@ -29,6 +30,8 @@ export { lwwResolver, localWinsResolver, remoteWinsResolver, } from './sync/conf
|
|
|
29
30
|
export { SyncManagerImpl } from './sync/sync-manager-impl.js';
|
|
30
31
|
// Store adapter for applying remote changes
|
|
31
32
|
export { createStoreAdapter } from './sync/store-adapter.js';
|
|
33
|
+
// In-SQL introspection TVF (opt-in: host calls after createSyncModule)
|
|
34
|
+
export { registerBasisLifecycleTvf } from './sql/basis-lifecycle-tvf.js';
|
|
32
35
|
// Factory function
|
|
33
36
|
export { createSyncModule, } from './create-sync-module.js';
|
|
34
37
|
// Reactive events
|
|
@@ -38,7 +41,7 @@ export {
|
|
|
38
41
|
// Key builders
|
|
39
42
|
SYNC_KEY_PREFIX, buildColumnVersionKey, buildTombstoneKey, buildTransactionKey, buildPeerStateKey, buildSchemaMigrationKey, buildColumnVersionScanBounds, buildTableColumnVersionScanBounds, buildTombstoneScanBounds, buildSchemaMigrationScanBounds, encodePK, decodePK, ColumnVersionStore, serializeColumnVersion, deserializeColumnVersion,
|
|
40
43
|
// SqlValue JSON encoding (for Uint8Array/bigint in JSON transport)
|
|
41
|
-
encodeSqlValue, decodeSqlValue, TombstoneStore, serializeTombstone, deserializeTombstone, PeerStateStore, serializePeerState, deserializePeerState, SchemaVersionStore, buildSchemaVersionKey, buildSchemaVersionScanBounds, buildAllSchemaVersionsScanBounds, serializeSchemaVersion, deserializeSchemaVersion, parseSchemaVersionKey,
|
|
44
|
+
encodeSqlValue, decodeSqlValue, TombstoneStore, serializeTombstone, deserializeTombstone, QuarantineStore, serializeQuarantineEntry, deserializeQuarantineEntry, buildQuarantineKey, buildQuarantineScanBounds, BasisLifecycleStore, classifyBasisLifecycle, parseEvictPolicyTag, effectiveEvictHorizonMs, quietSince, isEvictable, serializeBasisLifecycleRecord, deserializeBasisLifecycleRecord, buildBasisLifecycleKey, buildAllBasisLifecycleScanBounds, PeerStateStore, serializePeerState, deserializePeerState, SchemaVersionStore, buildSchemaVersionKey, buildSchemaVersionScanBounds, buildAllSchemaVersionsScanBounds, serializeSchemaVersion, deserializeSchemaVersion, parseSchemaVersionKey,
|
|
42
45
|
// Most destructive wins
|
|
43
46
|
getDestructiveness, getOperationDestructiveness, shouldApplySchemaChangeByOperation, } from './metadata/index.js';
|
|
44
47
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,eAAe;AACf,OAAO,EAGL,UAAU,EACV,UAAU,EACV,SAAS,EACT,MAAM,EACN,SAAS,EACT,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,cAAc,EAGd,SAAS,EACT,WAAW,EAGX,cAAc;AACd,qBAAqB;AACrB,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,YAAY,EAEZ,qBAAqB,EACrB,uBAAuB,EACvB,WAAW,GACZ,MAAM,kBAAkB,CAAC;AAE1B,sBAAsB;AACtB,OAAO,EA4CL,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAE5B,8BAA8B;AAC9B,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,8BAA8B,CAAC;AAItC,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D,4CAA4C;AAC5C,OAAO,EAAE,kBAAkB,EAAgC,MAAM,yBAAyB,CAAC;AAE3F,uEAAuE;AACvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAEzE,mBAAmB;AACnB,OAAO,EACL,gBAAgB,GAKjB,MAAM,yBAAyB,CAAC;AAEjC,kBAAkB;AAClB,OAAO,EAYL,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAE1B,mBAAmB;AACnB,OAAO;AACL,eAAe;AACf,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,4BAA4B,EAC5B,iCAAiC,EACjC,wBAAwB,EACxB,8BAA8B,EAC9B,QAAQ,EACR,QAAQ,EAGR,kBAAkB,EAClB,sBAAsB,EACtB,wBAAwB;AACxB,mEAAmE;AACnE,cAAc,EACd,cAAc,EAGd,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EAGpB,eAAe,EACf,wBAAwB,EACxB,0BAA0B,EAC1B,kBAAkB,EAClB,yBAAyB,EAKzB,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACnB,uBAAuB,EACvB,UAAU,EACV,WAAW,EACX,6BAA6B,EAC7B,+BAA+B,EAC/B,sBAAsB,EACtB,gCAAgC,EAGhC,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EAKpB,kBAAkB,EAClB,qBAAqB,EACrB,4BAA4B,EAC5B,gCAAgC,EAChC,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB;AACrB,wBAAwB;AACxB,kBAAkB,EAClB,2BAA2B,EAC3B,kCAAkC,GACnC,MAAM,qBAAqB,CAAC"}
|