251119:1200 set backend
This commit is contained in:
56
backend/.gitignore
vendored
Normal file
56
backend/.gitignore
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
# compiled output
|
||||
/dist
|
||||
/node_modules
|
||||
/build
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
pnpm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
|
||||
# Tests
|
||||
/coverage
|
||||
/.nyc_output
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# temp directory
|
||||
.temp
|
||||
.tmp
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
@@ -1,48 +0,0 @@
|
||||
# File: Dockerfile
|
||||
# บันทึกการแก้ไข: (สร้างไฟล์)
|
||||
|
||||
# --- STAGE 1: Builder ---
|
||||
# ติดตั้ง Dependencies และ Build โค้ด
|
||||
FROM node:18-alpine AS builder
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Copy package.json และ lock file
|
||||
COPY package*.json ./
|
||||
|
||||
# ติดตั้ง Dependencies (สำหรับ Build)
|
||||
RUN npm install
|
||||
|
||||
# Copy source code ทั้งหมด
|
||||
COPY . .
|
||||
|
||||
# Build application
|
||||
RUN npm run build
|
||||
|
||||
# ติดตั้งเฉพาะ Production Dependencies (สำหรับ Stage สุดท้าย)
|
||||
RUN npm prune --production
|
||||
|
||||
# --- STAGE 2: Runner ---
|
||||
# Image สุดท้ายที่มีขนาดเล็ก
|
||||
FROM node:18-alpine
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# (Security) สร้าง User ที่ไม่มีสิทธิ์ Root
|
||||
RUN addgroup -S nestjs && adduser -S nestjs -G nestjs
|
||||
USER nestjs
|
||||
|
||||
# Copy Production Dependencies (จาก Stage 1)
|
||||
COPY --from=builder /usr/src/app/node_modules ./node_modules
|
||||
|
||||
# Copy Build Artifacts (จาก Stage 1)
|
||||
COPY --from=builder /usr/src/app/dist ./dist
|
||||
|
||||
# Copy package.json (เผื่อจำเป็น)
|
||||
COPY package*.json ./
|
||||
|
||||
# เปิด Port (อ่านจาก Environment Variable)
|
||||
EXPOSE ${PORT:-3000}
|
||||
|
||||
# รัน Application
|
||||
CMD [ "node", "dist/main" ]
|
||||
@@ -1,62 +1,38 @@
|
||||
# File: docker-compose.yml
|
||||
# บันทึกการแก้ไข: (สร้างไฟล์)
|
||||
# (สำคัญ: ไฟล์นี้จะถูก import หรือคัดลอกไปใส่ใน UI ของ QNAP Container Station)
|
||||
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# ---------------------------------
|
||||
# Service 1: Backend (NestJS)
|
||||
# (Req 2.3)
|
||||
# ---------------------------------
|
||||
backend:
|
||||
build:
|
||||
context: ./backend # (สมมติว่า Dockerfile อยู่ในโฟลเดอร์ backend)
|
||||
dockerfile: Dockerfile
|
||||
image: lcbp3-backend:1.3.0 # (ตั้งชื่อ Image)
|
||||
container_name: lcbp3-backend
|
||||
restart: unless-stopped
|
||||
|
||||
# (สำคัญ) กำหนด Environment Variables ที่นี่ (ห้ามใช้ .env)
|
||||
# (Req 6.5, 2.1)
|
||||
mariadb:
|
||||
image: mariadb:11.8
|
||||
container_name: lcbp3-db-local
|
||||
restart: always
|
||||
environment:
|
||||
# --- App Config ---
|
||||
- PORT=3000
|
||||
- NODE_ENV=production
|
||||
|
||||
# --- Database (Req 2.4) ---
|
||||
# (ชี้ไปที่ Service 'mariadb' ใน Network 'lcbp3')
|
||||
- DATABASE_HOST=mariadb
|
||||
- DATABASE_PORT=3306
|
||||
- DATABASE_USER=your_db_user # (ต้องเปลี่ยน)
|
||||
- DATABASE_PASSWORD=your_db_pass # (ต้องเปลี่ยน)
|
||||
- DATABASE_NAME=lcbp3_dms
|
||||
|
||||
# --- Security (JWT) (Req 6.5) ---
|
||||
- JWT_SECRET=YOUR_VERY_STRONG_JWT_SECRET_KEY # (ต้องเปลี่ยน)
|
||||
- JWT_EXPIRATION_TIME=3600s # (เช่น 1 ชั่วโมง)
|
||||
|
||||
# --- Phase 4 Services ---
|
||||
- ELASTICSEARCH_URL=http://elasticsearch:9200 # (ชี้ไปที่ Service ES ถ้ามี)
|
||||
- N8N_WEBHOOK_URL=http://n8n:5678/webhook/your-webhook-id # (ชี้ไปที่ N8N)
|
||||
|
||||
# (สำคัญ) เชื่อมต่อ Network กลาง (Req 2.1)
|
||||
MYSQL_ROOT_PASSWORD: Center#2025
|
||||
MYSQL_DATABASE: lcbp3_dev
|
||||
MYSQL_USER: admin
|
||||
MYSQL_PASSWORD: Center2025
|
||||
ports:
|
||||
- '3306:3306'
|
||||
volumes:
|
||||
- db_data:/var/lib/mysql
|
||||
networks:
|
||||
- lcbp3
|
||||
- lcbp3-net
|
||||
|
||||
# (Deploy) ตั้งค่า Health Check
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3000/api/v1/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 20s # (รอให้ App เริ่มก่อน)
|
||||
# Optional: phpMyAdmin สำหรับจัดการ DB ง่ายๆ
|
||||
pma:
|
||||
image: phpmyadmin/phpmyadmin
|
||||
container_name: lcbp3-pma-local
|
||||
environment:
|
||||
PMA_HOST: mariadb
|
||||
ports:
|
||||
- '8080:80'
|
||||
depends_on:
|
||||
- mariadb
|
||||
networks:
|
||||
- lcbp3-net
|
||||
|
||||
volumes:
|
||||
db_data:
|
||||
|
||||
# ---------------------------------
|
||||
# Network กลาง (Req 2.1)
|
||||
# (ต้องสร้าง Network นี้ไว้ก่อนใน QNAP หรือสร้างพร้อมกัน)
|
||||
# ---------------------------------
|
||||
networks:
|
||||
lcbp3:
|
||||
external: true # (ถ้าสร้างไว้แล้ว)
|
||||
# name: lcbp3 # (ถ้าต้องการให้ Compose สร้าง)
|
||||
lcbp3-net:
|
||||
driver: bridge
|
||||
@@ -20,57 +20,34 @@
|
||||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@elastic/elasticsearch": "^9.2.0",
|
||||
"@nestjs/cache-manager": "^3.0.1",
|
||||
"@nestjs/common": "^11.0.1",
|
||||
"@nestjs/config": "^4.0.2",
|
||||
"@nestjs/core": "^11.0.1",
|
||||
"@nestjs/elasticsearch": "^11.1.0",
|
||||
"@nestjs/jwt": "^11.0.1",
|
||||
"@nestjs/passport": "^11.0.5",
|
||||
"@nestjs/platform-express": "^11.1.9",
|
||||
"@nestjs/schedule": "^6.0.1",
|
||||
"@nestjs/swagger": "^11.2.1",
|
||||
"@nestjs/platform-express": "^11.0.1",
|
||||
"@nestjs/typeorm": "^11.0.0",
|
||||
"@types/nodemailer": "^7.0.3",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"bcrypt": "^6.0.0",
|
||||
"cache-manager": "^7.2.4",
|
||||
"casl": "^0.2.0",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.2",
|
||||
"helmet": "^8.1.0",
|
||||
"multer": "^2.0.2",
|
||||
"mysql2": "^3.15.3",
|
||||
"nodemailer": "^7.0.10",
|
||||
"passport": "^0.7.0",
|
||||
"passport-jwt": "^4.0.1",
|
||||
"rate-limiter-flexible": "^8.2.1",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.1",
|
||||
"typeorm": "^0.3.27",
|
||||
"uuid": "^13.0.0"
|
||||
"typeorm": "^0.3.27"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@eslint/js": "^9.18.0",
|
||||
"@nestjs/cli": "^11.0.0",
|
||||
"@nestjs/schematics": "^11.0.0",
|
||||
"@nestjs/testing": "^11.1.9",
|
||||
"@nestjs/testing": "^11.0.1",
|
||||
"@types/express": "^5.0.0",
|
||||
"@types/jest": "^30.0.0",
|
||||
"@types/multer": "^2.0.0",
|
||||
"@types/node": "^22.10.7",
|
||||
"@types/passport-jwt": "^4.0.1",
|
||||
"@types/supertest": "^6.0.2",
|
||||
"eslint": "^9.18.0",
|
||||
"eslint-config-prettier": "^10.0.1",
|
||||
"eslint-plugin-prettier": "^5.2.2",
|
||||
"globals": "^16.0.0",
|
||||
"jest": "^30.2.0",
|
||||
"jest": "^30.0.0",
|
||||
"prettier": "^3.4.2",
|
||||
"source-map-support": "^0.5.21",
|
||||
"supertest": "^7.1.4",
|
||||
"supertest": "^7.0.0",
|
||||
"ts-jest": "^29.2.5",
|
||||
"ts-loader": "^9.5.2",
|
||||
"ts-node": "^10.9.2",
|
||||
|
||||
6725
backend/pnpm-lock.yaml
generated
Normal file
6725
backend/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,39 @@
|
||||
// src/app.module.ts
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
imports: [
|
||||
// 1. Load Config Module
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true, // ให้เรียกใช้ได้ทุกที่โดยไม่ต้อง import ใหม่
|
||||
envFilePath: '.env', // อ่านค่าจากไฟล์ .env
|
||||
}),
|
||||
|
||||
// 2. Setup TypeORM Connection (Async เพื่อรออ่าน Config ก่อน)
|
||||
TypeOrmModule.forRootAsync({
|
||||
imports: [ConfigModule],
|
||||
useFactory: async (configService: ConfigService) => ({
|
||||
type: 'mariadb', // หรือ 'mysql' ก็ได้เพราะใช้ driver เดียวกัน
|
||||
host: configService.get<string>('DB_HOST'),
|
||||
port: configService.get<number>('DB_PORT'),
|
||||
username: configService.get<string>('DB_USERNAME'),
|
||||
password: configService.get<string>('DB_PASSWORD'),
|
||||
database: configService.get<string>('DB_DATABASE'),
|
||||
// Auto Load Entities: โหลด Entity ทั้งหมดที่อยู่ในโปรเจกต์อัตโนมัติ
|
||||
autoLoadEntities: true,
|
||||
// Synchronize: true เฉพาะ Dev environment (ห้ามใช้ใน Prod)
|
||||
synchronize: configService.get<string>('NODE_ENV') === 'development',
|
||||
// Logging: เปิดดู Query SQL ตอน Dev
|
||||
logging: configService.get<string>('NODE_ENV') === 'development',
|
||||
}),
|
||||
inject: [ConfigService],
|
||||
}),
|
||||
],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
})
|
||||
export class AppModule {}
|
||||
export class AppModule {}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "nodenext",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "nodenext",
|
||||
"resolvePackageJsonExports": true,
|
||||
"esModuleInterop": true,
|
||||
@@ -10,16 +10,18 @@
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"target": "ES2023",
|
||||
"target": "ES2021",
|
||||
"sourceMap": true,
|
||||
"outDir": "./dist",
|
||||
"baseUrl": "./",
|
||||
"incremental": true,
|
||||
"skipLibCheck": true,
|
||||
"strictNullChecks": true,
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true, // บังคับใช้ Strict Mode
|
||||
"strictNullChecks": true, // ตรวจสอบค่า Null อย่างเคร่งครัด
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noImplicitAny": false,
|
||||
"strictBindCallApply": false,
|
||||
"noFallthroughCasesInSwitch": false
|
||||
"noImplicitAny": true, // ห้ามใช้ Any โดยไม่จำเป็น
|
||||
"strictBindCallApply": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user