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

signalk-database

v0.2.0

Published

SQLite library + admin UI for SignalK plugins: import { openPluginDb } from 'signalk-database' to get an isolated per-plugin database

Readme

signalk-database

A SQLite library and admin UI for SignalK Node Server plugins. Other plugins import signalk-database to get an isolated per-plugin SQLite database; the admin webapp browses every database on disk.

Status: early development (0.2.0). No server-side cooperation needed — works against stock signalk-server.

Backups are handled out-of-band by signalk-backup — see Backup integration below.

For plugin authors

Add signalk-database as a peer dependency and import the library:

// package.json
{
  "peerDependencies": {
    "signalk-database": "^0.2"
  }
}
import { openPluginDb } from 'signalk-database';

export default function (app) {
  let db;
  return {
    id: 'my-plugin',
    name: 'My Plugin',
    async start() {
      db = await openPluginDb(app);
      await db.migrate([
        {
          version: 1,
          sql: 'CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT)',
        },
      ]);
    },
    async stop() {
      // db handles are cached per-process; nothing to close per plugin.
    },
  };
}

The library exposes a PluginDb interface:

interface PluginDb {
  migrate(migrations: Migration[]): Promise<void>;
  query<T>(sql: string, params?: unknown[]): Promise<T[]>;
  run(sql: string, params?: unknown[]): Promise<RunResult>;
  transaction<T>(fn: (tx: PluginDb) => Promise<T>): Promise<T>;
}

Each plugin's database lives at {configPath}/plugin-config-data/{pluginId}/db.sqlite — the standard SignalK plugin data directory that app.getDataDirPath() returns. The library never touches app.config.configPath directly, so a plugin cannot reach across into another plugin's data. WAL mode, foreign keys on. Repeated calls to openPluginDb(app) return the cached handle.

For server admins

Install from the SignalK Appstore (or npm install signalk-database into ~/.signalk/). The plugin enables itself on a fresh install (signalk-plugin-enabled-by-default), so it starts running after the next server restart with no admin-UI configuration needed.

Visit http://<your-server>/signalk-database/ for the web admin UI. It:

  • Lists every plugin database on disk
  • Shows tables, schemas, indexes, foreign keys
  • Pages through table rows (read-only)

The admin UI file-scans {configPath}/plugin-config-data/*/db.sqlite, so it sees every database regardless of whether the owning plugin is currently running. This is the only place in signalk-database that walks across plugin scopes, which is appropriate for an admin/inspector role.

Requirements

  • Node 22.5.0 or newer. The library uses node:sqlite; older Node versions don't have it.
  • Admin auth. The plugin mounts its API under /plugins/signalk-database/api/*, which the SignalK server itself wraps in its admin-authentication middleware. When server security is configured, only admin users can reach the API; when it is disabled, the server allows the request through and our routes follow suit.

Backup integration

signalk-backup (0.5+) ships a built-in exporter for SignalK Database. With both plugins installed:

  1. In the SignalK admin UI, open the Backup plugin → SettingsDatabase export.
  2. Toggle on Export SignalK Database plugin DBs.

On every backup tick (and ahead of every manual backup), signalk-backup walks /plugins/signalk-database/api/full-export/databases, then for each entry calls /plugins/signalk-database/api/full-export/<id> to get a consistent point-in-time copy of that plugin's DB via VACUUM INTO. The resulting db.sqlite files are staged under plugin-config-data/signalk-backup/database-exports/signalk-database/<plugin-id>/ and picked up by the next kopia snapshot.

Why this matters: snapshotting the live WAL files directly is not transactionally safe — a torn WAL may need recovery on restore. The VACUUM INTO copy is a defragmented single-file snapshot that kopia dedupes efficiently across cycles, and the source plugin keeps running during the backup (brief read lock only).

The HTTP endpoints are also usable directly from curl or scripts; they're documented as a stable public API in AGENTS.md.

Why a peer dependency?

Peer-dep semantics ensure a single shared install across all consumer plugins:

  • One copy of signalk-database, one shared handle cache per process — no duplicate SQLite handles racing on the same file.
  • The admin UI sees every plugin DB without per-plugin glue.
  • npm warns if a consumer plugin's peer is unsatisfied, surfacing the missing install.

Contributing

See AGENTS.md for build/test/release notes and architecture pointers.

License

Apache-2.0