Files
hr-performance-system/server.js
donald bf475d16c1 Add Claude API support and fix CORS issues
- 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>
2025-12-04 00:05:36 +08:00

152 lines
3.8 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 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;