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

@objectql/driver-sqlite-wasm

v4.2.2

Published

SQLite WASM driver for ObjectQL - Browser-native SQL database with OPFS persistence

Readme

@objectql/driver-sqlite-wasm

Browser-native SQLite driver for ObjectQL using WebAssembly and OPFS persistence

npm version License: MIT

Overview

@objectql/driver-sqlite-wasm brings full-featured SQL database capabilities to browser environments through WebAssembly and the Origin Private File System (OPFS). This driver allows you to run ObjectQL applications entirely client-side with persistent storage.

Key Features:

  • Zero Server Dependencies — Complete SQL database in the browser
  • Persistent Storage — Data survives page refresh via OPFS
  • Full SQL Support — Leverages SQLite 3.x features (CTEs, window functions, JSON operators)
  • Reuses SQL Pipeline — Composes @objectql/driver-sql for proven Knex-based query building
  • ~300KB Bundle — Optimized WASM binary size
  • Library-Agnostic API — Public API references "SQLite WASM", underlying implementation (wa-sqlite) is swappable

Architecture

QueryAST → SqlDriver (Knex) → SQL string → wa-sqlite WASM → OPFS/Memory

This driver uses composition over inheritance:

  • Wraps SqlDriver from @objectql/driver-sql internally
  • Custom Knex client adapter bridges wa-sqlite WASM API
  • All query compilation logic delegated to SqlDriver
  • No code duplication, only WASM integration layer

Installation

pnpm add @objectql/driver-sqlite-wasm

Usage

Basic Example

import { SqliteWasmDriver } from '@objectql/driver-sqlite-wasm';

// Create driver with OPFS persistence (default)
const driver = new SqliteWasmDriver({
  storage: 'opfs',        // 'opfs' | 'memory'
  filename: 'myapp.db',   // Database filename in OPFS
  walMode: true,          // Enable WAL mode for concurrency
  pageSize: 4096          // SQLite page size
});

// Initialize schema
await driver.init([
  {
    name: 'tasks',
    fields: {
      id: { type: 'text', primary: true },
      title: { type: 'text' },
      completed: { type: 'boolean', default: false }
    }
  }
]);

// CRUD operations
const task = await driver.create('tasks', {
  title: 'Learn ObjectQL',
  completed: false
});

const tasks = await driver.find('tasks', {
  where: { completed: false },
  orderBy: [{ field: 'title', order: 'asc' }]
});

await driver.update('tasks', task.id, { completed: true });

await driver.delete('tasks', task.id);

With ObjectStack Kernel

import { ObjectStackKernel } from '@objectstack/runtime';
import { SqliteWasmDriver } from '@objectql/driver-sqlite-wasm';
import { HonoServerPlugin } from '@objectstack/plugin-hono-server';
import MyAppManifest from './objectstack.config';

const kernel = new ObjectStackKernel([
  MyAppManifest,
  new SqliteWasmDriver({ storage: 'opfs' }),
  new HonoServerPlugin({ port: 3000 })
]);

await kernel.start();

In-Memory Mode (Testing/SSR)

// Ephemeral storage - data lost on page refresh
const driver = new SqliteWasmDriver({ storage: 'memory' });

Configuration

export interface SqliteWasmDriverConfig {
  /** Storage backend. Default: 'opfs' */
  storage?: 'opfs' | 'memory';
  
  /** Database filename in OPFS. Default: 'objectql.db' */
  filename?: string;
  
  /** Enable WAL mode for better read concurrency. Default: true */
  walMode?: boolean;
  
  /** Page size in bytes. Default: 4096 */
  pageSize?: number;
}

Storage Modes

| Mode | Persistence | Use Case | Browser Support | |------|-------------|----------|-----------------| | opfs | Persistent (survives refresh) | Production PWAs, offline apps | Chrome 102+, Edge 102+, Safari 15.2+ | | memory | Ephemeral (lost on refresh) | Testing, SSR, demos | All browsers with WASM support |

Auto-fallback: If storage: 'opfs' is specified but OPFS is unavailable, the driver automatically falls back to 'memory' with a console warning.

Environment Requirements

| Requirement | Minimum Version | |-------------|-----------------| | WebAssembly | Required (95%+ browser coverage) | | OPFS | Optional (for persistence) | | Browser Support | Chrome 102+, Firefox 110+, Safari 15.2+, Edge 102+ |

Environment Detection:

import { checkWebAssembly, checkOPFS, detectStorageBackend } from '@objectql/driver-sqlite-wasm';

// Throws ObjectQLError({ code: 'ENVIRONMENT_ERROR' }) if WASM unavailable
checkWebAssembly();

// Returns true if OPFS is supported
const hasOPFS = await checkOPFS();

// Auto-detect best storage backend
const storage = await detectStorageBackend(); // 'opfs' | 'memory'

const driver = new SqliteWasmDriver({ storage });

Driver Capabilities

driver.supports = {
  create: true,
  read: true,
  update: true,
  delete: true,
  bulkCreate: true,
  bulkUpdate: true,
  bulkDelete: true,
  transactions: false,        // Single connection limitation
  savepoints: false,
  queryFilters: true,
  queryAggregations: true,
  querySorting: true,
  queryPagination: true,
  queryWindowFunctions: true,
  querySubqueries: true,
  queryCTE: true,
  joins: true,
  fullTextSearch: true,
  jsonFields: true,
  arrayFields: false,
  streaming: false,
  schemaSync: true,
  migrations: true,
  indexes: true,
  connectionPooling: false,   // Single connection
  preparedStatements: true,
  queryCache: false
};

API Reference

Driver Methods

All standard Driver interface methods are supported:

| Method | Description | |--------|-------------| | connect() | Initialize WASM module and database | | disconnect() | Close database connection | | checkHealth() | Verify database is responsive | | find(object, query, options?) | Query records | | findOne(object, id, query?, options?) | Get single record by ID | | create(object, data, options?) | Insert record | | update(object, id, data, options?) | Update record | | delete(object, id, options?) | Delete record | | count(object, filters, options?) | Count records | | bulkCreate(object, data[], options?) | Insert multiple records | | bulkUpdate(object, updates[], options?) | Update multiple records | | bulkDelete(object, ids[], options?) | Delete multiple records | | aggregate(object, query, options?) | Aggregate query | | distinct(object, field, filters?, options?) | Get distinct values | | init(objects[]) | Initialize schema from metadata | | introspectSchema() | Discover existing schema | | executeQuery(ast, options?) | Execute QueryAST (DriverInterface v4.0) | | executeCommand(command, options?) | Execute Command (DriverInterface v4.0) |

Query Syntax

Supports both legacy filter syntax and modern QueryAST:

// MongoDB-style filters
await driver.find('tasks', {
  where: {
    $or: [
      { completed: true },
      { priority: { $gte: 5 } }
    ]
  },
  orderBy: [{ field: 'createdAt', order: 'desc' }],
  limit: 10,
  skip: 0
});

// Simple object filters
await driver.find('tasks', {
  where: { completed: false, assignee: '[email protected]' }
});

Performance Considerations

OPFS Storage

  • Quota: Browsers allocate significant storage (10GB+ on desktop)
  • Performance: Near-native I/O speed (~80% of native SQLite)
  • Concurrency: Single connection per database (no cross-tab locking yet)

WAL Mode

Enabled by default (walMode: true):

  • Better read concurrency
  • Faster writes (batched to disk)
  • Small WAL file overhead

Bundle Size

| Component | Size (gzip) | |-----------|-------------| | Driver code | ~5KB | | wa-sqlite WASM | ~295KB | | Total | ~300KB |

Optimization Tips:

  • Use dynamic imports to lazy-load the driver
  • Consider code-splitting for apps with multiple drivers
  • WASM binary is cacheable (set long Cache-Control headers)

Migration from LocalStorage Driver

If you previously used @objectql/driver-localstorage (now deprecated):

// OLD (deprecated)
import { LocalStorageDriver } from '@objectql/driver-localstorage';
const driver = new LocalStorageDriver();

// NEW (recommended)
import { SqliteWasmDriver } from '@objectql/driver-sqlite-wasm';
const driver = new SqliteWasmDriver({ storage: 'opfs' });

Benefits of Migration:

  • No 5MB localStorage limit
  • Full SQL query support (joins, aggregations, subqueries)
  • Better performance for large datasets
  • Data persistence across sessions

Troubleshooting

ENVIRONMENT_ERROR: WebAssembly not supported

Cause: Browser does not support WebAssembly.

Solution: Check browser compatibility. All modern browsers (Chrome 57+, Firefox 52+, Safari 11+) support WASM.

OPFS not available warning

Cause: Browser does not support OPFS or it's disabled.

Solution: Driver auto-falls back to memory storage. To enable OPFS:

  • Ensure browser version supports OPFS (Chrome 102+, Safari 15.2+)
  • Check if OPFS is disabled in browser settings
  • Verify site is served over HTTPS (required for OPFS)

Data lost after page refresh

Cause: Driver is using memory storage instead of OPFS.

Solution:

// Explicitly check OPFS availability
import { checkOPFS } from '@objectql/driver-sqlite-wasm';

if (await checkOPFS()) {
  const driver = new SqliteWasmDriver({ storage: 'opfs' });
} else {
  console.error('OPFS not available - data will not persist');
}

Cross-origin isolation errors

Cause: SharedArrayBuffer requires cross-origin isolation headers.

Solution: Set these HTTP headers:

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin

Limitations

  • No Transactions: Single connection architecture prevents full ACID transactions
  • No Cross-Tab Sync: Database changes not visible across tabs/windows (yet)
  • No Streaming: Result sets fully materialized in memory
  • No Array Fields: SQLite JSON fields supported, but not native arrays

Roadmap

  • [ ] Cross-tab synchronization via BroadcastChannel
  • [ ] Transaction support via async locking
  • [ ] Streaming query results
  • [ ] Incremental vacuum on disconnect
  • [ ] IndexedDB fallback for older browsers
  • [ ] Encryption at rest (SQLite extension)

License

MIT © ObjectStack Inc.

Related Packages

Contributing

See CONTRIBUTING.md for development guidelines.

Support