@lix-js/sdk 0.10.0 → 0.11.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 CHANGED
@@ -88,7 +88,7 @@ server switch into a rejected operation. Explicit `lix.clientState.set()` and
88
88
  Rust transaction has already committed, `get()` continues to expose that live
89
89
  session value; a later successful snapshot save can make it durable.
90
90
 
91
- Filesystem sync and SQLite persistence use native Node.js dependencies:
91
+ Filesystem sync uses native Node.js dependencies:
92
92
 
93
93
  ```ts
94
94
  import { LocalFilesystem, openLix } from "@lix-js/sdk";
@@ -175,11 +175,10 @@ try {
175
175
  - `openLix()` opens a fresh in-memory Lix. Pass `new LocalFilesystem({ path, syncAllFiles: true })` for a filesystem workspace directory backed by `<path>/.lix/.internal/rocksdb`.
176
176
  - Pass `new LocalFilesystem({ path, lixDir, syncAllFiles: true })` for filesystem sync with repository metadata in an external `.lix` directory and no workspace `.lix` directory.
177
177
  - Pass `syncAllFiles: false` to start filesystem sync with no regular workspace files, then call `storage.importPaths(["notes/today.md"])` on the `LocalFilesystem` instance to sync selected files. Imported paths are exact workspace-relative file paths, not directories or globs.
178
- - Use `new SQLite({ path })` when a single SQLite-backed `.lix` file is the application document itself, for example when defining a new file format and using Lix as the application's file format.
179
178
  - In browsers, local mode and remote mode with client storage load the Rust
180
179
  engine as WebAssembly. Supplying a snapshot storage adapter persists that
181
180
  local Lix; in remote mode, the local engine contains only client state.
182
- - `LocalFilesystem` and `SQLite` are Node.js-only. Constructing them is safe in
181
+ - `LocalFilesystem` is Node.js-only. Constructing it is safe in
183
182
  shared code, but passing one to `openLix()` in a browser throws an error.
184
183
  - The package is ESM-only.
185
184
  - The package uses conditional ESM imports internally: Node.js resolves the
@@ -1,6 +1,8 @@
1
1
  import type { CreateBranchOptions, CreateBranchReceipt, CreateCheckpointReceipt, UndoReceipt, RedoReceipt, ExecuteOptions, LixBatchOptions, MergeBranchOptions, MergeBranchPreview, MergeBranchReceipt, SwitchBranchOptions, SwitchBranchReceipt, LixTelemetrySpan, JsonValue } from "./types.js";
2
2
  import type { NativeLixValue } from "./value.js";
3
3
  export type BindingExecuteResult = {
4
+ statementIndex?: number;
5
+ label?: string;
4
6
  columns: string[];
5
7
  rows: NativeLixValue[][];
6
8
  rowsAffected: number;
@@ -19,6 +21,7 @@ export type BindingParam = NativeLixValue;
19
21
  export type BindingBatchStatement = {
20
22
  sql: string;
21
23
  params: BindingParam[];
24
+ label?: string;
22
25
  };
23
26
  export type LixBinding = {
24
27
  execute(sql: string, params: BindingParam[], options?: ExecuteOptions): Promise<BindingExecuteResult>;
@@ -60,9 +63,6 @@ export type TelemetryDispatch = (span: LixTelemetrySpan) => void;
60
63
  export type LixStorageConfig = {
61
64
  kind: "memory";
62
65
  snapshot?: Uint8Array;
63
- } | {
64
- kind: "sqlite";
65
- path: string;
66
66
  } | {
67
67
  kind: "localFilesystem";
68
68
  path: string;
@@ -7,7 +7,7 @@ function initializeWasm() {
7
7
  }
8
8
  export async function openLixBinding(storage, telemetry) {
9
9
  if (storage.kind !== "memory") {
10
- throw new Error(`${storage.kind === "localFilesystem" ? "LocalFilesystem" : "SQLite"} is only available in Node.js`);
10
+ throw new Error("LocalFilesystem is only available in Node.js");
11
11
  }
12
12
  await initializeWasm();
13
13
  return openMemoryFromSnapshot(telemetry, storage.snapshot);
@@ -51,11 +51,6 @@ export function openLixBinding(storage, telemetry) {
51
51
  if (nativeTelemetry)
52
52
  return addon.Lix.openMemory(nativeTelemetry);
53
53
  return addon.Lix.openMemory();
54
- case "sqlite":
55
- if (nativeTelemetry) {
56
- return addon.Lix.openSQLite(storage.path, nativeTelemetry);
57
- }
58
- return addon.Lix.openSQLite(storage.path);
59
54
  case "localFilesystem":
60
55
  if (nativeTelemetry) {
61
56
  return addon.Lix.openLocalFilesystem(storage.path, storage.lixDir, storage.syncAllFiles, nativeTelemetry);
@@ -271,14 +271,11 @@ function decodeStoredClientState(snapshot) {
271
271
  const header = new TextEncoder().encode(STORED_CLIENT_STATE_HEADER);
272
272
  if (snapshot.length < header.length ||
273
273
  header.some((byte, index) => snapshot[index] !== byte)) {
274
- // Remote storage previously contained a full Lix snapshot. Backward
275
- // compatibility is intentionally not provided: start with empty state and
276
- // replace it on the next write.
277
- return new Map();
274
+ throw new Error("Stored Lix client state header is invalid");
278
275
  }
279
276
  let parsed;
280
277
  try {
281
- parsed = JSON.parse(new TextDecoder().decode(snapshot.subarray(header.length)));
278
+ parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(snapshot.subarray(header.length)));
282
279
  }
283
280
  catch (error) {
284
281
  throw new Error("Stored Lix client state is invalid", { cause: error });
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { LocalFilesystem, Lix, LixTransaction, ObserveEvents, openLix, SQLite, } from "./open-lix.js";
1
+ export { LocalFilesystem, Lix, LixTransaction, ObserveEvents, openLix, } from "./open-lix.js";
2
2
  export { bundledPluginArchives, type BundledPluginArchive, } from "./bundled-plugins.js";
3
3
  export { Row } from "./result.js";
4
4
  export { Value } from "./value.js";
5
5
  export type { LixClientState } from "./client-state.js";
6
- export type { CreateBranchOptions, CreateBranchReceipt, CreateCheckpointReceipt, RedoReceipt, ExecuteOptions, ExecuteResult, LixBatchOptions, LixBatchStatement, LocalFilesystemOptions, JsonValue, LixValue, MergeBranchOptions, MergeBranchOutcome, MergeBranchPreview, MergeBranchReceipt, MergeChangeStats, MergeConflict, MergeConflictSide, ObserveEvent, OpenLixOptions, LixTelemetryOptions, LixTelemetrySpan, LixSnapshotStorage, RemoteLixFetch, RemoteLixServerOptions, UndoReceipt, SqlParam, SQLiteOptions, SwitchBranchOptions, SwitchBranchReceipt, } from "./types.js";
6
+ export type { CreateBranchOptions, CreateBranchReceipt, CreateCheckpointReceipt, RedoReceipt, ExecuteOptions, ExecuteResult, LixBatchOptions, LixBatchStatement, LocalFilesystemOptions, JsonValue, LixValue, MergeBranchOptions, MergeBranchOutcome, MergeBranchPreview, MergeBranchReceipt, MergeChangeStats, MergeConflict, MergeConflictSide, ObserveEvent, OpenLixOptions, LixTelemetryOptions, LixTelemetrySpan, LixSnapshotStorage, RemoteLixFetch, RemoteLixServerOptions, UndoReceipt, SqlParam, SwitchBranchOptions, SwitchBranchReceipt, } from "./types.js";
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { LocalFilesystem, Lix, LixTransaction, ObserveEvents, openLix, SQLite, } from "./open-lix.js";
1
+ export { LocalFilesystem, Lix, LixTransaction, ObserveEvents, openLix, } from "./open-lix.js";
2
2
  export { bundledPluginArchives, } from "./bundled-plugins.js";
3
3
  export { Row } from "./result.js";
4
4
  export { Value } from "./value.js";
package/dist/lix.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { type LixClientState, type ManagedClientState } from "./client-state.js";
2
2
  import type { LixBinding, LixTransactionBinding, ObserveEventsBinding } from "./binding-types.js";
3
- import type { CreateBranchOptions, CreateBranchReceipt, CreateCheckpointReceipt, RedoReceipt, ExecuteOptions, ExecuteResult, LixBatchOptions, LixBatchStatement, MergeBranchOptions, MergeBranchPreview, MergeBranchReceipt, ObserveEvent, SqlParam, SwitchBranchOptions, SwitchBranchReceipt, UndoReceipt } from "./types.js";
3
+ import type { CreateBranchOptions, CreateBranchReceipt, CreateCheckpointReceipt, RedoReceipt, ExecuteOptions, ExecuteResult, ExecuteBatchResult, LixBatchOptions, LixBatchStatement, MergeBranchOptions, MergeBranchPreview, MergeBranchReceipt, ObserveEvent, SqlParam, SwitchBranchOptions, SwitchBranchReceipt, UndoReceipt } from "./types.js";
4
4
  export declare class Lix {
5
5
  #private;
6
6
  private readonly binding;
@@ -9,7 +9,7 @@ export declare class Lix {
9
9
  readonly clientState: LixClientState;
10
10
  constructor(binding: LixBinding, managedClientState?: ManagedClientState | undefined);
11
11
  execute(sql: string, params?: SqlParam[], options?: ExecuteOptions): Promise<ExecuteResult>;
12
- executeBatch(statements: readonly LixBatchStatement[], options?: LixBatchOptions): Promise<readonly ExecuteResult[]>;
12
+ executeBatch(statements: readonly LixBatchStatement[], options?: LixBatchOptions): Promise<readonly ExecuteBatchResult[]>;
13
13
  observe(sql: string, params?: SqlParam[]): ObserveEvents;
14
14
  beginTransaction(): Promise<LixTransaction>;
15
15
  activeBranchId(): Promise<string>;
package/dist/lix.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { invalidArgument } from "./errors.js";
2
2
  import { ACTIVE_BRANCH_CLIENT_STATE_KEY, unavailableClientState, } from "./client-state.js";
3
- import { normalizeOptionals, wrapExecuteResult } from "./result.js";
3
+ import { normalizeOptionals, wrapExecuteBatchResult, wrapExecuteResult, } from "./result.js";
4
4
  import { isSnapshotPersistenceAfterCommitError } from "./snapshot-persistence.js";
5
5
  import { normalizeParam, toNativeValue } from "./value.js";
6
6
  const transactionFinalizer = new FinalizationRegistry(({ transaction, onFinish }) => {
@@ -50,7 +50,7 @@ export class Lix {
50
50
  const normalizedStatements = normalizeBatchStatements(statements, options);
51
51
  return this.#runOperation(async () => {
52
52
  const results = await this.binding.executeBatch(normalizedStatements, options);
53
- return results.map(wrapExecuteResult);
53
+ return results.map(wrapExecuteBatchResult);
54
54
  });
55
55
  }
56
56
  observe(sql, params = []) {
@@ -336,9 +336,14 @@ function normalizeBatchStatements(statements, options) {
336
336
  if (!Array.isArray(params)) {
337
337
  throw invalidArgument("executeBatch", `statements[${statementIndex}].params`, "array", typeof params);
338
338
  }
339
+ if (statement.label !== undefined &&
340
+ typeof statement.label !== "string") {
341
+ throw invalidArgument("executeBatch", `statements[${statementIndex}].label`, "string", typeof statement.label);
342
+ }
339
343
  return {
340
344
  sql: statement.sql,
341
345
  params: params.map((param, parameterIndex) => toNativeValue(normalizeParam(param, parameterIndex))),
346
+ ...(statement.label === undefined ? {} : { label: statement.label }),
342
347
  };
343
348
  }
344
349
  catch (error) {
@@ -1,10 +1,6 @@
1
1
  import { Lix } from "./lix.js";
2
- import type { LocalFilesystemOptions, OpenLixOptions, SQLiteOptions } from "./types.js";
2
+ import type { LocalFilesystemOptions, OpenLixOptions } from "./types.js";
3
3
  export { Lix, LixTransaction, ObserveEvents } from "./lix.js";
4
- export declare class SQLite {
5
- readonly path: string;
6
- constructor(options: SQLiteOptions);
7
- }
8
4
  export declare class LocalFilesystem {
9
5
  readonly path: string;
10
6
  readonly lixDir: string | undefined;
package/dist/open-lix.js CHANGED
@@ -2,17 +2,6 @@ import { localFilesystemAlreadyOpen, localFilesystemNotOpen, } from "./errors.js
2
2
  import { ACTIVE_ACCOUNT_CLIENT_STATE_KEY, ACTIVE_BRANCH_CLIENT_STATE_KEY, openClientState, openStoredClientState, } from "./client-state.js";
3
3
  import { Lix } from "./lix.js";
4
4
  export { Lix, LixTransaction, ObserveEvents } from "./lix.js";
5
- export class SQLite {
6
- path;
7
- constructor(options) {
8
- if (!options ||
9
- typeof options.path !== "string" ||
10
- options.path.length === 0) {
11
- throw new TypeError("SQLite requires a non-empty path");
12
- }
13
- this.path = options.path;
14
- }
15
- }
16
5
  const openLocalFilesystems = new WeakMap();
17
6
  export class LocalFilesystem {
18
7
  path;
@@ -119,12 +108,6 @@ export async function openLix(options = {}) {
119
108
  if (options.storage === undefined) {
120
109
  return new Lix(await openLixWorkerBinding({ kind: "memory" }, undefined, options.telemetry));
121
110
  }
122
- if (options.storage instanceof SQLite) {
123
- return new Lix(await openLixWorkerBinding({
124
- kind: "sqlite",
125
- path: options.storage.path,
126
- }, undefined, options.telemetry));
127
- }
128
111
  if (options.storage instanceof LocalFilesystem) {
129
112
  const storage = options.storage;
130
113
  if (openLocalFilesystems.has(storage)) {
@@ -162,7 +145,7 @@ export async function openLix(options = {}) {
162
145
  throw error;
163
146
  }
164
147
  }
165
- throw new TypeError("openLix() requires storage to be SQLite, LocalFilesystem, or a Lix snapshot storage adapter");
148
+ throw new TypeError("openLix() requires storage to be LocalFilesystem or a Lix snapshot storage adapter");
166
149
  }
167
150
  function isSnapshotStorage(value) {
168
151
  return (typeof value === "object" &&
@@ -1,4 +1,4 @@
1
- import { decodeExecuteResult, decodeHandshake, decodeObserveEvent, encodeWireValue, errorFromResponseBody, protocolError, record, REMOTE_PROTOCOL_PATH, remoteError, } from "./protocol.js";
1
+ import { decodeExecuteBatchResult, decodeExecuteResult, decodeHandshake, decodeObserveEvent, encodeWireValue, errorFromResponseBody, protocolError, record, REMOTE_PROTOCOL_PATH, remoteError, } from "./protocol.js";
2
2
  import { readSseEvents } from "./sse.js";
3
3
  const OBSERVE_RETRY_BASE_MS = 100;
4
4
  const OBSERVE_RETRY_MAX_MS = 5_000;
@@ -73,6 +73,7 @@ class RemoteLixBinding {
73
73
  this.#initialActiveAccountId = clientOptions.initialActiveAccountId;
74
74
  this.#observationHub = new RemoteObservationHub({
75
75
  openStream: (subscriptions, signal) => this.#requestObserveStream(subscriptions, signal),
76
+ refreshObservation: (subscription) => this.#refreshObservation(subscription),
76
77
  });
77
78
  }
78
79
  async open() {
@@ -119,10 +120,12 @@ class RemoteLixBinding {
119
120
  const snapshot = statements.map((statement) => ({
120
121
  sql: statement.sql,
121
122
  params: snapshotParams(statement.params),
123
+ ...(statement.label === undefined ? {} : { label: statement.label }),
122
124
  }));
123
125
  return this.#enqueue(async () => {
124
126
  const preparedStatements = await Promise.all(snapshot.map(async (statement, statementIndex) => ({
125
127
  sql: statement.sql,
128
+ label: statement.label,
126
129
  prepared: await this.#prepareParams(statement.params, (paramIndex) => requestBlobSlot("batch", statement.sql, paramIndex, statementIndex)),
127
130
  })));
128
131
  const cacheBlobs = preparedStatements.some((statement) => statement.prepared.cacheBlobs);
@@ -133,6 +136,9 @@ class RemoteLixBinding {
133
136
  body: JSON.stringify({
134
137
  statements: preparedStatements.map((statement) => ({
135
138
  sql: statement.sql,
139
+ ...(statement.label === undefined
140
+ ? {}
141
+ : { label: statement.label }),
136
142
  params: full
137
143
  ? statement.prepared.fullParams()
138
144
  : statement.prepared.params,
@@ -145,7 +151,7 @@ class RemoteLixBinding {
145
151
  if (!Array.isArray(value)) {
146
152
  throw protocolError("execute batch response must be an array");
147
153
  }
148
- const results = value.map(decodeExecuteResult);
154
+ const results = value.map(decodeExecuteBatchResult);
149
155
  this.#commitRequestBlobBases(preparedStatements.flatMap((statement) => statement.prepared.cacheUpdates));
150
156
  return results;
151
157
  });
@@ -442,6 +448,18 @@ class RemoteLixBinding {
442
448
  throw remoteError("LIX_REMOTE_UNAVAILABLE", "The remote Lix observation stream is unavailable", { details: { cause: errorMessage(cause) } });
443
449
  }
444
450
  }
451
+ async #refreshObservation(subscription) {
452
+ return this.#enqueue(async () => {
453
+ const value = await this.#requestJson("execute", {
454
+ method: "POST",
455
+ body: JSON.stringify({
456
+ sql: subscription.sql,
457
+ params: subscription.params,
458
+ }),
459
+ });
460
+ return decodeExecuteResult(value);
461
+ });
462
+ }
445
463
  async #prepareParams(params, slot) {
446
464
  const prepared = await Promise.all(params.map(async (param, index) => {
447
465
  if (param.kind !== "blob" ||
@@ -661,6 +679,7 @@ function copyArrayBuffer(bytes) {
661
679
  }
662
680
  class RemoteObservationHub {
663
681
  #openStream;
682
+ #refreshObservation;
664
683
  #observations = new Map();
665
684
  #nextObservationId = 0;
666
685
  #controller;
@@ -672,6 +691,7 @@ class RemoteObservationHub {
672
691
  #closed = false;
673
692
  constructor(options) {
674
693
  this.#openStream = options.openStream;
694
+ this.#refreshObservation = options.refreshObservation;
675
695
  }
676
696
  observe(sql, params) {
677
697
  const id = `observe-${++this.#nextObservationId}`;
@@ -743,6 +763,7 @@ class RemoteObservationHub {
743
763
  if (!this.#isCurrent(generation, controller))
744
764
  return;
745
765
  streamOpened = true;
766
+ const initialSubscriptions = new Set(this.#observations.keys());
746
767
  if (!response.ok) {
747
768
  if (isRetryableObserveStatus(response.status)) {
748
769
  void response.body?.cancel();
@@ -781,7 +802,21 @@ class RemoteObservationHub {
781
802
  const transportDelta = payload.delta !== undefined;
782
803
  const event = decodeObserveEvent(payload, transportBases.get(subscriptionId));
783
804
  transportBases.set(subscriptionId, event);
784
- observation.accept(event, transportDelta);
805
+ if (initialSubscriptions.delete(subscriptionId)) {
806
+ // The first frame after opening (including a reconnect) is a
807
+ // synchronization point, not an authoritative snapshot. The
808
+ // remote runtime may have observed the stream before its
809
+ // external-storage watcher caught up. Reconcile through the
810
+ // normal execute endpoint before publishing it to consumers.
811
+ const rows = await this.#refreshObservation(observation.request());
812
+ observation.accept({
813
+ ...event,
814
+ rows,
815
+ }, false);
816
+ }
817
+ else {
818
+ observation.accept(event, transportDelta);
819
+ }
785
820
  this.#retryAttempt = 0;
786
821
  }
787
822
  catch (error) {
@@ -55,6 +55,7 @@ export type RemoteExecuteBatchRequest = {
55
55
  statements: Array<{
56
56
  sql: string;
57
57
  params: WireRequestValue[];
58
+ label?: string;
58
59
  }>;
59
60
  options?: {
60
61
  originKey?: string;
@@ -71,6 +72,10 @@ export type RemoteExecuteResponse = {
71
72
  hint?: string;
72
73
  }>;
73
74
  };
75
+ export type RemoteExecuteBatchResponse = RemoteExecuteResponse & {
76
+ statementIndex: number;
77
+ label?: string;
78
+ };
74
79
  export type RemoteObserveRequest = {
75
80
  sql: string;
76
81
  params: WireValue[];
@@ -156,6 +161,7 @@ export type RemoteMultiplexObserveErrorEvent = RemoteObserveErrorEvent & {
156
161
  };
157
162
  export declare function encodeWireValue(value: NativeLixValue): WireValue;
158
163
  export declare function decodeExecuteResult(value: unknown): BindingExecuteResult;
164
+ export declare function decodeExecuteBatchResult(value: unknown): BindingExecuteResult;
159
165
  export declare function decodeHandshake(value: unknown): RemoteHandshake;
160
166
  export declare function decodeObserveEvent(value: unknown, base?: BindingObserveEvent): BindingObserveEvent;
161
167
  export declare function remoteError(code: string, message: string, options?: {
@@ -57,6 +57,18 @@ export function decodeExecuteResult(value) {
57
57
  });
58
58
  return { columns, rows, rowsAffected: result.rowsAffected, notices };
59
59
  }
60
+ export function decodeExecuteBatchResult(value) {
61
+ const result = record(value, "execute batch result");
62
+ const statementIndex = nonNegativeSafeInteger(result.statementIndex, "execute batch result statementIndex");
63
+ if (result.label !== undefined && typeof result.label !== "string") {
64
+ throw protocolError("execute batch result label must be a string when present");
65
+ }
66
+ return {
67
+ ...decodeExecuteResult(value),
68
+ statementIndex,
69
+ ...(result.label === undefined ? {} : { label: result.label }),
70
+ };
71
+ }
60
72
  export function decodeHandshake(value) {
61
73
  const handshake = record(value, "remote handshake");
62
74
  if (handshake.protocolVersion !== REMOTE_PROTOCOL_VERSION) {
package/dist/result.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type NativeLixValue, Value } from "./value.js";
2
- import type { ExecuteResult, LixValue } from "./types.js";
2
+ import type { ExecuteBatchResult, ExecuteResult, LixValue } from "./types.js";
3
3
  export declare class Row {
4
4
  private readonly columns;
5
5
  private readonly values;
@@ -14,5 +14,6 @@ type NativeExecuteResult = Omit<ExecuteResult, "rows"> & {
14
14
  rows: NativeLixValue[][];
15
15
  };
16
16
  export declare function wrapExecuteResult(result: NativeExecuteResult): ExecuteResult;
17
+ export declare function wrapExecuteBatchResult(result: NativeExecuteResult): ExecuteBatchResult;
17
18
  export declare function normalizeOptionals<T>(value: T): T;
18
19
  export {};
package/dist/result.js CHANGED
@@ -36,6 +36,18 @@ export function wrapExecuteResult(result) {
36
36
  rows: result.rows.map((row) => Row.fromRaw(result.columns, row.map(fromNativeValue))),
37
37
  };
38
38
  }
39
+ export function wrapExecuteBatchResult(result) {
40
+ const statementIndex = result.statementIndex;
41
+ if (typeof statementIndex !== "number" ||
42
+ !Number.isSafeInteger(statementIndex) ||
43
+ statementIndex < 0) {
44
+ throw new Error("executeBatch result is missing a valid statementIndex");
45
+ }
46
+ return {
47
+ ...wrapExecuteResult(result),
48
+ statementIndex,
49
+ };
50
+ }
39
51
  export function normalizeOptionals(value) {
40
52
  if (Array.isArray(value))
41
53
  return value.map(normalizeOptionals);
package/dist/types.d.ts CHANGED
@@ -1,6 +1,3 @@
1
- export type SQLiteOptions = {
2
- path: string;
3
- };
4
1
  export type LocalFilesystemOptions = {
5
2
  path: string;
6
3
  lixDir?: string;
@@ -36,7 +33,7 @@ export interface LixSnapshotStorage {
36
33
  save(namespace: string, snapshot: Uint8Array): Promise<void>;
37
34
  }
38
35
  export type OpenLixOptions = {
39
- storage?: import("./open-lix.js").SQLite | import("./open-lix.js").LocalFilesystem | LixSnapshotStorage;
36
+ storage?: import("./open-lix.js").LocalFilesystem | LixSnapshotStorage;
40
37
  server?: never;
41
38
  telemetry?: LixTelemetryOptions;
42
39
  } | {
@@ -86,6 +83,7 @@ export type ExecuteOptions = {
86
83
  export type LixBatchStatement = {
87
84
  sql: string;
88
85
  params?: readonly SqlParam[];
86
+ label?: string;
89
87
  };
90
88
  export type LixBatchOptions = {
91
89
  originKey?: string;
@@ -93,6 +91,8 @@ export type LixBatchOptions = {
93
91
  idempotencyKey?: string;
94
92
  };
95
93
  export type ExecuteResult = {
94
+ statementIndex?: number;
95
+ label?: string;
96
96
  columns: string[];
97
97
  rows: RowLike[];
98
98
  rowsAffected: number;
@@ -102,9 +102,17 @@ export type ExecuteResult = {
102
102
  hint?: string;
103
103
  }>;
104
104
  };
105
+ export type ExecuteBatchResult = ExecuteResult & {
106
+ statementIndex: number;
107
+ };
105
108
  export type ObserveEvent = {
106
109
  sequence: number;
107
110
  mutationSequence: number;
111
+ /**
112
+ * The current result of the observed query. Remote observations reconcile
113
+ * the first frame of every stream through execute before publishing it, so
114
+ * reconnects cannot expose a stale server snapshot to consumers.
115
+ */
108
116
  result: ExecuteResult;
109
117
  };
110
118
  export type RowLike = {
@@ -83,8 +83,8 @@ export interface InitOutput {
83
83
  readonly wasmlixtransaction_rollback: (a: number) => number;
84
84
  readonly wasmobserveevents_close: (a: number) => void;
85
85
  readonly wasmobserveevents_next: (a: number) => number;
86
- readonly __wasm_bindgen_func_elem_120695: (a: number, b: number, c: number, d: number) => void;
87
- readonly __wasm_bindgen_func_elem_120697: (a: number, b: number, c: number, d: number) => void;
86
+ readonly __wasm_bindgen_func_elem_122229: (a: number, b: number, c: number, d: number) => void;
87
+ readonly __wasm_bindgen_func_elem_122231: (a: number, b: number, c: number, d: number) => void;
88
88
  readonly __wbindgen_export: (a: number, b: number) => number;
89
89
  readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
90
90
  readonly __wbindgen_export3: (a: number) => void;
@@ -536,7 +536,7 @@ function __wbg_get_imports() {
536
536
  const a = state0.a;
537
537
  state0.a = 0;
538
538
  try {
539
- return __wasm_bindgen_func_elem_120697(a, state0.b, arg0, arg1);
539
+ return __wasm_bindgen_func_elem_122231(a, state0.b, arg0, arg1);
540
540
  } finally {
541
541
  state0.a = a;
542
542
  }
@@ -646,8 +646,8 @@ function __wbg_get_imports() {
646
646
  return addHeapObject(ret);
647
647
  },
648
648
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
649
- // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 30501, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
650
- const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_120695);
649
+ // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 30525, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
650
+ const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_122229);
651
651
  return addHeapObject(ret);
652
652
  },
653
653
  __wbindgen_cast_0000000000000002: function(arg0) {
@@ -696,10 +696,10 @@ function __wbg_get_imports() {
696
696
  };
697
697
  }
698
698
 
699
- function __wasm_bindgen_func_elem_120695(arg0, arg1, arg2) {
699
+ function __wasm_bindgen_func_elem_122229(arg0, arg1, arg2) {
700
700
  try {
701
701
  const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
702
- wasm.__wasm_bindgen_func_elem_120695(retptr, arg0, arg1, addHeapObject(arg2));
702
+ wasm.__wasm_bindgen_func_elem_122229(retptr, arg0, arg1, addHeapObject(arg2));
703
703
  var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
704
704
  var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
705
705
  if (r1) {
@@ -710,8 +710,8 @@ function __wasm_bindgen_func_elem_120695(arg0, arg1, arg2) {
710
710
  }
711
711
  }
712
712
 
713
- function __wasm_bindgen_func_elem_120697(arg0, arg1, arg2, arg3) {
714
- wasm.__wasm_bindgen_func_elem_120697(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
713
+ function __wasm_bindgen_func_elem_122231(arg0, arg1, arg2, arg3) {
714
+ wasm.__wasm_bindgen_func_elem_122231(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
715
715
  }
716
716
 
717
717
  const WasmLixFinalization = (typeof FinalizationRegistry === 'undefined')
Binary file
@@ -31,8 +31,8 @@ export const wasmlixtransaction_execute: (a: number, b: number, c: number, d: nu
31
31
  export const wasmlixtransaction_rollback: (a: number) => number;
32
32
  export const wasmobserveevents_close: (a: number) => void;
33
33
  export const wasmobserveevents_next: (a: number) => number;
34
- export const __wasm_bindgen_func_elem_120695: (a: number, b: number, c: number, d: number) => void;
35
- export const __wasm_bindgen_func_elem_120697: (a: number, b: number, c: number, d: number) => void;
34
+ export const __wasm_bindgen_func_elem_122229: (a: number, b: number, c: number, d: number) => void;
35
+ export const __wasm_bindgen_func_elem_122231: (a: number, b: number, c: number, d: number) => void;
36
36
  export const __wbindgen_export: (a: number, b: number) => number;
37
37
  export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
38
38
  export const __wbindgen_export3: (a: number) => void;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lix-js/sdk",
3
3
  "type": "module",
4
- "version": "0.10.0",
4
+ "version": "0.11.0",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -57,10 +57,10 @@
57
57
  "typecheck": "tsc -p tsconfig.test.json --noEmit"
58
58
  },
59
59
  "optionalDependencies": {
60
- "@lix-js/sdk-darwin-arm64": "0.10.0",
61
- "@lix-js/sdk-linux-arm64": "0.10.0",
62
- "@lix-js/sdk-linux-x64": "0.10.0",
63
- "@lix-js/sdk-win32-x64": "0.10.0"
60
+ "@lix-js/sdk-darwin-arm64": "0.11.0",
61
+ "@lix-js/sdk-linux-arm64": "0.11.0",
62
+ "@lix-js/sdk-linux-x64": "0.11.0",
63
+ "@lix-js/sdk-win32-x64": "0.11.0"
64
64
  },
65
65
  "devDependencies": {
66
66
  "@vitest/browser-playwright": "4.1.10",