diff --git a/api/routes/single-page.ts b/api/routes/single-page.ts index 2a9416b6e..5ca8105bf 100644 --- a/api/routes/single-page.ts +++ b/api/routes/single-page.ts @@ -15,8 +15,10 @@ */ import { fetcher } from 'itty-fetcher' +import { createStorage } from 'unstorage' +import cloudflareKVBindingDriver from 'unstorage/drivers/cloudflare-kv-binding' -// Look inside tbe docs directory +// Look inside the docs directory const GITHUB_REPO = 'https://api.github.com/repos/fmhy/edit/contents/docs/' const EXCLUDE_FILES = [ 'README.md', @@ -45,6 +47,10 @@ interface File { } export default defineEventHandler(async (event) => { + const markdownStorage = createStorage({ + driver: cloudflareKVBindingDriver({ binding: 'STORAGE' }) + }) + let body = '\n' const f = fetcher({ headers: { @@ -54,7 +60,13 @@ export default defineEventHandler(async (event) => { try { // Fetch the list of files in the repository - const files = await f.get(GITHUB_REPO) + 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) => { @@ -67,12 +79,17 @@ export default defineEventHandler(async (event) => { return isMarkdownFile && !isExcludedFile && !isInExcludedDirectory }) - // console.info(markdownFiles.map((f) => f.name)) - - // Fetch and concatenate the contents of the markdown files + // 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 }) ) @@ -86,6 +103,9 @@ export default defineEventHandler(async (event) => { } // biome-ignore lint/correctness/noUndeclaredVariables: - appendResponseHeader(event, 'content-type', 'text/markdown;charset=utf-8') + appendResponseHeaders(event, { + 'content-type': 'text/markdown;charset=utf-8', + 'cache-control': 'public, max-age=3600' + }) return body }) diff --git a/nitro.config.ts b/nitro.config.ts index 02bcb293e..e35947e88 100644 --- a/nitro.config.ts +++ b/nitro.config.ts @@ -15,6 +15,8 @@ */ //https://nitro.unjs.io/config export default defineNitroConfig({ + preset: 'cloudflare_module', + compatibilityDate: '2024-11-01', runtimeConfig: { WEBHOOK_URL: process.env.WEBHOOK_URL }, diff --git a/package.json b/package.json index 9176eb78f..709c1a8f8 100644 --- a/package.json +++ b/package.json @@ -30,11 +30,11 @@ "feed": "^4.2.2", "itty-fetcher": "^0.9.4", "nitro-cors": "^0.7.1", - "nitropack": "^2.9.7", + "nitropack": "^2.10.4", "nprogress": "^0.2.0", "pathe": "^1.1.2", "unocss": "^0.63.4", - "vitepress": "^1.4.1", + "vitepress": "^1.5.0", "vue": "^3.5.12", "x-satori": "^0.2.0", "zod": "^3.23.8" @@ -61,7 +61,7 @@ "unplugin-auto-import": "^0.18.3", "vite-plugin-optimize-exclude": "^0.0.1", "vite-plugin-terminal": "^1.2.0", - "wrangler": "^3.80.5" + "wrangler": "^3.99.0" }, "pnpm": { "peerDependencyRules": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b99ceb04f..2fd7174e4 100644 Binary files a/pnpm-lock.yaml and b/pnpm-lock.yaml differ diff --git a/wrangler.toml b/wrangler.toml index 5e1c7b142..63243b028 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -2,12 +2,17 @@ name = "api" main = ".output/server/index.mjs" workers_dev = false account_id = "02f3b11d8d1017a20f95de4ba88fb5d6" -compatibility_date = "2022-09-10" +compatibility_flags = [ "nodejs_compat" ] +compatibility_date = "2024-11-01" routes = [ { pattern = "api.fmhy.net", custom_domain = true, zone_id = "b4212298934f7c1998b4d15f6d261715" }, ] +[[kv_namespaces]] +binding = "STORAGE" +id = "6f18adea26a64d6b8858ffbdfd3f4cf2" + [[unsafe.bindings]] name = "RATE_LIMITER" type = "ratelimit"