npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@moltendb-web/angular

v2.0.0

Published

Official Angular Signals wrapper for MoltenDb

Readme

@moltendb-web/angular

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:

| 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'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.