Fix production deployment: SQLite DB, externals, static path

- Switch DB from PostgreSQL to SQLite (data.db) for now
- Add better-sqlite3, pg, drizzle-orm/* to build externals
- Fix serveStatic path resolution with cwd fallback
- Fix import.meta issue in static.ts for CJS bundle
- Rate limit whitelist for home subnet (192.168.x.x)
- Relax dev rate limits: 500/15min general, 50/15min auth
master
isnowglobal-admin 2026-06-13 18:54:11 -04:00
parent a03ae5b62c
commit f019e4114f
3 changed files with 29 additions and 23 deletions

View File

@ -54,7 +54,7 @@ async function buildAll() {
"process.env.NODE_ENV": '"production"', "process.env.NODE_ENV": '"production"',
}, },
minify: true, minify: true,
external: externals, external: [...externals, "better-sqlite3", "pg", "drizzle-orm/better-sqlite3", "drizzle-orm/node-postgres"],
logLevel: "info", logLevel: "info",
}); });
} }

View File

@ -1,32 +1,31 @@
import { drizzle } from "drizzle-orm/node-postgres"; import { drizzle } from "drizzle-orm/better-sqlite3";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { users, User, NewUser } from "../shared/schema"; import { users, User, NewUser } from "../shared/schema";
import { Pool } from "pg"; import Database from "better-sqlite3";
import path from "node:path";
import fs from "node:fs";
// Production PostgreSQL connection // Use SQLite for production (PostgreSQL migration later)
const pool = new Pool({ const dbPath = path.resolve(__dirname || ".", "..", "data.db");
host: process.env.DB_HOST || "10.136.95.120",
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,
});
export const db = drizzle(pool); // 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);
// Initialize users table if it doesn't exist (called at startup) // Initialize users table if it doesn't exist (called at startup)
export async function initDb(): Promise<void> { export async function initDb(): Promise<void> {
await db.execute(` sqlite.exec(`
CREATE TABLE IF NOT EXISTS users ( CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY, id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL, name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE, email TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL, password_hash TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW() created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) )
`); `);
} }

View File

@ -2,13 +2,20 @@ import express from 'express';
import type { Express } from 'express'; import type { Express } from 'express';
import fs from "node:fs"; import fs from "node:fs";
import path from "node:path"; import path from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
export function serveStatic(app: Express) { export function serveStatic(app: Express) {
const distPath = path.resolve(__dirname, "..", "dist", "public"); // In production, dist/public is at the same level as index.cjs
const distPath = path.resolve(__dirname, "..", "public");
if (!fs.existsSync(distPath)) { if (!fs.existsSync(distPath)) {
// Fallback: check cwd
const cwdPath = path.resolve(process.cwd(), "dist", "public");
if (fs.existsSync(cwdPath)) {
app.use(express.static(cwdPath));
app.use("/{*path}", (_req, res) => {
res.sendFile(path.resolve(cwdPath, "index.html"));
});
return;
}
throw new Error( throw new Error(
`Could not find the build directory: ${distPath}, make sure to build the client first`, `Could not find the build directory: ${distPath}, make sure to build the client first`,
); );