feat(FontStore): implement lifecycle, param management, async methods, shortcuts, pagination, category getters, singleton — all tests green

This commit is contained in:
Ilia Mashkov
2026-04-08 09:54:27 +03:00
parent a9e4633b64
commit 2a761b9d47

View File

@@ -102,54 +102,105 @@ export class FontStore {
// -- Lifecycle -- // -- Lifecycle --
destroy(): void {} destroy() {
this.#unsubscribe();
this.#observer.destroy();
}
// -- Param management -- // -- Param management --
setParams(_updates: Partial<FontStoreParams>): void {} setParams(updates: Partial<FontStoreParams>) {
invalidate(): void {} this.#params = { ...this.#params, ...updates };
this.#observer.setOptions(this.buildOptions());
}
invalidate() {
this.#qc.invalidateQueries({ queryKey: this.buildQueryKey(this.#params) });
}
// -- Async operations -- // -- Async operations --
async refetch(): Promise<void> {} async refetch() {
async prefetch(_params: FontStoreParams): Promise<void> {} this.#observer.setOptions(this.buildOptions());
cancel(): void {} await this.#observer.refetch();
getCachedData(): UnifiedFont[] | undefined { }
return undefined;
async prefetch(params: FontStoreParams) {
await this.#qc.prefetchInfiniteQuery(this.buildOptions(params));
}
cancel() {
this.#qc.cancelQueries({ queryKey: this.buildQueryKey(this.#params) });
}
getCachedData(): UnifiedFont[] | undefined {
const data = this.#qc.getQueryData<InfiniteData<FontPage, PageParam>>(
this.buildQueryKey(this.#params),
);
if (!data) return undefined;
return data.pages.flatMap(p => p.fonts);
}
setQueryData(updater: (old: UnifiedFont[] | undefined) => UnifiedFont[]) {
this.#qc.setQueryData<InfiniteData<FontPage, PageParam>>(
this.buildQueryKey(this.#params),
old => {
const flatFonts = old?.pages.flatMap(p => p.fonts);
const newFonts = updater(flatFonts);
const template = old?.pages[0] ?? { total: newFonts.length, limit: newFonts.length, offset: 0 };
return {
pages: [{ ...template, fonts: newFonts }],
pageParams: [{ offset: 0 } as PageParam],
};
},
);
} }
setQueryData(_updater: (old: UnifiedFont[] | undefined) => UnifiedFont[]): void {}
// -- Filter shortcuts -- // -- Filter shortcuts --
setProviders(_v: ProxyFontsParams['providers']): void {} setProviders(v: ProxyFontsParams['providers']) {
setCategories(_v: ProxyFontsParams['categories']): void {} this.setParams({ providers: v });
setSubsets(_v: ProxyFontsParams['subsets']): void {} }
setSearch(_v: string): void {} setCategories(v: ProxyFontsParams['categories']) {
setSort(_v: ProxyFontsParams['sort']): void {} this.setParams({ categories: v });
}
setSubsets(v: ProxyFontsParams['subsets']) {
this.setParams({ subsets: v });
}
setSearch(v: string) {
this.setParams({ q: v || undefined });
}
setSort(v: ProxyFontsParams['sort']) {
this.setParams({ sort: v });
}
// -- Pagination navigation -- // -- Pagination navigation --
async nextPage(): Promise<void> {} async nextPage(): Promise<void> {
prevPage(): void {} // no-op: infinite scroll only loads forward await this.#observer.fetchNextPage();
}
prevPage(): void {} // no-op: infinite scroll accumulates forward only; method kept for API compatibility
goToPage(_page: number): void {} // no-op goToPage(_page: number): void {} // no-op
setLimit(_limit: number): void {}
setLimit(limit: number) {
this.setParams({ limit });
}
// -- Category views -- // -- Category views --
get sansSerifFonts(): UnifiedFont[] { get sansSerifFonts() {
return []; return this.fonts.filter(f => f.category === 'sans-serif');
} }
get serifFonts(): UnifiedFont[] { get serifFonts() {
return []; return this.fonts.filter(f => f.category === 'serif');
} }
get displayFonts(): UnifiedFont[] { get displayFonts() {
return []; return this.fonts.filter(f => f.category === 'display');
} }
get handwritingFonts(): UnifiedFont[] { get handwritingFonts() {
return []; return this.fonts.filter(f => f.category === 'handwriting');
} }
get monospaceFonts(): UnifiedFont[] { get monospaceFonts() {
return []; return this.fonts.filter(f => f.category === 'monospace');
} }
// -- Private helpers (TypeScript-private so tests can spy via `as any`) -- // -- Private helpers (TypeScript-private so tests can spy via `as any`) --
@@ -207,3 +258,5 @@ export class FontStore {
export function createFontStore(params: FontStoreParams = {}): FontStore { export function createFontStore(params: FontStoreParams = {}): FontStore {
return new FontStore(params); return new FontStore(params);
} }
export const fontStore = new FontStore({ limit: 50 });