npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

keyval-db

v1.1.0

Published

Indexdb, the way God intended it to be.

Downloads

85

Readme

keyval-db

A simple, type-safe wrapper for IndexedDB that eliminates the complexity of versions, upgrades, and store management the it was supposed to be.

What is keyval-db?

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.

Installation

npm

npm install keyval-db

pnpm

pnpm add keyval-db

bun

bun add keyval-db

API Reference

IDB Class

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');

Constructor Parameters

| 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 |

getDB

A factory function that creates and caches IDB instances cleaning up the cache when the database is dropped.

Benefits

  • 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');

Parameters

| 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 |

Returns

IDB - A cached IDB instance with all the same methods available

Usage Examples

// 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

get

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');
}

Parameters

| Parameter | Type | Description | | --------- | ----------- | ---------------------------------- | | key | IDBValidKey | The key to look up in the database |

Returns

Promise<T> - A promise that resolves to the value associated with the key

getValues

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);
	});

Returns

Promise<T extends Array<any>> - A promise that resolves to an array of all values

getKeys

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);
	});

Returns

Promise<Array<IDBValidKey>> - A promise that resolves to an array of all keys

set

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);
}

Parameters

| Parameter | Type | Description | | --------- | ----------- | -------------------------------- | | key | IDBValidKey | The key to store the value under | | value | unknown | The value to store |

Returns

Promise<true> - A promise that resolves to true when the operation is complete

setMultiple

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);
	});

Parameters

| Parameter | Type | Description | | --------- | ------------------------------------- | ------------------------------------------------------- | | items | Array<{ key: IDBValidKey, value: T }> | An array of objects containing key-value pairs to store |

Returns

Promise<true> - A promise that resolves to true when all items have been stored

del

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);
}

Parameters

| Parameter | Type | Description | | --------- | ----------- | ------------------------------ | | key | IDBValidKey | The key of the value to delete |

Returns

Promise<true> - A promise that resolves to true when the value has been deleted

clearStore

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);
}

Returns

Promise<true> - A promise that resolves to true when the store has been cleared

dropDB

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);
}

Returns

Promise<true> - A promise that resolves to true when the database has been deleted

Complete Example

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 [];
	}
}