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

bun-sqlite-watcher

v1.1.0

Published

A high-performance SQLite change watcher with type-safe events for Bun

Downloads

2

Readme

SQLite Watcher

A high-performance SQLite change tracking library for Bun that provides real-time notifications for database modifications. It offers type-safe event handling and can detect changes made by any process or connection to your SQLite database.

Built with performance and developer experience in mind, SQLite Watcher makes it easy to react to database changes in your Bun applications with minimal overhead.

Features

  • 🚀 High-performance change tracking using SQLite triggers
  • 📦 Zero dependencies (uses Bun's built-in SQLite)
  • 💪 Full TypeScript support with type-safe events
  • 🔄 Real-time change notifications
  • 🛡️ Safe concurrent access with WAL mode
  • 🎯 Chainable API with event filtering
  • 🧹 Automatic cleanup of old changes
  • 📊 Support for batch processing

Installation

bun add bun-sqlite-watcher

Quick Start

import { SQLiteWatcher } from 'bun-sqlite-watcher';

// Initialize the watcher
const watcher = new SQLiteWatcher({
  dbPath: "myapp.sqlite"
});

// Watch a table with type safety
interface User {
  id: number;
  name: string;
  email: string;
}

watcher.watch<User>('users')
  .onInsert(change => {
    console.log(`New user: ${change.changes.name}`);
  })
  .onUpdate(change => {
    console.log(`User updated: ${change.changes.name}`);
  })
  .onDelete(change => {
    console.log(`User deleted: ID ${change.rowId}`);
  });

// Start watching
watcher.start();

// Cleanup when done
watcher.cleanup();

Configuration

const watcher = new SQLiteWatcher({
  dbPath: "myapp.sqlite",        // Path to your SQLite database
  watchIntervalMs: 1000,         // How often to check for changes (default: 1000ms)
  maxChangesPerBatch: 1000,      // Maximum changes to process at once (default: 1000)
  retentionSeconds: 3600,        // How long to keep changes (default: 1 hour)
  bufferSize: 10000             // Maximum number of changes to buffer (default: 10000)
});

Advanced Usage

Filtering Changes

watcher.watch<User>('users')
  .filter(change => change.changes.role === 'admin')
  .onAny(change => {
    console.log(`Admin user changed: ${change.changes.name}`);
  });

Error Handling

watcher
  .onError(error => {
    console.error('Watcher error:', error);
  })
  .watch('users')
  .onAny(change => {
    // Handle changes
  });

Multiple Tables

// Watch multiple tables with different handlers
const tables = {
  users: {
    onInsert: notifyNewUser,
    onDelete: cleanupUserData
  },
  posts: {
    onUpdate: reindexPost,
    onDelete: removeFromCDN
  }
};

Object.entries(tables).forEach(([table, handlers]) => {
  watcher.watch(table)
    .onInsert(handlers.onInsert)
    .onDelete(handlers.onDelete);
});

Utility Methods

// Check if a table is being watched
console.log(watcher.isWatching('users'));

// Get list of watched tables
console.log(watcher.watchedTables);

// Get watcher table size
const size = await watcher.getWatcherTableSize();

Cleanup

// Stop watching and remove triggers
watcher.cleanup();

// Stop watching, remove triggers and watcher table
watcher.cleanup(true);

How It Works

The watcher creates a special table _sqlite_watcher_changes to track changes and sets up triggers on your tables. When a change occurs:

  1. The trigger adds a record to the watcher table
  2. The watcher periodically checks for new changes
  3. Changes are processed and emitted to your handlers
  4. Processed changes are automatically cleaned up

The watcher uses WAL mode for better performance and concurrent access.

Best Practices

  1. Always call cleanup() when you're done watching
  2. Use type parameters for type safety
  3. Handle errors with onError()
  4. Use filters to reduce unnecessary processing
  5. Adjust watchIntervalMs based on your needs
  6. Set appropriate retentionSeconds and bufferSize

Security & Performance Considerations

Security

  1. Access Control: Ensure proper file permissions on the SQLite database file to prevent unauthorized access
  2. SQL Injection: While the watcher uses prepared statements internally, be cautious with any custom SQL you execute
  3. Resource Exhaustion: Set appropriate bufferSize and maxChangesPerBatch limits to prevent memory issues
  4. Trigger Permissions: External tools or users need proper permissions to modify watched tables

Performance

  1. Watch Interval: Lower watchIntervalMs means faster updates but higher CPU usage
  2. Change Volume: High-frequency changes can impact performance; consider batch processing
  3. Database Size: Large watcher tables can slow down queries; adjust retentionSeconds
  4. Concurrent Access: While WAL mode helps, heavy write loads may impact watcher performance
  5. Memory Usage: Monitor bufferSize in high-change environments
  6. Trigger Overhead: Each watched table adds triggers that slightly impact write performance

License

MIT