Skip to content

T080 Fetch GitHub Repositories

In this assignment, you’ll work with asynchronous operations in TypeScript using the Fetch API. Your task is to retrieve and display repository information from a GitHub user profile.

Setup

  1. Create a new TypeScript file

Understanding the GitHub API

The GitHub API provides a simple way to retrieve public information about users and their repositories. For this exercise, you’ll use the endpoint:

https://api.github.com/users/{username}/repos

This endpoint returns a JSON array of repository objects, each containing information like name, description, stars, etc.

Creating the Repository Interface

  1. Define an interface named GitHubRepo with the following properties:
  2. name: string
  3. description: string or null
  4. html_url: string
  5. stargazers_count: number
  6. language: string or null

Fetching and Displaying Repositories

  1. Create an async function named fetchUserRepos that:
  2. Accepts a username as a parameter (string)
  3. Uses the Fetch API to retrieve repositories from https://api.github.com/users/${username}/repos
  4. Returns a Promise that resolves to an array of GitHubRepo objects
  5. Includes proper error handling

  6. Create a function named displayRepos that:

  7. Accepts an array of GitHubRepo objects
  8. Prints each repository’s name, description, stars, and language in a readable format
  9. Handles cases where description or language might be null

  10. Create a main function that:

  11. Calls fetchUserRepos with the username “microsoft”
  12. Displays the repositories using displayRepos
  13. Handles any errors that might occur

  14. Test your implementation by running the main function

Bonus Challenge

  • Add sorting functionality to display repositories by star count (highest first)
  • Add filtering to show only repositories written in a specific language
  • Display the total number of repositories and the total number of stars
Solution
interface GitHubRepo {
    name: string;
    description: string | null;
    html_url: string;
    stargazers_count: number;
    language: string | null;
}

async function fetchUserRepos(username: string): Promise<GitHubRepo[]> {
    try {
        const response = await fetch(`https://api.github.com/users/${username}/repos`);

        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }

        const repos: GitHubRepo[] = await response.json();
        return repos;
    } catch (error) {
        console.error('Error fetching repositories:', error);
        throw error;
    }
}

function displayRepos(repos: GitHubRepo[]): void {
    console.log(`\nFound ${repos.length} repositories:\n`);
    console.log('='.repeat(80));

    repos.forEach((repo, index) => {
        console.log(`\n${index + 1}. ${repo.name}`);
        console.log(`   Description: ${repo.description || 'No description'}`);
        console.log(`   Language: ${repo.language || 'Not specified'}`);
        console.log(`   Stars: ${repo.stargazers_count}`);
        console.log(`   URL: ${repo.html_url}`);
    });

    console.log('\n' + '='.repeat(80));
}

async function main() {
    try {
        const repos = await fetchUserRepos('microsoft');
        displayRepos(repos);

        // Bonus: Statistics
        const totalStars = repos.reduce((sum, repo) => sum + repo.stargazers_count, 0);
        console.log(`\nTotal repositories: ${repos.length}`);
        console.log(`Total stars: ${totalStars}`);
    } catch (error) {
        console.error('Failed to fetch and display repositories:', error);
    }
}

// Run the main function
main();

Bonus Solution

// Sort by stars (highest first)
function sortByStars(repos: GitHubRepo[]): GitHubRepo[] {
    return repos.sort((a, b) => b.stargazers_count - a.stargazers_count);
}

// Filter by language
function filterByLanguage(repos: GitHubRepo[], language: string): GitHubRepo[] {
    return repos.filter(repo => 
        repo.language?.toLowerCase() === language.toLowerCase()
    );
}

// Enhanced main function
async function mainEnhanced() {
    try {
        let repos = await fetchUserRepos('microsoft');

        // Sort by stars
        repos = sortByStars(repos);

        // Display all repos
        displayRepos(repos);

        // Filter and display TypeScript repos
        const tsRepos = filterByLanguage(repos, 'TypeScript');
        console.log(`\n\nTypeScript repositories (${tsRepos.length}):`);
        displayRepos(tsRepos);

        // Statistics
        const totalStars = repos.reduce((sum, repo) => sum + repo.stargazers_count, 0);
        const languages = new Set(repos.map(r => r.language).filter(l => l !== null));

        console.log(`\nStatistics:`);
        console.log(`Total repositories: ${repos.length}`);
        console.log(`Total stars: ${totalStars}`);
        console.log(`Languages used: ${Array.from(languages).join(', ')}`);
    } catch (error) {
        console.error('Failed to fetch and display repositories:', error);
    }
}