diff --git a/src/entities/Font/model/store/baseFontStore.svelte.ts b/src/entities/Font/model/store/baseFontStore.svelte.ts index 21d62cb..6f38f97 100644 --- a/src/entities/Font/model/store/baseFontStore.svelte.ts +++ b/src/entities/Font/model/store/baseFontStore.svelte.ts @@ -9,7 +9,6 @@ import type { UnifiedFont } from '../types'; /** */ export abstract class BaseFontStore> { - // params = $state({} as TParams); cleanup: () => void; #bindings = $state<(() => Partial)[]>([]); @@ -18,9 +17,11 @@ export abstract class BaseFontStore> { params = $derived.by(() => { let merged = { ...this.#internalParams }; + // Loop through every "Cable" plugged into the store // Loop through every "Cable" plugged into the store for (const getter of this.#bindings) { - merged = { ...merged, ...getter() }; + const bindingResult = getter(); + merged = { ...merged, ...bindingResult }; } return merged as TParams; @@ -54,7 +55,7 @@ export abstract class BaseFontStore> { protected abstract getQueryKey(params: TParams): QueryKey; protected abstract fetchFn(params: TParams): Promise; - private getOptions(params = this.params): QueryObserverOptions { + protected getOptions(params = this.params): QueryObserverOptions { return { queryKey: this.getQueryKey(params), queryFn: () => this.fetchFn(params), diff --git a/src/entities/Font/model/store/unifiedFontStore.svelte.ts b/src/entities/Font/model/store/unifiedFontStore.svelte.ts index b229709..da718c5 100644 --- a/src/entities/Font/model/store/unifiedFontStore.svelte.ts +++ b/src/entities/Font/model/store/unifiedFontStore.svelte.ts @@ -12,6 +12,7 @@ * - Provider-specific shortcuts for common operations */ +import type { QueryObserverOptions } from '@tanstack/query-core'; import type { ProxyFontsParams } from '../../api'; import { fetchProxyFonts } from '../../api'; import type { UnifiedFont } from '../types'; @@ -121,6 +122,19 @@ export class UnifiedFontStore extends BaseFontStore { this.#previousFilterParams = filterParams; } }); + + // Effect: Sync state from Query result (Handles Cache Hits) + $effect(() => { + const data = this.result.data; + const offset = this.params.offset || 0; + + // When we have data and we are at the start (offset 0), + // we must ensure accumulatedFonts matches the fresh (or cached) data. + // This fixes the issue where cache hits skip fetchFn side-effects. + if (offset === 0 && data && data.length > 0) { + this.#accumulatedFonts = data; + } + }); }); } @@ -145,15 +159,26 @@ export class UnifiedFontStore extends BaseFontStore { protected getQueryKey(params: ProxyFontsParams) { // Normalize params to treat empty arrays/strings as undefined const normalized = Object.entries(params).reduce((acc, [key, value]) => { - if (value === '' || (Array.isArray(value) && value.length === 0)) { + if (value === '' || value === undefined || (Array.isArray(value) && value.length === 0)) { return acc; } return { ...acc, [key]: value }; }, {}); + // Return a consistent key return ['unifiedFonts', normalized] as const; } + protected getOptions(params = this.params): QueryObserverOptions { + const hasFilters = !!(params.q || params.provider || params.category || params.subset); + return { + queryKey: this.getQueryKey(params), + queryFn: () => this.fetchFn(params), + staleTime: hasFilters ? 0 : 5 * 60 * 1000, + gcTime: 10 * 60 * 1000, + }; + } + /** * Fetch function that calls the proxy API * Returns the full response including pagination metadata @@ -187,11 +212,10 @@ export class UnifiedFontStore extends BaseFontStore { }; // Accumulate fonts for infinite scroll - if (params.offset === 0) { - // Reset when starting from beginning (new search/filter) - this.#accumulatedFonts = response.fonts; - } else { - // Append new fonts to existing ones + // Note: For offset === 0, we rely on the $effect above to handle the reset/init + // This prevents race conditions and double-setting. + if (params.offset !== 0) { + // Append new fonts to existing ones only for pagination this.#accumulatedFonts = [...this.#accumulatedFonts, ...response.fonts]; }