export type GameLibraryGame = 't5' | 't6'; export type GameLibraryState = 'importing' | 'ready' | 'failed'; export type LibraryCacheState = 'missing' | 'downloading' | 'verifying' | 'ready' | 'failed' | 'outdated'; export interface GameFileEntry { path: string; size: number; sha256: string } export interface HostLibraryCache { hostId: string; libraryVersionId: string; status: LibraryCacheState; bytesDownloaded: number; bytesTotal: number; manifestSha256: string | null; error: string | null; updatedAt: string; operationId: string | null; } export interface GameLibraryVersion { id: string; libraryId: string; game: GameLibraryGame; version: string; description: string; state: GameLibraryState; sizeBytes: number; fileCount: number; manifestSha256: string | null; files: GameFileEntry[]; createdAt: string; publishedAt: string | null; storageLocation: string; sourceHostId: string | null; sourceVolume: string | null; error: string | null; operationId: string | null; caches: HostLibraryCache[]; } export interface GameLibrary { id: string; name: string; game: GameLibraryGame; description: string; createdAt: string; versions: GameLibraryVersion[]; } export function formatGameBytes(bytes: number): string { if (!bytes) return '0 B'; const unit = Math.min(4, Math.floor(Math.log(bytes) / Math.log(1024))); return `${(bytes / 1024 ** unit).toFixed(unit ? 1 : 0)} ${['B', 'KiB', 'MiB', 'GiB', 'TiB'][unit]}`; }