Adds database connection logic
This commit is contained in:
parent
fe0cd10c36
commit
653f1f007b
18
docker-compose.yml
Normal file
18
docker-compose.yml
Normal file
@ -0,0 +1,18 @@
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:17
|
||||
container_name: molci-db
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- ./server/.env
|
||||
environment:
|
||||
POSTGRES_USER: ${DB_USER}
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||
POSTGRES_DB: ${DB_NAME}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
34
server/biome.json
Normal file
34
server/biome.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
|
||||
"vcs": {
|
||||
"enabled": false,
|
||||
"clientKind": "git",
|
||||
"useIgnoreFile": false
|
||||
},
|
||||
"files": {
|
||||
"ignoreUnknown": false
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
"indentStyle": "tab"
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true
|
||||
}
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
"quoteStyle": "double"
|
||||
}
|
||||
},
|
||||
"assist": {
|
||||
"enabled": true,
|
||||
"actions": {
|
||||
"source": {
|
||||
"organizeImports": "on"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,33 @@
|
||||
{
|
||||
"name": "server",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"packageManager": "pnpm@10.15.0"
|
||||
"name": "server",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "tsx --watch --env-file .env src/index.ts",
|
||||
"watch": "tsx watch src/index.ts",
|
||||
"check": "tsc --noEmit",
|
||||
"build": "tsc",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"packageManager": "pnpm@10.15.0",
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.2.0",
|
||||
"@tsconfig/strictest": "^2.0.5",
|
||||
"@types/express": "^5.0.3",
|
||||
"@types/jest": "^30.0.0",
|
||||
"@types/node": "^24.3.0",
|
||||
"@types/pg": "^8.15.5",
|
||||
"jest": "^30.0.5",
|
||||
"ts-jest": "^29.4.1",
|
||||
"tsx": "^4.20.4",
|
||||
"typescript": "^5.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"express": "^5.1.0",
|
||||
"pg": "^8.16.3"
|
||||
}
|
||||
}
|
||||
|
||||
4020
server/pnpm-lock.yaml
generated
Normal file
4020
server/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
30
server/src/config/db.ts
Normal file
30
server/src/config/db.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { Pool } from "pg";
|
||||
import { config } from "./env";
|
||||
|
||||
let pool: Pool;
|
||||
|
||||
const { DB_USER, DB_PASSWORD, DB_NAME } = config;
|
||||
|
||||
if (!DB_USER || !DB_PASSWORD || !DB_NAME) {
|
||||
throw new Error("DB_USER, DB_PASSWORD, and DB_NAME must be set");
|
||||
}
|
||||
|
||||
pool = new Pool({
|
||||
user: config.DB_USER,
|
||||
host: config.DB_HOST,
|
||||
database: config.DB_NAME,
|
||||
password: config.DB_PASSWORD,
|
||||
port: config.DB_PORT,
|
||||
});
|
||||
|
||||
const connectDB = async () => {
|
||||
try {
|
||||
await pool.connect();
|
||||
console.log("PostgreSQL DATABASE connected");
|
||||
} catch (err) {
|
||||
const error = err as Error;
|
||||
console.error("DB connection error:", error.stack || error.message);
|
||||
}
|
||||
};
|
||||
|
||||
export { pool, connectDB };
|
||||
33
server/src/config/env.ts
Normal file
33
server/src/config/env.ts
Normal file
@ -0,0 +1,33 @@
|
||||
type EnvMode = "development" | "production" | "test";
|
||||
|
||||
interface ProcessEnv {
|
||||
NODE_ENV?: EnvMode;
|
||||
APP_PORT?: string;
|
||||
DB_USER: string;
|
||||
DB_PASSWORD: string;
|
||||
DB_HOST?: string;
|
||||
DB_NAME: string;
|
||||
DB_PORT?: string;
|
||||
}
|
||||
|
||||
const env = process.env as unknown as ProcessEnv;
|
||||
|
||||
function requiredEnv(key: keyof ProcessEnv): string {
|
||||
const value = env[key];
|
||||
if (!value) {
|
||||
throw new Error(`Missing required environment variable: ${key}`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export const config = {
|
||||
NODE_ENV: env.NODE_ENV ?? "development",
|
||||
APP_PORT: env.APP_PORT ? Number(env.APP_PORT) : 3000,
|
||||
DB_HOST: env.DB_HOST ?? "localhost",
|
||||
DB_NAME: requiredEnv("DB_NAME"),
|
||||
DB_USER: requiredEnv("DB_USER"),
|
||||
DB_PASSWORD: requiredEnv("DB_PASSWORD"),
|
||||
DB_PORT: env.DB_PORT ? Number(env.DB_PORT) : 5432,
|
||||
};
|
||||
|
||||
export const isProduction = config.NODE_ENV === "production";
|
||||
26
server/src/index.ts
Normal file
26
server/src/index.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import express from "express";
|
||||
import { pool } from "./config/db";
|
||||
import { config, isProduction } from "./config/env";
|
||||
|
||||
const app = express();
|
||||
const PORT = config.APP_PORT;
|
||||
|
||||
app.use(express.json());
|
||||
|
||||
app.get("/ping", async (_req, res) => {
|
||||
try {
|
||||
const result = await pool.query("SELECT NOW()");
|
||||
res.json({ success: true, time: result.rows[0].now });
|
||||
} catch (error) {
|
||||
console.error("Database error:", error);
|
||||
res
|
||||
.status(500)
|
||||
.json({ success: false, error: "Database connection failed" });
|
||||
}
|
||||
});
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(
|
||||
`Server running in ${isProduction ? "production" : "development"} mode on port ${PORT}`,
|
||||
);
|
||||
});
|
||||
29
server/tsconfig.json
Normal file
29
server/tsconfig.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"extends": "@tsconfig/strictest/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"rootDir": "src",
|
||||
"outDir": "dist",
|
||||
"strict": true,
|
||||
"allowUnusedLabels": false,
|
||||
"allowUnreachableCode": false,
|
||||
"exactOptionalPropertyTypes": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
"noImplicitReturns": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "dist"],
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"_version": "2.0.0"
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user