Files
XCDesktop/api/app.ts

106 lines
2.7 KiB
TypeScript
Raw Normal View History

2026-03-08 01:34:54 +08:00
/**
* API
*/
import express, {
type Request,
type Response,
type NextFunction,
} from 'express'
import cors from 'cors'
import dotenv from 'dotenv'
import filesRoutes from './core/files/routes.js'
import eventsRoutes from './core/events/routes.js'
import settingsRoutes from './core/settings/routes.js'
import uploadRoutes from './core/upload/routes.js'
import searchRoutes from './core/search/routes.js'
import type { ApiResponse } from '../shared/types.js'
import { errorHandler } from './middlewares/errorHandler.js'
import { NOTEBOOK_ROOT } from './config/paths.js'
import { ModuleManager } from './infra/moduleManager.js'
import { ServiceContainer } from './infra/container.js'
import { apiModules } from './modules/index.js'
import { validateModuleConsistency } from './infra/moduleValidator.js'
import path from 'path'
import fs from 'fs'
import { fileURLToPath } from 'url'
2026-03-08 01:34:54 +08:00
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
dotenv.config({ path: path.resolve(__dirname, './.env') })
2026-03-08 01:34:54 +08:00
const app: express.Application = express()
export const container = new ServiceContainer()
export const moduleManager = new ModuleManager(container)
app.use(cors())
app.use(express.json({ limit: '200mb' }))
app.use(express.urlencoded({ extended: true, limit: '200mb' }))
/**
* Core Routes
*/
app.use('/api/files', filesRoutes)
app.use('/api/events', eventsRoutes)
app.use('/api/settings', settingsRoutes)
app.use('/api/upload', uploadRoutes)
app.use('/api/search', searchRoutes)
/**
* Module Routes (loaded dynamically via ModuleManager)
*/
for (const module of apiModules) {
await moduleManager.register(module)
}
await validateModuleConsistency(apiModules)
for (const module of moduleManager.getAllModules()) {
await moduleManager.activate(module.metadata.id)
const router = await module.createRouter(container)
app.use('/api' + module.metadata.basePath, router)
}
app.get('/background.png', (req, res, next) => {
const customBgPath = path.join(NOTEBOOK_ROOT, '.config', 'background.png')
if (fs.existsSync(customBgPath)) {
res.sendFile(customBgPath)
} else {
next()
}
})
/**
* health
*/
app.use(
'/api/health',
(_req: Request, res: Response): void => {
const response: ApiResponse<{ message: string }> = {
success: true,
data: { message: 'ok' },
}
res.status(200).json(response)
},
)
/**
* 404 handler
*/
app.use((req: Request, res: Response, next: NextFunction) => {
if (req.path.startsWith('/api')) {
const response: ApiResponse<null> = {
success: false,
error: { code: 'NOT_FOUND', message: 'API不存在' },
}
res.status(404).json(response)
} else {
next()
}
})
app.use(errorHandler)
export default app