Files
services/app.js
T

143 lines
4.7 KiB
JavaScript
Raw Normal View History

2026-05-23 14:15:45 +08:00
const Koa = require('koa')
const Router = require('koa-router')
2026-06-03 14:15:55 +08:00
const https = require('https')
const fs = require('fs')
2026-05-23 14:15:45 +08:00
const cors = require('@koa/cors')
const bodyParser = require('koa-bodyparser')
const path = require('path')
2026-05-26 09:18:48 +08:00
require('dotenv').config()
2026-05-23 14:15:45 +08:00
const app = new Koa()
const router = new Router()
2026-06-03 14:15:55 +08:00
const ALLOWED_ORIGINS = (process.env.CORS_ORIGIN || '')
.split(',')
.map(s => s.trim())
.filter(Boolean)
const IS_PROD = process.env.NODE_ENV === 'production'
if (IS_PROD && ALLOWED_ORIGINS.length === 0) {
console.error('CORS_ORIGIN is required in production. Set comma-separated allowlist in .env')
}
function corsOriginCheck(ctx) {
const reqOrigin = ctx.request.header.origin || ''
if (ALLOWED_ORIGINS.length === 0) {
return IS_PROD ? '' : reqOrigin || '*'
}
if (ALLOWED_ORIGINS.includes('*')) return reqOrigin
return ALLOWED_ORIGINS.includes(reqOrigin) ? reqOrigin : ''
}
2026-05-23 14:15:45 +08:00
app.use(cors({
2026-06-03 14:15:55 +08:00
origin: corsOriginCheck,
credentials: true,
2026-05-23 14:15:45 +08:00
allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowHeaders: ['Content-Type', 'Authorization']
}))
app.use(bodyParser({
2026-05-26 13:37:55 +08:00
jsonLimit: '5mb',
formLimit: '5mb'
2026-05-23 14:15:45 +08:00
}))
app.use(require('koa-static')(path.join(__dirname, 'public')))
const errorHandler = async (ctx, next) => {
try {
await next()
if (ctx.status === 404) {
ctx.body = {
code: 404,
message: '接口不存在'
}
2026-06-04 08:20:49 +08:00
ctx.status = 404
2026-05-23 14:15:45 +08:00
}
} catch (error) {
console.error('Server error:', error)
ctx.status = error.status || 500
ctx.body = {
code: ctx.status,
2026-06-03 14:15:55 +08:00
message: IS_PROD ? '服务器内部错误' : error.message
2026-05-23 14:15:45 +08:00
}
}
}
app.use(errorHandler)
const orderRoutes = require('./routes/orders')
const categoryRoutes = require('./routes/categories')
const goodsRoutes = require('./routes/goods')
const userRoutes = require('./routes/users')
const uploadRoutes = require('./routes/upload')
const stockRoutes = require('./routes/stock')
2026-05-24 10:34:02 +08:00
const aiRoutes = require('./routes/ai')
2026-05-26 09:18:48 +08:00
const supplierRoutes = require('./routes/suppliers')
const purchaseRoutes = require('./routes/purchases')
const pointsGoodsRoutes = require('./routes/points-goods')
const statsRoutes = require('./routes/stats')
const priceListRoutes = require('./routes/price-list')
const pointsLogsRoutes = require('./routes/points-logs')
2026-05-26 09:30:17 +08:00
const recognizeRoutes = require('./routes/recognize')
2026-05-26 13:37:55 +08:00
const reportRoutes = require('./routes/reports')
const exportRoutes = require('./routes/export')
const subscribeRoutes = require('./routes/subscribe')
const addressRoutes = require('./routes/addresses')
const goodsSpecRoutes = require('./routes/goods-specs')
2026-06-03 14:15:55 +08:00
const cartRoutes = require('./routes/carts')
const refundRoutes = require('./routes/refunds')
const homeCategoryRoutes = require('./routes/homeCategories')
const paymentRoutes = require('./routes/payment')
2026-05-23 14:15:45 +08:00
router.use('/api/orders', orderRoutes)
router.use('/api/categories', categoryRoutes)
router.use('/api/goods', goodsRoutes)
router.use('/api/users', userRoutes)
router.use('/api/upload', uploadRoutes)
router.use('/api/stock', stockRoutes)
2026-05-24 10:34:02 +08:00
router.use('/api/ai', aiRoutes)
2026-05-26 09:18:48 +08:00
router.use('/api/suppliers', supplierRoutes)
router.use('/api/purchases', purchaseRoutes)
router.use('/api/points-goods', pointsGoodsRoutes)
router.use('/api/stats', statsRoutes)
router.use('/api/price-list', priceListRoutes)
router.use('/api/points/logs', pointsLogsRoutes)
2026-05-26 09:30:17 +08:00
router.use('/api/recognize', recognizeRoutes)
2026-05-26 13:37:55 +08:00
router.use('/api/reports', reportRoutes)
router.use('/api/export', exportRoutes)
router.use('/api/subscribe', subscribeRoutes)
router.use('/api/addresses', addressRoutes)
router.use('/api/goods-specs', goodsSpecRoutes)
2026-06-03 14:15:55 +08:00
router.use('/api/cart', cartRoutes)
router.use('/api/refunds', refundRoutes)
router.use('/api/home', homeCategoryRoutes)
router.use('/api/payment', paymentRoutes)
2026-05-23 14:15:45 +08:00
app.use(router.routes())
app.use(router.allowedMethods())
2026-06-03 14:15:55 +08:00
const { startHealthCheck } = require('./config/database')
const PORT = parseInt(process.env.PORT) || 3006
const HTTPS_ENABLED = process.env.HTTPS_ENABLED === '1'
const SSL_KEY = process.env.SSL_KEY_PATH
const SSL_CERT = process.env.SSL_CERT_PATH
if (HTTPS_ENABLED) {
if (!SSL_KEY || !SSL_CERT || !fs.existsSync(SSL_KEY) || !fs.existsSync(SSL_CERT)) {
console.error('HTTPS_ENABLED=1 but SSL_KEY_PATH / SSL_CERT_PATH missing or files not found')
process.exit(1)
}
const options = { key: fs.readFileSync(SSL_KEY), cert: fs.readFileSync(SSL_CERT) }
https.createServer(options, app.callback()).listen(PORT, () => {
console.log(`HTTPS server running on port ${PORT}`)
startHealthCheck(30000)
})
} else {
if (IS_PROD) {
console.warn('Running HTTP in production. Set HTTPS_ENABLED=1 + SSL_KEY_PATH/SSL_CERT_PATH')
}
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`)
startHealthCheck(30000)
})
}