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 🙏

© 2025 – Pkg Stats / Ryan Hefner

dexbee-js

v0.4.0

Published

A TypeScript IndexedDB ORM with SQL-like query builder interface. Browser-first with limited Node.js support via fake-indexeddb.

Readme

DexBee 🐝

A modern TypeScript IndexedDB ORM with SQL-like query builder interface. Build powerful browser-based applications with type-safe database operations and automatic schema migrations.

CI npm version TypeScript License: MIT

✨ Features

  • 🎯 Type-safe - Full TypeScript support with strong typing
  • 🔍 SQL-like queries - Familiar syntax for database operations
  • 🚀 Tree-shakeable - Import only what you need for optimal bundle size
  • 📦 Schema migrations - Automatic database schema evolution
  • 🔄 Transaction support - ACID compliance with transaction wrapper
  • Operation queuing - Automatic race condition prevention for concurrent operations
  • 🌐 Modern ESM - Full ESM support with TypeScript declarations
  • 🎨 Query builder - Intuitive, chainable query interface
  • 🌍 Browser-focused - Built specifically for IndexedDB in browser environments
  • 📎 Blob storage - Native support for Files, Blobs, and binary data with streaming
  • 🧪 Comprehensive testing - Unit tests, browser integration tests, and manual testing tools

📦 Installation

npm install dexbee-js
pnpm add dexbee-js
yarn add dexbee-js

🌍 Runtime Compatibility

DexBee is primarily built for browser environments but also supports limited Node.js usage:

✅ Browser Support:

  • Modern browsers (Chrome 24+, Firefox 16+, Safari 8+, Edge 12+)
  • Electron applications
  • WebView-based applications
  • Progressive Web Apps (PWAs)

✅ Node.js Support (Limited):

  • Testing environments with fake-indexeddb
  • Development/prototyping with memory-only storage
  • CI/CD pipelines for database logic testing
  • Memory-only cache layers for structured data
  • Schema validation and migration testing

⚠️ Node.js Limitations:

  • Requires fake-indexeddb polyfill (memory-only, no persistence)
  • Blob/File storage has limitations due to jsdom constraints
  • Not suitable for production data persistence
  • Binary data handling may be incomplete

✅ Server-side Support (Limited):

  • Node.js: Full compatibility (officially supported)
  • Deno: Full compatibility (v2+) via npm: specifier
  • Bun: Full compatibility (v1.2.9+) with ESM support
  • Testing environments with fake-indexeddb
  • Development/prototyping with memory-only storage
  • CI/CD pipelines for database logic testing
  • Memory-only cache layers for structured data
  • Schema validation and migration testing

❌ Not supported:

  • Cloudflare Workers (different storage APIs)

🚀 Quick Start

Browser Usage (Recommended)

import { DexBee, type DatabaseSchema, eq, gt } from 'dexbee-js'

const schema: DatabaseSchema = {
  version: 1,
  tables: {
    users: {
      schema: {
        id: { type: 'number', required: true },
        name: { type: 'string', required: true },
        age: { type: 'number' }
      },
      primaryKey: 'id',
      autoIncrement: true
    }
  }
}

const db = await DexBee.connect('myapp', schema)
const users = db.table('users')

// Insert data
await users.insert({ name: 'John', age: 30 })

// Query with SQL-like syntax
const adults = await users
  .where(gt('age', 18))
  .orderBy('name')
  .all()

Server-side Usage (Limited)

DexBee works in server-side environments using fake-indexeddb as a polyfill:

# Node.js - install fake-indexeddb
npm install fake-indexeddb

# Deno - no installation needed, uses npm: specifier
# Bun - may need "type": "module" in package.json for some versions
// Node.js
import 'fake-indexeddb/auto'
import { DexBee, defineSchema, eq } from 'dexbee-js'

// Deno
import 'npm:fake-indexeddb/auto'
import { DexBee, defineSchema, eq } from 'npm:dexbee-js'

const schema = defineSchema({
  version: 1,
  tables: {
    users: {
      schema: {
        id: { type: 'number', required: true },
        name: { type: 'string', required: true },
        email: { type: 'string', required: true }
      },
      primaryKey: 'id',
      autoIncrement: true
    }
  }
})

// Testing database logic
const db = await DexBee.connect('test-db', schema)
const users = db.table('users')

// Test data operations
await users.insert({ name: 'Alice', email: '[email protected]' })
const alice = await users.where(eq('name', 'Alice')).first()
console.log('Found user:', alice?.name)

Run with:

# Node.js
npx tsx examples/node-testing-example.ts

# Deno
deno run --allow-all examples/deno-testing-example.ts

Runtime Compatibility:

  • Node.js: Full compatibility (officially supported)
  • Deno: Full compatibility (v2+) via npm import
  • Bun: Full compatibility (v1.2.9+) with ESM support

⚠️ Important Notes:

  • Data is stored in memory only (not persisted to disk)
  • Blob/File storage has limitations
  • Best suited for testing, development, and temporary caching
  • Not recommended for production data persistence
  • Deno requires --allow-all flag for full functionality

Basic Example

import { DexBee, eq, gt } from 'dexbee-js'

// Quick start with DexBee
const db = await DexBee.connect('myapp', {
  version: 1,
  tables: {
    users: {
      schema: {
        id: { type: 'number', required: true },
        name: { type: 'string', required: true },
        age: { type: 'number' }
      },
      primaryKey: 'id',
      autoIncrement: true
    }
  }
} as const)

// Insert and query data
const users = db.table('users')
await users.insert({ name: 'Alice', age: 25 })
const adults = await users.where(gt('age', 18)).all()
console.log(adults) // [{ id: 1, name: 'Alice', age: 25 }]

Define Your Schema

import { DexBee, type DatabaseSchema } from 'dexbee-js'

const schema: DatabaseSchema = {
  version: 1,
  tables: {
    users: {
      schema: {
        id: { type: 'number', required: true },
        name: { type: 'string', required: true },
        email: { type: 'string', unique: true },
        age: { type: 'number' },
        createdAt: { type: 'date', default: () => new Date() }
      },
      primaryKey: 'id',
      autoIncrement: true,
      indexes: [
        { name: 'email', keyPath: 'email', unique: true },
        { name: 'age', keyPath: 'age' }
      ]
    },
    posts: {
      schema: {
        id: { type: 'number', required: true },
        title: { type: 'string', required: true },
        content: { type: 'string' },
        authorId: { type: 'number', required: true },
        publishedAt: { type: 'date' }
      },
      primaryKey: 'id',
      autoIncrement: true,
      indexes: [
        { name: 'authorId', keyPath: 'authorId' },
        { name: 'publishedAt', keyPath: 'publishedAt' }
      ]
    }
  }
}

Connect to Database

// Create and connect to database
const db = await DexBee.connect('myapp', schema)

// Or create without auto-connect
const db = DexBee.create('myapp', schema)
await db.connect()

Basic Operations

// Get table references
const users = db.table('users')
const posts = db.table('posts')

// Insert data
await users.insert({
  id: '1',
  name: 'John Doe',
  email: '[email protected]',
  age: 30
})

// Query with SQL-like syntax
import { eq, gt, and, or } from 'dexbee-js'

// Find user by email
const user = await users
  .select()
  .where(eq('email', '[email protected]'))
  .first()

// Complex queries
const youngAdults = await users
  .select()
  .where(and(
    gt('age', 18),
    lt('age', 30)
  ))
  .orderBy('name')
  .limit(10)
  .all()

// Update records (use direct method)
await users.update(1, { age: 31 })

// Delete records (use direct method)
await users.delete(1)

📖 Advanced Usage

Transactions

import { TransactionWrapper } from 'dexbee-js'

await db.transaction(['users', 'posts'], 'readwrite', async (tx) => {
  const txUsers = tx.table('users')
  const txPosts = tx.table('posts')
  
  // All operations are wrapped in a single transaction
  await txUsers.insert({ id: '2', name: 'Jane Doe', email: '[email protected]' })
  await txPosts.insert({ 
    id: '1', 
    title: 'Hello World', 
    authorId: '2',
    content: 'My first post!'
  })
  
  // Transaction commits automatically on success
  // Rolls back automatically on error
})

Operation Queuing

DexBee automatically prevents race conditions by queuing operations on the same record while allowing parallel execution across different records.

// Automatic queuing is enabled by default
const users = db.table('users')

// These operations on the same user execute sequentially (no race conditions)
await Promise.all([
  users.update(1, { count: users.count + 1 }),  // Executes first
  users.update(1, { status: 'active' })          // Executes second
])

// These operations on different users execute in parallel
await Promise.all([
  users.update(1, { count: 10 }),  // Parallel
  users.update(2, { count: 20 })   // Parallel
])

// Disable queuing if needed (not recommended for concurrent operations)
const usersUnqueued = db.table('users', { queueOperations: false })

Key Benefits:

  • 🚀 Parallel performance - Different records operate concurrently
  • 🔒 Data integrity - Same record operations are sequential
  • ⚙️ Configurable - Enable/disable via TableOptions.queueOperations
  • 🎯 Automatic - Works transparently without manual coordination

Schema Migrations

Import the migration plugin separately to keep your bundle size small:

import { DexBee } from 'dexbee-js'
import { withMigrations } from 'dexbee-js/migrations'

// Connect with your current schema
const db = await DexBee.connect('myapp', currentSchema)

// Add migration capabilities
const migratable = withMigrations(db)

// Define new schema with added fields
const newSchema: DatabaseSchema = {
  version: 2,
  tables: {
    users: {
      schema: {
        id: { type: 'number', required: true },
        name: { type: 'string', required: true },
        email: { type: 'string', required: false },
        avatar: { type: 'string', required: false }, // New field
        isActive: { type: 'boolean', default: true }, // New field
      },
      primaryKey: 'id',
      autoIncrement: true
    }
  }
}

// Preview migration with dry run
const dryRun = await migratable.dryRunMigration(newSchema)
console.log('Operations:', dryRun.operations)
console.log('Warnings:', dryRun.warnings)
console.log('Valid:', dryRun.isValid)

// Apply migration if safe
if (dryRun.isValid && dryRun.warnings.length === 0) {
  const result = await migratable.migrate(newSchema)
  console.log(`Migration completed: ${result.operationsExecuted} operations`)
}

See docs/migrations.md for detailed migration documentation.

Query Builder API

// Comparison operators
import { eq, gt, gte, lt, lte, between, in_, notIn } from 'dexbee-js'

// Logical operators  
import { and, or, not } from 'dexbee-js'

// Complex query example
const results = await users
  .select(['name', 'email', 'age']) // Select specific fields
  .where(
    and(
      or(
        between('age', 25, 35),
        in_('name', ['Alice', 'Bob', 'Charlie'])
      ),
      not(eq('email', '[email protected]'))
    )
  )
  .orderBy('name', 'asc')
  .orderBy('age', 'desc')
  .limit(20)
  .offset(10)
  .all()

// Blob-specific queries
import { sizeGt, sizeLt, mimeType, sizeBetween } from 'dexbee-js'

// Find large files
const largeFiles = await fileTable
  .where(sizeGt('content', 1024 * 1024)) // > 1MB
  .all()

// Find images within size range
const mediumImages = await fileTable
  .where(
    and(
      mimeType('content', 'image/jpeg'),
      sizeBetween('content', 100 * 1024, 500 * 1024) // 100KB - 500KB
    )
  )
  .all()

Blob Storage

DexBee provides comprehensive support for storing and retrieving binary data:

// Store files and blobs
const fileTable = db.table('documents')

// Insert with file/blob data
const file = new File(['Hello world'], 'document.txt', { type: 'text/plain' })
await fileTable.insertWithBlob(
  { title: 'My Document', createdAt: new Date() },
  { content: file }
)

// Update blob data
const newFile = new File(['Updated content'], 'document.txt')
await fileTable.updateBlob(1, 'content', newFile)

// Get blob metadata
const metadata = await fileTable.getBlobMetadata(1, 'content')
console.log(metadata) // { size: 15, type: 'text/plain', name: 'document.txt', ... }

// Create object URL (remember to revoke!)
const url = await fileTable.getBlobUrl(1, 'content')
// Use URL for downloads, previews, etc.
URL.revokeObjectURL(url) // Clean up memory

Tree Shaking & Bundle Size

DexBee is optimized for tree-shaking with separate entry points for different features:

| Import Pattern | Bundle Size (gzipped) | Use Case | |----------------|----------------------|----------| | Core only | ~34KB | Basic database operations | | With migrations | ~56KB | Apps with schema evolution | | Query-heavy | ~35KB | Read-heavy applications |

// Core only (~34KB) - Basic database operations
import { DexBee, eq, and } from 'dexbee-js'

// With migrations (~56KB) - When you need schema evolution
import { DexBee } from 'dexbee-js'
import { withMigrations } from 'dexbee-js/migrations'

const db = await DexBee.connect('mydb', schema)
const migratable = withMigrations(db)
await migratable.migrate(newSchema)

The migration system is in a separate entry point (dexbee-js/migrations) to keep the core bundle small. Only import migrations when you need them!

🔧 API Reference

Core Classes

  • DexBee - Main factory class for creating database instances
  • Database - Primary database interface
  • Table - Table-specific operations and queries
  • QueryBuilder - SQL-like query construction
  • TransactionWrapper - Transaction management

Query Operators

  • Comparison: eq, gt, gte, lt, lte, between, in_, notIn
  • Logical: and, or, not
  • Blob-specific: sizeGt, sizeLt, sizeBetween, mimeType

Migration Operations (from dexbee-js/migrations)

Import migrations separately to optimize bundle size:

import { withMigrations } from 'dexbee-js/migrations'
  • withMigrations(db) - Add migration capabilities to a Database instance
  • migrate(schema, options) - Apply schema migration
  • dryRunMigration(schema) - Preview migration without applying (recommended!)
  • getMigrationStatus() - Get current migration state

See docs/migrations.md for complete migration documentation.

🧪 Testing

DexBee includes comprehensive test coverage with both unit tests and browser integration tests:

Unit Tests

Run the standard test suite (uses fake-indexeddb for Node.js compatibility):

npm test

Browser Integration Tests

Run tests in real browsers with actual IndexedDB (essential for blob storage):

npm run test:integration:browser

Run All Tests

Execute both unit and browser integration tests:

npm run test:all

Test Coverage

Generate detailed coverage reports:

npm run test:coverage

Interactive Testing

Use the test UI for development:

# Unit test UI
npm run test:ui

# Browser test UI
npm run test:integration:browser:ui

Manual Browser Testing

For manual testing of blob storage and other browser-specific features, DexBee includes an interactive HTML test interface:

# Build the library first
npm run build

# Start a local server (choose one):
python3 -m http.server 8080
# OR
npx http-server -p 8080

# Open in browser
open http://localhost:8080/tests/manual/blob-test.html

The manual test interface allows you to test blob storage operations interactively in a real browser environment.

🤝 Contributing

Contributions are welcome! Please read our contributing guidelines before submitting PRs.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • Built with modern web standards and TypeScript
  • Inspired by modern ORM patterns and SQL query builders
  • Thanks to the IndexedDB specification and browser vendors

DexBee - Making IndexedDB sweet as honey 🍯