Simplify D1 database access and add fallback to LocalStorage for Edge Runtime compatibility
This commit is contained in:
Vendored
+10
-30
@@ -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 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-24
@@ -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
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user