Simplify D1 database access and add fallback to LocalStorage for Edge Runtime compatibility

This commit is contained in:
katelya
2025-09-05 16:21:41 +08:00
parent 62072a5558
commit 3ce1bd1ce4
4 changed files with 48 additions and 67 deletions
+10 -30
View File
@@ -1,42 +1,22 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
import { NextRequest, NextResponse } from 'next/server'; import { NextResponse } from 'next/server';
export const runtime = 'edge'; export const runtime = 'edge';
export async function GET(request: NextRequest) { export async function GET() {
try { try {
const debugInfo = { return NextResponse.json({
status: 'ok',
timestamp: new Date().toISOString(), 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', runtime: 'edge',
userAgent: request.headers.get('user-agent')?.slice(0, 100), storageType: process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage',
}; hasDB: !!(globalThis as any).DB,
nodeEnv: process.env.NODE_ENV
return NextResponse.json(debugInfo); });
} catch (error) { } catch (error) {
return NextResponse.json({ return NextResponse.json({
error: 'Debug info collection failed', error: 'Debug failed',
message: error instanceof Error ? error.message : 'Unknown error', message: error instanceof Error ? error.message : 'Unknown error'
timestamp: new Date().toISOString()
}, { status: 500 }); }, { status: 500 });
} }
} }
View File
+10 -24
View File
@@ -39,35 +39,21 @@ interface D1ExecResult {
// 获取全局D1数据库实例 // 获取全局D1数据库实例
function getD1Database(): D1Database { function getD1Database(): D1Database {
// 尝试多种方式访问 D1 数据库 // 在 Cloudflare Pages 环境中,DB 通过全局绑定可用
if (typeof globalThis !== 'undefined') {
// 1. Cloudflare Pages Functions 中通过 env.DB 访问 // 尝试直接访问全局 DB
if (typeof globalThis !== 'undefined' && (globalThis as any).DB) { const globalDB = (globalThis as any).DB;
return (globalThis as any).DB as D1Database; if (globalDB) {
return globalDB as D1Database;
}
} }
// 2. 通过 process.env.DB 访问(用于本地开发) // 回退到 process.env(用于本地开发)
if ((process.env as any).DB) { if (process.env.DB) {
return (process.env as any).DB as D1Database; return (process.env as any).DB as D1Database;
} }
// 3. 通过 globalThis.process.env.DB 访问 throw new Error('D1 database not available');
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);
} }
export class D1Storage implements IStorage { export class D1Storage implements IStorage {
+28 -13
View File
@@ -20,19 +20,34 @@ const STORAGE_TYPE =
// 创建存储实例 // 创建存储实例
function createStorage(): IStorage { function createStorage(): IStorage {
switch (STORAGE_TYPE) { const storageType = STORAGE_TYPE;
case 'redis':
return new RedisStorage(); try {
case 'kvrocks': switch (storageType) {
return new KvrocksStorage(); case 'redis':
case 'upstash': return new RedisStorage();
return new UpstashRedisStorage(); case 'kvrocks':
case 'd1': return new KvrocksStorage();
return new D1Storage(); case 'upstash':
case 'localstorage': return new UpstashRedisStorage();
default: case 'd1':
// 使用 LocalStorage 实现,适用于本地开发和简单部署 // 对于 d1,先检查是否可用
return new LocalStorage(); 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();
} }
} }