{"_id":"@airdraft/db-adapter-mongodb","_rev":"7-e91385dfe59807684056862b45b36fcf","name":"@airdraft/db-adapter-mongodb","dist-tags":{"latest":"0.1.6"},"versions":{"0.1.0":{"name":"@airdraft/db-adapter-mongodb","version":"0.1.0","license":"MIT","_id":"@airdraft/db-adapter-mongodb@0.1.0","maintainers":[{"name":"miracleio","email":"miracleficient@gmail.com"}],"dist":{"shasum":"f1de882e6060e0283fc8be47cd3eec6191a7ab5d","tarball":"https://registry.npmjs.org/@airdraft/db-adapter-mongodb/-/db-adapter-mongodb-0.1.0.tgz","fileCount":10,"integrity":"sha512-BvglUMSghHWCq+555HUUGhUNl839aVC5m+SxzMTjh+ad/vMmVXqYflcwzNO6/gZdXcrORPvrGQYxwhXtjuDbNg==","signatures":[{"sig":"MEUCIQC2xFCzS6wULIlo+nRdcYMjNK/QoJok7/kXFdeWSO4ynwIge5YgtVp+uDGcWSEr2C/aJN7RYijgyvMU8PzHmjHfgKg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":42190},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"487fa21cb4354fe9f328783fc337269784e1262c","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"miracleio","email":"miracleficient@gmail.com"},"_npmVersion":"11.9.0","description":"Airdraft MongoDB database adapter via mongoose","directories":{},"_nodeVersion":"24.14.0","dependencies":{"@airdraft/core":"*"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.0.0","mongoose":">=8.0.0","typescript":"^5.4.0","@types/node":"^20.0.0","@airdraft/db-adapter":"*","mongodb-memory-server":"^10.0.0"},"peerDependencies":{"mongoose":">=8.0.0","@airdraft/db-adapter":">=0.1.0"},"_npmOperationalInternal":{"tmp":"tmp/db-adapter-mongodb_0.1.0_1780295194914_0.03177672250307806","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@airdraft/db-adapter-mongodb","version":"0.1.1","license":"MIT","_id":"@airdraft/db-adapter-mongodb@0.1.1","maintainers":[{"name":"miracleio","email":"miracleficient@gmail.com"}],"dist":{"shasum":"dd3c6850ec1089ba66a2f638ffcc8e8e9be47cb4","tarball":"https://registry.npmjs.org/@airdraft/db-adapter-mongodb/-/db-adapter-mongodb-0.1.1.tgz","fileCount":10,"integrity":"sha512-Eie1JERGFc4uDFrPScfNKCsm3bObL4hoyAaELv9gv4TzudwNSyW8YZa9ZuGFcEk8AqWUeWra41owYxtSoRZM/g==","signatures":[{"sig":"MEUCIQCbrRoD/XDQyxCt4+2jJRqkR5RUDpo1AbP6vT4P7/UayQIgDIo8wTdAfLNmpGFsQWDHkFPa+9BbW0ytka7yitqoL/U=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":41845},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"633bdabb60ea9a7fd1cf9b12434309cfa8b881cf","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"miracleio","email":"miracleficient@gmail.com"},"_npmVersion":"11.9.0","description":"Airdraft MongoDB database adapter via mongoose","directories":{},"_nodeVersion":"24.14.0","dependencies":{"@airdraft/core":"*"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.0.0","mongoose":">=8.0.0","typescript":"^5.4.0","@types/node":"^20.0.0","@airdraft/db-adapter":"*","mongodb-memory-server":"^10.0.0"},"peerDependencies":{"mongoose":">=8.0.0","@airdraft/db-adapter":">=0.1.0"},"_npmOperationalInternal":{"tmp":"tmp/db-adapter-mongodb_0.1.1_1780301336334_0.821491709452566","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@airdraft/db-adapter-mongodb","version":"0.1.2","license":"MIT","_id":"@airdraft/db-adapter-mongodb@0.1.2","maintainers":[{"name":"miracleio","email":"miracleficient@gmail.com"}],"dist":{"shasum":"2c7d4527dfdbac4936c5fa5f1bb5be5cdd53199a","tarball":"https://registry.npmjs.org/@airdraft/db-adapter-mongodb/-/db-adapter-mongodb-0.1.2.tgz","fileCount":10,"integrity":"sha512-Vo9Dx/Om1eJkrmp8Am5W/XU5AozeaOkyjHBbam0mUyDYsnqpLve2rg4UhE4j+yS+/KZ+SDy9RLaz8yZh18y0Kw==","signatures":[{"sig":"MEUCIG2LbiMs7ZW4PSKVzQjZA2Ey5Py503LHCdgRzPZkR8DxAiEA/eucxrijA3miN/Gc6iJlzM0UqEzPVHkiKEDq/iyRFjA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":42646},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"4d70e482082fc1a95cf93353d663ad714c800256","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"miracleio","email":"miracleficient@gmail.com"},"_npmVersion":"11.9.0","description":"Airdraft MongoDB database adapter via mongoose","directories":{},"_nodeVersion":"24.14.0","dependencies":{"@airdraft/core":"*"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.0.0","mongoose":">=8.0.0","typescript":"^5.4.0","@types/node":"^20.0.0","@airdraft/db-adapter":"*","mongodb-memory-server":"^10.0.0"},"peerDependencies":{"mongoose":">=8.0.0","@airdraft/db-adapter":">=0.1.0"},"_npmOperationalInternal":{"tmp":"tmp/db-adapter-mongodb_0.1.2_1780309923583_0.9519681188949327","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@airdraft/db-adapter-mongodb","version":"0.1.3","license":"MIT","_id":"@airdraft/db-adapter-mongodb@0.1.3","maintainers":[{"name":"miracleio","email":"miracleficient@gmail.com"}],"dist":{"shasum":"9fda06b1760013c3dac11c871b76b8b79af29af9","tarball":"https://registry.npmjs.org/@airdraft/db-adapter-mongodb/-/db-adapter-mongodb-0.1.3.tgz","fileCount":14,"integrity":"sha512-Xa7WnEJyK8F2QWUAjn5PHwKyBpBgM0wWmRJ/7mdTDCEMyQLNOlErefKDy+0R87c9hw5hj0ZRDSNXx+F8FmhkIg==","signatures":[{"sig":"MEUCIQDsQ0O8gu+mCMgybZcRtoUmYjvRCRDKCmTKP1d0QHe7xgIgMeeVOgClm0dPxXLmVBpEN9XOG5ALe+cAiskfT5VM57s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":64306},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"4d70e482082fc1a95cf93353d663ad714c800256","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"miracleio","email":"miracleficient@gmail.com"},"_npmVersion":"11.9.0","description":"Airdraft MongoDB database adapter via mongoose","directories":{},"_nodeVersion":"24.14.0","dependencies":{"@airdraft/core":"*"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.0.0","mongoose":">=8.0.0","typescript":"^5.4.0","@types/node":"^20.0.0","@airdraft/db-adapter":"*","mongodb-memory-server":"^10.0.0"},"peerDependencies":{"mongoose":">=8.0.0","@airdraft/db-adapter":">=0.1.0","@airdraft/plugin-auth":"*"},"_npmOperationalInternal":{"tmp":"tmp/db-adapter-mongodb_0.1.3_1780314145025_0.6694183638396802","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@airdraft/db-adapter-mongodb","version":"0.1.4","license":"MIT","_id":"@airdraft/db-adapter-mongodb@0.1.4","maintainers":[{"name":"miracleio","email":"miracleficient@gmail.com"}],"dist":{"shasum":"37d7f13e0894e9cbeacd1b38072d8ca4e3d7c8e6","tarball":"https://registry.npmjs.org/@airdraft/db-adapter-mongodb/-/db-adapter-mongodb-0.1.4.tgz","fileCount":14,"integrity":"sha512-RNzt+x5QQv8V/wZTz17ZsF5gjyCM7fDb9X+UZQ0s2pf2HQinHvmdGualhM+WobF9/z6VnJ4yv6k60UWzD5qmRQ==","signatures":[{"sig":"MEUCIAX2Djju39FiRejl6XB9wusXL9oVao5PeVfeNWu5kL/xAiEAxRASmT8UhqnI8NIubQz/X/1HrZvJwOtIJS8I9iYk19E=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":64395},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"4d70e482082fc1a95cf93353d663ad714c800256","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"miracleio","email":"miracleficient@gmail.com"},"_npmVersion":"11.9.0","description":"Airdraft MongoDB database adapter via mongoose","directories":{},"_nodeVersion":"24.14.0","dependencies":{"@airdraft/core":"*"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.0.0","mongoose":">=8.0.0","typescript":"^5.4.0","@types/node":"^20.0.0","@airdraft/db-adapter":"*","mongodb-memory-server":"^10.0.0"},"peerDependencies":{"mongoose":">=8.0.0","@airdraft/db-adapter":">=0.1.0","@airdraft/plugin-auth":"*"},"_npmOperationalInternal":{"tmp":"tmp/db-adapter-mongodb_0.1.4_1780316928567_0.011337842367990847","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@airdraft/db-adapter-mongodb","version":"0.1.5","license":"MIT","_id":"@airdraft/db-adapter-mongodb@0.1.5","maintainers":[{"name":"miracleio","email":"miracleficient@gmail.com"}],"dist":{"shasum":"88de8168bc10877abaec63723f7ea444a84d9005","tarball":"https://registry.npmjs.org/@airdraft/db-adapter-mongodb/-/db-adapter-mongodb-0.1.5.tgz","fileCount":14,"integrity":"sha512-WM4ozGs1UWtHSv6SiP+jniJJlEwegLfYi2lSeJY/06fO3TVvC+yzCs79/yOeTBK9omZpj3EBdYWzAvTE//wtIw==","signatures":[{"sig":"MEUCIQDcSoaVHqtr6Yu4mTosU2CNUoscs3v2NQeCIHqRbcfHkQIgDm/d9PN1w1PmTU/8NT5YSjmRsqvpJ8mFTd8MBDIVNnc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":64502},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"9fdb3e0fbca1e58bb84aca8dd92155d0057ca4b1","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"miracleio","email":"miracleficient@gmail.com"},"_npmVersion":"11.9.0","description":"Airdraft MongoDB database adapter via mongoose","directories":{},"_nodeVersion":"24.14.0","dependencies":{"@airdraft/core":"*"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.0.0","mongoose":">=8.0.0","typescript":"^5.4.0","@types/node":"^20.0.0","@airdraft/db-adapter":"*","mongodb-memory-server":"^10.0.0"},"peerDependencies":{"mongoose":">=8.0.0","@airdraft/db-adapter":">=0.1.0","@airdraft/plugin-auth":"*"},"_npmOperationalInternal":{"tmp":"tmp/db-adapter-mongodb_0.1.5_1782411674875_0.7569489900445725","host":"s3://npm-registry-packages-npm-production"}},"0.1.6":{"name":"@airdraft/db-adapter-mongodb","version":"0.1.6","description":"Airdraft MongoDB database adapter via mongoose","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"}},"scripts":{"build":"tsc","dev":"tsc --watch","clean":"rm -rf dist","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit","prepublishOnly":"npm run build","release":"standard-version","release:patch":"standard-version --release-as patch","release:minor":"standard-version --release-as minor","release:major":"standard-version --release-as major"},"publishConfig":{"access":"public"},"license":"MIT","dependencies":{"@airdraft/core":"*"},"peerDependencies":{"@airdraft/db-adapter":">=0.1.0","mongoose":">=8.0.0","@airdraft/plugin-auth":"*"},"devDependencies":{"@airdraft/db-adapter":"*","@types/node":"^20.0.0","mongodb-memory-server":"^10.0.0","mongoose":">=8.0.0","standard-version":"^9.5.0","typescript":"^5.4.0","vitest":"^2.0.0"},"gitHead":"d20236a8fba8458f9c30696a36380aded5d352db","_id":"@airdraft/db-adapter-mongodb@0.1.6","_nodeVersion":"24.14.0","_npmVersion":"11.9.0","dist":{"integrity":"sha512-0wI5XidmdDnatDFyAlrHHWX9cWHqP/jHUncjnYbhAYpqf92idiPNx0Ve3QP2r3EPzNS0ifzL6sAHKMfMEqzjWA==","shasum":"ddcf41129a9edd6c64f5145fea730f14620df6f1","tarball":"https://registry.npmjs.org/@airdraft/db-adapter-mongodb/-/db-adapter-mongodb-0.1.6.tgz","fileCount":19,"unpackedSize":91108,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGrrZIJndlXF6J6aZZE05m5uHcRMxWHKtRK26qC9jcFtAiEA9xK6gQJzypoIl7H1EJHLlEkSD4at5UCogEwzj8X9PF4="}]},"_npmUser":{"name":"miracleio","email":"miracleficient@gmail.com"},"directories":{},"maintainers":[{"name":"miracleio","email":"miracleficient@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/db-adapter-mongodb_0.1.6_1782562664879_0.7737529217765076"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-01T06:26:34.755Z","modified":"2026-06-27T12:17:45.137Z","0.1.0":"2026-06-01T06:26:35.092Z","0.1.1":"2026-06-01T08:08:56.464Z","0.1.2":"2026-06-01T10:32:03.700Z","0.1.3":"2026-06-01T11:42:25.170Z","0.1.4":"2026-06-01T12:28:48.707Z","0.1.5":"2026-06-25T18:21:15.023Z","0.1.6":"2026-06-27T12:17:45.034Z"},"license":"MIT","description":"Airdraft MongoDB database adapter via mongoose","maintainers":[{"name":"miracleio","email":"miracleficient@gmail.com"}],"readme":"# @airdraft/db-adapter-mongodb\n\nMongoDB storage adapter for [Airdraft](https://airdraft.io) via [`mongoose`](https://mongoosejs.com).\n\nUse 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.\n\n---\n\n## Installation\n\n```bash\nnpm install @airdraft/db-adapter @airdraft/db-adapter-mongodb mongoose\n```\n\n---\n\n## Quick start\n\n```ts\n// airdraft.config.ts\nimport { defineConfig } from '@airdraft/core'\nimport { MongoAdapter } from '@airdraft/db-adapter-mongodb'\n\nexport default defineConfig({\n  adapter: new MongoAdapter({\n    uri: process.env.MONGODB_URI!,\n  }),\n  // … collections, plugins\n})\n```\n\nAdd to `.env.local`:\n\n```\nMONGODB_URI=mongodb+srv://user:pass@cluster.mongodb.net/mydb\n```\n\nRun the migration on first deploy (idempotent — creates indexes and checks replica-set requirements):\n\n```ts\n// instrumentation.ts  (Next.js server-start hook)\nimport airdraft from '@/airdraft.config'\nimport { BaseDatabaseAdapter } from '@airdraft/db-adapter'\n\nexport async function register() {\n  if (airdraft.adapter instanceof BaseDatabaseAdapter) {\n    await airdraft.adapter.migrate()\n  }\n}\n```\n\n---\n\n## Options\n\n```ts\nnew MongoAdapter(options)\n```\n\n| Option | Type | Default | Description |\n|---|---|---|---|\n| `uri` | `string` | — | MongoDB connection URI. |\n| `connection` | `mongoose.Connection` | — | Provide an existing Mongoose connection (e.g. one shared across your app). Mutually exclusive with `uri`. |\n| `projectId` | `string` | `'default'` | Namespace for multi-tenant deployments. |\n| `history` | `boolean` | `false` | Mirror every write to the `airdraft_entry_history` collection. Requires a replica set. |\n| `cacheTtlMs` | `number` | `0` | Per-entry read cache TTL. `0` disables caching. |\n| `cacheMaxSize` | `number` | `500` | Maximum entries in the LRU cache. |\n\n---\n\n## Schema\n\n### `airdraft_entries` collection\n\n| Field | Type | Notes |\n|---|---|---|\n| `_id` | `ObjectId` | |\n| `project_id` | `String` | Multi-tenancy namespace |\n| `collection` | `String` | |\n| `slug` | `String` | |\n| `sha` | `String` | SHA-256 of the serialized content |\n| `data` | `Mixed` | Arbitrary entry data stored as a subdocument |\n| `published` | `Boolean` | `null` / `undefined` = published (default), `false` = draft |\n| `created_at` | `Date` | |\n| `updated_at` | `Date` | |\n\nUnique index on `{ project_id, collection, slug }`. Mongoose duplicate key error code `11000` → `ConflictError`.\n\n### `airdraft_entry_history` *(when `history: true`)*\n\nSame 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.\n\n---\n\n## Features\n\n- **Native subdocument storage** — `data` is a Mongoose `Mixed` field, so nested objects, arrays, and all BSON types are stored natively.\n- **Optimistic concurrency** — SHA checked on every write; `ConflictError` thrown on mismatch.\n- **Atomic field ops** — `$inc` / `$set` / `$push` / `$pull` applied to any dot-notation path.\n- **Field filters** — `queryEntries()` translates filter entries to MongoDB `$regex` or equality matchers on nested fields.\n- **Lazy model registration** — The Mongoose model is created on first use via `getEntryModel(connection)`, preventing `OverwriteModelError` in hot-reload environments.\n- **Shared connection** — Pass a `connection` option to reuse an existing Mongoose connection (typical in Next.js where you maintain a global connection singleton).\n\n---\n\n## Shared Mongoose connection (recommended for Next.js)\n\n```ts\n// lib/mongoose.ts\nimport mongoose from 'mongoose'\n\ndeclare global { var __mongooseConn: mongoose.Connection | undefined }\n\nexport async function getConnection() {\n  if (global.__mongooseConn?.readyState === 1) return global.__mongooseConn\n  const conn = await mongoose.createConnection(process.env.MONGODB_URI!).asPromise()\n  global.__mongooseConn = conn\n  return conn\n}\n```\n\n```ts\n// airdraft.config.ts\nimport { defineConfig } from '@airdraft/core'\nimport { MongoAdapter } from '@airdraft/db-adapter-mongodb'\nimport { getConnection } from './lib/mongoose'\n\nexport default defineConfig({\n  adapter: new MongoAdapter({ connection: await getConnection() }),\n})\n```\n\n---\n\n## History & rollback\n\nEnable history to keep every revision and restore any previous version:\n\n```ts\nconst adapter = new MongoAdapter({ uri: process.env.MONGODB_URI!, history: true })\n\n// Restore a specific past revision (sha from the audit log or history collection)\nawait adapter.rollback('posts/my-post', previousSha)\n```\n\n> **Note:** History requires a MongoDB **replica set**. On Atlas, all clusters support this. On self-hosted MongoDB, start with `--replSet`.\n\n---\n\n## Testing\n\nRuns the shared contract suite using [`mongodb-memory-server`](https://github.com/nodkz/mongodb-memory-server) — an in-process MongoDB that needs no external service:\n\n```bash\nnpm test\n```\n\nThe test file (`src/__tests__/contract.test.ts`) spins up a `MongoMemoryServer` before all tests and tears it down after. History tests are skipped because `MongoMemoryServer` runs a standalone node (not a replica set); run against a real replica set to exercise history + rollback paths.\n\n---\n\n## License\n\nMIT\n","readmeFilename":"README.md"}