@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:


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:

SignalTypeDescription
valueSignal<T | undefined>The latest query result
isLoadingSignal<boolean>true while a fetch is in progress
errorSignal<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

ExportTypeDescription
provideMoltenDb(config)ProviderRegisters MoltenDb as an Angular environment provider
moltendbClient()Injection hookReturns the MoltenDbClient instance
moltenDbReady()Injection hookReturns true once MoltenDb has finished initialising
moltenDbIsLeader()Injection hookReturns true if the current tab is the Leader
moltenDbTerminate()Injection hookTerminates the MoltenDb worker
moltenDbClearOpfs()Injection hook(v2.0.0) Flush and close the OPFS sync handle β€” call before moltenDbTerminate()
moltenDbResource(collection, queryFn)Injection hookReactive 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
DbEventTypeEvent object emitted on mutations: { event, collection, key, new_v }
AngularMoltenDbOptionsInterfaceConfig passed to provideMoltenDb β€” extends MoltenDbOptions with a required name field
MoltenDbResource<T>InterfaceReturn type of moltenDbResource: { value, isLoading, error } signals

Configuration

AngularMoltenDbOptions extends the core MoltenDbOptions with one required field:

OptionTypeDefaultDescription
namestringrequiredDatabase name (used as the OPFS directory name)
inMemorybooleanfalseRun 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
encryptionKeystringundefinedPassword 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
maxBodySizenumberundefinedMaximum request body size in bytes
maxKeysPerRequestnumber1000Maximum number of keys allowed per JSON request
workerUrlstring | URLundefinedCustom URL or path to moltendb-worker.js

Notes

  • provideMoltenDb() uses Angular's APP_INITIALIZER to block app bootstrap until the database is ready β€” no need to check a isReady flag in most components.
  • Multiple apps using the same name will share the same underlying OPFS storage and sync across tabs via the built-in leader/follower mechanism.
  • moltenDbResource re-fetches automatically when the bound collection is mutated by any tab β€” no manual refresh needed.