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

pinia-lite

v1.0.0

Published

A tiny, dependency-free reimplementation of the core Pinia API (defineStore, storeToRefs, createPinia) for Vue 3.

Readme

pinia-lite

A tiny, dependency-free reimplementation of the core Pinia API for Vue 3 — defineStore, storeToRefs, and a createPinia() plugin — in about 60 lines of code.

It covers the basics you reach for day to day: a single shared store instance per id, reactive state without .value boilerplate, and cleanup when a component unmounts. It does not aim to replace Pinia — no devtools, no plugins/middleware, no SSR story, no $patch/$reset, no options-API store syntax. If you need those, use real Pinia.

Install

npm install pinia-lite

vue (^3.0.0) is a peer dependency.

Quick start

// main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia-lite'
import App from './App.vue'

createApp(App).use(createPinia()).mount('#app')
// stores/counter.js
import { ref, computed } from 'vue'
import { defineStore } from 'pinia-lite'

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  const double = computed(() => count.value * 2)

  function increment() {
    count.value++
  }

  return { count, double, increment }
})
<!-- AnyComponent.vue -->
<script setup>
import { useCounterStore } from './stores/counter'

const counter = useCounterStore()
</script>

<template>
  <button @click="counter.increment()">{{ counter.count }} / {{ counter.double }}</button>
</template>

No .value needed in templates or in counter.count — the store is wrapped in reactive() for you, same as Pinia.

How it works

  • One store instance per id. defineStore(id, setup) returns a useXxxStore() composable. The first call runs your setup function inside an effectScope and stores the result in a module-level registry (Map), keyed by id. Every later call to useXxxStore() — from any component — returns that same reactive instance.
  • Reactive by default. The raw object your setup function returns is wrapped in reactive(), so you can destructure-and-use its properties directly instead of writing .value everywhere refs normally require. Use the exported storeToRefs(store) (a thin wrapper over Vue's toRefs) when you do want individual refs, e.g. for destructuring in <script setup> without losing reactivity.
  • Cleanup via $dispose(). Every store gets a $dispose() method that stops its effectScope (tearing down any watch/computed it created), removes it from the registry, and blanks out any ref-backed state. By default this runs automatically in onUnmounted() if the store was created inside a component — pass { autoDispose: false } to opt out if you want the store to outlive the component that first created it.
  • createPinia() is a real Vue plugin. app.use(createPinia()) provides the pinia instance and sets app.config.globalProperties.$pinia, matching Pinia's install API. It also wraps app.unmount() so every store still in the registry gets disposed when the app itself is torn down — handy for tests and hot-module reloads.

API

| Export | Description | |---|---| | defineStore(id, setup) | Returns a useStore(options?) composable. options.autoDispose (default true) controls whether the store disposes itself on the owning component's unmount. | | storeToRefs(store) | Converts a reactive store into an object of individual refs, for destructuring without losing reactivity. | | createPinia() | Returns a Vue plugin object ({ install }) with a $disposeAll() escape hatch that tears down every store currently in the registry. |

What's intentionally missing

Compared to Pinia, pinia-lite does not provide:

  • Devtools integration
  • Plugins (pinia.use(...))
  • $patch / $reset / $subscribe / $onAction
  • Options-API store syntax (defineStore(id, { state, getters, actions }))
  • SSR-safe per-request store isolation (the registry is a single module-level Map, shared across every app instance)

If your project needs any of the above, reach for Pinia itself — this project is meant for small apps/prototypes where a full state library is more than you need.

License

MIT