import nodePath from 'path' ; import { Octokit as createOctokit } from '@octokit/rest' ; import { throttling } from '@octokit/plugin-throttling' ; import type { GitHubFile } from '~/types' ; const Octokit = createOctokit . plugin ( throttling ) ; type ThrottleOptions = { method : string ; url : string ; request : { retryCount : number ; } ; } ; const octokit = new Octokit ( { auth : process . env . BOT_GITHUB_TOKEN , throttle : { onRateLimit : ( retryAfter , options ) => { console . warn ( `Request quota exhausted for request ${ options . method } ${ options . url }. Retrying after ${ retryAfter } seconds.` ) ; return true ; } , onAbuseLimit : ( retryAfter , options ) => { octokit . log . warn ( `Abuse detected for request ${ options . method } ${ options . url }` ) ; } , } , } ) ; async function downloadFirstMdxFile ( list ) { const filesOnly = list . filter ( ( { type } ) => type === 'file' ) ; for ( const extension of [ '.mdx' , '.md' ] ) { const file = filesOnly . find ( ( { name } ) => name . endsWith ( extension ) ) ; if ( file ) return downloadFileBySha ( file . sha ) ; } return null ; } param relativeMdxFileOrDirectory returns async function downloadMdxFileOrDirectory ( relativeMdxFileOrDirectory ) { const mdxFileOrDirectory = `content/${ relativeMdxFileOrDirectory }` ; const parentDir = nodePath . dirname ( mdxFileOrDirectory ) ; const dirList = await downloadDirList ( parentDir ) ; const basename = nodePath . basename ( mdxFileOrDirectory ) ; const mdxFileWithoutExt = nodePath . parse ( mdxFileOrDirectory ) . name ; const potentials = dirList . filter ( ( { name } ) => name . startsWith ( basename ) ) ; const exactMatch = potentials . find ( ( { name } ) => nodePath . parse ( name ) . name === mdxFileWithoutExt ) ; const dirPotential = potentials . find ( ( { type } ) => type === 'dir' ) ; const content = await downloadFirstMdxFile ( exactMatch ? [ exactMatch ] : potentials ) ; let files = [ ] ; let entry = mdxFileOrDirectory ; if ( content ) { entry = mdxFileOrDirectory . endsWith ( '.mdx' ) ? mdxFileOrDirectory : `${ mdxFileOrDirectory }.mdx` ; files = [ { path : nodePath . join ( mdxFileOrDirectory , 'index.mdx' ) , content } ] ; } else if ( dirPotential ) { entry = dirPotential . path ; files = await downloadDirectory ( mdxFileOrDirectory ) ; } return { entry , files } ; } param dir returns async function downloadDirectory ( dir ) { const dirList = await downloadDirList ( dir ) ; const result = await Promise . all ( dirList . map ( async ( { path : fileDir , type , sha } ) => { switch ( type ) { case 'file' : { const content = await downloadFileBySha ( sha ) ; return { path : fileDir , content } ; } case 'dir' : { return downloadDirectory ( fileDir ) ; } default : { throw new Error ( `Unexpected repo file type: ${ type }` ) ; } } } ) ) ; return result . flat ( ) ; } param sha returns async function downloadFileBySha ( sha ) { const { data } = await octokit . request ( 'GET /repos/{owner}/{repo}/git/blobs/{file_sha}' , { owner : 'kentcdodds' , repo : 'kentcdodds.com' , file_sha : sha , } ) ; const encoding = data . encoding as Parameters < typeof Buffer . from > [ '1' ] ; return Buffer . from ( data . content , encoding ) . toString ( ) ; } async function downloadFile ( path ) { const { data } = ( await octokit . request ( 'GET /repos/{owner}/{repo}/contents/{path}' , { owner : 'kentcdodds' , repo : 'kentcdodds.com' , path , } ) ) as { data : { content ? : string ; encoding ? : string ; } ; } ; if ( ! data . content || ! data . encoding ) { console . error ( data ) ; throw new Error ( `Tried to get ${ path } but got back something that was unexpected. It doesn't have a content or encoding property` ) ; } const encoding = data . encoding as Parameters < typeof Buffer . from > [ '1' ] ; return Buffer . from ( data . content , encoding ) . toString ( ) ; } param path returns async function downloadDirList ( path ) { const resp = await octokit . repos . getContent ( { owner : 'kentcdodds' , repo : 'kentcdodds.com' , path , } ) ; const data = resp . data ; if ( ! Array . isArray ( data ) ) { throw new Error ( `Tried to download content from ${ path }. GitHub did not return an array of files. This should never happen...` ) ; } return data ; } export { downloadMdxFileOrDirectory , downloadDirList , downloadFile } ;