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
- 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:
This endpoint returns a JSON array of repository objects, each containing information like name, description, stars, etc.
Creating the Repository Interface
- Define an interface named
GitHubRepowith the following properties: name: stringdescription: string or nullhtml_url: stringstargazers_count: numberlanguage: string or null
Fetching and Displaying Repositories
- Create an async function named
fetchUserReposthat: - Accepts a username as a parameter (string)
- Uses the Fetch API to retrieve repositories from
https://api.github.com/users/${username}/repos - Returns a Promise that resolves to an array of
GitHubRepoobjects -
Includes proper error handling
-
Create a function named
displayReposthat: - Accepts an array of
GitHubRepoobjects - Prints each repository’s name, description, stars, and language in a readable format
-
Handles cases where description or language might be null
-
Create a main function that:
- Calls
fetchUserReposwith the username “microsoft” - Displays the repositories using
displayRepos -
Handles any errors that might occur
-
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);
}
}