chore: document and standardize hosts/ports across apps

This commit is contained in:
2025-09-10 01:21:15 +05:30
parent 701ff61214
commit 70cfff90ce
13 changed files with 218 additions and 42 deletions

View File

@@ -45,6 +45,9 @@ cd apps/SeleniumService
python3 agent.py
```
## 📖 Developer Documentation
- [Development Hosts & Ports](docs/ports.md) — which app runs on which host/port
## This in a Turborepo. What's inside?

View File

@@ -1,6 +1,7 @@
HOST=localhost
NODE_ENV="development"
HOST=0.0.0.0
PORT=5000
FRONTEND_URL=http://localhost:3000
FRONTEND_URLS=http://localhost:3000,http://192.168.1.8:3000
JWT_SECRET = 'dentalsecret'
DB_HOST=localhost
DB_USER=postgres

View File

@@ -9,7 +9,11 @@ import dotenv from "dotenv";
import { startBackupCron } from "./cron/backupCheck";
dotenv.config();
const FRONTEND_URL = process.env.FRONTEND_URL;
const NODE_ENV = (
process.env.NODE_ENV ||
process.env.ENV ||
"development"
).toLowerCase();
const app = express();
@@ -17,9 +21,48 @@ app.use(express.json());
app.use(express.urlencoded({ extended: true })); // For form data
app.use(apiLogger);
// --- CORS handling (flexible for dev and strict for prod) ---
/**
* FRONTEND_URLS env value: comma-separated allowed origins
* Example: FRONTEND_URLS=http://localhost:3000,http://192.168.1.8:3000
*/
const rawFrontendUrls =
process.env.FRONTEND_URLS || process.env.FRONTEND_URL || "";
const FRONTEND_URLS = rawFrontendUrls
.split(",")
.map((s) => s.trim())
.filter(Boolean);
// helper to see if origin is allowed
function isOriginAllowed(origin?: string | null) {
if (!origin) return true; // allow non-browser clients (curl/postman)
if (NODE_ENV !== "production") {
// Dev mode: allow localhost origins automatically
if (
origin.startsWith("http://localhost") ||
origin.startsWith("http://127.0.0.1")
)
return true;
// allow explicit FRONTEND_URLS if provided
if (FRONTEND_URLS.includes(origin)) return true;
// optionally allow the server's LAN IP if FRONTEND_LAN_IP is provided
const lanIp = process.env.FRONTEND_LAN_IP;
if (lanIp && origin.startsWith(`http://${lanIp}`)) return true;
// fallback: deny if not matched
return false;
}
// production: strict whitelist — must match configured FRONTEND_URLS exactly
return FRONTEND_URLS.includes(origin);
}
app.use(
cors({
origin: FRONTEND_URL,
origin: (origin, cb) => {
if (isOriginAllowed(origin)) return cb(null, true);
cb(new Error(`CORS: Origin ${origin} not allowed`));
},
methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
allowedHeaders: ["Content-Type", "Authorization"],
credentials: true,

View File

@@ -3,11 +3,18 @@ import dotenv from "dotenv";
dotenv.config();
const HOST = process.env.HOST;
const PORT = process.env.PORT;
const NODE_ENV = (
process.env.NODE_ENV ||
process.env.ENV ||
"development"
).toLowerCase();
const HOST = process.env.HOST || "0.0.0.0";
const PORT = Number(process.env.PORT) || 5000;
const server = app.listen(PORT, () => {
console.log(`✅ Server running at http://${HOST}:${PORT}`);
const server = app.listen(PORT, HOST, () => {
console.log(
`✅ Server running in ${NODE_ENV} mode at http://${HOST}:${PORT}`
);
});
// Handle startup errors

View File

@@ -1,2 +1,4 @@
VITE_API_BASE_URL_BACKEND=http://localhost:5000
NODE_ENV=development
HOST=0.0.0.0
PORT=3000
VITE_API_BASE_URL_BACKEND=http://localhost:5000

View File

@@ -1,19 +1,20 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path';
import { defineConfig, loadEnv } from "vite";
import react from "@vitejs/plugin-react";
import path from "path";
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), "");
// https://vite.dev/config/
export default defineConfig({
plugins: [
react(),
],
server: {
port: 3000,
},
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
}
return {
plugins: [react()],
server: {
host: env.HOST,
port: Number(env.PORT),
},
resolve: {
alias: {
"@": path.resolve(__dirname, "src"),
},
},
};
});

View File

@@ -0,0 +1,2 @@
HOST=localhost
PORT=5001

View File

@@ -1,8 +1,22 @@
from flask import Flask, request, jsonify
from fastapi import FastAPI, UploadFile, File, HTTPException
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
import fitz # PyMuPDF
import re
import os
app = Flask(__name__)
from dotenv import load_dotenv
load_dotenv()
app = FastAPI()
# Optional: allow CORS for development
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # change in production
allow_methods=["*"],
allow_headers=["*"],
)
DOB_RE = re.compile(r'(?<!\d)(\d{1,2})/(\d{1,2})/(\d{4})(?!\d)')
ID_RE = re.compile(r'^\d{8,14}$') # 814 digits, whole line
@@ -14,10 +28,18 @@ STOP_WORDS = {
'provider', 'printed on', 'member id', 'name', 'date of birth'
}
@app.route("/extract", methods=["POST"])
def extract():
file = request.files['pdf']
doc = fitz.open(stream=file.read(), filetype="pdf")
@app.post("/extract")
async def extract(pdf: UploadFile = File(...)):
if not pdf:
raise HTTPException(status_code=400, detail="Missing 'pdf' file")
content = await pdf.read()
try:
doc = fitz.open(stream=content, filetype="pdf")
except Exception as e:
raise HTTPException(status_code=400, detail=f"Unable to open PDF: {e}")
# Extract text from all pages
text = "\n".join(page.get_text("text") for page in doc)
lines = [line.strip() for line in text.splitlines() if line.strip()]
@@ -34,7 +56,7 @@ def extract():
break
if id_idx == -1:
return jsonify({"memberId": "", "name": "", "dob": ""})
return {"memberId": "", "name": "", "dob": ""}
# 2) Scan forward to collect name + DOB; handle both same-line and next-line cases
collected = []
@@ -61,11 +83,13 @@ def extract():
# fallback: if we didn't find a date, assume first collected line(s) are name
name = blob
return jsonify({
return {
"memberId": member_id,
"name": name,
"dob": dob
})
}
if __name__ == "__main__":
app.run(port=5001)
host = os.getenv("HOST")
port = int(os.getenv("PORT"))
uvicorn.run(app, host=host, port=port)

View File

@@ -5,7 +5,7 @@ from typing import List, Optional
import io
import os
import asyncio
import uvicorn
from dotenv import load_dotenv
load_dotenv()
@@ -157,8 +157,6 @@ async def extract_csv(files: List[UploadFile] = File(...), filename: Optional[st
# Entrypoint (same pattern as your selenium app)
# -------------------------------------------------
if __name__ == "__main__":
import uvicorn
host = os.getenv("HOST")
port = int(os.getenv("PORT"))
reload_flag = os.getenv("RELOAD", "false").lower() == "true"
uvicorn.run(app, host=host, port=port, reload=reload_flag)
uvicorn.run(app, host=host, port=port)

View File

@@ -0,0 +1,2 @@
HOST=localhost
PORT=5002

View File

@@ -4,7 +4,10 @@ import uvicorn
import asyncio
from selenium_claimSubmitWorker import AutomationMassHealth
from selenium_eligibilityCheckWorker import AutomationMassHealthEligibilityCheck
import os
from dotenv import load_dotenv
load_dotenv()
app = FastAPI()
# Allow 1 selenium session at a time
@@ -89,4 +92,6 @@ async def get_status():
}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=5002)
host = os.getenv("HOST")
port = int(os.getenv("PORT"))
uvicorn.run(app, host=host, port=port)

88
docs/ports.md Normal file
View File

@@ -0,0 +1,88 @@
# 🛰️ Development Hosts & Ports
This document defines the default **host** and **port** used by each app/service
in this turborepo.
Update this file whenever a new service is added or port is changed.
---
## 🌐 Frontend (React + Vite)
- **Host:** `localhost` (default)
- Use `0.0.0.0` if you need LAN access (phone/other device on same Wi-Fi).
- **Port:** `3000`
- **Access URLs:**
- Local: [http://localhost:3000](http://localhost:3000)
- LAN: `http://<your-ip>:3000` (only if HOST=0.0.0.0)
**Current setup:**
Frontend is running on `0.0.0.0` and is accessible via the device IP.
**`.env` file:**
```env
NODE_ENV=development
HOST=0.0.0.0
PORT=3000
VITE_API_BASE_URL_BACKEND=http://192.168.1.8:5000
```
Based on backend HOST and PORT. Currently Backend runs on 0.0.0.0 so its accessible all over the same network.
Change the Backend url if needed,
And, VITE_API_BASE_URL_BACKEND shows the backend url of the network, make localhost if only own device to work with.
Or change accordingly with real IP.
---
## ⚙️ Backend (FastAPI)
- **Host:** `localhost`
- **Port:** `5000`
- **Access URL:** [http://localhost:5000](http://localhost:5000)
**Current setup:**
Currently runs for all network, and allow given frontend urls. Change accordingly.
**`.env` file:**
```env
NODE_ENV="development"
HOST=0.0.0.0
PORT=5000
FRONTEND_URLS=http://localhost:3000,http://192.168.1.8:3000
```
---
## 🧾 Patient Data Extractor Service
- **Host:** `localhost`
- **Port:** `5001`
- **Access URL:** [http://localhost:5001](http://localhost:5001)
## 💳 Selenium Service
- **Host:** `localhost`
- **Port:** `5002`
- **Access URL:** [http://localhost:5002](http://localhost:5002)
## 💳 Payment OCR Service
- **Host:** `localhost`
- **Port:** `5003`
- **Access URL:** [http://localhost:5003](http://localhost:5003)
---
## 📖 Notes
- These values come from per-app `.env` files:
- `HOST` controls binding (`localhost` = loopback only, `0.0.0.0` = all interfaces).
- `PORT` controls the services port.
- Frontend uses additional variables prefixed with `VITE_` for client-side access (e.g. `VITE_API_BASE_URL_BACKEND`).
- In production, ports and hosts may differ (configured by deployment platform).
---
**Action for developers:**
1. Copy `.env.example``.env` inside each app folder.
2. Adjust `HOST` / `PORT` if your ports are already taken.
3. Run `npm run dev` from the repo root.

View File

@@ -11,7 +11,7 @@
"db:generate": "prisma generate --schema=packages/db/prisma/schema.prisma && ts-node packages/db/scripts/patch-zod-buffer.ts",
"db:migrate": "dotenv -e packages/db/.env -- prisma migrate dev --schema=packages/db/prisma/schema.prisma",
"db:seed": "prisma db seed --schema=packages/db/prisma/schema.prisma",
"setup:env": "shx cp packages/db/prisma/.env.example packages/db/prisma/.env && shx cp apps/Frontend/.env.example apps/Frontend/.env && shx cp apps/Backend/.env.example apps/Backend/.env && shx cp apps/PaymentOCRService/.env.example apps/PaymentOCRService/.env",
"setup:env": "shx cp packages/db/prisma/.env.example packages/db/prisma/.env && shx cp apps/Frontend/.env.example apps/Frontend/.env && shx cp apps/Backend/.env.example apps/Backend/.env && shx cp apps/PatientDataExtractorService/.env.example apps/PatientDataExtractorService/.env && shx cp apps/SeleniumService/.env.example apps/SeleniumService/.env && shx cp apps/PaymentOCRService/.env.example apps/PaymentOCRService/.env",
"postinstall": "npm --prefix apps/PatientDataExtractorService run postinstall && npm --prefix apps/PaymentOCRService run postinstall"
},
"prisma": {