Skip to content

v5.0.2 - Multi-Driver Support with Cross-Runtime Compatibility

Choose a tag to compare

@snomiao snomiao released this 02 Feb 05:47
· 36 commits to main since this release

Release v5.0.2 - Multi-Driver Support with Cross-Runtime Compatibility

This fork of @resolid/keyv-sqlite introduces multi-driver support with automatic runtime detection, enabling seamless operation across Node.js, Bun, and Deno.

🎯 What's New in This Fork

Multi-Driver Architecture

Before (upstream - better-sqlite3 only):

// Only works with better-sqlite3
const store = new KeyvSqlite({ uri: './cache.db' });

After (this fork - auto-detects best driver):

// Works with node:sqlite, bun:sqlite, or better-sqlite3
const store = new KeyvSqlite('./cache.db');
// Automatically uses:
// - node:sqlite in Node.js 22.5+
// - bun:sqlite in Bun
// - better-sqlite3 as fallback

Key Improvements

  1. 🔌 Multi-Driver Support

    • node:sqlite (Node.js 22.5+ native - zero dependencies!)
    • bun:sqlite (Bun runtime native)
    • better-sqlite3 (npm package fallback)
    • Auto-detects and uses the best available driver
  2. 🚀 Cross-Runtime Compatibility

    • Works in Node.js (18+)
    • Works in Bun
    • Works in Deno
    • Single codebase, multiple runtimes
  3. ⚡ Native Driver Support

    • Zero-dependency native drivers pre-loaded via top-level await
    • No compilation needed for node:sqlite or bun:sqlite
    • Instant availability (no async overhead)
  4. ✨ Enhanced API

    • String parameter: new KeyvSqlite('./cache.db')
    • Driver selection: { driver: 'node:sqlite' }
    • Custom drivers: { driver: CustomDriverClass }
  5. 🎯 Better Defaults

    • WAL mode enabled by default (upstream requires opt-in)
    • Improved performance out of the box
    • Better concurrency handling

📦 Installation

npm install @snomiao/keyv-sqlite

🆚 Fork vs Upstream Comparison

Feature Upstream (@resolid) This Fork (@snomiao)
SQLite drivers ✅ better-sqlite3 only ✅ Multi-driver (node:sqlite, bun:sqlite, better-sqlite3)
Auto-detection ❌ No ✅ Yes (picks best driver for runtime)
Native drivers ❌ No ✅ node:sqlite (Node 22.5+), bun:sqlite
Cross-runtime ⚠️ Node.js only ✅ Node.js, Bun, Deno
WAL mode ⚠️ Opt-in (off by default) ✅ Enabled by default
Driver abstraction ❌ No ✅ Yes (sqliteAdapter.ts with top-level await)
String parameter ❌ No ✅ Yes (new KeyvSqlite('./db'))
Benchmark workflow ❌ No ✅ Comprehensive multi-driver benchmarks
Build tool tsup tsdown
Linter biome oxlint + oxfmt

🔄 Migration from Upstream

If you're migrating from @resolid/keyv-sqlite:

  1. Update package.json:

    npm uninstall @resolid/keyv-sqlite
    npm install @snomiao/keyv-sqlite
  2. Your code continues to work as-is! The API is backwards compatible.

  3. Optional improvements you can make:

    // Can now use string parameter
    const store = new KeyvSqlite('./cache.db');
    
    // Option name modernized (old name still works)
    const store = new KeyvSqlite({
      uri: './cache.db',
      wal: true  // was: enableWALMode
    });

🎨 Usage Examples

Basic Usage

import { KeyvSqlite, createKeyv } from '@snomiao/keyv-sqlite';

// Simple file path (recommended)
const store = new KeyvSqlite('./cache.db');

// In-memory
const store = new KeyvSqlite(':memory:');

// With Keyv helper
const keyv = createKeyv('./cache.db');

Specify Driver

// Use node:sqlite explicitly
const store = new KeyvSqlite({
  uri: './cache.db',
  driver: 'node:sqlite'
});

// Use bun:sqlite explicitly
const store = new KeyvSqlite({
  uri: './cache.db',
  driver: 'bun:sqlite'
});

// Use better-sqlite3 explicitly
const store = new KeyvSqlite({
  uri: './cache.db',
  driver: 'better-sqlite3'
});

Custom Driver Module

import Database from 'better-sqlite3';

const store = new KeyvSqlite({
  uri: './cache.db',
  driver: Database  // Pass driver constructor directly
});

Full Options

const store = new KeyvSqlite({
  uri: './cache.db',
  table: 'my_cache',
  wal: true,              // WAL mode (default: true)
  busyTimeout: 10000,     // Busy timeout in ms
  driver: 'auto'          // Auto-detect (default)
});

🏗️ Architecture: Multi-Driver Abstraction

Driver Abstraction Layer (sqliteAdapter.ts)

Native drivers are pre-loaded at module initialization using top-level await:

// Pre-loaded at module level (happens once)
let nodeSqliteDriver = await import("node:sqlite");
let bunSqliteDriver = await import("bun:sqlite");
let betterSqlite3Driver = await import("better-sqlite3");

// Now available synchronously throughout the app!
function loadSpecificDriver(driver) {
  if (driver === "node:sqlite") return nodeSqliteDriver;
  if (driver === "bun:sqlite") return bunSqliteDriver;
  if (driver === "better-sqlite3") return betterSqlite3Driver;
}

Auto-Detection Logic

// In Bun runtime
if (isBun) {
  try bun:sqlite → better-sqlite3 → node:sqlite
}

// In Node.js/Deno
else {
  try node:sqlite → better-sqlite3
}

This eliminates async overhead in constructors while maintaining full driver flexibility across runtimes.

🧪 Testing

All 47 tests passing with:

  • ✅ node:sqlite (Node.js 22.5+ native)
  • ✅ bun:sqlite (Bun runtime native)
  • ✅ better-sqlite3 (npm package)

Comprehensive benchmarking workflow tests performance across all drivers.

📝 Changes from Upstream

Non-breaking additions:

  • Multi-driver support (node:sqlite, bun:sqlite, better-sqlite3)
  • Cross-runtime compatibility (Node.js, Bun, Deno)
  • String parameter support: new KeyvSqlite('./db')
  • WAL mode enabled by default (can disable with wal: false)
  • Driver abstraction layer with top-level await
  • Comprehensive benchmark workflow

Minor API updates (backwards compatible):

  • enableWALMode → wal (old name still works)

Build tooling changes:

  • tsup → tsdown
  • biome → oxlint + oxfmt

🙏 Credits

This fork builds on the excellent foundation by @huijiewei in the original @resolid/keyv-sqlite. The multi-driver architecture and cross-runtime support were implemented on top of their solid work.

📄 License

MIT


Full Changelog: 5.0.1...v5.0.2