@chainplatform/appstore
v0.1.4
Published
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 usin
Maintainers
Readme
🧠 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.
✨ 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()andonHydrated() - ⚙️ Custom logging and debounced persistence
- 🔒 Works with encrypted or plain storage
🚀 Installation
npm install @chainplatform/appstoreor
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
namespacekey. - 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 |
| Ethereum (ETH) | 0xa2fd119a619908d53928e5848b49bf1cc15689d4 |
| Tron (TRX) | TYL8p2PLCLDfq3CgGBp58WdUvvg9zsJ8pd |
| DOGE (DOGE) | DDfKN2ys4frNaUkvPKcAdfL6SiVss5Bm19 |
| USDT (SOLANA) | cPUZsb7T9tMfiZFqXbWbRvrUktxgZQXQ2Ni1HiVXgFm |
Your contribution helps maintain open-source development under the Chain Platform ecosystem 🚀
