/** * MediaAdapter * * Handles HTTP operations for media assets. * This is where external API calls belong. */ import { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl'; import { Result } from '@/lib/contracts/Result'; import { DomainError } from '@/lib/contracts/services/Service'; import { MediaBinaryDTO } from '@/lib/types/MediaBinaryDTO'; // TODO why is this an adapter? /** * MediaAdapter * * Handles binary media fetching from the API. * All HTTP calls are isolated here. */ export class MediaAdapter { private baseUrl: string; constructor() { this.baseUrl = getWebsiteApiBaseUrl(); } /** * Fetch binary media from API * * @param mediaPath - API path to media resource * @returns Result with MediaBinaryDTO on success, DomainError on failure */ async fetchMedia(mediaPath: string): Promise> { try { const response = await fetch(`${this.baseUrl}${mediaPath}`, { method: 'GET', }); if (!response.ok) { if (response.status === 404) { return Result.err({ type: 'notFound', message: `Media not found: ${mediaPath}` }); } return Result.err({ type: 'serverError', message: `HTTP ${response.status}: ${response.statusText}` }); } const buffer = await response.arrayBuffer(); const contentType = response.headers.get('content-type') || 'image/svg+xml'; return Result.ok({ buffer, contentType }); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; return Result.err({ type: 'networkError', message: `Failed to fetch media: ${errorMessage}` }); } } }