@lix-js/sdk 0.12.1 → 0.12.3

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
@@ -155,6 +155,9 @@ try {
155
155
  - The package uses conditional ESM imports internally: Node.js resolves the
156
156
  native N-API binding, while browsers and other runtimes resolve the portable
157
157
  WebAssembly binding. Vite follows this split without consumer configuration.
158
+ - If the native addon cannot load in Node.js, in-memory Lix instances fall back
159
+ to the bundled WebAssembly engine. Filesystem storage and Component API v1
160
+ plugin execution still require the native addon.
158
161
  - Every browser `openLix()` owns one dedicated worker, so database work does
159
162
  not block the page's main thread. Node.js uses the native binding's actor.
160
163
  - Node.js executes installed Component API v1 plugins with the Rust SDK's
@@ -0,0 +1,2 @@
1
+ import type { LixBinding, TelemetryDispatch } from "./binding-types.js";
2
+ export declare function openMemoryWasmBinding(telemetry?: TelemetryDispatch): Promise<LixBinding>;
@@ -0,0 +1,14 @@
1
+ import { readFile } from "node:fs/promises";
2
+ // 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) {
12
+ await initializeWasm();
13
+ return openMemory(telemetry);
14
+ }
@@ -1,2 +1,3 @@
1
1
  import type { LixStorageConfig, LixBinding, TelemetryDispatch } from "./binding-types.js";
2
2
  export declare function openLixBinding(storage: LixStorageConfig, telemetry?: TelemetryDispatch): Promise<LixBinding>;
3
+ export declare function openNativeLixBinding(storage: LixStorageConfig, telemetry?: TelemetryDispatch): Promise<LixBinding>;
@@ -29,31 +29,62 @@ function resolveNativePath() {
29
29
  throw packageResolutionError;
30
30
  }
31
31
  let addon;
32
- try {
33
- addon = require(resolveNativePath());
32
+ let addonLoadError;
33
+ function loadNativeAddon() {
34
+ if (addon)
35
+ return addon;
36
+ if (addonLoadError)
37
+ throw addonLoadError;
38
+ try {
39
+ addon = require(resolveNativePath());
40
+ return addon;
41
+ }
42
+ catch (cause) {
43
+ const error = new Error(`Failed to load @lix-js/sdk native addon for ${process.platform}-${process.arch}. ` +
44
+ "This package requires the matching optional native binary package. " +
45
+ "Run `npm run build` from packages/js-sdk for local development, or install a release that includes your platform binary.", { cause });
46
+ addonLoadError = error;
47
+ throw error;
48
+ }
34
49
  }
35
- catch (cause) {
36
- const error = new Error(`Failed to load @lix-js/sdk native addon for ${process.platform}-${process.arch}. ` +
37
- "This package requires the matching optional native binary package. " +
38
- "Run `npm run build` from packages/js-sdk for local development, or install a release that includes your platform binary.");
39
- error.cause = cause;
40
- throw error;
50
+ export async function openLixBinding(storage, telemetry) {
51
+ try {
52
+ return await openNativeLixBinding(storage, telemetry);
53
+ }
54
+ catch (nativeError) {
55
+ if (storage.kind !== "memory")
56
+ throw nativeError;
57
+ try {
58
+ const { openMemoryWasmBinding } = await import("./binding.node-wasm.js");
59
+ return await openMemoryWasmBinding(telemetry);
60
+ }
61
+ catch (wasmError) {
62
+ throw new AggregateError([nativeError, wasmError], "Failed to open in-memory Lix with either the native or WebAssembly binding.");
63
+ }
64
+ }
41
65
  }
42
- export function openLixBinding(storage, telemetry) {
43
- const nativeTelemetry = telemetry
44
- ? (spanJson) => telemetry(JSON.parse(spanJson))
45
- : undefined;
66
+ export async function openNativeLixBinding(storage, telemetry) {
46
67
  switch (storage.kind) {
47
- case "memory":
68
+ case "memory": {
69
+ const nativeAddon = loadNativeAddon();
70
+ const nativeTelemetry = telemetry
71
+ ? (spanJson) => telemetry(JSON.parse(spanJson))
72
+ : undefined;
48
73
  if (nativeTelemetry)
49
- return addon.Lix.openMemory(nativeTelemetry);
50
- return addon.Lix.openMemory();
74
+ return nativeAddon.Lix.openMemory(nativeTelemetry);
75
+ return nativeAddon.Lix.openMemory();
76
+ }
51
77
  case "indexedDb":
52
78
  throw new Error("IndexedDbStorage is only available in browsers");
53
- case "filesystem":
79
+ case "filesystem": {
80
+ const nativeAddon = loadNativeAddon();
81
+ const nativeTelemetry = telemetry
82
+ ? (spanJson) => telemetry(JSON.parse(spanJson))
83
+ : undefined;
54
84
  if (nativeTelemetry) {
55
- return addon.Lix.openFilesystemStorage(storage.path, storage.syncAllFiles, nativeTelemetry);
85
+ return nativeAddon.Lix.openFilesystemStorage(storage.path, storage.syncAllFiles, nativeTelemetry);
56
86
  }
57
- return addon.Lix.openFilesystemStorage(storage.path, storage.syncAllFiles);
87
+ return nativeAddon.Lix.openFilesystemStorage(storage.path, storage.syncAllFiles);
88
+ }
58
89
  }
59
90
  }
package/dist/lix.js CHANGED
@@ -118,7 +118,10 @@ export class Lix {
118
118
  async close() {
119
119
  if (!this.closePromise) {
120
120
  if (this.#transactionsOpening > 0 || this.#activeTransactions > 0) {
121
- throw activeTransactionCloseError();
121
+ const error = new Error("cannot close Lix while an explicit transaction is active");
122
+ error.name = "LixError";
123
+ error.code = "LIX_INVALID_TRANSACTION_STATE";
124
+ throw error;
122
125
  }
123
126
  // Flip the public lifecycle gate before the first await. Operations that
124
127
  // already entered the gate are allowed to finish; later calls fail closed.
@@ -161,12 +164,6 @@ export class Lix {
161
164
  throw error;
162
165
  }
163
166
  }
164
- function activeTransactionCloseError() {
165
- const error = new Error("cannot close Lix while an explicit transaction is active");
166
- error.name = "LixError";
167
- error.code = "LIX_INVALID_TRANSACTION_STATE";
168
- return error;
169
- }
170
167
  export class ObserveEvents {
171
168
  onClose;
172
169
  setup = {};
@@ -265,9 +265,6 @@ export function record(value, description) {
265
265
  }
266
266
  return value;
267
267
  }
268
- function isRecord(value) {
269
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
270
- }
271
268
  function decodeWireValue(value) {
272
269
  const wire = record(value, "wire value");
273
270
  switch (wire.kind) {
@@ -78,8 +78,8 @@ export interface InitOutput {
78
78
  readonly wasmlixtransaction_rollback: (a: number) => number;
79
79
  readonly wasmobserveevents_close: (a: number) => void;
80
80
  readonly wasmobserveevents_next: (a: number) => number;
81
- readonly __wasm_bindgen_func_elem_119237: (a: number, b: number, c: number, d: number) => void;
82
- readonly __wasm_bindgen_func_elem_119239: (a: number, b: number, c: number, d: number) => void;
81
+ readonly __wasm_bindgen_func_elem_119238: (a: number, b: number, c: number, d: number) => void;
82
+ readonly __wasm_bindgen_func_elem_119240: (a: number, b: number, c: number, d: number) => void;
83
83
  readonly __wbindgen_export: (a: number, b: number) => number;
84
84
  readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
85
85
  readonly __wbindgen_export3: (a: number) => void;
@@ -362,7 +362,7 @@ function __wbg_get_imports() {
362
362
  __wbg__wbg_cb_unref_61db23ac97f16c31: function(arg0) {
363
363
  getObject(arg0)._wbg_cb_unref();
364
364
  },
365
- __wbg_applyChanges_e055d59b63743afd: function(arg0, arg1) {
365
+ __wbg_applyChanges_fa5b3bf30f8b61a3: function(arg0, arg1) {
366
366
  const ret = getObject(arg0).applyChanges(takeObject(arg1));
367
367
  return addHeapObject(ret);
368
368
  },
@@ -374,7 +374,7 @@ function __wbg_get_imports() {
374
374
  const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
375
375
  return addHeapObject(ret);
376
376
  }, arguments); },
377
- __wbg_close_93c7ea4f94bb464a: function(arg0) {
377
+ __wbg_close_65d6792c6f40ad89: function(arg0) {
378
378
  const ret = getObject(arg0).close();
379
379
  return addHeapObject(ret);
380
380
  },
@@ -481,7 +481,7 @@ function __wbg_get_imports() {
481
481
  const ret = getObject(arg0).length;
482
482
  return ret;
483
483
  },
484
- __wbg_loadEntries_7336ebc0a13d5ac7: function(arg0) {
484
+ __wbg_loadEntries_032470abc2177798: function(arg0) {
485
485
  const ret = getObject(arg0).loadEntries();
486
486
  return addHeapObject(ret);
487
487
  },
@@ -520,7 +520,7 @@ function __wbg_get_imports() {
520
520
  const a = state0.a;
521
521
  state0.a = 0;
522
522
  try {
523
- return __wasm_bindgen_func_elem_119239(a, state0.b, arg0, arg1);
523
+ return __wasm_bindgen_func_elem_119240(a, state0.b, arg0, arg1);
524
524
  } finally {
525
525
  state0.a = a;
526
526
  }
@@ -634,8 +634,8 @@ function __wbg_get_imports() {
634
634
  return addHeapObject(ret);
635
635
  },
636
636
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
637
- // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 28427, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
638
- const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_119237);
637
+ // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 28366, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
638
+ const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_119238);
639
639
  return addHeapObject(ret);
640
640
  },
641
641
  __wbindgen_cast_0000000000000002: function(arg0) {
@@ -684,10 +684,10 @@ function __wbg_get_imports() {
684
684
  };
685
685
  }
686
686
 
687
- function __wasm_bindgen_func_elem_119237(arg0, arg1, arg2) {
687
+ function __wasm_bindgen_func_elem_119238(arg0, arg1, arg2) {
688
688
  try {
689
689
  const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
690
- wasm.__wasm_bindgen_func_elem_119237(retptr, arg0, arg1, addHeapObject(arg2));
690
+ wasm.__wasm_bindgen_func_elem_119238(retptr, arg0, arg1, addHeapObject(arg2));
691
691
  var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
692
692
  var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
693
693
  if (r1) {
@@ -698,8 +698,8 @@ function __wasm_bindgen_func_elem_119237(arg0, arg1, arg2) {
698
698
  }
699
699
  }
700
700
 
701
- function __wasm_bindgen_func_elem_119239(arg0, arg1, arg2, arg3) {
702
- wasm.__wasm_bindgen_func_elem_119239(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
701
+ function __wasm_bindgen_func_elem_119240(arg0, arg1, arg2, arg3) {
702
+ wasm.__wasm_bindgen_func_elem_119240(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
703
703
  }
704
704
 
705
705
  const WasmLixFinalization = (typeof FinalizationRegistry === 'undefined')
Binary file
@@ -28,8 +28,8 @@ export const wasmlixtransaction_execute: (a: number, b: number, c: number, d: nu
28
28
  export const wasmlixtransaction_rollback: (a: number) => number;
29
29
  export const wasmobserveevents_close: (a: number) => void;
30
30
  export const wasmobserveevents_next: (a: number) => number;
31
- export const __wasm_bindgen_func_elem_119237: (a: number, b: number, c: number, d: number) => void;
32
- export const __wasm_bindgen_func_elem_119239: (a: number, b: number, c: number, d: number) => void;
31
+ export const __wasm_bindgen_func_elem_119238: (a: number, b: number, c: number, d: number) => void;
32
+ export const __wasm_bindgen_func_elem_119240: (a: number, b: number, c: number, d: number) => void;
33
33
  export const __wbindgen_export: (a: number, b: number) => number;
34
34
  export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
35
35
  export const __wbindgen_export3: (a: number) => void;
@@ -37,28 +37,30 @@ export async function openLixWorkerBinding(storage, onDisposed, telemetry) {
37
37
  }
38
38
  : undefined;
39
39
  const binding = await openDirectLixBinding(storage, telemetryDispatch);
40
- if (!onDisposed)
41
- return binding;
42
- let disposed = false;
43
- return new Proxy(binding, {
44
- get(target, property, receiver) {
45
- if (property === "close") {
46
- return async () => {
47
- try {
48
- await target.close();
49
- }
50
- finally {
51
- if (!disposed) {
52
- disposed = true;
53
- onDisposed();
40
+ if (binding) {
41
+ if (!onDisposed)
42
+ return binding;
43
+ let disposed = false;
44
+ return new Proxy(binding, {
45
+ get(target, property, receiver) {
46
+ if (property === "close") {
47
+ return async () => {
48
+ try {
49
+ await target.close();
54
50
  }
55
- }
56
- };
51
+ finally {
52
+ if (!disposed) {
53
+ disposed = true;
54
+ onDisposed();
55
+ }
56
+ }
57
+ };
58
+ }
59
+ const value = Reflect.get(target, property, receiver);
60
+ return typeof value === "function" ? value.bind(target) : value;
57
61
  }
58
- const value = Reflect.get(target, property, receiver);
59
- return typeof value === "function" ? value.bind(target) : value;
60
- },
61
- });
62
+ });
63
+ }
62
64
  }
63
65
  const client = await openLixWorker(storage, onDisposed, telemetry);
64
66
  return workerBinding(client);
@@ -1,4 +1,5 @@
1
1
  import type { LixBinding, LixStorageConfig, TelemetryDispatch } from "../binding-types.js";
2
2
  import type { WorkerConnection } from "./protocol.js";
3
3
  export declare function createWorkerConnection(): WorkerConnection;
4
- export declare const openDirectLixBinding: (storage: LixStorageConfig, telemetry?: TelemetryDispatch) => Promise<LixBinding>;
4
+ export declare function workerExecArgv(execArgv: readonly string[]): string[];
5
+ export declare const openDirectLixBinding: (storage: LixStorageConfig, telemetry?: TelemetryDispatch) => Promise<LixBinding | undefined>;
@@ -1,8 +1,9 @@
1
1
  import { Worker } from "node:worker_threads";
2
- import { openLixBinding } from "../binding.node.js";
2
+ import { openNativeLixBinding } from "../binding.node.js";
3
3
  export function createWorkerConnection() {
4
4
  const worker = new Worker(new URL("./entry.node.js", import.meta.url), {
5
5
  name: "lix",
6
+ execArgv: workerExecArgv(process.execArgv),
6
7
  });
7
8
  let terminating = false;
8
9
  return {
@@ -34,7 +35,30 @@ export function createWorkerConnection() {
34
35
  },
35
36
  };
36
37
  }
38
+ export function workerExecArgv(execArgv) {
39
+ const filtered = [];
40
+ for (let index = 0; index < execArgv.length; index++) {
41
+ const arg = execArgv[index];
42
+ if (arg === "--input-type") {
43
+ index += 1;
44
+ continue;
45
+ }
46
+ if (arg === "--expose-gc" || arg.startsWith("--input-type="))
47
+ continue;
48
+ filtered.push(arg);
49
+ }
50
+ return filtered;
51
+ }
37
52
  /// Native Lix already owns a dedicated serialized engine actor. Routing it
38
53
  /// through a second JavaScript worker adds two message-port hops per query
39
54
  /// without adding isolation or concurrency.
40
- export const openDirectLixBinding = (storage, telemetry) => openLixBinding(storage, telemetry);
55
+ export const openDirectLixBinding = async (storage, telemetry) => {
56
+ try {
57
+ return await openNativeLixBinding(storage, telemetry);
58
+ }
59
+ catch (error) {
60
+ if (storage.kind === "memory")
61
+ return undefined;
62
+ throw error;
63
+ }
64
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lix-js/sdk",
3
3
  "type": "module",
4
- "version": "0.12.1",
4
+ "version": "0.12.3",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -53,10 +53,10 @@
53
53
  "typecheck": "tsc -p tsconfig.test.json --noEmit"
54
54
  },
55
55
  "optionalDependencies": {
56
- "@lix-js/sdk-darwin-arm64": "0.12.1",
57
- "@lix-js/sdk-linux-arm64": "0.12.1",
58
- "@lix-js/sdk-linux-x64": "0.12.1",
59
- "@lix-js/sdk-win32-x64": "0.12.1"
56
+ "@lix-js/sdk-darwin-arm64": "0.12.3",
57
+ "@lix-js/sdk-linux-arm64": "0.12.3",
58
+ "@lix-js/sdk-linux-x64": "0.12.3",
59
+ "@lix-js/sdk-win32-x64": "0.12.3"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@vitest/browser-playwright": "4.1.10",