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>
This commit is contained in:
donald
2025-12-04 00:05:36 +08:00
parent de89a64bf2
commit bf475d16c1
7 changed files with 832 additions and 2 deletions

151
server.js Normal file
View File

@@ -0,0 +1,151 @@
/**
* 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;