@lix-js/sdk 0.16.0 → 0.17.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 +187 -22
- package/dist/binding-types.d.ts +20 -6
- package/dist/binding.browser.d.ts +2 -0
- package/dist/binding.browser.js +14 -4
- package/dist/binding.node-wasm.d.ts +1 -1
- package/dist/binding.node-wasm.js +5 -3
- package/dist/binding.node.d.ts +2 -0
- package/dist/binding.node.js +34 -8
- package/dist/bundled-plugins/plugin_csv.lixplugin +0 -0
- package/dist/bundled-plugins/plugin_markdown.lixplugin +0 -0
- package/dist/compatibility.d.ts +6 -0
- package/dist/compatibility.js +6 -0
- package/dist/component-host/dispatch.d.ts +12 -0
- package/dist/component-host/dispatch.js +364 -0
- package/dist/component-host/index.d.ts +15 -0
- package/dist/component-host/index.js +84 -0
- package/dist/component-host/instrument.d.ts +6 -0
- package/dist/component-host/instrument.js +260 -0
- package/dist/conversion-provider.d.ts +4 -0
- package/dist/conversion-provider.js +20 -0
- package/dist/hosted-lix.js +1 -1
- package/dist/http-transport.d.ts +25 -0
- package/dist/http-transport.js +162 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/lix.d.ts +20 -10
- package/dist/lix.js +68 -23
- package/dist/migration-binding.browser.d.ts +33 -0
- package/dist/migration-binding.browser.js +46 -0
- package/dist/migration-binding.node.d.ts +6 -0
- package/dist/migration-binding.node.js +5 -0
- package/dist/migration-wasm/lix_js_sdk.d.ts +271 -0
- package/dist/migration-wasm/lix_js_sdk.js +1852 -0
- package/dist/migration-wasm/lix_js_sdk_bg.wasm +4 -0
- package/dist/migration-wasm/lix_js_sdk_bg.wasm.d.ts +101 -0
- package/dist/migration.d.ts +23 -0
- package/dist/migration.js +55 -0
- package/dist/open-lix.js +29 -18
- package/dist/open-progress.d.ts +10 -0
- package/dist/open-progress.js +59 -0
- package/dist/remote/client.d.ts +2 -1
- package/dist/remote/client.js +11 -1
- package/dist/result.d.ts +4 -3
- package/dist/result.js +3 -4
- package/dist/storage-adapter.d.ts +7 -5
- package/dist/storage-ownership.d.ts +5 -0
- package/dist/storage-ownership.js +4 -0
- package/dist/types.d.ts +132 -22
- package/dist/wasm/lix_js_sdk.d.ts +57 -16
- package/dist/wasm/lix_js_sdk.js +268 -60
- package/dist/wasm/lix_js_sdk_bg.wasm +2 -2
- package/dist/wasm/lix_js_sdk_bg.wasm.d.ts +23 -9
- package/dist/worker/client.d.ts +12 -3
- package/dist/worker/client.js +98 -81
- package/dist/worker/durable-local-admission.d.ts +20 -0
- package/dist/worker/durable-local-admission.js +87 -0
- package/dist/worker/entry.shared.browser.d.ts +1 -0
- package/dist/worker/entry.shared.browser.js +211 -0
- package/dist/worker/factory.browser.d.ts +2 -0
- package/dist/worker/factory.browser.js +65 -1
- package/dist/worker/factory.node.d.ts +1 -0
- package/dist/worker/factory.node.js +3 -0
- package/dist/worker/host.d.ts +4 -2
- package/dist/worker/host.js +92 -32
- package/dist/worker/protocol.d.ts +33 -8
- package/dist/worker/protocol.js +25 -7
- package/dist/worker/shared-admission.d.ts +26 -0
- package/dist/worker/shared-admission.js +116 -0
- package/dist/worker/shared-engine.d.ts +34 -0
- package/dist/worker/shared-engine.js +194 -0
- package/package.json +21 -13
- package/dist/remote/server-protocol.d.ts +0 -185
- package/dist/remote/server-protocol.js +0 -417
package/README.md
CHANGED
|
@@ -22,16 +22,57 @@ console.log(result.rows[0]?.message);
|
|
|
22
22
|
await lix.close();
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
For compiled plugin downloads, installation, updates, and uninstalling, see
|
|
26
|
+
[Installing and managing plugins](../../docs/plugins.md).
|
|
27
|
+
|
|
25
28
|
## Hosted lifecycle
|
|
26
29
|
|
|
27
|
-
|
|
30
|
+
### Automatic upgrades and progress
|
|
31
|
+
|
|
32
|
+
Opening a supported older hosted repository automatically upgrades it on the
|
|
33
|
+
server. The SDK waits inside `openLix()`; applications do not implement migration
|
|
34
|
+
or retry logic. Concurrent opens share the server's upgrade operation.
|
|
35
|
+
|
|
36
|
+
Use `onProgress` to display status in either remote or partial-replica mode.
|
|
37
|
+
Authority upgrades emit `scope: "authority"` and `phase: "migrating"`, followed
|
|
38
|
+
by opening and completion. The source format and work totals may be unknown:
|
|
39
|
+
show “Upgrading repository” with an indeterminate indicator instead of inventing
|
|
40
|
+
a percentage. Progress callbacks are observational and cannot change the result
|
|
41
|
+
of opening.
|
|
42
|
+
|
|
43
|
+
### Compatibility metadata
|
|
44
|
+
|
|
45
|
+
Raw HTTP integrations can obtain this SDK's protocol versions without loading
|
|
46
|
+
the engine:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { compatibility } from "@lix-js/sdk/compatibility";
|
|
50
|
+
|
|
51
|
+
const headers = {
|
|
52
|
+
"Lix-Server-Protocol-Version": String(compatibility.serverProtocolVersion),
|
|
53
|
+
"Lix-Sync-Protocol-Version": String(compatibility.syncProtocolVersion),
|
|
54
|
+
};
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The object also includes `storageFormatVersion`. It is generated from the Rust
|
|
58
|
+
engine constants during the SDK build. Source-checkout CI can use
|
|
59
|
+
`node scripts/compatibility.mjs` before building the SDK.
|
|
60
|
+
|
|
61
|
+
### Execution modes
|
|
62
|
+
|
|
63
|
+
`openLix()` selects execution from storage and the explicit server mode:
|
|
28
64
|
|
|
29
65
|
| Options | Behavior |
|
|
30
66
|
| --- | --- |
|
|
31
67
|
| Neither | Fresh in-memory repository |
|
|
32
68
|
| `storage` | Local repository, initialized if empty |
|
|
33
|
-
| `server` | Execute against an existing hosted repository |
|
|
34
|
-
| `storage` and `server` |
|
|
69
|
+
| `server`, mode omitted or `"remote"` | Execute SQL remotely against an existing hosted repository; no local storage |
|
|
70
|
+
| `storage` and `server.mode: "partial_replica"` | Partial replica with on-demand sync; reads and writes whose dependencies are resident execute locally |
|
|
71
|
+
|
|
72
|
+
`server.mode` defaults to `"remote"`. Supplying storage requires explicitly opting
|
|
73
|
+
into `"partial_replica"`; remote mode rejects storage. Partial-replica mode requires
|
|
74
|
+
storage. These are the only supported server modes. `"replica"` may be added later;
|
|
75
|
+
the former `"sync"` mode is not an alias.
|
|
35
76
|
|
|
36
77
|
Creation and deletion are explicit server operations:
|
|
37
78
|
|
|
@@ -64,9 +105,10 @@ execution do not require streaming uploads.
|
|
|
64
105
|
|
|
65
106
|
## Synchronized local repositories
|
|
66
107
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
108
|
+
Provide storage and set `server.mode: "partial_replica"` to create a
|
|
109
|
+
**partial replica with on-demand sync**. Opening loads bounded metadata. SQL fetches missing native inputs on
|
|
110
|
+
demand and retains them locally; background synchronization updates the loaded
|
|
111
|
+
working set:
|
|
70
112
|
|
|
71
113
|
```ts
|
|
72
114
|
import { openLix } from "@lix-js/sdk";
|
|
@@ -75,6 +117,7 @@ import { OpfsStorage } from "@lix-js/storage-opfs";
|
|
|
75
117
|
const lix = await openLix({
|
|
76
118
|
storage: new OpfsStorage({ name: "acme" }),
|
|
77
119
|
server: {
|
|
120
|
+
mode: "partial_replica",
|
|
78
121
|
url: "https://example.com/lix/01936f4e-7b6c-7c3d-8f9a-123456789abc",
|
|
79
122
|
headers: async () => ({
|
|
80
123
|
Authorization: `Bearer ${await accessToken()}`,
|
|
@@ -83,12 +126,121 @@ const lix = await openLix({
|
|
|
83
126
|
});
|
|
84
127
|
```
|
|
85
128
|
|
|
86
|
-
A successful mutation confirms
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
129
|
+
A successful mutation confirms a local commit; it does not confirm server
|
|
130
|
+
acceptance. Pending commits upload in the background. Covered reads and writes
|
|
131
|
+
whose dependencies are resident work offline, with immediate local visibility.
|
|
132
|
+
A statement requiring missing inputs needs a connection; missing data is never
|
|
133
|
+
silently treated as an empty result. Current data means the coherently applied
|
|
134
|
+
server state plus pending local writes.
|
|
135
|
+
|
|
136
|
+
Prefetch a view on hover using the same ordinary SELECT it will display:
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
const sql = "SELECT content FROM lix_file WHERE path=$1";
|
|
140
|
+
const params = ["/notes.txt"];
|
|
141
|
+
await lix.execute(sql, params); // On hover: fetch missing read inputs.
|
|
142
|
+
const result = await lix.execute(sql, params); // On open: resident reads stay local.
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Use ordinary `execute()` for mutations. Reading a file does not promise that every
|
|
146
|
+
later write's validation or commit dependencies are resident; cold operations can
|
|
147
|
+
fetch additional inputs while connected.
|
|
148
|
+
|
|
90
149
|
See [Collaboration and Sync](https://lix.dev/docs/collaboration-and-sync).
|
|
91
150
|
|
|
151
|
+
### Upgrading a local replica
|
|
152
|
+
|
|
153
|
+
Keep the same storage name across SDK upgrades. Opening an existing full replica
|
|
154
|
+
with `server.mode: "partial_replica"` requires an explicit conversion; normal opening does not download a
|
|
155
|
+
replacement repository. Run conversion while the storage has no open Lix handle:
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
import { convertReplicaToPartial, openLix } from "@lix-js/sdk";
|
|
159
|
+
|
|
160
|
+
const storage = new OpfsStorage({ name: "acme" });
|
|
161
|
+
const server = {
|
|
162
|
+
mode: "partial_replica" as const,
|
|
163
|
+
url: "https://example.com/lix/01936f4e-7b6c-7c3d-8f9a-123456789abc",
|
|
164
|
+
headers: async () => ({ Authorization: `Bearer ${await accessToken()}` }),
|
|
165
|
+
};
|
|
166
|
+
await convertReplicaToPartial({ storage, server });
|
|
167
|
+
const lix = await openLix({ storage, server });
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Conversion authenticates the repository and account, preserves the original
|
|
171
|
+
storage generation, and publishes a separate partial replica only after its
|
|
172
|
+
required reconciliation and validation succeed. It can require time and extra
|
|
173
|
+
storage; measure it separately from ordinary opening. Unsupported pending work
|
|
174
|
+
returns an error with the original source preserved. Do not clear storage to
|
|
175
|
+
bypass that error.
|
|
176
|
+
|
|
177
|
+
If authority cleanup is interrupted after conversion, retry it explicitly while
|
|
178
|
+
storage is closed. Ordinary opening does not scan migration journals:
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
import { retryReplicaMigrationCleanup } from "@lix-js/sdk";
|
|
182
|
+
const completed = await retryReplicaMigrationCleanup({ storage, server });
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
This returns the number of newly completed cleanup records; repeating a
|
|
186
|
+
successful cleanup returns zero. It preserves the active replica and retained
|
|
187
|
+
source generation.
|
|
188
|
+
|
|
189
|
+
For retained pre-native sources, explicit format migration can succeed while
|
|
190
|
+
partial conversion reports that recovery is required. Open the resulting local
|
|
191
|
+
recovery repository without `server`, then inspect and restore retained work:
|
|
192
|
+
|
|
193
|
+
```ts
|
|
194
|
+
const recovery = await openLix({ storage });
|
|
195
|
+
try {
|
|
196
|
+
const sources = await recovery.replicaRecoverySources();
|
|
197
|
+
for (const source of sources.filter((source) => source.recoveryRequired)) {
|
|
198
|
+
const exported = await recovery.exportReplicaRecovery(source.id);
|
|
199
|
+
console.log(exported.unresolved); // Save a portable copy when needed.
|
|
200
|
+
|
|
201
|
+
const receipt = await recovery.recoverReplicaWithServer(source.id, server);
|
|
202
|
+
console.log(receipt.branchIds, receipt.restoredRows, receipt.unresolved);
|
|
203
|
+
}
|
|
204
|
+
} finally {
|
|
205
|
+
await recovery.close();
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
`recoverReplicaWithServer()` authenticates the same repository and account and
|
|
210
|
+
fetches missing recovery history or chunks explicitly. It does not start a
|
|
211
|
+
background sync worker or upload restored branches. Dynamic headers and custom
|
|
212
|
+
fetch remain scoped to this operation in the browser. The native Node binding
|
|
213
|
+
supports headers and rejects custom fetch.
|
|
214
|
+
|
|
215
|
+
`exportReplicaRecovery()` captures available logical rows, blob contents, and
|
|
216
|
+
original branch/checkpoint coordinates. `recoverReplica()` performs local
|
|
217
|
+
restoration; its server variant can hydrate missing dependencies. Both restore
|
|
218
|
+
supported tracked rows into separate recovery branches without inheriting
|
|
219
|
+
unrelated active-branch rows. Inspect `unresolved`: unavailable history/content
|
|
220
|
+
and local-only rows remain in the retained source. Neither operation deletes
|
|
221
|
+
that source, and retries reuse durable recovery receipts.
|
|
222
|
+
|
|
223
|
+
A recovery receipt confirms local restoration, not server acceptance or
|
|
224
|
+
eligibility for partial conversion. Conversion of every retained pending branch
|
|
225
|
+
is still a release gate: restored additional branches and unresolved retained
|
|
226
|
+
sources must not be silently discarded or marked acknowledged. The current
|
|
227
|
+
selected-branch native reconciliation path does not establish that broader
|
|
228
|
+
migration guarantee.
|
|
229
|
+
|
|
230
|
+
Recovery export currently allows up to 100,000 logical rows across all branches,
|
|
231
|
+
64 MiB per blob, and 128 MiB of blob content in total. Unfinished upload parts
|
|
232
|
+
have a separate 128 MiB content budget. A row-limit or upload-limit error leaves
|
|
233
|
+
the source intact; omitted blob content is identified in `unresolved`. Exported
|
|
234
|
+
JSON can be larger than these content budgets because binary data uses base64.
|
|
235
|
+
This recovery file is not a complete repository backup.
|
|
236
|
+
|
|
237
|
+
These methods require a local storage-backed handle; remote-only handles reject
|
|
238
|
+
with `LIX_ERROR_LOCAL_STORAGE_REQUIRED`. Do not clear browser storage to resolve
|
|
239
|
+
upgrade or recovery errors. Browser storage eviction or an unsupported old format
|
|
240
|
+
can still require external recovery; retaining bytes alone is not proof that all
|
|
241
|
+
work has been recovered. Standalone and authoritative repositories continue to
|
|
242
|
+
use history-preserving format migrations.
|
|
243
|
+
|
|
92
244
|
## Remote repositories
|
|
93
245
|
|
|
94
246
|
Use the same Lix client as a thin client against a hosted repository:
|
|
@@ -116,7 +268,8 @@ files.close();
|
|
|
116
268
|
await lix.close();
|
|
117
269
|
```
|
|
118
270
|
|
|
119
|
-
|
|
271
|
+
Remote mode is the default when `server.mode` is omitted. It rejects `storage`,
|
|
272
|
+
uses the server for all persistence and does not
|
|
120
273
|
open a local engine. Dynamic headers are resolved for every request and
|
|
121
274
|
observation reconnect. An injected `fetch` can route requests through a service
|
|
122
275
|
binding or another authorized server-side transport.
|
|
@@ -243,18 +396,30 @@ try {
|
|
|
243
396
|
- The package is ESM-only.
|
|
244
397
|
- The package uses conditional ESM imports internally: Node.js resolves the
|
|
245
398
|
native N-API binding, while browsers and other runtimes resolve the portable
|
|
246
|
-
WebAssembly binding. Vite
|
|
399
|
+
WebAssembly binding. Vite resolves these conditional imports automatically.
|
|
400
|
+
Configure Vite to emit ES module workers because the Component compiler uses
|
|
401
|
+
top-level await:
|
|
402
|
+
|
|
403
|
+
```js
|
|
404
|
+
// vite.config.js
|
|
405
|
+
export default { worker: { format: "es" } };
|
|
406
|
+
```
|
|
247
407
|
- If the native addon cannot load in Node.js, in-memory Lix instances fall back
|
|
248
|
-
to the bundled WebAssembly engine. Filesystem storage
|
|
249
|
-
plugin execution still require the native addon.
|
|
408
|
+
to the bundled WebAssembly engine. Filesystem storage still requires the native addon.
|
|
250
409
|
- Every browser `openLix()` owns one dedicated worker, so database work does
|
|
251
410
|
not block the page's main thread. Node.js uses the native binding's actor.
|
|
252
|
-
- Node.js
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
411
|
+
- Node.js and browsers execute installed Component API v2 plugins through the
|
|
412
|
+
same JavaScript Component host. The host adapts Component interfaces to the
|
|
413
|
+
platform's built-in WebAssembly runtime and connects them to Lix's shared Rust
|
|
414
|
+
host resources. Node.js retains its native engine and filesystem adapter;
|
|
415
|
+
the browser engine runs inside its dedicated worker.
|
|
416
|
+
- Components are compiled on first use. Each file actor gets an isolated guest
|
|
417
|
+
instance. Guest functions and loops check execution deadlines, and core memory
|
|
418
|
+
declarations are capped before instantiation. Unsupported memory forms are
|
|
419
|
+
rejected rather than executed without limits.
|
|
256
420
|
- A page Content Security Policy only needs to permit the package's same-origin
|
|
257
|
-
worker.
|
|
421
|
+
worker. Component bindings are generated as data URL modules and WebAssembly
|
|
422
|
+
compilation happens inside that worker, so the required
|
|
258
423
|
permission can be scoped to the worker script's HTTP response instead of
|
|
259
424
|
being allowed by the document:
|
|
260
425
|
|
|
@@ -263,11 +428,11 @@ try {
|
|
|
263
428
|
Content-Security-Policy: default-src 'self'; script-src 'self'; worker-src 'self'
|
|
264
429
|
|
|
265
430
|
# Lix worker response (Vite emits assets/entry.browser-<hash>.js)
|
|
266
|
-
Content-Security-Policy: default-src 'none'; script-src 'self' 'wasm-unsafe-eval'; connect-src 'self'
|
|
431
|
+
Content-Security-Policy: default-src 'none'; script-src 'self' data: 'wasm-unsafe-eval'; connect-src 'self'
|
|
267
432
|
```
|
|
268
433
|
|
|
269
434
|
Hosts that apply one policy to every response can use
|
|
270
|
-
`script-src 'self' 'wasm-unsafe-eval'; worker-src 'self'` globally
|
|
435
|
+
`script-src 'self' data: 'wasm-unsafe-eval'; worker-src 'self'` globally
|
|
271
436
|
instead. Worker-scoped headers keep those permissions out of the page.
|
|
272
437
|
|
|
273
438
|
- SQL parameters use normal JavaScript values: `string`, finite `number`, `boolean`, `Uint8Array`, `null`, JSON-compatible arrays, and JSON-compatible plain objects.
|
|
@@ -287,7 +452,7 @@ npm run test:browser
|
|
|
287
452
|
|
|
288
453
|
`npm run test:browser:production` additionally packs the SDK, installs the
|
|
289
454
|
tarball into a minimal Vite app, makes a production build, and exercises SQL
|
|
290
|
-
plus bundled-plugin
|
|
455
|
+
plus bundled-plugin installation and CSV row extraction in Chromium. It runs with both
|
|
291
456
|
worker-scoped and global strict CSP headers.
|
|
292
457
|
|
|
293
458
|
Use `npm run build:wasm:dev` while iterating on the Rust bridge when release
|
package/dist/binding-types.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { HttpTransport } from "./http-transport.js";
|
|
2
|
+
import type { CommitSpan, CreateBranchOptions, CreateBranchReceipt, UndoReceipt, RedoReceipt, ExecuteOptions, LixBatchOptions, MergeBranchOptions, MergeBranchPreview, MergeBranchReceipt, SwitchBranchOptions, SwitchBranchReceipt, LixTelemetrySpan, LixTelemetryParentContext, LixOpenProgress, LixOpenReport, ReplicaRecoverySource, ReplicaRecoveryExport, ReplicaRecoveryReceipt, OpenAnotherSessionOptions, ResultColumn } from "./types.js";
|
|
2
3
|
import type { NativeLixValue } from "./value.js";
|
|
3
4
|
import type { LixStorageProvider } from "./storage-adapter.js";
|
|
4
5
|
export type SyncServerBindingOptions = {
|
|
5
6
|
url: string;
|
|
6
7
|
headers: [string, string][];
|
|
7
8
|
headerProvider?: () => Promise<[string, string][]>;
|
|
8
|
-
|
|
9
|
+
transport?: HttpTransport;
|
|
9
10
|
};
|
|
10
11
|
export type BindingExecuteResult = {
|
|
11
12
|
statementIndex?: number;
|
|
@@ -18,6 +19,7 @@ export type BindingExecuteResult = {
|
|
|
18
19
|
message: string;
|
|
19
20
|
hint?: string;
|
|
20
21
|
}>;
|
|
22
|
+
commit?: CommitSpan;
|
|
21
23
|
};
|
|
22
24
|
export type BindingObserveEvent = {
|
|
23
25
|
sequence: number;
|
|
@@ -44,11 +46,19 @@ export type LixBinding = {
|
|
|
44
46
|
createHosted?(server: HostedServerBindingOptions): Promise<import("./types.js").HostedLix>;
|
|
45
47
|
openReport?(): LixOpenReport | undefined;
|
|
46
48
|
setTelemetryParent(parent?: TelemetryParentContext): void;
|
|
47
|
-
openAnotherSession(options: OpenAnotherSessionOptions): Promise<LixBinding>;
|
|
49
|
+
openAnotherSession(options: OpenAnotherSessionOptions, telemetry?: TelemetryDispatch): Promise<LixBinding>;
|
|
48
50
|
execute(sql: string, params: BindingParam[], options?: ExecuteOptions): Promise<BindingExecuteResult>;
|
|
49
|
-
executeBatch(statements: BindingBatchStatement[], options?: LixBatchOptions): Promise<
|
|
51
|
+
executeBatch(statements: BindingBatchStatement[], options?: LixBatchOptions): Promise<{
|
|
52
|
+
results: BindingExecuteResult[];
|
|
53
|
+
commit?: CommitSpan | null;
|
|
54
|
+
}>;
|
|
50
55
|
observe(sql: string, params: BindingParam[]): Promise<ObserveEventsBinding>;
|
|
51
56
|
beginTransaction(): Promise<LixTransactionBinding>;
|
|
57
|
+
replicaRecoverySources(): Promise<ReplicaRecoverySource[]>;
|
|
58
|
+
exportReplicaRecovery(id: string): Promise<ReplicaRecoveryExport>;
|
|
59
|
+
recoverReplica(id: string): Promise<ReplicaRecoveryReceipt>;
|
|
60
|
+
recoverReplicaWithServer(id: string, server: SyncServerBindingOptions): Promise<ReplicaRecoveryReceipt>;
|
|
61
|
+
syncHealth(): Promise<import("./types.js").SyncHealth>;
|
|
52
62
|
activeBranchId(): Promise<string>;
|
|
53
63
|
activeAccountId(): Promise<string>;
|
|
54
64
|
createBranch(options: CreateBranchOptions): Promise<CreateBranchReceipt>;
|
|
@@ -64,7 +74,9 @@ export type LixBinding = {
|
|
|
64
74
|
};
|
|
65
75
|
export type LixTransactionBinding = {
|
|
66
76
|
execute(sql: string, params: BindingParam[], options?: ExecuteOptions): Promise<BindingExecuteResult>;
|
|
67
|
-
commit(): Promise<
|
|
77
|
+
commit(): Promise<{
|
|
78
|
+
commit?: CommitSpan | null;
|
|
79
|
+
}>;
|
|
68
80
|
rollback(): Promise<void>;
|
|
69
81
|
};
|
|
70
82
|
export type ObserveEventsBinding = {
|
|
@@ -79,6 +91,8 @@ export type LixStorageProviderModule = {
|
|
|
79
91
|
createLixStorageProvider(options: unknown): Promise<LixStorageProvider>;
|
|
80
92
|
};
|
|
81
93
|
export type LixStorageConfig = {
|
|
94
|
+
durability?: import("./types.js").Durability;
|
|
95
|
+
} & ({
|
|
82
96
|
kind: "memory";
|
|
83
97
|
} | {
|
|
84
98
|
kind: "jsStorage";
|
|
@@ -88,7 +102,7 @@ export type LixStorageConfig = {
|
|
|
88
102
|
kind: "filesystem";
|
|
89
103
|
path: string;
|
|
90
104
|
syncAllFiles: boolean;
|
|
91
|
-
};
|
|
105
|
+
});
|
|
92
106
|
export type HostedServerBindingOptions = {
|
|
93
107
|
idempotencyKey?: string;
|
|
94
108
|
url: string;
|
|
@@ -2,3 +2,5 @@ import type { LixStorageConfig, LixBinding, SyncServerBindingOptions, TelemetryD
|
|
|
2
2
|
export declare function openLixBinding(storage: LixStorageConfig, telemetry?: TelemetryDispatch, telemetryParent?: TelemetryParentContext, server?: SyncServerBindingOptions, openProgress?: OpenProgressDispatch, snapshot?: ReadableStream<Uint8Array>): Promise<LixBinding>;
|
|
3
3
|
export declare function createHostedBinding(server: import("./binding-types.js").HostedServerBindingOptions): Promise<import("./types.js").HostedLix>;
|
|
4
4
|
export declare function deleteHostedBinding(server: import("./binding-types.js").HostedServerBindingOptions): Promise<void>;
|
|
5
|
+
export declare function convertReplicaBinding(storage: LixStorageConfig, server: SyncServerBindingOptions, branchId?: string): Promise<void>;
|
|
6
|
+
export declare function retryReplicaMigrationCleanupBinding(storage: LixStorageConfig, server: SyncServerBindingOptions): Promise<number>;
|
package/dist/binding.browser.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createComponentDispatch } from "./component-host/dispatch.js";
|
|
1
2
|
import { initializeWasm } from "./wasm-init.js";
|
|
2
3
|
import { restoreSnapshot } from "./snapshot-restore.js";
|
|
3
4
|
// Generated before TypeScript compilation and emitted beside this module.
|
|
@@ -7,11 +8,12 @@ import { createHosted, deleteHosted, openJsStorage, openJsStorageFromSnapshot, o
|
|
|
7
8
|
} from "./wasm/lix_js_sdk.js";
|
|
8
9
|
export async function openLixBinding(storage, telemetry, telemetryParent, server, openProgress, snapshot) {
|
|
9
10
|
await initializeWasm();
|
|
11
|
+
const componentDispatch = createComponentDispatch();
|
|
10
12
|
switch (storage.kind) {
|
|
11
13
|
case "memory":
|
|
12
14
|
return (snapshot
|
|
13
|
-
? restoreSnapshot(snapshot, openMemoryFromSnapshot(telemetry, telemetryParent, openProgress))
|
|
14
|
-
: openMemory(telemetry, telemetryParent, server, openProgress));
|
|
15
|
+
? restoreSnapshot(snapshot, openMemoryFromSnapshot(telemetry, telemetryParent, openProgress, componentDispatch, storage.durability))
|
|
16
|
+
: openMemory(telemetry, telemetryParent, server, openProgress, componentDispatch, storage.durability));
|
|
15
17
|
case "jsStorage": {
|
|
16
18
|
const module = (await import(
|
|
17
19
|
/* @vite-ignore */ storage.moduleUrl));
|
|
@@ -21,8 +23,8 @@ export async function openLixBinding(storage, telemetry, telemetryParent, server
|
|
|
21
23
|
const provider = await module.createLixStorageProvider(storage.options);
|
|
22
24
|
try {
|
|
23
25
|
const binding = (await (snapshot
|
|
24
|
-
? restoreSnapshot(snapshot, openJsStorageFromSnapshot(provider, telemetry, telemetryParent, openProgress))
|
|
25
|
-
: openJsStorage(provider, telemetry, telemetryParent, server, openProgress)));
|
|
26
|
+
? restoreSnapshot(snapshot, openJsStorageFromSnapshot(provider, telemetry, telemetryParent, openProgress, componentDispatch, storage.durability))
|
|
27
|
+
: openJsStorage(provider, telemetry, telemetryParent, server, openProgress, componentDispatch, storage.durability)));
|
|
26
28
|
return binding;
|
|
27
29
|
}
|
|
28
30
|
catch (error) {
|
|
@@ -42,3 +44,11 @@ export async function deleteHostedBinding(server) {
|
|
|
42
44
|
await initializeWasm();
|
|
43
45
|
await deleteHosted(server);
|
|
44
46
|
}
|
|
47
|
+
export async function convertReplicaBinding(storage, server, branchId) {
|
|
48
|
+
const migration = await import("./migration-binding.browser.js");
|
|
49
|
+
return migration.convertReplicaBinding(storage, server, branchId);
|
|
50
|
+
}
|
|
51
|
+
export async function retryReplicaMigrationCleanupBinding(storage, server) {
|
|
52
|
+
const migration = await import("./migration-binding.browser.js");
|
|
53
|
+
return migration.retryReplicaMigrationCleanupBinding(storage, server);
|
|
54
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { LixBinding, TelemetryDispatch, TelemetryParentContext, OpenProgressDispatch } from "./binding-types.js";
|
|
2
|
-
export declare function openMemoryWasmBinding(telemetry?: TelemetryDispatch, telemetryParent?: TelemetryParentContext, openProgress?: OpenProgressDispatch, snapshot?: ReadableStream<Uint8Array
|
|
2
|
+
export declare function openMemoryWasmBinding(telemetry?: TelemetryDispatch, telemetryParent?: TelemetryParentContext, openProgress?: OpenProgressDispatch, snapshot?: ReadableStream<Uint8Array>, durability?: import("./types.js").Durability): Promise<LixBinding>;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import { createComponentDispatch } from "./component-host/dispatch.js";
|
|
1
2
|
import { restoreSnapshot } from "./snapshot-restore.js";
|
|
2
3
|
import { initializeWasm } from "./wasm-init.js";
|
|
3
4
|
// Generated before TypeScript compilation and emitted beside this module.
|
|
4
5
|
// @ts-ignore Generated by build:wasm and absent in source-only checks.
|
|
5
6
|
import { openMemory, openMemoryFromSnapshot } from "./wasm/lix_js_sdk.js";
|
|
6
|
-
export async function openMemoryWasmBinding(telemetry, telemetryParent, openProgress, snapshot) {
|
|
7
|
+
export async function openMemoryWasmBinding(telemetry, telemetryParent, openProgress, snapshot, durability) {
|
|
7
8
|
await initializeWasm();
|
|
9
|
+
const componentDispatch = createComponentDispatch();
|
|
8
10
|
if (snapshot) {
|
|
9
|
-
return restoreSnapshot(snapshot, openMemoryFromSnapshot(telemetry, telemetryParent, openProgress));
|
|
11
|
+
return restoreSnapshot(snapshot, openMemoryFromSnapshot(telemetry, telemetryParent, openProgress, componentDispatch, durability));
|
|
10
12
|
}
|
|
11
|
-
return openMemory(telemetry, telemetryParent, undefined, openProgress);
|
|
13
|
+
return openMemory(telemetry, telemetryParent, undefined, openProgress, componentDispatch, durability);
|
|
12
14
|
}
|
package/dist/binding.node.d.ts
CHANGED
|
@@ -3,3 +3,5 @@ export declare function openLixBinding(storage: LixStorageConfig, telemetry?: Te
|
|
|
3
3
|
export declare function openNativeLixBinding(storage: LixStorageConfig, telemetry?: TelemetryDispatch, telemetryParent?: TelemetryParentContext, server?: SyncServerBindingOptions, openProgress?: OpenProgressDispatch, snapshot?: ReadableStream<Uint8Array>): Promise<LixBinding>;
|
|
4
4
|
export declare function createHostedBinding(server: import("./binding-types.js").HostedServerBindingOptions): Promise<import("./types.js").HostedLix>;
|
|
5
5
|
export declare function deleteHostedBinding(server: import("./binding-types.js").HostedServerBindingOptions): Promise<void>;
|
|
6
|
+
export declare function convertReplicaBinding(storage: LixStorageConfig, server: SyncServerBindingOptions, branchId?: string): Promise<void>;
|
|
7
|
+
export declare function retryReplicaMigrationCleanupBinding(storage: LixStorageConfig, server: SyncServerBindingOptions): Promise<number>;
|
package/dist/binding.node.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createComponentDispatch } from "./component-host/dispatch.js";
|
|
1
2
|
import { existsSync } from "node:fs";
|
|
2
3
|
import { createRequire } from "node:module";
|
|
3
4
|
import { fileURLToPath } from "node:url";
|
|
@@ -19,6 +20,14 @@ function normalizeNativeBinding(binding) {
|
|
|
19
20
|
if (property === "setTelemetryParent") {
|
|
20
21
|
return (parent) => target.setTelemetryParent(parent === undefined ? undefined : JSON.stringify(parent));
|
|
21
22
|
}
|
|
23
|
+
if (property === "recoverReplicaWithServer") {
|
|
24
|
+
return async (id, server) => {
|
|
25
|
+
if (server.transport)
|
|
26
|
+
throw new Error("Custom fetch is unsupported for native recovery");
|
|
27
|
+
const headers = server.headerProvider ? await server.headerProvider() : server.headers;
|
|
28
|
+
return target.recoverReplicaWithServer(id, server.url, headers);
|
|
29
|
+
};
|
|
30
|
+
}
|
|
22
31
|
if (property === "observe") {
|
|
23
32
|
return async (sql, params) => normalizeNativeObserveEvents(await target.observe(sql, params));
|
|
24
33
|
}
|
|
@@ -91,7 +100,7 @@ export async function openLixBinding(storage, telemetry, telemetryParent, server
|
|
|
91
100
|
}
|
|
92
101
|
try {
|
|
93
102
|
const { openMemoryWasmBinding } = await import("./binding.node-wasm.js");
|
|
94
|
-
return await openMemoryWasmBinding(telemetry, telemetryParent, openProgress, snapshot);
|
|
103
|
+
return await openMemoryWasmBinding(telemetry, telemetryParent, openProgress, snapshot, storage.durability);
|
|
95
104
|
}
|
|
96
105
|
catch (wasmError) {
|
|
97
106
|
throw new AggregateError([nativeError, wasmError], "Failed to open in-memory Lix with either the native or WebAssembly binding.");
|
|
@@ -99,7 +108,7 @@ export async function openLixBinding(storage, telemetry, telemetryParent, server
|
|
|
99
108
|
}
|
|
100
109
|
}
|
|
101
110
|
export async function openNativeLixBinding(storage, telemetry, telemetryParent, server, openProgress, snapshot) {
|
|
102
|
-
if (server?.
|
|
111
|
+
if (server?.transport) {
|
|
103
112
|
throw new TypeError("Custom sync fetch is only supported by the browser worker");
|
|
104
113
|
}
|
|
105
114
|
const nativeOpenProgress = openProgress
|
|
@@ -112,6 +121,7 @@ export async function openNativeLixBinding(storage, telemetry, telemetryParent,
|
|
|
112
121
|
}
|
|
113
122
|
}
|
|
114
123
|
: undefined;
|
|
124
|
+
const componentDispatch = createComponentDispatch();
|
|
115
125
|
switch (storage.kind) {
|
|
116
126
|
case "memory": {
|
|
117
127
|
const nativeAddon = loadAddon();
|
|
@@ -119,13 +129,13 @@ export async function openNativeLixBinding(storage, telemetry, telemetryParent,
|
|
|
119
129
|
? (spanJson) => telemetry(JSON.parse(spanJson))
|
|
120
130
|
: undefined;
|
|
121
131
|
if (snapshot) {
|
|
122
|
-
const restore = nativeAddon.Lix.openMemoryFromSnapshot(nativeTelemetry, telemetryParent ? JSON.stringify(telemetryParent) : undefined, nativeOpenProgress);
|
|
132
|
+
const restore = nativeAddon.Lix.openMemoryFromSnapshot(nativeTelemetry, telemetryParent ? JSON.stringify(telemetryParent) : undefined, nativeOpenProgress, componentDispatch, storage.durability);
|
|
123
133
|
return normalizeNativeBinding(await restoreSnapshot(snapshot, restore));
|
|
124
134
|
}
|
|
125
135
|
if (nativeTelemetry) {
|
|
126
|
-
return normalizeNativeBinding(await nativeAddon.Lix.openMemory(nativeTelemetry, telemetryParent ? JSON.stringify(telemetryParent) : undefined, server?.url, server?.headers, nativeOpenProgress));
|
|
136
|
+
return normalizeNativeBinding(await nativeAddon.Lix.openMemory(nativeTelemetry, telemetryParent ? JSON.stringify(telemetryParent) : undefined, server?.url, server?.headers, nativeOpenProgress, componentDispatch, storage.durability));
|
|
127
137
|
}
|
|
128
|
-
return normalizeNativeBinding(await nativeAddon.Lix.openMemory(undefined, undefined, server?.url, server?.headers, nativeOpenProgress));
|
|
138
|
+
return normalizeNativeBinding(await nativeAddon.Lix.openMemory(undefined, undefined, server?.url, server?.headers, nativeOpenProgress, componentDispatch, storage.durability));
|
|
129
139
|
}
|
|
130
140
|
case "jsStorage":
|
|
131
141
|
throw new Error("JavaScript storage providers are only available in browsers");
|
|
@@ -135,13 +145,13 @@ export async function openNativeLixBinding(storage, telemetry, telemetryParent,
|
|
|
135
145
|
? (spanJson) => telemetry(JSON.parse(spanJson))
|
|
136
146
|
: undefined;
|
|
137
147
|
if (snapshot) {
|
|
138
|
-
const restore = nativeAddon.Lix.openFilesystemStorageFromSnapshot(storage.path, storage.syncAllFiles, nativeTelemetry, telemetryParent ? JSON.stringify(telemetryParent) : undefined, nativeOpenProgress);
|
|
148
|
+
const restore = nativeAddon.Lix.openFilesystemStorageFromSnapshot(storage.path, storage.syncAllFiles, nativeTelemetry, telemetryParent ? JSON.stringify(telemetryParent) : undefined, nativeOpenProgress, componentDispatch, storage.durability);
|
|
139
149
|
return normalizeNativeBinding(await restoreSnapshot(snapshot, restore));
|
|
140
150
|
}
|
|
141
151
|
if (nativeTelemetry) {
|
|
142
|
-
return normalizeNativeBinding(await nativeAddon.Lix.openFilesystemStorage(storage.path, storage.syncAllFiles, nativeTelemetry, telemetryParent ? JSON.stringify(telemetryParent) : undefined, server?.url, server?.headers, nativeOpenProgress));
|
|
152
|
+
return normalizeNativeBinding(await nativeAddon.Lix.openFilesystemStorage(storage.path, storage.syncAllFiles, nativeTelemetry, telemetryParent ? JSON.stringify(telemetryParent) : undefined, server?.url, server?.headers, nativeOpenProgress, componentDispatch, storage.durability));
|
|
143
153
|
}
|
|
144
|
-
return normalizeNativeBinding(await nativeAddon.Lix.openFilesystemStorage(storage.path, storage.syncAllFiles, undefined, undefined, server?.url, server?.headers, nativeOpenProgress));
|
|
154
|
+
return normalizeNativeBinding(await nativeAddon.Lix.openFilesystemStorage(storage.path, storage.syncAllFiles, undefined, undefined, server?.url, server?.headers, nativeOpenProgress, componentDispatch, storage.durability));
|
|
145
155
|
}
|
|
146
156
|
}
|
|
147
157
|
}
|
|
@@ -151,3 +161,19 @@ export async function createHostedBinding(server) {
|
|
|
151
161
|
export async function deleteHostedBinding(server) {
|
|
152
162
|
await loadAddon().deleteHosted(server.url, server.headers);
|
|
153
163
|
}
|
|
164
|
+
export async function convertReplicaBinding(storage, server, branchId) {
|
|
165
|
+
if (storage.kind !== "filesystem")
|
|
166
|
+
throw new TypeError("Node conversion requires FilesystemStorage");
|
|
167
|
+
if (server.transport)
|
|
168
|
+
throw new TypeError("Custom sync fetch is only supported in browsers");
|
|
169
|
+
const headers = server.headerProvider ? await server.headerProvider() : server.headers;
|
|
170
|
+
await (await import("./migration-binding.node.js")).loadMigrationAddon().convertFilesystemReplicaToPartial(storage.path, storage.syncAllFiles, server.url, headers, branchId);
|
|
171
|
+
}
|
|
172
|
+
export async function retryReplicaMigrationCleanupBinding(storage, server) {
|
|
173
|
+
if (storage.kind !== "filesystem")
|
|
174
|
+
throw new TypeError("Node migration cleanup requires FilesystemStorage");
|
|
175
|
+
if (server.transport)
|
|
176
|
+
throw new TypeError("Custom sync fetch is only supported in browsers");
|
|
177
|
+
const headers = server.headerProvider ? await server.headerProvider() : server.headers;
|
|
178
|
+
return (await import("./migration-binding.node.js")).loadMigrationAddon().retryFilesystemReplicaMigrationCleanup(storage.path, storage.syncAllFiles, server.url, headers);
|
|
179
|
+
}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type ComponentRequest = {
|
|
2
|
+
operation: string;
|
|
3
|
+
data: string;
|
|
4
|
+
bytes?: Uint8Array;
|
|
5
|
+
host?: {
|
|
6
|
+
call(method: string, argumentsJson: string): string;
|
|
7
|
+
free?(): void;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
export type ComponentDispatch = (request: ComponentRequest) => Promise<string>;
|
|
11
|
+
/** One isolated handle registry per engine runtime, shared by Node and browsers. */
|
|
12
|
+
export declare function createComponentDispatch(): (request: ComponentRequest) => Promise<string>;
|