@airdraft/db-adapter-mongodb
v0.1.4
Published
Airdraft MongoDB database adapter via mongoose
Readme
@airdraft/db-adapter-mongodb
MongoDB storage adapter for Airdraft via mongoose.
Use this adapter to store Airdraft content in a MongoDB database — well suited for Atlas-hosted projects, existing Mongoose codebases, and scenarios where rich document queries or full-text search are valuable.
Installation
npm install @airdraft/db-adapter @airdraft/db-adapter-mongodb mongooseQuick start
// airdraft.config.ts
import { defineConfig } from '@airdraft/core'
import { MongoAdapter } from '@airdraft/db-adapter-mongodb'
export default defineConfig({
adapter: new MongoAdapter({
uri: process.env.MONGODB_URI!,
}),
// … collections, plugins
})Add to .env.local:
MONGODB_URI=mongodb+srv://user:[email protected]/mydbRun the migration on first deploy (idempotent — creates indexes and checks replica-set requirements):
// instrumentation.ts (Next.js server-start hook)
import airdraft from '@/airdraft.config'
import { BaseDatabaseAdapter } from '@airdraft/db-adapter'
export async function register() {
if (airdraft.adapter instanceof BaseDatabaseAdapter) {
await airdraft.adapter.migrate()
}
}Options
new MongoAdapter(options)| Option | Type | Default | Description |
|---|---|---|---|
| uri | string | — | MongoDB connection URI. |
| connection | mongoose.Connection | — | Provide an existing Mongoose connection (e.g. one shared across your app). Mutually exclusive with uri. |
| projectId | string | 'default' | Namespace for multi-tenant deployments. |
| history | boolean | false | Mirror every write to the airdraft_entry_history collection. Requires a replica set. |
| cacheTtlMs | number | 0 | Per-entry read cache TTL. 0 disables caching. |
| cacheMaxSize | number | 500 | Maximum entries in the LRU cache. |
Schema
airdraft_entries collection
| Field | Type | Notes |
|---|---|---|
| _id | ObjectId | |
| project_id | String | Multi-tenancy namespace |
| collection | String | |
| slug | String | |
| sha | String | SHA-256 of the serialized content |
| data | Mixed | Arbitrary entry data stored as a subdocument |
| published | Boolean | null / undefined = published (default), false = draft |
| created_at | Date | |
| updated_at | Date | |
Unique index on { project_id, collection, slug }. Mongoose duplicate key error code 11000 → ConflictError.
airdraft_entry_history (when history: true)
Same shape, stored in a separate collection. Each document is a point-in-time snapshot. Requires a replica set — the adapter checks this during migrate() and throws MigrationError if history is enabled on a standalone node.
Features
- Native subdocument storage —
datais a MongooseMixedfield, so nested objects, arrays, and all BSON types are stored natively. - Optimistic concurrency — SHA checked on every write;
ConflictErrorthrown on mismatch. - Atomic field ops —
$inc/$set/$push/$pullapplied to any dot-notation path. - Field filters —
queryEntries()translates filter entries to MongoDB$regexor equality matchers on nested fields. - Lazy model registration — The Mongoose model is created on first use via
getEntryModel(connection), preventingOverwriteModelErrorin hot-reload environments. - Shared connection — Pass a
connectionoption to reuse an existing Mongoose connection (typical in Next.js where you maintain a global connection singleton).
Shared Mongoose connection (recommended for Next.js)
// lib/mongoose.ts
import mongoose from 'mongoose'
declare global { var __mongooseConn: mongoose.Connection | undefined }
export async function getConnection() {
if (global.__mongooseConn?.readyState === 1) return global.__mongooseConn
const conn = await mongoose.createConnection(process.env.MONGODB_URI!).asPromise()
global.__mongooseConn = conn
return conn
}// airdraft.config.ts
import { defineConfig } from '@airdraft/core'
import { MongoAdapter } from '@airdraft/db-adapter-mongodb'
import { getConnection } from './lib/mongoose'
export default defineConfig({
adapter: new MongoAdapter({ connection: await getConnection() }),
})History & rollback
Enable history to keep every revision and restore any previous version:
const adapter = new MongoAdapter({ uri: process.env.MONGODB_URI!, history: true })
// Restore a specific past revision (sha from the audit log or history collection)
await adapter.rollback('posts/my-post', previousSha)Note: History requires a MongoDB replica set. On Atlas, all clusters support this. On self-hosted MongoDB, start with
--replSet.
Testing
Runs the shared contract suite using mongodb-memory-server — an in-process MongoDB that needs no external service:
npm testLicense
MIT
