@syncular/client 0.15.44 → 0.15.46
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 +37 -5
- package/dist/browser-storage-persistence.d.ts +20 -0
- package/dist/browser-storage-persistence.js +34 -0
- package/dist/bun-database.d.ts +1 -1
- package/dist/bun-database.js +1 -1
- package/dist/client.d.ts +3 -3
- package/dist/client.js +6 -6
- package/dist/database.d.ts +1 -1
- package/dist/devtools.d.ts +1 -1
- package/dist/http.d.ts +6 -2
- package/dist/http.js +68 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -2
- package/dist/invalidation.d.ts +1 -1
- package/dist/leader-lock.d.ts +2 -2
- package/dist/multi-tab.js +1 -1
- package/dist/naming.d.ts +1 -1
- package/dist/naming.js +1 -1
- package/dist/node-database.js +1 -1
- package/dist/query-guard.d.ts +1 -1
- package/dist/query-guard.js +1 -1
- package/dist/remote.d.ts +76 -0
- package/dist/remote.js +441 -0
- package/dist/schema.d.ts +3 -3
- package/dist/sql-tag.d.ts +1 -1
- package/dist/transport.d.ts +12 -1
- package/dist/transport.js +1 -1
- package/dist/wasm-database.d.ts +6 -4
- package/dist/wasm-database.js +13 -8
- package/dist/window.d.ts +1 -1
- package/dist/window.js +1 -1
- package/dist/worker-entry.js +1 -1
- package/dist/worker-host.d.ts +5 -5
- package/dist/worker-host.js +2 -2
- package/dist/worker-protocol.d.ts +3 -3
- package/dist/worker-protocol.js +1 -1
- package/package.json +3 -3
- package/src/browser-storage-persistence.ts +52 -0
- package/src/bun-database.ts +1 -1
- package/src/client.ts +6 -6
- package/src/database.ts +1 -1
- package/src/devtools.ts +1 -1
- package/src/http.ts +100 -8
- package/src/index.ts +4 -2
- package/src/invalidation.ts +1 -1
- package/src/leader-lock.ts +2 -2
- package/src/multi-tab.ts +1 -1
- package/src/naming.ts +1 -1
- package/src/node-database.ts +1 -1
- package/src/query-guard.ts +1 -1
- package/src/remote.ts +724 -0
- package/src/schema.ts +3 -3
- package/src/sql-tag.ts +1 -1
- package/src/transport.ts +20 -1
- package/src/wasm-database.ts +13 -8
- package/src/window.ts +1 -1
- package/src/worker-entry.ts +1 -1
- package/src/worker-host.ts +6 -6
- package/src/worker-protocol.ts +3 -3
package/src/schema.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Client schema IR (SPEC.md §2.4, §3.1) — the same shape the server
|
|
3
|
-
* compiles
|
|
3
|
+
* compiles and is emitted by codegen. Drives local table
|
|
4
4
|
* DDL, the generated row codec, mutation helpers, and the §3.3 purge
|
|
5
5
|
* mapping (scope variable → local column).
|
|
6
6
|
*/
|
|
@@ -19,7 +19,7 @@ export interface ClientIndexSpec {
|
|
|
19
19
|
readonly unique: boolean;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
/** One client-local contentful FTS5 projection
|
|
22
|
+
/** One client-local contentful FTS5 projection. */
|
|
23
23
|
export interface ClientFtsIndexSpec {
|
|
24
24
|
readonly name: string;
|
|
25
25
|
readonly columns: readonly string[];
|
|
@@ -63,7 +63,7 @@ export interface CompiledClientTable {
|
|
|
63
63
|
/**
|
|
64
64
|
* Scope variable → the pattern's literal prefix (§3.1). A stored-scope
|
|
65
65
|
* value `v` for this variable has scope key `prefix:v` — the invalidation
|
|
66
|
-
* vocabulary
|
|
66
|
+
* vocabulary and the delta-routing key.
|
|
67
67
|
*/
|
|
68
68
|
readonly scopePrefixByVariable: ReadonlyMap<string, string>;
|
|
69
69
|
/** Local secondary indexes to create on the mirror table (declaration
|
package/src/sql-tag.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The `sql` tagged template — the raw tier's composition helper
|
|
3
|
-
*
|
|
3
|
+
* Structural injection safety: an interpolated
|
|
4
4
|
* value can only ever become a `?` bind parameter; SQL text can only enter
|
|
5
5
|
* through the literal template, `sql.ident()` (allowlist-gated) or a loud
|
|
6
6
|
* `sql.raw()`. This helper is deliberately dumb plumbing and stays that
|
package/src/transport.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Transport seams
|
|
2
|
+
* Transport seams: request/response bytes, segment download,
|
|
3
3
|
* and the realtime attach surface matching §8's client side. Tests use
|
|
4
4
|
* loopback implementations that call the server library directly — the
|
|
5
5
|
* loopback doctrine; HTTP/WebSocket bindings live in `./http`.
|
|
@@ -8,6 +8,25 @@
|
|
|
8
8
|
/** One combined push+pull round trip: SSP2 request bytes → response bytes. */
|
|
9
9
|
export type SyncTransport = (request: Uint8Array) => Promise<Uint8Array>;
|
|
10
10
|
|
|
11
|
+
/** One registered authoritative query or command request. */
|
|
12
|
+
export type RemoteOperationTransport = (
|
|
13
|
+
request: Uint8Array,
|
|
14
|
+
) => Promise<Uint8Array>;
|
|
15
|
+
|
|
16
|
+
export interface RemoteOperationRealtimeHandlers {
|
|
17
|
+
onMessage(bytes: Uint8Array): void;
|
|
18
|
+
onClose?(): void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface RemoteOperationRealtimeSocket {
|
|
22
|
+
send(bytes: Uint8Array): void;
|
|
23
|
+
close(): void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type RemoteOperationRealtimeConnector = (
|
|
27
|
+
handlers: RemoteOperationRealtimeHandlers,
|
|
28
|
+
) => RemoteOperationRealtimeSocket | Promise<RemoteOperationRealtimeSocket>;
|
|
29
|
+
|
|
11
30
|
export interface SegmentFetchRequest {
|
|
12
31
|
readonly segmentId: string;
|
|
13
32
|
readonly table: string;
|
package/src/wasm-database.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `ClientDatabase` on @sqlite.org/sqlite-wasm
|
|
3
|
-
*
|
|
2
|
+
* `ClientDatabase` on @sqlite.org/sqlite-wasm. Two modes, no ladder between
|
|
3
|
+
* them:
|
|
4
4
|
*
|
|
5
|
-
* - `openPersistentWasmDatabase(name)` — THE persistent browser mode:
|
|
5
|
+
* - `openPersistentWasmDatabase(name)` — THE reload-persistent browser mode:
|
|
6
6
|
* OPFS via the `opfs-sahpool` VFS, restricted to Web Worker contexts
|
|
7
7
|
* because the whole client core runs in a worker by design. SAHPool
|
|
8
8
|
* needs **no COOP/COEP headers and no SharedArrayBuffer** (it is built
|
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
* proxy — the COOP/COEP requirement documented by sqlite-wasm applies
|
|
11
11
|
* only to `oo1.OpfsDb`, which this binding no longer uses). Browsers
|
|
12
12
|
* without OPFS are unsupported (support floor ~2023+): the factory
|
|
13
|
-
* fails loud. Never IndexedDB, never a silent in-memory fallback.
|
|
13
|
+
* fails loud. Never IndexedDB, never a silent in-memory fallback. The
|
|
14
|
+
* browser's separate origin-eviction policy is exposed from the root package
|
|
15
|
+
* by `checkBrowserStoragePersistence` and
|
|
16
|
+
* `requestBrowserStoragePersistence`.
|
|
14
17
|
* - `openWasmDatabase()` — EXPLICIT ephemeral: an in-memory database for
|
|
15
18
|
* tests, demos and SSR. Nothing survives a reload, on purpose.
|
|
16
19
|
*
|
|
@@ -184,7 +187,7 @@ function initSqlite3(): Promise<Sqlite3Static> {
|
|
|
184
187
|
* EXPLICIT ephemeral mode: an in-memory sqlite-wasm database. For tests,
|
|
185
188
|
* demos and SSR only — nothing persists. The persistent mode is
|
|
186
189
|
* `openPersistentWasmDatabase` inside a worker; there is no fallback from
|
|
187
|
-
* one to the other
|
|
190
|
+
* one to the other.
|
|
188
191
|
*/
|
|
189
192
|
export async function openWasmDatabase(): Promise<ClientDatabase> {
|
|
190
193
|
const sqlite3 = await initSqlite3();
|
|
@@ -238,14 +241,16 @@ function opfsSahPoolError(error: unknown, directory: string): ClientSyncError {
|
|
|
238
241
|
}
|
|
239
242
|
|
|
240
243
|
/**
|
|
241
|
-
* THE persistent browser mode: a named database on OPFS via the
|
|
244
|
+
* THE reload-persistent browser mode: a named database on OPFS via the
|
|
242
245
|
* `opfs-sahpool` VFS. Worker-context only — not because SAHPool requires
|
|
243
246
|
* it (it uses `FileSystemSyncAccessHandle`, no `Atomics.wait`, and could
|
|
244
247
|
* technically run on the main thread), but because the persistent mode IS
|
|
245
|
-
* whole-core-in-a-worker
|
|
248
|
+
* whole-core-in-a-worker and
|
|
246
249
|
* this factory enforces that decision. No COOP/COEP headers required.
|
|
247
250
|
*
|
|
248
|
-
* Support floor: no OPFS → a loud `ClientSyncError`, never a fallback.
|
|
251
|
+
* Support floor: no OPFS → a loud `ClientSyncError`, never a fallback. This
|
|
252
|
+
* factory cannot request eviction-resistant origin storage because that API
|
|
253
|
+
* belongs to the page's Window context.
|
|
249
254
|
*/
|
|
250
255
|
export async function openPersistentWasmDatabase(
|
|
251
256
|
name: string,
|
package/src/window.ts
CHANGED
package/src/worker-entry.ts
CHANGED
package/src/worker-host.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Main-thread side of the worker mode
|
|
3
|
-
* multi-tab topology
|
|
2
|
+
* Main-thread side of the worker mode and the
|
|
3
|
+
* multi-tab topology.
|
|
4
4
|
*
|
|
5
5
|
* `createSyncClientHandle` acquires the Web Locks leader lock and, when it
|
|
6
6
|
* wins, spawns the worker running the WHOLE core — so exactly one core runs
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* holding the lock). The returned {@link SyncClientHandle} is a thin, fully
|
|
9
9
|
* async proxy over the `worker-protocol` RPC.
|
|
10
10
|
*
|
|
11
|
-
* Multi-tab is the DEFAULT
|
|
11
|
+
* Multi-tab is the DEFAULT. The follower path is
|
|
12
12
|
* conformance-covered): a tab that LOSES the election becomes a FOLLOWER
|
|
13
13
|
* (`role === 'follower'`) that proxies every call to the leader tab over a
|
|
14
14
|
* BroadcastChannel (see `multi-tab.ts`). When the leader tab closes, its
|
|
@@ -181,7 +181,7 @@ export interface SyncClientHandleConfig {
|
|
|
181
181
|
/** Shared by default; isolated derives the database/lock/channel tuple. */
|
|
182
182
|
readonly replica?: BrowserReplicaMode;
|
|
183
183
|
/**
|
|
184
|
-
* Multi-tab followers
|
|
184
|
+
* Multi-tab followers. On by default: a tab that loses the
|
|
185
185
|
* leader election becomes a FOLLOWER that proxies to the leader over a
|
|
186
186
|
* BroadcastChannel, and contests + promotes when the leader closes. Set
|
|
187
187
|
* false for the single-tab contract — the loser is a dead
|
|
@@ -318,7 +318,7 @@ export class SyncClientHandle {
|
|
|
318
318
|
this.#diagnostics = internals.diagnostics;
|
|
319
319
|
this.#roleListeners = internals.roleListeners ?? new Set();
|
|
320
320
|
this.#leadershipListeners = internals.leadershipListeners ?? new Set();
|
|
321
|
-
//
|
|
321
|
+
// Console introspection is a no-op outside a dev page.
|
|
322
322
|
this.#devtoolsUnregister = registerDevtools({
|
|
323
323
|
kind: 'handle',
|
|
324
324
|
ref: this,
|
|
@@ -401,7 +401,7 @@ export class SyncClientHandle {
|
|
|
401
401
|
}
|
|
402
402
|
|
|
403
403
|
/**
|
|
404
|
-
*
|
|
404
|
+
* Subscribe to fine-grained invalidation. The identical
|
|
405
405
|
* surface as `SyncClient.onInvalidate`, so React bindings target one
|
|
406
406
|
* interface across direct, worker-leader, and follower modes. Returns an
|
|
407
407
|
* unsubscribe function.
|
package/src/worker-protocol.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The worker RPC protocol
|
|
2
|
+
* The worker RPC protocol: the whole
|
|
3
3
|
* client core runs in a Web Worker; the UI thread talks to it through
|
|
4
4
|
* this thin, multiplexed postMessage protocol. Exactly SIX message types
|
|
5
5
|
* (`init`, `call`, `ready`, `result`, `error`, `event`) — every logical
|
|
@@ -63,7 +63,7 @@ import type { WindowBase } from './window';
|
|
|
63
63
|
// Client-local error codes (never wire codes; §10 stays server-owned)
|
|
64
64
|
// ---------------------------------------------------------------------------
|
|
65
65
|
|
|
66
|
-
/** The handle exists but this tab lost the leader election
|
|
66
|
+
/** The handle exists but this tab lost the leader election. */
|
|
67
67
|
export const NOT_LEADER_CODE = 'client.not_leader';
|
|
68
68
|
/** The worker (or its RPC channel) failed outside protocol semantics. */
|
|
69
69
|
export const WORKER_FAILED_CODE = 'client.worker_failed';
|
|
@@ -76,7 +76,7 @@ export const WORKER_RESTART_REQUIRED_CODE = 'client.worker_restart_required';
|
|
|
76
76
|
|
|
77
77
|
export type WorkerDatabaseInit =
|
|
78
78
|
| {
|
|
79
|
-
/**
|
|
79
|
+
/** Reload-persistent OPFS mode; origin eviction policy stays page-owned. */
|
|
80
80
|
readonly mode: 'persistent';
|
|
81
81
|
readonly name: string;
|
|
82
82
|
/** Optional pool directory override (default `.syncular/<name>`). */
|