- Add Claude API integration to LLM service - Create Express backend server with CORS support - Add API proxy example page - Fix CORS errors by routing through backend - Update LLM configuration to support Claude - Add package.json with dependencies 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
152 lines
3.8 KiB
JavaScript
152 lines
3.8 KiB
JavaScript
/**
|
||
* Express Server
|
||
* HR 績效評核系統後端伺服器
|
||
*/
|
||
|
||
require('dotenv').config();
|
||
const express = require('express');
|
||
const cors = require('cors');
|
||
const helmet = require('helmet');
|
||
const morgan = require('morgan');
|
||
const path = require('path');
|
||
|
||
// Import routes
|
||
const llmRoutes = require('./routes/llm.routes');
|
||
|
||
// Import error handler
|
||
const { handleError } = require('./utils/errorHandler');
|
||
|
||
// Create Express app
|
||
const app = express();
|
||
const PORT = process.env.PORT || 3000;
|
||
|
||
// ============================================
|
||
// Middleware
|
||
// ============================================
|
||
|
||
// Security headers
|
||
app.use(helmet());
|
||
|
||
// CORS configuration
|
||
app.use(cors({
|
||
origin: process.env.FRONTEND_URL || '*',
|
||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
|
||
allowedHeaders: ['Content-Type', 'Authorization'],
|
||
credentials: true,
|
||
}));
|
||
|
||
// Body parsing
|
||
app.use(express.json({ limit: '10mb' }));
|
||
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
|
||
|
||
// Logging
|
||
if (process.env.NODE_ENV === 'development') {
|
||
app.use(morgan('dev'));
|
||
} else {
|
||
app.use(morgan('combined'));
|
||
}
|
||
|
||
// Static files
|
||
app.use(express.static('public'));
|
||
|
||
// ============================================
|
||
// Routes
|
||
// ============================================
|
||
|
||
// Health check
|
||
app.get('/health', (req, res) => {
|
||
res.json({
|
||
success: true,
|
||
message: 'HR Performance System API is running',
|
||
timestamp: new Date().toISOString(),
|
||
environment: process.env.NODE_ENV,
|
||
});
|
||
});
|
||
|
||
// API routes
|
||
app.use('/api/llm', llmRoutes);
|
||
|
||
// Root endpoint
|
||
app.get('/', (req, res) => {
|
||
res.json({
|
||
name: 'HR Performance System API',
|
||
version: '1.0.0',
|
||
description: '四卡循環績效管理系統',
|
||
endpoints: {
|
||
health: '/health',
|
||
llm: '/api/llm',
|
||
},
|
||
});
|
||
});
|
||
|
||
// ============================================
|
||
// Error Handling
|
||
// ============================================
|
||
|
||
// 404 handler
|
||
app.use((req, res, next) => {
|
||
res.status(404).json({
|
||
success: false,
|
||
error: {
|
||
statusCode: 404,
|
||
message: `Cannot ${req.method} ${req.path}`,
|
||
timestamp: new Date().toISOString(),
|
||
path: req.path,
|
||
},
|
||
});
|
||
});
|
||
|
||
// Global error handler
|
||
app.use(handleError);
|
||
|
||
// ============================================
|
||
// Server Start
|
||
// ============================================
|
||
|
||
const server = app.listen(PORT, () => {
|
||
console.log('='.repeat(50));
|
||
console.log('🚀 HR Performance System API Server');
|
||
console.log('='.repeat(50));
|
||
console.log(`📡 Server running on: http://localhost:${PORT}`);
|
||
console.log(`🌍 Environment: ${process.env.NODE_ENV || 'development'}`);
|
||
console.log(`📅 Started at: ${new Date().toLocaleString('zh-TW')}`);
|
||
console.log('='.repeat(50));
|
||
console.log('\n📚 Available endpoints:');
|
||
console.log(` GET / - API information`);
|
||
console.log(` GET /health - Health check`);
|
||
console.log(` POST /api/llm/test/* - Test LLM connections`);
|
||
console.log(` POST /api/llm/generate - Generate content with LLM`);
|
||
console.log('\n✨ Server is ready to accept connections!\n');
|
||
});
|
||
|
||
// Graceful shutdown
|
||
process.on('SIGTERM', () => {
|
||
console.log('\n⚠️ SIGTERM received. Shutting down gracefully...');
|
||
server.close(() => {
|
||
console.log('✅ Server closed');
|
||
process.exit(0);
|
||
});
|
||
});
|
||
|
||
process.on('SIGINT', () => {
|
||
console.log('\n⚠️ SIGINT received. Shutting down gracefully...');
|
||
server.close(() => {
|
||
console.log('✅ Server closed');
|
||
process.exit(0);
|
||
});
|
||
});
|
||
|
||
// Uncaught exception handler
|
||
process.on('uncaughtException', (error) => {
|
||
console.error('❌ Uncaught Exception:', error);
|
||
process.exit(1);
|
||
});
|
||
|
||
// Unhandled rejection handler
|
||
process.on('unhandledRejection', (reason, promise) => {
|
||
console.error('❌ Unhandled Rejection at:', promise, 'reason:', reason);
|
||
process.exit(1);
|
||
});
|
||
|
||
module.exports = app;
|