svelte-store

A Pinia-style state management library for Svelte 5, built on svelte/store, providing type-safe global state management.

Features

  • Pinia-style API (defineStore, supports Options API and Setup style)
  • Built on svelte/store, supports $store auto-subscription
  • Plugin system (persistence / logging, etc.)
  • Full TypeScript type inference
  • Zero extra dependencies
  • Compatible with CommonJS and ES Modules

Installation

npm Install

# npm
npm install @free-walk/svelte-store

# cnpm(国内镜像)
cnpm install @free-walk/svelte-store

# yarn
yarn add @free-walk/svelte-store

# pnpm
pnpm add @free-walk/svelte-store

Peer Dependencies

Make sure the following dependencies are installed:

npm install svelte

ES Module Import

import { defineStore, mapState, mapActions } from '@free-walk/svelte-store'

CommonJS Require

const { defineStore, mapState, mapActions } = require('@free-walk/svelte-store')

CDN Usage

You can also use it directly via CDN (for quick prototyping or online demos):

<script src="https://unpkg.com/@free-walk/svelte-store@1.2.0/dist/svelte-store.iife.js"></script>

Quick Start

// stores/counter.ts
import { defineStore } from '@free-walk/svelte-store'

export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  getters: {
    double: (state) => state.count * 2,
  },
  actions: {
    increment() {
      this.count++
    },
  },
})

// 组件中使用
<script>
  import { useCounterStore } from '../stores/counter'
  const counter = useCounterStore()
</script>

<p>count: {$counter.count}</p>
<p>double: {$counter.double}</p>
<button onclick={() => counter.increment()}>+1</button>

defineStore

Factory function for creating a Store, supports two styles.

Function Signature

// Options API 风格
defineStore(id: string, options: StoreOptions): () => StoreInstance

// Setup 风格
defineStore(id: string, setup: () => SetupReturn): () => StoreInstance

Param

ParamTypeDescription
idstringUnique identifier for the Store
optionsStoreOptionsOptions API configuration object
setup() => objectSetup function, returns state and methods

Options API

Define a Store using Pinia-like Options API style.

StoreOptions

PropertyTypeDescription
state() => objectFactory function returning initial state
gettersRecord<string, (state) => any>Computed properties, receives state as argument
actionsRecord<string, Function>Methods, this points to the store state

Example

export const useTodoStore = defineStore('todo', {
  state: () => ({
    items: [] as string[],
    filter: 'all' as 'all' | 'done' | 'pending',
  }),
  getters: {
    count: (state) => state.items.length,
    filtered: (state) => {
      if (state.filter === 'all') return state.items
      return state.items.filter(...)
    },
  },
  actions: {
    addItem(text: string) {
      this.items = [...this.items, text]
    },
    setFilter(f: 'all' | 'done' | 'pending') {
      this.filter = f
    },
  },
})

Setup API

Define a Store using the Setup function style, freely composing

Example

import { defineStore } from '@free-walk/svelte-store'
import { writable, derived } from 'svelte/store'

export const useCounterStore = defineStore('counter', () => {
  const count = writable(0)
  const double = derived(count, ($c) => $c * 2)

  function increment() {
    count.update((n) => n + 1)
  }

  function reset() {
    count.set(0)
  }

  return { count, double, increment, reset }
})

In the Setup function return value, writable / readable / derived are recognized as state, plain functions are recognized as actions.

Store Instance

defineStore returns a function. Calling it returns a Store instance (singleton).

Instance Properties & Methods

Property / MethodTypeDescription
$idstringStore unique identifier
$stateobjectCurrent state snapshot (read-only)
$patch(partial)(partial: object) => voidBatch update state
$reset()() => voidReset to initial state (Options API only)
$subscribe(callback)(cb) => unsubscribeListen for state changes
subscribe(callback)(cb) => unsubscribeSvelte store protocol, supports $store syntax

Example

const counter = useCounterStore()

// 批量更新
counter.$patch({ count: 10 })

// 重置
counter.$reset()

// 监听变化
const unsub = counter.$subscribe((state) => {
  console.log('状态变化:', state)
})

// 在 Svelte 组件中使用 $ 自动订阅
// {$counter.count}

Plugin System

Register global plugins via addPlugin, executed when each Store is created.

API

FunctionParamDescription
addPlugin(plugin)plugin: (context: PluginContext) => voidRegister a global plugin

PluginContext

PropertyTypeDescription
storeStoreInstanceStore instance
idstringStore ID

Example: Persistence Plugin

import { addPlugin } from '@free-walk/svelte-store'

addPlugin(({ store, id }) => {
  // 从 localStorage 恢复状态
  const saved = localStorage.getItem('store-' + id)
  if (saved) {
    store.$patch(JSON.parse(saved))
  }

  // 监听变化并持久化
  store.$subscribe((state) => {
    localStorage.setItem('store-' + id, JSON.stringify(state))
  })
})

Helper Functions

FunctionParamDescription
mapState(useStore, keys)useStore: () => Store, keys: string[]Extract state fields as independent Readable stores
mapActions(useStore, keys)useStore: () => Store, keys: string[]Extract actions as independent functions
getRegisteredStore(id)id: stringGet a registered Store instance by ID
clearStores()Clear all registered Store instances

mapState Example

import { mapState } from '@free-walk/svelte-store'
import { useCounterStore } from '../stores/counter'

const { count, filter } = mapState(useCounterStore, ['count', 'filter'])

// 在模板中
// {$count}  {$filter}

mapActions Example

import { mapActions } from '@free-walk/svelte-store'
import { useCounterStore } from '../stores/counter'

const { increment, reset } = mapActions(useCounterStore, ['increment', 'reset'])

// 直接调用
increment()
reset()

Re-exports

For convenience, svelte-store re-exports the core APIs from svelte/store:

ExportSourceDescription
writablesvelte/storeWritable store
readablesvelte/storeRead-only store
derivedsvelte/storeDerived store
getsvelte/storeRead store value once
readonlysvelte/storeWrap writable as read-only

Example

// 可以直接从 svelte-store 导入,无需额外安装
import { writable, derived, get } from '@free-walk/svelte-store'

const count = writable(0)
const double = derived(count, ($c) => $c * 2)
console.log(get(count)) // 0