@massalabs/gossip-sdk 0.0.2-dev.20260223124034 → 0.0.2-dev.20260223131319

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.
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * SQLite Web Worker — owns all WASM/SQLite state.
3
3
  *
4
- * Runs wa-sqlite (sync build) with AccessHandlePoolVFS for OPFS persistence.
5
- * The main thread communicates via postMessage with { id, type, ... } messages.
4
+ * Two VFS modes:
5
+ * - OPFS (mobile): AccessHandlePoolVFS + sync WASM fast, single-tab.
6
+ * - IDB (web): IDBBatchAtomicVFS + async WASM — multi-tab safe.
6
7
  *
7
8
  * Messages:
8
9
  * init → load WASM + VFS, open DB, run init SQL (PRAGMAs + DDL)
@@ -1,17 +1,16 @@
1
1
  /**
2
2
  * SQLite Web Worker — owns all WASM/SQLite state.
3
3
  *
4
- * Runs wa-sqlite (sync build) with AccessHandlePoolVFS for OPFS persistence.
5
- * The main thread communicates via postMessage with { id, type, ... } messages.
4
+ * Two VFS modes:
5
+ * - OPFS (mobile): AccessHandlePoolVFS + sync WASM fast, single-tab.
6
+ * - IDB (web): IDBBatchAtomicVFS + async WASM — multi-tab safe.
6
7
  *
7
8
  * Messages:
8
9
  * init → load WASM + VFS, open DB, run init SQL (PRAGMAs + DDL)
9
10
  * exec → prepare/bind/step/finalize, return { rows, lastInsertRowId }
10
11
  * close → close DB
11
12
  */
12
- import SQLiteESMFactory from 'wa-sqlite/dist/wa-sqlite.mjs';
13
13
  import * as SQLite from 'wa-sqlite';
14
- import { AccessHandlePoolVFS } from 'wa-sqlite/src/examples/AccessHandlePoolVFS.js';
15
14
  import { execStatements } from './exec-utils.js';
16
15
  let sqlite3 = null;
17
16
  let dbHandle = null;
@@ -34,15 +33,28 @@ addEventListener('message', async (e) => {
34
33
  try {
35
34
  switch (type) {
36
35
  case 'init': {
37
- const { opfsPath, wasmUrl, initSql } = e.data;
36
+ const { dbPath, wasmUrl, initSql, useOPFS } = e.data;
38
37
  const moduleArg = {};
39
38
  if (wasmUrl)
40
39
  moduleArg.locateFile = () => wasmUrl;
41
- const module = await SQLiteESMFactory(moduleArg);
42
- sqlite3 = SQLite.Factory(module);
43
- const vfs = new AccessHandlePoolVFS(opfsPath);
44
- await vfs.isReady;
45
- sqlite3.vfs_register(vfs, true);
40
+ // Load the right WASM build + VFS.
41
+ // NOTE: import() paths must be string literals — Vite can't resolve variables.
42
+ if (useOPFS) {
43
+ const { default: SQLiteESMFactory } = await import('wa-sqlite/dist/wa-sqlite.mjs');
44
+ const { AccessHandlePoolVFS } = await import('wa-sqlite/src/examples/AccessHandlePoolVFS.js');
45
+ const module = await SQLiteESMFactory(moduleArg);
46
+ sqlite3 = SQLite.Factory(module);
47
+ const vfs = new AccessHandlePoolVFS(dbPath);
48
+ await vfs.isReady;
49
+ sqlite3.vfs_register(vfs, true);
50
+ }
51
+ else {
52
+ const { default: SQLiteESMFactory } = await import('wa-sqlite/dist/wa-sqlite-async.mjs');
53
+ const { IDBBatchAtomicVFS } = await import('wa-sqlite/src/examples/IDBBatchAtomicVFS.js');
54
+ const module = await SQLiteESMFactory(moduleArg);
55
+ sqlite3 = SQLite.Factory(module);
56
+ sqlite3.vfs_register(new IDBBatchAtomicVFS(dbPath), true);
57
+ }
46
58
  dbHandle = await sqlite3.open_v2('gossip.db');
47
59
  if (initSql) {
48
60
  await sqlite3.exec(dbHandle, initSql);
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Uses wa-sqlite (WASM) with Drizzle ORM's sqlite-proxy driver.
5
5
  * Two execution paths:
6
- * - Browser (opfsPath set): Web Worker + AccessHandlePoolVFSOPFS persistence,
6
+ * - Browser (opfsPath set): Web Worker + IDBBatchAtomicVFSIndexedDB persistence,
7
7
  * off the main thread. Uses the sync WASM build (wa-sqlite).
8
8
  * - In-memory (tests): :memory: in-process — no persistence, fast, isolated.
9
9
  * Uses the sync WASM build with wasmBinary passed directly.
@@ -15,11 +15,15 @@ import * as schema from './schema/index.js';
15
15
  export type GossipDatabase = SqliteRemoteDatabase<typeof schema>;
16
16
  export interface InitDbOptions {
17
17
  /**
18
- * OPFS directory path for persistent storage.
19
- * When set, spawns a Web Worker with AccessHandlePoolVFS for OPFS persistence.
20
- * When omitted, uses an in-memory database (for tests).
18
+ * OPFS directory path. When set, uses AccessHandlePoolVFS (fast, single-tab).
19
+ * Use for mobile (Capacitor) where only one instance runs at a time.
21
20
  */
22
21
  opfsPath?: string;
22
+ /**
23
+ * IndexedDB database name. When set, uses IDBBatchAtomicVFS (multi-tab safe).
24
+ * Use for web where multiple tabs may be open.
25
+ */
26
+ idbName?: string;
23
27
  /**
24
28
  * Pre-loaded WASM binary for environments where fetch() is unavailable
25
29
  * (e.g. Node.js tests). When omitted, the factory uses fetch() to load
@@ -37,8 +41,9 @@ export interface InitDbOptions {
37
41
  * Initialize wa-sqlite and create the Drizzle ORM instance.
38
42
  * Idempotent — subsequent calls are no-ops.
39
43
  *
40
- * @param options.opfsPath - Set to persist via OPFS Worker (production).
41
- * Omit for in-memory database (tests).
44
+ * @param options.opfsPath - OPFS path for mobile (single-tab, fast).
45
+ * @param options.idbName - IndexedDB name for web (multi-tab safe).
46
+ * Omit both for in-memory database (tests).
42
47
  */
43
48
  export declare function initDb(options?: InitDbOptions): Promise<void>;
44
49
  /**
package/dist/db/sqlite.js CHANGED
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Uses wa-sqlite (WASM) with Drizzle ORM's sqlite-proxy driver.
5
5
  * Two execution paths:
6
- * - Browser (opfsPath set): Web Worker + AccessHandlePoolVFSOPFS persistence,
6
+ * - Browser (opfsPath set): Web Worker + IDBBatchAtomicVFSIndexedDB persistence,
7
7
  * off the main thread. Uses the sync WASM build (wa-sqlite).
8
8
  * - In-memory (tests): :memory: in-process — no persistence, fast, isolated.
9
9
  * Uses the sync WASM build with wasmBinary passed directly.
@@ -114,15 +114,17 @@ const PRAGMAS = `
114
114
  * Initialize wa-sqlite and create the Drizzle ORM instance.
115
115
  * Idempotent — subsequent calls are no-ops.
116
116
  *
117
- * @param options.opfsPath - Set to persist via OPFS Worker (production).
118
- * Omit for in-memory database (tests).
117
+ * @param options.opfsPath - OPFS path for mobile (single-tab, fast).
118
+ * @param options.idbName - IndexedDB name for web (multi-tab safe).
119
+ * Omit both for in-memory database (tests).
119
120
  */
120
121
  export async function initDb(options = {}) {
121
122
  if (db.drizzleDb)
122
123
  return;
123
- if (options.opfsPath) {
124
- // Browser path: spawn Worker with OPFS + AccessHandlePoolVFS.
125
- // The sync WASM build runs in the Worker (no Asyncify needed).
124
+ const useOPFS = !!options.opfsPath;
125
+ const dbPath = options.opfsPath ?? options.idbName;
126
+ if (dbPath) {
127
+ // Spawn Worker with persistent VFS.
126
128
  db.worker = new Worker(new URL('./sqlite-worker.ts', import.meta.url), {
127
129
  type: 'module',
128
130
  });
@@ -131,16 +133,15 @@ export async function initDb(options = {}) {
131
133
  try {
132
134
  await postToWorker({
133
135
  type: 'init',
134
- opfsPath: options.opfsPath,
136
+ dbPath,
137
+ useOPFS,
135
138
  wasmUrl: options.wasmUrl,
136
139
  initSql: PRAGMAS,
137
140
  });
138
141
  }
139
142
  catch (err) {
140
- // Prevent dangling worker and "another open Access Handle" on retry:
141
- // only one SyncAccessHandle per file is allowed (e.g. another tab or
142
- // a previous failed init may hold it). Terminate and reset so retry
143
- // doesn't create a second worker.
143
+ // Prevent dangling worker on init failure.
144
+ // Terminate and reset so retry doesn't create a second worker.
144
145
  if (db.worker) {
145
146
  db.worker.terminate();
146
147
  db.worker = null;
package/dist/gossip.d.ts CHANGED
@@ -23,14 +23,18 @@ export interface GossipSdkInitOptions {
23
23
  protocolBaseUrl?: string;
24
24
  /** SDK configuration (optional - uses defaults if not provided) */
25
25
  config?: DeepPartial<SdkConfig>;
26
- /** URL to wa-sqlite.wasm (for bundlers that rewrite asset paths) */
26
+ /** URL to wa-sqlite WASM file (for bundlers that rewrite asset paths) */
27
27
  wasmUrl?: string;
28
28
  /**
29
- * OPFS directory path for persistent SQLite storage.
30
- * When set, data persists across page reloads via OPFS.
31
- * When omitted, uses an in-memory database (data lost on reload).
29
+ * OPFS directory path for persistent SQLite storage (mobile/Capacitor).
30
+ * Fast but single-tab only. Mutually exclusive with `idbName`.
32
31
  */
33
32
  opfsPath?: string;
33
+ /**
34
+ * IndexedDB database name for persistent SQLite storage (web).
35
+ * Multi-tab safe. Mutually exclusive with `opfsPath`.
36
+ */
37
+ idbName?: string;
34
38
  }
35
39
  export interface OpenSessionOptions {
36
40
  /** BIP39 mnemonic phrase */
package/dist/gossip.js CHANGED
@@ -177,7 +177,11 @@ class GossipSdk {
177
177
  startWasmInitialization();
178
178
  console.log('[GossipSdk] Initializing SQLite');
179
179
  // Initialize SQLite (idempotent — no-op if already initialized).
180
- await initDb({ wasmUrl: options.wasmUrl, opfsPath: options.opfsPath });
180
+ await initDb({
181
+ wasmUrl: options.wasmUrl,
182
+ opfsPath: options.opfsPath,
183
+ idbName: options.idbName,
184
+ });
181
185
  console.log('[GossipSdk] SQLite initialized');
182
186
  // Create message protocol
183
187
  const messageProtocol = createMessageProtocol();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massalabs/gossip-sdk",
3
- "version": "0.0.2-dev.20260223124034",
3
+ "version": "0.0.2-dev.20260223131319",
4
4
  "description": "Gossip SDK for automation, chatbot, and integration use cases",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",