Skip to content

A lightweight, dependency-free global store with persistence, hydration, and subscription support — designed for React Native and Web environments. It lets you manage multiple namespaces (like `theme`, `user`, `settings`, etc) and persist them easily using your own storage backend.

License

Notifications You must be signed in to change notification settings

ChainPlatform/AppStore

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🧠 AppStore

A lightweight, dependency-free global store with persistence, hydration, and subscription support — designed for React Native and Web environments.
It lets you manage multiple namespaces (like theme, user, settings, etc) and persist them easily using your own storage backend.

PRs welcome! Follow @doansan


✨ Features

  • ✅ Multi-namespace store management (AppStore.use("theme"), AppStore.use("user"))
  • 💾 Persistent data via pluggable storage adapter
  • 🔁 Auto hydration (load from storage)
  • 👂 Reactive subscriptions with subscribe() and onHydrated()
  • ⚙️ Custom logging and debounced persistence
  • 🔒 Works with encrypted or plain storage

🚀 Installation

npm install @chainplatform/appstore

or

yarn add @chainplatform/appstore

⚙️ Quick Setup

You must configure your storage adapter once before using any stores.

Example with Chain SDK

import AppStore from "@chainplatform/appstore";
import { saveStorage, retrieveStorage, removeStorage } from "@chainplatform/sdk";

const customStorage = {
  get: async (key) => await retrieveStorage(key, { encrypted: true }),
  set: async (key, val) => await saveStorage(key, val, { encrypted: true }),
  remove: async (key) => await removeStorage(key, { encrypted: true }),
};

// Configure once at app startup
AppStore.configure({
  storage: customStorage,
  log: true, // or false, or a custom logger function
});

🧩 Usage Example

// Create or access a store
const themeStore = AppStore.use("theme", { encrypted: true });

// Hydrate data from persistent storage
await themeStore.hydrate();

// Subscribe to changes
const unsubscribe = themeStore.subscribe((newVal, oldVal) => {
  console.log("Theme changed:", newVal);
});

// Set data
themeStore.set({ mode: "dark", primary: "#3498db" });

// Clear only in-memory data
themeStore.clear();

// Clear both in-memory and storage
await themeStore.clearStorage();

// Unsubscribe when needed
unsubscribe();

🔄 Manage Multiple Stores

const userStore = AppStore.use("user");
const drawerStore = AppStore.use("drawer");

// Load all stores in parallel
await AppStore.hydrateAll();

// Clear all memory data (not storage)
AppStore.clearAll();

🧱 API Reference

AppStore.configure(options)

Configure global settings for all stores.
Should be called once, usually at app startup.

Option Type Description
storage { get, set, remove } Custom async storage adapter
log boolean | function Enables or overrides logging (default: false)

AppStore.use(namespace, options)

Create or get a store by namespace.

Param Type Description
namespace string Unique key for store (e.g. "theme", "user")

Returns a SingleStore instance.


SingleStore API

Method Description
hydrate() Load stored data and mark as hydrated
subscribe(cb, { fireImmediately? }) Listen for data changes
onHydrated(cb) Called once when hydration completes
set(data) Set data
clear() Clear in-memory data
clearStorage() Clear both in-memory and persistent storage
value Current store value
initialized Whether the store has been hydrated

🪵 Logging

You can pass a logger function or enable default console logging:

AppStore.configure({
  storage: customStorage,
  log: (msg, ...args) => console.debug("[AppStore]", msg, ...args),
});

// or simply:
AppStore.configure({ storage: customStorage, log: true });

All log messages include namespace tags like [theme] hydrated.


🧠 Tips

  • Call AppStore.configure() only once globally — all stores share the same storage and logger.
  • Each store persists independently using its own namespace key.
  • To reset everything quickly:
    AppStore.clearAll();
    await customStorage.remove("theme");
    await customStorage.remove("user");

🧪 Unit Testing Example (Jest)

import AppStore from "../src/helpers/AppStore";

describe("AppStore", () => {
  const mockStorage = {
    get: jest.fn(async () => JSON.stringify({ theme: "dark" })),
    set: jest.fn(async () => {}),
    remove: jest.fn(async () => {}),
  };

  beforeAll(() => {
    AppStore.configure({ storage: mockStorage, log: false });
  });

  it("hydrates and sets data", async () => {
    const store = AppStore.use("theme");
    await store.hydrate();
    expect(store.value).toEqual({ theme: "dark" });

    store.set({ theme: "light" });
    expect(store.value.theme).toBe("light");
  });
});

📜 License

MIT © 2025 Chain Platform


💖 Support & Donate

If you find this package helpful, consider supporting the development:

Cryptocurrency Address
Bitcoin (BTC) 17grbSNSEcEybS1nHh4TGYVodBwT16cWtc
alt text
Ethereum (ETH) 0xa2fd119a619908d53928e5848b49bf1cc15689d4
alt text
Tron (TRX) TYL8p2PLCLDfq3CgGBp58WdUvvg9zsJ8pd
alt text
DOGE (DOGE) DDfKN2ys4frNaUkvPKcAdfL6SiVss5Bm19
USDT (SOLANA) cPUZsb7T9tMfiZFqXbWbRvrUktxgZQXQ2Ni1HiVXgFm

Your contribution helps maintain open-source development under the Chain Platform ecosystem 🚀

About

A lightweight, dependency-free global store with persistence, hydration, and subscription support — designed for React Native and Web environments. It lets you manage multiple namespaces (like `theme`, `user`, `settings`, etc) and persist them easily using your own storage backend.

Resources

License

Stars

Watchers

Forks

Packages

No packages published