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 🙏

© 2024 – Pkg Stats / Ryan Hefner

idbee

v1.0.4

Published

A lightweight Promise-Based Wrapper to simplify the use of JavaScript IndexedDB

Downloads

3

Readme

IDBee :honeybee:

A lightweight, Promise-Based Wrapper designed to simplify the use of JavaScript's IndexedDB, making client-side database operations more intuitive.

Quick Start

Create a new database instance, open a connection, and perform transactions:

import { IDBee } from "idbee";

// Create a new database instance
const mydb = new IDBee();

// Open a connection with default settings
// Defaults: db name "idb", store name "app", store keyPath "id"
await mydb.open();

// Perform transactions
const result = await mydb.transaction(async ({ app }) => {
	await app.add({ value: { todo: "hello world" } });
	return await app.get();
});

console.log(result);
// Outputs: [{todo: 'hello world', id: 1}]

mydb.close();

await mydb.delete();

Installation

To install IDBee, run the following command in your project directory:

npm install idbee

Configuration

Setting the Database Name

Specify the name of your database using the name method.

| Arguments | Type | Default | Required | | --------- | -------- | ------- | -------- | | name | String | | |

mydb.name("mydb");

Specifying the Version

Set the version of your database. IndexedDB uses versions to manage schema changes.

| Arguments | Type | Default | Required | | --------- | -------- | ------- | -------- | | version | Number | 1 | true |

mydb.version(1);

Defining Object Stores and Indexes

Configure object stores with their respective key paths, auto-increment settings, and any indexes.

| Arguments | Type | Default | Required | | -------------------------------- | ---------- | ------- | -------- | | stores | Object[] | [] | | | stores[].name | String | | | | stores[].options | Object | | | | stores[].options.keyPath | String | id | | | stores[].options.autoIncrement | Boolean | true | | | stores[].indexes | Object[] | | | | stores[].indexes[].name | String | | | | stores[].indexes[].unique | Boolean | false | | | stores[].indexes[].multiEntry | Boolean | false | |

mydb.stores([
	{
		name: "users",
		// Defaults: options: { keyPath: "id", autoIncrement: true },
		indexes: [{ name: "firstName" }, { name: "age" }]
	},
	{
		name: "todos",
		options: { keyPath: null, autoIncrement: true },
		indexes: [{ name: "userId" }, { name: "todo" }, { name: "tags", multiEntry: true }]
	}
]);

Connecting to IndexedDB

Establish a connection to your IndexedDB and handle various database events with custom callbacks.

| Arguments | Type | Default | Required | | --------------------------- | ---------- | ------- | -------- | | callbacks | Object | {} | | | callbacks.onsuccess | Function | | | | callbacks.onerror | Function | | | | callbacks.onupgradeneeded | Function | | | | callbacks.onblocked | Function | | |

await mydb.open({
	onsuccess: (event) => {
		console.log("Database connected successfully.");
	},
	onerror: (event) => {
		console.error("An error occurred while connecting to the database.");
	},
	onupgradeneeded: (event) => {
		console.log("Database upgrade is required.");
	},
	onblocked: (event) => {
		console.warn("Database connection is blocked.");
	}
});

Versioning

Update the version and modify the object stores and indexes:

mydb.version(2).stores([
	{
		name: "users",
		indexes: [{ name: "firstName" }, { name: "lastName" }, { name: "age" }]
	},
	{
		name: "todos",
		options: { keyPath: null, autoIncrement: true },
		indexes: [{ name: "userId" }, { name: "tags", multiEntry: true }]
	},
	{ name: "products" }
]);

mydb.version(3).stores([
	{
		name: "users",
		indexes: [{ name: "firstName" }, { name: "lastName" }, { name: "age" }]
	},
	// {
	//   name: "todos",
	//   options: { keyPath: null, autoIncrement: true },
	//   indexes: [{ name: "userId" }, { name: "tags", multiEntry: true }],
	// },
	// This will remove the entire objectStore including its data.
	,
]);

Custom logic for handling a database upgrade:

await mydb.version(4).open({
	onupgradeneeded: (event) => {
		const db = event.target.result;
		db.createObjectStore("todos", { keyPath: "id" });
	}
});

await mydb.version(5).open({
	onupgradeneeded: (event) => {
		const db = event.target.result;
		// db.createObjectStore("todos", { keyPath: "id" });
		// This will remove the entire objectStore including its data.
	}
});

Handling Transactions

Transactions allow you to execute a series of database operations as a single unit.

| Arguments | Type | Default | Required | | ---------- | ---------- | ------- | -------- | | stores | String[] | | | | callback | Function | | true |

const result = await mydb.transaction();
// Outputs: ["users", "todos"]

await mydb.transaction(["users"], async (stores) => {
	const { users } = stores;

	// Your transactional operations here

	return { success: true };
});
// Outputs: { success: true };

Adding Data

Transactions provide a straightforward way to add data to your object stores.

| Arguments | Type | Default | Required | | --------- | -------- | ------- | -------- | | options | Object | {} | | | key | Any | | | | value | Object | | true |

await mydb.transaction(async ({ users, todos }) => {
	const userId = await users.add({
		value: {
			firstName: "John",
			lastName: "Doe",
			age: 50
		}
	});
	// Outputs: The primary key of the new user, e.g., 1

	const todoList = [
		{
			userId: userId,
			todo: "Go for a run",
			tags: ["health", "fitness"]
		},
		{
			userId: userId,
			todo: "Learn a new language",
			tags: ["education", "self-improvement"]
		}
	];

	// Add multiple todo items for the user
	for (const todo of todoList) {
		await todos.add({
			value: todo
		});
	}
});

Demo Data

Users

| # | Key ("id") | Value | | --- | ---------- | -------------------------------------------------------- | | 0 | 1 | { id: 1, firstName: "John", lastName: "Doe", age: 50 } |

Todos

| # | Key | Value | | --- | ---- | -------------------------------------------------------------------------------------- | | 0 | 1 | { userId: 1, todo: "Go for a run", tags: ["health", "fitness"] } | | 1 | 2 | { userId: 1, todo: "Learn a new language", tags: ["education", "self-improvement"] } | | 2 | 3 | { userId: 5, todo: "Cook a new recipe", tags: ["cooking", "food"] } | | 3 | 4 | { userId: 3, todo: "Write a journal entry", tags: ["reflection", "writing"] } | | 4 | 5 | { userId: 5, todo: "Paint a landscape", tags: ["creativity", "art"] } | | 5 | 6 | { userId: 2, todo: "Plan a weekend trip", tags: ["travel", "adventure"] } | | 6 | 7 | { userId: 8, todo: "Visit a museum", tags: ["culture", "learning"] } | | 7 | 8 | { userId: 5, todo: "Start a blog", tags: ["writing", "technology"] } | | 8 | 9 | { userId: 9, todo: "Practice meditation", tags: ["mindfulness", "health"] } | | 9 | 10 | { userId: 4, todo: "Organize a meetup", tags: ["social", "networking"] } |

Retrieving Data

Transactions provide a straightforward way to add data to your object stores.

Get One

| Arguments | Type | Default | Required | | --------------- | -------- | ------- | -------- | | options | Object | {} | | | options.key | Any | | true | | options.index | Any | | |

await mydb.transaction(["todos"], async ({ todos }) => {
	await todos.get({ key: 1 });
	// Outputs: { userId: 1, todo: "Go for a run", tags: ["health", "fitness"] }

	await todos.get({ index: "userId", key: 5 });
	// Outputs: { userId: 5, todo: "Cook a new recipe", tags: ["cooking", "food"] }
});

Get All

| Arguments | Type | Default | Required | | --------------------- | -------- | ------- | -------- | | options | Object | {} | | | options.index | Any | | | | options.query | Object | | | | options.query.start | Any | | | | options.query.end | Any | | | | options.query.only | Any | | | | options.count | Number | | |

await mydb.transaction(["todos"], async ({ todos }) => {
	await todos.get();
	// Outputs: [{ 1 ... 10 }]

	await todos.get({ query: { start: 3 } });
	// Outputs: [{ 3 ... 10 }]

	await todos.get({ index: "userId" });
	// Outputs: [{ 1 ... 10 }] sort by userId

	await todos.get({ index: "userId", query: { start: 7, end: 10 } });
	// Outputs: [
	//   { userId: 8, todo: "Visit a museum", tags: ["culture", "learning"] }
	//   { userId: 9, todo: "Practice meditation", tags: ["mindfulness", "health"] }
	// ]

	await todos.get({ index: "tags", query: { only: "health" } });
	// Outputs: [
	//   { userId: 1, todo: "Go for a run", tags: ["health", "fitness"] }
	//   { userId: 9, todo: "Practice meditation", tags: ["mindfulness", "health"] }
	// ]

	await todos.get({ index: "userId", query: { only: 5 }, count: 2 });
	// Outputs: [
	//   { userId: 5, todo: "Cook a new recipe", tags: ["cooking", "food"] }
	//   { userId: 5, todo: "Paint a landscape", tags: ["creativity", "art"] }
	// ]
});

Get with Cursor

| Arguments | Type | Default | Required | | --------------------- | ---------- | ------- | -------- | | options | Object | {} | | | options.where | Function | | true | | options.index | Any | | | | options.query | Object | | | | options.query.start | Any | | | | options.query.end | Any | | | | options.query.only | Any | | | | options.direction | String | | |

await mydb.transaction(["todos"], async ({ todos }) => {
	await todos.get({
		where: (value) => {
			if (value.userId === 5) {
				return value;
			}
		},
		direction: "prev"
	});
	// Outputs: [
	//   { userId: 5, todo: "Start a blog", tags: ["writing", "technology"] }
	//   { userId: 5, todo: "Paint a landscape", tags: ["creativity", "art"] }
	//   { userId: 5, todo: "Cook a new recipe", tags: ["cooking", "food"] }
	// ]

	await todos.get({
		index: "userId",
		where: (value) => (value.userId === 5 ? value : null),
		direction: "nextunique"
	});
	// Outputs: [
	//   { userId: 5, todo: "Cook a new recipe", tags: ["cooking", "food"] }
	// ]
});

Update Data

Update and Create

| Arguments | Type | Default | Required | | --------------- | -------- | ------- | -------- | | options | Object | {} | | | options.key | Any | | | | options.value | Object | | true |

await mydb.transaction(async ({ users, todos }) => {
	await users.put({
		value: {
			id: 1,
			firstName: "Jane",
			lastName: "Doe",
			age: 50
		}
	});
	// Outputs: 1

	await todos.put({
		key: 2,
		value: {
			userId: 1,
			todo: "Learn Javascript",
			tags: ["education", "self-improvement"]
		}
	});
	// Outputs: 2
});

Update with Cursor

| Arguments | Type | Default | Required | | --------------------- | ---------- | ------- | -------- | | options | Object | {} | | | options.where | Function | | true | | options.index | Any | | | | options.query | Object | | | | options.query.start | Any | | | | options.query.end | Any | | | | options.query.only | Any | | | | options.direction | String | | |

await mydb.transaction(["todos"], async ({ todos }) => {
	await todos.put({
		where: (value) => {
			if (value.userId === 1) {
				value.completed = true;

				return value;
			}
		}
	});
	// Outputs: [1, 2]
});

Delete Data

Delete One

| Arguments | Type | Default | Required | | --------------- | -------- | ------- | -------- | | options | Object | {} | | | options.key | Any | | true | | options.index | Any | | |

await mydb.transaction(async ({ todos }) => {
	await todos.delete({
		key: 4
	});
	// { userId: 3, todo: "Write a journal entry", tags: ["reflection", "writing"] }

	await todos.delete({
		index: "UserId",
		key: 4
	});
	// { userId: 4, todo: "Organize a meetup", tags: ["social", "networking"] }
});

Delete All

| Arguments | Type | Default | Required | | --------------- | -------- | ------- | -------- | | options | Object | {} | | | options.key | Any | | true | | options.index | Any | | |

await mydb.transaction(async ({ users }) => {
	await users.delete();
});

Delete with Cursor

| Arguments | Type | Default | Required | | --------------------- | ---------- | ------- | -------- | | options | Object | {} | | | options.where | Function | | true | | options.index | Any | | | | options.query | Object | | | | options.query.start | Any | | | | options.query.end | Any | | | | options.query.only | Any | | | | options.direction | String | | |

await mydb.transaction(["todos"], async ({ todos }) => {
	await todos.delete({
		where: (value) => {
			if (value.userId === 5) {
				return true;
			}
		}
	});
	// { userId: 5, todo: "Cook a new recipe", tags: ["cooking", "food"] }
	// { userId: 5, todo: "Paint a landscape", tags: ["creativity", "art"] }
	// { userId: 5, todo: "Start a blog", tags: ["writing", "technology"] }
});