Spoosh
Plugins

Plugin System

Extend Spoosh with powerful plugins

Plugins are the heart of Spoosh. They extend the core functionality with features like caching, automatic retries, cache invalidation, and optimistic updates.

Installing Plugins

Each plugin is a separate package:

npm install @spoosh/plugin-cache @spoosh/plugin-invalidation @spoosh/plugin-retry

Using Plugins

Add plugins using the .use() method:

import { Spoosh } from "@spoosh/core";
import { cachePlugin } from "@spoosh/plugin-cache";
import { invalidationPlugin } from "@spoosh/plugin-invalidation";
import { retryPlugin } from "@spoosh/plugin-retry";

const spoosh = new Spoosh<ApiSchema, Error>("/api").use([
  cachePlugin({ staleTime: 5000 }),
  invalidationPlugin(), // Auto-refresh queries after mutations
  retryPlugin({ retries: 3 }),
]);

Available Plugins

Essential

PluginPackageDescription
Cache@spoosh/plugin-cacheResponse caching with configurable stale time
Invalidation@spoosh/plugin-invalidationAuto-invalidate queries after mutations
Deduplication@spoosh/plugin-deduplicationPrevent duplicate concurrent requests

Data Management

PluginPackageDescription
Optimistic@spoosh/plugin-optimisticInstant UI updates with automatic rollback
Initial Data@spoosh/plugin-initial-dataProvide initial data for queries
Prefetch@spoosh/plugin-prefetchPreload data before it's needed
GC@spoosh/plugin-gcGarbage collection for cache management

Request Control

PluginPackageDescription
Retry@spoosh/plugin-retryAutomatic retry on failure
Polling@spoosh/plugin-pollingAutomatic periodic refetching
Refetch@spoosh/plugin-refetchRefetch on window focus/network reconnect
Debounce@spoosh/plugin-debounceDelay requests until input stops changing
Throttle@spoosh/plugin-throttleLimit request frequency
Progress@spoosh/plugin-progressUpload/download progress via XHR

Data Transformation

PluginPackageDescription
QS@spoosh/plugin-qsNested object serialization for query params
Transform@spoosh/plugin-transformTransform response data

Framework

PluginPackageDescription
Next.js@spoosh/plugin-nextjsServer-side cache revalidation

Development

PluginPackageDescription
Devtool@spoosh/devtoolVisual debugging panel with tracing

For most applications, we recommend this plugin combination:

import { Spoosh } from "@spoosh/core";
import { cachePlugin } from "@spoosh/plugin-cache";
import { invalidationPlugin } from "@spoosh/plugin-invalidation";
import { deduplicationPlugin } from "@spoosh/plugin-deduplication";

const spoosh = new Spoosh<ApiSchema, Error>("/api").use([
  cachePlugin({ staleTime: 5000 }),
  deduplicationPlugin(),
  invalidationPlugin(),
]);

This gives you:

  • Caching - Avoid redundant network requests
  • Deduplication - Prevent duplicate requests when multiple queries invalidate at once
  • Auto-invalidation - Queries refresh automatically after mutations

Plugin Execution Order

Plugins are executed based on their priority value, not their registration order. This means you can register plugins in any order you like.

  • Lower priority runs first (e.g., cachePlugin with priority -10)
  • Higher priority runs last (e.g., throttlePlugin with priority 100)
  • Default priority is 0 (most plugins)

Key plugins with non-default priorities:

  • cachePlugin (priority: -10) - Runs early to check cache before other plugins
  • throttlePlugin (priority: 100) - Runs last to block all requests including force fetches
// These produce the same execution order:
const spoosh = new Spoosh<ApiSchema, Error>("/api").use([
  throttlePlugin(), // priority: 100 (runs last)
  retryPlugin(), // priority: 0 (default)
  cachePlugin({ staleTime: 5000 }), // priority: -10 (runs first)
]);

// Same as:
const spoosh = new Spoosh<ApiSchema, Error>("/api").use([
  cachePlugin({ staleTime: 5000 }), // priority: -10 (runs first)
  retryPlugin(), // priority: 0 (default)
  throttlePlugin(), // priority: 100 (runs last)
]);

Tip: The deduplicationPlugin is especially useful with invalidationPlugin. When a mutation invalidates multiple queries with overlapping tags, deduplication ensures only one network request is made per unique endpoint.

Per-Request Options

Most plugins support per-request overrides:

// Override cache time for this query
useRead((api) => api("users").GET(), { staleTime: 60000 });

// Disable retries for this query
useRead((api) => api("health").GET(), {
  retry: { retries: false },
});

// Custom polling interval
useRead((api) => api("notifications").GET(), { pollingInterval: 5000 });

On this page