@rckflr/easydb-server
v0.4.0
Published
MongoDB-compatible server powered by EasyDB — use any backend (SQLite, PostgreSQL, Memory) with standard MongoDB clients
Maintainers
Readme
EasyDB Server
A MongoDB-compatible server powered by EasyDB. Connect with any standard MongoDB client and store data on your choice of backend.
mongosh ──┐
pymongo ──┤ ┌─────────┐
├── TCP:27017 ─│ EasyDB │── SQLite
Compass ──┤ │ Server │── PostgreSQL
├──────────────│ │── Memory
mongoose ─┘ └─────────┘── Redis, MySQL, Turso...Why?
FerretDB gives you MongoDB compatibility on PostgreSQL. EasyDB Server gives you MongoDB compatibility on any backend — SQLite, PostgreSQL, MySQL, Redis, in-memory, and more. One server, 10+ storage engines.
This project serves as a real-world showcase of EasyDB's universal storage abstraction.
Quick Start
# Run with in-memory storage (no persistence)
npx @rckflr/easydb-server
# Run with SQLite (persistent)
npx @rckflr/easydb-server --adapter sqlite --data ./mydata
# Then connect with mongosh
mongosh mongodb://localhost:27017// Or connect with the Node.js driver
import { MongoClient } from 'mongodb';
const client = new MongoClient('mongodb://localhost:27017');
await client.connect();
const db = client.db('test');
await db.collection('users').insertOne({ name: 'Alice', age: 30 });
const user = await db.collection('users').findOne({ name: 'Alice' });
console.log(user); // { _id: ObjectId('...'), name: 'Alice', age: 30 }Installation
npm install -g @rckflr/easydb-server
# SQLite support (recommended for persistent storage)
npm install -g @rckflr/easydb-server better-sqlite3
# PostgreSQL support
npm install -g @rckflr/easydb-server pgCLI Usage
easydb-server [options]
Options:
--port, -p <port> Port to listen on (default: 27017)
--host <host> Host to bind to (default: 0.0.0.0)
--adapter, -a <name> Storage backend (default: memory)
--data, -d <path> Data directory (for sqlite)
--connection-string <url> Database URL (for postgres)
--debug Enable debug logging
--quiet Only show warnings and errors
--help Show helpExamples
# In-memory (great for testing)
easydb-server
# SQLite with persistent storage
easydb-server --adapter sqlite --data ./data
# SQLite on a custom port
easydb-server -a sqlite -d ./data -p 27018
# PostgreSQL
easydb-server --adapter postgres --connection-string "postgresql://user:pass@localhost:5432/mydb"
# Debug mode (see every command)
easydb-server --adapter sqlite --data ./data --debugStorage Backends
| Backend | Flag | Persistence | Best For |
|---------|------|------------|----------|
| Memory | --adapter memory | No | Testing, development, CI |
| SQLite | --adapter sqlite --data ./path | Yes | Single-server, embedded, edge |
| PostgreSQL | --adapter postgres --connection-string "..." | Yes | Production, multi-tenant |
All backends are powered by EasyDB adapters and can be swapped with a single CLI flag — your application code doesn't change.
SQLite Persistence
Data is stored in per-collection .sqlite files:
./data/
├── _easydb_meta___global.sqlite # Collection registry
├── test.users.sqlite # db.users collection
├── test.products.sqlite # db.products collection
└── myapp.orders.sqlite # myapp.orders collectionCollections are automatically restored on server restart.
Compatibility
Supported Operations
| Operation | Status | Examples |
|-----------|--------|---------|
| insertOne / insertMany | Full | db.users.insertOne({name: "Alice"}) |
| find / findOne | Full | db.users.find({age: {$gt: 25}}) |
| updateOne / updateMany | Full | db.users.updateOne({name: "Alice"}, {$set: {age: 31}}) |
| deleteOne / deleteMany | Full | db.users.deleteOne({name: "Alice"}) |
| countDocuments | Full | db.users.countDocuments({role: "admin"}) |
| distinct | Full | db.users.distinct("role") |
| findOneAndUpdate | Full | db.users.findOneAndUpdate(filter, update, {returnDocument: "after"}) |
| findOneAndDelete | Full | db.users.findOneAndDelete({name: "Alice"}) |
| sort / skip / limit | Full | db.users.find().sort({age: -1}).skip(10).limit(5) |
| projection | Full | db.users.find({}, {name: 1, email: 1}) |
| aggregate | Basic | $match, $sort, $limit, $skip, $project, $group, $count, $unwind, $set |
| createIndex | Stub | Acknowledged but not enforced |
| show dbs / collections | Full | show dbs, show collections |
| drop / dropDatabase | Full | db.users.drop(), db.dropDatabase() |
Query Operators
| Category | Operators |
|----------|----------|
| Comparison | $eq $ne $gt $gte $lt $lte $in $nin |
| Logical | $and $or $not $nor |
| Element | $exists $type |
| Array | $size $all $elemMatch |
| Evaluation | $regex $mod |
| Implicit | {field: value} (exact match, works with arrays) |
Update Operators
| Operator | Description |
|----------|-------------|
| $set | Set field value |
| $unset | Remove field |
| $inc | Increment number |
| $mul | Multiply number |
| $min / $max | Set if less/greater than current |
| $push | Append to array (supports $each) |
| $pull | Remove from array |
| $addToSet | Append unique to array |
| $pop | Remove first/last from array |
| $rename | Rename field |
| $currentDate | Set to current date |
Aggregation Pipeline
| Stage | Status |
|-------|--------|
| $match | Full |
| $sort | Full |
| $skip / $limit | Full |
| $project | Full |
| $count | Full |
| $group | $sum, $avg, $min, $max, $push, $addToSet, $first, $last |
| $unwind | Full |
| $set / $addFields | Basic (field references only) |
| $lookup | Not supported |
| $facet | Not supported |
Not Supported
These MongoDB features are intentionally out of scope:
- Transactions (multi-document)
- Change streams
- Aggregation:
$lookup,$facet,$bucket,$graphLookup - Full-text search (
$text) - Geospatial queries
- Authentication (SCRAM-SHA-256)
- Replication / Sharding
- GridFS
- Wire compression
Architecture
┌─────────────────────────────────────────┐
│ MongoDB Client │
└──────────────┬──────────────────────────┘
│ TCP (MongoDB Wire Protocol)
│ OP_MSG + OP_QUERY (BSON)
▼
┌─────────────────────────────────────────┐
│ EasyDB Server │
│ │
│ Wire Protocol ─→ Command Router │
│ │ │
│ ┌───────┼────────┐ │
│ ▼ ▼ ▼ │
│ Handshake CRUD Admin │
│ │ │
│ Query Engine │
│ (matcher + updater) │
│ │ │
│ DatabaseManager │
│ │ │
│ EasyDB Core │
│ .put() .get() .where() │
└──────────────┬──────────────────────────┘
│
┌───────┼───────┐
▼ ▼ ▼
SQLite Postgres Memory ...Use Cases
- Development: Drop-in MongoDB replacement that requires zero setup
- Testing: Ephemeral in-memory database for CI/CD pipelines
- Edge/Embedded: Run a MongoDB-compatible database on devices with SQLite
- Prototyping: Start with SQLite, switch to PostgreSQL for production
- Learning: Understand how MongoDB wire protocol works under the hood
Docker
# Build
docker build -t easydb-server .
# Run with in-memory
docker run -p 27017:27017 easydb-server
# Run with SQLite persistence
docker run -p 27017:27017 -v ./data:/data easydb-server \
--adapter sqlite --data /dataOr with docker-compose:
services:
easydb:
build: .
ports:
- "27017:27017"
volumes:
- ./data:/data
command: ["--adapter", "sqlite", "--data", "/data"]Comparison with Alternatives
| Feature | EasyDB Server | FerretDB | MongoDB | |---------|:------------:|:--------:|:-------:| | Storage backends | 10+ | 2 | 1 | | SQLite backend | Yes | Yes | No | | PostgreSQL backend | Yes | Yes | No | | MySQL/Redis/KV backend | Yes | No | No | | In-memory mode | Yes | No | No | | Zero config startup | Yes | No | Yes | | npm installable | Yes | No | No | | Docker image size | ~50MB | ~100MB | ~700MB | | CRUD operations | Full | Full | Full | | Aggregation | Basic | Most | Full | | Transactions | No | Partial | Full | | Auth/TLS | No | Yes | Full | | License | MIT | Apache 2.0 | SSPL |
Contributing
PRs welcome! See SPEC.md for the full technical specification.
License
MIT
