UNPKG

@lucidclient/speculate

Version:

A lightweight library to handle speculate rules for prefetching and prerendering documents, with added support for data fetching on intent.

171 lines (161 loc) 4.42 kB
/** * Initialises the speculation library using requestIdleCallback if available */ declare const init: () => () => void; // -------------------------------------------------------- // Speculator type IntentError<D> = { message: string; exception?: unknown; details?: D; }; type IntentResult<T, D> = | { error: IntentError<D>; data: undefined } | { error: undefined; data: NonNullable<T> }; type IntentResponse<T, D> = Promise<IntentResult<T, D>>; type TargetElements = | Element | NodeListOf<Element> | Element[] | null | undefined; type OptimisticPrefetchStrategy = { /** * Elements to prefetch immediately when the strategy is active */ elements: TargetElements; /** * Priority order for prefetching (lower numbers = higher priority) */ priority?: number; /** * A condition that must be true for this strategy to be active */ condition?: () => boolean; }; type SpeculatorConfig<T, D> = { /** * Elements that will trigger prefetching when user intent is determined */ elements: TargetElements; /** * Strategies for optimistically prefetching on initialisation when idle */ optimistic?: OptimisticPrefetchStrategy | OptimisticPrefetchStrategy[]; /** * Callback that fetches the data for an element when user intent is determined * @returns Promise that resolves with either data or an error */ fetch: (element: Element) => IntentResponse<T, D>; /** * Called when a target element is clicked */ onClick?: (e: Event, result: IntentResult<T, D>) => void; /** * Cache configuration to control data freshness and memory usage */ cache?: { /** * Maximum number of responses to keep in cache * @default 5 */ maxSize?: number; /** * How long cached responses remain valid (in milliseconds) * @default 120000 */ staleTime?: number; }; /** * Generate a cache key for an element. Used to store and retrieve cached responses. * By default, it will fallback to the elements ID if it has one, otherwise responses will not be cached. * Return null/undefined to skip caching for an element. */ getCacheKey?: (element: Element) => string | undefined | null; /** * Delay before prefetching on hover (in milliseconds). * Helps avoid unnecessary loads during quick mouse movements. * @default 200 */ hoverDelay?: number; }; declare class Speculator<T, D> { private config; private cache; private abortController; private intentDebounce; constructor(config: SpeculatorConfig<T, D>); /** * Registers all required events */ private registerEvents; /** * The target mouseover event handler */ private mouseOverEventHandler; /** * The target click event handler */ private clickEventHandler; /** * Gets a cache key for an element */ private getCacheKey; /** * Checks if a cached item is stale */ private isStale; /** * Manages the cache size by removing oldest entries when limit is reached */ private manageCacheSize; /** * Handles optimistic prefetching based on configured strategies */ private handleOptimisticPrefetch; /** * Wraps the fetch callback to ensure consistent error handling */ private executeFetchCallback; /** * Scheduels the prefetch for when idle */ private schedulePrefetch; /** * Normalises a TargetElements value */ private normaliseTargets; /** * Cache config w/ defaults */ private get cacheConfig(); /** * Normalises optimistic strategies */ private get optimisticStrategies(); /** * Hover delay w/ config */ private get hoverDelay(); /** * Destroys and resets the Speculator instance */ destroy(): void; /** * Refreshes the Speculator instance */ refresh(refreshConfig?: Partial<Pick<SpeculatorConfig<T, D>, "elements" | "optimistic">>): void; /** * Prefetch fetch callback for a given element. */ prefetch(element: Element): Promise<IntentResult<T, D>>; /** * Prefetch multiple elements at once */ prefetchAll(elements: Element[] | NodeListOf<Element>): Promise<IntentResult<T, D>[]>; /** * Clears a cache entry. If no element is provided, clears entire cache */ clearCache(element?: Element): void; } export { Speculator, init as speculateLinks };