diff --git a/src/app/api/debug/env/route.ts b/src/app/api/debug/env/route.ts new file mode 100644 index 0000000..7d61e96 --- /dev/null +++ b/src/app/api/debug/env/route.ts @@ -0,0 +1,42 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { NextRequest, NextResponse } from 'next/server'; + +export const runtime = 'edge'; + +export async function GET(request: NextRequest) { + try { + const debugInfo = { + 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); + } catch (error) { + return NextResponse.json({ + error: 'Debug info collection failed', + message: error instanceof Error ? error.message : 'Unknown error', + timestamp: new Date().toISOString() + }, { status: 500 }); + } +} diff --git a/src/lib/d1.db.ts b/src/lib/d1.db.ts index 172785e..a65b4c3 100644 --- a/src/lib/d1.db.ts +++ b/src/lib/d1.db.ts @@ -39,22 +39,35 @@ interface D1ExecResult { // 获取全局D1数据库实例 function getD1Database(): D1Database { - // 在 Cloudflare Pages/Workers 环境中,DB 是全局变量 + // 尝试多种方式访问 D1 数据库 + + // 1. Cloudflare Pages Functions 中通过 env.DB 访问 if (typeof globalThis !== 'undefined' && (globalThis as any).DB) { return (globalThis as any).DB as D1Database; } - // 回退到 process.env(用于本地开发) + // 2. 通过 process.env.DB 访问(用于本地开发) if ((process.env as any).DB) { return (process.env as any).DB as D1Database; } - // 最后尝试从 globalThis.process.env + // 3. 通过 globalThis.process.env.DB 访问 if (typeof globalThis !== 'undefined' && (globalThis as any).process?.env?.DB) { return (globalThis as any).process.env.DB as D1Database; } - throw new Error('D1 database not available. Make sure DB binding is configured.'); + // 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); } export class D1Storage implements IStorage { diff --git a/wrangler.toml b/wrangler.toml index 77695a3..aee689e 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -1,14 +1,19 @@ name = "katelyatv" compatibility_date = "2024-09-01" compatibility_flags = ["nodejs_compat"] +pages_build_output_dir = ".vercel/output/static" -# 默认开发环境数据库配置 -[[d1_databases]] +# 生产环境 D1 数据库配置 +[[env.production.d1_databases]] binding = "DB" database_name = "katelyatv-db" database_id = "6d580637-1f87-4ddf-8b4d-3d97254b4c33" -[env.production] +# 预览环境也使用相同的数据库 +[[env.preview.d1_databases]] +binding = "DB" +database_name = "katelyatv-db" +database_id = "6d580637-1f87-4ddf-8b4d-3d97254b4c33" name = "katelyatv" [env.production.vars]