/** * Helper for grouping and caching events by hash * Centralizes the pattern of grouping events by hash ID and caching the latest version */ import type { Event } from 'nostr-tools' import { extractTagsFromEvent } from '../nostrTagSystem' import { parseObjectId } from '../urlGenerator' import { getLatestVersion } from '../versionManager' import type { ObjectType } from '../objectCache' import { writeObjectToCache } from './writeObjectHelper' export interface EventCacheConfig { objectType: ObjectType extractor: (event: Event) => Promise getHash?: (extracted: unknown) => string | null getIndex?: (extracted: unknown) => number getVersion?: (event: Event) => number getHidden?: (event: Event) => boolean } interface ExtractedObjectWithId { id?: string index?: number } /** * Group events by hash ID and cache the latest version of each */ export async function groupAndCacheEventsByHash( events: Event[], config: EventCacheConfig ): Promise { const { objectType, extractor, getHash, getIndex, getVersion, getHidden } = config // Group events by hash ID const eventsByHashId = new Map() for (const event of events) { const tags = extractTagsFromEvent(event) if (tags.id) { // Extract hash from id (can be __ or just hash) const parsed = parseObjectId(tags.id) const hash = parsed.hash ?? tags.id if (!eventsByHashId.has(hash)) { eventsByHashId.set(hash, []) } const hashEvents = eventsByHashId.get(hash) if (hashEvents) { hashEvents.push(event) } } } // Cache each object (latest version) for (const [_hash, hashEvents] of eventsByHashId.entries()) { const latestEvent = getLatestVersion(hashEvents) if (latestEvent) { const extracted = await extractor(latestEvent) if (extracted) { // Get hash, index, version, hidden const extractedHash = getHash ? getHash(extracted) : null const extractedObj = extracted as ExtractedObjectWithId const extractedId = extractedHash ?? extractedObj.id if (extractedId) { const publicationParsed = parseObjectId(extractedId) const hash = publicationParsed.hash ?? extractedId const index = getIndex ? getIndex(extracted) : publicationParsed.index ?? extractedObj.index ?? 0 const version = getVersion ? getVersion(latestEvent) : extractTagsFromEvent(latestEvent).version ?? 0 const hidden = getHidden ? getHidden(latestEvent) : extractTagsFromEvent(latestEvent).hidden ?? false await writeObjectToCache({ objectType, hash, event: latestEvent, parsed: extracted, version, hidden, index, }) } } } } } /** * Cache a single event as an object * Simplified version for direct event caching */ export async function cacheEventAsObject( event: Event, objectType: ObjectType, extractor: (event: Event) => Promise ): Promise { const extracted = await extractor(event) if (!extracted) { return false } const tags = extractTagsFromEvent(event) const hash = (extracted as { hash?: string })?.hash ?? (extracted as { id?: string })?.id ?? '' if (!hash) { return false } const index = (extracted as { index?: number })?.index ?? 0 await writeObjectToCache({ objectType, hash, event, parsed: extracted, version: tags.version, hidden: tags.hidden, index, }) return true }