import { Octokit } from "octokit"; const useOctokit = () => { const { user } = useUserSession(); if (!(user.value as any)?.githubToken) { throw new Error("GitHub access token not found. Please login first."); } return new Octokit({ auth: (user.value as any).githubToken }); }; export const useAuthenticatedUser = async (token: string) => { const octokit = new Octokit({ auth: token }); const { data: { login }, } = await octokit.rest.users.getAuthenticated(); return login; }; export const useGithubOrg = (org: string) => { return useAsyncData( `github-org-${org}`, async () => { const octokit = useOctokit(); return octokit.rest.orgs.get({ org }); }, {}, ); }; export const useGithubRepo = (owner: string, repo: string) => { return useAsyncData( `github-repo-${owner}-${repo}`, async () => { const octokit = useOctokit(); return octokit.rest.repos.get({ owner, repo }); }, {}, ); }; export const useGithubRepoReadme = (owner: string, repo: string) => { return useAsyncData( `github-readme-${owner}-${repo}`, async () => { const octokit = useOctokit(); try { // Fetch the README with HTML rendering const response = await octokit.rest.repos.getReadme({ owner, repo, mediaType: { format: "html" }, }); return { html: response.data as unknown as string, html_url: response.data.html_url || `https://github.com/${owner}/${repo}#readme`, }; } catch { return null; } }, {}, ); }; export const useGithubRepoLanguages = (owner: string, repo: string) => { return useAsyncData( `github-languages-${owner}-${repo}`, async () => { const octokit = useOctokit(); return octokit.rest.repos.listLanguages({ owner, repo }); }, {}, ); }; export const useGithubRepoContributors = (owner: string, repo: string) => { return useAsyncData( `github-contributors-${owner}-${repo}`, async () => { const octokit = useOctokit(); return octokit.rest.repos.listContributors({ owner, repo, per_page: 10 }); }, {}, ); }; export const useGithubRepoReleases = (owner: string, repo: string) => { return useAsyncData( `github-releases-${owner}-${repo}`, async () => { const octokit = useOctokit(); return octokit.rest.repos.listReleases({ owner, repo, per_page: 5 }); }, {}, ); }; export const useGithubRepoIssues = ( owner: string, repo: string, options: MaybeRef<{ state?: "open" | "closed" | "all"; sort?: "created" | "updated" | "comments"; direction?: "asc" | "desc"; per_page?: number; page?: number; }> = {}, ) => { return useAsyncData( () => `github-issues-${owner}-${repo}-${JSON.stringify(unref(options))}`, async () => { const octokit = useOctokit(); const opts = unref(options); return octokit.rest.issues.listForRepo({ owner, repo, state: opts.state || "open", sort: opts.sort || "created", direction: opts.direction || "desc", per_page: opts.per_page || 25, page: opts.page || 1, }); }, { watch: [() => unref(options)], }, ); }; export const useGithubRepoIssuesCount = (owner: string, repo: string, state: "closed") => { return useAsyncData( `github-issues-count-${owner}-${repo}-${state}`, async () => { const octokit = useOctokit(); try { // Use the search API to get an accurate count of closed issues // This is more efficient than fetching all issues just for the count const searchQuery = `repo:${owner}/${repo} type:issue state:${state}`; const response = await octokit.rest.search.issuesAndPullRequests({ q: searchQuery, per_page: 1, // We only need the total_count, not the actual results }); return response.data.total_count; } catch { // Fallback: try to fetch first page of closed issues and estimate try { const response = await octokit.rest.issues.listForRepo({ owner, repo, state, per_page: 1, }); // This won't give us the exact count, but it's better than nothing // GitHub doesn't provide total count in the response headers for issues API return response.data.length > 0 ? 1 : 0; } catch { return 0; } } }, {}, ); };