The Memory driver has been refactored to use Mingo (MongoDB query engine for in-memory objects) for query processing, while maintaining full backward compatibility with the existing Driver interface from @objectql/types. This brings MongoDB-like query capabilities to the in-memory driver.
Package Version: 4.0.0
DriverInterface Version: v4.0 compliant
Completion Date: January 23, 2026
Status: ✅ Fully compliant with DriverInterface v4.0 and Mingo-powered
The driver now uses Mingo for query processing, which provides:
- MongoDB Query Operators: Full support for MongoDB query syntax
- High Performance: Optimized query execution for in-memory data
- Standard Compliance: MongoDB-compatible query semantics
Mingo is a MongoDB query language for in-memory JavaScript objects. It brings the power of MongoDB queries to client-side and server-side JavaScript applications without requiring a MongoDB server.
- Consistency: Same query syntax as MongoDB
- Expressiveness: Rich query operators ($gt, $lt, $in, $regex, etc.)
- Reliability: Well-tested MongoDB query semantics
- Performance: Optimized for in-memory operations
The driver now exposes metadata for ObjectStack compatibility:
const driver = new MemoryDriver(config);
console.log(driver.name); // 'MemoryDriver'
console.log(driver.version); // '3.0.1'
console.log(driver.supports); // { transactions: false, joins: false, ... }The new standard method for query execution using the ObjectStack QueryAST format:
import { MemoryDriver } from '@objectql/driver-memory';
const driver = new MemoryDriver();
// Using QueryAST format
const result = await driver.executeQuery({
object: 'users',
fields: ['id', 'name', 'email'],
filters: {
type: 'comparison',
field: 'active',
operator: '=',
value: true
},
sort: [{ field: 'name', order: 'asc' }],
top: 10,
skip: 0
});
console.log(result.value); // Array of user records
console.log(result.count); // Number of records returnedUnified interface for all mutation operations:
// Create a record
const createResult = await driver.executeCommand({
type: 'create',
object: 'users',
data: { name: 'Alice', email: 'alice@example.com' }
});
// Update a record
const updateResult = await driver.executeCommand({
type: 'update',
object: 'users',
id: 'user-123',
data: { email: 'alice.new@example.com' }
});
// Delete a record
const deleteResult = await driver.executeCommand({
type: 'delete',
object: 'users',
id: 'user-123'
});
// Bulk create
const bulkCreateResult = await driver.executeCommand({
type: 'bulkCreate',
object: 'users',
records: [
{ name: 'Bob', email: 'bob@example.com' },
{ name: 'Charlie', email: 'charlie@example.com' }
]
});
console.log(createResult.success); // true
console.log(createResult.affected); // 1
console.log(createResult.data); // Created recordThe driver now supports both legacy and QueryAST formats:
const query = {
fields: ['name', 'age'],
filters: [['age', '>', 18]],
sort: [['name', 'asc']],
limit: 10,
skip: 0
};
const results = await driver.find('users', query);const query = {
object: 'users',
fields: ['name', 'age'],
filters: {
type: 'comparison',
field: 'age',
operator: '>',
value: 18
},
sort: [{ field: 'name', order: 'asc' }],
top: 10, // Instead of 'limit'
skip: 0
};
const result = await driver.executeQuery(query);
// or
const results = await driver.find('users', query);| Aspect | Legacy Format | QueryAST Format |
|---|---|---|
| Limit | limit: 10 |
top: 10 |
| Sort | [['field', 'dir']] |
[{field, order}] |
| Filters | Array format | FilterNode AST |
The driver uses a normalization layer that automatically converts QueryAST format to the internal format. This means:
- ✅ Existing code continues to work without changes
- ✅ New code can use QueryAST format
- ✅ Both formats work interchangeably
- ✅ No breaking changes
- ✅ 100% backward compatible
import { MemoryDriver } from '@objectql/driver-memory';
const driver = new MemoryDriver({
initialData: {
users: [
{ id: '1', name: 'Alice', age: 30 },
{ id: '2', name: 'Bob', age: 25 }
]
}
});
// Create
const user = await driver.create('users', {
name: 'Charlie',
age: 28
});
// Read
const users = await driver.find('users', {
filters: [['age', '>=', 25]]
});
// Update
await driver.update('users', '1', { age: 31 });
// Delete
await driver.delete('users', '2');
// Count
const count = await driver.count('users', []);import { MemoryDriver } from '@objectql/driver-memory';
const driver = new MemoryDriver();
// Query with executeQuery
const result = await driver.executeQuery({
object: 'users',
filters: {
type: 'and',
children: [
{
type: 'comparison',
field: 'age',
operator: '>=',
value: 25
},
{
type: 'comparison',
field: 'active',
operator: '=',
value: true
}
]
},
sort: [
{ field: 'name', order: 'asc' }
],
top: 20
});
// Command execution
const result = await driver.executeCommand({
type: 'bulkUpdate',
object: 'users',
updates: [
{ id: '1', data: { status: 'active' } },
{ id: '2', data: { status: 'inactive' } }
]
});import { ObjectQL } from '@objectql/core';
import { MemoryDriver } from '@objectql/driver-memory';
const app = new ObjectQL({
datasources: {
default: new MemoryDriver({
initialData: {
projects: [
{ id: '1', name: 'Project A', status: 'active' }
]
}
})
}
});
await app.init();
// The core will use the driver's new interface internally
const ctx = app.createContext({ userId: 'user123' });
const repo = ctx.object('projects');
const projects = await repo.find({
filters: [['status', '=', 'active']]
});The driver includes comprehensive test coverage:
cd packages/drivers/memory
npm testTest coverage includes:
- Driver metadata exposure (name, version, supports)
- Lifecycle methods (connect, checkHealth, disconnect)
- Legacy CRUD operations (backward compatibility)
- QueryAST format with
topparameter - Object-based sort notation
- FilterNode AST support
- executeQuery method
- executeCommand method with all operation types
- Bulk operations (create, update, delete)
- Error handling and edge cases
Test Results: ✅ All tests passing (~75% code coverage)
package.json: Added@objectstack/spec@^0.2.0dependencysrc/index.ts:- Added DriverInterface implementation
- Added
executeQuery()method (~35 lines) - Added
executeCommand()method (~100 lines) - Added
convertFilterNodeToLegacy()helper (~60 lines) - Added
execute()stub for compatibility - Added Command and CommandResult interfaces
- Added: ~200 lines (new methods and interfaces)
- Modified: ~15 lines (imports and class declaration)
- Deleted: 0 lines
The Memory driver supports:
- Transactions: ❌ No (in-memory, atomic operations only)
- Joins: ❌ No (single-table queries)
- Full-Text Search: ❌ No (simple string matching via filters)
- JSON Fields: ✅ Yes (JavaScript objects)
- Array Fields: ✅ Yes (JavaScript arrays)
The Memory driver is perfect for:
- Unit Testing: No database setup required
- Development & Prototyping: Quick iteration without database overhead
- Edge/Worker Environments: Cloudflare Workers, Deno Deploy
- Client-Side State Management: Browser applications
- Temporary Data Caching: Short-lived data storage
- Demo Applications: Examples and showcases
- Zero External Dependencies: No database connection overhead
- In-Memory Storage: Extremely fast read/write operations
- No I/O Overhead: All operations are synchronous internally
- Linear Search: O(n) for filtering (acceptable for small datasets)
- No Persistence: Data is lost when process terminates
Recommended Dataset Size: < 10,000 records per object
100% backward compatible - all existing code using the Memory driver will continue to work without any changes. The DriverInterface support is additive, not replacing.
| Feature | v3.0.1 (before) | v3.0.1 (current) | Notes |
|---|---|---|---|
| Legacy find() | ✅ | ✅ | Unchanged |
| Legacy create() | ✅ | ✅ | Unchanged |
| Legacy update() | ✅ | ✅ | Unchanged |
| Legacy delete() | ✅ | ✅ | Unchanged |
| executeQuery() | ❌ | ✅ | New - DriverInterface v4.0 |
| executeCommand() | ❌ | ✅ | New - DriverInterface v4.0 |
| QueryAST support | ❌ | ✅ | New - DriverInterface v4.0 |
Simply update your package.json:
{
"dependencies": {
"@objectql/driver-memory": "^3.0.1"
}
}All existing code will continue to work.
If you want to use the new features:
// Before (legacy API - still works)
const users = await driver.find('users', {
filters: [['active', '=', true]],
limit: 10
});
// After (DriverInterface v4.0) - Using executeQuery
const result = await driver.executeQuery({
object: 'users',
filters: {
type: 'comparison',
field: 'active',
operator: '=',
value: true
},
top: 10
});
const users = result.value;Solution: Ensure you have @objectstack/spec@^0.2.0 installed:
npm install @objectstack/spec@^0.2.0Solution: Clear node_modules and reinstall:
rm -rf node_modules package-lock.json
npm installSolution: Memory driver is optimized for small datasets (<10k records). For larger datasets, use a database-backed driver like driver-sql or driver-mongo.
With Memory driver DriverInterface v4.0 compliance complete, the migration pattern is established for other drivers:
- ✅ SQL Driver (completed - DriverInterface v4.0)
- ✅ Memory Driver (completed - DriverInterface v4.0)
- ✅ MongoDB Driver (completed - DriverInterface v4.0)
- 🔜 Redis Driver
- 🔜 FS Driver
- 🔜 LocalStorage Driver
- 🔜 Excel Driver
- 🔜 SDK Driver
Note: All drivers maintain package version 3.0.1 due to changeset fixed group constraints.
- ObjectStack Spec Package
- SQL Driver Migration Guide
- MongoDB Driver Migration Guide
- Driver Interface Documentation
- DriverInterface Specification
For questions or issues:
- GitHub Issues: https://github.com/objectstack-ai/objectql/issues
- Documentation: https://objectql.org/docs
- Community: https://objectql.org/community
Last Updated: January 23, 2026
Package Version: 3.0.1
DriverInterface Version: v4.0 compliant
Specification: @objectstack/spec@0.2.0