/** * ───────────────────────────────────────────── * SPB Git — Personal Git Platform * ───────────────────────────────────────────── * Author : Simon-Pierre Boucher * Contact : contact@spboucher.ai * File : cli/commands/list.mjs * Purpose : `spbgit list` — table of server repositories * License : MIT © Simon-Pierre Boucher * ───────────────────────────────────────────── */ import pc from 'picocolors'; import { requireCliConfig } from '../lib/config.mjs'; import { api } from '../lib/api.mjs'; import { printTable } from '../lib/ui.mjs'; /** Compact "3 h ago" style formatter (client-side). */ export function ago(iso) { if (!iso) return pc.dim('never'); const s = Math.floor((Date.now() - new Date(iso).getTime()) / 1000); if (s < 90) return 'just now'; if (s < 3600) return `${Math.floor(s / 60)} min ago`; if (s < 86400) return `${Math.floor(s / 3600)} h ago`; if (s < 2592000) return `${Math.floor(s / 86400)} d ago`; return `${Math.floor(s / 2592000)} mo ago`; } export function registerList(program) { program .command('list') .alias('ls') .description('list every repository on the server') .option('--json', 'machine-readable output') .action(async (opts) => { const config = requireCliConfig(); const { repos } = await api(config, 'GET', '/api/v1/repos', undefined, { auth: false }); if (opts.json) { console.log(JSON.stringify(repos, null, 2)); return; } if (repos.length === 0) { console.log(pc.dim('No repositories yet. Create one: spbgit create ')); return; } printTable([ [pc.bold('NAME'), pc.bold('DESCRIPTION'), pc.bold('LANGUAGE'), pc.bold('PUSHED'), pc.bold('CLONE URL')], ...repos.map((r) => [ (r.pinned ? pc.yellow('★ ') : ' ') + pc.bold(r.name), (r.description || pc.dim('—')).slice(0, 48), r.topLanguage ?? pc.dim('—'), ago(r.lastPush), pc.dim(r.cloneUrl), ]), ]); }); }