API Reference
createCache()
Factory function to create a typed cache object from a schema
createCache()
The createCache function is the main entry point for next-cool-cache. It takes a schema and scopes, and returns a fully typed cache object.
Import
import { createCache } from 'next-cool-cache';Signature
function createCache<T, S extends readonly string[]>(
schema: T,
scopes: S
): ScopedCache<T, S>Parameters
schema
Type: T extends Record<string, unknown>
Required: Yes
The cache schema defining your resources and their parameters.
const schema = {
users: {
list: {},
byId: { _params: ['id'] as const },
},
} as const;Rules:
- Must use
as constfor full type inference - Leaf nodes are either
{}(no params) or{ _params: [...] as const }(with params) - Branch nodes are nested objects without
_params _paramsis a reserved key
scopes
Type: S extends readonly string[]
Required: Yes
Array of scope names for your cache namespaces.
const scopes = ['admin', 'public', 'user'] as const;Rules:
- Must use
as constfor full type inference - Each scope becomes a namespace in the returned cache object
- Common patterns:
['admin', 'public'],['admin', 'public', 'user']
Return Value
Returns a ScopedCache<T, S> object with:
- Scoped namespaces - One property per scope (e.g.,
cache.admin,cache.public) - Unscoped access - Direct access to resources for cross-scope operations (e.g.,
cache.users) - Type-safe methods - All paths and parameters are typed
Usage
Basic Usage
import { createCache } from 'next-cool-cache';
const schema = {
users: {
list: {},
byId: { _params: ['id'] as const },
},
posts: {
list: {},
byId: { _params: ['id'] as const },
},
} as const;
const scopes = ['admin', 'public'] as const;
export const cache = createCache(schema, scopes);Accessing Scoped Namespaces
// Admin scope
cache.admin.users.list.cacheTag();
cache.admin.users.byId.revalidateTag({ id: '123' });
// Public scope
cache.public.users.list.cacheTag();
cache.public.users.byId.revalidateTag({ id: '123' });Cross-Scope Operations
// Invalidate across all scopes
cache.users.byId.revalidateTag({ id: '123' });
// This invalidates 'users/byId:123' which affects all scopesTesting
Mock the next/cache module in your tests:
import { jest } from '@jest/globals';
const mockCacheTag = jest.fn();
const mockRevalidateTag = jest.fn();
const mockUpdateTag = jest.fn();
jest.mock('next/cache', () => ({
cacheTag: (...args: unknown[]) => mockCacheTag(...args),
revalidateTag: (...args: unknown[]) => mockRevalidateTag(...args),
updateTag: (...args: unknown[]) => mockUpdateTag(...args),
}));
import { createCache } from 'next-cool-cache';
const cache = createCache(schema, scopes);
// Test your code
cache.admin.users.byId.cacheTag({ id: '123' });
// Assert
expect(mockCacheTag).toHaveBeenCalledWith(
'admin/users/byId:123',
'admin/users',
'admin',
'users/byId:123',
'users'
);Examples
Complex Schema
const schema = {
blog: {
posts: {
list: {},
byId: { _params: ['id'] as const },
bySlug: { _params: ['slug'] as const },
byAuthor: { _params: ['authorId'] as const },
},
drafts: {
list: {},
byId: { _params: ['id'] as const },
},
categories: {
list: {},
bySlug: { _params: ['slug'] as const },
},
},
users: {
list: {},
byId: { _params: ['id'] as const },
settings: {
byUserId: { _params: ['userId'] as const },
},
},
} as const;
const scopes = ['admin', 'public', 'author'] as const;
const cache = createCache(schema, scopes);
// Access patterns
cache.admin.blog.posts.list.cacheTag();
cache.admin.blog.posts.byId.cacheTag({ id: 'post-123' });
cache.public.blog.categories.bySlug.revalidateTag({ slug: 'tech' });
cache.author.blog.drafts.byId.updateTag({ id: 'draft-456' });
// Branch operations
cache.admin.blog.posts.revalidateTag(); // All posts
cache.admin.blog.revalidateTag(); // All blog contentMultiple Parameters
const schema = {
comments: {
byPostAndUser: { _params: ['postId', 'userId'] as const },
},
projects: {
byOwnerAndSlug: { _params: ['ownerId', 'slug'] as const },
},
} as const;
const cache = createCache(schema, ['admin'] as const);
// Must provide all params
cache.admin.comments.byPostAndUser.cacheTag({
postId: 'post-1',
userId: 'user-1',
});
// TypeScript error if missing param
cache.admin.comments.byPostAndUser.cacheTag({ postId: 'post-1' });
// Error: Property 'userId' is missingType Safety
The returned cache object is fully typed:
// Autocomplete works
cache.admin.users.b // suggests: byId
// TypeScript catches typos
cache.admin.user.byId // Error: 'user' doesn't exist, did you mean 'users'?
// Params are enforced
cache.admin.users.byId.cacheTag({ userId: '123' }); // Error: Expected 'id', got 'userId'
cache.admin.users.byId.cacheTag(); // Error: Expected params object
cache.admin.users.list.cacheTag({ id: '123' }); // Error: 'list' takes no paramsSee Also
- Cache Methods - Methods available on cache nodes
- Types - TypeScript type definitions
- Schema Design - How to design your schema