#!/usr/bin/env node
/**
* Mini CLI example for hyper-deploy
*
* Usage:
* node examples/cli.js serve <dir> [--topic <hex>]
* node examples/cli.js pull <topic> [dest]
* node examples/cli.js info <topic>
*/
import { DeployServer, DeployClient } from '../index.js'
function fmt (b) {
if (b < 1024) return b + ' B'
if (b < 1048576) return (b / 1024).toFixed(1) + ' KB'
if (b < 1073741824) return (b / 1048576).toFixed(1) + ' MB'
return (b / 1073741824).toFixed(2) + ' GB'
}
const args = process.argv.slice(2)
const cmd = args[0]
if (cmd === 'serve') {
const dir = args[1]
if (!dir) { console.error('Usage: cli.js serve <dir>'); process.exit(1) }
let topic
const ti = args.indexOf('--topic')
if (ti !== -1 && args[ti + 1]) topic = Buffer.from(args[ti + 1], 'hex')
const server = new DeployServer(dir, { topic })
server.on('indexed', (count, size) => {
console.log('Indexed: %d files, %s', count, fmt(size))
})
server.on('ready', () => {
console.log('Topic: %s', server.topicHex)
console.log('Pull: node examples/cli.js pull %s ./dest', server.topicHex)
console.log('Waiting for peers...')
})
server.on('peer', ({ key, state }) => console.log('Peer %s: %s', key, state))
server.on('progress', (p) => {
if (p.file) console.log(' sent %s (%d files, %s)', p.file, p.filesServed, fmt(p.bytesServed))
})
server.ready().catch((err) => { console.error(err.message); process.exit(1) })
} else if (cmd === 'pull') {
const topicHex = args[1]
const dest = args[2] || './deploy-output'
if (!topicHex || topicHex.length !== 64) {
console.error('Usage: cli.js pull <64-char-hex> [dest]')
process.exit(1)
}
const client = new DeployClient(topicHex, dest)
const t0 = Date.now()
client.on('connected', (key) => console.log('Connected: %s (%dms)', key, Date.now() - t0))
client.on('manifest', (n) => console.log('Manifest: %d files', n))
client.on('diff', (needed, skipped) => console.log('Need: %d, skip: %d', needed, skipped))
client.on('up-to-date', () => console.log('Up to date'))
client.on('progress', (p) => {
const total = p.filesTransferred + p.filesSkipped
if (p.filesTransferred % 100 === 0 || total === p.totalFiles) {
console.log(' %d/%d transferred, %s', p.filesTransferred, p.totalFiles, fmt(p.bytesReceived))
}
})
client.ready()
.then(() => client.pull())
.then((stats) => {
const speed = stats.bytesReceived > 0 ? (stats.bytesReceived / stats.elapsed * 1000 / 1024 / 1024).toFixed(1) : '0'
console.log('Done: %d files, %s, %ss (%s MB/s)',
stats.filesTransferred, fmt(stats.bytesReceived),
(stats.elapsed / 1000).toFixed(1), speed)
if (stats.errors.length) console.log('Errors:', stats.errors)
return client.close()
})
.then(() => process.exit(0))
.catch((err) => { console.error(err.message); process.exit(1) })
} else if (cmd === 'info') {
const topicHex = args[1]
if (!topicHex || topicHex.length !== 64) {
console.error('Usage: cli.js info <64-char-hex>')
process.exit(1)
}
const client = new DeployClient(topicHex, '/tmp/hyper-deploy-info', { timeout: 15000 })
client.on('connected', (key) => console.log('Connected: %s', key))
client.on('manifest', (n) => console.log('Files: %d', n))
client.on('diff', (needed, skipped) => {
console.log('Would transfer: %d, already local: %d', needed, skipped)
client.close().then(() => process.exit(0))
})
client.ready()
.then(() => client.pull())
.catch((err) => {
if (!err.message.includes('closed during pull')) {
console.error(err.message)
process.exit(1)
}
})
} else {
console.log('hyper-deploy example CLI')
console.log(' serve <dir> [--topic <hex>] Serve a directory')
console.log(' pull <topic> [dest] Pull files from server')
console.log(' info <topic> Show remote manifest')
}