Something went wrong. Try again.
[READ-ONLY]
a fast, modern browser for the npm registry forked from npmx.dev/npmx.dev
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111/** * Configuration for the stale-while-revalidate fetch cache. * * This cache intercepts external API calls during SSR and caches responses * using Nitro's storage layer (backed by Vercel's runtime cache in production). */
import { CONSTELLATION_HOST, SLINGSHOT_HOST } from './constants'
/** * Domains that should have their fetch responses cached. * Only requests to these domains will be intercepted and cached. */export const FETCH_CACHE_ALLOWED_DOMAINS = [ // npm registry 'registry.npmjs.org', // npm package metadata (packuments) 'api.npmjs.org', // npm download statistics
// JSR registry 'jsr.io', // JSR package metadata
// Git hosting providers (for repo metadata) 'ungh.cc', // GitHub proxy (avoids rate limits) 'api.github.com', // GitHub API 'gitlab.com', // GitLab API 'api.bitbucket.org', // Bitbucket API 'codeberg.org', // Codeberg (Gitea-based) 'gitee.com', // Gitee API // microcosm endpoints for atproto data CONSTELLATION_HOST, SLINGSHOT_HOST,] as const
/** * Default TTL for cached fetch responses (in seconds). * After this time, cached data is considered "stale" but will still be * returned immediately while a background revalidation occurs. */export const FETCH_CACHE_DEFAULT_TTL = 60 * 5 // 5 minutes
/** * Cache key version prefix. * Increment this to invalidate all cached entries (e.g., after format changes). */export const FETCH_CACHE_VERSION = 'v1'
/** * Storage key prefix for fetch cache entries. */export const FETCH_CACHE_STORAGE_BASE = 'fetch-cache'
/** * Check if a URL's host is in the allowed domains list. */export function isAllowedDomain(url: string | URL): boolean { try { const urlObj = typeof url === 'string' ? new URL(url) : url return FETCH_CACHE_ALLOWED_DOMAINS.some(domain => urlObj.host === domain) } catch { return false }}
/** * Structure of a cached fetch entry stored in Nitro storage. */export interface CachedFetchEntry<T = unknown> { /** The response body/data */ data: T /** HTTP status code */ status: number /** Response headers (subset) */ headers: Record<string, string> /** Unix timestamp when the entry was cached */ cachedAt: number /** TTL in seconds */ ttl: number}
/** * Check if a cached entry is stale (past its TTL). */export function isCacheEntryStale(entry: CachedFetchEntry): boolean { const now = Date.now() const expiresAt = entry.cachedAt + entry.ttl * 1000 return now > expiresAt}
/** * Result returned by cachedFetch with staleness metadata. * This allows consumers to know if the data came from stale cache * and potentially trigger client-side revalidation. */export interface CachedFetchResult<T> { /** The response data */ data: T /** Whether the data came from stale cache (past TTL) */ isStale: boolean /** Unix timestamp when the data was cached, or null if fresh fetch */ cachedAt: number | null}
/** * Type for the cachedFetch function attached to event context. */export type CachedFetchFunction = <T = unknown>( url: string, options?: Parameters<typeof $fetch>[1], ttl?: number,) => Promise<CachedFetchResult<T>>