Skip to content
/ idbee Public

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

License

Notifications You must be signed in to change notification settings

Eahnns12/idbee

Repository files navigation

IDBee 🐝

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

About

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

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published