feat(fonts): implement Phase 1 - Create Proxy API Client
- Created src/entities/Font/api/proxy/proxyFonts.ts - Implemented fetchProxyFonts function with full pagination support - Implemented fetchProxyFontById convenience function - Added TypeScript interfaces: ProxyFontsParams, ProxyFontsResponse - Added comprehensive JSDoc documentation - Updated src/entities/Font/api/index.ts to export proxy API Phase 1/7: Proxy API Integration for GlyphDiff
This commit is contained in:
@@ -4,6 +4,17 @@
|
||||
* Exports API clients and normalization utilities
|
||||
*/
|
||||
|
||||
// Proxy API (PRIMARY - NEW)
|
||||
export {
|
||||
fetchProxyFontById,
|
||||
fetchProxyFonts,
|
||||
} from './proxy/proxyFonts';
|
||||
export type {
|
||||
ProxyFontsParams,
|
||||
ProxyFontsResponse,
|
||||
} from './proxy/proxyFonts';
|
||||
|
||||
// Google Fonts API (DEPRECATED - kept for backward compatibility)
|
||||
export {
|
||||
fetchGoogleFontFamily,
|
||||
fetchGoogleFonts,
|
||||
@@ -14,6 +25,7 @@ export type {
|
||||
GoogleFontsResponse,
|
||||
} from './google/googleFonts';
|
||||
|
||||
// Fontshare API (DEPRECATED - kept for backward compatibility)
|
||||
export {
|
||||
fetchAllFontshareFonts,
|
||||
fetchFontshareFontBySlug,
|
||||
|
||||
160
src/entities/Font/api/proxy/proxyFonts.ts
Normal file
160
src/entities/Font/api/proxy/proxyFonts.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* Proxy API client
|
||||
*
|
||||
* Handles API requests to GlyphDiff proxy API for fetching font metadata.
|
||||
* Provides error handling, pagination support, and type-safe responses.
|
||||
*
|
||||
* Proxy API normalizes font data from Google Fonts and Fontshare into a single
|
||||
* unified format, eliminating the need for client-side normalization.
|
||||
*
|
||||
* @see https://api.glyphdiff.com/api/v1/fonts
|
||||
*/
|
||||
|
||||
import { api } from '$shared/api/api';
|
||||
import { buildQueryString } from '$shared/lib/utils';
|
||||
import type { QueryParams } from '$shared/lib/utils';
|
||||
import type { UnifiedFont } from '../../model/types';
|
||||
import type {
|
||||
FontCategory,
|
||||
FontSubset,
|
||||
} from '../../model/types';
|
||||
|
||||
/**
|
||||
* Proxy API base URL
|
||||
*/
|
||||
const PROXY_API_URL = 'https://api.glyphdiff.com/api/v1/fonts' as const;
|
||||
|
||||
/**
|
||||
* Proxy API parameters
|
||||
*
|
||||
* Maps directly to the proxy API query parameters
|
||||
*/
|
||||
export interface ProxyFontsParams extends QueryParams {
|
||||
/**
|
||||
* Font provider filter ("google" or "fontshare")
|
||||
* Omit to fetch from both providers
|
||||
*/
|
||||
provider?: 'google' | 'fontshare';
|
||||
|
||||
/**
|
||||
* Font category filter
|
||||
*/
|
||||
category?: FontCategory;
|
||||
|
||||
/**
|
||||
* Character subset filter
|
||||
*/
|
||||
subset?: FontSubset;
|
||||
|
||||
/**
|
||||
* Search query (e.g., "roboto", "satoshi")
|
||||
*/
|
||||
q?: string;
|
||||
|
||||
/**
|
||||
* Sort order for results
|
||||
* "name" - Alphabetical by font name
|
||||
* "popularity" - Most popular first
|
||||
* "lastModified" - Recently updated first
|
||||
*/
|
||||
sort?: 'name' | 'popularity' | 'lastModified';
|
||||
|
||||
/**
|
||||
* Number of items to return (pagination)
|
||||
*/
|
||||
limit?: number;
|
||||
|
||||
/**
|
||||
* Number of items to skip (pagination)
|
||||
* Use for pagination: offset = (page - 1) * limit
|
||||
*/
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy API response
|
||||
*
|
||||
* Includes pagination metadata alongside font data
|
||||
*/
|
||||
export interface ProxyFontsResponse {
|
||||
/** Array of unified font objects */
|
||||
fonts: UnifiedFont[];
|
||||
|
||||
/** Total number of fonts matching the query */
|
||||
total: number;
|
||||
|
||||
/** Limit used for this request */
|
||||
limit: number;
|
||||
|
||||
/** Offset used for this request */
|
||||
offset: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch fonts from proxy API
|
||||
*
|
||||
* @param params - Query parameters for filtering and pagination
|
||||
* @returns Promise resolving to proxy API response
|
||||
* @throws ApiError when request fails
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // Fetch all sans-serif fonts from Google
|
||||
* const response = await fetchProxyFonts({
|
||||
* provider: 'google',
|
||||
* category: 'sans-serif',
|
||||
* limit: 50,
|
||||
* offset: 0
|
||||
* });
|
||||
*
|
||||
* // Search fonts across all providers
|
||||
* const searchResponse = await fetchProxyFonts({
|
||||
* q: 'roboto',
|
||||
* limit: 20
|
||||
* });
|
||||
*
|
||||
* // Fetch fonts with pagination
|
||||
* const page1 = await fetchProxyFonts({ limit: 50, offset: 0 });
|
||||
* const page2 = await fetchProxyFonts({ limit: 50, offset: 50 });
|
||||
* ```
|
||||
*/
|
||||
export async function fetchProxyFonts(
|
||||
params: ProxyFontsParams = {},
|
||||
): Promise<ProxyFontsResponse> {
|
||||
const queryString = buildQueryString(params);
|
||||
const url = `${PROXY_API_URL}${queryString}`;
|
||||
|
||||
try {
|
||||
const response = await api.get<ProxyFontsResponse>(url);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
// Re-throw ApiError with context
|
||||
if (error instanceof Error) {
|
||||
throw error;
|
||||
}
|
||||
throw new Error(`Failed to fetch fonts from proxy API: ${String(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch font by ID
|
||||
*
|
||||
* Convenience function for fetching a single font by ID
|
||||
* Note: This fetches a page and filters client-side, which is not ideal
|
||||
* For production, consider adding a dedicated endpoint to the proxy API
|
||||
*
|
||||
* @param id - Font ID (family name for Google, slug for Fontshare)
|
||||
* @returns Promise resolving to font or undefined
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const roboto = await fetchProxyFontById('Roboto');
|
||||
* const satoshi = await fetchProxyFontById('satoshi');
|
||||
* ```
|
||||
*/
|
||||
export async function fetchProxyFontById(
|
||||
id: string,
|
||||
): Promise<UnifiedFont | undefined> {
|
||||
const response = await fetchProxyFonts({ limit: 1000, q: id });
|
||||
return response.fonts.find(font => font.id === id);
|
||||
}
|
||||
Reference in New Issue
Block a user