feat : add docker
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
# Node modules
|
||||
node_modules
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# Build outputs
|
||||
.output
|
||||
.nuxt
|
||||
dist
|
||||
.cache
|
||||
|
||||
# Environment files
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# IDE
|
||||
.vscode
|
||||
.idea
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Git
|
||||
.git
|
||||
.gitignore
|
||||
.github
|
||||
|
||||
# Documentation
|
||||
README.md
|
||||
docs
|
||||
|
||||
# Test files
|
||||
*.test.js
|
||||
*.spec.js
|
||||
coverage
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
||||
# Docker files (if building)
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
docker-compose.yml
|
||||
@@ -0,0 +1,23 @@
|
||||
# Environment Variables Example
|
||||
# Copy this file to .env and fill in your values
|
||||
# This file is used by both development and Docker
|
||||
|
||||
# Application
|
||||
NODE_ENV=development
|
||||
|
||||
# Keycloak Configuration
|
||||
KEYCLOAK_ISSUER=https://your-keycloak-server/realms/your-realm
|
||||
KEYCLOAK_CLIENT_ID=your-client-id
|
||||
KEYCLOAK_CLIENT_SECRET=your-client-secret
|
||||
|
||||
# API Configuration
|
||||
NUXT_PUBLIC_API_BASE_URL=https://your-api-server.com
|
||||
NUXT_PUBLIC_AUTH_URL=http://localhost:3005
|
||||
|
||||
# Database (if needed)
|
||||
# DATABASE_URL=postgresql://user:password@postgres:5432/dbname
|
||||
|
||||
# Redis (if using Redis for session store)
|
||||
# REDIS_HOST=redis
|
||||
# REDIS_PORT=6379
|
||||
# REDIS_PASSWORD=your-redis-password
|
||||
+5
-2
@@ -5,6 +5,9 @@ node_modules
|
||||
.cache
|
||||
.output
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
dist
|
||||
Dockerfile
|
||||
docker-compose.yml
|
||||
# Dockerfile and docker-compose.yml should be committed
|
||||
# Dockerfile
|
||||
# docker-compose.yml
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
# Dockerfile for Nuxt.js Application
|
||||
# Multi-stage build for optimized image size
|
||||
|
||||
# Stage 1: Build Stage
|
||||
FROM node:20-alpine AS builder
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
COPY package*.json ./
|
||||
|
||||
# Install dependencies
|
||||
RUN npm ci
|
||||
|
||||
# Copy application files
|
||||
COPY . .
|
||||
|
||||
# Build the application
|
||||
RUN npm run build
|
||||
|
||||
# Stage 2: Production Stage
|
||||
FROM node:20-alpine AS runner
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
COPY package*.json ./
|
||||
|
||||
# Install production dependencies only (skip postinstall script)
|
||||
RUN npm ci --omit=dev --ignore-scripts
|
||||
|
||||
# Copy built application from builder stage
|
||||
COPY --from=builder /app/.output /app/.output
|
||||
COPY --from=builder /app/.nuxt /app/.nuxt
|
||||
COPY --from=builder /app/nuxt.config.ts /app/nuxt.config.ts
|
||||
COPY --from=builder /app/node_modules /app/node_modules
|
||||
|
||||
# Create non-root user for security
|
||||
RUN addgroup -g 1001 -S nodejs && \
|
||||
adduser -S nuxtjs -u 1001 && \
|
||||
chown -R nuxtjs:nodejs /app
|
||||
|
||||
# Switch to non-root user
|
||||
USER nuxtjs
|
||||
|
||||
# Expose port
|
||||
EXPOSE 3000
|
||||
|
||||
# Set environment variables
|
||||
ENV NODE_ENV=production
|
||||
ENV HOST=0.0.0.0
|
||||
ENV PORT=3000
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
|
||||
CMD node -e "require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"
|
||||
|
||||
# Start the application
|
||||
CMD ["node", ".output/server/index.mjs"]
|
||||
@@ -0,0 +1,179 @@
|
||||
# Docker Deployment Guide
|
||||
|
||||
## 📦 Prerequisites
|
||||
|
||||
- Docker Desktop installed
|
||||
- Docker Compose installed (included with Docker Desktop)
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### 1. Build the Docker Image
|
||||
|
||||
```bash
|
||||
docker build -t antrean-operasi:latest .
|
||||
```
|
||||
|
||||
### 2. Run with Docker Compose
|
||||
|
||||
```bash
|
||||
# Make sure .env file exists with your configuration
|
||||
# Docker Compose will automatically use .env file
|
||||
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### 3. Run without Docker Compose
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name antrean-operasi \
|
||||
-p 3005:3000 \
|
||||
-e KEYCLOAK_ISSUER=https://your-keycloak/realms/your-realm \
|
||||
-e KEYCLOAK_CLIENT_ID=your-client-id \
|
||||
-e KEYCLOAK_CLIENT_SECRET=your-client-secret \
|
||||
-e API_BASE_URL=https://your-api.com \
|
||||
-e AUTH_URL=http://localhost:3005 \
|
||||
antrean-operasi:latest
|
||||
```
|
||||
|
||||
## 🔧 Available Commands
|
||||
|
||||
### Build image
|
||||
```bash
|
||||
docker build -t antrean-operasi:latest .
|
||||
```
|
||||
|
||||
### Start containers
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### Stop containers
|
||||
```bash
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
### View logs
|
||||
```bash
|
||||
docker-compose logs -f antrean-operasi
|
||||
```
|
||||
|
||||
### Rebuild and restart
|
||||
```bash
|
||||
docker-compose up -d --build
|
||||
```
|
||||
|
||||
### Access container shell
|
||||
```bash
|
||||
docker exec -it antrean-operasi sh
|
||||
```
|
||||
|
||||
## 🌐 Access Application
|
||||
|
||||
After starting the container, access the application at:
|
||||
- **http://localhost:3005**
|
||||
|
||||
## 📝 Environment Variables
|
||||
|
||||
Required environment variables (set in `.env` file):
|
||||
|
||||
| Variable | Description | Example |
|
||||
|----------|-------------|---------|
|
||||
| `KEYCLOAK_ISSUER` | Keycloak realm URL | `https://keycloak.example.com/realms/myrealm` |
|
||||
| `KEYCLOAK_CLIENT_ID` | Keycloak client ID | `antrean-operasi-client` |
|
||||
| `KEYCLOAK_CLIENT_SECRET` | Keycloak client secret | `your-secret-here` |
|
||||
| `API_BASE_URL` | Backend API URL | `https://api.example.com` |
|
||||
| `AUTH_URL` | Application auth URL | `http://localhost:3005` |
|
||||
|
||||
## 🐳 Docker Hub (Optional)
|
||||
|
||||
### Tag and Push to Docker Hub
|
||||
|
||||
```bash
|
||||
# Tag the image
|
||||
docker tag antrean-operasi:latest yourusername/antrean-operasi:latest
|
||||
|
||||
# Login to Docker Hub
|
||||
docker login
|
||||
|
||||
# Push to Docker Hub
|
||||
docker push yourusername/antrean-operasi:latest
|
||||
```
|
||||
|
||||
### Pull from Docker Hub
|
||||
|
||||
```bash
|
||||
docker pull yourusername/antrean-operasi:latest
|
||||
```
|
||||
|
||||
## 🔍 Troubleshooting
|
||||
|
||||
### Check container status
|
||||
```bash
|
||||
docker ps -a
|
||||
```
|
||||
|
||||
### View detailed logs
|
||||
```bash
|
||||
docker logs antrean-operasi
|
||||
```
|
||||
|
||||
### Check container resource usage
|
||||
```bash
|
||||
docker stats antrean-operasi
|
||||
```
|
||||
|
||||
### Restart container
|
||||
```bash
|
||||
docker restart antrean-operasi
|
||||
```
|
||||
|
||||
### Remove all containers and images
|
||||
```bash
|
||||
docker-compose down --rmi all --volumes
|
||||
```
|
||||
|
||||
## 🏗️ Production Recommendations
|
||||
|
||||
1. **Use environment-specific configs**: Create separate `.env.production` files
|
||||
2. **Enable HTTPS**: Use a reverse proxy (Nginx, Traefik) with SSL certificates
|
||||
3. **Use Docker secrets**: For sensitive data in production
|
||||
4. **Set resource limits**: Add memory and CPU limits in docker-compose.yml
|
||||
5. **Use Redis**: Replace in-memory session store with Redis
|
||||
6. **Setup monitoring**: Add health checks and monitoring tools
|
||||
7. **Regular backups**: Backup mounted volumes and data
|
||||
|
||||
### Example Production docker-compose.yml with limits:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
antrean-operasi:
|
||||
# ... other config ...
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '2'
|
||||
memory: 2G
|
||||
reservations:
|
||||
cpus: '1'
|
||||
memory: 1G
|
||||
```
|
||||
|
||||
## 📊 Health Check
|
||||
|
||||
The container includes a health check endpoint. Check container health:
|
||||
|
||||
```bash
|
||||
docker inspect --format='{{json .State.Health}}' antrean-operasi
|
||||
```
|
||||
|
||||
## 🔐 Security Notes
|
||||
|
||||
- Never commit `.env.docker` to version control
|
||||
- Use Docker secrets for production deployments
|
||||
- Run container as non-root user (already configured)
|
||||
- Regularly update base images for security patches
|
||||
|
||||
## 📞 Support
|
||||
|
||||
For issues or questions, please contact the development team.
|
||||
@@ -0,0 +1,35 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
antrean-operasi:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: antrean-operasi
|
||||
ports:
|
||||
- "3005:3000"
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- HOST=0.0.0.0
|
||||
- PORT=3000
|
||||
volumes:
|
||||
# Mount for persistent data
|
||||
- ./data:/app/data
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- antrean-network
|
||||
healthcheck:
|
||||
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
networks:
|
||||
antrean-network:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
data:
|
||||
+17
-14
@@ -89,22 +89,25 @@ export default defineNuxtConfig({
|
||||
// }
|
||||
},
|
||||
runtimeConfig: {
|
||||
// Nuxt will automatically map NUXT_* environment variables
|
||||
// NUXT_KEYCLOAK_CLIENT_ID → keycloakClientId
|
||||
authSecret: process.env.NUXT_AUTH_SECRET,
|
||||
keycloakClientId: process.env.KEYCLOAK_CLIENT_ID,
|
||||
keycloakClientSecret: process.env.KEYCLOAK_CLIENT_SECRET,
|
||||
keycloakIssuer: process.env.KEYCLOAK_ISSUER,
|
||||
keycloakLogoutUri: process.env.KEYCLOAK_LOGOUT_URI, // Optional: custom logout URI
|
||||
postLogoutRedirectUri: process.env.POST_LOGOUT_REDIRECT_URI, // Optional: custom post-logout redirect URI
|
||||
keycloakClientId: process.env.NUXT_KEYCLOAK_CLIENT_ID || process.env.KEYCLOAK_CLIENT_ID,
|
||||
keycloakClientSecret: process.env.NUXT_KEYCLOAK_CLIENT_SECRET || process.env.KEYCLOAK_CLIENT_SECRET,
|
||||
keycloakIssuer: process.env.NUXT_KEYCLOAK_ISSUER || process.env.KEYCLOAK_ISSUER,
|
||||
keycloakLogoutUri: process.env.NUXT_KEYCLOAK_LOGOUT_URI || process.env.KEYCLOAK_LOGOUT_URI,
|
||||
postLogoutRedirectUri: process.env.NUXT_POST_LOGOUT_REDIRECT_URI || process.env.POST_LOGOUT_REDIRECT_URI,
|
||||
public: {
|
||||
authUrl: process.env.AUTH_ORIGIN,
|
||||
// authUrl: process.env.AUTH_ORIGIN || "http://10.10.150.175:3001",
|
||||
// authUrl: process.env.AUTH_ORIGIN || "http://localhost:3001",
|
||||
wsBaseUrl: process.env.WS_BASE_URL || 'ws://10.10.150.100:8084/api/v1/ws',
|
||||
baseUrl: process.env.BASE_URL || 'http://10.10.150.144:8080/api',
|
||||
baseUrlGomed: process.env.BASE_URL_GOMED || 'https://gomed.rssa.my.id/api',
|
||||
keycloakUrl: process.env.KEYCLOAK_ISSUER ? `${process.env.KEYCLOAK_ISSUER}/protocol/openid-connect/token` : 'https://auth.rssa.top/realms/sandbox/protocol/openid-connect/token',
|
||||
keycloakClientId: process.env.KEYCLOAK_CLIENT_ID || 'akbar-test',
|
||||
keycloakClientSecret: process.env.KEYCLOAK_CLIENT_SECRET || 'FDyv3UYMgJOYPnvzXVVv6diRtcgEevKg',
|
||||
// NUXT_PUBLIC_* variables are exposed to client-side
|
||||
authUrl: process.env.NUXT_PUBLIC_AUTH_URL || process.env.AUTH_ORIGIN,
|
||||
wsBaseUrl: process.env.NUXT_PUBLIC_WS_BASE_URL || process.env.WS_BASE_URL || 'ws://10.10.150.100:8084/api/v1/ws',
|
||||
baseUrl: process.env.NUXT_PUBLIC_BASE_URL || process.env.BASE_URL || 'http://10.10.150.144:8080/api',
|
||||
baseUrlGomed: process.env.NUXT_PUBLIC_BASE_URL_GOMED || process.env.BASE_URL_GOMED || 'https://gomed.rssa.my.id/api',
|
||||
keycloakUrl: process.env.NUXT_KEYCLOAK_ISSUER ? `${process.env.NUXT_KEYCLOAK_ISSUER}/protocol/openid-connect/token` :
|
||||
process.env.KEYCLOAK_ISSUER ? `${process.env.KEYCLOAK_ISSUER}/protocol/openid-connect/token` :
|
||||
'https://auth.rssa.top/realms/sandbox/protocol/openid-connect/token',
|
||||
keycloakClientId: process.env.NUXT_KEYCLOAK_CLIENT_ID || process.env.KEYCLOAK_CLIENT_ID || 'akbar-test',
|
||||
keycloakClientSecret: process.env.NUXT_KEYCLOAK_CLIENT_SECRET || process.env.KEYCLOAK_CLIENT_SECRET || 'FDyv3UYMgJOYPnvzXVVv6diRtcgEevKg',
|
||||
keycloakClientUuid: process.env.KEYCLOAK_CLIENT_UUID,
|
||||
keycloakAdminRealmUrl: process.env.KEYCLOAK_ADMIN_REALM_URL
|
||||
},
|
||||
|
||||
Generated
+57
-8
@@ -18,7 +18,6 @@
|
||||
"apexcharts": "4.5.0",
|
||||
"axios": "^1.9.0",
|
||||
"axios-mock-adapter": "^2.1.0",
|
||||
"better-sqlite3": "^12.6.2",
|
||||
"gsap": "^3.14.2",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"lodash-es": "^4.17.21",
|
||||
@@ -3926,6 +3925,8 @@
|
||||
"integrity": "sha512-8VYKM3MjCa9WcaSAI3hzwhmyHVlH8tiGFwf0RlTsZPWJ1I5MkzjiudCo4KC4DxOaL/53A5B1sI/IbldNFDbsKA==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"bindings": "^1.5.0",
|
||||
"prebuild-install": "^7.1.1"
|
||||
@@ -3969,6 +3970,8 @@
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"buffer": "^5.5.0",
|
||||
"inherits": "^2.0.4",
|
||||
@@ -3994,6 +3997,8 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.1.13"
|
||||
@@ -4004,6 +4009,8 @@
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
@@ -4916,6 +4923,8 @@
|
||||
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
|
||||
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"mimic-response": "^3.1.0"
|
||||
},
|
||||
@@ -4931,6 +4940,8 @@
|
||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
@@ -5651,6 +5662,8 @@
|
||||
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
|
||||
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
|
||||
"license": "(MIT OR WTFPL)",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
@@ -6004,7 +6017,9 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
@@ -6168,7 +6183,9 @@
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
|
||||
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "10.4.5",
|
||||
@@ -7471,6 +7488,8 @@
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
|
||||
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
@@ -7548,7 +7567,9 @@
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
|
||||
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/mlly": {
|
||||
"version": "1.7.4",
|
||||
@@ -7648,7 +7669,9 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/neo-async": {
|
||||
"version": "2.6.2",
|
||||
@@ -7940,6 +7963,8 @@
|
||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.87.0.tgz",
|
||||
"integrity": "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"semver": "^7.3.5"
|
||||
},
|
||||
@@ -9573,6 +9598,8 @@
|
||||
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
|
||||
"integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.0",
|
||||
"expand-template": "^2.0.3",
|
||||
@@ -9599,6 +9626,8 @@
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@@ -9798,6 +9827,8 @@
|
||||
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
|
||||
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
|
||||
"license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"deep-extend": "^0.6.0",
|
||||
"ini": "~1.3.0",
|
||||
@@ -9812,7 +9843,9 @@
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
||||
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
|
||||
"license": "ISC"
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/rc9": {
|
||||
"version": "2.1.2",
|
||||
@@ -10512,7 +10545,9 @@
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/simple-get": {
|
||||
"version": "4.0.1",
|
||||
@@ -10533,6 +10568,8 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"decompress-response": "^6.0.0",
|
||||
"once": "^1.3.1",
|
||||
@@ -10875,6 +10912,8 @@
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -11061,6 +11100,8 @@
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz",
|
||||
"integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"chownr": "^1.1.1",
|
||||
"mkdirp-classic": "^0.5.2",
|
||||
@@ -11072,13 +11113,17 @@
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
||||
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
|
||||
"license": "ISC"
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/tar-fs/node_modules/readable-stream": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
@@ -11093,6 +11138,8 @@
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"bl": "^4.0.3",
|
||||
"end-of-stream": "^1.4.1",
|
||||
@@ -11286,6 +11333,8 @@
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
},
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
"apexcharts": "4.5.0",
|
||||
"axios": "^1.9.0",
|
||||
"axios-mock-adapter": "^2.1.0",
|
||||
"better-sqlite3": "^12.6.2",
|
||||
"gsap": "^3.14.2",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"lodash-es": "^4.17.21",
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// server/api/health.get.ts
|
||||
// Health check endpoint for Docker and monitoring
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
try {
|
||||
// Basic health check
|
||||
const health = {
|
||||
status: 'healthy',
|
||||
timestamp: new Date().toISOString(),
|
||||
uptime: process.uptime(),
|
||||
environment: process.env.NODE_ENV || 'development',
|
||||
memory: {
|
||||
used: Math.round(process.memoryUsage().heapUsed / 1024 / 1024),
|
||||
total: Math.round(process.memoryUsage().heapTotal / 1024 / 1024),
|
||||
unit: 'MB'
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
success: true,
|
||||
...health
|
||||
};
|
||||
} catch (error: any) {
|
||||
// If health check fails, return 500
|
||||
setResponseStatus(event, 500);
|
||||
return {
|
||||
success: false,
|
||||
status: 'unhealthy',
|
||||
error: error.message,
|
||||
timestamp: new Date().toISOString()
|
||||
};
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user