One-click backups for AT Protocol
at main 60 lines 1.5 kB view raw
1import { RepoReader } from "@atcute/car/v4"; 2 3export interface CarStats { 4 totalBlocks: number; 5 totalSize: number; 6 recordCount: number; 7 recordTypes: Record<string, number>; 8 fileSize: number; 9 collections: string[]; 10 createdAt: string; 11} 12 13export async function getCarStats(carData: Uint8Array): Promise<CarStats> { 14 try { 15 // Parse the CAR file 16 const repo = RepoReader.fromUint8Array(carData); 17 18 let totalBlocks = 0; 19 let totalSize = 0; 20 let recordCount = 0; 21 const recordTypes: Record<string, number> = {}; 22 const collections = new Set<string>(); 23 24 // Iterate through all blocks in the CAR file 25 for await (const record of repo) { 26 totalBlocks++; 27 28 try { 29 // Try to decode the block as a record 30 if (record) { 31 // Count different record types 32 const type = (record.record as any)["$type"]; 33 if (type) { 34 recordTypes[type] = (recordTypes[type] || 0) + 1; 35 recordCount++; 36 37 // Extract collection name 38 collections.add(type); 39 } 40 } 41 } catch (e) { 42 // Not all blocks are records, some are structural 43 continue; 44 } 45 } 46 47 return { 48 totalBlocks, 49 totalSize, 50 recordCount, 51 recordTypes, 52 fileSize: carData.length, 53 collections: Array.from(collections), 54 createdAt: new Date().toISOString(), 55 }; 56 } catch (error) { 57 console.error("Error parsing CAR file:", error); 58 throw new Error(`Failed to parse CAR file: ${error}`); 59 } 60}