From 1877bb7aa7af87af841cd67e9a536c4f1aa17ba2 Mon Sep 17 00:00:00 2001 From: isnowglobal-admin Date: Sat, 13 Jun 2026 19:28:48 -0400 Subject: [PATCH] Fix: PostgreSQL setup on production droplet - Revert schema to pgTable/serial (matches PostgreSQL) - db.ts switched back to node-postgres driver - PostgreSQL 16 installed and running on 142.93.245.235 - Database: gammanexus, User: gn_admin - Same schema across local and production --- server/db.ts | 39 ++++++++++++++++++--------------------- shared/schema.ts | 12 ++++++------ 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/server/db.ts b/server/db.ts index dfe6dba..e7a900b 100644 --- a/server/db.ts +++ b/server/db.ts @@ -1,35 +1,32 @@ -import { drizzle } from "drizzle-orm/better-sqlite3"; +import { drizzle } from "drizzle-orm/node-postgres"; import { eq } from "drizzle-orm"; import { users, User, NewUser } from "../shared/schema"; -import Database from "better-sqlite3"; -import path from "node:path"; -import fs from "node:fs"; -import { fileURLToPath } from "node:url"; +import { Pool } from "pg"; -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); +// PostgreSQL connection (local on production droplet) +const pool = new Pool({ + host: process.env.DB_HOST || "127.0.0.1", + port: parseInt(process.env.DB_PORT || "5432"), + user: process.env.DB_USER || "gn_admin", + password: process.env.DB_PASSWORD || "", + database: process.env.DB_NAME || "gammanexus", + ssl: (process.env.DB_SSL === "true" && process.env.NODE_ENV === "production") ? { rejectUnauthorized: false } : false, + max: 20, + idleTimeoutMillis: 30000, + connectionTimeoutMillis: 5000, +}); -// Use SQLite for production (PostgreSQL migration later) -const dbPath = path.resolve(__dirname, "..", "data.db"); - -// Ensure data directory exists -const dbDir = path.dirname(dbPath); -if (!fs.existsSync(dbDir)) { - fs.mkdirSync(dbDir, { recursive: true }); -} - -const sqlite = new Database(dbPath); -export const db = drizzle(sqlite); +export const db = drizzle(pool); // Initialize users table if it doesn't exist (called at startup) export async function initDb(): Promise { - sqlite.exec(` + await db.execute(` CREATE TABLE IF NOT EXISTS users ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + id SERIAL PRIMARY KEY, name TEXT NOT NULL, email TEXT NOT NULL UNIQUE, password_hash TEXT NOT NULL, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW() ) `); } diff --git a/shared/schema.ts b/shared/schema.ts index f3c2dd9..5d129aa 100644 --- a/shared/schema.ts +++ b/shared/schema.ts @@ -1,20 +1,20 @@ // GammaDesk shared data model // ORATS-style options analytics types + Drizzle tables for auth. -// Database: SQLite (PostgreSQL migration planned later) +// Database: PostgreSQL import { z } from "zod"; -import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core"; +import { pgTable, text, serial, timestamp } from "drizzle-orm/pg-core"; // --------------------------------------------------------------------------- -// Auth - Users table (Drizzle + SQLite) +// Auth - Users table (Drizzle + PostgreSQL) // --------------------------------------------------------------------------- -export const users = sqliteTable("users", { - id: integer("id").primaryKey({ autoIncrement: true }), +export const users = pgTable("users", { + id: serial("id").primaryKey(), name: text("name").notNull(), email: text("email").notNull().unique(), passwordHash: text("password_hash").notNull(), - createdAt: text("created_at").default(new Date().toISOString()), + createdAt: timestamp("created_at", { mode: "date" }).defaultNow().notNull(), }); export type User = typeof users.$inferSelect;