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

svelte-querify

v1.0.0

Published

`Svelte Querify` is a **minimal**, **performant**, and **easy-to-use** library for reactive data fetching in Svelte‑5 applications. Designed with precision and simplicity.

Readme

Svelte Querify — Lightweight & Elegant Data Query Cache Library For Sveltekit 🌟

Svelte Querify is a minimal, performant, and easy-to-use library for reactive data fetching in Svelte‑5 applications. Designed with precision and simplicity.

  • ✅ Fast, automatic caching and revalidation
  • ✅ Reactive state for query & mutation
  • ✅ No boilerplate, No ceremonies — just clean, concise API
  • ✅ Fully compatible with Svelte 5 runes ($state, $derived)

📦 Installation

npm install svelte-querify

then in your components, you can use the following:

import { QueryCache, mutation, query } from 'svelte-querify';

🚀 Key Features

🔧 QueryCache.config(opts)

Set global configuration options for:

  • ttl (cache time in minutes, default: 10)
  • refresh (background revalidation every n minutes, default: 5)
  • enabled (default query behavior, default: true)

🧠 query(key, fn, options)

Reactive query builder that returns:

  • data — fetched result
  • pending — initial fetch state
  • refetching — background revalidate in progress
  • error — fetch error
  • refetch() — manual refresh method

⚡ Features:

  • Smart key validation (prevents invalid queries)
  • Customizable cache-timing (ttl)
  • Lazy revalidation (refresh)
  • Debouncing during active fetches
  • Data preserved across refetches
  • Automatic Response/JSON handling

🔁 mutation(fn, hooks)

Handles mutations with:

  • data, pending, error — reactive state

  • submit(vars) — execute mutation

  • Optional lifecycle hooks:

    • processing (before start) - for optimistic updates
    • success (on success)
    • failure (on error) - for rollback or notifications
    • completion (always runs) - for cleanup

Example:

import { mutation } from 'svelte-querify';

const PostMutation = mutation(
	(post: { title: string }) => fetch('/api/posts', { method: 'POST', body: JSON.stringify(post) }),
	{
		processing: (vars) => console.log('Creating post...', vars),
		success: (response) => {
			console.log('Post created!', response.data);
			QueryCache.refresh(['posts']); // Refresh posts list
		},
		failure: (error) => console.error('Failed:', error.message),
		completion: (response) => console.log('Request finished', response.status)
	}
);

// Execute the mutation
await PostMutation.submit({ title: 'My New Post' });

🔍 QueryCache.get(key)

Retrieve cached data without triggering a fetch:

const cachedUser = QueryCache.get(['user', userId]);
if (cachedUser) {
	// Use cached data immediately
}

🧹 QueryCache.refresh(key)

Re-execute an existing query in background (preserves current data during refetch):

QueryCache.refresh(['posts']); // Triggers background refetch

🧼 QueryCache.invalidate(key, options)

Remove cached queries:

  • Single query: QueryCache.invalidate(['posts', 42])
  • Bulk removal: QueryCache.invalidate(['posts'], { bulk: true }) - removes all queries starting with "posts"
  • Clear all: QueryCache.invalidate() - clears entire cache

Example:

// Remove specific post
QueryCache.invalidate(['posts', 42]);

// Remove all post-related queries
QueryCache.invalidate(['posts'], { bulk: true });

// Clear everything
QueryCache.invalidate();

🎯 How It Works

  1. Cache Map: Each query is stored by a unique key
  2. TTL Timer: Auto-deletes stale entries after configured time
  3. Refresh Timer: Triggers lazy background revalidation
  4. Debouncing Guard: Prevents duplicate concurrent fetches
  5. Reactive State: Built with Svelte $state for optimal performance

📋 Usage Examples

Setup Global Config (Optional)

// In your +layout.svelte or app initialization
import { QueryCache } from 'svelte-querify';

QueryCache.config({
	ttl: 15, // Cache for 15 minutes
	refresh: 3, // Lazy Background refresh every 3 minutes if the query is accessed again
	enabled: true // Queries run immediately by default
});

Basic Query

import { query } from 'svelte-querify';

// Simple query - note: don't destructure unless using $derived
const UsersQuery = query(['users'], () => fetch('/api/users'), { ttl: 5, refresh: 2 });

// In your template
{#if UsersQuery.pending}
  <span>Loading users...</span>
{/if}

{#if UsersQuery.error}
  <p>Error: {UsersQuery.error.message}</p>
{/if}

{#if UsersQuery.data}
  <ul>
    {#each UsersQuery.data as user}
      <li>{user.name}</li>
    {/each}
  </ul>
{/if}

<!-- Manual refresh -->
<button onclick={() => UsersQuery.refetch()}>
  Refresh Users
</button>

Reactive Query with Parameters

// For dynamic queries (search, pagination, etc.)
let userId = $state(1);

// Wrap in $derived for reactivity when parameters change
let { data: user, pending, error, refetch } = $derived(
  query(
    ['user', userId],
    () => fetch(`/api/users/${userId}`).then(r => r.json()),
    { enabled: !!userId } // Only run when userId exists
  )
);

{#if pending}
  <span>Loading user...</span>
{:else if error}
  <p>Error: {error.message}</p>
{:else if user}
  <h1>{user.name}</h1>
  <p>{user.email}</p>
{/if}

Search Query Example

let searchTerm = $state('');

// Reactive search that triggers when searchTerm changes, can also be used for pagination
let searchResults = $derived(
	query(
		['search', searchTerm],
		() => fetch(`/api/search?q=${encodeURIComponent(searchTerm)}`).then((r) => r.json()),
		{
			enabled: searchTerm.length > 2, // Only search with 3+ characters
			ttl: 2 // Short cache for search results
		}
	)
);

Mutation with Cache Updates

import { mutation, QueryCache } from 'svelte-querify';

const createUser = mutation(
	(userData: { name: string; email: string }) =>
		fetch('/api/users', {
			method: 'POST',
			headers: { 'Content-Type': 'application/json' },
			body: JSON.stringify(userData)
		}),
	{
		processing: (vars) => {
			// Optimistic updates
			console.log('Creating user:', vars);
		},
		success: (response) => {
			// Invalidate and refresh users list
			QueryCache.refresh(['users']);
		},
		failure: (error) => {
			// Handle error, maybe show toast
			console.error('Failed to create user:', error.message);
		}
	}
);

// Usage in component
let name = $state('');
let email = $state('');

async function handleSubmit() {
	const result = await createUser.submit({ name, email });
	if (result) {
		// Success! Clear form
		name = '';
		email = '';
	}
}

Advanced Cache Management

// Get cached data without triggering fetch
const cachedPosts = QueryCache.get(['posts']);

// Refresh specific query in background
QueryCache.refresh(['posts', 'popular']);

// Invalidate related queries
QueryCache.invalidate(['posts'], { bulk: true }); // All post queries
QueryCache.invalidate(['user', userId]); // Specific user
QueryCache.invalidate(); // Everything

🎁 Advantages

  • Zero external dependencies
  • Minimal bundle size
  • Built specifically for Svelte 5 runes
  • Intelligent caching with TTL and background refresh
  • Automatic debouncing and duplicate request prevention
  • Flexible Response handling (fetch Response or direct data)
  • Type-safe with full TypeScript support
  • Dev-friendly with cache debugging in development

📚 API Reference

| Function | Signature | Description | | ------------------------- | --------------------------------------------------------------- | -------------------------- | | QueryCache.config(opts) | (opts: { ttl?: number, refresh?: number, enabled?: boolean }) | Set global defaults | | query | (key: any[], fn: () => Promise<T>, opts?: QueryOptions) | Create reactive query | | mutation | (fn: (vars: V) => Promise<T>, hooks?: MutationHooks) | Create reactive mutation | | QueryCache.get | (key: any[]) => T \| undefined | Get cached data | | QueryCache.refresh | (key: any[]) | Trigger background refetch | | QueryCache.invalidate | (key?: any[], flag?: { bulk?: boolean }) | Remove cache entries |

QueryOptions

type QueryOptions = {
	enabled?: boolean; // Execute immediately (default: true)
	refresh?: number; // Background refresh interval in minutes (default: 5)
	ttl?: number; // Cache lifetime in minutes (default: 10)
};

MutationHooks

type MutationHooks<T, V> = {
	processing?: (vars?: V) => void; // Before request
	success?: (response: Response) => void; // On success
	failure?: (error: { message: string }) => void; // On error
	completion?: (response: Response) => void; // Always runs
};

✅ When to Use This Package

  • Building Svelte 5 applications with data fetching needs
  • Want automatic caching without complexity
  • Need reactive queries that work seamlessly with runes
  • Prefer lightweight solutions over heavy query libraries
  • Value clean, maintainable code with minimal boilerplate

🐛 Development Features

In development mode, the cache is exposed on window.QUERY_CACHE for easy debugging and inspection.


✨ Contribute & Feedback

Contributions welcome! Feel free to open issues for bugs, feature requests, or submit PRs to improve the library.