SPB Git

spb/spbgit Public MIT

SPB Git — the platform hosting itself

JavaScript 73.9% CSS 11.7% Nunjucks 11.6% Shell 2.7%
2.2 KB · 58 lines javascript
Raw Blame History
1/**2 * ─────────────────────────────────────────────3 *  SPB Git — Personal Git Platform4 * ─────────────────────────────────────────────5 *  Author  : Simon-Pierre Boucher6 *  Contact : contact@spboucher.ai7 *  File    : cli/commands/list.mjs8 *  Purpose : `spbgit list` — table of server repositories9 *  License : MIT © Simon-Pierre Boucher10 * ─────────────────────────────────────────────11 */1213import pc from 'picocolors';14import { requireCliConfig } from '../lib/config.mjs';15import { api } from '../lib/api.mjs';16import { printTable } from '../lib/ui.mjs';1718/** Compact "3 h ago" style formatter (client-side). */19export function ago(iso) {20  if (!iso) return pc.dim('never');21  const s = Math.floor((Date.now() - new Date(iso).getTime()) / 1000);22  if (s < 90) return 'just now';23  if (s < 3600) return `${Math.floor(s / 60)} min ago`;24  if (s < 86400) return `${Math.floor(s / 3600)} h ago`;25  if (s < 2592000) return `${Math.floor(s / 86400)} d ago`;26  return `${Math.floor(s / 2592000)} mo ago`;27}2829export function registerList(program) {30  program31    .command('list')32    .alias('ls')33    .description('list every repository on the server')34    .option('--json', 'machine-readable output')35    .action(async (opts) => {36      const config = requireCliConfig();37      const { repos } = await api(config, 'GET', '/api/v1/repos', undefined, { auth: false });38      if (opts.json) {39        console.log(JSON.stringify(repos, null, 2));40        return;41      }42      if (repos.length === 0) {43        console.log(pc.dim('No repositories yet. Create one: spbgit create <name>'));44        return;45      }46      printTable([47        [pc.bold('NAME'), pc.bold('DESCRIPTION'), pc.bold('LANGUAGE'), pc.bold('PUSHED'), pc.bold('CLONE URL')],48        ...repos.map((r) => [49          (r.pinned ? pc.yellow('★ ') : '  ') + pc.bold(r.name),50          (r.description || pc.dim('—')).slice(0, 48),51          r.topLanguage ?? pc.dim('—'),52          ago(r.lastPush),53          pc.dim(r.cloneUrl),54        ]),55      ]);56    });57}58