92 lines
2.3 KiB
TypeScript
92 lines
2.3 KiB
TypeScript
import { fontKeys } from '$shared/api/queryKeys';
|
|
import { BaseQueryStore } from '$shared/lib/helpers/BaseQueryStore.svelte';
|
|
import {
|
|
fetchFontsByIds,
|
|
seedFontCache,
|
|
} from '../../api/proxy/proxyFonts';
|
|
import {
|
|
FontNetworkError,
|
|
FontResponseError,
|
|
} from '../../lib/errors/errors';
|
|
import type { UnifiedFont } from '../../model/types';
|
|
|
|
/**
|
|
* Internal fetcher that seeds the cache and handles error wrapping.
|
|
* Standalone function to avoid 'this' issues during construction.
|
|
*/
|
|
async function fetchAndSeed(ids: string[]): Promise<UnifiedFont[]> {
|
|
if (ids.length === 0) return [];
|
|
|
|
let response: UnifiedFont[];
|
|
try {
|
|
response = await fetchFontsByIds(ids);
|
|
} catch (cause) {
|
|
throw new FontNetworkError(cause);
|
|
}
|
|
|
|
if (!response || !Array.isArray(response)) {
|
|
throw new FontResponseError('batchResponse', response);
|
|
}
|
|
|
|
seedFontCache(response);
|
|
return response;
|
|
}
|
|
|
|
/**
|
|
* Reactive store for fetching and caching batches of fonts by ID.
|
|
* Integrates with TanStack Query via BaseQueryStore and handles
|
|
* normalized cache seeding.
|
|
*/
|
|
export class BatchFontStore extends BaseQueryStore<UnifiedFont[]> {
|
|
constructor(initialIds: string[] = []) {
|
|
super({
|
|
queryKey: fontKeys.batch(initialIds),
|
|
queryFn: () => fetchAndSeed(initialIds),
|
|
enabled: initialIds.length > 0,
|
|
retry: false,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Updates the IDs to fetch. Triggers a new query.
|
|
*
|
|
* @param ids - Array of font IDs
|
|
*/
|
|
setIds(ids: string[]): void {
|
|
this.updateOptions({
|
|
queryKey: fontKeys.batch(ids),
|
|
queryFn: () => fetchAndSeed(ids),
|
|
enabled: ids.length > 0,
|
|
retry: false,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Array of fetched fonts
|
|
*/
|
|
get fonts(): UnifiedFont[] {
|
|
return this.result.data ?? [];
|
|
}
|
|
|
|
/**
|
|
* Whether the query is currently loading
|
|
*/
|
|
get isLoading(): boolean {
|
|
return this.result.isLoading;
|
|
}
|
|
|
|
/**
|
|
* Whether the query encountered an error
|
|
*/
|
|
get isError(): boolean {
|
|
return this.result.isError;
|
|
}
|
|
|
|
/**
|
|
* The error object if the query failed
|
|
*/
|
|
get error(): Error | null {
|
|
return (this.result.error as Error) ?? null;
|
|
}
|
|
}
|