@moltendb-web/core 1.0.0-rc.3 → 1.0.0-rc.4
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 +28 -28
- package/dist/index.d.ts +7 -7
- package/dist/index.js +5 -5
- package/dist/moltendb-worker.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
#
|
|
1
|
+
# MoltenDb Web
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
|
-
<img src="../../assets/logo.png" alt="
|
|
4
|
+
<img src="../../assets/logo.png" alt="MoltenDb Logo" width="64"/>
|
|
5
5
|
|
|
6
6
|
### 🌋 The Embedded Database for the Modern Web
|
|
7
7
|
**High-performance Rust engine compiled to WASM. Persistent storage via OPFS.**
|
|
8
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/
|
|
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
10
|
|
|
11
11
|
[](https://www.npmjs.com/package/@moltendb-web/core)
|
|
12
12
|
[](LICENSE.md)
|
|
@@ -17,15 +17,15 @@
|
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
## What is
|
|
20
|
+
## What is MoltenDb Web?
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
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.
|
|
23
23
|
|
|
24
24
|
> **🚀 Release Candidate** — The core engine, multi-tab sync, and storage layer are feature-complete and stabilised for v1. Server sync, encryption and analytics are planned for a future release.
|
|
25
25
|
|
|
26
26
|
### 🎮 Explore the Full Functionality
|
|
27
27
|
|
|
28
|
-
The best way to experience
|
|
28
|
+
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.
|
|
29
29
|
|
|
30
30
|
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.
|
|
31
31
|
|
|
@@ -37,7 +37,7 @@ Prefer to run it in your own environment? You can **[clone the demo repository](
|
|
|
37
37
|
- **Worker-Threaded:** The database runs entirely inside a Web Worker—zero impact on your UI thread.
|
|
38
38
|
- **Multi-Tab Sync (stabilised):** Leader election via the Web Locks API ensures only one tab owns the OPFS handle. All other tabs proxy reads and writes through a `BroadcastChannel`. Seamless leader promotion when the active tab closes.
|
|
39
39
|
- **Automatic Compaction:** The engine automatically compacts the append-only log when it exceeds **500 entries or 5 MB**, keeping storage lean without any manual intervention.
|
|
40
|
-
- **Real-Time Pub/Sub:** Every write and delete emits a typed `
|
|
40
|
+
- **Real-Time Pub/Sub:** Every write and delete emits a typed `DbEvent` to all open tabs instantly. The `subscribe()` pattern supports multiple independent listeners per tab — perfect for modern UI frameworks like React and Angular.
|
|
41
41
|
- **GraphQL-style Selection:** Request only the fields you need (even deeply nested ones) to save memory and CPU.
|
|
42
42
|
- **Auto-Indexing:** The engine monitors your queries and automatically creates indexes for frequently filtered fields.
|
|
43
43
|
- **Conflict Resolution:** Incoming writes with `_v ≤ stored _v` are silently skipped.
|
|
@@ -47,7 +47,7 @@ Prefer to run it in your own environment? You can **[clone the demo repository](
|
|
|
47
47
|
|
|
48
48
|
## Installation
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
MoltenDb is split into two packages: the core engine and the type-safe, chainable query builder.
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
53
|
# Install the core engine and WASM artifacts
|
|
@@ -58,7 +58,7 @@ npm install @moltendb-web/query
|
|
|
58
58
|
```
|
|
59
59
|
📦 **Bundler Setup**
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
MoltenDb handles its own Web Workers and WASM loading automatically. However, depending on your build tool, you may need a tiny config tweak to ensure it serves the static files correctly.
|
|
62
62
|
|
|
63
63
|
**For Vite:**
|
|
64
64
|
Exclude the core package from pre-bundling in your vite.config.js:
|
|
@@ -85,17 +85,17 @@ module.exports = {
|
|
|
85
85
|
# Quick Start
|
|
86
86
|
1. Initialize the Client
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
MoltenDb handles the Web Worker and WASM instantiation for you.
|
|
89
89
|
TypeScript
|
|
90
90
|
```ts
|
|
91
|
-
import {
|
|
92
|
-
import {
|
|
91
|
+
import { MoltenDb } from '@moltendb-web/core';
|
|
92
|
+
import { MoltenDbClient, WorkerTransport } from '@moltendb-web/query';
|
|
93
93
|
|
|
94
|
-
const db = new
|
|
94
|
+
const db = new MoltenDb('moltendb_demo');
|
|
95
95
|
await db.init();
|
|
96
96
|
|
|
97
97
|
// Connect the query builder to the WASM worker
|
|
98
|
-
const client = new
|
|
98
|
+
const client = new MoltenDbClient(db);
|
|
99
99
|
|
|
100
100
|
// 2. Insert and Query
|
|
101
101
|
|
|
@@ -200,7 +200,7 @@ await client.collection('laptops')
|
|
|
200
200
|
|
|
201
201
|
// Supported Query Operators
|
|
202
202
|
|
|
203
|
-
|
|
203
|
+
MoltenDb supports a variety of operators in the `where` clause:
|
|
204
204
|
|
|
205
205
|
| Operator | Aliases | Description |
|
|
206
206
|
|---|---|---|
|
|
@@ -248,14 +248,14 @@ await client.collection('laptops')
|
|
|
248
248
|
|
|
249
249
|
### How the Log Works
|
|
250
250
|
|
|
251
|
-
|
|
251
|
+
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.
|
|
252
252
|
|
|
253
253
|
- **Automatic Compaction:** When the log exceeds **500 entries or 5 MB**, the engine automatically "squashes" the log, removing superseded document versions to reclaim space. No manual `compact()` calls are needed in normal operation.
|
|
254
254
|
- **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.
|
|
255
255
|
|
|
256
256
|
### Multi-Tab Sync
|
|
257
257
|
|
|
258
|
-
|
|
258
|
+
MoltenDb uses the **Web Locks API** for leader election. The first tab to acquire the lock becomes the *leader* and owns the OPFS file handle directly. Every subsequent tab becomes a *follower* and proxies all reads and writes through a `BroadcastChannel` to the leader.
|
|
259
259
|
|
|
260
260
|
When the leader tab is closed, the next queued follower automatically acquires the lock and promotes itself to leader — no data loss, no manual reconnection required.
|
|
261
261
|
|
|
@@ -268,12 +268,12 @@ Tab 1 (Leader) ──owns──▶ Web Worker ──▶ WASM Engine ──▶ OP
|
|
|
268
268
|
|
|
269
269
|
### Real-Time Events (Pub/Sub)
|
|
270
270
|
|
|
271
|
-
|
|
271
|
+
MoltenDb has a built-in pub/sub system that automatically notifies **all open tabs** whenever a document is created, updated, or deleted — no polling required.
|
|
272
272
|
|
|
273
273
|
You can attach multiple independent listeners using the subscribe() method, making it trivial to keep different UI components (like React hooks or Angular signals) in sync without memory leaks:
|
|
274
274
|
|
|
275
275
|
```ts
|
|
276
|
-
const db = new
|
|
276
|
+
const db = new MoltenDb('my-app');
|
|
277
277
|
await db.init();
|
|
278
278
|
|
|
279
279
|
// Attach a listener (Returns an unsubscribe function)
|
|
@@ -298,21 +298,21 @@ db.subscribe(({ event, collection, key }) => {
|
|
|
298
298
|
});
|
|
299
299
|
```
|
|
300
300
|
|
|
301
|
-
The `
|
|
301
|
+
The `DbEvent` type is exported from the package for full TypeScript support:
|
|
302
302
|
|
|
303
303
|
```ts
|
|
304
|
-
import {
|
|
304
|
+
import { MoltenDb, DbEvent } from '@moltendb-web/core';
|
|
305
305
|
|
|
306
|
-
const db = new
|
|
306
|
+
const db = new MoltenDb('my-app');
|
|
307
307
|
await db.init();
|
|
308
308
|
|
|
309
|
-
db.subscribe((e:
|
|
309
|
+
db.subscribe((e: DbEvent) => { /* fully typed */ });```
|
|
310
310
|
|
|
311
311
|
---
|
|
312
312
|
|
|
313
313
|
### Performance Note
|
|
314
314
|
|
|
315
|
-
Because
|
|
315
|
+
Because MoltenDb uses OPFS, your browser must support `SharedArrayBuffer`. Most modern browsers support this, but your server must send the following headers:
|
|
316
316
|
|
|
317
317
|
```http
|
|
318
318
|
Cross-Origin-Opener-Policy: same-origin
|
|
@@ -356,7 +356,7 @@ npm run test:coverage # with coverage report
|
|
|
356
356
|
|
|
357
357
|
This monorepo contains the following packages:
|
|
358
358
|
|
|
359
|
-
- **`packages/core`:** The core WASM engine, Web Worker logic, and the
|
|
359
|
+
- **`packages/core`:** The core WASM engine, Web Worker logic, and the MoltenDb main client.
|
|
360
360
|
- **`packages/query`:** The type-safe, chainable Query Builder.
|
|
361
361
|
|
|
362
362
|
## Roadmap
|
|
@@ -366,7 +366,7 @@ This monorepo contains the following packages:
|
|
|
366
366
|
- [x] **Rich Test Suite:** 50 unit, integration, and stress tests via Vitest — **stabilised in RC1**.
|
|
367
367
|
- [ ] **React Adapter:** Official `@moltendb-web/react` package with `useQuery` hooks and real-time context providers.
|
|
368
368
|
- [ ] **Angular Adapter:** Official `@moltendb-web/angular` package featuring RxJS observables and Signal-based data fetching.
|
|
369
|
-
- [ ] **Delta Sync:** Automatic two-way sync with the
|
|
369
|
+
- [ ] **Delta Sync:** Automatic two-way sync with the MoltenDb Rust server.
|
|
370
370
|
- [ ] **Data Encryption:** Transparent encryption-at-rest using hardware-backed keys (Web Crypto API).
|
|
371
371
|
- [ ] **Analytics Functionality:** Run complex analytics queries straight in the browser without blocking the UI.
|
|
372
372
|
|
|
@@ -379,8 +379,8 @@ Found a bug or have a feature request? Please open an issue on the [GitHub issue
|
|
|
379
379
|
|
|
380
380
|
## License
|
|
381
381
|
|
|
382
|
-
The
|
|
382
|
+
The MoltenDb Web packages (`@moltendb-web/core` and `@moltendb-web/query`) are licensed under the MIT License.
|
|
383
383
|
|
|
384
|
-
The **
|
|
384
|
+
The **MoltenDb Server** (Rust backend) remains under the Business Source License 1.1 (Free for organizations under $5M revenue, requires a license for managed services).
|
|
385
385
|
|
|
386
386
|
For commercial licensing or questions: [maximilian.both27@outlook.com](mailto:maximilian.both27@outlook.com)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface MoltenDbOptions {
|
|
2
2
|
/** URL or path to moltendb-worker.js. */
|
|
3
3
|
workerUrl?: string | URL;
|
|
4
4
|
}
|
|
5
|
-
export interface
|
|
5
|
+
export interface DbEvent {
|
|
6
6
|
type: 'event';
|
|
7
7
|
event: 'change' | 'delete' | 'drop';
|
|
8
8
|
collection: string;
|
|
9
9
|
key: string;
|
|
10
10
|
new_v: number | null;
|
|
11
11
|
}
|
|
12
|
-
export declare class
|
|
12
|
+
export declare class MoltenDb {
|
|
13
13
|
readonly dbName: string;
|
|
14
14
|
readonly workerUrl?: string | URL;
|
|
15
15
|
worker: Worker | null;
|
|
@@ -17,16 +17,16 @@ export declare class MoltenDB {
|
|
|
17
17
|
isLeader: boolean;
|
|
18
18
|
private bc;
|
|
19
19
|
/** Legacy global hook. Use `subscribe()` for multi-component listeners. */
|
|
20
|
-
onEvent?: (event:
|
|
20
|
+
onEvent?: (event: DbEvent) => void;
|
|
21
21
|
private eventListeners;
|
|
22
|
-
constructor(dbName?: string, options?:
|
|
22
|
+
constructor(dbName?: string, options?: MoltenDbOptions);
|
|
23
23
|
/**
|
|
24
24
|
* âš¡ Subscribe to real-time DB mutations.
|
|
25
25
|
* @returns An unsubscribe function to prevent memory leaks in UI frameworks.
|
|
26
26
|
*/
|
|
27
|
-
subscribe(listener: (event:
|
|
27
|
+
subscribe(listener: (event: DbEvent) => void): () => void;
|
|
28
28
|
/** Manually remove a specific listener */
|
|
29
|
-
unsubscribe(listener: (event:
|
|
29
|
+
unsubscribe(listener: (event: DbEvent) => void): void;
|
|
30
30
|
private dispatchEvent;
|
|
31
31
|
private initialized;
|
|
32
32
|
init(): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { mapToObj } from "./helpers";
|
|
2
|
-
export class
|
|
2
|
+
export class MoltenDb {
|
|
3
3
|
dbName;
|
|
4
4
|
workerUrl;
|
|
5
5
|
worker = null;
|
|
@@ -34,7 +34,7 @@ export class MoltenDB {
|
|
|
34
34
|
listener(event);
|
|
35
35
|
}
|
|
36
36
|
catch (err) {
|
|
37
|
-
console.error('[
|
|
37
|
+
console.error('[MoltenDb] Error in subscribed listener', err);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
}
|
|
@@ -61,7 +61,7 @@ export class MoltenDB {
|
|
|
61
61
|
this.startAsFollower();
|
|
62
62
|
resolveInit();
|
|
63
63
|
navigator.locks.request(`moltendb_lock_${this.dbName}`, async () => {
|
|
64
|
-
console.log(`[
|
|
64
|
+
console.log(`[MoltenDb] Promoting this tab to Leader.`);
|
|
65
65
|
await this.startAsLeader();
|
|
66
66
|
return new Promise(() => { }); // Hold lock
|
|
67
67
|
});
|
|
@@ -75,7 +75,7 @@ export class MoltenDB {
|
|
|
75
75
|
await navigator.storage.getDirectory();
|
|
76
76
|
}
|
|
77
77
|
catch {
|
|
78
|
-
throw new Error('[
|
|
78
|
+
throw new Error('[MoltenDb] Origin Private File System (OPFS) is not available in this browser context. ' +
|
|
79
79
|
'Try a non-private window or a browser that supports OPFS (Chrome 102+, Firefox 111+, Safari 15.2+).');
|
|
80
80
|
}
|
|
81
81
|
this.isLeader = true;
|
|
@@ -153,7 +153,7 @@ export class MoltenDB {
|
|
|
153
153
|
const timer = setTimeout(() => {
|
|
154
154
|
if (this.pendingRequests.has(id)) {
|
|
155
155
|
this.pendingRequests.delete(id);
|
|
156
|
-
reject(new Error(`[
|
|
156
|
+
reject(new Error(`[MoltenDb] Request "${action}" timed out.`));
|
|
157
157
|
}
|
|
158
158
|
}, 10000);
|
|
159
159
|
this.pendingRequests.set(id, {
|
package/dist/moltendb-worker.js
CHANGED
|
@@ -17,7 +17,7 @@ self.onmessage = async (e) => {
|
|
|
17
17
|
self.postMessage({ type: 'event', ...eventData });
|
|
18
18
|
}
|
|
19
19
|
catch (err) {
|
|
20
|
-
console.error('[
|
|
20
|
+
console.error('[MoltenDb Worker] Event parse error', err);
|
|
21
21
|
}
|
|
22
22
|
});
|
|
23
23
|
db = instance;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moltendb-web/core",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.0-rc.4",
|
|
4
|
+
"description": "MoltenDb WASM runtime — the database engine, Web Worker, and main-thread client in one package.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Maximilian Both <maximilian.both27@outlook.com>",
|
|
7
7
|
"license": "MIT",
|