Monorepo for wisp.place. A static site hosting service built on top of the AT Protocol. wisp.place
1import type { Directory } from "@wisp/lexicons/types/place/wisp/fs"; 2 3/** 4 * Estimate the JSON size of a directory tree 5 */ 6export function estimateDirectorySize(directory: Directory): number { 7 return JSON.stringify(directory).length; 8} 9 10/** 11 * Count files in a directory tree 12 */ 13export function countFilesInDirectory(directory: Directory): number { 14 let count = 0; 15 for (const entry of directory.entries) { 16 if ('type' in entry.node && entry.node.type === 'file') { 17 count++; 18 } else if ('type' in entry.node && entry.node.type === 'directory') { 19 count += countFilesInDirectory(entry.node as Directory); 20 } 21 } 22 return count; 23} 24 25/** 26 * Find all directories in a tree with their paths and sizes 27 */ 28export function findLargeDirectories(directory: Directory, currentPath: string = ''): Array<{ 29 path: string; 30 directory: Directory; 31 size: number; 32 fileCount: number; 33}> { 34 const result: Array<{ path: string; directory: Directory; size: number; fileCount: number }> = []; 35 36 for (const entry of directory.entries) { 37 if ('type' in entry.node && entry.node.type === 'directory') { 38 const dirPath = currentPath ? `${currentPath}/${entry.name}` : entry.name; 39 const dir = entry.node as Directory; 40 const size = estimateDirectorySize(dir); 41 const fileCount = countFilesInDirectory(dir); 42 43 result.push({ path: dirPath, directory: dir, size, fileCount }); 44 45 // Recursively find subdirectories 46 const subdirs = findLargeDirectories(dir, dirPath); 47 result.push(...subdirs); 48 } 49 } 50 51 return result; 52} 53 54/** 55 * Replace a directory with a subfs node in the tree 56 */ 57export function replaceDirectoryWithSubfs( 58 directory: Directory, 59 targetPath: string, 60 subfsUri: string 61): Directory { 62 const pathParts = targetPath.split('/'); 63 const targetName = pathParts[pathParts.length - 1]; 64 const parentPath = pathParts.slice(0, -1).join('/'); 65 66 // If this is a root-level directory 67 if (pathParts.length === 1) { 68 const newEntries = directory.entries.map(entry => { 69 if (entry.name === targetName && 'type' in entry.node && entry.node.type === 'directory') { 70 return { 71 name: entry.name, 72 node: { 73 $type: 'place.wisp.fs#subfs' as const, 74 type: 'subfs' as const, 75 subject: subfsUri, 76 flat: false // Preserve directory structure 77 } 78 }; 79 } 80 return entry; 81 }); 82 83 return { 84 $type: 'place.wisp.fs#directory' as const, 85 type: 'directory' as const, 86 entries: newEntries 87 }; 88 } 89 90 // Recursively navigate to parent directory 91 const newEntries = directory.entries.map(entry => { 92 if ('type' in entry.node && entry.node.type === 'directory') { 93 const entryPath = entry.name; 94 if (parentPath.startsWith(entryPath) || parentPath === entry.name) { 95 const remainingPath = pathParts.slice(1).join('/'); 96 return { 97 name: entry.name, 98 node: { 99 ...replaceDirectoryWithSubfs(entry.node as Directory, remainingPath, subfsUri), 100 $type: 'place.wisp.fs#directory' as const 101 } 102 }; 103 } 104 } 105 return entry; 106 }); 107 108 return { 109 $type: 'place.wisp.fs#directory' as const, 110 type: 'directory' as const, 111 entries: newEntries 112 }; 113}