@waelio/ustore

Universal Storage
6,008 2
Install
npm install @waelio/ustore
Latest Version:2.0.4
Vue:3
Older releases:2
License:MIT
Last Updated:Jul 5, 2026
Links: GitHub  ·  npm
Maintainer: waelio

uStore

Universal storage for browser, Vue, reactive, and server-side runtimes.

Join the chat at https://discord.gg/tBZ2Fmdb7E CI NPM version NPM monthly downloads NPM total downloads Donate

uStore gives you one small CRUD-style API across multiple storage backends so you can switch between browser state, in-memory state, Vue integrations, and server storage without rewriting the same get / set / remove plumbing over and over.

Why use uStore

  • One familiar API across multiple storage adapters
  • Works with both uStore.<adapter> and direct named exports
  • Browser-friendly adapters with SSR-safe fallbacks where applicable
  • Includes encrypted memory, config-backed storage, server-side Keyv storage, and a messaging bridge
  • Ships ESM, Node ESM, CommonJS, UMD, and TypeScript declarations

Install

pnpm add @waelio/ustore

Or with npm:

npm install @waelio/ustore

The server entrypoint is included in the same package and is imported via @waelio/ustore/server.

Quick start

import { uStore } from "@waelio/ustore";

uStore.local.set("greeting", "hello");

const greeting = uStore.local.get("greeting");
const exists = uStore.local.has("greeting");

console.log(greeting); // "hello"
console.log(exists); // true

uStore.local.remove("greeting");

uStore is also attached to window.uStore in browsers and globalThis.uStore in non-browser runtimes.

Package entrypoints

Import path Purpose
@waelio/ustore Main adapter exports, uStore, and the messaging bridge
@waelio/ustore/server Async server-side storage backed by Keyv

Root exports

  • uStore
  • localStorage
  • sessionStorage
  • cookieStorage
  • memoryStorage
  • piniaStorage
  • vuexStorage
  • gunStorage
  • secureStorage
  • configStorage
  • signalStorage
  • createMessagingStore

Server exports

  • serverStorage
  • createServerStorage
  • createMongoServerStorage

Adapter overview

Adapter Access pattern Runtime Notes
local uStore.local, localStorage Browser / SSR-friendly Local storage wrapper.
session uStore.session, sessionStorage Browser / SSR-friendly Session storage wrapper.
cookie uStore.cookie, cookieStorage Browser / Node fallback get() returns the raw key=value cookie entry.
memory uStore.memory, memoryStorage Universal Keyed in-memory storage.
pinia uStore.pinia, piniaStorage Universal Current compatibility layer behaves like an in-memory store.
vuex uStore.vuex, vuexStorage Universal Reads the latest committed value from a single slot.
secure uStore.secure, secureStorage Universal In-memory encrypted values via waelio-utils.
config uStore.config, configStorage Universal Supports nested keys such as client:apiUrl.
signal uStore.signal, signalStorage Universal Lightweight in-memory state for reactive-style workflows.
gun uStore.gun, gunStorage Browser / CommonJS / direct import Experimental, chain-oriented Gun integration.
server serverStorage, createServerStorage Node / server Async Keyv-backed storage from @waelio/ustore/server.

The common shape

Most adapters expose aliases for the same basic operations:

type StoreLike = {
  get(key: string): unknown;
  getItem(key: string): unknown;
  set(key: string, value: unknown): unknown;
  setItem(key: string, value: unknown): unknown;
  has(key: string): unknown;
  hasItem(key: string): unknown;
  remove(key: string): unknown;
  removeItem(key: string): unknown;
};

That means you can swap adapters without changing the overall call style.

Browser adapters

Local storage

import { localStorage, uStore } from "@waelio/ustore";

uStore.local.set("profile", { name: "Wael" });
console.log(uStore.local.get("profile"));

localStorage.set("theme", "dark");
console.log(localStorage.has("theme")); // true

Session storage

import { sessionStorage, uStore } from "@waelio/ustore";

uStore.session.set("draft", { title: "Hello" });
console.log(uStore.session.get("draft"));

sessionStorage.set("token", "abc123");
sessionStorage.remove("token");

Cookie storage

import { cookieStorage, uStore } from "@waelio/ustore";

uStore.cookie.set("theme", "dark");
console.log(uStore.cookie.get("theme")); // "theme=dark"

cookieStorage.set("locale", "en-US");
console.log(cookieStorage.has("locale")); // true

Cookie values are written as simple cookie strings, so plain strings are usually the best fit.

In-memory and utility adapters

Memory storage

import { memoryStorage, uStore } from "@waelio/ustore";

uStore.memory.set("count", 42);
console.log(uStore.memory.get("count")); // 42

memoryStorage.setItem("feature", { enabled: true });
console.log(memoryStorage.getItem("feature"));

Secure storage

import { secureStorage, uStore } from "@waelio/ustore";

uStore.secure.set("secret", "hello world");
console.log(uStore.secure.getItem("secret"));

secureStorage.set("token", "signed-value", { salt: "demo-salt" });
console.log(secureStorage.getItem("token", { salt: "demo-salt" }));

Config storage

import { configStorage, uStore } from "@waelio/ustore";

uStore.config.set("client:apiUrl", "https://api.example.com");
console.log(uStore.config.get("client:apiUrl"));

configStorage.set("featureFlags", { dashboard: true });
console.log(configStorage.get("featureFlags"));
console.log(configStorage.client());
console.log(configStorage.server());
console.log(configStorage.dev());

Signal storage

import { signalStorage, uStore } from "@waelio/ustore";

uStore.signal.set("online", true);
console.log(uStore.signal.get("online")); // true

signalStorage.set("users", ["alice", "bob"]);
console.log(signalStorage.has("users")); // true
signalStorage.remove("users");

Vue adapters

Pinia adapter

import { piniaStorage, uStore } from "@waelio/ustore";

uStore.pinia.set("theme", "dark");
console.log(uStore.pinia.get("theme"));

piniaStorage.setItem("language", "en");
console.log(piniaStorage.hasItem("language"));

The current Pinia adapter is a compatibility layer backed by in-memory state, which makes it predictable in SSR and test environments.

Vuex adapter

import { vuexStorage, uStore } from "@waelio/ustore";

uStore.vuex.set("status", "ready");
console.log(uStore.vuex.get());
console.log(uStore.vuex.has());

vuexStorage.setItem("message", { text: "hello" });
console.log(vuexStorage.getItem());

The current Vuex adapter stores the latest committed value in a single slot, so reads do not need a key.

Gun adapter

import { gunStorage } from "@waelio/ustore";

await gunStorage.set("room", { hello: "world" });
const roomRef = await gunStorage.get("room");

console.log(roomRef);

The Gun adapter is experimental and chain-oriented, so it behaves differently from the purely synchronous adapters.

Native Node ESM note

In the native Node ESM entry, uStore.gun intentionally throws to avoid eager-import issues. If you need Gun in that environment:

  • import gunStorage directly from @waelio/ustore
  • or use CommonJS / a bundler-based environment

Server-side storage

Use @waelio/ustore/server when you want async storage backed by Keyv.

import { createServerStorage } from "@waelio/ustore/server";

const store = createServerStorage({
  namespace: "sessions",
  ttl: 1000 * 60 * 60,
});

await store.set("session:waelio", {
  role: "owner",
  authenticated: true,
});

console.log(await store.get("session:waelio"));
console.log(await store.has("session:waelio"));

await store.remove("session:waelio");

There is also a ready-to-use singleton:

import { serverStorage } from "@waelio/ustore/server";

await serverStorage.set("healthcheck", "ok");
console.log(await serverStorage.get("healthcheck"));

Mongo-backed server storage

import { createMongoServerStorage } from "@waelio/ustore/server";

const store = createMongoServerStorage("mongodb://127.0.0.1:27017/ustore", {
  namespace: "waelio-auth",
});

await store.set("user:1", { role: "admin" });
console.log(await store.getItem("user:1"));

Messaging bridge

createMessagingStore is a client-side bridge between uStore adapters and a Socket.io-compatible messaging backend.

Install a Socket.io client in the consuming app if you do not already have one:

pnpm add socket.io-client

Then wire it up:

import { io } from "socket.io-client";
import { createMessagingStore } from "@waelio/ustore";

const socket = io("https://waelio-messaging.onrender.com");
const store = createMessagingStore(socket, {
  historyLimit: 200,
  storagePrefix: "wm",
});

const unsubscribe = store.onMessage((message) => {
  console.log("incoming", message.senderId, message.payload);
});

store.send("userId-abc", "hello!");
store.broadcast({ text: "hello everyone" });

const history = await store.loadHistory();
console.log(history.length);
console.log(store.getUnread());

unsubscribe();
store.destroy();

The messaging bridge uses:

  • localStorage for cached history
  • sessionStorage for session identity
  • signalStorage for unread count, user list, and connection state

Runtime notes

  • Browser-oriented adapters such as local, session, and cookie storage include fallbacks where applicable so they can still behave safely during SSR or non-browser execution.
  • uStore.gun is intentionally unavailable in native Node ESM via the uStore object, but gunStorage remains exportable.
  • idbStorage and webqlStorage exist in the source tree as planned adapters and are not currently exported from the public package.

Test coverage

The test suite currently covers:

  • localStorage
  • sessionStorage
  • cookieStorage
  • memoryStorage
  • piniaStorage
  • vuexStorage
  • secureStorage
  • configStorage
  • signalStorage
  • createServerStorage
  • cross-adapter isolation
  • alias consistency such as get / getItem and set / setItem
  • messaging behavior and Node runtime behavior

Development

pnpm test -- e2e.test.ts
pnpm test
pnpm build

Publishing

Typical local release flow:

pnpm test
pnpm build
npm publish --access public

References

Related Packages

ee-vuex

More convenient global status manager than Vuex and Pinia

2,452 6
@pinia/nuxt

Nuxt Module for pinia

34,268,649 14,743
pinia-cached-store

Pinia store extension that allows transparent caching of state in local storage.

3,282 21
vue-petit-store

petit store for vue mixin

3,490 0
vuex-pathify

Ridiculously simple Vuex setup + wiring

322,817 1,358

Version History

Version Released Vue License
2.0.4 3.2.47 MIT
2.0.3 3.2.47 MIT
2.0.2 3.2.47 MIT
2.0.0 3.2.47 MIT
1.0.15 3.2.47 MIT