Compare commits

..

2 Commits

Author SHA1 Message Date
0576193b76 fixed reference 2025-05-22 13:22:33 +02:00
c0db4dc2c9 updated caching to resolve 403 entity too large errors 2025-05-22 12:52:05 +02:00
16 changed files with 140 additions and 423 deletions

@ -14,6 +14,10 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
with:
driver-opts: |
image=moby/buildkit:latest
network=host
- name: Login to Docker Registry
uses: docker/login-action@v2
@ -30,11 +34,10 @@ jobs:
tags: registry.liquidrinu.com/fusero-backend:latest
cache-from: type=registry,ref=registry.liquidrinu.com/fusero-backend:buildcache
cache-to: type=registry,ref=registry.liquidrinu.com/fusero-backend:buildcache,mode=max
- name: Create .env file
run: |
echo "VITE_API_BASE_URL=/api" > ./frontend/.env
# This only affects the CI/CD build, not your local dev .env
build-args: |
BUILDKIT_INLINE_CACHE=1
platforms: linux/amd64
compression: zstd
- name: Build and Push Frontend
uses: docker/build-push-action@v4
@ -45,6 +48,10 @@ jobs:
tags: registry.liquidrinu.com/fusero-frontend:latest
cache-from: type=registry,ref=registry.liquidrinu.com/fusero-frontend:buildcache
cache-to: type=registry,ref=registry.liquidrinu.com/fusero-frontend:buildcache,mode=max
build-args: |
BUILDKIT_INLINE_CACHE=1
platforms: linux/amd64
compression: zstd
- name: Install kubectl
uses: azure/setup-kubectl@v3
@ -74,13 +81,6 @@ jobs:
run: |
kubectl delete job fusero-backend-db-init -n fusero-prod || true
- name: Install Helm
run: |
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
- name: Generate values.prod.yaml from template
run: cp chart/values.prod.template.yaml chart/values.prod.yaml
- name: Deploy to Kubernetes
run: |
helm upgrade --install fusero ./chart \
@ -88,8 +88,8 @@ jobs:
--create-namespace \
--values ./chart/values.prod.yaml \
--values ./chart/secrets.prod.yaml \
--set backend.image=registry.liquidrinu.com/fusero-backend:latest \
--set frontend.image=registry.liquidrinu.com/fusero-frontend:latest
--set backend.image.repository=registry.liquidrinu.com/fusero-backend \
--set frontend.image.repository=registry.liquidrinu.com/fusero-frontend
- name: Wait for migration/seed job
run: |

4
.gitignore vendored

@ -143,7 +143,3 @@ chart/secrets.*.yaml
!chart/values.prod.public.yaml
.bkup/
# Ignore production values and secrets files
chart/values.prod.yaml
chart/secrets.prod.yaml

@ -1,4 +1,4 @@
# Use Node.js 18.3 as the base image
# Build stage
FROM node:20-slim AS build
# Install Python and build tools for node-gyp
@ -12,31 +12,53 @@ RUN apt-get update && \
ENV APP_DIR=/usr/src/app/
RUN mkdir -p ${APP_DIR}
# Install global dependencies like pm2, ts-node, and typescript as root
# Install global dependencies
RUN npm install -g pm2 ts-node typescript
# Create a non-root user and switch to it
# Create a non-root user
ENV APP_USER=appuser
RUN adduser --disabled-password --gecos '' ${APP_USER}
WORKDIR ${APP_DIR}
RUN chown -R ${APP_USER}:${APP_USER} ${APP_DIR}
# Switch to non-root user before copying files and installing dependencies
# Switch to non-root user
USER ${APP_USER}
# Copy package.json and package-lock.json and install dependencies as appuser
# Copy package files and install dependencies
COPY --chown=${APP_USER}:${APP_USER} package.json package-lock.json ./
RUN npm install
# Copy the rest of the application code with appropriate ownership
# Copy source code
COPY --chown=${APP_USER}:${APP_USER} . .
# Rebuild bcrypt and other native dependencies as appuser
# Rebuild native dependencies
RUN npm rebuild bcrypt --build-from-source
# Build the application using the npm script, assuming "build:ts" is defined
# Build the application
RUN npm run build:ts
# Production stage
FROM node:20-slim
# Install only production dependencies
ENV APP_DIR=/usr/src/app/
RUN mkdir -p ${APP_DIR}
# Create non-root user
ENV APP_USER=appuser
RUN adduser --disabled-password --gecos '' ${APP_USER}
WORKDIR ${APP_DIR}
RUN chown -R ${APP_USER}:${APP_USER} ${APP_DIR}
# Copy only necessary files from build stage
COPY --from=build --chown=${APP_USER}:${APP_USER} ${APP_DIR}/dist ./dist
COPY --from=build --chown=${APP_USER}:${APP_USER} ${APP_DIR}/package.json ./
COPY --from=build --chown=${APP_USER}:${APP_USER} ${APP_DIR}/package-lock.json ./
# Install only production dependencies
USER ${APP_USER}
RUN npm ci --only=production
# Environment variables
ENV CI=true
ENV PORT=14000
@ -45,5 +67,5 @@ ENV NODE_ENV=production
# Expose the application's port
EXPOSE ${PORT}
# Command to run the application using npm start
# Command to run the application
CMD ["npm", "start"]

138
README.md

@ -10,9 +10,44 @@ A full-stack application boilerplate with a React frontend and Node.js backend
- [📚 Table of Contents](#-table-of-contents)
- [📁 Project Structure](#-project-structure)
- [⚙️ Prerequisites](#-prerequisites)
- [Development Setup](#development-setup)
- [Important Note: Database Must Run in Docker](#important-note-database-must-run-in-docker)
- [💻 Development Setup](#-development-setup)
- [To create a new migration:](#to-create-a-new-migration)
- [npm run migration:create](#npm-run-migrationcreate)
- [To apply migrations:](#to-apply-migrations)
- [To seed the database:](#to-seed-the-database)
- [Alternate: Running Services in Separate Terminals](#alternate-running-services-in-separate-terminals)
- [🛠️ Environment Setup](#-environment-setup)
- [For Kubernetes, these are set in chart/values.yaml:](#for-kubernetes-these-are-set-in-chartvaluesyaml)
- [POSTGRES\_NAME=fusero-boilerplate-db](#postgres_namefusero-boilerplate-db)
- [POSTGRES\_HOSTNAME=postgres-service](#postgres_hostnamepostgres-service)
- [POSTGRES\_PORT=19095](#postgres_port19095)
- [POSTGRES\_USER=root](#postgres_userroot)
- [POSTGRES\_PASSWORD=root123](#postgres_passwordroot123)
- [🐳 Docker Development](#-docker-development)
- [To create a new migration:](#to-create-a-new-migration-1)
- [npm run migration:create](#npm-run-migrationcreate-1)
- [To apply migrations:](#to-apply-migrations-1)
- [To seed the database:](#to-seed-the-database-1)
- [🚀 Kubernetes Deployment](#-kubernetes-deployment)
- [🌐 Frontend Routing in Production](#-frontend-routing-in-production)
- [🔐 HTTPS with Self-Signed Certificates](#-https-with-self-signed-certificates)
- [🧠 Development Best Practices](#-development-best-practices)
- [📘 API Documentation](#-api-documentation)
- [🧩 ChatGPT-Powered Endpoint Creation](#-chatgpt-powered-endpoint-creation)
- [🧪 Troubleshooting](#-troubleshooting)
- [🤝 Contributing](#-contributing)
- [📄 License](#-license)
- [Kubernetes Troubleshooting \& Redeployment Commands](#kubernetes-troubleshooting--redeployment-commands)
- [1. Rebuild the backend Docker image (after code/config changes)](#1-rebuild-the-backend-docker-image-after-codeconfig-changes)
- [2. (If using a remote registry) Push the image](#2-if-using-a-remote-registry-push-the-image)
- [3. Upgrade the Helm release with the latest values](#3-upgrade-the-helm-release-with-the-latest-values)
- [4. Restart the backend deployment to pick up new images and env vars](#4-restart-the-backend-deployment-to-pick-up-new-images-and-env-vars)
- [5. Check backend pod environment variables](#5-check-backend-pod-environment-variables)
- [6. Check backend pod logs for errors](#6-check-backend-pod-logs-for-errors)
- [7. If you change DB env vars or code, repeat steps 1-6](#7-if-you-change-db-env-vars-or-code-repeat-steps-1-6)
- [Frontend Rebuild \& Redeploy (Kubernetes)](#frontend-rebuild--redeploy-kubernetes)
- [1. Rebuild the frontend Docker image](#1-rebuild-the-frontend-docker-image)
- [2. (If using a remote registry) Push the image](#2-if-using-a-remote-registry-push-the-image-1)
- [3. Upgrade the Helm release](#3-upgrade-the-helm-release)
- [4. Restart the frontend deployment](#4-restart-the-frontend-deployment)
- [Port-Forwarding for Local Access](#port-forwarding-for-local-access)
@ -47,17 +82,12 @@ A full-stack application boilerplate with a React frontend and Node.js backend
- [Troubleshooting Production](#troubleshooting-production)
- [🆕 Recent Improvements \& Troubleshooting](#-recent-improvements--troubleshooting)
- [🚀 Production Deployment Pipeline (CI/CD)](#-production-deployment-pipeline-cicd)
- [CI/CD Kubernetes Deployment Setup](#cicd-kubernetes-deployment-setup)
- [Using Private Docker Registry with Kubernetes](#using-private-docker-registry-with-kubernetes)
- [Production Secrets Management (Gitea as Source of Truth)](#production-secrets-management-gitea-as-source-of-truth)
- [CI/CD Pipeline Behavior: Multiple Merges to Main](#cicd-pipeline-behavior-multiple-merges-to-main)
---
## 📁 Project Structure
```
fusero-app-boilerplate
fusero-app-boilerplate/
├── chart/ # Helm chart for Kubernetes
│ ├── Chart.yaml
│ ├── values.dev.yaml
@ -95,7 +125,6 @@ fusero-app-boilerplate
├── test/
├── utils/
└── README.md
```
---
@ -528,94 +557,3 @@ The application uses a secure secrets management approach:
- This ensures your database is always migrated and seeded with every deploy, and you'll know immediately if something goes wrong.
- To trigger a production deployment, just push or merge to `main`.
## CI/CD Kubernetes Deployment Setup
To enable automated deployment to your Kubernetes cluster from CI/CD (Gitea Actions):
1. **Get your kubeconfig file from your Kubernetes master node or provider.**
- For self-hosted clusters, it's usually at `~/.kube/config` on the master node.
- For managed clusters, download it from your provider's dashboard.
2. **Edit the kubeconfig file:**
- Change the `server:` field to use your cluster's public IP or DNS, e.g.:
```yaml
server: https://[YOUR_PUBLIC_IP_OR_DNS]:6443
```
(For IPv6, use square brackets around the address.)
3. **Base64-encode the kubeconfig file as a single line:**
- On Linux:
```bash
base64 -w 0 /path/to/your/kubeconfig
```
- On Mac:
```bash
base64 /path/to/your/kubeconfig | tr -d '\n'
```
4. **Add the base64 string as a secret in your Gitea repository:**
- Go to **Settings → Secrets**
- Name: `KUBE_CONFIG`
- Value: (paste the base64 string)
5. **Make sure port 6443 is open to your CI/CD runner's IP in your VPS firewall/security group.**
6. **Your pipeline will now be able to deploy to your Kubernetes cluster.**
---
## Using Private Docker Registry with Kubernetes
If you use a private Docker registry (like registry.liquidrinu.com), you must create a Kubernetes secret and reference it in your deployments:
1. **Create the registry secret:**
```bash
kubectl create secret docker-registry regcred \
--docker-server=registry.liquidrinu.com \
--docker-username=YOUR_REGISTRY_USERNAME \
--docker-password=YOUR_REGISTRY_PASSWORD \
--docker-email=YOUR_EMAIL \
-n fusero-prod
```
2. **Reference the secret in your deployment YAMLs:**
In your deployment spec, add:
```yaml
imagePullSecrets:
- name: regcred
```
Example:
```yaml
spec:
template:
spec:
imagePullSecrets:
- name: regcred
containers:
- name: backend
image: ...
```
This allows Kubernetes to authenticate to your private registry and pull images securely.
---
## Production Secrets Management (Gitea as Source of Truth)
- In production, all sensitive values (like `POSTGRES_PASSWORD`, `DEFAULT_ADMIN_PASSWORD`, etc.) are managed as secrets in your Gitea repository (Settings → Secrets).
- The CI/CD pipeline uses these secrets to generate `chart/secrets.prod.yaml` and other files at runtime.
- Helm uses these generated files to set environment variables for your Kubernetes resources.
- The Postgres password is set from the secret **only when the database is first initialized** (i.e., when the persistent volume is empty). Changing the secret later will not update the password for an existing database unless you reset the DB or delete the volume.
- **Summary:** Gitea secrets are the source of truth for production. Always update secrets in Gitea and redeploy to apply changes to new pods.
---
## CI/CD Pipeline Behavior: Multiple Merges to Main
- If multiple merges or pushes happen to the `main` branch in quick succession, your CI/CD system will start a separate pipeline for each commit.
- These pipelines will run in parallel unless your CI/CD is configured to queue or cancel previous runs.
- This can result in race conditions, where the last pipeline to finish will determine the final deployed state.
- **Best practice:** Avoid merging multiple large changes to `main` at the same time. Wait for the pipeline to finish before merging the next PR, or configure your CI/CD to cancel previous runs on new pushes.
---

6
chart/Chart.yml Normal file

@ -0,0 +1,6 @@
apiVersion: v2
name: fusero
description: Fusero App Boilerplate Helm Chart
type: application
version: 0.1.0
appVersion: "1.0.0"

@ -12,8 +12,6 @@ spec:
labels:
app: fusero-backend
spec:
imagePullSecrets:
- name: regcred
containers:
- name: backend
image: {{ .Values.backend.image }}

@ -8,62 +8,18 @@ spec:
metadata:
name: fusero-backend-db-init
spec:
imagePullSecrets:
- name: regcred
containers:
- name: migrate-seed
image: {{ .Values.backend.image }}
command: ["/bin/sh", "-c"]
args:
- |
echo "=== Environment Variables ==="
env | grep -i postgres
echo "=== Testing Connection ==="
PGPASSWORD=$POSTGRES_PASSWORD psql "postgresql://$POSTGRES_USER@$POSTGRES_HOSTNAME:$POSTGRES_PORT/$POSTGRES_NAME" -c "SELECT 1"
echo "=== Running Migrations ==="
npx mikro-orm migration:up
echo "=== Running Seeds ==="
echo "Running migrations and seeds..." && \
npx mikro-orm migration:up && \
npm run seed
env:
- name: POSTGRES_HOSTNAME
value: "postgres-service"
- name: POSTGRES_PORT
value: "5432"
- name: POSTGRES_NAME
value: "fusero-db"
- name: POSTGRES_USER
value: "prod_admin"
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: fusero-backend-secrets
key: POSTGRES_PASSWORD
- name: NODE_ENV
value: "production"
- name: DEFAULT_ADMIN_USERNAME
value: "{{ .Values.backend.env.DEFAULT_ADMIN_USERNAME }}"
- name: DEFAULT_ADMIN_EMAIL
value: "{{ .Values.backend.env.DEFAULT_ADMIN_EMAIL }}"
- name: DEFAULT_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: fusero-backend-secrets
key: DEFAULT_ADMIN_PASSWORD
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: fusero-backend-secrets
key: JWT_SECRET
- name: CHATGPT_API_KEY
valueFrom:
secretKeyRef:
name: fusero-backend-secrets
key: CHATGPT_API_KEY
- name: CANVAS_API_KEY
valueFrom:
secretKeyRef:
name: fusero-backend-secrets
key: CANVAS_API_KEY
- name: CANVAS_API_URL
value: "{{ .Values.backend.env.CANVAS_API_URL }}"
{{- range $key, $val := .Values.backend.env }}
- name: {{ $key }}
value: "{{ $val }}"
{{- end }}
restartPolicy: Never

@ -12,8 +12,6 @@ spec:
labels:
app: fusero-frontend
spec:
imagePullSecrets:
- name: regcred
containers:
- name: frontend
image: {{ .Values.frontend.image }}

@ -8,51 +8,11 @@ data:
local all all trust
host all all 127.0.0.1/32 trust
host all all ::1/128 trust
host all all 0.0.0.0/0 scram-sha-256
host all all 0.0.0.0/0 md5
postgresql.conf: |
# Connection Settings
listen_addresses = '*'
max_connections = 100
# Memory Settings
shared_buffers = 128MB
work_mem = 4MB
maintenance_work_mem = 64MB
# Write Ahead Log
dynamic_shared_memory_type = posix
max_wal_size = 1GB
min_wal_size = 80MB
checkpoint_timeout = 5min
checkpoint_completion_target = 0.9
# Query Planner
random_page_cost = 1.1
effective_cache_size = 4GB
# Autovacuum
autovacuum = on
autovacuum_max_workers = 3
autovacuum_naptime = 1min
autovacuum_vacuum_threshold = 50
autovacuum_analyze_threshold = 50
# Logging
log_min_duration_statement = 1000
log_checkpoints = on
log_connections = on
log_disconnections = on
log_lock_waits = on
log_temp_files = 0
log_autovacuum_min_duration = 0
# Other Settings
dynamic_shared_memory_type = posix
effective_io_concurrency = 200
default_statistics_target = 100
# Authentication
password_encryption = scram-sha-256
# Error Reporting
log_min_error_statement = error
log_statement = 'all'

@ -19,42 +19,11 @@ spec:
- containerPort: 5432
env:
- name: POSTGRES_DB
value: "{{ .Values.postgres.dbName }}"
value: {{ .Values.postgres.dbName }}
- name: POSTGRES_USER
value: "{{ .Values.postgres.user }}"
value: {{ .Values.postgres.user }}
- name: POSTGRES_PASSWORD
value: "{{ .Values.postgres.password }}"
- name: POSTGRES_HOST_AUTH_METHOD
value: "scram-sha-256"
startupProbe:
exec:
command:
- pg_isready
- -U
- "{{ .Values.postgres.user }}"
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 30
readinessProbe:
exec:
command:
- pg_isready
- -U
- "{{ .Values.postgres.user }}"
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 5
livenessProbe:
exec:
command:
- pg_isready
- -U
- "{{ .Values.postgres.user }}"
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
value: {{ .Values.postgres.password }}
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: postgres-data

@ -1,69 +0,0 @@
global:
namespace: fusero-prod
security:
cors:
origin: "https://your-domain.com"
methods: "GET,POST,PUT,DELETE"
credentials: true
https:
enabled: true
certSecret: "your-tls-secret"
logging:
level: "info"
format: "json"
monitoring:
prometheus:
enabled: true
path: "/metrics"
backend:
image: registry.liquidrinu.com/fusero-backend:latest
port: 14000
resources:
requests:
cpu: "200m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
env:
POSTGRES_HOSTNAME: postgres-service
POSTGRES_PORT: "5432"
POSTGRES_DB: fusero-db
POSTGRES_USER: prod_admin
POSTGRES_PASSWORD: "<POSTGRES_PASSWORD>"
DEFAULT_ADMIN_USERNAME: admin
DEFAULT_ADMIN_EMAIL: admin@your-domain.com
DEFAULT_ADMIN_PASSWORD: "<DEFAULT_ADMIN_PASSWORD>"
ENCRYPTION_KEY: "<ENCRYPTION_KEY>"
JWT_SECRET: "<JWT_SECRET>"
CHATGPT_API_KEY: "<CHATGPT_API_KEY>"
CANVAS_API_KEY: "<CANVAS_API_KEY>"
CANVAS_API_URL: https://your-canvas-instance/api/v1
frontend:
image: registry.liquidrinu.com/fusero-frontend:latest
port: 80
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "300m"
memory: "256Mi"
env:
VITE_API_BASE_URL: https://your-domain.com
postgres:
image: postgres:15
storage: 5Gi
resources:
requests:
cpu: "200m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
password: "<POSTGRES_PASSWORD>"
user: "prod_admin"
dbName: "fusero-db"

@ -1,70 +0,0 @@
global:
namespace: fusero-prod
security:
cors:
origin: "https://your-domain.com"
methods: "GET,POST,PUT,DELETE"
credentials: true
https:
enabled: true
certSecret: "your-tls-secret"
logging:
level: "info"
format: "json"
monitoring:
prometheus:
enabled: true
path: "/metrics"
backend:
image: registry.liquidrinu.com/fusero-backend:latest
port: 14000
resources:
requests:
cpu: "200m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
env:
POSTGRES_HOST: postgres-service
POSTGRES_HOSTNAME: postgres-service
POSTGRES_PORT: "5432"
POSTGRES_NAME: fusero-db
POSTGRES_USER: prod_admin
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
DEFAULT_ADMIN_USERNAME: admin
DEFAULT_ADMIN_EMAIL: admin@fusero.nl
DEFAULT_ADMIN_PASSWORD: ${DEFAULT_ADMIN_PASSWORD}
ENCRYPTION_KEY: ${ENCRYPTION_KEY}
JWT_SECRET: ${JWT_SECRET}
CHATGPT_API_KEY: ${CHATGPT_API_KEY}
CANVAS_API_KEY: ${CANVAS_API_KEY}
CANVAS_API_URL: https://talnet.instructure.com/api/v1
frontend:
image: registry.liquidrinu.com/fusero-frontend:latest
port: 80
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "300m"
memory: "256Mi"
env:
VITE_API_BASE_URL: https://app.fusero.nl
postgres:
image: postgres:15
storage: 5Gi
dbName: fusero-db
user: prod_admin
password: ${POSTGRES_PASSWORD}
resources:
requests:
cpu: "200m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"

22
chart/values.prod.yml Normal file

@ -0,0 +1,22 @@
backend:
image: fusero-backend:latest
env:
POSTGRES_HOST: postgres-service
POSTGRES_PORT: "5432"
POSTGRES_NAME: fusero-db
POSTGRES_USER: prod_admin
POSTGRES_PASSWORD: REPLACE_ME
DEFAULT_ADMIN_USERNAME: admin
DEFAULT_ADMIN_EMAIL: admin@fusero.nl
DEFAULT_ADMIN_PASSWORD: STRONG_REPLACE_ME
ENCRYPTION_KEY: PROD_REPLACE_ME_KEY
JWT_SECRET: PROD_REPLACE_ME_JWT
CHATGPT_API_KEY: PROD_REPLACE_ME_CHATGPT
CANVAS_API_KEY: PROD_REPLACE_ME_CANVAS
frontend:
image: fusero-frontend:latest
postgres:
image: postgres:15
storage: 5Gi

@ -1,10 +1,14 @@
{
"compilerOptions": {
"target": "ESNext",
"lib": ["DOM", "DOM.Iterable", "ESNext", "ES2015"],
"lib": [
"DOM",
"DOM.Iterable",
"ESNext",
"ES2015"
],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
@ -12,7 +16,6 @@
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": false,
"noUnusedLocals": false,
@ -22,7 +25,6 @@
"noImplicitReturns": false,
"noImplicitThis": false,
"alwaysStrict": false
/* Additional Options */
// "forceConsistentCasingInFileNames": true,
// "strictNullChecks": true,
@ -32,6 +34,12 @@
// "incremental": true,
// "esModuleInterop": true
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
"include": [
"src"
],
"references": [
{
"path": "./tsconfig.node.json"
}
]
}

@ -3,21 +3,12 @@ import { PostgreSqlDriver } from '@mikro-orm/postgresql';
import { Migrator } from '@mikro-orm/migrations';
import dotenv from 'dotenv';
// Load environment variables if not in Kubernetes
if (process.env.KUBERNETES_SERVICE_HOST === undefined) {
dotenv.config({ override: true });
}
const isProduction = process.env.NODE_ENV === 'production';
// Validate required environment variables
const requiredEnvVars = ['POSTGRES_DB', 'POSTGRES_USER', 'POSTGRES_PASSWORD'];
const missingEnvVars = requiredEnvVars.filter(envVar => !process.env[envVar]);
if (missingEnvVars.length > 0 && isProduction) {
throw new Error(`Missing required environment variables: ${missingEnvVars.join(', ')}`);
}
const config: Options = {
driver: PostgreSqlDriver,
entities: [
@ -34,14 +25,14 @@ const config: Options = {
warnWhenNoEntities: true,
disableDynamicFileAccess: false,
},
dbName: process.env.POSTGRES_DB || 'fusero-boilerplate-db',
dbName: process.env.POSTGRES_NAME || 'fusero-boilerplate-db',
host: process.env.POSTGRES_HOSTNAME || 'localhost',
port: Number(process.env.POSTGRES_PORT) || 5432,
user: process.env.POSTGRES_USER || 'root',
password: process.env.POSTGRES_PASSWORD || 'root123',
debug: !isProduction,
migrations: {
tableName: process.env.POSTGRES_DB,
tableName: process.env.POSTGRES_NAME,
path: isProduction ? './dist/src/database/migrations' : './src/database/migrations',
glob: '!(*.d).{js,ts}',
transactional: true,
@ -52,13 +43,6 @@ const config: Options = {
snapshot: true,
emit: 'ts',
},
// Add connection pool settings
pool: {
min: 2,
max: 10,
idleTimeoutMillis: 30000,
acquireTimeoutMillis: 30000,
},
};
export default config;

@ -1 +0,0 @@
# trigger