Skip to content

Instantly share code, notes, and snippets.

@tigawanna
Created January 14, 2024 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tigawanna/3ae4b14f2820c50f5b3d993c4f8773c6 to your computer and use it in GitHub Desktop.
Save tigawanna/3ae4b14f2820c50f5b3d993c4f8773c6 to your computer and use it in GitHub Desktop.
Recursively fetch all github repositories and it's langauges

code to fetch the viewer's repos

export async function getViewerRepos(
  viewer_token: string,
  cursor: string | null = null,
): Promise<{ data: ViewerRepos | null; error: BadDataGitHubError | null }> {

  const query = `
    query($first: Int!,$after: String) {
    viewer {
    repositories(      
     first: $first
      after: $after
      isFork: false
      orderBy: {field: PUSHED_AT, direction: DESC}
      ) {

      edges {
        node {
          id
          name
          nameWithOwner
          languages(first: 10) {
            edges {
              node {
                id
                name
                color
              }
            }
          }
        }
      }
      totalCount
      pageInfo {
        endCursor
        startCursor
      }
    }
  }
}
`;
  try {
    const response = await fetch("https://api.github.com/graphql", {
      method: "POST",
      headers: {
        "Authorization": `bearer ${viewer_token}`,
        "Content-Type": "application/json",
        "accept": "application/vnd.github.hawkgirl-preview+json",
      },
      body: JSON.stringify({
        query,
        variables: {
          first: 50,
          after: cursor,
        },
        // operationName,
      }),
    });
    const data = await response.json() as unknown as ViewerRepos;

    if ("message" in data) {
      console.log("throw error fetching viewer repos  ==> ", data);
      return { data: null, error: data as unknown as BadDataGitHubError };
    }
    // logSuccess("all user repositories ===== ", data);
    return { data, error: null };
  } catch (err) {
    console.log("catch error fetching viewer repos ==> ", err);
    return { data: null, error: err as BadDataGitHubError };
  }
}

export interface ViewerRepos {
  data: Data;
}

export interface Data {
  viewer: Viewer;
}

export interface Viewer {
  repositories: Repositories;
}

export interface Repositories {
  edges: Edge[];
  totalCount: number;
  pageInfo: PageInfo;
}

export interface Edge {
  cursor: string;
  node: Node;
}

export interface Node {
  id: string;
  name: string;
  nameWithOwner: string;
  languages: Languages;
}

export interface Languages {
  edges: LanguageEdge[];
}

export interface LanguageEdge {
  node: LanguageNode;
}

export interface LanguageNode {
  id: string;
  name: string;
  color: string;
}

export interface PageInfo {
  endCursor: string;
  startCursor: string;
}

export interface BadDataGitHubError {
  message: string;
  documentation_url: string;
}

recursively fetch all the repos

async function fetchReposRecursivelyWithGQL({
  viewer_token,
  all_repos = [],
  cursor,
}: FetchRepoRecursivelyWithGQL) {
  try {
    const repos = await getViewerRepos(viewer_token, cursor);
    if (repos.data) {
      const fetched_repos = repos.data.data.viewer.repositories.edges;
      const totalCount = repos.data.data.viewer.repositories.totalCount;
      const next_cursor =
        repos.data.data.viewer.repositories.pageInfo.endCursor;
      const new_repos = all_repos.concat(fetched_repos);

      console.log({
        fetched_repos_count: new_repos.length,
        totalCount,
        next_cursor,
      });

      if (new_repos.length < totalCount) {
        return fetchReposRecursivelyWithGQL({
          viewer_token,
          cursor: next_cursor,
          all_repos: new_repos,
        });
      }
      return new_repos;
    }
  } catch (error) {
    logError(error);
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment