@@ -38,9 +38,19 @@ function getLuminance(hex: string) {
3838export async function GET ( req : NextRequest ) {
3939 const { searchParams } = new URL ( req . url ) ;
4040
41- const { user, theme, bg, text, accent } = ogParamsSchema . parse (
42- Object . fromEntries ( searchParams . entries ( ) )
43- ) ;
41+ const parseResult = ogParamsSchema . safeParse ( Object . fromEntries ( searchParams . entries ( ) ) ) ;
42+
43+ if ( ! parseResult . success ) {
44+ return new Response (
45+ JSON . stringify ( { error : 'Invalid parameters' , details : parseResult . error . flatten ( ) } ) ,
46+ {
47+ status : 400 ,
48+ headers : { 'Content-Type' : 'application/json' , 'Cache-Control' : 'no-store' } ,
49+ }
50+ ) ;
51+ }
52+
53+ const { user, theme, bg, text, accent, refresh } = parseResult . data ;
4454
4555 const selectedTheme = themes [ theme ] || themes . dark ;
4656 const resolvedBg = `#${ bg || selectedTheme . bg } ` ;
@@ -59,7 +69,7 @@ export async function GET(req: NextRequest) {
5969
6070 // Only the data fetching is wrapped in try/catch — not the JSX rendering.
6171 try {
62- const calendar = await fetchGitHubContributions ( user , { bypassCache : true } ) ;
72+ const calendar = await fetchGitHubContributions ( user , { bypassCache : refresh } ) ;
6373 const stats = calculateStreak ( calendar ) ;
6474 totalCommits = stats . totalContributions ;
6575 longestStreak = stats . longestStreak ;
@@ -69,6 +79,10 @@ export async function GET(req: NextRequest) {
6979 // fallback to zeros if GitHub is unreachable
7080 }
7181
82+ const cacheControl = refresh
83+ ? 'no-cache, no-store, must-revalidate'
84+ : 'public, max-age=3600, stale-while-revalidate=86400' ;
85+
7286 return new ImageResponse (
7387 < div
7488 style = { {
@@ -189,7 +203,7 @@ export async function GET(req: NextRequest) {
189203 width : 1200 ,
190204 height : 630 ,
191205 headers : {
192- 'Cache-Control' : 'public, max-age=3600, stale-while-revalidate=86400' ,
206+ 'Cache-Control' : cacheControl ,
193207 } ,
194208 }
195209 ) ;
0 commit comments