npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

astand

v0.0.8

Published

A lightweight, reactive state management library for Svelte 5 with middleware support.

Downloads

16

Readme

Astand 🚀

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.


✨ Features

  • Reactive Stores:
    Utilizes Svelte’s $state rune for fine‑grained reactivity.
  • Middleware Support:
    Easily plug in middleware to run on every state update (e.g. logging with consoleLogMiddleware, validation with validationMiddleware, etc.).
  • Direct Svelte Store Contract:
    Implements a subscribe method under the hood so you can directly use the store in your Svelte components (no extra wrappers required).
  • TypeScript First:
    Built with TypeScript to provide a fully typed API.

📦 Installation

Install via npm (or your preferred package manager):

npm install astand
# or
pnpm add astand
# or
yarn add astand

🛠 Usage

Creating a Store

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 }));
	}
};

Using the Store in Svelte Components

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.

Middleware

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 }));
	}
};

🔌 API Reference

The main exports from the library are:

Types:

  • Store – the store interface.
  • Middleware – middleware function type.
  • StoreOptions – options for store creation.

Functions:

  • createStore(initialState: T, options?: StoreOptions): Store Creates a reactive store with optional middleware.
  • combineStores(stores: Record<string, { subscribe: (run: (value: any) => void) => () => void } & Record<string, any>>): CombinedStore
    Combines multiple Svelte stores into a single derived store. The returned object has:
    • A subscribe method that yields an object with each key’s current state.
    • All the original store objects (with their methods), so you can call, for example, combinedStore.counter.increment().
  • createSvelteStore(store: Store) Optional: A helper that exposes only the subscribe method (if you prefer to limit your store’s public API).
  • consoleLogMiddleware(prevState: T, nextState: T): void A sample middleware function for logging state changes.
  • timestampMiddleware(prevState: T, nextState: T): void Adds/updates an updatedAt property on the state with the current ISO timestamp whenever the state is updated.
  • validationMiddleware(conditions: ValidationCondition[]): Middleware Checks one or more conditions on the new state and either logs, warns, or throws an error if a condition isn’t met.
type ValidationCondition<T> = {
  predicate: (state: T) => boolean;
  message: string;
  level?: 'log' | 'warn' | 'error';
};
  • Persist Options: The persist option in StoreOptions allows you to specify a key and an optional storage type ('local' or 'session') to automatically rehydrate and save state between page loads.
const options = {
  persist: { key: 'counterStore', storage: 'local' }
};

Example of a combination of persist and middlewares

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);