#!/usr/bin/env node
/**
* Mini CLI example for hyper-sync
*
* Usage:
* node examples/cli.js status [--repos <dir>]
* node examples/cli.js serve [name] [--repos <dir>]
* node examples/cli.js add-remote <name> <serverKey>
* node examples/cli.js pull <remote> [repo]
*/
const HyperSync = require('../index')
const args = process.argv.slice(2)
const cmd = args[0]
function getFlag (name) {
const i = args.indexOf('--' + name)
return i !== -1 && args[i + 1] ? args[i + 1] : null
}
function fmt (b) {
if (b < 1024) return b + ' B'
if (b < 1048576) return (b / 1024).toFixed(1) + ' KB'
return (b / 1048576).toFixed(1) + ' MB'
}
async function main () {
const repos = getFlag('repos')
const sync = new HyperSync(repos ? { repos } : {})
await sync.ready()
if (cmd === 'status') {
const s = sync.status()
console.log('Server key: %s', s.serverKey)
console.log('Repos: %d, Serving: %d, Remotes: %d\n', s.repoCount, s.serving, s.remotes)
if (s.repos.length === 0) {
console.log(' (no repos found)')
} else {
for (const r of s.repos) {
console.log(' %s %d branches %s %s',
r.name.padEnd(30), r.branches, fmt(r.packSize).padStart(8),
r.head ? r.head : '(empty)')
}
}
await sync.close()
} else if (cmd === 'serve') {
const name = args[1] && !args[1].startsWith('--') ? args[1] : null
sync.on('serve', (n, topic) => console.log(' %s → %s', n, topic.slice(0, 16) + '...'))
sync.on('connection', (peer, repo) => console.log('Peer %s connected (repo: %s)', peer, repo))
await sync.serve(name)
console.log('Serving %d repo(s). Server key: %s', sync.serving, sync.serverKey)
console.log('Ctrl+C to stop')
} else if (cmd === 'add-remote') {
const name = args[1]
const key = args[2]
if (!name || !key) {
console.error('Usage: cli.js add-remote <name> <serverKey>')
await sync.close()
process.exit(1)
}
sync.addRemote(name, key)
console.log('Added remote "%s" → %s', name, key.slice(0, 16) + '...')
// Note: remotes are in-memory only — a real app would persist them
console.log('(remote stored in memory — will not persist across restarts)')
await sync.close()
} else if (cmd === 'pull') {
const remoteName = args[1]
const repoName = args[2] && !args[2].startsWith('--') ? args[2] : null
if (!remoteName) {
console.error('Usage: cli.js pull <remote> [repo]')
await sync.close()
process.exit(1)
}
// For this example, accept serverKey directly as the remote name
// and auto-register it
if (remoteName.length === 64) {
sync.addRemote('remote', remoteName)
console.log('Auto-registered remote from key: %s...', remoteName.slice(0, 16))
}
const remote = remoteName.length === 64 ? 'remote' : remoteName
sync.on('pull', (r, name, state) => console.log(' %s/%s: %s', r, name, state))
try {
const result = await sync.pull(remote, repoName)
console.log('Synced: %d, Failed: %d, Elapsed: %dms',
result.synced.length, result.failed.length, result.elapsed)
if (result.failed.length) {
for (const f of result.failed) console.log(' FAIL: %s — %s', f.name, f.error)
}
} catch (err) {
console.error('Pull failed: %s', err.message)
}
await sync.close()
} else {
console.log('hyper-sync example CLI')
console.log(' status List repos')
console.log(' serve [name] Announce repos on DHT')
console.log(' add-remote <name> <key> Register a remote server')
console.log(' pull <remote|key> [repo] Fetch updates from remote')
console.log('')
console.log('Options:')
console.log(' --repos <dir> Git repos directory (default: ~/git-repos)')
await sync.close()
}
}
main().catch((err) => { console.error(err.message); process.exit(1) })