coffeeql
v0.3.0
Published
CoffeeQL — The query language for structured and unstructured data
Maintainers
Readme
☕ CoffeeQL
One query language. Every database.
CoffeeQL is a universal query orchestration layer. Write one expressive, chain-based query and run it seamlessly across PostgreSQL, MongoDB, MySQL, and Redis. Powered by a blazing-fast Rust engine compiled to WebAssembly, executing natively via standard Node.js database drivers.
✨ Why CoffeeQL?
Most modern applications talk to three or more databases. You end up writing raw SQL for Postgres, Mongoose schemas for MongoDB, and ioredis commands for Redis—battling three different APIs, mental models, and error-handling patterns.
CoffeeQL abstracts this friction. It provides one unified syntax that compiles down to the exact query required for each underlying database, with a Rust-powered WASM engine handling the heavy lifting of parsing and query planning across Node.js, the browser, or the edge. No pg. No mongodb. No mysql2. No ioredis. Just CoffeeQL.
| Problem | Without CoffeeQL | With CoffeeQL |
|---|---|---|
| Query PostgreSQL | SELECT name FROM users WHERE plan = $1 | users[].where(plan = "pro").give(name) |
| Query MongoDB | db.products.find({ category: "coffee" }) | products{}.where(category = "coffee") |
| Cross-DB JOIN | Impossible in one query | users[].mix(products{} ON users[].id = products{}.user_id) |
| Switch databases | Rewrite all queries | Change adapter config |
| Geo search | PostGIS extension | .where(location.near(28.6, 77.2, 5km)) |
| AI similarity | pgvector extension | .where(embed.like("espresso machine").threshold(0.85)) |
📦 Installation
npm install coffeeqlPeer dependencies — install only the native drivers for the databases you intend to use:
npm install pg # PostgreSQL
npm install mongodb # MongoDB
npm install mysql2 # MySQL
npm install ioredis # Redis📖 The Syntax & The Two Brackets
CoffeeQL uses a highly readable, chain-based syntax designed to feel natural at a glance. It uses two bracket types to distinguish database architectures:
users[]→ Structured → PostgreSQL, MySQL, SQLiteproducts{}→ Unstructured → MongoDBsession:id{}→ Key-Value → Redis (namespace:key pattern)
The same query methods work seamlessly across all of them:
# PostgreSQL
users[].where(plan = "pro").give(name, email).cup(10)
# MongoDB — identical syntax
products{}.where(category = "coffee").give(name, price).cup(10)
# Redis
session:usr_001{}.give(*)🚀 Quick Start & Federation
Initialize your adapters and run queries with a single, unified client.
import { CoffeeQL, PostgresAdapter, MongoAdapter } from 'coffeeql'
const db = new CoffeeQL({
adapters: {
'users[]': new PostgresAdapter({ uri: process.env.PG_URI }),
'products{}': new MongoAdapter({ uri: process.env.MONGO_URI, db: 'shop' }),
}
})
await db.connect()
// Cross-adapter JOIN — PostgreSQL + MongoDB in one query!
const result = await db.query(`
users[]
.where(plan = "pro", active = true)
.mix(products{} ON users[].id = products{}.user_id)
.give(users[].name, products{}.title, products{}.price)
.sort(products{}.price, DESC)
.cup(10)
`)
console.log(result.rows)🔍 Query Reference
Reading Data
# Filter — comma = AND, pipe = OR
users[].where(plan = "pro", active = true)
users[].where(plan = "pro" | plan = "team")
# Select fields & Limit (.cup)
users[].give(name, email, balance).cup(10)
# Sort
users[].sort(balance, DESC)Writing Data (Mutations)
# Insert — .pour()
users[].pour({
id: uuid(), // Built-in auto-generator
name: "Rahul Sharma",
email: "[email protected]",
date: today(), // Built-in date
balance: 2500.00
})
# Update — .refill()
users[].where(email = "[email protected]").refill({ balance: 5000.00 })
# Delete — .spill()
users[].where(email = "[email protected]").spill()Aggregation
# Group + aggregate (Works on SQL and MongoDB)
orders[]
.where(status = "completed")
.blend(city)
.give(city, COUNT() as orders, SUM(total) as revenue, AVG(total) as avg)
.sort(revenue, DESC)Geo Search & AI Similarity
# Find within radius — m, km, mi
cafes[].where(location.near(28.6139, 77.2090, 5km)).give(name, rating).cup(10)
# Vector similarity — 0 to 1 threshold
products{}
.where(embed.like("dark roast espresso machine").threshold(0.85))
.give(name, price)
.cup(5)Time Windows & Array Filtering
# Recency filter — s, m, h, d, w, mo, y
events{}.where(created_at.last(7d))
logs{}.where(ts.last(1h), level = "error")
# Array contains
products{}.where(tags.has("espresso"))🏗️ Schema — Grind & Menu
# Define structured collection for SQL
grind users[] (
id UUID PRIMARY,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
age INT,
balance FLOAT,
active BOOL,
joined_at DATETIME,
location GEOPOINT,
embedding VECTOR
)
# Define unstructured — no schema needed
grind products{}
# Inspect schema
menu() # list all collections
menu(users[]) # show schema of users🧠 Advanced Features
🛡️ Resiliency & Transactions
Built for the real world, where networks drop and databases stall.
// Fail fast if a DB is slow
await db.query('users[].cup(100)').timeout(3000).run()
// Retry automatically on flaky connections
await db.query('products{}.where(active = true)').retry(3).run()
// Accept partial results if a federated node fails
await db.query('users[].mix(products{} ON ...)').partial().run()
// Atomic Transaction (Executes sequentially, rolling back where supported)
await db.query(`
shot {
users[].where(id = "u1").refill({ balance: balance - 500 })
/
users[].where(id = "u2").refill({ balance: balance + 500 })
}
`)🔬 Explain API (Zero Dependencies)
Inspect execution plans before hitting any database.
const plan = db.explain(`
users[]
.where(plan = "pro")
.mix(products{} ON users[].id = products{}.user_id)
.cup(10)
`)
console.log(plan.render())Output:
// CoffeeQL Execution Plan
// Query: users[].mix(products{} ON ...).cup(10)
//
// Step 1 → PostgreSQL SCAN users[] WHERE plan='pro'
// Step 2 → MongoDB SCAN products{}
// Step 3 → Memory HASH JOIN ON users[].id = products{}.user_id
// Step 4 → Memory LIMIT 10
//
// Adapters: 2 · Strategy: in-memory hash join · Concurrent fetch: yes⚡ Parse-only mode (WASM)
If you only need query validation or planning without execution, running natively in Node, Deno, Bun, or the Browser:
import { coffeeql, isValid } from 'coffeeql'
isValid('users[].where(age > 18).cup(10)') // → true
const result = coffeeql('users[].where(plan = "pro").cup(10)')
console.log(result.plan) // execution plan string🔌 Supported Adapters
CoffeeQL natively maps to the most trusted Node.js database drivers.
- PostgresAdapter: Works with Supabase, Neon, AWS RDS, Railway, local PostgreSQL.
- MongoAdapter: Works with MongoDB Atlas, self-hosted, Docker.
- MySQLAdapter: Works with PlanetScale, AWS RDS MySQL, self-hosted. (Auto-handles booleans and UUIDs).
- RedisAdapter: Works with Redis Cloud, Upstash, self-hosted.
import { CoffeeQL, PostgresAdapter, MongoAdapter, MySQLAdapter, RedisAdapter } from 'coffeeql'
const db = new CoffeeQL({
adapters: {
'users[]': new PostgresAdapter({ uri: PG_URI }),
'products{}': new MongoAdapter({ uri: MONGO_URI, db: 'shop' }),
'inventory[]': new MySQLAdapter({ uri: MYSQL_URI }),
'session:{}': new RedisAdapter({ uri: REDIS_URI }),
}
})⚙️ Architecture Layer
The Rust core is the exact same engine that powers the Python pip package—guaranteeing 100% parity across languages for parsing, planning, and explain outputs.
graph TD;
A[Your CoffeeQL Query] -->|String| B(Rust Engine via WASM);
B -->|Parse & Plan - Runs Anywhere| C(Adapter Layer);
C -->|Routes to Target| D{Native Node Drivers};
D -->|node-postgres| E[(PostgreSQL)];
D -->|mongodb| F[(MongoDB)];
D -->|mysql2| G[(MySQL)];
D -->|ioredis| H[(Redis)];
E & F & G & H --> I[Real Rows Returned];📚 Language Reference
All Keywords
| Keyword | What it does |
|---|---|
| collection[] | Structured collection — SQL |
| collection{} | Unstructured collection — Document |
| ns:key{} | Redis key-value hash |
| .where() | Filter records |
| .give() | Select fields |
| .sort() | Order results |
| .cup() | Limit results |
| .blend() | Group by field |
| .mix() | Join two collections |
| .pour() | Insert record |
| .refill() | Update records |
| .spill() | Delete records |
| grind | Define collection schema |
| menu() | List / inspect collections |
| shot{} | Atomic transaction block |
All Operators
| Operator | Meaning | Example |
|---|---|---|
| = | Equal | plan = "pro" |
| != | Not equal | status != "cancelled" |
| > | Greater than | balance > 1000 |
| < | Less than | price < 500 |
| >= | Greater or equal | age >= 18 |
| <= | Less or equal | age <= 65 |
| , | AND | active = true, age > 18 |
| \| | OR | city = "Delhi" \| city = "Mumbai" |
| ! | NOT | !active |
| EXISTS | Field is not null | brand EXISTS |
📦 What's in v0.3.0
db.explain(cql)— Human-readable execution plans..timeout(ms),.retry(n),.partial()— Resiliency modifiers.- Cross-adapter federation (Experimental) — PostgreSQL + MongoDB in one query.
- Full test suite — 265 tests across 4 real databases.
🤝 Contributing & Issues
CoffeeQL is an open-source initiative released under the MIT License. We welcome contributions from the community to help expand our adapter ecosystem and refine the engine.
- GitHub: KhushviB/coffeeql
- npm: npmjs.com/package/coffeeql
- pip: crates.io/crates/coffeeql (Written in Rust)
Made with ☕ by Khushvi Bamrolia Checkout Khushvi's Github
