@@ -2,13 +2,57 @@ import {
22 extractFrontMatter ,
33 fetchApiContents ,
44 fetchRepoFile ,
5+ isRecoverableGitHubContentError ,
56} from '~/utils/documents.server'
67import removeMarkdown from 'remove-markdown'
78import { notFound } from '@tanstack/react-router'
89import { createServerFn } from '@tanstack/react-start'
910import * as v from 'valibot'
1011import { setResponseHeader } from '@tanstack/react-start/server'
1112
13+ const DOCS_UNAVAILABLE_TITLE = 'Content temporarily unavailable'
14+
15+ function buildUnavailableDoc ( filePath : string ) {
16+ return {
17+ title : DOCS_UNAVAILABLE_TITLE ,
18+ description :
19+ 'This page could not be refreshed from GitHub right now. Please try again shortly.' ,
20+ filePath,
21+ content : [
22+ '# Content temporarily unavailable' ,
23+ '' ,
24+ 'This page could not be refreshed from GitHub right now.' ,
25+ 'Please try again shortly.' ,
26+ ] . join ( '\n' ) ,
27+ frontmatter : {
28+ title : DOCS_UNAVAILABLE_TITLE ,
29+ description :
30+ 'This page could not be refreshed from GitHub right now. Please try again shortly.' ,
31+ } ,
32+ }
33+ }
34+
35+ function buildUnavailableFile ( filePath : string ) {
36+ const lowerFilePath = filePath . toLowerCase ( )
37+ const isMarkdown = lowerFilePath . endsWith ( '.md' )
38+
39+ if ( isMarkdown ) {
40+ return [
41+ '# Content temporarily unavailable' ,
42+ '' ,
43+ 'This file could not be refreshed from GitHub right now.' ,
44+ 'Please try again shortly.' ,
45+ ] . join ( '\n' )
46+ }
47+
48+ return [
49+ '// Content temporarily unavailable' ,
50+ `// ${ filePath } ` ,
51+ '// This file could not be refreshed from GitHub right now.' ,
52+ '// Please try again shortly.' ,
53+ ] . join ( '\n' )
54+ }
55+
1256export const loadDocs = async ( {
1357 repo,
1458 branch,
@@ -42,7 +86,23 @@ export const fetchDocs = createServerFn({ method: 'GET' })
4286 v . object ( { repo : v . string ( ) , branch : v . string ( ) , filePath : v . string ( ) } ) ,
4387 )
4488 . handler ( async ( { data : { repo, branch, filePath } } ) => {
45- const file = await fetchRepoFile ( repo , branch , filePath )
89+ let file : string | null
90+
91+ try {
92+ file = await fetchRepoFile ( repo , branch , filePath )
93+ } catch ( error ) {
94+ if ( isRecoverableGitHubContentError ( error ) ) {
95+ console . warn ( '[fetchDocs] Falling back to unavailable placeholder:' , {
96+ repo,
97+ branch,
98+ filePath,
99+ message : error instanceof Error ? error . message : String ( error ) ,
100+ } )
101+ return buildUnavailableDoc ( filePath )
102+ }
103+
104+ throw error
105+ }
46106
47107 if ( ! file ) {
48108 throw notFound ( )
@@ -73,7 +133,23 @@ export const fetchFile = createServerFn({ method: 'GET' })
73133 v . object ( { repo : v . string ( ) , branch : v . string ( ) , filePath : v . string ( ) } ) ,
74134 )
75135 . handler ( async ( { data : { repo, branch, filePath } } ) => {
76- const file = await fetchRepoFile ( repo , branch , filePath )
136+ let file : string | null
137+
138+ try {
139+ file = await fetchRepoFile ( repo , branch , filePath )
140+ } catch ( error ) {
141+ if ( isRecoverableGitHubContentError ( error ) ) {
142+ console . warn ( '[fetchFile] Falling back to unavailable placeholder:' , {
143+ repo,
144+ branch,
145+ filePath,
146+ message : error instanceof Error ? error . message : String ( error ) ,
147+ } )
148+ return buildUnavailableFile ( filePath )
149+ }
150+
151+ throw error
152+ }
77153
78154 if ( ! file ) {
79155 throw notFound ( )
0 commit comments