Next.js 14 + Drizzle/PostgreSQL + SSE realtime sync — highlight, freehand, comment, bookmark + ฟีเจอร์ต่อยอด F1–F19 (edit/move, undo/redo, shapes, redaction, export PDF/CSV, reply, resolve, search, summary, textbox, stamp, version history) Co-Authored-By: Claude Code <noreply@anthropic.com>
29 lines
1.5 KiB
TypeScript
29 lines
1.5 KiB
TypeScript
import { drizzle } from "drizzle-orm/postgres-js";
|
|
import postgres from "postgres";
|
|
|
|
import * as schema from "./schema";
|
|
|
|
// DATABASE_URL ชี้ที่ PostgreSQL container `judes-note-db` (PLAN.md §0 A7)
|
|
// prepare:false เพราะ Server Actions ยิง connection สั้น ๆ พร้อมกันได้ (CLAUDE.md invariant #11)
|
|
//
|
|
// **เก็บ client บน globalThis** — Next dev hot-reload re-evaluate module นี้ทุกครั้ง
|
|
// ถ้าสร้าง postgres() ใน module scope ตรง ๆ pool เก่า (default 10 connections) จะไม่
|
|
// ถูกปิดและสะสมจนชน max_connections ของ Postgres ("sorry, too many clients already")
|
|
// — pattern เดียวกับ lib/annotate-events.ts (rules/realtime.md)
|
|
const globalForDb = globalThis as unknown as {
|
|
pgClient?: ReturnType<typeof postgres>;
|
|
};
|
|
|
|
// FIX-9: เอา non-null ! ออก — ไม่ตั้ง env ต้อง error ชัดเจน
|
|
// ไม่ใช่ปล่อย undefined ไหลเข้า postgres() จนพังในทางที่หาสาเหตุยาก
|
|
const databaseUrl = process.env.DATABASE_URL;
|
|
if (!databaseUrl) {
|
|
throw new Error("ตั้งค่า DATABASE_URL ก่อน (container judes-note-db — PLAN.md §0 A7)");
|
|
}
|
|
|
|
const client = globalForDb.pgClient ?? postgres(databaseUrl, { prepare: false });
|
|
if (process.env.NODE_ENV !== "production") {
|
|
globalForDb.pgClient = client;
|
|
}
|
|
|
|
export const db = drizzle(client, { schema });
|