Skip to main content
Glama
github-api.ts6.06 kB
/** * GitHub API Utilities * * This file contains utility functions for interacting with the GitHub API * to fetch repository data for diagram generation. */ import axios, { AxiosInstance } from 'axios'; /** * Create an axios instance configured for GitHub API requests. * * @param {string|undefined} token - GitHub API token for authenticated requests * @returns {AxiosInstance} Configured axios instance */ export function createGitHubApiClient(token?: string): AxiosInstance { return axios.create({ headers: token ? { Authorization: `token ${token}` } : {} }); } /** * Fetch repository data from GitHub API. * * This function fetches repository data including structure, files, and metadata * to be used for diagram generation. * * @param {AxiosInstance} apiClient - Axios instance for making API requests * @param {string} owner - The repository owner * @param {string} repo - The repository name * @returns {Promise<any>} A promise that resolves to the repository data */ export async function fetchRepositoryData(apiClient: AxiosInstance, owner: string, repo: string): Promise<any> { try { // Fetch repository information const repoResponse = await apiClient.get( `https://api.github.com/repos/${owner}/${repo}` ); // Fetch repository contents (top-level files and directories) const contentsResponse = await apiClient.get( `https://api.github.com/repos/${owner}/${repo}/contents` ); // Fetch languages used in the repository const languagesResponse = await apiClient.get( `https://api.github.com/repos/${owner}/${repo}/languages` ); // Fetch code files for analysis const codeFiles = await fetchCodeFiles(apiClient, owner, repo, contentsResponse.data); // Return combined repository data return { info: repoResponse.data, contents: contentsResponse.data, languages: languagesResponse.data, codeFiles: codeFiles }; } catch (error) { console.error('Error fetching repository data:', error); throw new Error('Failed to fetch repository data from GitHub API'); } } /** * Fetch code files from a GitHub repository for analysis. * * This function recursively fetches code files from the repository, * focusing on files that are likely to contain code (based on extension). * * @param {AxiosInstance} apiClient - Axios instance for making API requests * @param {string} owner - The repository owner * @param {string} repo - The repository name * @param {any[]} contents - The contents of the current directory * @param {string} path - The current path within the repository * @param {number} maxFiles - Maximum number of files to fetch * @returns {Promise<Array<{path: string, content: string, language: string}>>} A promise that resolves to an array of code files */ async function fetchCodeFiles( apiClient: AxiosInstance, owner: string, repo: string, contents: any[], path: string = '', maxFiles: number = 20 ): Promise<Array<{path: string, content: string, language: string}>> { const codeFiles: Array<{path: string, content: string, language: string}> = []; const codeExtensions = ['.js', '.ts', '.jsx', '.tsx', '.py', '.java', '.rb', '.go', '.php', '.cs', '.cpp', '.c', '.h']; // Process each item in the contents for (const item of contents) { // Stop if we've reached the maximum number of files if (codeFiles.length >= maxFiles) { break; } if (item.type === 'file') { // Check if this is a code file based on extension const fileExt = item.name.substring(item.name.lastIndexOf('.')); if (codeExtensions.includes(fileExt)) { try { // Fetch the file content const contentResponse = await apiClient.get(item.download_url); // Determine the language based on file extension let language = 'unknown'; if (['.js', '.jsx'].includes(fileExt)) language = 'javascript'; else if (['.ts', '.tsx'].includes(fileExt)) language = 'typescript'; else if (fileExt === '.py') language = 'python'; else if (fileExt === '.java') language = 'java'; else if (fileExt === '.rb') language = 'ruby'; else if (fileExt === '.go') language = 'go'; else if (fileExt === '.php') language = 'php'; else if (fileExt === '.cs') language = 'csharp'; else if (['.cpp', '.c', '.h'].includes(fileExt)) language = 'cpp'; // Add the file to our collection codeFiles.push({ path: item.path, content: contentResponse.data, language: language }); } catch (error) { console.error(`Error fetching file ${item.path}:`, error); } } } else if (item.type === 'dir') { try { // Fetch the contents of the subdirectory const subdirResponse = await apiClient.get( `https://api.github.com/repos/${owner}/${repo}/contents/${item.path}` ); // Recursively fetch code files from the subdirectory const subdirFiles = await fetchCodeFiles( apiClient, owner, repo, subdirResponse.data, item.path, maxFiles - codeFiles.length ); // Add the subdirectory files to our collection codeFiles.push(...subdirFiles); } catch (error) { console.error(`Error fetching directory ${item.path}:`, error); } } } return codeFiles; } /** * Extract owner and repository name from a GitHub URL. * * @param {string} url - GitHub repository URL * @returns {[string, string]} A tuple containing [owner, repo] * @throws {Error} If the URL is not a valid GitHub repository URL */ export function extractRepoInfoFromUrl(url: string): [string, string] { const match = url.match(/github\.com\/([^\/]+)\/([^\/]+)/); if (!match) { throw new Error('Invalid GitHub repository URL'); } return [match[1], match[2]]; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/phxdev1/archy-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server