This guide covers building custom storage adapters for NebulaDB with full examples.
The SQLite Adapter persists data to a SQLite database file.
npm install @nebula/adapter-sqlite
import { createDb } from '@nebula/core';
import { SQLiteAdapter } from '@nebula/adapter-sqlite';
const db = createDb({
adapter: new SQLiteAdapter('data.sqlite')
});
const users = db.collection('users');
await users.insert({ name: 'Alice', age: 30 });
const adapter = new SQLiteAdapter('data.sqlite', {
readonly: false,
fileMustExist: false,
timeout: 5000,
verbose: console.log
});
npm install @nebula/adapter-redis
import { createDb } from '@nebula/core';
import { RedisAdapter } from '@nebula/adapter-redis';
const db = createDb({
adapter: new RedisAdapter(
{ host: 'localhost', port: 6379, password: 'your-password' },
'nebula:' // Key prefix
)
});
await db.adapter.close();
| Feature | Memory | LocalStorage | IndexedDB | FileSystem | SQLite | Redis |
|---|---|---|---|---|---|---|
| Persistence | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Browser | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
| Node.js | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ |
| Edge | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
| Transactions | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ |
| Scalability | Low | Low | Medium | Medium | Medium | High |
| Speed | Very Fast | Fast | Medium | Medium | Fast | Very Fast |
| External Deps | None | None | None | None | None | Redis |
Implement the Adapter interface:
import { Adapter, Document } from '@nebula/core';
class CustomAdapter implements Adapter {
async load(): Promise<Record<string, Document[]>> {
// Load data from your storage
}
async save(data: Record<string, Document[]>): Promise<void> {
// Save data to your storage
}
}
import { Adapter, Document } from '@nebula/core';
import { MongoClient, Db } from 'mongodb';
export class MongoDBAdapter implements Adapter {
private client: MongoClient;
private db: Db | null = null;
private dbName: string;
constructor(uri: string, dbName: string) {
this.client = new MongoClient(uri);
this.dbName = dbName;
}
private async connect(): Promise<Db> {
if (!this.db) {
await this.client.connect();
this.db = this.client.db(this.dbName);
}
return this.db;
}
async load(): Promise<Record<string, Document[]>> {
const db = await this.connect();
const result: Record<string, Document[]> = {};
const collections = await db.listCollections().toArray();
for (const collection of collections) {
const collectionName = collection.name;
if (collectionName.startsWith('system.')) continue;
const docs = await db.collection(collectionName).find().toArray();
result[collectionName] = docs.map(doc => {
const { _id, ...rest } = doc;
return { id: _id.toString(), ...rest };
});
}
return result;
}
async save(data: Record<string, Document[]>): Promise<void> {
const db = await this.connect();
for (const [collectionName, documents] of Object.entries(data)) {
const collection = db.collection(collectionName);
await collection.deleteMany({});
if (documents.length > 0) await collection.insertMany(documents);
}
}
async close(): Promise<void> {
if (this.client) await this.client.close();
}
}