spb/spbgit Public MIT
SPB Git — the platform hosting itself
JavaScript 73.9%
CSS 11.7%
Nunjucks 11.6%
Shell 2.7%
1/**2 * ─────────────────────────────────────────────3 * SPB Git — Personal Git Platform4 * ─────────────────────────────────────────────5 * Author : Simon-Pierre Boucher6 * Contact : contact@spboucher.ai7 * File : cli/lib/api.mjs8 * Purpose : SPB Git API client (native fetch, friendly errors)9 * License : MIT © Simon-Pierre Boucher10 * ─────────────────────────────────────────────11 */1213import pc from 'picocolors';1415/** Exit codes per CLAUDE.md §6.3. */16export const EXIT = Object.freeze({ OK: 0, USER: 1, NETWORK: 2, PARTIAL: 3 });1718/**19 * Perform an API request against the configured server.20 * @param {object} config CLI config21 * @param {string} method22 * @param {string} path e.g. `/api/v1/repos`23 * @param {object} [body]24 * @param {{auth?: boolean}} [opts]25 * @returns {Promise<any>} parsed JSON26 */27export async function api(config, method, path, body, opts = {}) {28 const headers = { Accept: 'application/json' };29 if (opts.auth !== false && config.token) headers.Authorization = `Bearer ${config.token}`;30 if (body !== undefined) headers['Content-Type'] = 'application/json';31 let response;32 try {33 response = await fetch(`${config.server.replace(/\/+$/, '')}${path}`, {34 method,35 headers,36 body: body === undefined ? undefined : JSON.stringify(body),37 });38 } catch (err) {39 console.error(pc.red(`✗ Cannot reach ${config.server} — ${err.cause?.code ?? err.message}`));40 console.error(' Check the server URL in ~/.spbgit/config.json or run: spbgit doctor');41 process.exit(EXIT.NETWORK);42 }43 const text = await response.text();44 let json = null;45 try {46 json = text ? JSON.parse(text) : null;47 } catch {48 /* non-JSON error body */49 }50 if (!response.ok) {51 if (response.status === 401) {52 console.error(pc.red('✗ Token invalid or revoked.'));53 console.error(' Run `spbgit token new` on a machine with a valid token, then `spbgit init`.');54 process.exit(EXIT.NETWORK);55 }56 const message = json?.error?.message ?? `HTTP ${response.status}`;57 const error = new Error(message);58 error.status = response.status;59 error.code = json?.error?.code;60 throw error;61 }62 return json;63}64