@moltendb-web/core 0.1.0-alpha.10

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/LICENSE.md ADDED
@@ -0,0 +1,35 @@
1
+ # MoltenDB License
2
+
3
+ MoltenDB is dual-licensed:
4
+
5
+ 1. **Free for Startups & Personal Use:** Licensed under the Business Source License (BSL) 1.1 with an Additional Use Grant (see below).
6
+ 2. **Commercial/Enterprise Use:** For companies exceeding the revenue threshold, or companies wishing to provide MoltenDB as a managed cloud service, a commercial license is required. Contact: [maximilian.both27@outlook.com]
7
+
8
+ ---
9
+
10
+ ## Business Source License 1.1
11
+
12
+ License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
13
+ "Business Source License" is a trademark of MariaDB Corporation Ab.
14
+
15
+ **Licensor:** Maximilian Both.
16
+ **Licensed Work:** The MoltenDB source code and compiled binaries.
17
+ **Change Date:** 3 years after the publication of each specific version/release.
18
+ **Change License:** MIT License
19
+
20
+ ### Additional Use Grant
21
+
22
+ You may make use of the Licensed Work (including running it in production) provided that your organization (including any parent companies, subsidiaries, and affiliates) meets **ALL** of the following conditions:
23
+
24
+ 1. **Revenue Limit:** Your organization's total annual gross revenue does not exceed $5,000,000 USD (or equivalent).
25
+ 2. **Not a Managed Service:** You do not offer the Licensed Work to third parties as a hosted or managed service (e.g., Database-as-a-Service, Backend-as-a-Service), regardless of your company's revenue.
26
+
27
+ If you meet these conditions, the Licensor grants you a non-exclusive, royalty-free, worldwide license to reproduce, use, merge, publish, distribute, and modify the Licensed Work.
28
+
29
+ If your organization exceeds the Revenue Limit, or if you wish to provide the Licensed Work as a managed service, you must purchase a Commercial License from the Licensor.
30
+
31
+ ### BSL General Terms
32
+
33
+ If your use of the Licensed Work does not comply with the Additional Use Grant, you may still use the Licensed Work strictly for non-production, internal testing, and development purposes.
34
+
35
+ Effective on the Change Date, or the fourth anniversary of the first publicly available distribution of a specific version of the Licensed Work under this License, whichever comes first, the Licensor hereby grants you rights under the terms of the Change License (MIT License), and the terms of this Business Source License will terminate for that specific version.
package/README.md ADDED
@@ -0,0 +1,261 @@
1
+ # MoltenDB Web
2
+
3
+ <div align="center">
4
+ <img src="./dist/assets/logo.png" alt="MoltenDB Logo" width="64"/>
5
+
6
+ ### 🌋 The Embedded Database for the Modern Web
7
+ **High-performance Rust engine compiled to WASM. Persistent storage via OPFS.**
8
+
9
+ [Interactive Demo](https://stackblitz.com/~/github.com/maximilian27/moltendb-wasm-demo?file=package.json) • [Core Engine](https://www.npmjs.com/package/@moltendb-web/core) • [Query Builder](https://www.npmjs.com/package/@moltendb-web/query) • [Original Repository](https://github.com/maximilian27/MoltenDB) • [License](LICENSE.md)
10
+
11
+ [![NPM Version](https://img.shields.io/npm/v/@moltendb-web/core?style=flat-square&color=orange)](https://www.npmjs.com/package/@moltendb-web/core)
12
+ [![License](https://img.shields.io/badge/license-BSL%201.1-blue?style=flat-square)](LICENSE.md)
13
+ [![WASM](https://img.shields.io/badge/wasm-optimized-magenta?style=flat-square)](https://webassembly.org/)
14
+
15
+ </div>
16
+
17
+ ---
18
+
19
+ ## What is MoltenDB Web?
20
+
21
+ MoltenDB is a JSON document database written in Rust that runs directly in your browser. Unlike traditional browser databases limited by `localStorage` quotas or IndexedDB's complex API, MoltenDB leverages the **Origin Private File System (OPFS)** to provide a high-performance, append-only storage engine.
22
+
23
+ ### 🎮 Explore the Full Functionality
24
+
25
+ The best way to experience MoltenDB is through the **[Interactive Demo on StackBlitz](https://stackblitz.com/~/github.com/maximilian27/moltendb-wasm-demo?file=package.json)**. It provides a complete, live environment where you can test query builder expressions, perform mutations, and see real-time events with zero local setup.
26
+
27
+ Prefer to run it in your own environment? You can **[clone the demo repository](https://github.com/maximilian27/moltendb-wasm-demo)** to inspect the source code, run the explorers locally, and experiment with your own schema.
28
+
29
+ **⚠️ Note for Online IDEs:** If you are viewing this on StackBlitz or CodeSandbox, the WASM engine may be blocked by iframe security restrictions. Please click the "Open in New Window/Tab" button in the preview pane to enable the full OPFS storage engine.
30
+
31
+ ### Core Features
32
+ - **Pure Rust Engine:** The same query logic used in our server binary, compiled to WebAssembly.
33
+ - **OPFS Persistence:** Data persists across page reloads in a dedicated, high-speed sandbox.
34
+ - **Worker-Threaded:** The database runs entirely inside a Web Worker—zero impact on your UI thread.
35
+ - **GraphQL-style Selection:** Request only the fields you need (even deeply nested ones) to save memory and CPU.
36
+ - **Auto-Indexing:** The engine monitors your queries and automatically creates indexes for frequently filtered fields.
37
+ - **Conflict Resolution:** Incoming writes with `_v ≤ stored _v` are silently skipped.
38
+ - **Inline reference embedding (`extends`):** Embed data from another collection at insert time.
39
+
40
+ ---
41
+
42
+ ## Installation
43
+
44
+ MoltenDB is split into two packages: the core engine and the type-safe, chainable query builder.
45
+
46
+ ```bash
47
+ # Install the core engine and WASM artifacts
48
+ npm install @moltendb-web/core
49
+
50
+ # Install the chainable query builder
51
+ npm install @moltendb-web/query
52
+ ```
53
+
54
+ ---
55
+
56
+ # Quick Start
57
+ 1. Initialize the Client
58
+
59
+ MoltenDB handles the Web Worker and WASM instantiation for you.
60
+ TypeScript
61
+ ```ts
62
+ import { MoltenDB } from '@moltendb-web/core';
63
+ import { MoltenDBClient, WorkerTransport } from '@moltendb-web/query';
64
+
65
+ const workerUrl = new URL('@moltendb-web/core/worker', import.meta.url).href;
66
+ const db = new MoltenDB('moltendb_demo', { syncEnabled: false, workerUrl });
67
+ await db.init();
68
+
69
+ // Connect the query builder to the WASM worker
70
+ const client = new MoltenDBClient(new WorkerTransport(db.worker));
71
+
72
+ // 2. Insert and Query
73
+
74
+ // Use the @moltendb-web/query builder for a type-safe experience.
75
+
76
+ // Insert data
77
+ await client.collection('laptops').set({
78
+ lp1: {
79
+ brand: "Apple",
80
+ model: "MacBook Pro",
81
+ price: 1999,
82
+ in_stock: true,
83
+ memory_id: 'mem1',
84
+ specs: {
85
+ cpu: {
86
+ cores: 8,
87
+ clock_speed: 3.5,
88
+ },
89
+ display: {
90
+ refresh_hz: 60,
91
+ }
92
+ }
93
+ },
94
+ lp2: {
95
+ brand: "Apple",
96
+ model: "MacBook Air",
97
+ price: 900,
98
+ in_stock: true,
99
+ memory_id: 'mem2',
100
+ specs: {
101
+ cpu: {
102
+ cores: 4,
103
+ clock_speed: 3.5,
104
+ },
105
+ display: {
106
+ refresh_hz: 60,
107
+ }
108
+ }
109
+ }
110
+ }).exec();
111
+
112
+ await client.collection('memory').set({
113
+ mem1: {
114
+ capacity_gb: 16,
115
+ type: 'DDR4',
116
+ speed_mhz: 4800,
117
+ upgradeable: false
118
+ },
119
+ mem2: {
120
+ capacity_gb: 64,
121
+ type: 'DDR5',
122
+ speed_mhz: 5600,
123
+ upgradeable: true
124
+ },
125
+ }).exec();
126
+
127
+ // Query with field selection
128
+ const results = await client.collection('laptops')
129
+ .get()
130
+ .where({ brand: { $in: ["Apple", "Dell"] }, in_stock: true }) // Using $in operator
131
+ .fields(['model', 'price']) // Only return these specific fields
132
+ .sort([{ field: 'price', order: 'desc' }])
133
+ .exec();
134
+
135
+ console.log(results);
136
+ // [
137
+ // {
138
+ // "_key": "lp1",
139
+ // "model": "MacBook Pro",
140
+ // "price": 1999
141
+ // },
142
+ // {
143
+ // "_key": "lp2",
144
+ // "model": "MacBook Air",
145
+ // "price": 900
146
+ // }
147
+ // ]
148
+
149
+ // Powerful Query Capabilities
150
+ // GraphQL-style Field Selection
151
+
152
+ // Never over-fetch data again. Use dot-notation to extract deeply nested values.
153
+
154
+ await client.collection('laptops')
155
+ .get()
156
+ .fields(["brand", "specs.cpu.cores", "specs.display.refresh_hz"])
157
+ .exec();
158
+
159
+ // Inline Joins
160
+
161
+ // Resolve relationships between collections at query time.
162
+
163
+ await client.collection('laptops')
164
+ .get()
165
+ .joins([{
166
+ alias: 'ram',
167
+ from: 'memory',
168
+ on: 'memory_id',
169
+ fields: ['capacity_gb', 'type']
170
+ }])
171
+ .exec();
172
+
173
+ // Supported Query Operators
174
+
175
+ MoltenDB supports a variety of operators in the `where` clause:
176
+
177
+ | Operator | Aliases | Description |
178
+ |---|---|---|
179
+ | `$eq` | `$equals` | Exact equality |
180
+ | `$ne` | `$notEquals` | Not equal |
181
+ | `$gt` | `$greaterThan` | Greater than (numeric) |
182
+ | `$gte` | | Greater than or equal |
183
+ | `$lt` | `$lessThan` | Less than (numeric) |
184
+ | `$lte` | | Less than or equal |
185
+ | `$contains` | `$ct` | Substring check (string) or membership check (array) |
186
+ | `$in` | `$oneOf` | Field value is one of a list |
187
+ | `$nin` | `$notIn` | Field value is not in a list |
188
+
189
+ // Inline reference embedding (`extends`)
190
+
191
+ The `extends` key embeds data from another collection directly into the stored document at insert time — no join needed on reads.
192
+
193
+ ```ts
194
+ await client.collection('laptops')
195
+ .set({
196
+ lp7: {
197
+ brand: "MSI",
198
+ model: "Titan GT77",
199
+ price: 3299,
200
+ }
201
+ })
202
+ .extends({
203
+ ram: "memory.mem4",
204
+ screen: "display.dsp3"
205
+ })
206
+ .exec();
207
+ ```
208
+
209
+ **When to use `extends` vs `joins`:**
210
+
211
+ | | `extends` | `joins` |
212
+ |---|---|---|
213
+ | Resolved at | Insert time (once) | Query time (every request) |
214
+ | Data freshness | Snapshot — may become stale | Always live |
215
+ | Read cost | O(1) — data already embedded | O(1) per join per document |
216
+ | Use when | Data rarely changes, fast reads matter | Data changes frequently, freshness matters |
217
+
218
+ ---
219
+ ## Storage Architecture
220
+
221
+ ### How the Log Works
222
+
223
+ MoltenDB uses an append-only JSON log. Every write is a new line, ensuring your data is safe even if the tab is closed unexpectedly.
224
+
225
+ - **Compaction:** When the log exceeds 5MB or 500 entries, the engine automatically "squashes" the log, removing old versions of documents to save space.
226
+ - **Persistence:** All data is stored in the Origin Private File System (OPFS). This is a special file system for web apps that provides much higher performance than IndexedDB.
227
+
228
+ ### Performance Note
229
+
230
+ Because MoltenDB uses OPFS, your browser must support `SharedArrayBuffer`. Most modern browsers support this, but your server must send the following headers:
231
+
232
+ ```http
233
+ Cross-Origin-Opener-Policy: same-origin
234
+ Cross-Origin-Embedder-Policy: require-corp
235
+ ```
236
+
237
+ ## Project Structure
238
+
239
+ This monorepo contains the following packages:
240
+
241
+ - **`packages/core`:** The core WASM engine, Web Worker logic, and the MoltenDB main client.
242
+ - **`packages/query`:** The type-safe, chainable Query Builder.
243
+
244
+ ## Roadmap
245
+
246
+ - [ ] **Multi-Tab Sync:** Leader election for multiple tabs to share a single OPFS instance.
247
+ - [ ] **Delta Sync:** Automatic two-way sync with the MoltenDB Rust server.
248
+ - [ ] **Analytics functionality:** Run analytics queries straight in the browser.
249
+
250
+ ## License
251
+
252
+ MoltenDB is licensed under the **Business Source License 1.1**.
253
+
254
+ - Free for personal use and organizations with annual revenue under $5 million USD.
255
+ - Converts to MIT automatically 3 years after each version's release date.
256
+
257
+ For commercial licensing or questions: [maximilian.both27@outlook.com](mailto:maximilian.both27@outlook.com)
258
+
259
+ ---
260
+
261
+ Created with 🌋 by Maximilian Both. Coming to the world on the Equinox.
Binary file
@@ -0,0 +1,56 @@
1
+ export interface MoltenDBOptions {
2
+ /** URL or path to moltendb-worker.js. Defaults to './moltendb-worker.js'. */
3
+ workerUrl?: string | URL;
4
+ /** Enable WebSocket sync with a MoltenDB server. Default: false. */
5
+ syncEnabled?: boolean;
6
+ /** WebSocket server URL. Default: 'wss://localhost:3000/ws'. */
7
+ serverUrl?: string;
8
+ /** Sync batch flush interval in ms. Default: 5000. */
9
+ syncIntervalMs?: number;
10
+ /** JWT token for WebSocket authentication. */
11
+ authToken?: string;
12
+ }
13
+
14
+ export type SyncCallback = (update: {
15
+ event: 'change' | 'delete' | 'drop';
16
+ collection: string;
17
+ key: string;
18
+ new_v: number | null;
19
+ }) => void;
20
+
21
+ export class MoltenDB {
22
+ readonly dbName: string;
23
+ readonly worker: Worker | null;
24
+
25
+ constructor(dbName?: string, options?: MoltenDBOptions);
26
+
27
+ /** Initialise the Web Worker and open the OPFS database. */
28
+ init(): Promise<void>;
29
+
30
+ /** Send a raw message to the worker. */
31
+ sendMessage(action: string, params?: Record<string, unknown>): Promise<unknown>;
32
+
33
+ /** Insert / upsert one document. */
34
+ set(collection: string, key: string, value: Record<string, unknown>, options?: { skipSync?: boolean }): Promise<void>;
35
+
36
+ /** Fetch a single document by key. */
37
+ get(collection: string, key: string): Promise<unknown>;
38
+
39
+ /** Fetch all documents in a collection. */
40
+ getAll(collection: string): Promise<unknown>;
41
+
42
+ /** Delete a document by key. */
43
+ delete(collection: string, key: string, options?: { skipSync?: boolean }): Promise<void>;
44
+
45
+ /** Compact the OPFS log file. */
46
+ compact(): Promise<unknown>;
47
+
48
+ /** Subscribe to real-time server push events. Returns an unsubscribe function. */
49
+ onSync(callback: SyncCallback): () => void;
50
+
51
+ /** Close the WebSocket connection and stop the sync timer. */
52
+ disconnect(): void;
53
+
54
+ /** Terminate the Web Worker (and disconnect sync). */
55
+ terminate(): void;
56
+ }
package/dist/index.js ADDED
@@ -0,0 +1,176 @@
1
+ /**
2
+ * MoltenDB main-thread client.
3
+ *
4
+ * Usage:
5
+ * import { MoltenDB } from 'moltendb-wasm';
6
+ *
7
+ * const db = new MoltenDB('my-db', {
8
+ * // Required: URL or path to the moltendb-worker.js file.
9
+ * // With a bundler: new URL('moltendb-wasm/worker', import.meta.url)
10
+ * // Plain script: '/node_modules/moltendb-wasm/dist/moltendb-worker.js'
11
+ * workerUrl: new URL('moltendb-wasm/worker', import.meta.url),
12
+ * });
13
+ * await db.init();
14
+ */
15
+ export class MoltenDB {
16
+ /**
17
+ * @param {string} dbName - OPFS file name (unique per database).
18
+ * @param {object} [options]
19
+ * @param {string|URL} [options.workerUrl] - URL to moltendb-worker.js.
20
+ * Defaults to './moltendb-worker.js' (works when served from the same directory).
21
+ * @param {boolean} [options.syncEnabled=false] - Enable WebSocket sync.
22
+ * @param {string} [options.serverUrl='wss://localhost:3000/ws'] - WS server URL.
23
+ * @param {number} [options.syncIntervalMs=5000] - Sync batch flush interval.
24
+ * @param {string} [options.authToken] - JWT token for WS authentication.
25
+ */
26
+ constructor(dbName = 'moltendb', options = {}) {
27
+ this.dbName = dbName;
28
+ this.workerUrl = options.workerUrl ?? './moltendb-worker.js';
29
+ this.worker = null;
30
+ this.messageId = 0;
31
+ this.pendingRequests = new Map();
32
+
33
+ this.syncEnabled = options.syncEnabled ?? false;
34
+ this.serverUrl = options.serverUrl ?? 'wss://localhost:3000/ws';
35
+ this.syncIntervalMs = options.syncIntervalMs ?? 5000;
36
+ this.authToken = options.authToken ?? null;
37
+
38
+ this.ws = null;
39
+ this.syncCallbacks = new Set();
40
+ this.syncQueue = [];
41
+ this.syncTimer = null;
42
+ }
43
+
44
+ /** Initialise the Web Worker and open the OPFS database. */
45
+ async init() {
46
+ return new Promise((resolve, reject) => {
47
+ this.worker = new Worker(this.workerUrl, { type: 'module' });
48
+
49
+ this.worker.onmessage = (event) => {
50
+ const { id, result, error } = event.data;
51
+ const pending = this.pendingRequests.get(id);
52
+ if (!pending) return;
53
+ this.pendingRequests.delete(id);
54
+ if (error) pending.reject(new Error(error));
55
+ else pending.resolve(result);
56
+ };
57
+
58
+ this.worker.onerror = (err) => {
59
+ console.error('[MoltenDB] Worker error:', err);
60
+ reject(err);
61
+ };
62
+
63
+ this.sendMessage('init', { dbName: this.dbName })
64
+ .then(() => this.syncEnabled ? this.connectSync() : undefined)
65
+ .then(resolve)
66
+ .catch(reject);
67
+ });
68
+ }
69
+
70
+ /**
71
+ * Send a raw message to the worker and return a Promise for the result.
72
+ * @param {string} action
73
+ * @param {object} [params]
74
+ */
75
+ sendMessage(action, params = {}) {
76
+ return new Promise((resolve, reject) => {
77
+ const id = this.messageId++;
78
+ this.pendingRequests.set(id, { resolve, reject });
79
+ this.worker.postMessage({ id, action, ...params });
80
+ });
81
+ }
82
+
83
+ // ── WebSocket sync ────────────────────────────────────────────────────────
84
+
85
+ connectSync() {
86
+ return new Promise((resolve, reject) => {
87
+ this.ws = new WebSocket(this.serverUrl);
88
+
89
+ this.ws.onopen = () => {
90
+ if (this.authToken) {
91
+ this.ws.send(JSON.stringify({ action: 'AUTH', token: this.authToken }));
92
+ }
93
+ if (this.syncTimer) clearInterval(this.syncTimer);
94
+ this.syncTimer = setInterval(() => this.flushSyncQueue(), this.syncIntervalMs);
95
+ resolve();
96
+ };
97
+
98
+ this.ws.onmessage = (event) => {
99
+ try { this.handleServerUpdate(JSON.parse(event.data)); }
100
+ catch (e) { console.error('[MoltenDB] Failed to parse server message:', e); }
101
+ };
102
+
103
+ this.ws.onclose = () => {
104
+ if (this.syncTimer) clearInterval(this.syncTimer);
105
+ setTimeout(() => this.connectSync(), 3000);
106
+ };
107
+
108
+ this.ws.onerror = (err) => reject(err);
109
+ });
110
+ }
111
+
112
+ handleServerUpdate(update) {
113
+ if (update.event === 'change' && update.collection && update.key) {
114
+ // Re-fetch the updated document from the server and apply locally.
115
+ // (The WS push only carries the key + new _v, not the full document.)
116
+ }
117
+ this.syncCallbacks.forEach(cb => cb(update));
118
+ }
119
+
120
+ /** Subscribe to real-time server push events. Returns an unsubscribe fn. */
121
+ onSync(callback) {
122
+ this.syncCallbacks.add(callback);
123
+ return () => this.syncCallbacks.delete(callback);
124
+ }
125
+
126
+ flushSyncQueue() {
127
+ if (!this.syncQueue.length || !this.ws || this.ws.readyState !== WebSocket.OPEN) return;
128
+ const batch = this.syncQueue.splice(0);
129
+ this.ws.send(JSON.stringify({ action: 'set', operations: batch }));
130
+ }
131
+
132
+ // ── Convenience CRUD helpers ──────────────────────────────────────────────
133
+
134
+ /** Insert / upsert one document. */
135
+ async set(collection, key, value, options = {}) {
136
+ await this.sendMessage('set', { collection, data: { [key]: value } });
137
+ if (this.syncEnabled && !options.skipSync) {
138
+ this.syncQueue.push({ action: 'set', collection, data: { [key]: value } });
139
+ }
140
+ }
141
+
142
+ /** Fetch a single document by key. */
143
+ get(collection, key) {
144
+ return this.sendMessage('get', { collection, keys: key });
145
+ }
146
+
147
+ /** Fetch all documents in a collection. */
148
+ getAll(collection) {
149
+ return this.sendMessage('get', { collection });
150
+ }
151
+
152
+ /** Delete a document by key. */
153
+ async delete(collection, key, options = {}) {
154
+ await this.sendMessage('delete', { collection, keys: key });
155
+ if (this.syncEnabled && !options.skipSync) {
156
+ this.syncQueue.push({ action: 'delete', collection, keys: key });
157
+ }
158
+ }
159
+
160
+ /** Compact the OPFS log file. */
161
+ compact() {
162
+ return this.sendMessage('compact');
163
+ }
164
+
165
+ /** Close the WebSocket connection and stop the sync timer. */
166
+ disconnect() {
167
+ if (this.syncTimer) clearInterval(this.syncTimer);
168
+ if (this.ws) this.ws.close();
169
+ }
170
+
171
+ /** Terminate the Web Worker (and disconnect sync). */
172
+ terminate() {
173
+ this.disconnect();
174
+ if (this.worker) this.worker.terminate();
175
+ }
176
+ }
@@ -0,0 +1,30 @@
1
+ // MoltenDB Web Worker — auto-generated by moltendb-wasm build script
2
+ // Do not edit directly; edit moltendb-wasm/scripts/build.mjs instead.
3
+ import init, { WorkerDb } from './moltendb.js';
4
+
5
+ let db = null;
6
+
7
+ self.onmessage = async (event) => {
8
+ const { id, action, ...params } = event.data;
9
+
10
+ try {
11
+ if (!db && action === 'init') {
12
+ await init();
13
+ db = await new WorkerDb(params.dbName || 'moltendb');
14
+ self.postMessage({ id, result: { status: 'initialized' } });
15
+ return;
16
+ }
17
+
18
+ if (!db) {
19
+ throw new Error('Database not initialized. Send an "init" message first.');
20
+ }
21
+
22
+ // Pass action + params but NOT id so the Rust validator does not see
23
+ // 'id' as an unknown property.
24
+ const result = db.handle_message({ action, ...params });
25
+ self.postMessage({ id, result });
26
+
27
+ } catch (error) {
28
+ self.postMessage({ id, error: error.toString() });
29
+ }
30
+ };
@@ -0,0 +1,119 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /**
5
+ * The WASM-exposed database handle used by the JavaScript Web Worker.
6
+ *
7
+ * `#[wasm_bindgen]` on the struct makes it visible to JavaScript.
8
+ * JavaScript creates an instance with: `const db = await new WorkerDb("mydb")`
9
+ *
10
+ * The struct wraps a `Db` — the same engine used on the server.
11
+ * All methods on this struct are thin adapters that:
12
+ * 1. Convert JavaScript values (JsValue) to Rust types.
13
+ * 2. Call the underlying Db methods.
14
+ * 3. Convert the result back to JsValue for JavaScript.
15
+ */
16
+ export class WorkerDb {
17
+ free(): void;
18
+ [Symbol.dispose](): void;
19
+ /**
20
+ * Execute an analytics query and return the result as a JSON string.
21
+ *
22
+ * This is the method called by the dashboard's auto-refresh loop:
23
+ * `const resultStr = db.analytics(JSON.stringify(query))`
24
+ *
25
+ * Takes a JSON string (not a JsValue) because the analytics query format
26
+ * is complex and easier to pass as a pre-serialized string from JavaScript.
27
+ *
28
+ * Returns a JSON string (not a JsValue) so JavaScript can parse it with
29
+ * `JSON.parse(resultStr)` and access `result` and `metadata`.
30
+ *
31
+ * Example input:
32
+ * `'{"collection":"events","metric":{"type":"COUNT"},"where":{"event_type":"button_click"}}'`
33
+ *
34
+ * Example output:
35
+ * `'{"result":42,"metadata":{"execution_time_ms":0,"rows_scanned":42}}'`
36
+ *
37
+ * `#[wasm_bindgen(js_name = analytics)]` sets the JavaScript method name to
38
+ * "analytics" (matching the call in analytics-worker.js).
39
+ */
40
+ analytics(query_json: string): string;
41
+ /**
42
+ * Route an incoming message from the JavaScript worker to the correct handler.
43
+ *
44
+ * Called from moltendb-worker.js as:
45
+ * `db.handle_message({ action: 'get', collection: 'laptops', keys: 'lp1' })`
46
+ *
47
+ * The `data` parameter is a plain JavaScript object (not a MessageEvent wrapper).
48
+ * It must have an `action` field that determines which operation to perform.
49
+ *
50
+ * Supported actions — identical to the HTTP server endpoints:
51
+ * - "get" → query documents (single key, batch, full collection, WHERE, joins, sort, pagination)
52
+ * - "set" → insert or upsert documents: { collection, data: { key: doc, ... } }
53
+ * - "update" → patch/merge documents: { collection, data: { key: patch, ... } }
54
+ * - "delete" → delete documents or drop: { collection, keys: ... } or { drop: true }
55
+ * - "compact" → compact the OPFS log file
56
+ * - "get_size" → return current OPFS file size in bytes
57
+ *
58
+ * Returns a JsValue result on success, or a JsValue error string on failure.
59
+ */
60
+ handle_message(data: any): any;
61
+ /**
62
+ * Initialize the database and open (or create) the OPFS storage file.
63
+ *
64
+ * This is the constructor — called from JavaScript as:
65
+ * `const db = await new WorkerDb("click_analytics_db")`
66
+ *
67
+ * `#[wasm_bindgen(constructor)]` tells wasm-bindgen that this function
68
+ * is the JavaScript `new WorkerDb(...)` constructor.
69
+ *
70
+ * `async` because opening the OPFS file handle is an async browser API.
71
+ * Returns `Result<WorkerDb, JsValue>` — on error, the JsValue becomes a
72
+ * JavaScript exception that the worker's try/catch can handle.
73
+ *
74
+ * # Arguments
75
+ * * `db_name` — The name of the OPFS file to open (e.g. "click_analytics_db").
76
+ * Each unique name is a separate database file in the browser's OPFS storage.
77
+ */
78
+ constructor(db_name: string);
79
+ }
80
+
81
+ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
82
+
83
+ export interface InitOutput {
84
+ readonly memory: WebAssembly.Memory;
85
+ readonly __wbg_workerdb_free: (a: number, b: number) => void;
86
+ readonly workerdb_analytics: (a: number, b: number, c: number, d: number) => void;
87
+ readonly workerdb_handle_message: (a: number, b: number, c: number) => void;
88
+ readonly workerdb_new: (a: number, b: number) => number;
89
+ readonly __wasm_bindgen_func_elem_3598: (a: number, b: number) => void;
90
+ readonly __wasm_bindgen_func_elem_3677: (a: number, b: number, c: number, d: number) => void;
91
+ readonly __wasm_bindgen_func_elem_3690: (a: number, b: number, c: number, d: number) => void;
92
+ readonly __wbindgen_export: (a: number, b: number) => number;
93
+ readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
94
+ readonly __wbindgen_export3: (a: number) => void;
95
+ readonly __wbindgen_export4: (a: number, b: number, c: number) => void;
96
+ readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
97
+ }
98
+
99
+ export type SyncInitInput = BufferSource | WebAssembly.Module;
100
+
101
+ /**
102
+ * Instantiates the given `module`, which can either be bytes or
103
+ * a precompiled `WebAssembly.Module`.
104
+ *
105
+ * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
106
+ *
107
+ * @returns {InitOutput}
108
+ */
109
+ export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
110
+
111
+ /**
112
+ * If `module_or_path` is {RequestInfo} or {URL}, makes a request and
113
+ * for everything else, calls `WebAssembly.instantiate` directly.
114
+ *
115
+ * @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
116
+ *
117
+ * @returns {Promise<InitOutput>}
118
+ */
119
+ export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;