import path from "node:path" import { PrismaBetterSqlite3 } from "@prisma/adapter-better-sqlite3" import { PrismaClient } from "@/generated/prisma/client" type PrismaClientInstance = InstanceType type TransactionCallback = Extract< Parameters[0], (tx: PrismaClientInstance) => Promise > export type PrismaTransactionClient = TransactionCallback extends (tx: infer Client) => Promise ? Client : never export type PrismaDelegateClient = PrismaClientInstance declare global { var prisma: PrismaClientInstance | undefined } // Resolve a robust DATABASE_URL for all runtimes (prod/dev) const PROJECT_ROOT = process.cwd() const PRISMA_DIR = path.join(PROJECT_ROOT, "prisma") function resolveFileUrl(url: string) { if (!url.startsWith("file:")) { return url } const filePath = url.slice("file:".length) if (filePath.startsWith("//")) { return url } if (path.isAbsolute(filePath)) { return `file:${path.normalize(filePath)}` } const normalized = path.normalize(filePath) const prismaPrefix = `prisma${path.sep}` const relativeToPrisma = normalized.startsWith(prismaPrefix) ? normalized.slice(prismaPrefix.length) : normalized const absolutePath = path.resolve(PRISMA_DIR, relativeToPrisma) if (!absolutePath.startsWith(PROJECT_ROOT)) { throw new Error(`DATABASE_URL path escapes project directory: ${filePath}`) } return `file:${absolutePath}` } function normalizeDatasourceUrl(envUrl?: string | null) { const trimmed = envUrl?.trim() if (trimmed) { return resolveFileUrl(trimmed) } if (process.env.NODE_ENV === "production") { return "file:/app/data/db.sqlite" } return resolveFileUrl("file:./db.dev.sqlite") } const resolvedDatabaseUrl = normalizeDatasourceUrl(process.env.DATABASE_URL) process.env.DATABASE_URL = resolvedDatabaseUrl const sqliteAdapter = new PrismaBetterSqlite3({ url: resolvedDatabaseUrl, }) export const prisma = global.prisma ?? new PrismaClient({ adapter: sqliteAdapter }) if (process.env.NODE_ENV !== "production") { global.prisma = prisma } if (process.env.NODE_ENV !== "production") { // Helps detect mismatched DB path during dev server bootstrap console.log("[prisma] Using database:", resolvedDatabaseUrl) } export * from "@/generated/prisma/client" type PrismaKnownErrorLike = { code?: string meta?: Record message?: string } export function asPrismaKnownError(error: unknown): PrismaKnownErrorLike | null { if (!error || typeof error !== "object") { return null } const candidate = error as PrismaKnownErrorLike if (typeof candidate.code !== "string") { return null } return candidate }