74 lines
2.2 KiB
TypeScript
74 lines
2.2 KiB
TypeScript
// server/utils/prisma.ts - Prisma 客户端初始化:使用 MariaDB adapter 并在开发热更新中复用连接池。
|
|
import { PrismaMariaDb } from "@prisma/adapter-mariadb";
|
|
import { PrismaClient } from "~~/app/generated/prisma/client";
|
|
|
|
const globalForPrisma = globalThis as unknown as {
|
|
prisma?: PrismaClient;
|
|
};
|
|
|
|
const databaseUrl = process.env.DATABASE_URL;
|
|
|
|
if (!databaseUrl) {
|
|
throw new Error("DATABASE_URL is required to initialize PrismaClient");
|
|
}
|
|
|
|
type MariaDbPoolConfig = Exclude<
|
|
ConstructorParameters<typeof PrismaMariaDb>[0],
|
|
string
|
|
>;
|
|
|
|
/** 从 DATABASE_URL 查询参数读取连接池配置,非法值回退到默认值 */
|
|
function getNumberParam(url: URL, name: string, fallback: number) {
|
|
const value = url.searchParams.get(name);
|
|
if (!value) {
|
|
return fallback;
|
|
}
|
|
|
|
const parsed = Number(value);
|
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
}
|
|
|
|
/** 将 DATABASE_URL 拆成 Prisma MariaDB adapter 需要的连接池配置 */
|
|
function createMariaDbConfig(urlString: string): MariaDbPoolConfig {
|
|
const url = new URL(urlString);
|
|
const database = decodeURIComponent(url.pathname.replace(/^\//, ""));
|
|
|
|
if (!url.hostname || !url.username || !database) {
|
|
throw new Error("DATABASE_URL must include host, user and database");
|
|
}
|
|
|
|
const port = url.port ? Number(url.port) : 3306;
|
|
|
|
if (!Number.isInteger(port) || port <= 0) {
|
|
throw new Error("DATABASE_URL port is invalid");
|
|
}
|
|
|
|
return {
|
|
host: url.hostname,
|
|
port,
|
|
user: decodeURIComponent(url.username),
|
|
password: decodeURIComponent(url.password),
|
|
database,
|
|
connectionLimit: getNumberParam(url, "connection_limit", 5),
|
|
acquireTimeout: getNumberParam(url, "pool_timeout", 30) * 1000,
|
|
connectTimeout: getNumberParam(url, "connect_timeout", 10) * 1000
|
|
};
|
|
}
|
|
|
|
const mariaDbConfig = createMariaDbConfig(databaseUrl);
|
|
const adapter = new PrismaMariaDb(mariaDbConfig, {
|
|
database: mariaDbConfig.database
|
|
});
|
|
|
|
/** Reuse PrismaClient during dev hot reloads so Nuxt does not create duplicate pools. */
|
|
export const prisma =
|
|
globalForPrisma.prisma ??
|
|
new PrismaClient({
|
|
adapter,
|
|
log: ["warn", "error"]
|
|
});
|
|
|
|
if (process.env.NODE_ENV !== "production") {
|
|
globalForPrisma.prisma = prisma;
|
|
}
|