A simple, type-safe wrapper for IndexedDB that eliminates the complexity of versions, upgrades, and store management the it was supposed to be.
keyval-db
is a lightweight TypeScript library that simplifies working with IndexedDB by providing a Promise-based API. It automatically handles:
- Database connections and reconnections
- Object store creation
- Version management
- Upgrade processes
- Transaction retries on connection errors
With keyval-db
, you can focus on storing and retrieving data without worrying about the complexities of IndexedDB's low-level API.
npm install keyval-db
pnpm add keyval-db
bun add keyval-db
The main class for interacting with IndexedDB through a key-value interface.
import { IDB } from 'keyval-db';
// Create a new database connection
const db = new IDB('myDatabase', 'myStore');
Parameter | Type | Description |
---|---|---|
db_name | string | The name of the IndexedDB database to connect to |
storeName | string | The name of the object store to use within the database |
A factory function that creates and caches IDB instances cleaning up the cache when the database is dropped.
- Instance Caching: Prevents duplicate database connections
- Memory Efficient: Reuses existing instances instead of creating new ones
- Simplified API: No need to manually manage database instances
- Automatic Cleanup: Instances are automatically removed from cache when database is dropped
import { getDB } from 'keyval-db';
// Create or get a cached database connection
const db = getDB('myDatabase', 'myStore');
// Multiple calls with the same parameters return the same instance
const sameDb = getDB('myDatabase', 'myStore');
console.log(db === sameDb); // true
// Different database or table names create separate instances
const otherDb = getDB('otherDatabase', 'myStore');
const differentStore = getDB('myDatabase', 'otherStore');
Parameter | Type | Description |
---|---|---|
db_name | string | The name of the IndexedDB database to connect to |
tableName | string | The name of the object store to use within the database |
IDB
- A cached IDB instance with all the same methods available
// Basic usage with automatic caching
const userDB = getDB('myApp', 'users');
const settingsDB = getDB('myApp', 'settings');
// Store and retrieve data
await userDB.set('user-123', { name: 'John', email: '[email protected]' });
const user = await userDB.get('user-123');
// The same instance is returned for subsequent calls
const sameUserDB = getDB('myApp', 'users');
await sameUserDB.set('user-456', { name: 'Jane', email: '[email protected]' });
// All IDB methods are available
const allUsers = await userDB.getValues();
const userKeys = await userDB.getKeys();
await userDB.setMultiple([
{ key: 'user-789', value: { name: 'Bob', email: '[email protected]' } },
{ key: 'user-101', value: { name: 'Alice', email: '[email protected]' } }
]);
await userDB.clearStore();
// Drop database (removes from cache automatically)
await userDB.dropDB(); // This removes the instance from cache
Retrieves a value from the database by its key.
// With TypeScript generics for type safety
const user = await db.get<{ name: string; age: number }>('user-123');
console.log(user.name); // Type-safe access
// Using Promise chain
db.get<string>('settings-theme')
.then((theme) => {
console.log(`Current theme: ${theme}`);
})
.catch((err) => {
console.error('Failed to get theme:', err);
});
// Try-catch with await
try {
const count = await db.get<number>('visit-count');
console.log(`Visit count: ${count}`);
} catch (err) {
console.error('Failed to get visit count:', err);
} finally {
console.log('Get operation completed');
}
Parameter | Type | Description |
---|---|---|
key | IDBValidKey | The key to look up in the database |
Promise<T>
- A promise that resolves to the value associated with the key
Retrieves all values stored in the database.
// Get all items as an array with type safety
const allItems = await db.getValues<Array<{ id: string; content: string }>>();
for (const item of allItems) {
console.log(item.id, item.content);
}
// Using Promise chain
db.getValues<string[]>()
.then((values) => {
console.log(`Found ${values.length} values`);
})
.catch((err) => {
console.error('Failed to get values:', err);
});
Promise<T extends Array<any>>
- A promise that resolves to an array of all values
Retrieves all keys stored in the database.
// Get all keys
const allKeys = await db.getKeys();
console.log(`Found ${allKeys.length} keys in the store`);
// Using Promise chain
db.getKeys()
.then((keys) => {
keys.forEach((key) => console.log(`Key: ${key}`));
})
.catch((err) => {
console.error('Failed to get keys:', err);
});
Promise<Array<IDBValidKey>>
- A promise that resolves to an array of all keys
Stores a value in the database with the specified key.
// Simple value
await db.set('settings-theme', 'dark');
// Complex object
await db.set('user-profile', {
name: 'John Doe',
email: '[email protected]',
preferences: {
notifications: true
}
});
// Using Promise chain with type checking
db.set('counter', 5)
.then((result) => {
// result is typed as true
console.log('Value saved:', result);
})
.catch((err) => {
console.error('Failed to save:', err);
});
// Try-catch with await
try {
const result = await db.set('last-login', new Date().toISOString());
console.log('Login time saved:', result); // result is true
} catch (err) {
console.error('Failed to save login time:', err);
}
Parameter | Type | Description |
---|---|---|
key | IDBValidKey | The key to store the value under |
value | unknown | The value to store |
Promise<true>
- A promise that resolves to true
when the operation is complete
Stores multiple key-value pairs in the database in a single transaction.
// Store multiple items in one transaction
await db.setMultiple([
{ key: 'item-1', value: { name: 'Item 1', price: 10 } },
{ key: 'item-2', value: { name: 'Item 2', price: 20 } },
{ key: 'item-3', value: { name: 'Item 3', price: 30 } }
]);
// With type safety
type Product = { name: string; price: number };
const products: Array<{ key: string; value: Product }> = [
{ key: 'product-1', value: { name: 'Product 1', price: 9.99 } },
{ key: 'product-2', value: { name: 'Product 2', price: 19.99 } }
];
const result = await db.setMultiple<Product>(products);
console.log('Products saved:', result); // result is true
// Using Promise chain
db.setMultiple([
{ key: 'setting-1', value: 'value-1' },
{ key: 'setting-2', value: 'value-2' }
])
.then((result) => {
console.log('All settings saved:', result);
})
.catch((err) => {
console.error('Failed to save settings:', err);
});
Parameter | Type | Description |
---|---|---|
items | Array<{ key: IDBValidKey, value: T }> | An array of objects containing key-value pairs to store |
Promise<true>
- A promise that resolves to true
when all items have been stored
Deletes a value from the database by its key.
// Delete an item
await db.del('temporary-data');
// Using Promise chain to check result
db.del('session-token')
.then((result) => {
console.log('Token deleted:', result); // result is true
})
.catch((err) => {
console.error('Failed to delete token:', err);
});
// Try-catch with await
try {
const result = await db.del('cache-item-123');
console.log('Cache item deleted:', result); // result is true
} catch (err) {
console.error('Failed to delete cache item:', err);
}
Parameter | Type | Description |
---|---|---|
key | IDBValidKey | The key of the value to delete |
Promise<true>
- A promise that resolves to true
when the value has been deleted
Clears all data from the current object store.
// Clear all data from the store
await db.clearStore();
// Using Promise chain
db.clearStore()
.then((result) => {
console.log('Store cleared:', result); // result is true
})
.catch((err) => {
console.error('Failed to clear store:', err);
});
// Try-catch with await
try {
const result = await db.clearStore();
console.log('All data cleared:', result); // result is true
} catch (err) {
console.error('Failed to clear data:', err);
}
Promise<true>
- A promise that resolves to true
when the store has been cleared
Deletes the entire database.
// Delete the entire database
await db.dropDB();
// Using Promise chain
db.dropDB()
.then((result) => {
console.log('Database deleted:', result); // result is true
})
.catch((err) => {
console.error('Failed to delete database:', err);
});
// Try-catch with await
try {
const result = await db.dropDB();
console.log('Database deleted successfully:', result); // result is true
} catch (err) {
console.error('Failed to delete database:', err);
}
Promise<true>
- A promise that resolves to true
when the database has been deleted
import { IDB } from 'keyval-db';
// Define your data types
interface User {
id: string;
name: string;
email: string;
createdAt: string;
}
// Create a database connection
const userDB = new IDB('myApp', 'users');
// Store a user
async function saveUser(user: User) {
try {
await userDB.set(user.id, user);
console.log(`User ${user.name} saved successfully!`);
} catch (error) {
console.error('Failed to save user:', error);
}
}
// Retrieve a user
async function getUser(userId: string) {
try {
const user = await userDB.get<User>(userId);
console.log(`Found user: ${user.name}`);
return user;
} catch (error) {
console.error(`Failed to get user ${userId}:`, error);
return null;
}
}
// Delete a user
async function deleteUser(userId: string) {
try {
await userDB.del(userId);
console.log(`User ${userId} deleted successfully!`);
} catch (error) {
console.error(`Failed to delete user ${userId}:`, error);
}
}
// Get all users
async function getAllUsers() {
try {
const users = await userDB.getValues<User[]>();
console.log(`Found ${users.length} users`);
return users;
} catch (error) {
console.error('Failed to get users:', error);
return [];
}
}