Polystore

A library to unify KV-stores. Allows you to write code that works on any KV store, both front-end and backend. Supports substores and intuitive expiration times:

npm install polystore
import kv from "polystore";
import { createClient } from "redis";

const store = kv(createClient().connect());

await store.set("hi", data, { expires: "1h" });
console.log(await store.get("hi"));
// { hello: "world" }

Easy peasy

It's a KV store. It has set(), get(), has(), add(), del() and more.

Documented

Getting started, API, Adapters and custom stores fully documented for you.

Tested and Typed

1600+ tests, Typescript and JSDocs for the best experience using the library.

Intuitive expirations

Write the TTL as "100s", "1week", "1h" and forget time-related bugs.

Tiny Footprint

At just 4kb (min+gzip), the impact on your app loading time is minimal.

Universal Javascript

Use it with React, Angular, Plain JS, Node.js, Bun, Tauri, Electron, etc.

🧩 Support for many adapters

We support 10+ adapters with documentation for each of them. Adding your own adapter is also easy, you only need to define 3 methods: .get(), .set() and .entries().

Adapters Documentation

import kv from "polystore";

const store1 = kv(new Map());
const store2 = kv(localStorage);
const store3 = kv(redisClient);
const store4 = kv("cookie");
const store5 = kv("file:///users/me/kv.json");
const store6 = kv(yourOwnStore);

🏖️ Clean and intuitive API

A set of high-performance item operations with .add(), .set(), .get(), .has() or .del(). We also provide group operations to manage your data easily.

API Documentation

import kv from "polystore";
const store = kv(new Map());

const key1 = await store.add("value1");
const key2 = await store.set("key2", "value2");
const val1 = await store.get("key1");
const has1 = await store.has("key1");
const key1 = await store.del("key1");

⏰ Easy expiration time

Simply write "1day" with ANY adapter and forget about calculating TTL, Unix time, seconds vs milliseconds bugs, etc.

Expiration Documentation

await store.get("key");  // null

await store.set("key", "hi", "1second");
await store.get("key");  // "hi"

await sleep(2000);

await store.get("key");  // null

🛗 Create substores

Create a new substore with .prefix(), then you can ignore anything related to the prefix and treat it as if it was a brand new store.

Substore Documentation

const session = store.prefix("session:");
session.set("key1", "value1");

console.log(await session.all());
// { "key1": "value1" }

console.log(await store.all());
// { "session:key1": "value1" }

🏃‍♂️‍➡️ Iterate over the data

Iterate asynchronously straight on the store! It will return a pair of [key, value] for each of the entries. You can also use it on a substore as well.

Iterator Documentation

for await (const [key, value] of store) {
  console.log(key, value);
}

const session = store.prefix('session:');
for await (const [key, value] of session) {
  console.log(key, value);
}

✨ Magic Autocomplete

Added jsdocs so the expected parameters and return value will be clearly defined in your IDE/Code Editor.

We added the description, a representative example and even a link for more information for every one of the methods available! We want you to have the best development experience possible with Polystore!