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 authmaster
parent
a03ae5b62c
commit
f019e4114f
|
|
@ -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",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
35
server/db.ts
35
server/db.ts
|
|
@ -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
|
||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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`,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue