@lix-js/sdk 0.12.3 → 0.15.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.
Files changed (50) hide show
  1. package/README.md +54 -10
  2. package/dist/binding-types.d.ts +37 -9
  3. package/dist/binding.browser.d.ts +2 -2
  4. package/dist/binding.browser.js +20 -13
  5. package/dist/binding.node-wasm.d.ts +2 -2
  6. package/dist/binding.node-wasm.js +9 -11
  7. package/dist/binding.node.d.ts +3 -3
  8. package/dist/binding.node.js +70 -13
  9. package/dist/bundled-plugins/plugin_csv.lixplugin +0 -0
  10. package/dist/bundled-plugins/plugin_markdown.lixplugin +0 -0
  11. package/dist/index.d.ts +4 -4
  12. package/dist/index.js +2 -2
  13. package/dist/lix.d.ts +27 -5
  14. package/dist/lix.js +125 -6
  15. package/dist/open-lix.d.ts +4 -5
  16. package/dist/open-lix.js +174 -33
  17. package/dist/remote/client.d.ts +1 -2
  18. package/dist/remote/client.js +40 -1151
  19. package/dist/remote/server-protocol.d.ts +5 -6
  20. package/dist/remote/server-protocol.js +40 -6
  21. package/dist/result.d.ts +6 -13
  22. package/dist/result.js +9 -35
  23. package/dist/snapshot-restore.d.ts +6 -0
  24. package/dist/snapshot-restore.js +101 -0
  25. package/dist/storage-adapter.d.ts +175 -19
  26. package/dist/storage-adapter.js +21 -0
  27. package/dist/types.d.ts +104 -34
  28. package/dist/value.d.ts +1 -0
  29. package/dist/value.js +8 -0
  30. package/dist/wasm/lix_js_sdk.d.ts +121 -24
  31. package/dist/wasm/lix_js_sdk.js +606 -78
  32. package/dist/wasm/lix_js_sdk_bg.wasm +0 -0
  33. package/dist/wasm/lix_js_sdk_bg.wasm.d.ts +48 -6
  34. package/dist/wasm-init.d.ts +2 -0
  35. package/dist/wasm-init.js +23 -0
  36. package/dist/worker/client.d.ts +31 -5
  37. package/dist/worker/client.js +541 -45
  38. package/dist/worker/factory.browser.d.ts +2 -2
  39. package/dist/worker/factory.node.d.ts +2 -2
  40. package/dist/worker/factory.node.js +3 -10
  41. package/dist/worker/host.d.ts +4 -2
  42. package/dist/worker/host.js +401 -43
  43. package/dist/worker/protocol.d.ts +107 -3
  44. package/package.json +6 -10
  45. package/dist/indexeddb-backend.d.ts +0 -19
  46. package/dist/indexeddb-backend.js +0 -121
  47. package/dist/remote/sse.d.ts +0 -12
  48. package/dist/remote/sse.js +0 -87
  49. package/dist/workerd.d.ts +0 -25
  50. package/dist/workerd.js +0 -35
package/README.md CHANGED
@@ -18,10 +18,36 @@ import { openLix } from "@lix-js/sdk";
18
18
 
19
19
  const lix = await openLix();
20
20
  const result = await lix.execute("SELECT $1 AS message", ["hello"]);
21
- console.log(result.rows[0]?.get("message"));
21
+ console.log(result.rows[0]?.message);
22
22
  await lix.close();
23
23
  ```
24
24
 
25
+ ## Synchronized local repositories
26
+
27
+ Use sync mode when reads and writes should execute locally while Lix exchanges
28
+ commits with a hosted repository in the background:
29
+
30
+ ```ts
31
+ import { openLix } from "@lix-js/sdk";
32
+ import { OpfsStorage } from "@lix-js/storage-opfs";
33
+
34
+ const lix = await openLix({
35
+ storage: new OpfsStorage({ name: "acme" }),
36
+ server: {
37
+ mode: "sync",
38
+ url: "https://example.com/lix/01936f4e-7b6c-7c3d-8f9a-123456789abc",
39
+ headers: async () => ({
40
+ Authorization: `Bearer ${await accessToken()}`,
41
+ }),
42
+ },
43
+ });
44
+ ```
45
+
46
+ `await lix.execute(...)` means that the local transaction committed. It does
47
+ not mean that the server has received the commit. Current data and new commits
48
+ synchronize automatically; older history and binary content load when needed.
49
+ See [Collaboration and Sync](https://lix.dev/docs/collaboration-and-sync).
50
+
25
51
  ## Remote repositories
26
52
 
27
53
  Use the same Lix client as a thin client against a hosted repository:
@@ -30,7 +56,7 @@ Use the same Lix client as a thin client against a hosted repository:
30
56
  const lix = await openLix({
31
57
  server: {
32
58
  mode: "remote",
33
- url: "https://example.com/repositories/acme",
59
+ url: "https://example.com/lix/01936f4e-7b6c-7c3d-8f9a-123456789abc",
34
60
  headers: async () => ({
35
61
  Authorization: `Bearer ${await accessToken()}`,
36
62
  }),
@@ -59,6 +85,20 @@ Remote server sessions are branch-pinned, so switching one client does not
59
85
  switch another client. Browser-local application state belongs to the
60
86
  application rather than the remote Lix handle.
61
87
 
88
+ Remote handles support branch creation, merge preview and merge through the
89
+ server's Rust engine. `openAnotherSession()` inherits the active branch unless
90
+ one is supplied, retains the authenticated account, and returns an independent
91
+ handle with the same operations—including streaming `exportSnapshot()`. Snapshot
92
+ export covers the complete repository, not only the active branch. Cancelling
93
+ the returned stream releases the HTTP request.
94
+
95
+ Internally, local and connected-sync bindings call `Lix`; remote bindings call
96
+ the Rust protocol client. Both implement the required Rust session operation
97
+ contract, and the WASM bindings share SQL and branch-operation forwarding and
98
+ value conversion. Host-specific storage, telemetry, stream, and actor cleanup
99
+ remain in the bindings. This does not make network availability or authentication
100
+ constraints identical to an offline local engine.
101
+
62
102
  Filesystem sync uses native Node.js dependencies:
63
103
 
64
104
  ```ts
@@ -78,7 +118,7 @@ const result = await lix.execute(
78
118
  "SELECT content FROM lix_file WHERE path = $1",
79
119
  ["/hello.txt"],
80
120
  );
81
- const bytes = result.rows[0]?.value("content").asBytes();
121
+ const bytes = result.rows[0]?.content as Uint8Array | undefined;
82
122
 
83
123
  console.log(bytes && new TextDecoder().decode(bytes));
84
124
 
@@ -143,12 +183,16 @@ try {
143
183
  ## Notes
144
184
 
145
185
  - `openLix()` opens a fresh in-memory Lix. Install `@lix-js/storage-filesystem` and pass `new FilesystemStorage({ path })` for a filesystem repository directory backed by `<path>/.lix/.internal/rocksdb`.
146
- - In browsers, pass `new IndexedDbStorage({ name })` to persist a complete local Lix across reloads.
147
- - Only one Lix handle may open an IndexedDB storage name at a time, including across browser tabs.
186
+ - In browsers, install a storage provider such as `@lix-js/storage-opfs` and pass its
187
+ storage registration to `openLix()`.
188
+ - JavaScript storage packages register a worker-loadable module URL. That module exports
189
+ `createLixStorageProvider(options)` and returns the SDK's Rust-shaped `LixStorageProvider`:
190
+ `beginRead`, `beginWrite`, read/scan handles, write mutation methods, `commit`, and `rollback`.
191
+ The provider module is loaded beside the Lix Wasm engine in its dedicated worker; it does not
192
+ bundle or select a Lix engine version.
148
193
  - Pass `syncAllFiles: false` to start filesystem sync with no regular repository files, then call `storage.importPaths(["notes/today.md"])` on the `FilesystemStorage` instance to sync selected files. Imported paths are exact repository-relative file paths, not directories or globs.
149
- - In browsers, local mode and remote mode with IndexedDB storage load the Rust
150
- engine as WebAssembly. In remote mode, the local engine contains only client
151
- state.
194
+ - Browser-local storage loads the Rust engine as WebAssembly. Remote mode does
195
+ not open a local storage provider.
152
196
  - `FilesystemStorage` is Node.js-only. Constructing it is safe in
153
197
  shared code, but passing one to `openLix()` in a browser throws an error.
154
198
  - The package is ESM-only.
@@ -161,8 +205,8 @@ try {
161
205
  - Every browser `openLix()` owns one dedicated worker, so database work does
162
206
  not block the page's main thread. Node.js uses the native binding's actor.
163
207
  - Node.js executes installed Component API v1 plugins with the Rust SDK's
164
- Wasmtime runtime. The browser and Workerd bindings currently open without a
165
- component runtime: they can use ordinary Lix storage and SQL, but do not
208
+ Wasmtime runtime. The browser binding currently opens without a component
209
+ runtime: it can use ordinary Lix storage and SQL, but does not
166
210
  execute installed plugins. A browser Component host is a separate follow-up.
167
211
  - A page Content Security Policy only needs to permit the package's same-origin
168
212
  worker. WebAssembly compilation happens inside that worker, so the required
@@ -1,10 +1,16 @@
1
- import type { CreateBranchOptions, CreateBranchReceipt, CreateCheckpointReceipt, UndoReceipt, RedoReceipt, ExecuteOptions, LixBatchOptions, MergeBranchOptions, MergeBranchPreview, MergeBranchReceipt, SwitchBranchOptions, SwitchBranchReceipt, LixTelemetrySpan } from "./types.js";
1
+ import type { CreateBranchOptions, CreateBranchReceipt, UndoReceipt, RedoReceipt, ExecuteOptions, LixBatchOptions, MergeBranchOptions, MergeBranchPreview, MergeBranchReceipt, SwitchBranchOptions, SwitchBranchReceipt, LixTelemetrySpan, LixTelemetryParentContext, LixOpenProgress, LixOpenReport, OpenAnotherSessionOptions, ResultColumn } from "./types.js";
2
2
  import type { NativeLixValue } from "./value.js";
3
- import type { LixStorageAdapterConfig } from "./storage-adapter.js";
3
+ import type { LixStorageProvider } from "./storage-adapter.js";
4
+ export type SyncServerBindingOptions = {
5
+ url: string;
6
+ headers: [string, string][];
7
+ headerProvider?: () => Promise<[string, string][]>;
8
+ fetch?: typeof fetch;
9
+ };
4
10
  export type BindingExecuteResult = {
5
11
  statementIndex?: number;
6
12
  label?: string;
7
- columns: string[];
13
+ columns: ResultColumn[];
8
14
  rows: NativeLixValue[][];
9
15
  rowsAffected: number;
10
16
  notices: Array<{
@@ -19,12 +25,25 @@ export type BindingObserveEvent = {
19
25
  rows: BindingExecuteResult;
20
26
  };
21
27
  export type BindingParam = NativeLixValue;
28
+ export type SnapshotExportBinding = {
29
+ next(): Promise<Uint8Array | null | undefined>;
30
+ cancel(): void | Promise<void>;
31
+ };
32
+ export type SnapshotRestoreBinding<T> = {
33
+ write(chunk: Uint8Array): Promise<void>;
34
+ isComplete(): boolean;
35
+ finish(): Promise<T>;
36
+ cancel(): void | Promise<void>;
37
+ };
22
38
  export type BindingBatchStatement = {
23
39
  sql: string;
24
40
  params: BindingParam[];
25
41
  label?: string;
26
42
  };
27
43
  export type LixBinding = {
44
+ openReport?(): LixOpenReport | undefined;
45
+ setTelemetryParent(parent?: TelemetryParentContext): void;
46
+ openAnotherSession(options: OpenAnotherSessionOptions): Promise<LixBinding>;
28
47
  execute(sql: string, params: BindingParam[], options?: ExecuteOptions): Promise<BindingExecuteResult>;
29
48
  executeBatch(statements: BindingBatchStatement[], options?: LixBatchOptions): Promise<BindingExecuteResult[]>;
30
49
  observe(sql: string, params: BindingParam[]): Promise<ObserveEventsBinding>;
@@ -32,7 +51,6 @@ export type LixBinding = {
32
51
  activeBranchId(): Promise<string>;
33
52
  activeAccountId(): Promise<string>;
34
53
  createBranch(options: CreateBranchOptions): Promise<CreateBranchReceipt>;
35
- createCheckpoint(): Promise<CreateCheckpointReceipt>;
36
54
  undo(): Promise<UndoReceipt>;
37
55
  redo(): Promise<RedoReceipt>;
38
56
  switchBranch(options: SwitchBranchOptions): Promise<SwitchBranchReceipt>;
@@ -40,8 +58,7 @@ export type LixBinding = {
40
58
  mergeBranchPreview(options: MergeBranchOptions): Promise<MergeBranchPreview>;
41
59
  mergeBranch(options: MergeBranchOptions): Promise<MergeBranchReceipt>;
42
60
  syncDiskToLix(): Promise<void>;
43
- /** Explicit snapshot utility available on direct in-memory WASM bindings. */
44
- exportSnapshot?(): Promise<Uint8Array>;
61
+ exportSnapshot(): SnapshotExportBinding;
45
62
  close(): Promise<void>;
46
63
  };
47
64
  export type LixTransactionBinding = {
@@ -50,13 +67,24 @@ export type LixTransactionBinding = {
50
67
  rollback(): Promise<void>;
51
68
  };
52
69
  export type ObserveEventsBinding = {
70
+ setTelemetryParent(parent?: TelemetryParentContext): void;
53
71
  next(): Promise<BindingObserveEvent | null | undefined>;
54
72
  close(): void;
55
73
  };
56
74
  export type TelemetryDispatch = (span: LixTelemetrySpan) => void;
75
+ export type OpenProgressDispatch = (progress: LixOpenProgress) => void;
76
+ export type TelemetryParentContext = LixTelemetryParentContext;
77
+ export type LixStorageProviderModule = {
78
+ createLixStorageProvider(options: unknown): Promise<LixStorageProvider>;
79
+ };
57
80
  export type LixStorageConfig = {
58
81
  kind: "memory";
59
82
  } | {
60
- kind: "indexedDb";
61
- name: string;
62
- } | LixStorageAdapterConfig;
83
+ kind: "jsStorage";
84
+ moduleUrl: string;
85
+ options: unknown;
86
+ } | {
87
+ kind: "filesystem";
88
+ path: string;
89
+ syncAllFiles: boolean;
90
+ };
@@ -1,2 +1,2 @@
1
- import type { LixStorageConfig, LixBinding, TelemetryDispatch } from "./binding-types.js";
2
- export declare function openLixBinding(storage: LixStorageConfig, telemetry?: TelemetryDispatch): Promise<LixBinding>;
1
+ import type { LixStorageConfig, LixBinding, SyncServerBindingOptions, TelemetryDispatch, TelemetryParentContext, OpenProgressDispatch } from "./binding-types.js";
2
+ export declare function openLixBinding(storage: LixStorageConfig, telemetry?: TelemetryDispatch, telemetryParent?: TelemetryParentContext, server?: SyncServerBindingOptions, openProgress?: OpenProgressDispatch, snapshot?: ReadableStream<Uint8Array>): Promise<LixBinding>;
@@ -1,23 +1,30 @@
1
- import { IndexedDbBackend } from "./indexeddb-backend.js";
1
+ import { initializeWasm } from "./wasm-init.js";
2
+ import { restoreSnapshot } from "./snapshot-restore.js";
2
3
  // Generated before TypeScript compilation and emitted beside this module.
3
- // @ts-expect-error Generated by build:wasm.
4
- import initWasm, { openIndexedDb, openMemory } from "./wasm/lix_js_sdk.js";
5
- let wasmInitialized;
6
- function initializeWasm() {
7
- return (wasmInitialized ??= initWasm());
8
- }
9
- export async function openLixBinding(storage, telemetry) {
4
+ // @ts-ignore Generated by build:wasm and absent in source-only checks.
5
+ import { openJsStorage, openJsStorageFromSnapshot, openMemory, openMemoryFromSnapshot, } from "./wasm/lix_js_sdk.js";
6
+ export async function openLixBinding(storage, telemetry, telemetryParent, server, openProgress, snapshot) {
10
7
  await initializeWasm();
11
8
  switch (storage.kind) {
12
9
  case "memory":
13
- return openMemory(telemetry);
14
- case "indexedDb": {
15
- const backend = await IndexedDbBackend.open(storage.name);
10
+ return (snapshot
11
+ ? restoreSnapshot(snapshot, openMemoryFromSnapshot(telemetry, telemetryParent, openProgress))
12
+ : openMemory(telemetry, telemetryParent, server, openProgress));
13
+ case "jsStorage": {
14
+ const module = (await import(
15
+ /* @vite-ignore */ storage.moduleUrl));
16
+ if (typeof module.createLixStorageProvider !== "function") {
17
+ throw new TypeError(`Storage provider module '${storage.moduleUrl}' does not export createLixStorageProvider()`);
18
+ }
19
+ const provider = await module.createLixStorageProvider(storage.options);
16
20
  try {
17
- return (await openIndexedDb(backend, telemetry));
21
+ const binding = (await (snapshot
22
+ ? restoreSnapshot(snapshot, openJsStorageFromSnapshot(provider, telemetry, telemetryParent, openProgress))
23
+ : openJsStorage(provider, telemetry, telemetryParent, server, openProgress)));
24
+ return binding;
18
25
  }
19
26
  catch (error) {
20
- await backend.close().catch(() => undefined);
27
+ await provider.close().catch(() => undefined);
21
28
  throw error;
22
29
  }
23
30
  }
@@ -1,2 +1,2 @@
1
- import type { LixBinding, TelemetryDispatch } from "./binding-types.js";
2
- export declare function openMemoryWasmBinding(telemetry?: TelemetryDispatch): Promise<LixBinding>;
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>): Promise<LixBinding>;
@@ -1,14 +1,12 @@
1
- import { readFile } from "node:fs/promises";
1
+ import { restoreSnapshot } from "./snapshot-restore.js";
2
+ import { initializeWasm } from "./wasm-init.js";
2
3
  // Generated before TypeScript compilation and emitted beside this module.
3
- // @ts-expect-error Generated by build:wasm.
4
- import initWasm, { openMemory } from "./wasm/lix_js_sdk.js";
5
- let wasmInitialized;
6
- function initializeWasm() {
7
- return (wasmInitialized ??= initWasm({
8
- module_or_path: readFile(new URL("./wasm/lix_js_sdk_bg.wasm", import.meta.url)),
9
- }));
10
- }
11
- export async function openMemoryWasmBinding(telemetry) {
4
+ // @ts-ignore Generated by build:wasm and absent in source-only checks.
5
+ import { openMemory, openMemoryFromSnapshot } from "./wasm/lix_js_sdk.js";
6
+ export async function openMemoryWasmBinding(telemetry, telemetryParent, openProgress, snapshot) {
12
7
  await initializeWasm();
13
- return openMemory(telemetry);
8
+ if (snapshot) {
9
+ return restoreSnapshot(snapshot, openMemoryFromSnapshot(telemetry, telemetryParent, openProgress));
10
+ }
11
+ return openMemory(telemetry, telemetryParent, undefined, openProgress);
14
12
  }
@@ -1,3 +1,3 @@
1
- import type { LixStorageConfig, LixBinding, TelemetryDispatch } from "./binding-types.js";
2
- export declare function openLixBinding(storage: LixStorageConfig, telemetry?: TelemetryDispatch): Promise<LixBinding>;
3
- export declare function openNativeLixBinding(storage: LixStorageConfig, telemetry?: TelemetryDispatch): Promise<LixBinding>;
1
+ import type { LixStorageConfig, LixBinding, SyncServerBindingOptions, TelemetryDispatch, TelemetryParentContext, OpenProgressDispatch } from "./binding-types.js";
2
+ export declare function openLixBinding(storage: LixStorageConfig, telemetry?: TelemetryDispatch, telemetryParent?: TelemetryParentContext, server?: SyncServerBindingOptions, openProgress?: OpenProgressDispatch, snapshot?: ReadableStream<Uint8Array>): Promise<LixBinding>;
3
+ export declare function openNativeLixBinding(storage: LixStorageConfig, telemetry?: TelemetryDispatch, telemetryParent?: TelemetryParentContext, server?: SyncServerBindingOptions, openProgress?: OpenProgressDispatch, snapshot?: ReadableStream<Uint8Array>): Promise<LixBinding>;
@@ -1,6 +1,32 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { createRequire } from "node:module";
3
3
  import { fileURLToPath } from "node:url";
4
+ import { restoreSnapshot } from "./snapshot-restore.js";
5
+ function normalizeNativeObserveEvents(events) {
6
+ return new Proxy(events, {
7
+ get(target, property, receiver) {
8
+ if (property === "setTelemetryParent") {
9
+ return (parent) => target.setTelemetryParent(parent === undefined ? undefined : JSON.stringify(parent));
10
+ }
11
+ const value = Reflect.get(target, property, receiver);
12
+ return typeof value === "function" ? value.bind(target) : value;
13
+ },
14
+ });
15
+ }
16
+ function normalizeNativeBinding(binding) {
17
+ return new Proxy(binding, {
18
+ get(target, property, receiver) {
19
+ if (property === "setTelemetryParent") {
20
+ return (parent) => target.setTelemetryParent(parent === undefined ? undefined : JSON.stringify(parent));
21
+ }
22
+ if (property === "observe") {
23
+ return async (sql, params) => normalizeNativeObserveEvents(await target.observe(sql, params));
24
+ }
25
+ const value = Reflect.get(target, property, receiver);
26
+ return typeof value === "function" ? value.bind(target) : value;
27
+ },
28
+ });
29
+ }
4
30
  const require = createRequire(import.meta.url);
5
31
  const localNativePath = fileURLToPath(new URL("../lix_js_sdk.node", import.meta.url));
6
32
  const nativePackages = {
@@ -30,6 +56,12 @@ function resolveNativePath() {
30
56
  }
31
57
  let addon;
32
58
  let addonLoadError;
59
+ class NativeAddonUnavailableError extends Error {
60
+ constructor(message, options) {
61
+ super(message, options);
62
+ this.name = "NativeAddonUnavailableError";
63
+ }
64
+ }
33
65
  function loadNativeAddon() {
34
66
  if (addon)
35
67
  return addon;
@@ -40,51 +72,76 @@ function loadNativeAddon() {
40
72
  return addon;
41
73
  }
42
74
  catch (cause) {
43
- const error = new Error(`Failed to load @lix-js/sdk native addon for ${process.platform}-${process.arch}. ` +
75
+ const error = new NativeAddonUnavailableError(`Failed to load @lix-js/sdk native addon for ${process.platform}-${process.arch}. ` +
44
76
  "This package requires the matching optional native binary package. " +
45
77
  "Run `npm run build` from packages/js-sdk for local development, or install a release that includes your platform binary.", { cause });
46
78
  addonLoadError = error;
47
79
  throw error;
48
80
  }
49
81
  }
50
- export async function openLixBinding(storage, telemetry) {
82
+ export async function openLixBinding(storage, telemetry, telemetryParent, server, openProgress, snapshot) {
51
83
  try {
52
- return await openNativeLixBinding(storage, telemetry);
84
+ return await openNativeLixBinding(storage, telemetry, telemetryParent, server, openProgress, snapshot);
53
85
  }
54
86
  catch (nativeError) {
55
- if (storage.kind !== "memory")
87
+ if (!(nativeError instanceof NativeAddonUnavailableError) ||
88
+ storage.kind !== "memory" ||
89
+ server !== undefined) {
56
90
  throw nativeError;
91
+ }
57
92
  try {
58
93
  const { openMemoryWasmBinding } = await import("./binding.node-wasm.js");
59
- return await openMemoryWasmBinding(telemetry);
94
+ return await openMemoryWasmBinding(telemetry, telemetryParent, openProgress, snapshot);
60
95
  }
61
96
  catch (wasmError) {
62
97
  throw new AggregateError([nativeError, wasmError], "Failed to open in-memory Lix with either the native or WebAssembly binding.");
63
98
  }
64
99
  }
65
100
  }
66
- export async function openNativeLixBinding(storage, telemetry) {
101
+ export async function openNativeLixBinding(storage, telemetry, telemetryParent, server, openProgress, snapshot) {
102
+ if (server?.fetch) {
103
+ throw new TypeError("Custom sync fetch is only supported by the browser worker");
104
+ }
105
+ const nativeOpenProgress = openProgress
106
+ ? (progressJson) => {
107
+ try {
108
+ openProgress(JSON.parse(progressJson));
109
+ }
110
+ catch {
111
+ // Open progress is observational and cannot fail repository opening.
112
+ }
113
+ }
114
+ : undefined;
67
115
  switch (storage.kind) {
68
116
  case "memory": {
69
117
  const nativeAddon = loadNativeAddon();
70
118
  const nativeTelemetry = telemetry
71
119
  ? (spanJson) => telemetry(JSON.parse(spanJson))
72
120
  : undefined;
73
- if (nativeTelemetry)
74
- return nativeAddon.Lix.openMemory(nativeTelemetry);
75
- return nativeAddon.Lix.openMemory();
121
+ if (snapshot) {
122
+ const restore = nativeAddon.Lix.openMemoryFromSnapshot(nativeTelemetry, telemetryParent ? JSON.stringify(telemetryParent) : undefined, nativeOpenProgress);
123
+ return normalizeNativeBinding(await restoreSnapshot(snapshot, restore));
124
+ }
125
+ if (nativeTelemetry) {
126
+ return normalizeNativeBinding(await nativeAddon.Lix.openMemory(nativeTelemetry, telemetryParent ? JSON.stringify(telemetryParent) : undefined, server?.url, server?.headers, nativeOpenProgress));
127
+ }
128
+ return normalizeNativeBinding(await nativeAddon.Lix.openMemory(undefined, undefined, server?.url, server?.headers, nativeOpenProgress));
76
129
  }
77
- case "indexedDb":
78
- throw new Error("IndexedDbStorage is only available in browsers");
130
+ case "jsStorage":
131
+ throw new Error("JavaScript storage providers are only available in browsers");
79
132
  case "filesystem": {
80
133
  const nativeAddon = loadNativeAddon();
81
134
  const nativeTelemetry = telemetry
82
135
  ? (spanJson) => telemetry(JSON.parse(spanJson))
83
136
  : undefined;
137
+ if (snapshot) {
138
+ const restore = nativeAddon.Lix.openFilesystemStorageFromSnapshot(storage.path, storage.syncAllFiles, nativeTelemetry, telemetryParent ? JSON.stringify(telemetryParent) : undefined, nativeOpenProgress);
139
+ return normalizeNativeBinding(await restoreSnapshot(snapshot, restore));
140
+ }
84
141
  if (nativeTelemetry) {
85
- return nativeAddon.Lix.openFilesystemStorage(storage.path, storage.syncAllFiles, nativeTelemetry);
142
+ return normalizeNativeBinding(await nativeAddon.Lix.openFilesystemStorage(storage.path, storage.syncAllFiles, nativeTelemetry, telemetryParent ? JSON.stringify(telemetryParent) : undefined, server?.url, server?.headers, nativeOpenProgress));
86
143
  }
87
- return nativeAddon.Lix.openFilesystemStorage(storage.path, storage.syncAllFiles);
144
+ return normalizeNativeBinding(await nativeAddon.Lix.openFilesystemStorage(storage.path, storage.syncAllFiles, undefined, undefined, server?.url, server?.headers, nativeOpenProgress));
88
145
  }
89
146
  }
90
147
  }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { IndexedDbStorage, Lix, LixTransaction, ObserveEvents, openLix, } from "./open-lix.js";
2
- export type { LixStorage, LixStorageAdapterConfig, LixStorageConnection, } from "./storage-adapter.js";
1
+ export { Lix, LixTransaction, ObserveEvents, openLix } from "./open-lix.js";
2
+ export type { LixStorage, LixStorageBound, LixStorageChangeWatch, LixStorageCommitResult, LixStorageErrorCode, LixStorageGetManyRequest, LixStorageKeyRange, LixStoragePrecondition, LixStorageProjectedValue, LixStorageProvider, LixStorageProviderRegistration, LixStoragePutEntry, LixStorageRead, LixStorageReadEntry, LixStorageReadOptions, LixStorageScanOrder, LixStorageScanSource, LixStorageSpace, LixStorageWrite, LixStorageWriteOptions, LixStorageWriteStats, } from "./storage-adapter.js";
3
+ export { LixStorageError } from "./storage-adapter.js";
3
4
  export { bundledPluginArchives, type BundledPluginArchive, } from "./bundled-plugins.js";
4
- export { Row } from "./result.js";
5
5
  export { Value } from "./value.js";
6
- export type { CreateBranchOptions, CreateBranchReceipt, CreateCheckpointReceipt, RedoReceipt, ExecuteOptions, ExecuteResult, LixBatchOptions, LixBatchStatement, IndexedDbStorageOptions, JsonValue, LixValue, MergeBranchOptions, MergeBranchOutcome, MergeBranchPreview, MergeBranchReceipt, MergeChangeStats, MergeConflict, MergeConflictSide, ObserveEvent, OpenLixOptions, LixTelemetryOptions, LixTelemetrySpan, RemoteLixFetch, RemoteLixServerOptions, UndoReceipt, SqlParam, SwitchBranchOptions, SwitchBranchReceipt, } from "./types.js";
6
+ export type { CreateBranchOptions, CreateBranchReceipt, RedoReceipt, ExecuteOptions, ExecuteResult, ExecuteBatchResult, LixBatchOptions, LixBatchStatement, JsonValue, LixValue, ResultArrayRow, ResultColumn, ResultColumnType, ResultObjectRow, ResultRow, MergeBranchOptions, MergeBranchOutcome, MergeBranchPreview, MergeBranchReceipt, MergeChangeStats, MergeConflict, MergeConflictSide, ObserveEvent, OpenLixOptions, OpenAnotherSessionOptions, LixTelemetryOptions, LixTelemetryParentContext, LixTelemetrySpan, LixTelemetrySpanLink, LixOpenMigrationReport, LixOpenPhase, LixOpenProgress, LixOpenProgressOptions, LixOpenReport, RemoteLixFetch, RemoteLixServerOptions, SyncLixServerOptions, UndoReceipt, SqlParam, SwitchBranchOptions, SwitchBranchReceipt, } from "./types.js";
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { IndexedDbStorage, Lix, LixTransaction, ObserveEvents, openLix, } from "./open-lix.js";
1
+ export { Lix, LixTransaction, ObserveEvents, openLix } from "./open-lix.js";
2
+ export { LixStorageError } from "./storage-adapter.js";
2
3
  export { bundledPluginArchives, } from "./bundled-plugins.js";
3
- export { Row } from "./result.js";
4
4
  export { Value } from "./value.js";
package/dist/lix.d.ts CHANGED
@@ -1,12 +1,27 @@
1
1
  import type { LixBinding, LixTransactionBinding, ObserveEventsBinding } from "./binding-types.js";
2
- import type { CreateBranchOptions, CreateBranchReceipt, CreateCheckpointReceipt, RedoReceipt, ExecuteOptions, ExecuteResult, ExecuteBatchResult, LixBatchOptions, LixBatchStatement, MergeBranchOptions, MergeBranchPreview, MergeBranchReceipt, ObserveEvent, SqlParam, SwitchBranchOptions, SwitchBranchReceipt, UndoReceipt } from "./types.js";
2
+ import type { CreateBranchOptions, CreateBranchReceipt, RedoReceipt, ExecuteOptions, ExecuteResult, ExecuteBatchResult, LixBatchOptions, LixBatchStatement, MergeBranchOptions, MergeBranchPreview, MergeBranchReceipt, ObserveEvent, OpenAnotherSessionOptions, LixOpenReport, SqlParam, ResultArrayRow, ResultObjectRow, ResultRow, SwitchBranchOptions, SwitchBranchReceipt, UndoReceipt } from "./types.js";
3
3
  export declare class Lix {
4
4
  #private;
5
5
  private readonly binding;
6
+ readonly openReport: LixOpenReport | undefined;
6
7
  private closePromise;
7
8
  constructor(binding: LixBinding);
8
- execute(sql: string, params?: SqlParam[], options?: ExecuteOptions): Promise<ExecuteResult>;
9
- executeBatch(statements: readonly LixBatchStatement[], options?: LixBatchOptions): Promise<readonly ExecuteBatchResult[]>;
9
+ /** Opens an independent session over the same repository storage. */
10
+ openAnotherSession(options?: OpenAnotherSessionOptions): Promise<Lix>;
11
+ execute(sql: string, params: SqlParam[] | undefined, options: ExecuteOptions & {
12
+ rowMode: "array";
13
+ }): Promise<ExecuteResult<ResultArrayRow>>;
14
+ execute<TRow extends object = ResultObjectRow>(sql: string, params?: SqlParam[], options?: ExecuteOptions & {
15
+ rowMode?: "object";
16
+ }): Promise<ExecuteResult<TRow>>;
17
+ execute(sql: string, params: SqlParam[] | undefined, options?: ExecuteOptions): Promise<ExecuteResult<ResultRow>>;
18
+ executeBatch(statements: readonly LixBatchStatement[], options: LixBatchOptions & {
19
+ rowMode: "array";
20
+ }): Promise<readonly ExecuteBatchResult<ResultArrayRow>[]>;
21
+ executeBatch(statements: readonly LixBatchStatement[], options?: LixBatchOptions & {
22
+ rowMode?: "object";
23
+ }): Promise<readonly ExecuteBatchResult<ResultObjectRow>[]>;
24
+ executeBatch(statements: readonly LixBatchStatement[], options?: LixBatchOptions): Promise<readonly ExecuteBatchResult<ResultRow>[]>;
10
25
  observe(sql: string, params?: SqlParam[]): ObserveEvents;
11
26
  beginTransaction(): Promise<LixTransaction>;
12
27
  activeBranchId(): Promise<string>;
@@ -14,7 +29,8 @@ export declare class Lix {
14
29
  /** Subscribes to successful branch switches made through this Lix handle. */
15
30
  subscribeActiveBranch(listener: () => void): () => void;
16
31
  createBranch(options: CreateBranchOptions): Promise<CreateBranchReceipt>;
17
- createCheckpoint(): Promise<CreateCheckpointReceipt>;
32
+ /** Streams a deterministic snapshot of the complete Lix. */
33
+ exportSnapshot(): ReadableStream<Uint8Array>;
18
34
  undo(): Promise<UndoReceipt>;
19
35
  redo(): Promise<RedoReceipt>;
20
36
  switchBranch(options: SwitchBranchOptions): Promise<SwitchBranchReceipt>;
@@ -37,7 +53,13 @@ export declare class LixTransaction {
37
53
  private finishPromise;
38
54
  private finished;
39
55
  constructor(binding: LixTransactionBinding, onFinish?: () => void);
40
- execute(sql: string, params?: SqlParam[], options?: ExecuteOptions): Promise<ExecuteResult>;
56
+ execute(sql: string, params: SqlParam[] | undefined, options: ExecuteOptions & {
57
+ rowMode: "array";
58
+ }): Promise<ExecuteResult<ResultArrayRow>>;
59
+ execute<TRow extends object = ResultObjectRow>(sql: string, params?: SqlParam[], options?: ExecuteOptions & {
60
+ rowMode?: "object";
61
+ }): Promise<ExecuteResult<TRow>>;
62
+ execute(sql: string, params: SqlParam[] | undefined, options?: ExecuteOptions): Promise<ExecuteResult<ResultRow>>;
41
63
  commit(): Promise<void>;
42
64
  rollback(): Promise<void>;
43
65
  private finish;