One SDK for your entire backend. Store JSON data, upload images, PDFs and files — all inside your Gmail account. Zero cost, no Supabase, no Cloudinary, no AWS S3. Just
npm install gmaildband you're done.
Developers today install multiple services for a single app:
- Supabase or MongoDB for database
- Cloudinary for image storage
- AWS S3 for file storage
- SendGrid for emails
GmailDB replaces all of it with one SDK and one Gmail account.
| Gmail | GmailDB |
|---|---|
| Label | Collection / Table |
| Record / Document | |
| Email Body | Encrypted JSON Data |
| Attachment | File Storage |
npm install gmaildbnpx gmaildb initThis automatically:
- Asks for your Google OAuth credentials
- Opens browser for authentication
- Creates
.envfile - Saves
token.json - Generates a starter example file
No manual configuration needed.
- Go to console.cloud.google.com
- Create a new project
- Go to APIs & Services → Library → Enable Gmail API
- Go to APIs & Services → Credentials → Create OAuth 2.0 Client ID
- Application type: Web application
- Add redirect URI:
http://localhost:3000/oauth/callback - Copy your Client ID and Client Secret
GOOGLE_CLIENT_ID=your_client_id
GOOGLE_CLIENT_SECRET=your_client_secret
GOOGLE_REDIRECT_URI=http://localhost:3000/oauth/callback
GMAILDB_SECRET=your_long_random_secret_keynpm run authimport { GmailDB } from 'gmaildb';
const db = new GmailDB();
await db.connect();
const users = db.collection('users');
// Insert one
await users.insert({ name: 'Aryan', age: 19, role: 'admin' });
// Insert many
await users.insertMany([
{ name: 'Alice', age: 25, role: 'admin' },
{ name: 'Bob', age: 30, role: 'user' },
]);
// Find all
const all = await users.find();
// Find with filter
const admins = await users.find({ role: 'admin' });
// Find with query operators
const adults = await users.find({ age: { $gte: 18 } });
const notAdmin = await users.find({ role: { $ne: 'admin' } });
const search = await users.find({ name: { $contains: 'ary' } });
const roles = await users.find({ role: { $in: ['admin', 'superadmin'] } });
// Find with pagination
const page1 = await users.find({}, { limit: 10, skip: 0 });
const page2 = await users.find({}, { limit: 10, skip: 10 });
// Find with sorting
const sorted = await users.find({}, { sort: { field: 'age', order: 'asc' } });
// Find with field projection
const names = await users.find({}, { fields: ['name', 'email'] });
// Find by ID — O(1) instant lookup
const user = await users.findById('abc-123');
// Find one
const one = await users.findOne({ name: 'Aryan' });
// Check if exists
const exists = await users.exists({ email: 'aryan@gmail.com' });
// Count
const total = await users.count();
const adminCount = await users.count({ role: 'admin' });
// Get distinct values
const uniqueRoles = await users.distinct('role');
// Update by ID — O(1) instant
await users.update({ _id: 'abc-123' }, { age: 20 });
// Update by filter
await users.update({ name: 'Aryan' }, { age: 20 });
// Update many
await users.updateMany({ role: 'user' }, { verified: true });
// Delete one
await users.deleteOne({ name: 'Aryan' });
// Delete by ID — O(1) instant
await users.deleteOne('abc-123');
// Delete many
await users.deleteMany({ role: 'user' });
// Delete all
await users.deleteAll();// Auto-delete after 1 day
await sessions.insert(
{ token: 'abc123', userId: 'user_1' },
{ ttl: 1 }
);
// Auto-delete after 7 days
await posts.insert(
{ title: 'Draft Post' },
{ ttl: 7 }
);
// Manually purge expired records
sessions.purgeExpired();import * as fs from 'fs';
const files = db.collection('files');
// Upload
const buffer = fs.readFileSync('photo.png');
const uploaded = await files.upload('photo.png', buffer, 'image/png');
console.log(uploaded.id);
// Download
const file = await files.getFile(uploaded.id);
fs.writeFileSync('downloaded.png', file.data);
// Store file reference inside a record
await notes.insert({
title: 'My Note',
content: 'Note with image',
imageId: uploaded.id,
});| Operator | Description | Example |
|---|---|---|
$gt |
Greater than | { age: { $gt: 18 } } |
$gte |
Greater than or equal | { age: { $gte: 18 } } |
$lt |
Less than | { age: { $lt: 30 } } |
$lte |
Less than or equal | { age: { $lte: 30 } } |
$ne |
Not equal | { role: { $ne: 'admin' } } |
$in |
In array | { role: { $in: ['admin', 'user'] } } |
$nin |
Not in array | { role: { $nin: ['guest'] } } |
$contains |
String contains | { name: { $contains: 'ary' } } |
$exists |
Field exists | { phone: { $exists: true } } |
GmailDB is fully typed. All methods have proper return types:
import type {
GmailDBDocument,
InsertResult,
InsertManyResult,
DeleteResult,
FindOptions,
InsertOptions,
UploadResult,
FileResult,
} from 'gmaildb';import {
ValidationError,
NotFoundError,
FileSizeError,
RateLimitError,
NetworkError,
TokenExpiredError,
StorageFullError,
InvalidCollectionError
} from 'gmaildb';
try {
await users.insert({});
} catch (err) {
if (err instanceof ValidationError) {
console.log('Bad data:', err.message);
}
if (err instanceof NotFoundError) {
console.log('Not found:', err.message);
}
if (err instanceof RateLimitError) {
console.log('Slow down:', err.message);
}
if (err instanceof TokenExpiredError) {
console.log('Re-authenticate:', err.message);
}
if (err instanceof NetworkError) {
console.log('Check internet:', err.message);
}
if (err instanceof FileSizeError) {
console.log('File too large:', err.message);
}
}- ✅ Setup CLI —
npx gmaildb init— zero manual setup for any new project - ✅ Full CRUD — insert, insertMany, find, findOne, findById, update, updateMany, delete, deleteMany, deleteAll
- ✅ exists() — check if record exists
- ✅ distinct() — get unique field values
- ✅ Field projection — return only specific fields
- ✅ File upload and download — images, PDFs, any file under 25MB
- ✅ AES-256 encryption — data encrypted before storing in Gmail
- ✅ TTL — auto expire records after X days
- ✅ SQLite O(1) index — instant lookup by _id at any scale
- ✅ SQLite local caching for fast reads
- ✅ Auto sync between Gmail and cache
- ✅ Rate limit handler with request queue
- ✅ Network retry with exponential backoff
- ✅ Token auto-refresh
- ✅ Pagination and sorting
- ✅ Query operators ($gt, $gte, $lt, $lte, $ne, $in, $nin, $contains, $exists)
- ✅ Batch operations — insertMany, deleteMany, deleteAll
- ✅ UUID-based record IDs
- ✅ Full TypeScript types
- ✅ JSDoc on every method
- ✅ Full error classes with error codes
- ✅ 21 unit and integration tests
- 25MB max file size (Gmail limit)
- Not suitable for high-traffic production apps
- Rate limited by Gmail API quotas
- No real-time updates (polling only)
- Setup CLI
- Full CRUD
- File upload and download
- AES-256 encryption
- TTL support
- SQLite caching and O(1) index
- Auto sync
- Rate limit handler
- Network retry
- Token auto-refresh
- Pagination, sorting, projection
- Query operators
- Batch operations
- Error handling
- Full TypeScript types
- JSDoc
- Unit and integration tests
- Binary file encryption
- Multi-user OAuth
- VS Code extension
- Demo website
- AI natural language queries
- Transactions
- Hooks (beforeInsert, afterInsert, beforeDelete)
- aggregate()
MIT