import { Context, Hono } from 'hono' import * as dotenv from 'dotenv' import { cors } from "hono/cors"; import { compress } from "hono/compress"; import { prettyJSON } from "hono/pretty-json"; import { trimTrailingSlash } from "hono/trailing-slash"; import { serve } from '@hono/node-server' import { createStorage } from "unstorage"; import cloudflareKVHTTPDriver from "unstorage/drivers/cloudflare-kv-http"; import { serveStatic } from '@hono/node-server/serve-static' import path from 'path' import { fileURLToPath } from 'url' import { dirname } from 'path' // 导入所有路由处理函数 import { onRequest as handleAccount } from './functions/api/account.js' import { onRequest as handleLogin } from './functions/api/login.js' import { onRequest as handleSetting } from './functions/api/setting.js' import { onRequest as handleGithub } from './functions/api/github/[[path]].js' import { onRequest as handleHF } from './functions/api/hf/[[path]].js' dotenv.config({ path: ['.env', '.env.local'], override: true }); const isDev = process.env.NODE_ENV === 'development' const app = new Hono<{ Bindings: Env }>() app.use(compress()); app.use(prettyJSON()); app.use(trimTrailingSlash()); app.use('*', cors({ origin: '*', allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], allowHeaders: ['Content-Type', 'Authorization'], exposeHeaders: ['Content-Length'], credentials: true, })); const storage = createStorage({ driver: cloudflareKVHTTPDriver({ accountId: process.env.CLOUDFLARE_ACCOUNT_ID || "", namespaceId: process.env.CLOUDFLARE_NAMESPACE_ID || "", apiToken: process.env.CLOUDFLARE_API_TOKEN || "", }), }); var kv: KVNamespace = { get: async (key: string) => { const value = await storage.getItemRaw(key); return value as string; }, put: async (key: string, value: string) => { await storage.setItem(key, value); }, delete: async (key: string) => { await storage.removeItem(key); } }; app.use('*', async (c, next) => { c.env.KV = kv; await next() }) const scriptPath = fileURLToPath(import.meta.url) const scriptDir = dirname(scriptPath) const rootDir = isDev ? dirname(scriptPath) : dirname(scriptDir) const currentDir = process.cwd(); let staticPath = path.relative(currentDir, rootDir); if (!isDev) { staticPath = path.relative(currentDir, path.join(rootDir, "dist")) } console.log('Script dir:', scriptDir) console.log('Root dir:', rootDir) console.log('Current dir:', currentDir); console.log('Relative path for static files:', staticPath || '.'); const createContext = (c: Context) => { const eventContext: RouteContext = { request: c.req.raw, functionPath: c.req.path, waitUntil: (promise: Promise) => { if (c.executionCtx?.waitUntil) { c.executionCtx.waitUntil(promise); } }, passThroughOnException: () => { if (c.executionCtx?.passThroughOnException) { c.executionCtx.passThroughOnException(); } }, next: async (input?: Request | string, init?: RequestInit) => { if (typeof input === 'string') { return fetch(input, init); } else if (input instanceof Request) { return fetch(input); } return new Response('Not Found', { status: 404 }); }, env: { ...c.env, ASSETS: { fetch: fetch.bind(globalThis) } }, params: c.req.param(), // 可以从 c.get() 获取数据,或者传入空对象 data: c.get('data') || {} }; return eventContext; } app.all('/api/*', async (c) => { try { const context = createContext(c); const path = c.req.path; // 根据路径匹配对应的处理函数 let response: Response; switch (path) { case '/api/account': response = await handleAccount(context); break; case '/api/login': response = await handleLogin(context); break; case '/api/setting': response = await handleSetting(context); break; default: if (path.startsWith('/api/github/')) { response = await handleGithub(context); break; } else if (path.startsWith('/api/hf/')) { response = await handleHF(context); break; } return c.json({ error: 'Route not found' }, 404); } return response; } catch (error) { return c.json({ error: (error as Error).message }, 500); } }) // 中间件配置 app.get('/*', serveStatic({ root: staticPath, rewriteRequestPath: (path) => { return path === '/' ? '/index.html' : path; }, onFound: async (path, c) => { console.log('Found:', path) }, onNotFound: async (path, c) => { console.log('Not Found:', path) } })) // 启动服务器 const port = parseInt(process.env.PORT || '8788') serve({ fetch: (request: Request, env) => app.fetch(request, { ...env, ...process.env }), port }, () => { console.log(`Server running at http://localhost:${port}`) }) export default app