kaneo (minimalist kanban) fork to experiment adding a tangled integration github.com/usekaneo/kaneo
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 113 lines 3.4 kB view raw
1import { HTTPException } from "hono/http-exception"; 2import { getGithubApp } from "../../plugins/github/utils/github-app"; 3 4async function listUserRepositories() { 5 const githubApp = getGithubApp(); 6 7 if (!githubApp) { 8 throw new HTTPException(500, { 9 message: "GitHub app not configured", 10 }); 11 } 12 13 try { 14 const { data: installations } = 15 await githubApp.octokit.rest.apps.listInstallations(); 16 17 const allRepositories = []; 18 const installationsWithRepos = []; 19 20 for (const installation of installations) { 21 try { 22 const installationOctokit = await githubApp.getInstallationOctokit( 23 installation.id, 24 ); 25 26 // Use pagination to fetch ALL repositories for this installation 27 const repos = await installationOctokit.paginate( 28 installationOctokit.rest.apps.listReposAccessibleToInstallation, 29 { 30 per_page: 100, // GitHub's maximum 31 }, 32 ); 33 34 // Store installation info with repository names for UI 35 installationsWithRepos.push({ 36 id: installation.id, 37 account: installation.account 38 ? { 39 login: installation.account.login, 40 type: installation.account.type, 41 } 42 : null, 43 repositories: repos.map((repo) => repo.full_name), 44 }); 45 46 const mappedRepos = repos.map((repo) => ({ 47 id: repo.id, 48 name: repo.name, 49 full_name: repo.full_name, 50 private: repo.private, 51 owner: { 52 login: repo.owner.login, 53 avatar_url: repo.owner.avatar_url, 54 type: repo.owner.type, 55 }, 56 description: repo.description, 57 html_url: repo.html_url, 58 permissions: repo.permissions 59 ? { 60 admin: repo.permissions.admin, 61 push: repo.permissions.push, 62 pull: repo.permissions.pull, 63 } 64 : undefined, 65 updated_at: repo.updated_at || new Date().toISOString(), 66 installation_id: installation.id, 67 })); 68 69 allRepositories.push(...mappedRepos); 70 } catch (error) { 71 console.warn( 72 `Failed to get repositories for installation ${installation.id}:`, 73 error, 74 ); 75 // Still add installation info even if repo fetch fails 76 installationsWithRepos.push({ 77 id: installation.id, 78 account: installation.account 79 ? { 80 login: installation.account.login, 81 type: installation.account.type, 82 } 83 : null, 84 repositories: [], 85 }); 86 } 87 } 88 89 // Remove duplicates and sort by most recently updated 90 const uniqueRepositories = allRepositories 91 .filter( 92 (repo, index, self) => 93 index === self.findIndex((r) => r.id === repo.id), 94 ) 95 .sort( 96 (a, b) => 97 new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime(), 98 ); 99 100 return { 101 repositories: uniqueRepositories, 102 installations: installationsWithRepos, 103 total: uniqueRepositories.length, 104 }; 105 } catch (error) { 106 console.error("Failed to list user repositories:", error); 107 throw new HTTPException(500, { 108 message: "Failed to fetch repositories from GitHub", 109 }); 110 } 111} 112 113export default listUserRepositories;