Ctrl K
ComunidadGuías…

src/services/project-meta.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// Star count for the top bar's GitHub chip. GitHub allows 60 unauthenticated API calls an hour
// per address, so one wizard session that opens many pages, or several sessions, could use them up
// and the chip showed "?". Keep a good count for 15 minutes, share one request between pages that
// load together, ask Relmio's website (which caches the same count) when GitHub refuses, and keep
// the last good count when both fail.

const GITHUB_URL = "https://api.github.com/repos/Demonbane18/relmio";
const WEBSITE_URL = "https://relmio.jpfusin.tech/api/project-meta";
export const PROJECT_META_TTL_MS = 15 * 60_000;
const TIMEOUT_MS = 5_000;
// After both sources fail, answer from the last count for a minute instead of waiting on them again.
export const PROJECT_META_RETRY_MS = 60_000;

const validStars = (value) => (Number.isSafeInteger(value) && value >= 0 ? value : null);

async function readStars(fetchImpl, url, headers, pick) {
  try {
    const response = await fetchImpl(url, { headers, redirect: "error", signal: AbortSignal.timeout(TIMEOUT_MS) });
    return response.ok ? validStars(pick(await response.json())) : null;
  } catch {
    return null;
  }
}

export function createProjectMetaReader({ version, fetchImpl = fetch, now = Date.now } = {}) {
  const headers = { "User-Agent": `relmio/${version}` };
  let cached = null;
  let pending = null;
  let retryAt = 0;

  async function refresh() {
    const stars = await readStars(fetchImpl, GITHUB_URL, { ...headers, Accept: "application/vnd.github+json" },
      (body) => body?.stargazers_count)
      ?? await readStars(fetchImpl, WEBSITE_URL, { ...headers, Accept: "application/json" }, (body) => body?.stars);
    if (stars !== null) cached = { stars, at: now() };
    else retryAt = now() + PROJECT_META_RETRY_MS;
    return cached?.stars ?? null;
  }

  return async function getProjectMeta() {
    const at = now();
    if ((cached && at - cached.at < PROJECT_META_TTL_MS) || at < retryAt) return { stars: cached?.stars ?? null, version };
    pending ??= refresh().finally(() => { pending = null; });
    return { stars: await pending, version };
  };
}