One-click backups for AT Protocol
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}