- π Vue 3 Composition API only
- β‘οΈ Almost identical DX to Zustand: supports set/get/selector, middleware composition
- π§βπ» TypeScript friendly: easy type inference, separation, and actions
- π Lightweight & simple: true 1-file store, ZERO learning curve
- π§© Selector-based partial subscription supported for optimal component performance
- π§© Pluggable middleware support (Logger, Persist, ... with compose or chain)
- π Full npm-style import/usage (
import ... from "zenon"
,"zenon/plugins"
, etc.)
pnpm add zenon
# or
npm install zenon
# or
yarn add zenon
// stores/counter.ts
import { createStore, compose } from "zenon";
import { withLogger, withPersist } from "zenon/plugins";
type CounterState = { count: number };
type CounterActions = {
increase: () => void;
reset: () => void;
};
const STORE_KEY = "zenon-counter";
// Compose DX
export const useCounter = () =>
createStore(
compose(
withLogger({ store: "counter", timestamp: true, expanded: true }),
withPersist<CounterState & CounterActions>(STORE_KEY, {
storage: window.sessionStorage,
})
)((set, get) => ({
count: 0,
increase: () => set({ count: get().count + 1 }, "increase"),
reset: () => set({ count: 0 }, "reset"),
}))
);
<template>
<div>
<h2>Zenon Counter</h2>
<p>Count: {{ count }}</p>
<button @click="increase">+1</button>
<button @click="reset">Reset</button>
</div>
</template>
<script setup lang="ts">
import { useCounter } from "@/stores/counter";
const store = useCounter();
const count = store.useSelector((s) => s.count);
const { increase, reset } = store;
</script>
-
Compose or chain multiple plugins
-
Plugin entry: zenon/plugins
import { createStore, compose } from "zenon";
import { withLogger, withPersist } from "zenon/plugins";
// Compose style
export const useCounter = () =>
createStore(
compose(
withLogger({ store: "counter" }),
withPersist("counter")
)((set, get) => ({
count: 0,
increase: () => set({ count: get().count + 1 }, "increase"),
reset: () => set({ count: 0 }, "reset"),
}))
);
// Or chain style
export const useCounter = () =>
createStore(
withLogger({ store: "counter" })(
withPersist("counter")((set, get) => ({
count: 0,
increase: () => set({ count: get().count + 1 }, "increase"),
reset: () => set({ count: 0 }, "reset"),
}))
)
);
const store = useCounter();
const count = store.useSelector((s) => s.count); // Subscribe only to count
const double = store.useSelector((s) => s.count * 2); // Derived value is also OK
MIT
Ideas, PRs, and feedback are all welcome!