### Install ClassicLevel with Source Compilation Source: https://github.com/level/classic-level/blob/main/README.md Command to install classic-level while forcing compilation from source, bypassing prebuilt binaries. Useful for custom build environments or troubleshooting. ```bash npm install classic-level --build-from-source ``` -------------------------------- ### Basic ClassicLevel Database Operations (JavaScript) Source: https://github.com/level/classic-level/blob/main/README.md Demonstrates fundamental database operations including creation, adding entries, batching, retrieving values, and iterating over entries. Requires 'classic-level' to be installed. ```javascript const { ClassicLevel } = require('classic-level') // Create a database const db = new ClassicLevel('./db', { valueEncoding: 'json' }) // Add an entry with key 'a' and value 1 await db.put('a', 1) // Add multiple entries await db.batch([{ type: 'put', key: 'b', value: 2 }]) // Get value of key 'a': 1 const value = await db.get('a') // Iterate entries with keys that are greater than 'a' for await (const [key, value] of db.iterator({ gt: 'a' })) { console.log(value) // 2 } ``` -------------------------------- ### Manually open classic-level with options Source: https://github.com/level/classic-level/blob/main/UPGRADING.md When `db.open(options)` is called manually, its options are merged with constructor options. This example shows merging `compression: true` with constructor options. ```javascript // Results in { createIfMissing: false, compression: true } await db.open({ compression: true }) ``` -------------------------------- ### db.compactRange(start, end[, options]) Source: https://context7.com/level/classic-level/llms.txt Manually triggers LevelDB compaction for a specified key range to reclaim disk space and merge SST files. ```APIDOC ## `db.compactRange(start, end[, options])` — Trigger manual compaction Manually triggers LevelDB compaction for the given key range, reclaiming disk space from deleted/overwritten entries and merging SST files. Useful after bulk deletes or imports. ```js const db = new ClassicLevel('./mydb') // Bulk delete followed by compaction to reclaim space await db.clear({ gte: 'archive:', lte: 'archive:~' }) await db.compactRange('archive:', 'archive:~') console.log('Compaction complete') // Compact the full keyspace (use '!' and '~' as practical bounds) await db.compactRange('!', '~') await db.close() ``` ``` -------------------------------- ### db.approximateSize(start, end[, options]) Source: https://context7.com/level/classic-level/llms.txt Estimates the storage size in bytes for a given key range, useful for monitoring disk usage. ```APIDOC ## `db.approximateSize(start, end[, options])` — Estimate storage size Returns the approximate number of bytes of file system space used by the key range `[start..end)`. Useful for monitoring storage usage or deciding when to trigger manual compaction. ```js const db = new ClassicLevel('./mydb') // Write some data first and reopen to ensure it is packed into SST files await db.batch( Array.from({ length: 1000 }, (_, i) => ({ type: 'put', key: `key:${String(i).padStart(4, '0')}`, value: 'x'.repeat(100) })) ) await db.close() await db.open() const bytes = await db.approximateSize('key:0000', 'key:~') console.log(`Range uses ~${bytes} bytes`) // With custom key encoding const size = await db.approximateSize('a', 'z', { keyEncoding: 'utf8' }) console.log(size) // number await db.close() ``` ``` -------------------------------- ### Estimate Storage Size with ClassicLevel Source: https://context7.com/level/classic-level/llms.txt Use `db.approximateSize(start, end)` to estimate the disk space used by entries within a specified key range. This is useful for monitoring storage and deciding when to perform manual compaction. Options for `keyEncoding` can be provided. ```javascript const db = new ClassicLevel('./mydb') // Write some data first and reopen to ensure it is packed into SST files await db.batch( Array.from({ length: 1000 }, (_, i) => ({ type: 'put', key: `key:${String(i).padStart(4, '0')}`, value: 'x'.repeat(100) })) ) await db.close() await db.open() const bytes = await db.approximateSize('key:0000', 'key:~') console.log(`Range uses ~${bytes} bytes`) // With custom key encoding const size = await db.approximateSize('a', 'z', { keyEncoding: 'utf8' }) console.log(size) // number await db.close() ``` -------------------------------- ### Custom Filter Policy Implementation Source: https://github.com/level/classic-level/blob/main/deps/leveldb/leveldb-1.20/doc/index.md Example of implementing a custom filter policy that ignores trailing spaces. This is necessary when using a custom comparator that also ignores trailing spaces to ensure filter compatibility. ```c++ class CustomFilterPolicy : public leveldb::FilterPolicy { private: FilterPolicy* builtin_policy_; public: CustomFilterPolicy() : builtin_policy_(NewBloomFilterPolicy(10)) {} ~CustomFilterPolicy() { delete builtin_policy_; } const char* Name() const { return "IgnoreTrailingSpacesFilter"; } void CreateFilter(const Slice* keys, int n, std::string* dst) const { // Use builtin bloom filter code after removing trailing spaces std::vector trimmed(n); for (int i = 0; i < n; i++) { trimmed[i] = RemoveTrailingSpaces(keys[i]); } return builtin_policy_->CreateFilter(&trimmed[i], n, dst); } }; ``` -------------------------------- ### Create Consistent Snapshots with ClassicLevel Source: https://context7.com/level/classic-level/llms.txt Use `db.snapshot()` to create a reusable, named snapshot. Pass this snapshot to read operations (`get`, `iterator`) to ensure they view a consistent point-in-time state, unaffected by concurrent writes. ```javascript const db = new ClassicLevel('./mydb', { valueEncoding: 'json' }) await db.put('counter', 0) const snap = db.snapshot() // Concurrent writes do not affect reads through the snapshot await db.put('counter', 99) // Both reads see the snapshot value (0), not the live value (99) const v1 = await db.get('counter', { snapshot: snap }) const v2 = await db.get('counter', { snapshot: snap }) console.log(v1, v2) // 0 0 // Iterators through the snapshot also stay consistent for await (const [k, v] of db.iterator({ snapshot: snap })) { console.log(k, v) // counter 0 } await snap.close() await db.close() ``` -------------------------------- ### Get value as Buffer Source: https://github.com/level/classic-level/blob/main/UPGRADING.md To retrieve values as Buffers, specify `valueEncoding: 'buffer'`. This replaces the `valueAsBuffer: true` option. ```javascript db.get('example', { valueEncoding: 'buffer' }, callback) const buf = await db.get('example', { valueEncoding: 'buffer' }) ``` -------------------------------- ### LevelDB Read and Write Operations Source: https://github.com/level/classic-level/blob/main/deps/leveldb/leveldb-1.20/doc/index.md Performs a sequence of Get, Put, and Delete operations. Note that these operations are not atomic as a whole. ```c++ std::string value; leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value); if (s.ok()) s = db->Put(leveldb::WriteOptions(), key2, value); if (s.ok()) s = db->Delete(leveldb::WriteOptions(), key1); ``` -------------------------------- ### Get value as string (default encoding) Source: https://github.com/level/classic-level/blob/main/UPGRADING.md The default encoding is 'utf8', so `db.get` returns a string unless otherwise specified. This replaces the `asBuffer: false` option. ```javascript db.get('example', callback) const str = await db.get('example') ``` -------------------------------- ### Open Database with Bloom Filter Source: https://github.com/level/classic-level/blob/main/deps/leveldb/leveldb-1.20/doc/index.md Associates a Bloom filter with the database to reduce disk reads for Get() calls. Recommended for applications with working sets that do not fit in memory and perform many random reads. Ensure compatibility with custom comparators. ```c++ leveldb::Options options; options.filter_policy = NewBloomFilterPolicy(10); leveldb::DB* db; leveldb::DB::Open(options, "/tmp/testdb", &db); ... use the database ... delete db; delete options.filter_policy; ``` -------------------------------- ### Get Approximate Sizes of Key Ranges Source: https://github.com/level/classic-level/blob/main/deps/leveldb/leveldb-1.20/doc/index.md Retrieves the approximate number of bytes of file system space used by specified key ranges. Useful for understanding disk space consumption. ```c++ leveldb::Range ranges[2]; ranges[0] = leveldb::Range("a", "c"); ranges[1] = leveldb::Range("x", "z"); uint64_t sizes[2]; leveldb::Status s = db->GetApproximateSizes(ranges, 2, sizes); ``` -------------------------------- ### Iterate Through a Key Range in LevelDB Source: https://github.com/level/classic-level/blob/main/deps/leveldb/leveldb-1.20/doc/index.md This code iterates through keys within a specified range [start, limit). The loop continues as long as the iterator is valid and the current key is less than the limit. ```c++ for (it->Seek(start); it->Valid() && it->key().ToString() < limit; it->Next()) { ... } ``` -------------------------------- ### Trigger Manual Compaction in ClassicLevel Source: https://context7.com/level/classic-level/llms.txt Use `db.compactRange(start, end)` to manually trigger LevelDB compaction for a given key range. This reclaims disk space from deleted or overwritten entries and merges SST files, typically used after bulk operations. ```javascript const db = new ClassicLevel('./mydb') // Bulk delete followed by compaction to reclaim space await db.clear({ gte: 'archive:', lte: 'archive:~' }) await db.compactRange('archive:', 'archive:~') console.log('Compaction complete') // Compact the full keyspace (use '!' and '~' as practical bounds) await db.compactRange('!', '~') await db.close() ``` -------------------------------- ### Define Custom Comparator for LevelDB Source: https://github.com/level/classic-level/blob/main/deps/leveldb/leveldb-1.20/doc/index.md Subclass `leveldb::Comparator` to implement custom key ordering logic. This example defines a comparator for keys composed of two numbers, sorting by the first then the second. ```c++ class TwoPartComparator : public leveldb::Comparator { public: // Three-way comparison function: // if a < b: negative result // if a > b: positive result // else: zero result int Compare(const leveldb::Slice& a, const leveldb::Slice& b) const { int a1, a2, b1, b2; ParseKey(a, &a1, &a2); ParseKey(b, &b1, &b2); if (a1 < b1) return -1; if (a1 > b1) return +1; if (a2 < b2) return -1; if (a2 > b2) return +1; return 0; } // Ignore the following methods for now: const char* Name() const { return "TwoPartComparator"; } void FindShortestSeparator(std::string*, const leveldb::Slice&) const {} void FindShortSuccessor(std::string*) const {} }; ``` -------------------------------- ### Initialize classic-level with default options Source: https://github.com/level/classic-level/blob/main/UPGRADING.md Use the `new` keyword to instantiate `ClassicLevel`. The database path is the first argument. ```javascript const { ClassicLevel } = require('classic-level') const db = new ClassicLevel('./db') ``` -------------------------------- ### Get value as Uint8Array Source: https://github.com/level/classic-level/blob/main/UPGRADING.md Use `valueEncoding: 'view'` to retrieve values as Uint8Array. This is a new option. ```javascript const arr = await db.get('example', { valueEncoding: 'view' }) ``` -------------------------------- ### Initialize classic-level with constructor options Source: https://github.com/level/classic-level/blob/main/UPGRADING.md Pass options directly to the `ClassicLevel` constructor for deferred open behavior. Options are shallowly merged if `db.open()` is called later. ```javascript const db = new ClassicLevel('./db', { createIfMissing: false, compression: false }) ``` -------------------------------- ### new ClassicLevel(location[, options]) Source: https://context7.com/level/classic-level/llms.txt Opens or creates a LevelDB database at the specified directory path. It supports various options for configuration and performance tuning, and automatically handles opening the database before the first operation. ```APIDOC ## new ClassicLevel(location[, options]) — Open or create a database Creates or opens a LevelDB database at the given directory path. The constructor accepts all `abstract-level` options plus LevelDB-specific performance tuning options. The directory is created recursively if `createIfMissing` is true (the default). ### Parameters #### Path Parameters - **location** (string) - Required - The directory path for the database. #### Options - **valueEncoding** (string) - Optional - Encoding for values (e.g., 'json', 'utf8', 'buffer'). - **compression** (boolean) - Optional - Enable Snappy compression (default: true). - **cacheSize** (number) - Optional - LRU block cache size in bytes (default: 8MB). - **writeBufferSize** (number) - Optional - Write buffer size in bytes (default: 4MB). - **blockSize** (number) - Optional - SST block size in bytes (default: 4096). - **maxOpenFiles** (number) - Optional - Maximum open file descriptors (default: 1000). - **maxFileSize** (number) - Optional - Maximum SST file size in bytes (default: 2MB). ### Request Example ```javascript const { ClassicLevel } = require('classic-level') // Open with JSON value encoding and custom LevelDB tuning const db = new ClassicLevel('./mydb', { valueEncoding: 'json', compression: true, cacheSize: 16 * 1024 * 1024, writeBufferSize: 8 * 1024 * 1024, blockSize: 4096, maxOpenFiles: 2000, maxFileSize: 4 * 1024 * 1024 }) // db.open() is called automatically before first operation (deferred open) await db.put('user:1', { name: 'Alice', age: 30 }) console.log(await db.get('user:1')) await db.close() ``` ### TypeScript Example ```typescript import { ClassicLevel } from 'classic-level' const tsDb = new ClassicLevel('./tsdb', { valueEncoding: 'json' }) await tsDb.put('user:1', { name: 'Bob', age: 25 }) const user = await tsDb.get('user:1') await tsDb.close() ``` ``` -------------------------------- ### Initialize Git Submodules Source: https://github.com/level/classic-level/blob/main/README.md Alternatively, initialize submodules within the working tree after cloning the repository. ```bash cd classic-level git submodule update --init --recursive ``` -------------------------------- ### Open LevelDB with Custom Comparator Source: https://github.com/level/classic-level/blob/main/deps/leveldb/leveldb-1.20/doc/index.md Instantiate a custom comparator and pass it via `leveldb::Options` when opening a database. Ensure `options.comparator` is set to your custom comparator instance. ```c++ TwoPartComparator cmp; leveldb::DB* db; leveldb::Options options; options.create_if_missing = true; options.comparator = &cmp; leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db); ... ``` -------------------------------- ### ClassicLevel Constructor Source: https://github.com/level/classic-level/blob/main/README.md Creates or opens a LevelDB database. The location must be a directory path. Options are similar to abstract-level, with additional options for db.open(). ```APIDOC ## new ClassicLevel(location[, options]) ### Description Create a database or open an existing database. The `location` argument must be a directory path (relative or absolute) where LevelDB will store its files. If the directory does not yet exist (and `options.createIfMissing` is true) it will be created recursively. Options are the same as in `abstract-level` except for the additional options accepted by `db.open()` and thus by this constructor. A `classic-level` database obtains an exclusive lock. If another process or instance has already opened the underlying LevelDB store at the same `location` then opening will fail with error code [`LEVEL_LOCKED`](https://github.com/Level/abstract-level#errors). ``` -------------------------------- ### Publishing a New Version Source: https://github.com/level/classic-level/blob/main/README.md Steps for publishing a new version of the package, including version increment, pushing to GitHub, downloading prebuilds, and publishing to npm. ```bash npm version .. git push --follow-tags npm run download-prebuilds npm publish ``` -------------------------------- ### Get Internal LevelDB Properties Source: https://context7.com/level/classic-level/llms.txt Retrieves internal LevelDB statistics like the number of SST files per level or detailed compaction stats. Useful for diagnostics and tuning. ```javascript const db = new ClassicLevel('./mydb') await db.open() // Number of SST files at each level for (let i = 0; i < 7; i++) { console.log(`Level ${i}: ${db.getProperty('leveldb.num-files-at-level' + i)} files`) } // Detailed internal statistics (compaction stats, cache, etc.) console.log(db.getProperty('leveldb.stats')) // Compactions // Level Files Size(MB) Time(sec) Read(MB) Write(MB) // -------------------------------------------------- // 0 1 0 0 0 0 // 1 1 0 0 0 0 // List all SST files console.log(db.getProperty('leveldb.sstables')) await db.close() ``` -------------------------------- ### Initialize classic-level and create sublevel Source: https://github.com/level/classic-level/blob/main/UPGRADING.md Replace wrappers like `levelup`, `encoding-down`, and `subleveldown` with `ClassicLevel` and its built-in `sublevel` method. ```javascript const { ClassicLevel } = require('classic-level') const db = new ClassicLevel('./db') const sublevel = db.sublevel('foo') ``` -------------------------------- ### Open LevelDB Database Source: https://github.com/level/classic-level/blob/main/deps/leveldb/leveldb-1.20/doc/index.md Opens a LevelDB database, creating it if it does not exist. Ensure the directory is accessible and writable. ```c++ #include #include "leveldb/db.h" leveldb::DB* db; leveldb::Options options; options.create_if_missing = true; leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db); assert(status.ok()); ... ``` -------------------------------- ### ClassicLevel TypeScript Usage with Generics Source: https://github.com/level/classic-level/blob/main/README.md Illustrates how to use ClassicLevel with TypeScript, specifying key and value types using generic parameters. Shows type inference and usage with sublevels. ```typescript // Specify types of keys and values (any, in the case of json). // The generic type parameters default to ClassicLevel. const db = new ClassicLevel('./db', { valueEncoding: 'json' }) // All relevant methods then use those types await db.put('a', { x: 123 }) // Specify different types when overriding encoding per operation await db.get('a', { valueEncoding: 'utf8' }) // Though in some cases TypeScript can infer them await db.get('a', { valueEncoding: db.valueEncoding('utf8') }) // It works the same for sublevels const abc = db.sublevel('abc') const xyz = db.sublevel('xyz', { valueEncoding: 'json' }) ``` -------------------------------- ### Open Database with ClassicLevel Source: https://context7.com/level/classic-level/llms.txt Instantiate ClassicLevel to open or create a LevelDB database. Supports custom options for value encoding and LevelDB performance tuning. TypeScript users can specify key/value types using generics. ```javascript const { ClassicLevel } = require('classic-level') // Open with JSON value encoding and custom LevelDB tuning const db = new ClassicLevel('./mydb', { valueEncoding: 'json', // values are auto-serialized/deserialized as JSON compression: true, // Snappy compression (default: true) cacheSize: 16 * 1024 * 1024, // 16 MB LRU block cache (default: 8 MB) writeBufferSize: 8 * 1024 * 1024, // 8 MB write buffer (default: 4 MB) blockSize: 4096, // SST block size in bytes (default: 4096) maxOpenFiles: 2000, // max open file descriptors (default: 1000) maxFileSize: 4 * 1024 * 1024, // max SST file size (default: 2 MB) }) // db.open() is called automatically before first operation (deferred open) await db.put('user:1', { name: 'Alice', age: 30 }) console.log(await db.get('user:1')) // { name: 'Alice', age: 30 } await db.close() ``` ```typescript // TypeScript — specify key/value types via generics import { ClassicLevel } from 'classic-level' const tsDb = new ClassicLevel('./tsdb', { valueEncoding: 'json' }) await tsDb.put('user:1', { name: 'Bob', age: 25 }) const user = await tsDb.get('user:1') // typed as { name: string; age: number } | undefined await tsDb.close() ``` -------------------------------- ### db.sublevel(prefix[, options]) Source: https://context7.com/level/classic-level/llms.txt Creates a namespaced sublevel, acting as an independent logical database within the same LevelDB store. ```APIDOC ## `db.sublevel(prefix[, options])` — Namespaced sub-database Creates a sublevel that prefixes all keys with a namespace separator. Sublevels are fully independent logical databases sharing the same underlying LevelDB store and can themselves have sublevels. ```js const db = new ClassicLevel('./mydb', { valueEncoding: 'json' }) const users = db.sublevel('users') const sessions = db.sublevel('sessions') const metadata = users.sublevel('meta') // nested sublevel await users.put('1', { name: 'Alice' }) await sessions.put('abc', { userId: '1', expires: Date.now() + 3600_000 }) await metadata.put('schema', { version: 3 }) // Keys are isolated — no cross-contamination for await (const [key, value] of users.iterator()) { console.log(key, value) // '1' { name: 'Alice' } } // Batch across multiple sublevels atomically await db.batch([ { type: 'put', key: '2', value: { name: 'Bob' }, sublevel: users }, { type: 'del', key: 'old-session', sublevel: sessions } ]) await db.close() ``` ``` -------------------------------- ### db.snapshot([options]) Source: https://context7.com/level/classic-level/llms.txt Creates a reusable, named snapshot of the database for consistent, point-in-time read operations. ```APIDOC ## `db.snapshot([options])` — Explicit read snapshot Creates a reusable, named snapshot of the database. Pass the snapshot to multiple read operations to ensure they all see a consistent point-in-time view, even as writes continue. ```js const db = new ClassicLevel('./mydb', { valueEncoding: 'json' }) await db.put('counter', 0) const snap = db.snapshot() // Concurrent writes do not affect reads through the snapshot await db.put('counter', 99) // Both reads see the snapshot value (0), not the live value (99) const v1 = await db.get('counter', { snapshot: snap }) const v2 = await db.get('counter', { snapshot: snap }) console.log(v1, v2) // 0 0 // Iterators through the snapshot also stay consistent for await (const [k, v] of db.iterator({ snapshot: snap })) { console.log(k, v) // counter 0 } await snap.close() await db.close() ``` ``` -------------------------------- ### Configure LevelDB LRU Cache Source: https://github.com/level/classic-level/blob/main/deps/leveldb/leveldb-1.20/doc/index.md Create and configure an LRU cache using `leveldb::NewLRUCache` and assign it to `options.cache`. The cache size should be based on application-level data sizes, not compressed sizes. ```c++ #include "leveldb/cache.h" leveldb::Options options; options.cache = leveldb::NewLRUCache(100 * 1048576); // 100MB cache leveldb::DB* db; leveldb::DB::Open(options, name, &db); ... use the db ... delete db delete options.cache; ``` -------------------------------- ### Write Entry with db.put() Source: https://context7.com/level/classic-level/llms.txt Store a key-value pair using `db.put()`. Use the `sync: true` option for `fsync()` before resolving, which guarantees data on disk but slows writes. Per-operation encoding overrides are also supported. ```javascript const db = new ClassicLevel('./mydb', { valueEncoding: 'json' }) // Basic put await db.put('session:abc', { userId: 42, expires: Date.now() + 3600_000 }) // Synchronous disk write (fsync before resolving) await db.put('critical:config', { version: 2 }, { sync: true }) // Per-operation encoding override await db.put('raw', Buffer.from([0xde, 0xad, 0xbe, 0xef]), { valueEncoding: 'buffer' }) await db.close() ``` -------------------------------- ### SQLite3 Benchmark Source Code Link Source: https://github.com/level/classic-level/blob/main/deps/leveldb/leveldb-1.20/doc/benchmark.html Link to the source code for the SQLite3 benchmark tool. ```plaintext doc/bench/db_bench_sqlite3.cc ``` -------------------------------- ### LevelDB Benchmark Source Code Link Source: https://github.com/level/classic-level/blob/main/deps/leveldb/leveldb-1.20/doc/benchmark.html Link to the source code for the LevelDB benchmark tool. ```plaintext db/db_bench.cc ``` -------------------------------- ### Iterate Keys or Values with ClassicLevel Source: https://context7.com/level/classic-level/llms.txt Use `db.keys()` for key-only iteration and `db.values()` for value-only iteration to optimize performance by avoiding transfer of the unused data half. Options like `gte`, `lte`, `limit`, and `reverse` can filter the iteration. ```javascript const db = new ClassicLevel('./mydb', { valueEncoding: 'json' }) // Keys only for await (const key of db.keys({ gte: 'user:', lte: 'user:~' })) { console.log(key) // 'user:1', 'user:2', ... } // Values only for await (const value of db.values({ limit: 5, reverse: true })) { console.log(value) // most recent 5 values } await db.close() ``` -------------------------------- ### db.get(key[, options]) Source: https://context7.com/level/classic-level/llms.txt Retrieves the value associated with a given key from the database. If the key is not found, it returns `undefined`. Reads are performed against a point-in-time snapshot, and the `fillCache` option can be used to control LRU cache population. ```APIDOC ## db.get(key[, options]) — Read a single entry Returns the value for a key, or `undefined` if not found. Reads from a point-in-time snapshot. `fillCache: false` skips populating the LRU block cache, useful for large sequential scans where caching would be wasteful. ### Parameters #### Path Parameters - **key** (any) - Required - The key to retrieve. #### Options - **valueEncoding** (string) - Optional - Encoding for the value for this specific operation (overrides constructor option). - **fillCache** (boolean) - Optional - Whether to populate the LRU block cache (default: true). ### Request Example ```javascript const db = new ClassicLevel('./mydb', { valueEncoding: 'json' }) // Standard get — returns undefined if key does not exist const value = await db.get('user:1') if (value === undefined) { console.log('Key not found') } else { console.log(value) } // Per-operation encoding override const raw = await db.get('raw', { valueEncoding: 'buffer' }) // raw is a Buffer // Skip LRU cache population (good for one-off large reads) const nocache = await db.get('big-blob', { fillCache: false }) await db.close() ``` ``` -------------------------------- ### db.put(key, value[, options]) Source: https://context7.com/level/classic-level/llms.txt Stores a key-value pair in the database. It supports an optional `sync` flag to ensure data is written to disk before the operation resolves, which guarantees persistence at the cost of performance. ```APIDOC ## db.put(key, value[, options]) — Write a single entry Stores a key-value pair. Accepts an optional `sync` flag to force an `fsync()` before resolving, guaranteeing the data is on disk at the cost of significantly slower writes. ### Parameters #### Path Parameters - **key** (any) - Required - The key to store. - **value** (any) - Required - The value to store. #### Options - **sync** (boolean) - Optional - If true, forces an `fsync()` before resolving (default: false). - **valueEncoding** (string) - Optional - Encoding for the value for this specific operation (overrides constructor option). ### Request Example ```javascript const db = new ClassicLevel('./mydb', { valueEncoding: 'json' }) // Basic put await db.put('session:abc', { userId: 42, expires: Date.now() + 3600_000 }) // Synchronous disk write (fsync before resolving) await db.put('critical:config', { version: 2 }, { sync: true }) // Per-operation encoding override await db.put('raw', Buffer.from([0xde, 0xad, 0xbe, 0xef]), { valueEncoding: 'buffer' }) await db.close() ``` ``` -------------------------------- ### Kyoto TreeDB Benchmark Source Code Link Source: https://github.com/level/classic-level/blob/main/deps/leveldb/leveldb-1.20/doc/benchmark.html Link to the source code for the Kyoto TreeDB benchmark tool. ```plaintext doc/bench/db_bench_tree_db.cc ``` -------------------------------- ### Open LevelDB Database with Error on Existing Source: https://github.com/level/classic-level/blob/main/deps/leveldb/leveldb-1.20/doc/index.md Configures LevelDB to raise an error if the database directory already exists upon opening. Use this when you need to ensure a fresh database. ```c++ options.error_if_exists = true; ``` -------------------------------- ### Clone Repository with Submodules Source: https://github.com/level/classic-level/blob/main/README.md Clone the repository recursively to include all git submodules required for development. ```bash git clone --recurse-submodules https://github.com/Level/classic-level.git ``` -------------------------------- ### db.compactRange Source: https://github.com/level/classic-level/blob/main/README.md Manually initiates a database compaction process for a specified key range. This can help optimize storage and performance. ```APIDOC ## db.compactRange(start, end[, options]) ### Description Manually trigger a database compaction in the range `[start..end]`. ### Parameters #### Path Parameters - `start` (key) - Required - The starting key of the range. - `end` (key) - Required - The ending key of the range (inclusive). #### Query Parameters - `options` (object) - Optional - Configuration options. - `keyEncoding` (string) - Custom key encoding for `start` and `end`. ### Response Returns a promise that resolves when the compaction is complete. ``` -------------------------------- ### Fluent batch builder with db.batch() (chained) Source: https://context7.com/level/classic-level/llms.txt The no-argument form of db.batch() returns a ChainedBatch for building operations with a fluent API before writing them all at once. The `sync` option can be passed to the `write()` method for durable writes. ```javascript const db = new ClassicLevel('./mydb', { valueEncoding: 'json' }) await db.batch() .put('product:1', { name: 'Widget', price: 9.99 }) .put('product:2', { name: 'Gadget', price: 24.99 }) .del('product:discontinued') .put('inventory:1', 500) .write({ sync: true }) // flush to disk synchronously await db.close() ``` -------------------------------- ### Custom Environment Implementation in LevelDB Source: https://github.com/level/classic-level/blob/main/deps/leveldb/leveldb-1.20/doc/index.md Implement a custom `leveldb::Env` to control file operations, such as introducing artificial delays for IO management. This is useful for advanced applications needing fine-grained control over LevelDB's interaction with the operating system. ```c++ class SlowEnv : public leveldb::Env { ... implementation of the Env interface ... }; SlowEnv env; leveldb::Options options; options.env = &env; Status s = leveldb::DB::Open(options, ...); ``` -------------------------------- ### db.iterator([options]) Source: https://context7.com/level/classic-level/llms.txt Returns an async iterator over entries in key-sorted order. Supports range filters and the `highWaterMarkBytes` option to cap memory usage during iteration. ```APIDOC ## `db.iterator([options])` — Range iteration Returns an async iterator over entries in key-sorted order. Supports range filters (`gt`, `gte`, `lt`, `lte`, `limit`, `reverse`) and the `highWaterMarkBytes` option to cap memory usage during iteration. ### Parameters #### Options - **options** (object) - Optional - Configuration options for the iterator. - **gt** (string) - Optional - Greater than. - **gte** (string) - Optional - Greater than or equal to. - **lt** (string) - Optional - Less than. - **lte** (string) - Optional - Less than or equal to. - **limit** (number) - Optional - Maximum number of entries to return. - **reverse** (boolean) - Optional - If true, iterate in reverse order. - **highWaterMarkBytes** (number) - Optional - Maximum number of bytes to buffer in memory during iteration. - **signal** (AbortSignal) - Optional - An AbortSignal to cancel the iteration. ### Request Example ```javascript const db = new ClassicLevel('./mydb', { valueEncoding: 'json' }) // Load test data await db.batch([ { type: 'put', key: 'user:1', value: { name: 'Alice' } }, { type: 'put', key: 'user:2', value: { name: 'Bob' } }, { type: 'put', key: 'user:3', value: { name: 'Carol' } }, { type: 'put', key: 'event:1', value: { type: 'login' } } ]) // for-await iteration over a range for await (const [key, value] of db.iterator({ gte: 'user:', lte: 'user:~' })) { console.log(key, value) // user:1 { name: 'Alice' } // user:2 { name: 'Bob' } // user:3 { name: 'Carol' } } // Reverse, limited iteration for await (const [key, value] of db.iterator({ reverse: true, limit: 2 })) { console.log(key) // user:3, user:2 } // Memory-bounded batch reads with nextv() const it = db.iterator({ highWaterMarkBytes: 1024 }) const batch = await it.nextv(100) // up to 100 entries, or fewer if 1024 bytes exceeded await it.close() // Abort iteration via AbortSignal const controller = new AbortController() setTimeout(() => controller.abort(), 50) try { for await (const entry of db.iterator({ signal: controller.signal })) { // process entries } } catch (err) { if (err.code === 'LEVEL_ITERATOR_NOT_OPEN') console.log('Aborted') } await db.close() ``` ### Response #### Success Response (Async Iterator) - Returns an async iterator that yields entries as `[key, value]` pairs. Each entry is decoded according to the `valueEncoding` option. ``` -------------------------------- ### db.getSync(key[, options]) Source: https://context7.com/level/classic-level/llms.txt Synchronously reads a value from the database without returning a Promise. This method is useful for performance-critical code paths where asynchronous overhead needs to be minimized. It maintains the same snapshot and encoding semantics as `db.get()`. ```APIDOC ## db.getSync(key[, options]) — Synchronous single-entry read Reads a value synchronously without returning a Promise. Useful in tight loops or when async overhead matters. Same snapshot and encoding semantics as `db.get()`. ### Parameters #### Path Parameters - **key** (any) - Required - The key to retrieve. #### Options - **valueEncoding** (string) - Optional - Encoding for the value for this specific operation (overrides constructor option). ### Request Example ```javascript const db = new ClassicLevel('./mydb') await db.open() // Synchronous — blocks the event loop but avoids Promise overhead const value = db.getSync('counter') console.log(value) // With encoding override const buf = db.getSync('binary-key', { valueEncoding: 'buffer' }) await db.close() ``` ``` -------------------------------- ### db.getMany(keys[, options]) Source: https://context7.com/level/classic-level/llms.txt Fetches multiple values in a single native call, returning an array aligned with the input keys. Missing keys are `undefined` in the result. ```APIDOC ## `db.getMany(keys[, options])` — Batch read multiple entries Fetches multiple values in a single native call, returning an array aligned with the input keys. Missing keys are `undefined` in the result. ### Parameters #### Path Parameters - **keys** (Array) - Required - An array of keys to fetch. #### Options - **options** (object) - Optional - Configuration options for the operation. ### Request Example ```javascript const db = new ClassicLevel('./mydb', { valueEncoding: 'json' }) await db.batch([ { type: 'put', key: 'a', value: 1 }, { type: 'put', key: 'b', value: 2 }, { type: 'put', key: 'c', value: 3 } ]) // Fetch multiple keys at once — result is always same length as input const [a, b, missing, c] = await db.getMany(['a', 'b', 'nope', 'c']) console.log(a, b, missing, c) // 1, 2, undefined, 3 await db.close() ``` ### Response #### Success Response (Array) - Returns an array of values corresponding to the input keys. Missing keys will have `undefined` values. ``` -------------------------------- ### db.batch() (chained) Source: https://context7.com/level/classic-level/llms.txt The no-argument form of `db.batch()` returns a `ChainedBatch` for building operations with a fluent API before writing them all at once. ```APIDOC ## `db.batch()` (chained) — Fluent batch builder The no-argument form of `db.batch()` returns a `ChainedBatch` for building operations with a fluent API before writing them all at once. ### Methods on ChainedBatch - **put(key, value[, options])**: Adds a `put` operation. - **del(key[, options])**: Adds a `del` operation. - **write([options])**: Writes all accumulated operations. ### Parameters for `write()` #### Options - **options** (object) - Optional - Configuration options. - **sync** (boolean) - Optional - If true, performs a synchronous `fsync` before resolving the promise, ensuring the write is durable. ### Request Example ```javascript const db = new ClassicLevel('./mydb', { valueEncoding: 'json' }) await db.batch() .put('product:1', { name: 'Widget', price: 9.99 }) .put('product:2', { name: 'Gadget', price: 24.99 }) .del('product:discontinued') .put('inventory:1', 500) .write({ sync: true }) // flush to disk synchronously await db.close() ``` ### Response #### Success Response (void) - Resolves when all accumulated operations have been written. ``` -------------------------------- ### db.has(key[, options]) / db.hasMany(keys[, options]) Source: https://context7.com/level/classic-level/llms.txt Efficiently checks whether one or more keys exist without fetching their values. `hasMany()` uses an internal bitset for space-efficient parallel lookups. ```APIDOC ## `db.has(key[, options])` / `db.hasMany(keys[, options])` — Existence checks Efficiently checks whether one or more keys exist without fetching their values. `hasMany()` uses an internal bitset for space-efficient parallel lookups. ### Parameters #### Path Parameters - **key** (string) - Required - The key to check for existence. - **keys** (Array) - Required - An array of keys to check for existence. #### Options - **options** (object) - Optional - Configuration options. - **fillCache** (boolean) - Optional - Whether to populate the LRU cache during the check. Defaults to true. ### Request Example ```javascript const db = new ClassicLevel('./mydb') await db.put('exists', 'yes') // Single key check console.log(await db.has('exists')) // true console.log(await db.has('nope')) // false // Multi-key check — returns boolean[] const results = await db.hasMany(['exists', 'nope', 'exists']) console.log(results) // [true, false, true] // Skip LRU cache during existence check console.log(await db.has('exists', { fillCache: false })) // true await db.close() ``` ### Response #### Success Response (Boolean for `has`, Array for `hasMany`) - `db.has()` returns `true` if the key exists, `false` otherwise. - `db.hasMany()` returns an array of booleans, where each boolean corresponds to the existence of the key at the same index in the input array. ``` -------------------------------- ### db.keys([options]) / db.values([options]) Source: https://context7.com/level/classic-level/llms.txt Provides efficient iterators that yield only keys or only values from the database, reducing overhead. ```APIDOC ## `db.keys([options])` / `db.values([options])` — Key-only or value-only iteration Efficient iterators that yield only keys or only values, avoiding the overhead of transferring the other half of each entry. ```js const db = new ClassicLevel('./mydb', { valueEncoding: 'json' }) // Keys only for await (const key of db.keys({ gte: 'user:', lte: 'user:~' })) { console.log(key) // 'user:1', 'user:2', ... } // Values only for await (const value of db.values({ limit: 5, reverse: true })) { console.log(value) // most recent 5 values } await db.close() ``` ``` -------------------------------- ### Multithreading with Worker Threads Source: https://context7.com/level/classic-level/llms.txt Demonstrates how to share a single LevelDB store across multiple Node.js worker threads using the `multithreading: true` option. ```APIDOC ## Multithreading with Worker Threads The `multithreading` option allows a single LevelDB store to be shared across multiple Node.js worker threads in the same process. All instances at the same location must opt in with `multithreading: true`. ```js // main.js const { Worker } = require('worker_threads') const { ClassicLevel } = require('classic-level') const db = new ClassicLevel('./shared-db', { multithreading: true }) await db.open() // Spawn workers that also open the same db const worker = new Worker('./worker.js') worker.on('message', (msg) => console.log('Worker says:', msg)) worker.on('exit', async () => { await db.close() }) // worker.js const { workerData, parentPort } = require('worker_threads') const { ClassicLevel } = require('classic-level') const db = new ClassicLevel('./shared-db', { multithreading: true }) await db.open() await db.put('from-worker', 'hello') parentPort.postMessage('done') await db.close() ``` ``` -------------------------------- ### Read Entry with db.get() Source: https://context7.com/level/classic-level/llms.txt Retrieve a value by key using `db.get()`. Returns `undefined` if the key is not found. Reads are from a point-in-time snapshot. Use `fillCache: false` to skip populating the LRU block cache for large, sequential reads. ```javascript const db = new ClassicLevel('./mydb', { valueEncoding: 'json' }) // Standard get — returns undefined if key does not exist const value = await db.get('user:1') if (value === undefined) { console.log('Key not found') } else { console.log(value) // { name: 'Alice', age: 30 } } // Per-operation encoding override const raw = await db.get('raw', { valueEncoding: 'buffer' }) // raw is a Buffer // Skip LRU cache population (good for one-off large reads) const nocache = await db.get('big-blob', { fillCache: false }) await db.close() ``` -------------------------------- ### db.batch(operations[, options]) Source: https://context7.com/level/classic-level/llms.txt Performs an array of `put` and `del` operations atomically. All operations succeed or all fail. Supports the `sync` option for durable writes. ```APIDOC ## `db.batch(operations[, options])` — Atomic multi-operation write Performs an array of `put` and `del` operations atomically. All operations succeed or all fail. Supports the `sync` option for durable writes. ### Parameters #### Path Parameters - **operations** (Array) - Required - An array of operations to perform. Each operation should be an object with: - **type** ('put' | 'del') - The type of operation. - **key** (string) - The key for the operation. - **value** (any) - The value for 'put' operations. - **valueEncoding** (string) - Optional - Overrides the default value encoding for this specific operation. #### Options - **options** (object) - Optional - Configuration options. - **sync** (boolean) - Optional - If true, performs a synchronous `fsync` before resolving the promise, ensuring the write is durable. ### Request Example ```javascript const db = new ClassicLevel('./mydb', { valueEncoding: 'json' }) // Atomic batch write await db.batch([ { type: 'put', key: 'user:1', value: { name: 'Alice', score: 100 } }, { type: 'put', key: 'user:2', value: { name: 'Bob', score: 90 } }, { type: 'del', key: 'user:old' }, { type: 'put', key: 'meta:count', value: 2, valueEncoding: 'json' } ]) // Per-operation encoding override inside batch await db.batch([ { type: 'put', key: 'bin', value: Buffer.from([1, 2, 3]), valueEncoding: 'buffer' }, { type: 'put', key: 'str', value: 'hello', valueEncoding: 'utf8' } ]) await db.close() ``` ### Response #### Success Response (void) - Resolves when all operations in the batch have been completed atomically. ```