From 3ce1bd1ce4be0e8663766959e18c16387f573fac Mon Sep 17 00:00:00 2001 From: katelya Date: Fri, 5 Sep 2025 16:21:41 +0800 Subject: [PATCH] Simplify D1 database access and add fallback to LocalStorage for Edge Runtime compatibility --- src/app/api/debug/env/route.ts | 40 ++++++++----------------------- src/app/api/test/simple/route.ts | 0 src/lib/d1.db.ts | 34 ++++++++------------------ src/lib/db.ts | 41 ++++++++++++++++++++++---------- 4 files changed, 48 insertions(+), 67 deletions(-) create mode 100644 src/app/api/test/simple/route.ts diff --git a/src/app/api/debug/env/route.ts b/src/app/api/debug/env/route.ts index 7d61e96..0ffed83 100644 --- a/src/app/api/debug/env/route.ts +++ b/src/app/api/debug/env/route.ts @@ -1,42 +1,22 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { NextRequest, NextResponse } from 'next/server'; +import { NextResponse } from 'next/server'; export const runtime = 'edge'; -export async function GET(request: NextRequest) { +export async function GET() { try { - const debugInfo = { + return NextResponse.json({ + status: 'ok', timestamp: new Date().toISOString(), - environment: { - NODE_ENV: process.env.NODE_ENV, - NEXT_PUBLIC_STORAGE_TYPE: process.env.NEXT_PUBLIC_STORAGE_TYPE, - USERNAME: process.env.USERNAME ? '***' : undefined, - PASSWORD: process.env.PASSWORD ? '***' : undefined, - }, - globalThis: { - hasDB: typeof globalThis !== 'undefined' && !!(globalThis as any).DB, - hasProcess: typeof globalThis !== 'undefined' && !!(globalThis as any).process, - hasCloudflare: typeof globalThis !== 'undefined' && !!(globalThis as any).cloudflare, - }, - processEnv: { - hasDB: !!(process.env as any).DB, - keys: Object.keys(process.env).filter(key => - key.startsWith('DB') || - key.startsWith('NEXT_') || - key.startsWith('CF_') || - key.startsWith('CLOUDFLARE_') - ), - }, runtime: 'edge', - userAgent: request.headers.get('user-agent')?.slice(0, 100), - }; - - return NextResponse.json(debugInfo); + storageType: process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage', + hasDB: !!(globalThis as any).DB, + nodeEnv: process.env.NODE_ENV + }); } catch (error) { return NextResponse.json({ - error: 'Debug info collection failed', - message: error instanceof Error ? error.message : 'Unknown error', - timestamp: new Date().toISOString() + error: 'Debug failed', + message: error instanceof Error ? error.message : 'Unknown error' }, { status: 500 }); } } diff --git a/src/app/api/test/simple/route.ts b/src/app/api/test/simple/route.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/d1.db.ts b/src/lib/d1.db.ts index a65b4c3..8ce77ff 100644 --- a/src/lib/d1.db.ts +++ b/src/lib/d1.db.ts @@ -39,35 +39,21 @@ interface D1ExecResult { // 获取全局D1数据库实例 function getD1Database(): D1Database { - // 尝试多种方式访问 D1 数据库 - - // 1. Cloudflare Pages Functions 中通过 env.DB 访问 - if (typeof globalThis !== 'undefined' && (globalThis as any).DB) { - return (globalThis as any).DB as D1Database; + // 在 Cloudflare Pages 环境中,DB 通过全局绑定可用 + if (typeof globalThis !== 'undefined') { + // 尝试直接访问全局 DB + const globalDB = (globalThis as any).DB; + if (globalDB) { + return globalDB as D1Database; + } } - // 2. 通过 process.env.DB 访问(用于本地开发) - if ((process.env as any).DB) { + // 回退到 process.env(用于本地开发) + if (process.env.DB) { return (process.env as any).DB as D1Database; } - // 3. 通过 globalThis.process.env.DB 访问 - if (typeof globalThis !== 'undefined' && (globalThis as any).process?.env?.DB) { - return (globalThis as any).process.env.DB as D1Database; - } - - // 4. 检查 Cloudflare Workers 环境变量 - if (typeof globalThis !== 'undefined' && (globalThis as any).cloudflare?.env?.DB) { - return (globalThis as any).cloudflare.env.DB as D1Database; - } - - // 最后检查是否在测试环境中,如果是则抛出更详细的错误 - const isDev = process.env.NODE_ENV === 'development'; - const errorMessage = isDev - ? 'D1 database not available in development. Using D1 requires deployment to Cloudflare Pages.' - : 'D1 database binding not configured. Check your Cloudflare Pages settings.'; - - throw new Error(errorMessage); + throw new Error('D1 database not available'); } export class D1Storage implements IStorage { diff --git a/src/lib/db.ts b/src/lib/db.ts index 3df2046..ff2a5e1 100644 --- a/src/lib/db.ts +++ b/src/lib/db.ts @@ -20,19 +20,34 @@ const STORAGE_TYPE = // 创建存储实例 function createStorage(): IStorage { - switch (STORAGE_TYPE) { - case 'redis': - return new RedisStorage(); - case 'kvrocks': - return new KvrocksStorage(); - case 'upstash': - return new UpstashRedisStorage(); - case 'd1': - return new D1Storage(); - case 'localstorage': - default: - // 使用 LocalStorage 实现,适用于本地开发和简单部署 - return new LocalStorage(); + const storageType = STORAGE_TYPE; + + try { + switch (storageType) { + case 'redis': + return new RedisStorage(); + case 'kvrocks': + return new KvrocksStorage(); + case 'upstash': + return new UpstashRedisStorage(); + case 'd1': + // 对于 d1,先检查是否可用 + if (typeof globalThis !== 'undefined' && (globalThis as any).DB) { + return new D1Storage(); + } else if (process.env.DB) { + return new D1Storage(); + } else { + // D1 不可用,回退到 LocalStorage + return new LocalStorage(); + } + case 'localstorage': + default: + // 使用 LocalStorage 实现,适用于本地开发和简单部署 + return new LocalStorage(); + } + } catch (error) { + // 创建存储失败,回退到 LocalStorage + return new LocalStorage(); } }