Skip to main content
Version: v7.0.0

Cache

Read the API Reference »

The Cache class is a core subsystem in Hyper Fetch, responsible for storing and managing response data from requests. It provides a flexible, event-driven system for data retention, validation, and propagation throughout your application. By default, it uses an in-memory Map for storage, but you can easily swap in persistent storage solutions like localStorage or IndexedDB.


Purpose
  1. Store and manage request results for fast, reliable data access.
  2. Emit events to keep your app in sync with cache changes.
  3. Support flexible storage—from in-memory to persistent solutions.
  4. Integrate seamlessly with the Client and Request systems for a unified data flow.

Quick Start

Here's how to get started with the Cache in Hyper Fetch:

Basic Cache Usage
import { createClient, Cache } from "@hyper-fetch/core";

// Initialize the client with default cache
const client = createClient({ url: "http://localhost:3000" });

// Read from cache
const data = client.cache.get("key");

// Write to cache
client.cache.set("key", { data: "value" });

You can also customize the cache storage:

Custom Cache Storage
const client = createClient({
url: "http://localhost:3000",
cache: (instance) => new Cache(instance, { storage: localStorage }),
});
Client
Learn how to configure the Client and its subsystems.
Request
Understand how requests interact with the cache.

Available methods

Methods
Name Description
update(request, partialResponse)
Update the cache data with partial response data
set(request, response)
Set the cache data to the storage
scheduleGarbageCollector(cacheKey)
Schedule garbage collection for given key
keys()
Get sync storage keys, lazyStorage keys will not be included
invalidate(cacheKeys)
Invalidate cache by cacheKey or partial matching with RegExp It emits invalidation event for each matching cacheKey and sets staleTime to 0 to indicate out of time cache
initialize(client)
getLazyResource(cacheKey)
Used to receive data from lazy storage
getLazyKeys()
Used to receive keys from sync storage and lazy storage
getAllKeys()
Used to receive keys from sync storage and lazy storage
get(cacheKey)
Get particular record from storage by cacheKey. It will trigger lazyStorage to emit lazy load event for reading it's data.
delete(cacheKey)
Delete record from storages and trigger invalidation event
clear()
Clear cache storages

Detailed Cache API Methods
Explore all available methods, their parameters, and return values for the Cache class.

Features

  • Key-based storage: Data is stored and retrieved using unique cache keys, auto-generated from request details.
  • Flexible storage: Use in-memory, localStorage, IndexedDB, or any compatible storage interface.
  • Event-driven: Emits events on cache changes for real-time updates.
  • Persistence: Easily enable persistent cache across sessions.
  • Fine-grained control: Read, write, update, delete, and invalidate cache entries with simple methods.
  • Integration: Works seamlessly with the Client and Request systems.

How it works

The cache stores data on a key-value basis. The key (usually cacheKey) is auto-generated from the request's method, endpoint, and query params, but you can override it for advanced scenarios.

const getUsers = client.createRequest()({
method: "GET",
endpoint: "/users",
});

// get data by cache key
const data = client.cache.get(getUsers.cacheKey);

// or directly by request instance
const data = getUsers.read();

You can also set a custom cache key:

const getUsers = client.createRequest()({
method: "GET",
endpoint: "/users",
cacheKey: "CUSTOM_CACHE_KEY",
});

// get data by custom cache key
const data = client.cache.get("CUSTOM_CACHE_KEY");

// or directly by request instance
const data = getUsers.read();

CacheKey

The cacheKey is a unique identifier for the cache entry. By default it is auto-generated from the request's endpoint, url params and query params but you can still add the key manually when setting the Request or generic generator.

const getUser = client.createRequest()({
method: "GET",
endpoint: "/users/:userId",
});

const cacheKey = getUser.cacheKey; // "/users/:userId"
const cacheKeyWithParams = getUser.setParams({ userId: 1 }).cacheKey; // "/users/1"
const cacheKeyWithQueryParams = getUser.setQueryParams({ page: 1 }).cacheKey; // "/users/:userId?page=1"

Custom cacheKey

You can also set a custom cache key:

import { client } from "./api";

const getUser = client.createRequest()({
method: "GET",
endpoint: "/users/:userId",
cacheKey: "CUSTOM_CACHE_KEY",
});

console.log(getUser.cacheKey); // "CUSTOM_CACHE_KEY"

Generic cacheKey

You can also set a generic cache key:

import { client } from "./api";

client.setCacheKeyMapper((request) => {
if (request.requestOptions.endpoint === "/users/:userId") {
return `CUSTOM_CACHE_KEY_${request.params?.userId || "unknown"}`;
}
});

const getUser = client.createRequest()({
method: "GET",
endpoint: "/users/:userId",
});

console.log(getUser.setParams({ userId: 1 }).cacheKey); // "CUSTOM_CACHE_KEY_1"

Quick Start

  1. Reading from Cache

Use the get method to read data stored under a given key:

const data = client.cache.get("key");

Or with a request instance:

const getNote = client.createRequest<{ response: Note }>()({
method: "GET",
endpoint: "/notes/:noteId",
});

const data = getNote.setParams({ noteId: 1 }).read();
console.log(data); // Note or undefined

  1. Writing to Cache

Use the set method to store data under a given key. Pass the request instance to ensure correct configuration:

const getNote = client.createRequest()({
method: "GET",
endpoint: "/notes/:noteId",
});

client.cache.set(getNote.setParams({ noteId: 1 }), {
data: { text: "Hello World" },
error: null,
status: 200,
success: true,
extra: xhrExtra,
});

  1. Updating Cache

Update existing cache entries with the update method. The cache will not update if the initial data is missing.

Updating rules

Cache will NOT update if the initial data is not present in the cache.

client.cache.update(getNote.setParams({ noteId: 1 }), {
data: { text: "Hello World" },
error: null,
status: 200,
success: true,
extra: xhrExtra,
});

// Or with a callback
client.cache.update(getNote.setParams({ noteId: 1 }), (prevData) => ({
...prevData,
data: { text: "Hello World" },
}));

  1. Deleting from Cache

Remove data from the cache using the delete method:

client.cache.delete(getNote.setParams({ noteId: 1 }).cacheKey);
// OR
client.cache.delete("CUSTOM_CACHE_KEY");

  1. Invalidating Cache

Invalidate cache entries with the invalidate method. This sets the staleTime to 0, so the next request will refetch the data. It also emits an event, triggering refetching in dedicated frameworks integrations like for example in React.

client.cache.invalidate(getNote.setParams({ noteId: 1 }).cacheKey);
// OR
client.cache.invalidate("CUSTOM_CACHE_KEY");
// OR via RegExp
client.cache.invalidate(new RegExp("CUSTOM_CACHE_KEY"));

Persistence

Enable persistent cache by providing a compatible storage interface (e.g., localStorage, IndexedDB):

const client = createClient({
url: "http://localhost:3000",
cache: (instance) => new Cache(instance, { storage: localStorage }),
});
Persistence
Learn how to enable persistent cache.
info

Currently, there is no cross-tab synchronization. This is planned for a future release.


Events & Lifecycle

The cache emits events on changes, allowing you to react to updates in real time. See all available events:

getCacheEvents
Name Type Description
emitCacheData
<Response, Error, Adapter>(data: ResponseType<Response, Error, Adapter> & ResponseDetailsType & { cacheKey: string; cacheTime: number; cached: boolean; hydrated?: boolean; staleTime: number; version: string } & { cached: boolean }, isTriggeredExternally: boolean) => void
Set cache data
emitDelete
(cacheKey: string, isTriggeredExternally: boolean) => void
Delete of cache values
emitInvalidation
(cacheKey: string, isTriggeredExternally: boolean) => void
Invalidate cache values event
onData
<Response, Error, Adapter>(callback: (data: ResponseType<Response, Error, Adapter> & ResponseDetailsType & { cacheKey: string; cacheTime: number; cached: boolean; hydrated?: boolean; staleTime: number; version: string } & { cached: boolean }) => void) => VoidFunction
Cache data listener
onDataByKey
<Response, Error, Adapter>(cacheKey: string, callback: (data: CacheValueType<Response, Error, Adapter>) => void) => VoidFunction
Cache data listener
onDelete
(callback: (cacheKey: string) => void) => VoidFunction
onDeleteByKey
(cacheKey: string, callback: () => void) => VoidFunction
onInvalidate
(callback: (cacheKey: string) => void) => VoidFunction
Cache invalidation listener
onInvalidateByKey
(cacheKey: string, callback: () => void) => VoidFunction
Cache invalidation listener

Cache Events API
Learn more about cache events.

Configuration Options

You can configure the cache with various options:

CacheOptionsType
Name Type Description
lazyStorage
CacheAsyncStorageType
Lazy loading from remote resources - possibly persistent
storage
CacheStorageType
Assign your custom sync storage
version
string
Key to clear lazy storage data, often used for versioning If the new key is different from the old one, the cache will be cleared

Lazy storage
Learn more about lazy storages.

TypeScript

The Cache system is fully typed and integrates with your Client and Request types. When using TypeScript, you get full type safety for cache operations, including data, error, and extra fields.

const getUser = client.createRequest<{ response: { name: string } }>()({ endpoint: "/users/:id" });

const data = getUser.setParams({ id: 1 }).read();
console.log(data); // { name: string }

See Also

Client
Central configuration and entry point for all requests.
Request
How requests interact with the cache and other subsystems.