@krishna2nd/indexdb-lite
v1.0.1
Published
Fast, portable IndexedDB implementation for Node.js with native C++ backend
Maintainers
Readme
local-indexed-db (Node.js Binding)
A fast, efficient Node.js binding for the Local Indexed DB C++ library. Store and retrieve data with IndexedDB semantics using native performance.
Architecture (visual)
flowchart LR
subgraph JS [JavaScript Layer]
A[App] --> B[`lib/index.js`]
end
subgraph Native [Native Layer]
B --> C[`local_indexed_db_native.node`]
C --> D[Portable C++ Library]
end
subgraph Storage [Storage]
D -->|abstracts| E{IStorage}
E --> F[InMemoryStorage]
E --> G[File-backed (demo: file_db.js)]
E --> H[LevelDB/RocksDB (prod)]
end
style JS fill:#f3f9ff,stroke:#0366d6
style Native fill:#fff6f0,stroke:#d73a49
style Storage fill:#f0fff4,stroke:#22863a(Diagram: put/get flow between JS, native addon, C++ library and storage)
Installation
From source
npm install local-indexed-db
# or
git clone <repo>
cd nodejs
npm install
npm run buildRequirements
- Node.js 12.0.0 or higher
- Python 3.6+ (for node-gyp)
- C++17 compatible compiler (GCC 7+, Clang 5+)
Quick Start
const { Database, IDBKey, Encoding, Status } = require('local-indexed-db');
// Create a database
const db = new Database();
// Store values
db.put('key1', 'value1');
db.put('user:123', JSON.stringify({ name: 'Alice', age: 30 }));
// Retrieve values
const result = db.get('key1');
if (Database.isOk(result)) {
console.log('Found:', result.value);
} else if (Database.isNotFound(result)) {
console.log('Key not found');
}
// Atomic batch operations
const batch = [
['key1', 'new_value'],
['key2', 'another_value'],
['key3', null] // null = delete
];
db.commitBatch(batch);
// Delete a key
db.delete('key1');API
Database
new Database()
Create a new in-memory database instance.
const db = new Database();put(key, value) -> number
Store a key-value pair. Returns status code (0 = OK).
const status = db.put('mykey', 'myvalue');get(key) -> Object
Retrieve a value by key. Returns {status, value}.
const result = db.get('mykey');
if (Database.isOk(result)) {
console.log(result.value);
}Status codes:
Status.OK(0): SuccessStatus.NOT_FOUND(1): Key doesn't existStatus.ERROR(2): Error occurred
delete(key) -> number
Delete a key-value pair. Returns status code.
db.delete('mykey');commitBatch(batch) -> number
Commit multiple operations atomically.
const batch = [
['key1', 'value1'],
['key2', 'value2'],
['key3', null] // delete
];
db.commitBatch(batch);Database.isOk(result) -> boolean
Check if a get() result is successful.
if (Database.isOk(db.get('key'))) { /* ... */ }Database.isNotFound(result) -> boolean
Check if a get() result indicates key not found.
if (Database.isNotFound(db.get('key'))) { /* ... */ }IDBKey
Utilities for working with IndexedDB key types.
new IDBKey(value)
Create a key from a value. Automatically detects type (number, string, array, etc.).
const numKey = new IDBKey(42);
const strKey = new IDBKey('abc');
const arrKey = new IDBKey([1, 'two', null]);IDBKey.null()
Create a null key.
const nullKey = IDBKey.null();IDBKey.date(ms)
Create a date key (stored as milliseconds since epoch).
const dateKey = IDBKey.date(Date.now());Key Types
IDBKey.TYPES = {
INVALID: 0,
NULL: 1,
NUMBER: 2,
DATE: 3,
STRING: 4,
BINARY: 5,
ARRAY: 6
};Encoding
Utilities for encoding/decoding keys.
Encoding.encodeKey(key) -> Buffer
Encode an IDBKey to a buffer.
const key = new IDBKey('test');
const encoded = Encoding.encodeKey(key);Encoding.decodeKey(buffer) -> IDBKey
Decode a buffer back to an IDBKey.
const decoded = Encoding.decodeKey(encoded);Examples
JSON Documents
const db = new Database();
const user = { id: 1, name: 'Alice', email: '[email protected]' };
db.put('user:1', JSON.stringify(user));
const result = db.get('user:1');
const userData = JSON.parse(result.value);
console.log(userData.name);Numeric Keys
const db = new Database();
// Store with numeric keys
const scores = [
['score:100', 'player1'],
['score:95', 'player2'],
['score:88', 'player3']
];
db.commitBatch(scores);
// Retrieve
const result = db.get('score:100');
console.log(result.value); // 'player1'Key Prefixes
const db = new Database();
// Use prefixes for hierarchical storage
db.put('users:123:profile', '...');
db.put('users:123:settings', '...');
db.put('users:456:profile', '...');
// Retrieve user data
const profile = db.get('users:123:profile');
const settings = db.get('users:123:settings');Transactions with Error Handling
const db = new Database();
function transferFunds(from, to, amount) {
const fromResult = db.get(`account:${from}:balance`);
const toResult = db.get(`account:${to}:balance`);
if (!Database.isOk(fromResult) || !Database.isOk(toResult)) {
console.error('Account not found');
return false;
}
const fromBalance = parseFloat(fromResult.value);
const toBalance = parseFloat(toResult.value);
if (fromBalance < amount) {
console.error('Insufficient funds');
return false;
}
const batch = [
[`account:${from}:balance`, String(fromBalance - amount)],
[`account:${to}:balance`, String(toBalance + amount)]
];
return db.commitBatch(batch) === Status.OK;
}Testing
npm testRun tests with verbose output:
npm test -- --reporter specBuilding
npm run build # Build native module
npm run clean # Clean build artifactsPerformance Notes
- All operations are synchronous (blocking).
- The native C++ backend provides fast key-value operations.
- Batch commits are atomic but single-threaded.
- In-memory storage is suitable for testing and caching; for persistent storage, implement a file-backed
IStoragebackend in C++.
Future Enhancements
- [ ] Async/Promise API
- [ ] Persistent file-backed storage
- [ ] LevelDB backend option
- [ ] SQLite backend option
- [ ] Cursor/range iteration support
- [ ] Transaction API
- [ ] Blob support
License
BSD-3-Clause (compatible with Chromium source)
