[READ-ONLY] a fast, modern browser for the npm registry
at main 70 lines 2.5 kB view raw
1import type { CachedFetchResult } from '#shared/utils/fetch-cache-config' 2import { defu } from 'defu' 3 4/** 5 * Get the cachedFetch function from the current request context. 6 * 7 * IMPORTANT: This must be called in the composable setup context (outside of 8 * useAsyncData handlers). The returned function can then be used inside handlers. 9 * 10 * The returned function returns a wrapper object with staleness metadata: 11 * - `data`: The response data 12 * - `isStale`: Whether the data came from stale cache 13 * - `cachedAt`: Unix timestamp when cached, or null if fresh fetch 14 * 15 * @example 16 * ```ts 17 * export function usePackage(name: MaybeRefOrGetter<string>) { 18 * // Get cachedFetch in setup context 19 * const cachedFetch = useCachedFetch() 20 * 21 * return useLazyAsyncData( 22 * () => `package:${toValue(name)}`, 23 * // Use it inside the handler - destructure { data } or { data, isStale } 24 * async () => { 25 * const { data } = await cachedFetch<Packument>(`https://registry.npmjs.org/${toValue(name)}`) 26 * return data 27 * } 28 * ) 29 * } 30 * ``` 31 */ 32export function useCachedFetch(): CachedFetchFunction { 33 // On client, return a function that just uses $fetch (no caching, not stale) 34 if (import.meta.client) { 35 return async <T = unknown>( 36 url: string, 37 options: Parameters<typeof $fetch>[1] = {}, 38 _ttl: number = FETCH_CACHE_DEFAULT_TTL, 39 ): Promise<CachedFetchResult<T>> => { 40 const defaultFetchOptions: Parameters<typeof $fetch>[1] = { 41 cache: 'force-cache', 42 } 43 const data = (await $fetch<T>(url, defu(options, defaultFetchOptions))) as T 44 return { data, isStale: false, cachedAt: null } 45 } 46 } 47 48 // On server, get the cachedFetch from request context 49 const event = useRequestEvent() 50 const serverCachedFetch = event?.context?.cachedFetch 51 52 // If cachedFetch is available from middleware, return it 53 if (serverCachedFetch) { 54 return serverCachedFetch as CachedFetchFunction 55 } 56 57 // Fallback: return a function that uses regular $fetch 58 // (shouldn't happen in normal operation) 59 return async <T = unknown>( 60 url: string, 61 options: Parameters<typeof $fetch>[1] = {}, 62 _ttl: number = FETCH_CACHE_DEFAULT_TTL, 63 ): Promise<CachedFetchResult<T>> => { 64 const defaultFetchOptions: Parameters<typeof $fetch>[1] = { 65 cache: 'force-cache', 66 } 67 const data = (await $fetch<T>(url, defu(options, defaultFetchOptions))) as T 68 return { data, isStale: false, cachedAt: null } 69 } 70}