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-memory

v4.2.2

Published

In-memory driver for ObjectQL - Fast MongoDB-like query engine powered by Mingo with DriverInterface v4.0 compliance

Readme

Memory Driver for ObjectQL

Production-Ready - A high-performance in-memory driver powered by Mingo for testing, development, and edge environments.

Overview

The Memory Driver is a production-ready implementation of the ObjectQL Driver interface that stores data in JavaScript Maps and uses Mingo (MongoDB query engine for in-memory objects) for query processing. It provides full MongoDB-like query support with high performance, making it ideal for scenarios where persistence is not required.

Features

  • MongoDB Query Engine - Powered by Mingo for MongoDB-compatible queries
  • Full Query Support - Filters, sorting, pagination, field projection
  • High Performance - No I/O overhead, all operations in-memory
  • Bulk Operations - createMany, updateMany, deleteMany
  • Thread-Safe - Safe for concurrent operations
  • Strict Mode - Optional error throwing for missing records
  • Initial Data - Pre-populate on initialization
  • TypeScript - Full type safety and IntelliSense support

Use Cases

This driver is perfect for:

  1. Unit Testing - No database setup required, instant cleanup
  2. Development & Prototyping - Quick iteration without infrastructure
  3. Edge Environments - Cloudflare Workers, Deno Deploy, Vercel Edge
  4. Client-Side State - Browser-based applications
  5. Temporary Caching - Short-lived data storage
  6. CI/CD Pipelines - Fast tests without database dependencies

Installation

# Using pnpm (recommended)
pnpm add @objectql/driver-memory

# Using npm
npm install @objectql/driver-memory

# Using yarn
yarn add @objectql/driver-memory

Or if you're using the ObjectQL monorepo:

pnpm add @objectql/driver-memory

Basic Usage

import { ObjectQL } from '@objectql/core';
import { MemoryDriver } from '@objectql/driver-memory';

// Initialize the driver
const driver = new MemoryDriver();

// Create ObjectQL instance
const app = new ObjectQL({
  datasources: { default: driver }
});

// Register your schema
app.registerObject({
  name: 'users',
  fields: {
    name: { type: 'text', required: true },
    email: { type: 'email', unique: true },
    role: { type: 'select', options: ['admin', 'user'] }
  }
});

await app.init();

// Use it!
const ctx = app.createContext({ isSystem: true });
const repo = ctx.object('users');

// Create
const user = await repo.create({
  name: 'Alice',
  email: '[email protected]',
  role: 'admin'
});

// Find
const users = await repo.find({
  filters: [['role', '=', 'user']]
});

// Update
await repo.update(user.id, { email: '[email protected]' });

// Delete
await repo.delete(user.id);

Browser Usage

The Memory Driver works seamlessly in web browsers! Perfect for prototyping, client-side apps, and offline experiences.

Quick Start in Browser

<!DOCTYPE html>
<html>
<head>
    <title>ObjectQL in Browser</title>
</head>
<body>
    <h1>ObjectQL Browser Demo</h1>
    <script type="module">
        import { ObjectQL } from '@objectql/core';
        import { MemoryDriver } from '@objectql/driver-memory';
        
        // Initialize
        const driver = new MemoryDriver();
        const app = new ObjectQL({
            datasources: { default: driver }
        });
        
        // Define schema
        app.registerObject({
            name: 'tasks',
            fields: {
                title: { type: 'text', required: true },
                completed: { type: 'boolean', defaultValue: false }
            }
        });
        
        await app.init();
        
        // Use it!
        const ctx = app.createContext({ isSystem: true });
        const tasks = ctx.object('tasks');
        
        await tasks.create({ title: 'Learn ObjectQL in Browser!' });
        const allTasks = await tasks.find({});
        console.log('Tasks:', allTasks);
    </script>
</body>
</html>

Interactive Browser Demo

See the examples in the repository for interactive demonstrations.

  • 🎨 Beautiful UI with live CRUD operations
  • 🖥️ Browser console debugging
  • 📊 Real-time statistics
  • ✨ Sample data generation

Browser Compatibility

  • ✅ Chrome/Edge 90+
  • ✅ Firefox 88+
  • ✅ Safari 14+
  • ✅ All modern browsers with ES6+ support

Browser vs Node.js

| Feature | Browser | Node.js | |---------|---------|---------| | Performance | ⚡ Fast | ⚡ Fast | | Persistence | ❌ Lost on refresh | ❌ Lost on process exit | | Use Case | Prototyping, Client state | Testing, Dev, Edge | | Data Limit | RAM (GB) | RAM (GB) |

For persistent browser storage, use the LocalStorage Driver.

Configuration Options

Basic Configuration

const driver = new MemoryDriver();

With Initial Data

const driver = new MemoryDriver({
  initialData: {
    users: [
      { id: '1', name: 'Alice', email: '[email protected]' },
      { id: '2', name: 'Bob', email: '[email protected]' }
    ],
    posts: [
      { id: '1', title: 'Hello World', author_id: '1' }
    ]
  }
});

With Strict Mode

const driver = new MemoryDriver({
  strictMode: true  // Throws errors for missing records
});

// This will throw an error instead of returning null
await driver.update('users', 'non-existent-id', { name: 'Test' });
// ObjectQLError: Record with id 'non-existent-id' not found in 'users'

API Reference

Core Methods

All methods implement the standard Driver interface from @objectql/types:

find(objectName, query, options)

Find multiple records with optional filtering, sorting, and pagination.

const users = await driver.find('users', {
  filters: [
    ['role', '=', 'admin'],
    'or',
    ['age', '>', 30]
  ],
  sort: [['name', 'asc']],
  skip: 0,
  limit: 10,
  fields: ['name', 'email']
});

findOne(objectName, id, query, options)

Find a single record by ID or query.

// By ID
const user = await driver.findOne('users', 'user-123');

// By query
const admin = await driver.findOne('users', null, {
  filters: [['role', '=', 'admin']]
});

create(objectName, data, options)

Create a new record.

const user = await driver.create('users', {
  name: 'Alice',
  email: '[email protected]'
});
// Returns: { id: 'users-1234567890-1', name: 'Alice', ... }

update(objectName, id, data, options)

Update an existing record.

const updated = await driver.update('users', 'user-123', {
  email: '[email protected]'
});

delete(objectName, id, options)

Delete a record.

const deleted = await driver.delete('users', 'user-123');
// Returns: true if deleted, false if not found

count(objectName, filters, options)

Count records matching filters.

const adminCount = await driver.count('users', [
  ['role', '=', 'admin']
]);

Bulk Operations

createMany(objectName, data, options)

Create multiple records at once.

const users = await driver.createMany('users', [
  { name: 'Alice' },
  { name: 'Bob' },
  { name: 'Charlie' }
]);

updateMany(objectName, filters, data, options)

Update all records matching filters.

const result = await driver.updateMany(
  'users',
  [['role', '=', 'user']],
  { status: 'active' }
);
// Returns: { modifiedCount: 5 }

deleteMany(objectName, filters, options)

Delete all records matching filters.

const result = await driver.deleteMany('users', [
  ['status', '=', 'inactive']
]);
// Returns: { deletedCount: 3 }

Advanced Operations

distinct(objectName, field, filters, options)

Get unique values for a field.

const roles = await driver.distinct('users', 'role');
// Returns: ['admin', 'user', 'moderator']

Utility Methods

clear()

Remove all data from the store.

await driver.clear();

getSize()

Get the total number of records in the store.

const size = driver.getSize();
// Returns: 42

disconnect()

Gracefully disconnect (no-op for memory driver).

await driver.disconnect();

Supported Query Operators

The Memory Driver supports all standard ObjectQL query operators:

Comparison Operators

  • =, == - Equals
  • !=, <> - Not equals
  • > - Greater than
  • >= - Greater than or equal
  • < - Less than
  • <= - Less than or equal

Set Operators

  • in - Value in array
  • nin, not in - Value not in array

String Operators

  • contains, like - Contains substring (case-insensitive)
  • startswith, starts_with - Starts with string
  • endswith, ends_with - Ends with string

Range Operators

  • between - Value between two values (inclusive)

Logical Operators

  • and - Logical AND (default)
  • or - Logical OR

Query Examples

Simple Filter

const admins = await driver.find('users', {
  filters: [['role', '=', 'admin']]
});

Multiple Filters (AND)

const activeAdmins = await driver.find('users', {
  filters: [
    ['role', '=', 'admin'],
    'and',
    ['status', '=', 'active']
  ]
});

OR Filters

const results = await driver.find('users', {
  filters: [
    ['role', '=', 'admin'],
    'or',
    ['permissions', 'contains', 'manage_users']
  ]
});

Range Queries

const middleAged = await driver.find('users', {
  filters: [['age', 'between', [30, 50]]]
});

Sorting

const sorted = await driver.find('users', {
  sort: [
    ['role', 'asc'],
    ['created_at', 'desc']
  ]
});

Pagination

// Get page 2 with 10 items per page
const page2 = await driver.find('users', {
  skip: 10,
  limit: 10,
  sort: [['created_at', 'desc']]
});

Field Projection

const names = await driver.find('users', {
  fields: ['id', 'name', 'email']
});
// Returns only id, name, and email fields

Testing with Memory Driver

The Memory Driver is ideal for unit tests:

import { MemoryDriver } from '@objectql/driver-memory';

describe('User Service', () => {
  let driver: MemoryDriver;

  beforeEach(() => {
    driver = new MemoryDriver({
      initialData: {
        users: [
          { id: '1', name: 'Test User', role: 'user' }
        ]
      }
    });
  });

  afterEach(async () => {
    await driver.clear();
  });

  it('should find users by role', async () => {
    const users = await driver.find('users', {
      filters: [['role', '=', 'user']]
    });
    expect(users).toHaveLength(1);
  });
});

Performance Characteristics

  • Create: O(1)
  • Read by ID: O(1)
  • Update: O(1)
  • Delete: O(1)
  • Find/Query: O(n) - Scans all records for the object type
  • Count: O(n) - Scans all matching records
  • Sort: O(n log n)

Performance Tips

  1. Use specific filters - More filters reduce the result set faster
  2. Limit results - Use limit to avoid processing large result sets
  3. Clear regularly - Call clear() to free memory in long-running processes
  4. Consider size - Memory driver is best for < 10,000 records per object type

Comparison with Other Drivers

| Feature | Memory | SQL | MongoDB | Redis | |---------|--------|-----|---------|-------| | Setup Required | ❌ None | ✅ Database | ✅ Database | ✅ Redis Server | | Persistence | ❌ No | ✅ Yes | ✅ Yes | ✅ Yes | | Performance | ⚡ Fastest | 🐢 Slower | 🏃 Fast | 🏃 Fast | | Query Support | ✅ Full | ✅ Full | ✅ Full | ⚠️ Limited | | Production Ready | ✅ Yes* | ✅ Yes | ✅ Yes | ⚠️ Example | | Dependencies | 0 | 2-3 | 1 | 1 |

*For use cases where persistence is not required

Limitations

  1. No Persistence - Data is lost when the process ends
  2. Memory Bound - Limited by available RAM
  3. Single Instance - No distribution or clustering
  4. No Transactions - Operations are individual (though atomic)
  5. Linear Scans - Queries scan all records (no indexes)

Migration Guide

From Redis Driver to Memory Driver

// Before
import { RedisDriver } from '@objectql/driver-redis';
const driver = new RedisDriver({ url: 'redis://localhost:6379' });

// After
import { MemoryDriver } from '@objectql/driver-memory';
const driver = new MemoryDriver();

From SQL Driver to Memory Driver (for testing)

// Production
const driver = new SqlDriver({
  client: 'pg',
  connection: process.env.DATABASE_URL
});

// Testing
const driver = new MemoryDriver({
  initialData: {
    users: [/* test data */],
    posts: [/* test data */]
  }
});

Troubleshooting

Out of Memory Errors

// Problem: Too much data
const driver = new MemoryDriver();
// ... add millions of records

// Solution: Clear periodically or use a persistent driver
await driver.clear();

Slow Queries

// Problem: Scanning large datasets
const results = await driver.find('users', {}); // Returns 100,000 records

// Solution: Add filters and limits
const results = await driver.find('users', {
  filters: [['status', '=', 'active']],
  limit: 100
});

Related Documentation

Contributing

Found a bug or have a feature request? Please open an issue on GitHub.

License

MIT - Same as ObjectQL

Changelog

See CHANGELOG.md for version history.