{"_id":"@airdraft/db-adapter-sqlite","_rev":"2-e9ff38734ed70ad25c880631a8af35b7","name":"@airdraft/db-adapter-sqlite","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@airdraft/db-adapter-sqlite","version":"0.1.0","license":"MIT","_id":"@airdraft/db-adapter-sqlite@0.1.0","maintainers":[{"name":"miracleio","email":"miracleficient@gmail.com"}],"dist":{"shasum":"0bb89f1323da8af50af70b61c775d5f5c7b5ad3d","tarball":"https://registry.npmjs.org/@airdraft/db-adapter-sqlite/-/db-adapter-sqlite-0.1.0.tgz","fileCount":14,"integrity":"sha512-HxeY4eughqAP9tzqAcYmTBYbt7NU0XJN8Ox6TAgUZn2dtSIg39agSTU+h90PeytRF/rD+jzkrviVwjY9/CM/Dg==","signatures":[{"sig":"MEUCIQCy5X3IjnDXIZcdfrlFsqYgofOab3KwQ1DNM+YEkumnkgIgLr5u6xHRc/RaaqGeW6s/tYXLxkNTAcEgrmBk1dMItII=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":41195},"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 SQLite database adapter via better-sqlite3","directories":{},"_nodeVersion":"24.14.0","dependencies":{"@airdraft/core":">=0.1.16"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.0.0","typescript":"^5.4.0","@types/node":"^20.0.0","better-sqlite3":">=9.0.0","@airdraft/db-adapter":">=0.1.0","@types/better-sqlite3":"^7.6.0"},"peerDependencies":{"better-sqlite3":">=9.0.0","@airdraft/db-adapter":">=0.1.0"},"_npmOperationalInternal":{"tmp":"tmp/db-adapter-sqlite_0.1.0_1780295186735_0.8351240185870066","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@airdraft/db-adapter-sqlite","version":"0.1.1","description":"Airdraft SQLite database adapter via better-sqlite3","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"},"publishConfig":{"access":"public"},"license":"MIT","dependencies":{"@airdraft/core":">=0.1.16"},"peerDependencies":{"@airdraft/db-adapter":">=0.1.0","better-sqlite3":">=9.0.0"},"devDependencies":{"@airdraft/db-adapter":">=0.1.0","@types/better-sqlite3":"^7.6.0","@types/node":"^20.0.0","better-sqlite3":">=9.0.0","typescript":"^5.4.0","vitest":"^2.0.0"},"gitHead":"9fdb3e0fbca1e58bb84aca8dd92155d0057ca4b1","_id":"@airdraft/db-adapter-sqlite@0.1.1","_nodeVersion":"24.14.0","_npmVersion":"11.9.0","dist":{"integrity":"sha512-9nYy67RxYvW0+dne/hBQMR7Lm9gPt4oG67R9XfSIPFi1/OgT8WlOllDPhqms3+vU4he+EyhN7OSH0vwVHSQsEQ==","shasum":"672dd71b4d56121fb7d77b8d5bd78b8dbeaf3ecb","tarball":"https://registry.npmjs.org/@airdraft/db-adapter-sqlite/-/db-adapter-sqlite-0.1.1.tgz","fileCount":14,"unpackedSize":41302,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIE5iJTWjHKUSg4dxpe6qYonk3M1I2CJXPuvOroy/fOxwAiAiVljdV0OcOi1ELZcl8u+I4jSVmlsSFFt+XzZxK2iihA=="}]},"_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-sqlite_0.1.1_1782411680683_0.12182547962239187"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-01T06:26:26.585Z","modified":"2026-06-25T18:21:21.017Z","0.1.0":"2026-06-01T06:26:26.892Z","0.1.1":"2026-06-25T18:21:20.887Z"},"license":"MIT","description":"Airdraft SQLite database adapter via better-sqlite3","maintainers":[{"name":"miracleio","email":"miracleficient@gmail.com"}],"readme":"# @airdraft/db-adapter-sqlite\n\nSQLite storage adapter for [Airdraft](https://airdraft.io) via [`better-sqlite3`](https://github.com/WiseLibs/better-sqlite3).\n\nUse this adapter to store Airdraft content in a local SQLite file — great for self-hosted deployments on a single server, VPS, or edge runtimes that bundle SQLite (e.g. Cloudflare D1 with a custom driver).\n\n---\n\n## Installation\n\n```bash\nnpm install @airdraft/db-adapter @airdraft/db-adapter-sqlite better-sqlite3\n```\n\n---\n\n## Quick start\n\n```ts\n// airdraft.config.ts\nimport { defineConfig } from '@airdraft/core'\nimport { SQLiteAdapter } from '@airdraft/db-adapter-sqlite'\n\nexport default defineConfig({\n  adapter: new SQLiteAdapter({\n    filename: process.env.DATABASE_URL ?? '.airdraft.db',\n  }),\n  // … collections, plugins\n})\n```\n\nAdd to `.env.local`:\n\n```\nDATABASE_URL=.airdraft.db\n```\n\nRun the migration on first deploy (or on every deploy — it is idempotent):\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 SQLiteAdapter(options)\n```\n\n| Option | Type | Default | Description |\n|---|---|---|---|\n| `filename` | `string` | — | Path to the `.db` file. Pass `':memory:'` for in-memory testing. |\n| `projectId` | `string` | `'default'` | Namespace for multi-tenant deployments. |\n| `history` | `boolean` | `false` | Mirror every write to `airdraft_entry_history`. Enables `rollback()`. |\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\nThe adapter creates two tables via `migrate()`:\n\n### `airdraft_entries`\n\n| Column | Type | Notes |\n|---|---|---|\n| `id` | `INTEGER PRIMARY KEY` | Auto-increment |\n| `project_id` | `TEXT NOT NULL` | Multi-tenancy namespace |\n| `collection` | `TEXT NOT NULL` | Collection name (first path segment) |\n| `slug` | `TEXT NOT NULL` | Entry slug (second path segment) |\n| `sha` | `TEXT NOT NULL` | SHA-256 of the serialized content |\n| `data` | `TEXT NOT NULL` | JSON-serialized entry data |\n| `published` | `INTEGER` | 1 = published, 0 = draft (`NULL` = published) |\n| `created_at` | `TEXT` | ISO-8601 datetime |\n| `updated_at` | `TEXT` | ISO-8601 datetime |\n\nUnique index on `(project_id, collection, slug)`.\n\n### `airdraft_entry_history` *(when `history: true`)*\n\n| Column | Type | Notes |\n|---|---|---|\n| `id` | `INTEGER PRIMARY KEY` | |\n| `project_id` | `TEXT NOT NULL` | |\n| `collection` | `TEXT NOT NULL` | |\n| `slug` | `TEXT NOT NULL` | |\n| `sha` | `TEXT NOT NULL` | SHA at the time of the snapshot |\n| `data` | `TEXT NOT NULL` | Snapshot of the entry data |\n| `created_at` | `TEXT` | When the snapshot was taken |\n\n---\n\n## Features\n\n- **Optimistic concurrency** — Every write checks the current SHA. Throws `ConflictError` on mismatch.\n- **Field filters** — `queryEntries()` translates `ListOptions.filter` to `json_extract()` predicates.\n- **Pagination** — `offset` + `limit` via `LIMIT ? OFFSET ?`.\n- **Sort** — `json_extract()` on any dot-notation field path.\n- **Atomic field ops** — `increment`, `set`, `push`, `pull` applied to any nested field with SHA re-computation.\n- **History** — Opt-in snapshot table; `rollback(path, sha)` restores any previous revision.\n- **Lazy `require`** — `better-sqlite3` is loaded on first use, so the module is tree-shakeable.\n\n---\n\n## Running migration as a standalone script\n\n```ts\n// scripts/db-setup.ts\nimport airdraft from '../airdraft.config.js'\nimport { BaseDatabaseAdapter } from '@airdraft/db-adapter'\n\nasync function main() {\n  if (!(airdraft.adapter instanceof BaseDatabaseAdapter)) {\n    console.error('No database adapter configured')\n    process.exit(1)\n  }\n  await airdraft.adapter.migrate()\n  await airdraft.adapter.close()\n  console.log('Migration complete')\n}\n\nmain().catch((err) => { console.error(err); process.exit(1) })\n```\n\n```bash\nnpx tsx scripts/db-setup.ts\n```\n\n---\n\n## Testing\n\nThe adapter runs the shared [contract test suite](../db-adapter/README.md#contract-test-suite) against an in-memory database:\n\n```ts\n// src/__tests__/contract.test.ts\nimport { describe } from 'vitest'\nimport { runStorageAdapterContract } from '@airdraft/db-adapter/testing'\nimport { SQLiteAdapter } from '../SQLiteAdapter.js'\n\ndescribe('SQLiteAdapter contract', () => {\n  runStorageAdapterContract(() => new SQLiteAdapter({ filename: ':memory:', history: true }))\n})\n```\n\n---\n\n## License\n\nMIT\n","readmeFilename":"README.md"}