2026-01-06 14:38:55 +03:00
|
|
|
/**
|
|
|
|
|
* Google Fonts API client
|
|
|
|
|
*
|
|
|
|
|
* Handles API requests to Google Fonts API for fetching font metadata.
|
|
|
|
|
* Provides error handling, retry logic, and type-safe responses.
|
|
|
|
|
*
|
|
|
|
|
* @see https://developers.google.com/fonts/docs/developer_api
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import { api } from '$shared/api/api';
|
2026-01-06 15:00:31 +03:00
|
|
|
import { buildQueryString } from '$shared/utils';
|
|
|
|
|
import type { QueryParams } from '$shared/utils';
|
2026-01-06 14:38:55 +03:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Google Fonts API parameters
|
|
|
|
|
*/
|
2026-01-06 15:00:31 +03:00
|
|
|
export interface GoogleFontsParams extends QueryParams {
|
2026-01-06 14:38:55 +03:00
|
|
|
/**
|
|
|
|
|
* Google Fonts API key (optional for public endpoints)
|
|
|
|
|
*/
|
|
|
|
|
key?: string;
|
|
|
|
|
/**
|
|
|
|
|
* Font family name (to fetch specific font)
|
|
|
|
|
*/
|
|
|
|
|
family?: string;
|
|
|
|
|
/**
|
|
|
|
|
* Font category filter (e.g., "sans-serif", "serif", "display")
|
|
|
|
|
*/
|
|
|
|
|
category?: string;
|
|
|
|
|
/**
|
|
|
|
|
* Character subset filter (e.g., "latin", "latin-ext", "cyrillic")
|
|
|
|
|
*/
|
|
|
|
|
subset?: string;
|
|
|
|
|
/**
|
|
|
|
|
* Sort order for results
|
|
|
|
|
*/
|
|
|
|
|
sort?: 'popularity' | 'alpha' | 'date' | 'style';
|
|
|
|
|
/**
|
|
|
|
|
* Cap the number of fonts returned
|
|
|
|
|
*/
|
|
|
|
|
capability?: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Google Fonts API response wrapper
|
|
|
|
|
*/
|
|
|
|
|
export interface GoogleFontsResponse {
|
|
|
|
|
kind: string;
|
|
|
|
|
items: GoogleFontItem[];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Simplified font item from Google Fonts API
|
|
|
|
|
*/
|
|
|
|
|
export interface GoogleFontItem {
|
|
|
|
|
family: string;
|
|
|
|
|
category: string;
|
|
|
|
|
variants: string[];
|
|
|
|
|
subsets: string[];
|
|
|
|
|
version: string;
|
|
|
|
|
lastModified: string;
|
|
|
|
|
files: Record<string, string>;
|
|
|
|
|
menu: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Google Fonts API base URL
|
|
|
|
|
*/
|
|
|
|
|
const GOOGLE_FONTS_API_URL = 'https://fonts.googleapis.com/v2/fonts' as const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Fetch fonts from Google Fonts API
|
|
|
|
|
*
|
|
|
|
|
* @param params - Query parameters for filtering fonts
|
|
|
|
|
* @returns Promise resolving to Google Fonts API response
|
|
|
|
|
* @throws ApiError when request fails
|
|
|
|
|
*
|
|
|
|
|
* @example
|
|
|
|
|
* ```ts
|
|
|
|
|
* // Fetch all sans-serif fonts sorted by popularity
|
|
|
|
|
* const response = await fetchGoogleFonts({
|
|
|
|
|
* category: 'sans-serif',
|
|
|
|
|
* sort: 'popularity'
|
|
|
|
|
* });
|
|
|
|
|
*
|
|
|
|
|
* // Fetch specific font family
|
|
|
|
|
* const robotoResponse = await fetchGoogleFonts({
|
|
|
|
|
* family: 'Roboto'
|
|
|
|
|
* });
|
|
|
|
|
* ```
|
|
|
|
|
*/
|
|
|
|
|
export async function fetchGoogleFonts(
|
|
|
|
|
params: GoogleFontsParams = {},
|
|
|
|
|
): Promise<GoogleFontsResponse> {
|
|
|
|
|
const queryString = buildQueryString(params);
|
|
|
|
|
const url = `${GOOGLE_FONTS_API_URL}${queryString}`;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const response = await api.get<GoogleFontsResponse>(url);
|
|
|
|
|
return response.data;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
// Re-throw ApiError with context
|
|
|
|
|
if (error instanceof Error) {
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
throw new Error(`Failed to fetch Google Fonts: ${String(error)}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Fetch font by family name
|
|
|
|
|
* Convenience function for fetching a single font
|
|
|
|
|
*
|
|
|
|
|
* @param family - Font family name (e.g., "Roboto")
|
|
|
|
|
* @returns Promise resolving to Google Font item
|
|
|
|
|
*
|
|
|
|
|
* @example
|
|
|
|
|
* ```ts
|
|
|
|
|
* const roboto = await fetchGoogleFontFamily('Roboto');
|
|
|
|
|
* ```
|
|
|
|
|
*/
|
|
|
|
|
export async function fetchGoogleFontFamily(
|
|
|
|
|
family: string,
|
|
|
|
|
): Promise<GoogleFontItem | undefined> {
|
|
|
|
|
const response = await fetchGoogleFonts({ family });
|
|
|
|
|
return response.items.find(item => item.family === family);
|
|
|
|
|
}
|