web based infinite canvas
at main 61 lines 1.7 kB view raw
1import type { Timestamp } from "./repo"; 2 3export type BoardStats = { 4 pageCount: number; 5 shapeCount: number; 6 bindingCount: number; 7 docSizeBytes: number; 8 lastUpdated: Timestamp; 9}; 10 11export type SchemaInfo = { declaredVersion: number; installedVersion: number }; 12 13export type MigrationInfo = { id: string; appliedAt: Timestamp }; 14 15export type BoardInspectorData = { 16 stats: BoardStats; 17 schema: SchemaInfo; 18 migrations: MigrationInfo[]; 19 pendingMigrations: string[]; 20}; 21 22/** 23 * Calculate board statistics from row counts and doc size. 24 */ 25export const BoardStatsOps = { 26 create( 27 options: { 28 pageCount: number; 29 shapeCount: number; 30 bindingCount: number; 31 docSizeBytes: number; 32 lastUpdated: Timestamp; 33 }, 34 ): BoardStats { 35 return { 36 pageCount: options.pageCount, 37 shapeCount: options.shapeCount, 38 bindingCount: options.bindingCount, 39 docSizeBytes: options.docSizeBytes, 40 lastUpdated: options.lastUpdated, 41 }; 42 }, 43 44 /** 45 * Format doc size in human-readable format (e.g., "1.2 KB", "3.4 MB") 46 */ 47 formatDocSize(bytes: number): string { 48 if (bytes === 0) return "0 B"; 49 if (bytes < 1024) return `${bytes} B`; 50 if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; 51 return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; 52 }, 53}; 54 55/** 56 * Determine pending migrations by comparing known migration list with applied migrations. 57 */ 58export function getPendingMigrations(knownMigrationIds: string[], appliedMigrations: MigrationInfo[]): string[] { 59 const appliedIds = new Set(appliedMigrations.map((m) => m.id)); 60 return knownMigrationIds.filter((id) => !appliedIds.has(id)); 61}