diff --git a/apps/api/src/db/client.ts b/apps/api/src/db/client.ts index 1d3c9dc..df718cc 100644 --- a/apps/api/src/db/client.ts +++ b/apps/api/src/db/client.ts @@ -1,20 +1,33 @@ -import { env } from 'node:process'; +import type { Logger } from 'drizzle-orm'; import { drizzle, PostgresJsDatabase } from 'drizzle-orm/postgres-js'; import { Context } from 'hono'; import postgres from 'postgres'; import { AppContext } from '@/index'; -const DATABASE_URL = env.INFISCAL_DATABASE_URL; +// Logs each SQL statement in non-prod (params omitted — they can hold PII). +class QueryLogger implements Logger { + logQuery(query: string): void { + console.log(`[db] ${query}`); + } +} -export const useDb = (ctx: Context) => { +export const useDb = (ctx: Context): PostgresJsDatabase => { const storedDb: PostgresJsDatabase | undefined = ctx.get('db'); if (storedDb) { return storedDb; } - const sql = postgres(DATABASE_URL); - const newDb = drizzle(sql); + const connectionString = ctx.env.HYPERDRIVE?.connectionString ?? ctx.env.INFISCAL_DATABASE_URL; + + const sql = postgres(connectionString, { + max: 5, + fetch_types: false, + }); + + const newDb = drizzle(sql, { + logger: ctx.env.NODE_ENV !== 'production' ? new QueryLogger() : undefined, + }); ctx.set('db', newDb); diff --git a/apps/api/worker-configuration.d.ts b/apps/api/worker-configuration.d.ts index 60cc3db..0500207 100644 --- a/apps/api/worker-configuration.d.ts +++ b/apps/api/worker-configuration.d.ts @@ -29,6 +29,7 @@ declare namespace Cloudflare { ASSETS_BUCKET: R2Bucket; WHITEBOARD_ASSETS_BUCKET: R2Bucket; API_RATE_LIMITER: RateLimit; + HYPERDRIVE?: Hyperdrive; } } interface Env extends Cloudflare.Env {} diff --git a/apps/api/wrangler.jsonc b/apps/api/wrangler.jsonc index 066f1c2..54a37ef 100644 --- a/apps/api/wrangler.jsonc +++ b/apps/api/wrangler.jsonc @@ -99,6 +99,9 @@ "bucket_name": "coderscreen-whiteboard", }, ], + "hyperdrive": [ + { "binding": "HYPERDRIVE", "id": "c205221f01db4e28bcc6ba8c2a1798a2" }, + ], "env": { "staging": { "name": "coderscreen-api-staging",