FMHY-Website/api/routes/single-page.ts

111 lines
3.1 KiB
TypeScript

/**
* Copyright (c) taskylizard. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { fetcher } from 'itty-fetcher'
import { createStorage } from 'unstorage'
import cloudflareKVBindingDriver from 'unstorage/drivers/cloudflare-kv-binding'
// Look inside the docs directory
const GITHUB_REPO = 'https://api.github.com/repos/fmhy/edit/contents/docs/'
const EXCLUDE_FILES = [
'README.md',
'index.md',
'feedback.md',
'posts.md',
'sandbox.md'
]
const EXCLUDE_DIRECTORIES = ['posts/']
interface File {
name: string
path: string
sha: string
size: number
url: string
html_url: string
git_url: string
download_url: string | null
type: string
_links: {
self: string
git: string
html: string
}
}
export default defineEventHandler(async (event) => {
const markdownStorage = createStorage({
driver: cloudflareKVBindingDriver({ binding: 'STORAGE' })
})
let body = '<!-- This is autogenerated content, do not edit manually. -->\n'
const f = fetcher({
headers: {
'User-Agent': 'taskylizard'
}
})
try {
// Fetch the list of files in the repository
const indexCacheKey = "INDEX"
let files = await markdownStorage.getItem<File[]>(indexCacheKey)
if (!files) {
files = await f.get(GITHUB_REPO)
await markdownStorage.setItem(indexCacheKey, files, { ttl: 60 * 60 * 24 * 7 })
}
// Filter out the excluded files and non-markdown files
const markdownFiles = files.filter((file: File) => {
const isExcludedFile = EXCLUDE_FILES.includes(file.name)
const isInExcludedDirectory = EXCLUDE_DIRECTORIES.some((dir) =>
file.path.startsWith(dir)
)
const isMarkdownFile = file.name.endsWith('.md')
return isMarkdownFile && !isExcludedFile && !isInExcludedDirectory
})
// Fetch and concatenate the contents of the markdown files with caching
const contents = await Promise.all(
markdownFiles.map(async (file: File) => {
const cached = await markdownStorage.getItem(file.name)
if (cached) return cached
const content = await f.get<string>(file.download_url)
if (content) {
await markdownStorage.setItem(file.name, content, { ttl: 60 * 60 })
}
return content
})
)
body += contents.join('\n\n')
} catch (error) {
return {
status: 500,
body: `Error fetching markdown files: ${error.message}`
}
}
// biome-ignore lint/correctness/noUndeclaredVariables: <explanation>
appendResponseHeaders(event, {
'content-type': 'text/markdown;charset=utf-8',
'cache-control': 'public, max-age=3600'
})
return body
})