@@ -5,127 +5,133 @@ import { TPullRequest, ZPullRequest } from "@/types/pullRequest";
55import { Octokit } from "@octokit/rest" ;
66import { unstable_cache } from "next/cache" ;
77
8- import { GITHUB_APP_ACCESS_TOKEN , OSS_GG_LABEL } from "../constants" ;
8+ import { GITHUB_APP_ACCESS_TOKEN , GITHUB_CACHE_REVALIDATION_INTERVAL , OSS_GG_LABEL } from "../constants" ;
9+ import { githubCache } from "./cache" ;
910import { extractPointsFromLabels } from "./utils" ;
1011
1112type PullRequestStatus = "open" | "merged" | "closed" | undefined ;
1213
1314const octokit = new Octokit ( { auth : GITHUB_APP_ACCESS_TOKEN } ) ;
1415
15- const fetchPullRequestsByGithubLogin = async (
16+ export const getPullRequestsByGithubLogin = (
1617 playerRepositoryIds : string [ ] ,
1718 githubLogin : string ,
1819 status ?: PullRequestStatus
19- ) : Promise < TPullRequest [ ] > => {
20- if ( ! playerRepositoryIds || playerRepositoryIds . length === 0 ) {
21- console . warn ( "No repository IDs provided. Returning empty array." ) ;
22- return [ ] ;
23- }
24-
25- const pullRequests : TPullRequest [ ] = [ ] ;
26-
27- let statusQuery = "is:pr" ;
28- if ( status === "open" ) statusQuery += " is:open" ;
29- else if ( status === "merged" ) statusQuery += " is:merged" ;
30- else if ( status === "closed" ) statusQuery += " is:closed -is:merged" ;
31-
32- const repoQuery = playerRepositoryIds . map ( ( id ) => `repo:${ id } ` ) . join ( " " ) ;
33- const query = `${ repoQuery } ${ statusQuery } author:${ githubLogin } ` ;
34-
35- try {
36- const { data } = await octokit . search . issuesAndPullRequests ( {
37- q : query ,
38- per_page : 99 ,
39- sort : "created" ,
40- order : "desc" ,
41- } ) ;
42-
43- for ( const pr of data . items ) {
44- let prStatus : "open" | "merged" | "closed" ;
45- if ( pr . state === "open" ) {
46- prStatus = "open" ;
47- } else if ( pr . pull_request ?. merged_at ) {
48- prStatus = "merged" ;
49- } else {
50- prStatus = "closed" ;
20+ ) =>
21+ unstable_cache (
22+ async ( ) : Promise < TPullRequest [ ] > => {
23+ if ( ! playerRepositoryIds || playerRepositoryIds . length === 0 ) {
24+ console . warn ( "No repository IDs provided. Returning empty array." ) ;
25+ return [ ] ;
5126 }
5227
53- const prLabels = pr . labels . filter ( ( label ) => label . name !== undefined ) as { name : string } [ ] ;
28+ const pullRequests : TPullRequest [ ] = [ ] ;
29+
30+ let statusQuery = "is:pr" ;
31+ if ( status === "open" ) statusQuery += " is:open" ;
32+ else if ( status === "merged" ) statusQuery += " is:merged" ;
33+ else if ( status === "closed" ) statusQuery += " is:closed -is:merged" ;
34+
35+ const repoQuery = playerRepositoryIds . map ( ( id ) => `repo:${ id } ` ) . join ( " " ) ;
36+ const query = `${ repoQuery } ${ statusQuery } author:${ githubLogin } ` ;
5437
5538 try {
56- const pullRequest : TPullRequest = ZPullRequest . parse ( {
57- title : pr . title ,
58- href : pr . html_url ,
59- author : pr . user ?. login || "" ,
60- repositoryFullName : pr . repository_url . split ( "/" ) . slice ( - 2 ) . join ( "/" ) ,
61- dateOpened : pr . created_at ,
62- dateMerged : pr . pull_request ?. merged_at || null ,
63- dateClosed : pr . closed_at ,
64- status : prStatus ,
65- points : prLabels ? extractPointsFromLabels ( prLabels ) : null ,
39+ const { data } = await octokit . search . issuesAndPullRequests ( {
40+ q : query ,
41+ per_page : 99 ,
42+ sort : "created" ,
43+ order : "desc" ,
6644 } ) ;
6745
68- pullRequests . push ( pullRequest ) ;
46+ for ( const pr of data . items ) {
47+ let prStatus : "open" | "merged" | "closed" ;
48+ if ( pr . state === "open" ) {
49+ prStatus = "open" ;
50+ } else if ( pr . pull_request ?. merged_at ) {
51+ prStatus = "merged" ;
52+ } else {
53+ prStatus = "closed" ;
54+ }
55+
56+ const prLabels = pr . labels . filter ( ( label ) => label . name !== undefined ) as { name : string } [ ] ;
57+
58+ try {
59+ const pullRequest : TPullRequest = ZPullRequest . parse ( {
60+ title : pr . title ,
61+ href : pr . html_url ,
62+ author : pr . user ?. login || "" ,
63+ repositoryFullName : pr . repository_url . split ( "/" ) . slice ( - 2 ) . join ( "/" ) ,
64+ dateOpened : pr . created_at ,
65+ dateMerged : pr . pull_request ?. merged_at || null ,
66+ dateClosed : pr . closed_at ,
67+ status : prStatus ,
68+ points : prLabels ? extractPointsFromLabels ( prLabels ) : null ,
69+ } ) ;
70+
71+ pullRequests . push ( pullRequest ) ;
72+ } catch ( error ) {
73+ console . error ( `Error parsing pull request: ${ pr . title } ` , error ) ;
74+ }
75+ }
6976 } catch ( error ) {
70- console . error ( `Error parsing pull request: ${ pr . title } ` , error ) ;
77+ console . error ( `Error fetching or processing pull requests: ` , error ) ;
7178 }
79+
80+ // Sort pullRequests by dateOpened in descending order
81+ pullRequests . sort ( ( a , b ) => new Date ( b . dateOpened ) . getTime ( ) - new Date ( a . dateOpened ) . getTime ( ) ) ;
82+
83+ return pullRequests ;
84+ } ,
85+ [ `getPullRequests-${ githubLogin } -${ status } -${ playerRepositoryIds . join ( "," ) } ` ] ,
86+ {
87+ tags : [ githubCache . tag . byGithubLogin ( githubLogin ) ] ,
88+ revalidate : GITHUB_CACHE_REVALIDATION_INTERVAL ,
7289 }
73- } catch ( error ) {
74- console . error ( `Error fetching or processing pull requests:` , error ) ;
75- }
76-
77- pullRequests . sort ( ( a , b ) => new Date ( b . dateOpened ) . getTime ( ) - new Date ( a . dateOpened ) . getTime ( ) ) ;
78-
79- return pullRequests ;
80- } ;
81-
82- export const getPullRequestsByGithubLogin = unstable_cache (
83- fetchPullRequestsByGithubLogin ,
84- [ "fetchPullRequestsByGithubLogin" ] ,
85- { revalidate : 60 }
86- ) ;
87-
88- const fetchAllOssGgIssuesOfRepos = async ( repoGithubIds : number [ ] ) : Promise < TPullRequest [ ] > => {
89- const githubHeaders = {
90- Authorization : `Bearer ${ GITHUB_APP_ACCESS_TOKEN } ` ,
91- Accept : "application/vnd.github.v3+json" ,
92- } ;
93-
94- const allIssues = await Promise . all (
95- repoGithubIds . map ( async ( repoGithubId ) => {
96- const repoResponse = await fetch ( `https://api.github.com/repositories/${ repoGithubId } ` , {
97- headers : githubHeaders ,
98- } ) ;
99- const repoData = await repoResponse . json ( ) ;
100-
101- const issuesResponse = await fetch (
102- `https://api.github.com/search/issues?q=repo:${ repoData . full_name } +is:issue+is:open+label:"${ OSS_GG_LABEL } "&sort=created&order=desc` ,
103- { headers : githubHeaders }
104- ) ;
105- const issuesData = await issuesResponse . json ( ) ;
106- const validatedData = ZGithubApiResponseSchema . parse ( issuesData ) ;
107-
108- return validatedData . items . map ( ( issue ) =>
109- ZPullRequest . parse ( {
110- title : issue . title ,
111- href : issue . html_url ,
112- author : issue . user . login ,
113- repositoryFullName : repoData . full_name ,
114- dateOpened : issue . created_at ,
115- dateMerged : null ,
116- dateClosed : issue . closed_at ,
117- status : "open" ,
118- points : extractPointsFromLabels ( issue . labels ) ,
90+ ) ( ) ;
91+
92+ export const getAllOssGgIssuesOfRepos = ( repoGithubIds : number [ ] ) =>
93+ unstable_cache (
94+ async ( ) : Promise < TPullRequest [ ] > => {
95+ const githubHeaders = {
96+ Authorization : `Bearer ${ GITHUB_APP_ACCESS_TOKEN } ` ,
97+ Accept : "application/vnd.github.v3+json" ,
98+ } ;
99+
100+ const allIssues = await Promise . all (
101+ repoGithubIds . map ( async ( repoGithubId ) => {
102+ const repoResponse = await fetch ( `https://api.github.com/repositories/${ repoGithubId } ` , {
103+ headers : githubHeaders ,
104+ } ) ;
105+ const repoData = await repoResponse . json ( ) ;
106+
107+ const issuesResponse = await fetch (
108+ `https://api.github.com/search/issues?q=repo:${ repoData . full_name } +is:issue+is:open+label:"${ OSS_GG_LABEL } "&sort=created&order=desc` ,
109+ { headers : githubHeaders }
110+ ) ;
111+ const issuesData = await issuesResponse . json ( ) ;
112+ const validatedData = ZGithubApiResponseSchema . parse ( issuesData ) ;
113+
114+ // Map the GitHub API response to TPullRequest format
115+ return validatedData . items . map ( ( issue ) =>
116+ ZPullRequest . parse ( {
117+ title : issue . title ,
118+ href : issue . html_url ,
119+ author : issue . user . login ,
120+ repositoryFullName : repoData . full_name ,
121+ dateOpened : issue . created_at ,
122+ dateMerged : null ,
123+ dateClosed : issue . closed_at ,
124+ status : "open" ,
125+ points : extractPointsFromLabels ( issue . labels ) ,
126+ } )
127+ ) ;
119128 } )
120129 ) ;
121- } )
122- ) ;
123-
124- return allIssues . flat ( ) ;
125- } ;
126130
127- export const getAllOssGgIssuesOfRepos = unstable_cache (
128- fetchAllOssGgIssuesOfRepos ,
129- [ "fetchAllOssGgIssuesOfRepos" ] ,
130- { revalidate : 60 }
131- ) ;
131+ return allIssues . flat ( ) ;
132+ } ,
133+ [ `getAllOssGgIssuesOfRepos-${ repoGithubIds . join ( "-" ) } ` ] ,
134+ {
135+ revalidate : GITHUB_CACHE_REVALIDATION_INTERVAL ,
136+ }
137+ ) ( ) ;
0 commit comments