mirror of
https://github.com/linsa-io/linsa.git
synced 2026-01-12 12:20:23 +01:00
.
This commit is contained in:
75
packages/web/src/db/connection.ts
Normal file
75
packages/web/src/db/connection.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import postgres from "postgres"
|
||||
import { drizzle } from "drizzle-orm/postgres-js"
|
||||
import * as schema from "./schema"
|
||||
|
||||
type Hyperdrive = {
|
||||
connectionString: string
|
||||
}
|
||||
|
||||
type CloudflareEnv = {
|
||||
DATABASE_URL?: string
|
||||
HYPERDRIVE?: Hyperdrive
|
||||
}
|
||||
|
||||
// Note: NO caching - Cloudflare Workers don't allow sharing I/O objects across requests
|
||||
|
||||
// Get the database connection string, preferring DATABASE_URL over Hyperdrive
|
||||
const getConnectionString = (env?: CloudflareEnv): string => {
|
||||
// Prefer DATABASE_URL if set (direct connection, bypasses Hyperdrive)
|
||||
if (env?.DATABASE_URL) {
|
||||
return env.DATABASE_URL
|
||||
}
|
||||
|
||||
// Fall back to Hyperdrive if available
|
||||
if (env?.HYPERDRIVE?.connectionString) {
|
||||
return env.HYPERDRIVE.connectionString
|
||||
}
|
||||
|
||||
// Fall back to process.env (local dev)
|
||||
if (process.env.DATABASE_URL) {
|
||||
return process.env.DATABASE_URL
|
||||
}
|
||||
|
||||
throw new Error("No database connection available. Set DATABASE_URL or configure Hyperdrive.")
|
||||
}
|
||||
|
||||
// Helper to get Cloudflare env from server context
|
||||
const getCloudflareEnv = (): CloudflareEnv | undefined => {
|
||||
try {
|
||||
const { getServerContext } = require("@tanstack/react-start/server") as {
|
||||
getServerContext: () => { cloudflare?: { env?: CloudflareEnv } } | null
|
||||
}
|
||||
return getServerContext()?.cloudflare?.env
|
||||
} catch {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience function to get db using server context
|
||||
export const db = () => getDb(getConnectionString(getCloudflareEnv()))
|
||||
export const authDb = () => getAuthDb(getConnectionString(getCloudflareEnv()))
|
||||
|
||||
// Main db with snake_case casing for app tables (chat_threads, chat_messages)
|
||||
export const getDb = (databaseUrlOrHyperdrive: string | Hyperdrive) => {
|
||||
const connectionString =
|
||||
typeof databaseUrlOrHyperdrive === "string"
|
||||
? databaseUrlOrHyperdrive
|
||||
: databaseUrlOrHyperdrive.connectionString
|
||||
|
||||
// Create fresh connection per request for Cloudflare Workers compatibility
|
||||
const sql = postgres(connectionString, { prepare: false })
|
||||
return drizzle(sql, { schema, casing: "snake_case" })
|
||||
}
|
||||
|
||||
// Auth db WITHOUT casing transform for better-auth tables (users, sessions, etc.)
|
||||
// better-auth uses camelCase columns and manages its own naming
|
||||
export const getAuthDb = (databaseUrlOrHyperdrive: string | Hyperdrive) => {
|
||||
const connectionString =
|
||||
typeof databaseUrlOrHyperdrive === "string"
|
||||
? databaseUrlOrHyperdrive
|
||||
: databaseUrlOrHyperdrive.connectionString
|
||||
|
||||
// Create fresh connection per request for Cloudflare Workers compatibility
|
||||
const sql = postgres(connectionString, { prepare: false })
|
||||
return drizzle(sql, { schema })
|
||||
}
|
||||
Reference in New Issue
Block a user