import { execSync } from 'child_process'
import { existsSync, readdirSync, statSync } from 'fs'
import { join } from 'path'
// Known Hypercore storage locations under a home directory
const KNOWN_PATHS = [
'.config/pear/corestores',
'.config/pear/app-storage',
'.config/pear/by-dkey',
'.config/Holepunch',
'.config/hypernote',
'.config/keet-cli',
'.config/keet-daemon',
'.config/godot-keet',
'.config/hyper-tps',
'.config/agregore-browser/hyper',
'.config/Beaker Browser',
'.config/manyverse',
'.config/holepunch-runtime',
'.config/pear-runtime',
'.config/hyper-social-web'
]
export function findCorestores (homeDir) {
const results = []
// Check known paths
for (const rel of KNOWN_PATHS) {
const full = join(homeDir, rel)
if (existsSync(full)) {
const size = getDirSize(full)
results.push({ path: full, size, type: 'known', rel })
}
}
// Find CORESTORE marker files
try {
const output = execSync(
`find ${homeDir} -maxdepth 5 -name "CORESTORE" -type f 2>/dev/null`,
{ encoding: 'utf8', timeout: 30000 }
)
for (const line of output.trim().split('\n').filter(Boolean)) {
const dir = line.replace(/\/CORESTORE$/, '')
// Check if already covered by known paths
const isKnown = results.some(r => dir.startsWith(r.path))
if (!isKnown) {
const size = getDirSize(dir)
results.push({ path: dir, size, type: 'discovered', marker: line })
}
}
} catch {}
// Sort by size descending
results.sort((a, b) => b.size - a.size)
return results
}
export function getDirSize (dirPath) {
try {
const output = execSync(`du -sb "${dirPath}" 2>/dev/null`, { encoding: 'utf8', timeout: 30000 })
return parseInt(output.split('\t')[0]) || 0
} catch {
return 0
}
}
export function getLastModified (dirPath) {
try {
const stat = statSync(dirPath)
return stat.mtime
} catch {
return null
}
}
export function isLocked (dbPath) {
try {
const lockFile = join(dbPath, 'LOCK')
if (!existsSync(lockFile)) return false
const output = execSync(`lsof "${lockFile}" 2>/dev/null`, { encoding: 'utf8', timeout: 5000 })
return output.trim().length > 0
} catch {
return false
}
}
export function getLockHolder (dbPath) {
try {
const lockFile = join(dbPath, 'LOCK')
const output = execSync(`lsof "${lockFile}" 2>/dev/null`, { encoding: 'utf8', timeout: 5000 })
const lines = output.trim().split('\n')
if (lines.length > 1) {
const parts = lines[1].split(/\s+/)
return { command: parts[0], pid: parts[1] }
}
} catch {}
return null
}
export function hasRocksDB (dirPath) {
const dbPath = join(dirPath, 'db')
if (existsSync(dbPath)) {
try {
const files = readdirSync(dbPath)
return files.some(f => f.endsWith('.sst') || f.endsWith('.blob'))
} catch {}
}
return false
}