Tag Utilities
Low-level tag building functions for advanced use cases
Tag Utilities
next-cool-cache exports several utility functions for building cache tags. These are used internally by the cache object, but are also available for advanced use cases.
Import
import {
buildTag,
buildAncestorTags,
buildScopedTag,
buildAllTags,
buildUnscopedTags,
} from 'next-cool-cache';buildTag()
Builds a single tag string from a path and optional parameters.
Signature:
function buildTag(
path: string[],
params: Record<string, string>
): stringParameters:
path- Array of path segmentsparams- Object of parameter key-value pairs
Returns: A tag string
Examples:
// Without params
buildTag(['users', 'list'], {})
// Returns: 'users/list'
// With single param
buildTag(['users', 'byId'], { id: '123' })
// Returns: 'users/byId:123'
// With multiple params
buildTag(['comments', 'byPostAndUser'], { postId: 'p1', userId: 'u1' })
// Returns: 'comments/byPostAndUser:p1:u1'
// With scoped path
buildTag(['admin', 'users', 'byId'], { id: '123' })
// Returns: 'admin/users/byId:123'Format:
- Path segments are joined with
/ - Params are appended with
:separator - Multiple param values are joined with
:
buildAncestorTags()
Generates all ancestor tags for a given path. Used for hierarchical tag registration.
Signature:
function buildAncestorTags(path: string[]): string[]Parameters:
path- Array of path segments
Returns: Array of ancestor tag strings (not including the full path itself)
Examples:
buildAncestorTags(['users', 'byId'])
// Returns: ['users']
buildAncestorTags(['blog', 'posts', 'byId'])
// Returns: ['blog', 'blog/posts']
buildAncestorTags(['admin', 'blog', 'posts', 'byId'])
// Returns: ['admin', 'admin/blog', 'admin/blog/posts']
buildAncestorTags(['users'])
// Returns: []Note: The result does not include the full path itself. The full path is typically the leaf tag.
buildScopedTag()
Prefixes a tag with a scope name.
Signature:
function buildScopedTag(scope: string, tag: string): stringParameters:
scope- The scope nametag- The tag to prefix
Returns: Scoped tag string
Examples:
buildScopedTag('admin', 'users/byId:123')
// Returns: 'admin/users/byId:123'
buildScopedTag('public', 'blog/posts/list')
// Returns: 'public/blog/posts/list'buildAllTags()
Builds the complete set of hierarchical tags for a scoped cache operation. This is what cacheTag() uses internally.
Signature:
function buildAllTags(
resourcePath: string[],
scopePath: string[],
params: Record<string, string>
): string[]Parameters:
resourcePath- The resource path segments (e.g.,['users', 'byId'])scopePath- The scope path segments (e.g.,['admin'])params- Parameter key-value pairs
Returns: Array of all tags (scoped and unscoped, leaf and ancestors)
Example:
buildAllTags(['users', 'byId'], ['admin'], { id: '123' })
// Returns:
// [
// 'admin/users/byId:123', // scoped leaf
// 'admin/users', // scoped ancestor
// 'admin', // scope root
// 'users/byId:123', // unscoped leaf
// 'users' // unscoped ancestor
// ]Order: Tags are returned from most specific to least specific:
- Scoped leaf tag
- Scoped ancestor tags (reversed, most specific first)
- Unscoped leaf tag
- Unscoped ancestor tags (reversed, most specific first)
buildUnscopedTags()
Builds hierarchical tags without scope prefix. Used for cross-scope operations.
Signature:
function buildUnscopedTags(
resourcePath: string[],
params: Record<string, string>
): string[]Parameters:
resourcePath- The resource path segmentsparams- Parameter key-value pairs
Returns: Array of unscoped tags (leaf and ancestors)
Example:
buildUnscopedTags(['blog', 'posts', 'byId'], { id: '456' })
// Returns:
// [
// 'blog/posts/byId:456', // leaf
// 'blog/posts', // ancestor
// 'blog' // ancestor
// ]Schema Utilities
These utilities help work with schema definitions:
isLeafNode()
Check if a schema node is a leaf node.
import { isLeafNode } from 'next-cool-cache';
isLeafNode({}) // true (empty object)
isLeafNode({ _params: ['id'] }) // true (has only _params)
isLeafNode({ list: {}, byId: {} }) // false (has children)getParams()
Extract the params array from a schema node.
import { getParams } from 'next-cool-cache';
getParams({ _params: ['id', 'slug'] }) // ['id', 'slug']
getParams({}) // []
getParams({ list: {} }) // []getChildKeys()
Get all child keys from a schema node, excluding _params.
import { getChildKeys } from 'next-cool-cache';
getChildKeys({
list: {},
byId: { _params: ['id'] },
_params: ['test'] // excluded
})
// Returns: ['list', 'byId']Advanced Use Cases
Custom Tag Generation
If you need to build tags manually (e.g., for logging or debugging):
import { buildTag, buildAllTags } from 'next-cool-cache';
function logCacheOperation(operation: string, scope: string, resource: string[], params: Record<string, string>) {
const tags = buildAllTags(resource, [scope], params);
console.log(`Cache ${operation}:`, {
leafTag: tags[0],
allTags: tags,
scope,
resource: resource.join('/'),
params,
});
}
// Usage
logCacheOperation('revalidate', 'admin', ['users', 'byId'], { id: '123' });
// Logs:
// Cache revalidate: {
// leafTag: 'admin/users/byId:123',
// allTags: ['admin/users/byId:123', 'admin/users', 'admin', 'users/byId:123', 'users'],
// scope: 'admin',
// resource: 'users/byId',
// params: { id: '123' }
// }Custom Invalidation Logic
Building custom invalidation patterns:
import { buildTag } from 'next-cool-cache';
import { revalidateTag } from 'next/cache';
// Invalidate a specific pattern without using the typed cache
function invalidatePattern(pattern: string[]) {
const tag = buildTag(pattern, {});
revalidateTag(tag, 'max');
}
// Example: Invalidate all admin caches
invalidatePattern(['admin']);Testing Helpers
Creating test utilities:
import { buildAllTags } from 'next-cool-cache';
function expectCacheTagsRegistered(
mockCacheTag: jest.Mock,
scope: string,
resource: string[],
params: Record<string, string>
) {
const expectedTags = buildAllTags(resource, [scope], params);
expect(mockCacheTag).toHaveBeenCalledWith(...expectedTags);
}
// Usage in tests (with jest.mock for next/cache)
it('registers correct cache tags', () => {
const cache = createCache(schema, scopes);
cache.admin.users.byId.cacheTag({ id: '123' });
expectCacheTagsRegistered(mockCacheTag, 'admin', ['users', 'byId'], { id: '123' });
});See Also
- Cache Methods - How these utilities are used
- Hierarchical Tagging - Concept explanation
- Types - TypeScript type definitions