UNPKG

gh-star-fetch

Version:

Fetch all the starred repositories for a GitHub user

150 lines (149 loc) 4.88 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.setHttpClient = exports.compactByTopic = exports.compactByLanguage = exports.getNextPage = void 0; const parse_link_header_1 = __importDefault(require("parse-link-header")); const client_1 = require("./client"); function getNextPage({ next, last }) { if (!next?.page || !last?.page) return null; if (next.page === last.page) return null; return next.page; } exports.getNextPage = getNextPage; async function* paginateStars(url, opts) { let nextPage = '1'; while (nextPage) { try { const { headers, body } = await opts.http.get(url, { searchParams: { per_page: 100, page: nextPage, }, }); for (const record of body) { yield record; } const links = (0, parse_link_header_1.default)(headers.link); if (!links) return; // exit if no page nextPage = getNextPage(links); if (!opts.accessToken) { console.warn('No github access token provided, limiting call to first page to avoid rate limit ban'); break; } } catch (e) { console.error('[http-error]:', e?.response?.body || e); break; } } } function compactByLanguage(data, _transform = transform) { return data.reduce((acc, val) => { const language = val.language || 'miscellaneous'; acc[language] ||= []; const parsed = typeof _transform !== 'function' ? val : _transform(val); acc[language].push(parsed); return acc; }, {}); } exports.compactByLanguage = compactByLanguage; function compactByTopic(data, _transform = transform) { return data.reduce((acc, val) => { if (!Array.isArray(val.topics)) return acc; const topics = val.topics.length === 0 ? ['miscellaneous'] : val.topics; for (const topic of topics) { if (!Array.isArray(acc[topic])) acc[topic] = []; const parsed = typeof _transform !== 'function' ? val : _transform(val); acc[topic].push(parsed); } return acc; }, {}); } exports.compactByTopic = compactByTopic; async function apiGetStar(opts) { const data = []; const API_STARRED_URL = `users/${opts.username}/starred`; for await (const star of paginateStars(API_STARRED_URL, opts)) { data.push(star); } if (opts.compactByLanguage) { return compactByLanguage(data, opts.transform); } if (opts.compactByTopic) { return compactByTopic(data, opts.transform); } if (typeof opts.transform !== 'function') return data; return data.map((star) => opts.transform(star)); } function transform(star) { return { id: star.id, node_id: star.node_id, name: star.name, full_name: star.full_name, owner: { login: star?.owner?.login, id: star?.owner?.id, avatar_url: star?.owner?.avatar_url, url: star?.owner?.url, html_url: star?.owner?.html_url, }, html_url: star.html_url, description: star.description, url: star.url, languages_url: star.languages_url, created_at: star.created_at, updated_at: star.updated_at, git_url: star.git_url, ssh_url: star.ssh_url, clone_url: star.clone_url, homepage: star.homepage, stargazers_count: star.stargazers_count, watchers_count: star.watchers_count, language: star.language, topics: star.topics, }; } const DEFAULT_OPTIONS = { accessToken: process.env.GITHUB_TOKEN, username: process.env.GITHUB_USERNAME, compactByLanguage: false, compactByTopic: false, transform, }; function setHttpClient(opts) { // http is provided in opts in test cases env if (opts.http) return opts.http; const headers = {}; if (opts.accessToken) { headers.Authorization = `token ${opts.accessToken}`; } return (0, client_1.createClient)({ headers }); } exports.setHttpClient = setHttpClient; async function main(options) { const http = setHttpClient(options); const opts = Object.assign({}, DEFAULT_OPTIONS, options, { http, }); if (!opts.username) { try { const { login } = await http.get('user').json(); opts.username = login; } catch { throw new Error('[options.username] is not set'); } } return apiGetStar(opts); } exports.default = main;