/** * 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 = '\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(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(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: appendResponseHeaders(event, { 'content-type': 'text/markdown;charset=utf-8', 'cache-control': 'public, max-age=3600' }) return body })