A lightweight, reactive state management library for Svelte 5 with middleware support.
Inspired by the simplicity of Zustand and the power of Svelte’s reactive runes, this library provides a single‑file API to create global or scoped state stores—complete with middleware (like logging) and full TypeScript support.
$state rune for fine‑grained reactivity.consoleLogMiddleware, validation with validationMiddleware, etc.).subscribe method under the hood so you can directly use the store in your Svelte components (no extra wrappers required).Install via npm (or your preferred package manager):
npm install astand
# or
pnpm add astand
# or
yarn add astand
Use the createStore function to create a store with an initial state and optional middleware. For example, create a counter store that logs every state update:
// src/stores/counterStore.svelte.ts
import { consoleLogMiddleware, createStore, type Store } from '$lib/store.svelte.js';
interface CounterState {
count: number;
}
export interface CounterStore extends Store<CounterState> {
increment: () => void;
decrement: () => void;
}
const initialState: CounterState = { count: 0 };
const options = {};
const baseCounterStore = createStore<CounterState>(initialState, options);
export const counterStore: CounterStore = {
...baseCounterStore,
increment: () => {
baseCounterStore.setState((prev) => ({ count: prev.count + 1 }));
},
decrement: () => {
baseCounterStore.setState((prev) => ({ count: prev.count - 1 }));
}
};
Since the store implements Svelte’s store contract (with a subscribe method), you can import and use it directly in your Svelte components:
<!-- src/components/Counter.svelte -->
<script lang="ts">
import { counterStore } from '../stores/counterStore.svelte';
</script>
<main>
<h1>Counter: {$counterStore.count}</h1>
<button on:click={() => counterStore.increment()}>âž• Increment</button>
<button on:click={() => counterStore.decrement()}>âž– Decrement</button>
</main>
Svelte will auto‑subscribe to your store and update the component whenever state changes.
This is a work in progress. For the moment, you can log the state everytime there is a change in the store by using the consoleLogMiddleware.
// src/stores/counterStore.svelte.ts
import { consoleLogMiddleware, createStore, type Store } from '$lib/store.svelte.js';
interface CounterState {
count: number;
}
export interface CounterStore extends Store<CounterState> {
increment: () => void;
decrement: () => void;
}
const initialState: CounterState = { count: 0 };
const options = { middleware: [consoleLogMiddleware] }; // 🚀 Add the middleware here!
const baseCounterStore = createStore<CounterState>(initialState, options);
export const counterStore: CounterStore = {
...baseCounterStore,
increment: () => {
baseCounterStore.setState((prev) => ({ count: prev.count + 1 }));
},
decrement: () => {
baseCounterStore.setState((prev) => ({ count: prev.count - 1 }));
}
};
The main exports from the library are:
subscribe method that yields an object with each key’s current state.combinedStore.counter.increment().type ValidationCondition<T> = {
predicate: (state: T) => boolean;
message: string;
level?: 'log' | 'warn' | 'error';
};
const options = {
persist: { key: 'counterStore', storage: 'local' }
};
const options = {
middleware: [
consoleLogMiddleware,
validationMiddleware([
{
predicate: (s: { count: number }) => s.count >= 0,
message: 'Count must be non-negative',
level: 'error'
}
])
],
persist: { key: 'testMiddlewareStore', storage: 'local' }
};
const store = createStore({ count: 0 }, options);