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

miftahdb

v1.15.0

Published

Fast and lightweight key-value database library for Node.js

Downloads

1,927

Readme

MiftahDB

Fast and lightweight key-value database library.

NPM Version NPM Type Definitions NPM Downloads NPM License

Release Test-Bun Test-Node Lint

Features

  • Fast and efficient key-value storage
  • Support for expiration of keys
  • Disk and in-memory database support
  • Synchronous API for better performance and concurrency
  • Built on top of better-sqlite3 for optimal Node.js performance
  • Utilizes bun:sqlite for seamless Bun integration
  • Pattern-based key retrieval
  • Supports both Bun and Node.js environments

Installation

# With npm
npm install miftahdb

# With bun
bun add miftahdb

Usage

// For Node
import { MiftahDB } from "miftahdb";

// For Bun
import { MiftahDB } from "miftahdb/bun";

Example Usage

// Create a new disk-based database instance
const db = new MiftahDB("database.db");

// Or create an in-memory database
const memDB = new MiftahDB(":memory:");

// Use the database
db.set("user:1234", { name: "Ahmad Aburob" });
const user = db.get("user:1234");
console.log(user);

Synchronous API

MiftahDB uses a synchronous API, which may seem counterintuitive but actually provides better performance and concurrency than an asynchronous API for most use cases. This is because:

API Reference

Constructor

Creates a new MiftahDB instance.

  • Parameters:
    • path: The path to the database file, or :memory: for an in-memory database.
const diskDB = new MiftahDB("database.db");
const memoryDB = new MiftahDB(":memory:");

Get

Retrieves a value from the database by its key.

  • Parameters:
    • key: The key to look up.
  • Returns:
    • The value associated with the key, or null if not found or expired.
const value = db.get<User>("user:1234");
if (value) {
  console.log(`User: ${value.name}`);
} else {
  console.log("User not found");
}

Set

Sets a value in the database with an optional expiration.

  • Parameters:
    • key: The key under which to store the value.
    • value: The value to store.
    • expiresAt: Optional expiration date for the key-value pair.
// Set a value without expiration
db.set("user:1234", { name: "Ahmad Aburob" });

// Set a value with expiration
db.set("session:5678", "data", new Date("2025-12-31"));

Exists

Checks if a key exists in the database.

  • Parameters:
    • key: The key to check.
  • Returns:
    • True if the key exists and hasn't expired, false otherwise.
if (db.exists("user:1234")) {
  console.log("User exists");
} else {
  console.log("User not found");
}

Delete

Deletes a key-value pair from the database.

  • Parameters:
    • key: The key to delete.
db.delete("user:1234");

Rename

Renames a key in the database.

  • Parameters:
    • oldKey: The current key name.
    • newKey: The new key name.
db.rename("user:old_id", "user:new_id");

Get Expire

Gets the expiration date of a key.

  • Parameters:
    • key: The key to check.
  • Returns:
    • The expiration date of the key, or null if the key doesn't exist or has no expiration.
const expirationDate = db.getExpire("session:5678");
if (expirationDate) {
  console.log(`Session expires at: ${expirationDate}`);
} else {
  console.log("Session has no expiration or does not exist");
}

Set Expire

Sets the expiration date of a key.

  • Parameters:
    • key: The key to set the expiration date for.
    • expiresAt: The expiration date to set.
db.setExpire("user:1234", new Date("2028-12-31"));

Keys

Retrieves keys matching a pattern.

  • Parameters:
    • pattern: Optional SQL LIKE pattern to match keys. Defaults to "%" which matches all keys.
  • Returns:
    • An array of matching keys.
// Get all keys
const allKeys = db.keys();

// Get keys starting with "user:"
const userKeys = db.keys("user:%");

// Get keys with exactly 5 characters
const fiveCharKeys = db.keys("_____");

// Get keys starting with "log", followed by exactly two characters, and ending with any number of characters
const logKeys = db.keys("log__:%");

Pagination

Retrieves a paginated list of keys matching a pattern.

  • Parameters:
    • limit: The maximum number of keys to return per page.
    • page: The page number to retrieve (1-based index).
    • pattern: Optional SQL LIKE pattern to match keys. Defaults to "%" which matches all keys.
  • Returns:
    • An array of matching keys.
// Get the first 5 keys from the database
const firstPage = db.pagination(5, 1);

// Get the first 10 keys with pattern
const firstUsersPage = db.pagination(10, 1, "user:%");

// Get the next 10 keys with pattern
const secondUsersPage = db.pagination(10, 2, "user:%");

Count

Counts the number of keys in the database.

  • Parameters:
    • pattern: Optional SQL LIKE pattern to match keys. Defaults to "%" which matches all keys.
  • Returns:
    • The number of keys in the database.
// Get the total number of keys
const count = db.count();

// Get the number of keys matching "user:%"
const userCount = db.count("user:%");

Count Expired

Counts the number of expired keys in the database.

  • Parameters:
    • pattern: Optional SQL LIKE pattern to match keys. Defaults to "%" which matches all keys.
  • Returns:
    • The number of expired keys in the database.
// Get the total number of expired keys
const countExpired = db.countExpired();

// Get the number of expired keys matching "user:%"
const userCountExpired = db.countExpired("user:%");

Multi Get

Retrieves multiple values from the database by their keys.

  • Parameters:
    • keys: An array of keys to look up.
  • Returns:
    • An object with keys and their corresponding values, or null if not found or expired.
const values = db.multiGet(["user:1234", "user:5678"]);

Multi Set

Sets multiple key-value pairs in the database with optional expirations.

  • Parameters:
    • entries: An array of objects containing key, value, and optional expiresAt.
db.multiSet([
  {
    key: "user:1234",
    value: { name: "Ahmad" },
    expiresAt: new Date("2023-12-31"),
  },
  { key: "user:5678", value: { name: "Fatima" } },
]);

Multi Delete

Deletes multiple key-value pairs from the database.

  • Parameters:
    • keys: An array of keys to delete.
db.multiDelete(["user:1234", "user:5678"]);

Cleanup

Removes expired key-value pairs from the database.

db.cleanup();

Vacuum

Optimizes the database file, reducing its size.

db.vacuum();

Flush

Ensures all the changes are written to disk.

db.flush();

Execute

Executes a raw SQL statement and returns the result.

  • Parameters:
    • sql: The SQL statement to execute.
    • params: Optional parameters to bind to the SQL statement.
  • Returns:
    • The result of the SQL statement.
// Execute a SELECT statement and get results
const rows = db.execute("SELECT * FROM miftahdb WHERE key LIKE ? LIMIT 5;", [
  "%",
]);

Backup

Backups the database to a file.

  • Parameters:
    • path: The path to where the backup should be saved.
const db = new MiftahDB(":memory:");
db.set("key", "value");
db.backup("backup-1.db");

Restore

Restores the database from a backup file.

  • Parameters:
    • path: The path to the backup file.
const db = new MiftahDB(":memory:");
db.restore("backup-1.db");
console.log(db.get("key"));

Close

Closes the database connection.

db.close();

Error Handling

// Node
import { SqliteError } from "miftahdb";

// Bun
// import { SQLiteError } from "miftahdb/bun";

try {
  db.execute("WRONG SQL STATEMENT");
} catch (err) {
  if (err instanceof SqliteError) {
    console.log(err.message);
  }
}

Supported Value Types

MiftahDB supports various value types:

  1. String
  2. Number
  3. Boolean
  4. Array
  5. Record (Object)
  6. Date
  7. Buffer (Binary Data)
  8. Uint8Array (Binary Data)
  9. Null

Example for each type:

db.set("String", "Hello!");
db.set("Number", 42);
db.set("Boolean", true);
db.set("Array", [1, 2, 3, 4, 5]);
db.set("Record", { name: "Ahmad", age: 15 });
db.set("Date", new Date());
db.set("Buffer", Buffer.from([1, 2, 3, 4, 5]));
db.set("Uint8Array", new Uint8Array([1, 2, 3, 4, 5]));
db.set("Null", null);

TypeScript Typing & Generics

MiftahDB is fully typed with TypeScript, allowing you to leverage TypeScript's static type checking and type inference. You can use generic types to specify the type of values stored and retrieved from the database.

When retrieving values from MiftahDB, you can define the type of the stored value for better type safety:

type User = {
  name: string;
  age: number;
  email: string;
};

// Set a value with a known structure
db.set<User>("user:1234", {
  name: "Ahmad",
  age: 25,
  email: "[email protected]",
});

// Retrieve the value with TypeScript typing
const value = db.get<User>("user:1234");
if (value) {
  console.log(`User: ${value.name}, Age: ${value.age}`);
} else {
  console.log("User not found");
}

Pattern Matching

MiftahDB provides powerful pattern matching capabilities for working with keys. You can use patterns in multiple methods, such as:

  • db.keys(pattern)
  • db.pagination(limit, page, pattern)
  • db.count(pattern)
  • db.countExpired(pattern)

The pattern syntax follows SQL-like wildcard matching:

  • %: Matches any sequence of characters (including none).
  • _: Matches exactly one character.
// Match keys starting with "user:"
db.keys("user:%");

// Match keys ending with "osama"
db.keys("%osama");

// Match keys starting with "osama" and ending with any number of characters
db.keys("osama%");

// Match keys that are exactly 3 characters long
db.keys("___");

// Combine patterns: Match keys starting with "log", followed by exactly two characters, and ending with any number of characters
db.keys("log__:%");

Performance Considerations

MiftahDB is designed for high performance:

  1. Synchronous API reduces overhead and improves concurrency
  2. Optimized SQLite settings for improved performance
  3. In-memory database option for maximum speed

For best performance, consider the following tips:

  • Use in-memory databases for temporary or cache-like data
  • Regularly run the cleanup() and vacuum() methods to optimize the database