export type GameLibraryGame = 't5' | 't6'; export const GAME_FILE_GAMES = [ { id: 't5', name: 'Black Ops I (T5)' }, { id: 't6', name: 'Black Ops II (T6)' } ] as const; 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 LibraryTransferProgress { phase: 'downloading' | 'verifying'; startedAt: string; elapsedSeconds: number; phaseElapsedSeconds: number; bytesPerSecond: number | null; etaSeconds: number | null; } export interface HostLibraryCache { hostId: string; libraryVersionId: string; status: LibraryCacheState; bytesDownloaded: number; bytesTotal: number; manifestSha256: string | null; error: string | null; updatedAt: string; operationId: string | null; bytesVerified?: number; transfer?: LibraryTransferProgress; } 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[]; filesRemoved?: boolean; filesRemoving?: boolean; } export interface GameLibrary { id: string; name: string; game: GameLibraryGame; description: string; createdAt: string; latestVersionId: string | null; 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]}`; }