Files
frontend-svelte/src/features/FetchFonts/model/services/fetchGoogleFonts.ts
Ilia Mashkov 2c666646cb style(font): fix lint warnings - remove unused imports and variables
- Removed unused FontFeatures, FontMetadata, FontProvider from normalize.ts imports
- Removed unused UnifiedFont from normalize.test.ts imports
- Removed unused FontSubset from store.ts imports
- Changed unused queryClient variables to void calls to suppress warnings
2026-01-06 15:24:34 +03:00

214 lines
5.4 KiB
TypeScript

/**
* Service for fetching Google Fonts
*
* Integrates with TanStack Query for caching, deduplication,
* and automatic refetching.
*
* Uses reactive query args pattern for Svelte 5 compatibility.
*/
import { fetchGoogleFonts } from '$entities/Font/api/google/googleFonts';
import { normalizeGoogleFonts } from '$entities/Font/api/normalize/normalize';
import type {
FontCategory,
FontSubset,
} from '$entities/Font/model/types';
import type { UnifiedFont } from '$entities/Font/model/types/normalize';
import type { QueryFunction } from '@tanstack/svelte-query';
import {
createQuery,
useQueryClient,
} from '@tanstack/svelte-query';
/**
* Google Fonts query parameters
*/
export interface GoogleFontsQueryParams {
/** Font category filter */
category?: FontCategory;
/** Character subset filter */
subset?: FontSubset;
/** Sort order */
sort?: 'popularity' | 'alpha' | 'date';
/** Search query (for specific font) */
search?: string;
/** Force refetch even if cached */
forceRefetch?: boolean;
}
/**
* Query key factory for Google Fonts
* Generates consistent query keys for cache management
*/
export function getGoogleFontsQueryKey(
params: GoogleFontsQueryParams,
): readonly unknown[] {
return ['googleFonts', params];
}
/**
* Query function for fetching Google Fonts
* Handles caching, loading states, and errors
*/
export const fetchGoogleFontsQuery: QueryFunction<
UnifiedFont[],
readonly unknown[]
> = async ({ queryKey }) => {
const params = queryKey[1] as GoogleFontsQueryParams;
try {
const response = await fetchGoogleFonts({
category: params.category,
subset: params.subset,
sort: params.sort,
});
const normalizedFonts = normalizeGoogleFonts(response.items);
return normalizedFonts;
} catch (error) {
// User-friendly error messages
if (error instanceof Error) {
if (error.message.includes('Failed to fetch')) {
throw new Error(
'Unable to connect to Google Fonts. Please check your internet connection and try again.',
);
}
if (error.message.includes('404')) {
throw new Error('Font not found in Google Fonts catalog.');
}
throw new Error(
'Failed to load fonts from Google Fonts. Please try again later.',
);
}
throw new Error('An unexpected error occurred while fetching fonts.');
}
};
/**
* Create a Google Fonts query hook
* Use this in Svelte components to fetch Google Fonts with caching
*
* @param params - Query parameters
* @returns Query result with data, loading state, and error
*
* @example
* ```svelte
* <script lang="ts">
* let { category }: { category?: FontCategory } = $props();
*
* const query = useGoogleFontsQuery({ category });
*
* if ($query.isLoading) {
* return <LoadingSpinner />;
* }
*
* if ($query.error) {
* return <ErrorMessage message={$query.error.message} />;
* }
*
* const fonts = $query.data ?? [];
* </script>
*
* {#each fonts as font}
* <FontCard {font} />
* {/each}
* ```
*/
export function useGoogleFontsQuery(params: GoogleFontsQueryParams = {}) {
useQueryClient();
const query = createQuery(() => ({
queryKey: getGoogleFontsQueryKey(params),
queryFn: fetchGoogleFontsQuery,
staleTime: 5 * 60 * 1000, // 5 minutes
gcTime: 10 * 60 * 1000, // 10 minutes
}));
return query;
}
/**
* Prefetch Google Fonts
* Fetch fonts in background without showing loading state
*
* @param params - Query parameters for prefetch
*
* @example
* ```ts
* // Prefetch fonts when user hovers over button
* function onMouseEnter() {
* prefetchGoogleFonts({ category: 'sans-serif' });
* }
* ```
*/
export async function prefetchGoogleFonts(
params: GoogleFontsQueryParams = {},
): Promise<void> {
const queryClient = useQueryClient();
await queryClient.prefetchQuery({
queryKey: getGoogleFontsQueryKey(params),
queryFn: fetchGoogleFontsQuery,
staleTime: 5 * 60 * 1000,
});
}
/**
* Invalidate Google Fonts cache
* Forces refetch on next query
*
* @param params - Query parameters to invalidate (all if not provided)
*
* @example
* ```ts
* // Invalidate all Google Fonts cache
* invalidateGoogleFonts();
*
* // Invalidate specific category cache
* invalidateGoogleFonts({ category: 'sans-serif' });
* ```
*/
export function invalidateGoogleFonts(
params?: GoogleFontsQueryParams,
): void {
const queryClient = useQueryClient();
if (params) {
queryClient.invalidateQueries({
queryKey: getGoogleFontsQueryKey(params),
});
} else {
queryClient.invalidateQueries({
queryKey: ['googleFonts'],
});
}
}
/**
* Cancel Google Fonts queries
* Abort in-flight requests
*
* @param params - Query parameters to cancel (all if not provided)
*
* @example
* ```ts
* // Cancel all Google Fonts queries
* cancelGoogleFontsQueries();
* ```
*/
export function cancelGoogleFontsQueries(
params?: GoogleFontsQueryParams,
): void {
const queryClient = useQueryClient();
if (params) {
queryClient.cancelQueries({
queryKey: getGoogleFontsQueryKey(params),
});
} else {
queryClient.cancelQueries({
queryKey: ['googleFonts'],
});
}
}