@moltendb-web/angular
May 20, 2026 Β· View on GitHub
Official Angular integration for MoltenDb, providing a seamless reactive developer experience using modern Angular Signals.
Requirements: Angular 17 or higher. This library uses Angular Signals and standalone APIs introduced in Angular 17.
What's New in v2.0.0
- Bulk Delete with
.where()β delete documents matching a filter clause without listing individual keys. - Capped Collections (
.maxSize()) β cap a collection to a maximum number of documents; oldest entries are evicted automatically when the limit is reached. - TTL Collections (
.ttl()) β set a time-to-live (in seconds) on a collection; documents are removed automatically after expiry.
Demo
See the library in action with a real-world demo application:
- π Demo repo: github.com/maximilian27/moltendb-angular
- β‘ StackBlitz: Open in StackBlitz
- π **Live demo: ** moltendb-angular.maximilian-both27.workers.dev/laptops
Installation
npm install @moltendb-web/angular
@moltendb-web/core and @moltendb-web/query are automatically installed as dependencies β no need to install them
separately.
Step 1: Configure Assets
MoltenDb runs its database engine inside a background Web Worker and relies on WebAssembly (WASM). You must tell Angular to serve these compiled files as public assets.
Update the assets array in your angular.json:
"assets": [
{
"glob": "moltendb-worker.js",
"input": "node_modules/@moltendb-web/core/dist",
"output": "/"
},
{
"glob": "moltendb_core.js",
"input": "node_modules/@moltendb-web/core/dist/wasm",
"output": "/wasm/"
},
{
"glob": "*.wasm",
"input": "node_modules/@moltendb-web/core/dist/wasm",
"output": "/wasm/"
}
]
Note: Restart your Angular dev server after modifying
angular.json.
Step 2: Provide MoltenDb
Initialise MoltenDb in your root app.config.ts:
import {ApplicationConfig} from '@angular/core';
import {provideMoltenDb} from '@moltendb-web/angular';
export const appConfig: ApplicationConfig = {
providers: [
provideMoltenDb({
name: 'my_app_db',
workerUrl: '/moltendb-worker.js',
})
]
};
Step 3: Fetching and Mutating Data
Reactive data β moltenDbResource()
Use moltenDbResource to bind data to your template. It handles loading states, errors, and live collection updates
automatically.
import {Component} from '@angular/core';
import {moltenDbResource} from '@moltendb-web/angular';
interface Laptop {
_key: string;
brand: string;
model: string;
price: number;
}
@Component({
selector: 'app-laptops',
template: `
@if (laptops.isLoading() && !laptops.value()) {
<p>Loadingβ¦</p>
}
@if (laptops.value(); as list) {
<ul>
@for (item of list; track item._key) {
<li>{{ item.brand }} {{ item.model }} β {{ item.price | currency }}</li>
}
</ul>
}
@if (laptops.error()) {
<p class="error">{{ laptops.error().message }}</p>
}
`
})
export class LaptopsComponent {
laptops = moltenDbResource<Laptop[]>('laptops', (col) =>
col.get()
.where({in_stock: true})
.sort([{field: 'price', order: 'asc'}])
.exec() as Promise<Laptop[]>
);
}
Imperative access β moltendbClient()
Use moltendbClient() for mutations and one-off queries triggered by user actions:
import {Component} from '@angular/core';
import {moltendbClient} from '@moltendb-web/angular';
@Component({...})
export class AdminComponent {
private client = moltendbClient();
async addLaptop() {
await this.client.collection('laptops').set({
lp_new: {brand: 'Framework', model: 'Laptop 16', price: 1049, in_stock: true}
}).exec();
// Any moltenDbResource watching 'laptops' refreshes automatically
}
}
Hooks
moltendbClient()
Returns the MoltenDbClient instance for imperative database access. Must be called in an injection context.
moltenDbResource<T>(collection, queryFn)
Creates a reactive resource bound to a collection. Automatically re-fetches when the collection is mutated. Must be called in an injection context.
Returns a MoltenDbResource<T> with three readonly signals:
| Signal | Type | Description |
|---|---|---|
value | Signal<T | undefined> | The latest query result |
isLoading | Signal<boolean> | true while a fetch is in progress |
error | Signal<any | null> | The last error, or null if none |
moltenDbReady()
Returns true once MoltenDb has finished initialising. Useful for gating UI until the database is ready. Must be called
in an injection context.
import {Component} from '@angular/core';
import {moltenDbReady} from '@moltendb-web/angular';
@Component({
selector: 'app-shell',
template: `
@if (!isReady()) {
<p>β Initialising databaseβ¦</p>
} @else {
<ng-content />
}
`
})
export class AppShellComponent {
isReady = moltenDbReady;
}
moltenDbIsLeader()
Returns true if the current tab is the Leader β the tab running the WASM worker and performing actual writes.
Other tabs act as follower proxies. Must be called in an injection context.
import {Component} from '@angular/core';
import {moltenDbIsLeader} from '@moltendb-web/angular';
@Component({
selector: 'app-tab-badge',
template: `<span>{{ isLeader() ? 'π Leader' : 'π Follower' }}</span>`
})
export class TabBadgeComponent {
isLeader = moltenDbIsLeader;
}
moltenDbTerminate()
Terminates the MoltenDb worker. Must be called in an injection context.
moltenDbClearOpfs() (v2.0.0)
Flushes and closes the OPFS sync handle. Call this before moltenDbTerminate() β without it the browser throws a "
No modification allowed" error when removing the OPFS directory. Must be called in an injection context.
import { Component } from '@angular/core';
import { moltenDbClearOpfs, moltenDbTerminate } from '@moltendb-web/angular';
@Component({
selector: 'app-reset-button',
template: `<button (click)="handleReset()">π Reset All Data</button>`
})
export class ResetButtonComponent {
private clearOpfs = moltenDbClearOpfs;
private terminate = moltenDbTerminate;
async handleReset() {
if (!confirm('This will delete all local data and reload. Continue?')) return;
// 1. Flush and close the OPFS sync handle
await this.clearOpfs();
// 2. Now safe to terminate the worker
this.terminate();
location.reload();
}
}
moltenDbEvents(listener) (v2.0.0 β auto-unsubscribe)
Subscribes to real-time mutation events. The listener is called with a DbEvent whenever any document is created,
updated, deleted, or a collection is dropped. The subscription is automatically cleaned up when the injection
context (component/service) is destroyed β no ngOnDestroy or manual unsubscription needed. Must be called in an
injection context.
import {Component} from '@angular/core';
import {moltenDbEvents} from '@moltendb-web/angular';
import type {DbEvent} from '@moltendb-web/angular';
@Component({
selector: 'app-live-feed',
template: `
<ul>
@for (e of events; track e) {
<li>{{ e.event }} β {{ e.collection }}/{{ e.key }}</li>
}
</ul>
`
})
export class LiveFeedComponent {
events: DbEvent[] = [];
constructor() {
moltenDbEvents((evt) => {
this.events = [evt, ...this.events].slice(0, 50);
});
// β
No ngOnDestroy needed β subscription is auto-cleaned up when component is destroyed
}
}
API Reference
| Export | Type | Description |
|---|---|---|
provideMoltenDb(config) | Provider | Registers MoltenDb as an Angular environment provider |
moltendbClient() | Injection hook | Returns the MoltenDbClient instance |
moltenDbReady() | Injection hook | Returns true once MoltenDb has finished initialising |
moltenDbIsLeader() | Injection hook | Returns true if the current tab is the Leader |
moltenDbTerminate() | Injection hook | Terminates the MoltenDb worker |
moltenDbClearOpfs() | Injection hook | (v2.0.0) Flush and close the OPFS sync handle β call before moltenDbTerminate() |
moltenDbResource(collection, queryFn) | Injection hook | Reactive resource with value, isLoading, error signals and auto-refresh |
moltenDbEvents(listener) | Injection hook | (v2.0.0) Subscribe to real-time DbEvent mutation events; auto-unsubscribes when the injection context is destroyed |
DbEvent | Type | Event object emitted on mutations: { event, collection, key, new_v } |
AngularMoltenDbOptions | Interface | Config passed to provideMoltenDb β extends MoltenDbOptions with a required name field |
MoltenDbResource<T> | Interface | Return type of moltenDbResource: { value, isLoading, error } signals |
Configuration
AngularMoltenDbOptions extends the core MoltenDbOptions with one required field:
| Option | Type | Default | Description |
|---|---|---|---|
name | string | required | Database name (used as the OPFS directory name) |
inMemory | boolean | false | Run entirely in RAM β no OPFS writes. Data persists as long as at least one tab is open; any tab refresh or close wipes the shared store for all tabs |
encryptionKey | string | undefined | Password for at-rest encryption. If omitted, data is stored as plain JSON |
writeMode | 'async' | 'sync' | 'async' | Storage write mode: 'async' for high throughput or 'sync' for durable writes |
maxBodySize | number | undefined | Maximum request body size in bytes |
maxKeysPerRequest | number | 1000 | Maximum number of keys allowed per JSON request |
workerUrl | string | URL | undefined | Custom URL or path to moltendb-worker.js |
Notes
provideMoltenDb()uses Angular'sAPP_INITIALIZERto block app bootstrap until the database is ready β no need to check aisReadyflag in most components.- Multiple apps using the same
namewill share the same underlying OPFS storage and sync across tabs via the built-in leader/follower mechanism. moltenDbResourcere-fetches automatically when the bound collection is mutated by any tab β no manual refresh needed.