@@ -249,9 +249,11 @@ export const GITHUB_CACHE_TTL_MS = 5 * 60 * 1000;
249249const contributionsCache = new DistributedCache < ExtendedContributionData > ( 1000 ) ;
250250const profileCache = new DistributedCache < GitHubUserProfile > ( 1000 ) ;
251251const reposCache = new DistributedCache < GitHubRepo [ ] > ( 500 ) ;
252+ const contributedReposCache = new DistributedCache < Record < string , unknown > [ ] > ( 500 ) ;
252253const pendingContributions = new Map < string , Promise < ExtendedContributionData > > ( ) ;
253254const pendingProfiles = new Map < string , Promise < GitHubUserProfile > > ( ) ;
254255const pendingRepos = new Map < string , Promise < GitHubRepo [ ] > > ( ) ;
256+ const pendingContributedRepos = new Map < string , Promise < Record < string , unknown > [ ] > > ( ) ;
255257
256258interface GitHubUserProfile {
257259 login : string ;
@@ -268,18 +270,18 @@ interface GitHubUserProfile {
268270}
269271
270272export function cacheKey (
271- kind : 'contributions' | 'profile' | 'repos' ,
273+ kind : 'contributions' | 'profile' | 'repos' | 'repos:contributed' ,
272274 username : string ,
273275 year ?: string
274276) : string ;
275277export function cacheKey (
276- kind : 'contributions' | 'profile' | 'repos' ,
278+ kind : 'contributions' | 'profile' | 'repos' | 'repos:contributed' ,
277279 username : string ,
278280 from ?: string ,
279281 to ?: string
280282) : string ;
281283export function cacheKey (
282- kind : 'contributions' | 'profile' | 'repos' ,
284+ kind : 'contributions' | 'profile' | 'repos' | 'repos:contributed' ,
283285 username : string ,
284286 yearOrFrom ?: string ,
285287 to ?: string
@@ -296,9 +298,11 @@ export function clearGitHubApiCacheForTests(): void {
296298 contributionsCache . clear ( ) ;
297299 profileCache . clear ( ) ;
298300 reposCache . clear ( ) ;
301+ contributedReposCache . clear ( ) ;
299302 pendingContributions . clear ( ) ;
300303 pendingProfiles . clear ( ) ;
301304 pendingRepos . clear ( ) ;
305+ pendingContributedRepos . clear ( ) ;
302306}
303307
304308function dedupeRequest < T > (
@@ -906,38 +910,54 @@ export async function fetchContributedRepos(
906910 username : string ,
907911 options : FetchOptions = { }
908912) : Promise < Record < string , unknown > [ ] > {
909- const query = `
910- query($login: String!) {
911- user(login: $login) {
912- repositoriesContributedTo(first: 100, contributionTypes: [COMMIT, ISSUE, PULL_REQUEST, REPOSITORY], orderBy: {field: UPDATED_AT, direction: DESC}) {
913- nodes {
914- name
915- nameWithOwner
916- owner { login }
917- stargazerCount
918- forkCount
919- primaryLanguage { name }
920- updatedAt
913+ const key = cacheKey ( 'repos:contributed' , username ) ;
914+ if ( ! options . bypassCache ) {
915+ const cached = await contributedReposCache . get ( key ) ;
916+ if ( cached ) return cached ;
917+ }
918+
919+ const load = async ( ) => {
920+ const query = `
921+ query($login: String!) {
922+ user(login: $login) {
923+ repositoriesContributedTo(first: 100, contributionTypes: [COMMIT, ISSUE, PULL_REQUEST, REPOSITORY], orderBy: {field: UPDATED_AT, direction: DESC}) {
924+ nodes {
925+ name
926+ nameWithOwner
927+ owner { login }
928+ stargazerCount
929+ forkCount
930+ primaryLanguage { name }
931+ updatedAt
932+ }
921933 }
922934 }
923935 }
936+ ` ;
937+
938+ const res = await fetchWithRetry ( GITHUB_GRAPHQL_URL , {
939+ method : 'POST' ,
940+ headers : getHeaders ( ) ,
941+ body : JSON . stringify ( {
942+ query,
943+ variables : { login : username } ,
944+ } ) ,
945+ cache : 'no-store' ,
946+ signal : options . signal ,
947+ } ) ;
948+
949+ if ( ! res . ok ) return [ ] ;
950+ const data = await res . json ( ) ;
951+ const result = data ?. data ?. user ?. repositoriesContributedTo ?. nodes || [ ] ;
952+
953+ if ( ! options . bypassCache ) {
954+ await contributedReposCache . set ( key , result , GITHUB_CACHE_TTL_MS ) ;
924955 }
925- ` ;
926-
927- const res = await fetchWithRetry ( GITHUB_GRAPHQL_URL , {
928- method : 'POST' ,
929- headers : getHeaders ( ) ,
930- body : JSON . stringify ( {
931- query,
932- variables : { login : username } ,
933- } ) ,
934- cache : 'no-store' ,
935- signal : options . signal ,
936- } ) ;
956+ return result ;
957+ } ;
937958
938- if ( ! res . ok ) return [ ] ;
939- const data = await res . json ( ) ;
940- return data ?. data ?. user ?. repositoriesContributedTo ?. nodes || [ ] ;
959+ if ( options . bypassCache ) return load ( ) ;
960+ return dedupeRequest ( pendingContributedRepos , key , load ) ;
941961}
942962
943963export interface DeveloperScoreInput {
0 commit comments