{"id":16280,"library":"y-leveldb","title":"Yjs LevelDB Persistence Adapter","description":"y-leveldb is a persistence adapter for Yjs, the CRDT framework for real-time collaboration. It enables storing Yjs document updates persistently using LevelDB and its compatible implementations (like RocksDB, LMDB, or `level-mem`). The current stable version is `0.2.0`. Releases are infrequent but address compatibility, dependency updates, and bug fixes. Key differentiators include its flexibility to use various LevelUP-compatible storage backends, its direct integration into Yjs ecosystems (e.g., `y-websocket`), and its ability to manage multiple Yjs documents within a single database instance. The library provides a granular API for storing and retrieving document updates, state vectors, and custom metadata without necessarily hydrating a full Y.Doc object, which is crucial for efficient server-side synchronization and data management.","status":"active","version":"0.2.0","language":"javascript","source_language":"en","source_url":"https://github.com/yjs/y-leveldb","tags":["javascript","Yjs","CRDT","offline","shared editing","collaboration","concurrency","typescript"],"install":[{"cmd":"npm install y-leveldb","lang":"bash","label":"npm"},{"cmd":"yarn add y-leveldb","lang":"bash","label":"yarn"},{"cmd":"pnpm add y-leveldb","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core Yjs library for CRDT functionality and document updates.","package":"yjs","optional":false}],"imports":[{"note":"Primarily designed for ESM. While CommonJS might work with transpilation or specific Node.js loader setups, native ESM import is the idiomatic approach.","wrong":"const { LeveldbPersistence } = require('y-leveldb')","symbol":"LeveldbPersistence","correct":"import { LeveldbPersistence } from 'y-leveldb'"},{"note":"Yjs exports its API as a namespace object; destructuring or a default import is generally incorrect for the core Y object.","wrong":"import Y from 'yjs'","symbol":"Y","correct":"import * as Y from 'yjs'"},{"note":"When providing a custom LevelUP-compatible adapter, import it directly. This example uses `level-mem` for in-memory persistence, which is a named export from the module.","wrong":"const level = require('level-mem')","symbol":"level","correct":"import level from 'level-mem'"}],"quickstart":{"code":"import * as Y from 'yjs'\nimport { LeveldbPersistence } from 'y-leveldb'\n\n// Create a persistence instance pointing to a storage location.\n// For in-memory, you could pass { level: require('level-mem') } as the second argument.\nconst persistence = new LeveldbPersistence('./yjs-storage')\n\nasync function runExample() {\n  // Create a new Yjs document and make some changes.\n  const ydoc = new Y.Doc()\n  const yarray = ydoc.getArray('my-array')\n  yarray.insert(0, ['item 1', 'item 2'])\n  yarray.push(['item 3'])\n\n  console.log('Initial Y.Doc content:', yarray.toArray())\n\n  // Store the current state of 'my-doc' to LevelDB.\n  await persistence.storeUpdate('my-doc', Y.encodeStateAsUpdate(ydoc))\n  console.log('Document state stored.')\n\n  // To retrieve data or sync, create a temporary Y.Doc from persistence.\n  const persistedYDoc = await persistence.getYDoc('my-doc')\n  const persistedYarray = persistedYDoc.getArray('my-array')\n  console.log('Retrieved Y.Doc content:', persistedYarray.toArray())\n\n  // Example of retrieving metadata\n  await persistence.setMeta('my-doc', 'owner', 'Alice')\n  const owner = await persistence.getMeta('my-doc', 'owner')\n  console.log('Document owner:', owner)\n\n  // Clean up example data (optional)\n  // await persistence.clearDocument('my-doc')\n  // console.log('Document cleared.')\n}\n\nrunExample().catch(console.error)\n","lang":"javascript","description":"This quickstart demonstrates how to initialize `y-leveldb`, store a Yjs document's state, and then retrieve it from the persistent storage, including setting and getting metadata. It shows basic CRUD operations for Yjs documents."},"warnings":[{"fix":"Review the changelog for the `level` package between v6 and v8 and update your custom `level` client code or configurations accordingly. Ensure your direct `level` dependencies are compatible with the version `y-leveldb` now expects.","message":"Version `0.2.0` upgraded the underlying `level` dependency from version 6.x to 8.x. Users who directly interact with or pass custom `level` instances might encounter breaking changes due to API differences in `level` itself. Ensure compatibility if you rely on specific `level` versions or APIs.","severity":"breaking","affected_versions":">=0.2.0"},{"fix":"For highly critical synchronization or to ensure the most up-to-date state, retrieve the full `Y.Doc` using `getYDoc` and then encode its state, or ensure `flushDocument` has been called if you manually manage flushes (though `flushDocument` is generally not needed in production).","message":"The `getAllDocStateVectors` method returns state vectors that \"might be outdated if the associated document is not yet flushed.\" Relying on these state vectors for critical synchronization without understanding the internal flushing mechanism can lead to inconsistent states. Use with caution for real-time synchronization.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Avoid using `flushDocument` in production code unless you have a specific, well-understood need for it and have thoroughly tested its implications on your application's data integrity and performance.","message":"The `flushDocument` method is explicitly marked as 'dev only' and generally not recommended for regular use. Calling it unnecessarily could impact performance or lead to unexpected behavior if not fully understood.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Always ensure that `yjs` is installed in your project and matches the peer dependency version range specified (e.g., `npm install yjs@^13.0.0`). Check `npm ls yjs` to verify your installed version.","message":"The package has a peer dependency on `yjs` version `^13.0.0`. Incompatible versions of `yjs` can lead to runtime errors, unexpected behavior, or subtle data corruption due to mismatches in update formats or CRDT logic.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Ensure you are using the correct ESM import: `import { LeveldbPersistence } from 'y-leveldb'`. If running in a pure CommonJS environment, ensure Node.js can resolve ESM modules or consider transpilation.","cause":"Attempting to import `LeveldbPersistence` using CommonJS `require()` syntax in an environment expecting ESM, or using incorrect destructuring.","error":"TypeError: LeveldbPersistence is not a constructor"},{"fix":"Install the correct version of `yjs`: `npm install yjs@^13.0.0`. Verify with `npm ls yjs`.","cause":"The `yjs` package is either not installed or an incompatible version is installed in the project.","error":"Error: Peer dependency yjs@^13.0.0 not met"},{"fix":"Change the `storageLocation` to a path where the Node.js process has full read/write permissions (e.g., a subdirectory within your application's data folder) or adjust the file system permissions for the target directory.","cause":"The Node.js process does not have sufficient read/write permissions for the specified `storageLocation` directory or its parent. This is common on servers when trying to write to `/` or system-protected directories.","error":"Error: EACCES: permission denied, open './storage-location/manifest'"},{"fix":"Install the missing `level` adapter package: `npm install level-mem` (or the specific adapter you intend to use).","cause":"When providing a custom `level` adapter (e.g., `level-mem`), the adapter package itself must be installed as a dependency.","error":"Error: Could not find module 'level-mem'"}],"ecosystem":"npm"}