import type { NextFunction, Request, Response } from 'express' import express from 'express' import process from 'node:process' import adminRouter from './routes/admin.js' import affiliateDashRouter from './routes/affiliate-dash.js' import collectRouter from './routes/collect.js' import filesRouter from './routes/files.js' import claimsRouter from './routes/claims.js' import kuaishouFeifeiRouter from './routes/kuaishou-feifei.js' import kuaishouIndustryRouter from './routes/kuaishou-industry.js' import open91Router from './routes/open-91.js' import shortLinksRouter from './routes/short-links.js' import workerRouter from './routes/worker.js' import { accessLogMiddleware } from './middleware/access-log.js' import { createCorsMiddleware } from './middleware/cors.js' import { buildHealthPayload, type StartupState } from './startup/state.js' import type { RuntimeConfig } from './types/runtime-config.js' import { buildSuccessPayload, sendRouteError } from './utils/http.js' type CreateAppOptions = { startupState: StartupState isShutdownStarted: () => boolean config: RuntimeConfig } export function createApp({ startupState, isShutdownStarted, config }: CreateAppOptions) { const app = express() app.use(accessLogMiddleware) app.use(createCorsMiddleware(config)) app.use( express.json({ limit: '2mb', verify: (req, _res, buffer) => { ;(req as Request).rawBody = buffer.toString('utf8') }, }), ) app.use(express.urlencoded({ extended: true })) app.get('/health', (_req, res) => { res.json( buildSuccessPayload( buildHealthPayload(startupState, isShutdownStarted()), startupState.core.ready ? 'ready' : 'starting', ), ) }) app.get('/health/live', (_req, res) => { res.json( buildSuccessPayload({ status: isShutdownStarted() ? 'shutting_down' : 'alive', pid: process.pid, mode: 'kuaishou-lite', }), ) }) app.get('/health/ready', (_req, res) => { if (startupState.core.ready) { res.json(buildSuccessPayload(buildHealthPayload(startupState, isShutdownStarted()), 'ready')) return } res.status(503).json({ code: 1, msg: startupState.core.lastError || '服务启动中,请稍后重试', errorCode: 'service_not_ready', time: Math.floor(Date.now() / 1000), data: buildHealthPayload(startupState, isShutdownStarted()), }) }) app.use((req, res, next) => { if (startupState.core.ready) { next() return } res.status(503).json({ code: 1, msg: startupState.core.lastError || '服务启动中,请稍后重试', errorCode: 'service_not_ready', time: Math.floor(Date.now() / 1000), data: { startup: { phase: startupState.phase, attemptCount: startupState.core.attemptCount, lastAttemptAt: startupState.core.lastAttemptAt, }, }, }) }) app.use('/api/v1/open/affiliate-dash', affiliateDashRouter) app.use('/api/v1/open/91', open91Router) app.use('/api/v1/open/kuaishou-industry', kuaishouIndustryRouter) app.use('/api/v1/open/kuaishou-feifei', kuaishouFeifeiRouter) app.use('/api/v1/claim', claimsRouter) app.use('/api/v1/collect', collectRouter) app.use('/api/v1/files', filesRouter) app.use('/api/v1/worker', workerRouter) app.use('/api/v1/admin', adminRouter) app.use('/s', shortLinksRouter) app.use((err: unknown, _req: Request, res: Response, _next: NextFunction) => { sendRouteError(res, err, '服务内部错误', '[global]') }) return app }