57 lines
1.6 KiB
TypeScript
57 lines
1.6 KiB
TypeScript
export interface CachedDocMeta {
|
|
id: string
|
|
title: string
|
|
date?: string
|
|
timestamp?: number
|
|
place?: string
|
|
city?: string
|
|
state?: string
|
|
country?: string
|
|
type?: string
|
|
slug?: string
|
|
draft?: string
|
|
[key: string]: unknown
|
|
}
|
|
|
|
const MAX_ENTRIES = 500
|
|
|
|
function cacheKey(collection: string, id: string): string {
|
|
return `${collection}:${id}`
|
|
}
|
|
|
|
/**
|
|
* Caché de metadata de documentos (título, fecha, lugar...) compartida entre
|
|
* páginas de búsqueda, con vida de sesión (sobrevive entre queries, no se
|
|
* vacía al buscar de nuevo). Clave `collection:id` porque los IDs no son
|
|
* únicos entre colecciones (p.ej. `conferences` vs `activities`).
|
|
*
|
|
* Tope de tamaño con eviction LRU simple: en cada lectura/escritura la
|
|
* entrada se reinserta al final del Map (orden de inserción = recencia), así
|
|
* que la más antigua a evictar siempre es `.keys().next().value`.
|
|
*/
|
|
export function useDocMetaCache() {
|
|
const cache = useState<Map<string, CachedDocMeta>>('doc-meta-cache', () => new Map())
|
|
|
|
function get(collection: string, id: string): CachedDocMeta | undefined {
|
|
const key = cacheKey(collection, id)
|
|
const entry = cache.value.get(key)
|
|
if (entry) {
|
|
cache.value.delete(key)
|
|
cache.value.set(key, entry)
|
|
}
|
|
return entry
|
|
}
|
|
|
|
function set(collection: string, id: string, meta: CachedDocMeta) {
|
|
const key = cacheKey(collection, id)
|
|
cache.value.delete(key)
|
|
cache.value.set(key, meta)
|
|
if (cache.value.size > MAX_ENTRIES) {
|
|
const oldestKey = cache.value.keys().next().value
|
|
if (oldestKey !== undefined) cache.value.delete(oldestKey)
|
|
}
|
|
}
|
|
|
|
return { get, set }
|
|
}
|