This guide covers creating custom plugins to extend NebulaDB — cache, logger, migration, and more patterns.
The Cache Plugin improves query performance by caching query results.
npm install @nebula/plugin-cache
import { createDb } from '@nebula/core';
import { MemoryAdapter } from '@nebula/adapter-memory';
import { createCachePlugin } from '@nebula/plugin-cache';
const cachePlugin = createCachePlugin({
maxCacheSize: 100,
ttl: 60000,
excludeCollections: ['logs'],
cacheEmptyResults: true
});
const db = createDb({
adapter: new MemoryAdapter(),
plugins: [cachePlugin]
});
const users = db.collection('users');
const result1 = await users.find({ age: { $gt: 30 } }); // Executed
const result2 = await users.find({ age: { $gt: 30 } }); // From cache
npm install @nebula/plugin-logger
import { createLoggerPlugin, LogLevel } from '@nebula/plugin-logger';
const loggerPlugin = createLoggerPlugin({
level: LogLevel.DEBUG,
logQueryParams: true,
logDocuments: false,
logPerformance: true
});
const db = createDb({
adapter: new MemoryAdapter(),
plugins: [loggerPlugin]
});
// All operations will be logged automatically
import { createLoggerPlugin, Logger } from '@nebula/plugin-logger';
class MyCustomLogger implements Logger {
debug(message: string, ...args: any[]): void { /* custom */ }
info(message: string, ...args: any[]): void { /* custom */ }
warn(message: string, ...args: any[]): void { /* custom */ }
error(message: string, ...args: any[]): void { /* custom */ }
}
const loggerPlugin = createLoggerPlugin({ logger: new MyCustomLogger() });
npm install @nebula/plugin-migration
import { createMigrationPlugin } from '@nebula/plugin-migration';
const migrations = [
{
version: 1,
name: 'Add email to users',
async up(db) {
const users = db.collection('users');
const allUsers = await users.find();
for (const user of allUsers) {
if (!user.email) {
await users.update(
{ id: user.id },
{ $set: { email: `${user.name.toLowerCase()}@example.com` } }
);
}
}
},
async down(db) {
const users = db.collection('users');
await users.update({}, { $unset: { email: true } });
}
},
{
version: 2,
name: 'Add createdAt to posts',
async up(db) {
const posts = db.collection('posts');
const allPosts = await posts.find();
for (const post of allPosts) {
if (!post.createdAt) {
await posts.update(
{ id: post.id },
{ $set: { createdAt: new Date().toISOString() } }
);
}
}
}
}
];
const migrationPlugin = createMigrationPlugin({
migrations,
migrationCollection: '_migrations',
autoApply: true,
throwOnError: true
});
const db = createDb({
adapter: new MemoryAdapter(),
plugins: [migrationPlugin]
});
// Manual control:
// await migrationPlugin.applyMigrations();
// await migrationPlugin.revertMigrations();
// await migrationPlugin.revertMigrations(1); // Revert to version 1
Each migration should have: