import path from "node:path" import { fileURLToPath, pathToFileURL } from "node:url" import { PrismaClient } from "@prisma/client" declare global { var prisma: PrismaClient | undefined } // Resolve a robust DATABASE_URL for all runtimes (prod/dev) const PROJECT_ROOT = process.cwd() const PROJECT_ROOT_URL = (() => { const baseHref = pathToFileURL(PROJECT_ROOT).href return new URL(baseHref.endsWith("/") ? baseHref : `${baseHref}/`) })() function resolveFileUrl(url: string) { if (!url.startsWith("file:")) { return url } const filePath = url.slice("file:".length) if (filePath.startsWith("./") || filePath.startsWith("../")) { const normalized = path.normalize(filePath) const targetUrl = new URL(normalized, PROJECT_ROOT_URL) const absolutePath = fileURLToPath(targetUrl) if (!absolutePath.startsWith(PROJECT_ROOT)) { throw new Error(`DATABASE_URL path escapes project directory: ${filePath}`) } return `file:${absolutePath}` } if (!filePath.startsWith("/")) { return resolveFileUrl(`file:./${filePath}`) } return url } const resolvedDatabaseUrl = (() => { const envUrl = process.env.DATABASE_URL?.trim() if (envUrl && envUrl.length > 0) return resolveFileUrl(envUrl) // Fallbacks by environment to ensure correctness in containers if (process.env.NODE_ENV === "production") { return "file:/app/data/db.sqlite" } // In development, prefer a dedicated dev DB file return resolveFileUrl("file:./prisma/db.dev.sqlite") })() export const prisma = global.prisma ?? new PrismaClient({ datasources: { db: { url: resolvedDatabaseUrl } } }) if (process.env.NODE_ENV !== "production") { global.prisma = prisma } if (process.env.NODE_ENV !== "production") { // Helps detect mismatched DB path during dev server bootstrap // eslint-disable-next-line no-console console.log("[prisma] Using database:", resolvedDatabaseUrl) }