{"id":16539,"library":"sqlite-level","title":"SQLite-backed Abstract LevelDB","description":"sqlite-level is a Node.js library that provides an `abstract-level` compliant interface, backed by a SQLite database. It leverages `better-sqlite3` for its underlying SQLite operations, offering a synchronous-like API while maintaining `abstract-level` compatibility. This allows developers familiar with the LevelDB API to utilize a durable, file-based store without needing to manage separate database processes or complex setups typical of other embedded databases. Currently stable at version 1.2.1, its release cadence is tied to the needs of the TinaCMS project, ensuring ongoing maintenance and updates. A key differentiator is its use of SQLite, offering ACID properties and wide tooling support, contrasting with LevelDB's LSM-tree design. It's particularly useful for server-side applications requiring a lightweight, transactional key-value store with data persistence for development or smaller deployments.","status":"active","version":"1.2.1","language":"javascript","source_language":"en","source_url":"https://github.com/tinacms/sqlite-level","tags":["javascript","level","leveldb","leveldown","levelup","memory","sqlite","typescript"],"install":[{"cmd":"npm install sqlite-level","lang":"bash","label":"npm"},{"cmd":"yarn add sqlite-level","lang":"bash","label":"yarn"},{"cmd":"pnpm add sqlite-level","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency, often required for on-the-fly TypeScript or ESM compilation in some build environments, especially when integrated into larger frameworks. Not strictly required for runtime if transpilation is handled separately.","package":"sucrase","optional":true},{"reason":"Runtime dependency for SQLite database interactions. Its native bindings can sometimes cause installation issues on specific platforms or environments.","package":"better-sqlite3","optional":false}],"imports":[{"note":"sqlite-level is an ESM-first package. Use `import` syntax. CommonJS `require` will result in a runtime error or require an import shim.","wrong":"const { Level } = require('sqlite-level');","symbol":"Level","correct":"import { Level } from 'sqlite-level';"},{"note":"When importing types in TypeScript, explicitly use `import type` for clarity and to prevent bundling issues in environments that do not support type stripping.","wrong":"import { LevelOptions } from 'sqlite-level';","symbol":"LevelOptions","correct":"import type { LevelOptions } from 'sqlite-level';"}],"quickstart":{"code":"import { Level } from 'sqlite-level';\nimport { join } from 'path';\nimport { tmpdir } from 'os';\n\nasync function runExample() {\n  const dbPath = join(tmpdir(), 'my_sqlite_level_db.sqlite');\n  const db = new Level(dbPath);\n\n  try {\n    console.log(`Opening database at: ${dbPath}`);\n    await db.open();\n    console.log('Database opened.');\n\n    await db.put('name', 'Alice');\n    await db.put('age', '30');\n\n    const name = await db.get('name');\n    const age = await db.get('age');\n    console.log(`Name: ${name}, Age: ${age}`);\n\n    // Iterate over entries\n    console.log('Iterating over entries:');\n    for await (const [key, value] of db.iterator({ gte: 'a', lt: 'z' })) {\n      console.log(`  Key: ${key}, Value: ${value}`);\n    }\n\n    await db.del('age');\n    const newAge = await db.get('age');\n    console.log(`Age after deletion: ${newAge}`); // Should be undefined\n  } catch (error) {\n    console.error('An error occurred:', error);\n  } finally {\n    if (!db.isClosed()) {\n      await db.close();\n      console.log('Database closed.');\n    }\n  }\n}\n\nrunExample();","lang":"typescript","description":"Demonstrates opening a SQLite-backed LevelDB, performing basic put, get, delete operations, and iterating over stored keys and values, ensuring proper database closure."},"warnings":[{"fix":"Ensure you have C++ build tools installed (e.g., `build-essential` on Debian/Ubuntu, Xcode Command Line Tools on macOS, or Visual Studio Build Tools on Windows). Consider using a Docker environment for consistent builds.","message":"Installation issues can occur due to the native bindings of `better-sqlite3`, which `sqlite-level` relies on. Users may encounter compilation errors on certain platforms or specific Node.js versions.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Implement retry logic for write operations, or design your application to minimize concurrent writes to the same database. Consider moving to a more robust database solution if high-volume, concurrent writes are a core requirement.","message":"As `sqlite-level` uses SQLite internally, it inherits SQLite's concurrency model. While WAL (Write-Ahead Logging) can improve read concurrency, writes are still serialized. Aggressive concurrent writes can lead to `SQLITE_BUSY` errors if not handled properly.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"For Node.js projects, ensure your `package.json` specifies `\"type\": \"module\"` or use dynamic `import()` for `sqlite-level`. If using TypeScript, configure `\"module\": \"NodeNext\"` or `\"ESNext\"` in `tsconfig.json`.","message":"`sqlite-level` is distributed as an ECMAScript Module (ESM). Direct `require()` statements in CommonJS environments will fail with a runtime error, indicating it's an ESM module.","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"Always ensure `db.close()` is called and awaited in a `finally` block or on application shutdown hooks. For long-running processes, consider implementing graceful shutdown procedures.","message":"Forgetting to `await db.close()` can lead to data corruption or locks on the SQLite database file, especially if the application exits abruptly. This is critical for persistent, file-based databases.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Change your importing code from `const { Level } = require('sqlite-level');` to `import { Level } from 'sqlite-level';`. Ensure your `package.json` for the consuming project has `\"type\": \"module\"` or dynamically import with `const { Level } = await import('sqlite-level');`.","cause":"Attempting to `require()` an ESM-only package from a CommonJS module.","error":"Error [ERR_REQUIRE_ESM]: require() of ES Module ...sqlite-level/build/index.js from ... not supported."},{"fix":"This often occurs in concurrent environments. Implement basic retry logic with a short delay for write operations. Ensure database connections are managed properly and closed when not in use. Consider using WAL mode if not already active.","cause":"Multiple concurrent write operations or an active read transaction holding a lock prevents other operations from proceeding.","error":"Error: SQLITE_BUSY: database is locked"},{"fix":"Ensure all database operations are completed before `db.close()` is called. Use `db.isOpen()` to check the database state if you suspect it might be closed prematurely. Wrap operations in `try...finally` to ensure `db.close()` is called only when needed.","cause":"An attempt was made to perform an operation (put, get, iterate) on a `Level` instance that has already been `close()`d or failed to `open()`.","error":"Error: Database is closed"}],"ecosystem":"npm"}