Return

All tests / src/pages/api github-stars.ts

100% Statements 14/14
100% Branches 0/0
100% Functions 1/1
100% Lines 13/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53  1x 1x 1x     1x   1x                                   5x 5x 5x 3x           3x                       2x 2x 2x      
import { NextApiRequest, NextApiResponse } from 'next';
import { Octokit } from 'octokit';
import allowCors from '../../helpers/cors';
import { CACHE } from '@/helpers/http';
import type { GithubStarsData } from '../../types/schemas';
 
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
 
const REPOSITORY = {
    owner: 'xabierlameiro',
    repo: 'the-last-dance',
};
 
/**
 * @description This function is used to get the total number of stars for a given repository. It uses the GitHub REST
 * API to get the data.
 *
 * @param {NextApiRequest} req
 * @param {NextApiResponse} res
 * @returns {Promise<{
 *     error?: string;
 *     total?: number;
 * }>}
 */
type GitHubStarsResponse = GithubStarsData | { statusCode: number; message: string };
 
export default allowCors(async function handler(_req: NextApiRequest, res: NextApiResponse<GitHubStarsResponse>) {
    try {
        const { data } = await octokit.rest.repos.get(REPOSITORY);
        res.setHeader('Cache-Control', CACHE.slow);
        /**
         * Only the five fields the UI reads. Forwarding Octokit's whole payload would ship the
         * owner's account object and every URL template to the client for no reason, and would
         * make the response shape GitHub's to change rather than ours.
         */
        res.status(200).json({
            stars: data.stargazers_count,
            forks: data.forks_count,
            watchers: data.subscribers_count,
            issues: data.open_issues_count,
            pushedAt: data.pushed_at,
        });
    } catch (err: unknown) {
        // Was forwarding Octokit's raw message. Under rate limiting GitHub answers "API rate limit
        // exceeded for user ID 12345", disclosing the owner's numeric account id; on a revoked token
        // it answers "Bad credentials", which is a live oracle for when the PAT was rotated or broke.
        // Log the detail, return a flat message like the other seven routes.
        console.error('GitHub stars API Error:', err);
        res.setHeader('Cache-Control', CACHE.error);
        res.status(500).json({ statusCode: 500, message: 'Internal server error' });
    }
});