OverviewFilesCommitsIssuesDocsReleasesPeers

pear-git / lib / cli / commands / serve.js

119 lines · javascript ref:
/**
 * pgh serve commands
 *
 * Subcommands: status, p2p, restart, shutdown
 */

import { jsonOut, log, error } from '../output.js'

export async function serveCommand (client, sub, args, flags) {
  switch (sub) {
    case 'status':
    case undefined:
      return serveStatus(client, flags)
    case 'p2p':
      return serveP2P(client, flags)
    case 'restart':
      return serveRestart(client, flags)
    case 'shutdown':
      return serveShutdown(client, flags)
    default:
      serveHelp()
  }
}

async function serveStatus (client, flags) {
  const data = await client.get('/api/admin/stats')

  if (flags.json) {
    jsonOut(data)
    return
  }

  const mem = data.server.memory
  const rss = (mem.rss / 1024 / 1024).toFixed(1)
  const heap = (mem.heapUsed / 1024 / 1024).toFixed(1)

  log(`Uptime:       ${formatUptime(data.server.uptime)}`)
  log(`Memory:       ${rss} MB RSS, ${heap} MB heap`)
  log(`Repos:        ${data.server.repos}`)
  log(`Users:        ${data.registry.users}`)
  log(`Identities:   ${data.registry.identities}`)
  log(`Challenges:   ${data.challenges.active || 0} active`)
  log(`Rate limits:  ${data.rateLimiter.cached} cached`)
}

async function serveP2P (client, flags) {
  const data = await client.get('/api/p2p/info')

  if (flags.json) {
    jsonOut(data)
    return
  }

  if (!data.enabled) {
    log('P2P is not enabled on this server.')
    return
  }

  log(`Server key:   ${data.serverKey}`)
  log(`Short key:    ${data.shortKey}`)
  log(`Connections:  ${data.connections}`)
  log(`Repos:`)
  for (const repo of data.repos) {
    log(`  ${repo.name}`)
    if (repo.cloneUrl) log(`    Clone:  ${repo.cloneUrl}`)
    if (repo.punchUrl) log(`    Punch:  ${repo.punchUrl}`)
    else if (repo.pearUrl) log(`    Punch:  ${repo.pearUrl}`)
  }
}

async function serveRestart (client, flags) {
  const data = await client.post('/api/admin/restart', { delay: 500 })

  if (flags.json) {
    jsonOut(data)
    return
  }

  const mode = data.mode || 'unknown'
  log(`Restarting server (${mode})...`)
}

async function serveShutdown (client, flags) {
  const data = await client.post('/api/admin/shutdown', { delay: 1000 })

  if (flags.json) {
    jsonOut(data)
    return
  }

  log('Shutting down server...')
}

function formatUptime (seconds) {
  const d = Math.floor(seconds / 86400)
  const h = Math.floor((seconds % 86400) / 3600)
  const m = Math.floor((seconds % 3600) / 60)
  const s = Math.floor(seconds % 60)
  const parts = []
  if (d > 0) parts.push(`${d}d`)
  if (h > 0) parts.push(`${h}h`)
  if (m > 0) parts.push(`${m}m`)
  parts.push(`${s}s`)
  return parts.join(' ')
}

export function serveHelp () {
  log(`Usage: pgh serve <subcommand> [flags]

Subcommands:
  status               Server uptime, memory, repos, users
  p2p                  P2P info (server key, repos, connections)
  restart              Restart the server
  shutdown             Shutdown the server

Flags:
  --json               Output as JSON`)
}