/** * 中央 Webhook 中继服务入口 * * 启动方式:npm run dev (开发) * npm start (生产,需先 npm run build) */ import 'dotenv/config'; import express from 'express'; import cors from 'cors'; import { initRelayDatabase } from './schema.js'; import { relayRoutes } from './routes.js'; import { getPort, getDbPath, getAdminKey, getUpstreamCallbackSecret, } from './lib/config.js'; const app = express(); const PORT = getPort(); // 启动前检查关键配置 if (!getAdminKey()) { console.warn('[Relay] ADMIN_KEY 未设置,管理员接口无法使用。建议运行 openssl rand -hex 32 生成。'); } if (!getUpstreamCallbackSecret()) { console.warn('[Relay] UPSTREAM_CALLBACK_SECRET 未设置,全局企微回调入口不可用。'); } // ---- 中间件 ---- app.use(cors()); app.use( express.json({ limit: '10mb', verify: (req: express.Request, _res: express.Response, buf: Buffer) => { (req as any).rawBody = buf.toString('utf8'); }, }), ); // ---- 初始化数据库 ---- initRelayDatabase(getDbPath()); console.log('[Relay] 数据库初始化完成'); // ---- 路由 ---- app.use('/api', relayRoutes); // ---- 全局 404 ---- app.use((_req, res) => { res.status(404).json({ error: 'Not found' }); }); // ---- 启动 ---- app.listen(PORT, () => { console.log(`\n========================================`); console.log(` 企微 Agent Skill 中央 Relay`); console.log(` http://localhost:${PORT}`); console.log(`========================================\n`); console.log(` 健康检查: http://localhost:${PORT}/api/health`); console.log(` 创建租户: POST http://localhost:${PORT}/api/admin/tenant`); console.log(` 全局 Webhook: POST http://localhost:${PORT}/api/webhook/ingest`); console.log(` 兼容 Webhook: POST http://localhost:${PORT}/api/webhook/ingest/:tenantId/:deviceGuid`); console.log(` 客户端轮询: POST http://localhost:${PORT}/api/poll`); console.log(` 客户端确认: POST http://localhost:${PORT}/api/ack\n`); });