@mindbase/express-common 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,10 +1,3 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
1
  // core/state.ts
9
2
  import express from "express";
10
3
  function createState(options = {}) {
@@ -324,11 +317,11 @@ async function scan(onlyPaths = false) {
324
317
  if (cacheHit) {
325
318
  Logger_default.debug(`\u7F13\u5B58\u547D\u4E2D: ${file}`);
326
319
  }
327
- const module2 = await import(pathToFileURL(file).href);
320
+ const module = await import(pathToFileURL(file).href);
328
321
  const scanResult = {
329
322
  fileName,
330
- defaultExport: module2.default,
331
- allExports: module2,
323
+ defaultExport: module.default,
324
+ allExports: module,
332
325
  type,
333
326
  filePath: file,
334
327
  cacheHit
@@ -1795,7 +1788,7 @@ var DocManager = class {
1795
1788
  * @param module 模块名称(可选)
1796
1789
  * @returns 路由列表
1797
1790
  */
1798
- getRoutes(module2) {
1791
+ getRoutes(module) {
1799
1792
  if (!this.db) return [];
1800
1793
  try {
1801
1794
  let query = `
@@ -1804,9 +1797,9 @@ var DocManager = class {
1804
1797
  FROM doc_routes
1805
1798
  `;
1806
1799
  const params = {};
1807
- if (module2) {
1800
+ if (module) {
1808
1801
  query += " WHERE module = @module";
1809
- params.module = module2;
1802
+ params.module = module;
1810
1803
  }
1811
1804
  query += " ORDER BY module, method, path";
1812
1805
  const stmt = this.db.prepare(query);
@@ -2110,8 +2103,8 @@ router.get("/modules", (req, res) => {
2110
2103
  });
2111
2104
  router.get("/routes", (req, res) => {
2112
2105
  try {
2113
- const module2 = req.query.module;
2114
- const routes = docManager.getRoutes(module2);
2106
+ const module = req.query.module;
2107
+ const routes = docManager.getRoutes(module);
2115
2108
  const response = {
2116
2109
  code: 200,
2117
2110
  data: routes,
@@ -2262,6 +2255,7 @@ function createApp(options = {}) {
2262
2255
  }
2263
2256
 
2264
2257
  // commands/prepare.ts
2258
+ import fs5 from "fs";
2265
2259
  import path6 from "path";
2266
2260
  async function prepare(cwd = process.cwd()) {
2267
2261
  console.log("\u{1F680} MindBase \u73AF\u5883\u51C6\u5907\u5DE5\u5177");
@@ -2277,8 +2271,18 @@ async function prepare(cwd = process.cwd()) {
2277
2271
  console.log(` \u53D1\u73B0 ${results.length} \u4E2A\u7EC4\u4EF6\u6587\u4EF6`);
2278
2272
  console.log(` - \u8DEF\u7531: ${routeFiles.length}`);
2279
2273
  console.log(` - \u4E2D\u95F4\u4EF6: ${middlewareFiles.length}`);
2280
- console.log(` - Schema: ${schemaFiles.length}
2274
+ console.log(` - Schema: ${schemaFiles.length}`);
2275
+ if (schemaFiles.length > 0) {
2276
+ const schemaJsonPath = path6.join(cwd, ".drizzle-schemas.json");
2277
+ const relativeSchemaPaths = schemaFiles.map(
2278
+ (f) => path6.relative(cwd, f.filePath).replace(/\\/g, "/")
2279
+ );
2280
+ fs5.writeFileSync(schemaJsonPath, JSON.stringify(relativeSchemaPaths, null, 2));
2281
+ console.log(` \u5DF2\u751F\u6210 schema \u6E05\u5355: .drizzle-schemas.json
2281
2282
  `);
2283
+ } else {
2284
+ console.log(" \u8B66\u544A: \u672A\u627E\u5230 schema \u6587\u4EF6\n");
2285
+ }
2282
2286
  const schemas = {};
2283
2287
  for (const item of results) {
2284
2288
  if (item.type === "schema" && item.allExports) {
@@ -2310,10 +2314,6 @@ async function prepare(cwd = process.cwd()) {
2310
2314
  async function precache(cwd) {
2311
2315
  return prepare(cwd);
2312
2316
  }
2313
- if (__require.main === module) {
2314
- const cwd = process.argv[2] || process.cwd();
2315
- prepare(cwd);
2316
- }
2317
2317
 
2318
2318
  // feature/cron/CronManager.ts
2319
2319
  import { CronJob } from "cron";
@@ -2352,7 +2352,7 @@ function generateId() {
2352
2352
 
2353
2353
  // core/module/FindPackageRoot.ts
2354
2354
  import path7 from "path";
2355
- import fs5 from "fs";
2355
+ import fs6 from "fs";
2356
2356
  function findPackageRoot(startPath) {
2357
2357
  if (!startPath || typeof startPath !== "string") {
2358
2358
  throw new Error("\u65E0\u6548\u7684\u8D77\u59CB\u8DEF\u5F84\uFF1A\u8DEF\u5F84\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");
@@ -2364,10 +2364,10 @@ function findPackageRoot(startPath) {
2364
2364
  throw new Error(`\u65E0\u6CD5\u89E3\u6790\u8DEF\u5F84\uFF1A${startPath}`);
2365
2365
  }
2366
2366
  try {
2367
- if (!fs5.existsSync(currentPath)) {
2367
+ if (!fs6.existsSync(currentPath)) {
2368
2368
  throw new Error(`\u8DEF\u5F84\u4E0D\u5B58\u5728\uFF1A${currentPath}`);
2369
2369
  }
2370
- const stat = fs5.statSync(currentPath);
2370
+ const stat = fs6.statSync(currentPath);
2371
2371
  if (stat.isFile()) {
2372
2372
  currentPath = path7.dirname(currentPath);
2373
2373
  }
@@ -2377,8 +2377,8 @@ function findPackageRoot(startPath) {
2377
2377
  while (currentPath !== path7.parse(currentPath).root) {
2378
2378
  try {
2379
2379
  const pkgJsonPath = path7.join(currentPath, "package.json");
2380
- if (fs5.existsSync(pkgJsonPath)) {
2381
- const pkgStat = fs5.statSync(pkgJsonPath);
2380
+ if (fs6.existsSync(pkgJsonPath)) {
2381
+ const pkgStat = fs6.statSync(pkgJsonPath);
2382
2382
  if (pkgStat.isFile()) {
2383
2383
  return currentPath;
2384
2384
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../core/state.ts","../feature/scanner/FileScanner.ts","../utils/Dayjs.ts","../utils/Logger.ts","../utils/InitExpress.ts","../middleware/Cors.ts","../middleware/IpParser.ts","../middleware/UaParser.ts","../utils/InitDatabase.ts","../utils/MiddlewareRegistry.ts","../utils/RouteParser.ts","../utils/ZodSchemaParser.ts","../utils/TSTypeParser.ts","../utils/DocManager.ts","../utils/RouteRegistry.ts","../utils/ComponentRegistry.ts","../utils/InitErrorHandler.ts","../utils/HttpServer.ts","../routes/Doc.route.ts","../utils/Validate.ts","../zod/Doc.schema.ts","../core/app.ts","../commands/prepare.ts","../feature/cron/CronManager.ts","../core/module/FindPackageRoot.ts","../core/module/GetModulePath.ts","../core/module/CreateModule.ts","../utils/AppError.ts"],"sourcesContent":["import express, { Express } from \"express\";\nimport type { BetterSQLite3Database } from \"drizzle-orm/better-sqlite3\";\nimport { LogLevel } from \"../types\";\n\nexport interface MindBaseAppOptions {\n /** 服务监听主机名 @default 127.0.0.1 */\n host?: string;\n /** 服务监听端口 @default 3000 */\n port?: number;\n /** 是否启用请求日志 @default true */\n logging?: boolean;\n /** 静态文件目录路径 */\n staticPath?: string;\n /** 是否解析 User-Agent 信息 @default true */\n userAgent?: boolean;\n /** 是否解析 IP 地理位置信息 @default true */\n ip?: boolean;\n /** 是否启用 CORS 跨域 @default true */\n cors?: boolean;\n /** API 路由前缀,如 \"/api\" */\n apiPrefix?: string;\n /**\n * 日志级别(优先级从低到高):\n * - debug: 调试信息(显示所有)\n * - info: 普通信息(隐藏 debug)\n * - warn: 警告信息(隐藏 debug、info)\n * - error: 错误信息(隐藏 debug、info、warn)\n * - silent: 静默模式(隐藏所有)\n * @default \"info\"\n */\n logLevel?: LogLevel;\n /** 数据库配置 */\n database?: {\n /** SQLite 数据库文件路径 @default \"./data/app.db\" */\n path?: string;\n };\n /** 认证白名单路径(支持字符串和正则表达式) */\n authWhitelist?: (string | RegExp)[];\n}\nexport interface AppState {\n options: MindBaseAppOptions;\n express: Express;\n db?: BetterSQLite3Database<Record<string, any>>; // Drizzle 数据库实例\n schemas?: Record<string, any>; // 合并后的所有 schema\n}\n\nexport function createState(options: MindBaseAppOptions = {}): AppState {\n return {\n options: {\n host: options.host || \"127.0.0.1\",\n port: options.port || 3000,\n logging: options.logging !== false,\n staticPath: options.staticPath,\n userAgent: options.userAgent !== false,\n ip: options.ip !== false,\n cors: options.cors !== false,\n apiPrefix: options.apiPrefix,\n logLevel: options.logLevel || \"info\",\n authWhitelist: [],\n database: {\n path: options.database?.path || \"./data/app.db\",\n },\n },\n express: express(),\n schemas: {},\n };\n}\n","import { glob } from \"glob\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport { pathToFileURL } from \"url\";\nimport logger from \"../../utils/Logger\";\n\nconst CACHE_VERSION = \"2.0\";\nconst CACHE_DIR = path.join(process.cwd(), \"node_modules/.cache/mindbase\");\nconst CACHE_FILE = path.join(CACHE_DIR, \"startup-cache.json\");\n\n/**\n * 缓存条目接口\n */\ninterface CacheEntry {\n filePath: string;\n mtime: number;\n}\n\n/**\n * 缓存数据接口\n */\ninterface CacheData {\n version: string;\n entries: Map<string, CacheEntry>;\n}\n\n// 全局缓存数据\nlet cacheData: CacheData | null = null;\n\n/**\n * 扫描结果接口\n */\nexport interface ScanResult {\n fileName: string;\n defaultExport: any;\n allExports?: any;\n type: \"route\" | \"middleware\" | \"schema\";\n filePath: string;\n /** 缓存命中标志(文档已在数据库) */\n cacheHit?: boolean;\n}\n\n/**\n * 扫描器状态接口\n */\ninterface ScannerState {\n scanPaths: string[]; // 要扫描的目录数组\n baseDir: string; // 基础目录(最后扫描)\n}\n\n// 初始化扫描器状态\nconst state: ScannerState = {\n scanPaths: [],\n baseDir: \"\",\n};\n\n/**\n * 设置基础目录\n * @param baseDir 基础目录路径\n */\nexport function setBaseDir(baseDir: string): void {\n state.baseDir = baseDir;\n}\n\n/**\n * 添加扫描目录\n * @param dirPath 要添加的目录绝对路径\n * @throws 如果路径不是目录或不存在\n */\nexport function addScanPath(dirPath: string): void {\n // 验证路径是否为绝对路径\n if (!path.isAbsolute(dirPath)) {\n throw new Error(`路径必须是绝对路径: ${dirPath}`);\n }\n\n // 验证路径是否存在且为目录\n if (!fs.existsSync(dirPath)) {\n throw new Error(`目录不存在: ${dirPath}`);\n }\n\n if (!fs.statSync(dirPath).isDirectory()) {\n throw new Error(`路径不是目录: ${dirPath}`);\n }\n\n // 去重:检查路径是否已经存在\n if (state.scanPaths.includes(dirPath)) {\n return;\n }\n\n // 检查是否是基础目录的子目录,如果是则跳过\n if (state.baseDir && dirPath.startsWith(state.baseDir)) {\n return;\n }\n\n // 检查是否是其他已添加路径的子目录,如果是则跳过\n for (const existingPath of state.scanPaths) {\n if (dirPath.startsWith(existingPath)) {\n return;\n }\n }\n\n // 添加到扫描路径数组\n state.scanPaths.push(dirPath);\n}\n\n/**\n * 验证路径是否为有效目录\n * @param dirPath 目录路径\n * @returns 是否为有效目录\n */\nfunction isValidDirectory(dirPath: string): boolean {\n try {\n return fs.statSync(dirPath).isDirectory();\n } catch {\n return false;\n }\n}\n\n/**\n * 从文件路径提取文件名(不含扩展名)\n * @param filePath 文件路径\n * @returns 文件名(不含扩展名)\n */\nfunction extractFileName(filePath: string): string {\n const fileName = path.basename(filePath);\n // 移除 .route.ts, .middleware.ts 或 .schema.ts 扩展名\n return fileName.replace(/\\.(route|middleware|schema)\\.ts$/, \"\");\n}\n\n/**\n * 加载缓存数据\n * @returns 缓存数据对象,加载失败返回 null\n */\nasync function loadCache(): Promise<void> {\n try {\n if (!fs.existsSync(CACHE_FILE)) {\n cacheData = { version: CACHE_VERSION, entries: new Map() };\n return;\n }\n\n const json = fs.readFileSync(CACHE_FILE, \"utf-8\");\n const data = JSON.parse(json);\n\n // 检查缓存版本\n if (data.version !== CACHE_VERSION) {\n logger.debug(`缓存版本不匹配 (${data.version} vs ${CACHE_VERSION}),将重新构建`);\n cacheData = { version: CACHE_VERSION, entries: new Map() };\n return;\n }\n\n // 重建 Map\n cacheData = {\n version: data.version,\n entries: new Map(Object.entries(data.entries).map(([k, v]: [string, any]) => [k, v])),\n };\n\n logger.debug(`已加载缓存,包含 ${cacheData.entries.size} 个文件条目`);\n } catch (error) {\n logger.warn(`加载缓存失败,将重新构建: ${error}`);\n cacheData = { version: CACHE_VERSION, entries: new Map() };\n }\n}\n\n/**\n * 保存缓存数据\n */\nasync function saveCache(): Promise<void> {\n try {\n if (!cacheData) return;\n\n // 确保目录存在\n if (!fs.existsSync(CACHE_DIR)) {\n fs.mkdirSync(CACHE_DIR, { recursive: true });\n }\n\n // 序列化 Map 为普通对象\n const data = {\n version: cacheData.version,\n entries: Object.fromEntries(cacheData.entries),\n };\n\n fs.writeFileSync(CACHE_FILE, JSON.stringify(data, null, 2), \"utf-8\");\n logger.debug(`缓存已保存,包含 ${cacheData.entries.size} 个文件条目`);\n } catch (error) {\n logger.warn(`保存缓存失败: ${error}`);\n }\n}\n\n/**\n * 启动扫描目录\n * @param onlyPaths 是否仅返回路径,不导入模块\n * @returns 扫描结果数组\n */\nexport async function scan(onlyPaths: boolean = false): Promise<ScanResult[]> {\n // 加载缓存\n await loadCache();\n\n const results: ScanResult[] = [];\n const allScanPaths = [...state.scanPaths];\n const processedFiles = new Set<string>();\n\n // 如果设置了基础目录,将其添加到最后扫描\n if (state.baseDir) {\n allScanPaths.push(state.baseDir);\n }\n\n // 循环扫描所有目录\n for (const dirPath of allScanPaths) {\n if (!isValidDirectory(dirPath)) {\n logger.warn(`跳过无效目录: ${dirPath}`);\n continue;\n }\n\n // 构建 glob 模式\n const patterns = [\n { type: \"middleware\" as const, pattern: \"**/*.middleware.ts\" },\n { type: \"route\" as const, pattern: \"**/*.route.ts\" },\n { type: \"schema\" as const, pattern: \"**/*.schema.ts\" },\n ];\n\n for (const { type, pattern } of patterns) {\n const globPattern = path.join(dirPath, pattern).replace(/\\\\/g, \"/\");\n try {\n const files = await glob(globPattern, { absolute: true });\n for (const file of files) {\n // 去重:跳过已处理的文件\n if (processedFiles.has(file)) {\n continue;\n }\n processedFiles.add(file);\n\n try {\n const fileName = extractFileName(file);\n\n if (onlyPaths) {\n results.push({\n fileName,\n type,\n filePath: file,\n defaultExport: null,\n allExports: null,\n });\n continue;\n }\n\n // 检查文件修改时间\n const stats = await fs.promises.stat(file);\n const mtime = stats.mtimeMs;\n\n // 检查缓存命中\n const cached = cacheData?.entries.get(file);\n const cacheHit = cached && cached.mtime === mtime;\n\n if (cacheHit) {\n // 缓存命中,文档已在数据库\n logger.debug(`缓存命中: ${file}`);\n }\n\n // 导入模块(必须执行,获取 handler 用于 app.use)\n const module = await import(pathToFileURL(file).href);\n const scanResult: ScanResult = {\n fileName,\n defaultExport: module.default,\n allExports: module,\n type,\n filePath: file,\n cacheHit,\n };\n results.push(scanResult);\n\n // 更新缓存(无论是否命中,都更新 mtime)\n if (cacheData) {\n cacheData.entries.set(file, { filePath: file, mtime });\n }\n } catch (error) {\n logger.warn(`处理文件失败: ${file}`, error);\n }\n }\n } catch (error) {\n logger.warn(`扫描目录失败: ${dirPath} (Pattern: ${pattern})`, error);\n }\n }\n }\n\n // 保存缓存\n await saveCache();\n\n return results;\n}\n","import dayjs from \"dayjs\";\nimport \"dayjs/locale/zh-cn\";\nimport duration from \"dayjs/plugin/duration\";\nimport relativeTime from \"dayjs/plugin/relativeTime\";\nimport utc from \"dayjs/plugin/utc\";\n\n// 设置中文语言包\ndayjs.locale(\"zh-cn\");\n\n// 注册常用插件\ndayjs.extend(utc);\ndayjs.extend(duration);\ndayjs.extend(relativeTime);\n\nexport default dayjs;\nexport { dayjs };\n","import dayjs from \"./Dayjs\";\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\" | \"silent\";\n\nconst LOG_LEVELS = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n} as const;\n\nlet currentLogLevel: LogLevel = \"info\";\n\nconst COLORS = {\n debug: \"\\x1b[36m\",\n info: \"\\x1b[32m\",\n warn: \"\\x1b[33m\",\n error: \"\\x1b[31m\",\n reset: \"\\x1b[0m\",\n} as const;\n\n/**\n * 计算字符串在终端中的视觉宽度\n * 修复:区分单宽符号 (如 ✓) 和双宽符号 (如 中文、Emoji)\n */\nfunction getVisualWidth(str: string): number {\n let width = 0;\n const segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n for (const { segment } of segmenter.segment(str)) {\n const charCode = segment.charCodeAt(0);\n\n // 1. 基础 ASCII\n if (charCode <= 255) {\n width += 1;\n continue;\n }\n\n // 2. CJK 字符集范围 (常用中文、标点、全角符号)\n const isCJK =\n (charCode >= 0x4e00 && charCode <= 0x9fff) || // CJK Unified Ideographs\n (charCode >= 0x3000 && charCode <= 0x303f) || // CJK Symbols and Punctuation\n (charCode >= 0xff00 && charCode <= 0xffef); // Fullwidth Forms\n\n // 3. Emoji 或代理对 (通常 segment.length > 1)\n const isMultiByte = segment.length > 1;\n\n if (isCJK || isMultiByte) {\n width += 2;\n } else {\n // 4. 其他特殊符号 (如 ✓, ★, ☎) 在大多数终端占 1 格\n width += 1;\n }\n }\n return width;\n}\n\n/**\n * 截断字符串以适应视觉宽度,从头部截断并保留末尾\n */\nfunction truncateToWidth(str: string, maxWidth: number): string {\n const segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n const segments = Array.from(segmenter.segment(str)).map((s) => s.segment);\n\n if (getVisualWidth(str) <= maxWidth) return str;\n\n let currentWidth = 3; // 为 \"...\" 预留\n let result = \"\";\n\n // 从后往前遍历 segments\n for (let i = segments.length - 1; i >= 0; i--) {\n const segment = segments[i];\n const segmentWidth = getVisualWidth(segment);\n if (currentWidth + segmentWidth > maxWidth) break;\n result = segment + result;\n currentWidth += segmentWidth;\n }\n return \"...\" + result;\n}\n\nfunction formatMessage(level: LogLevel, message: string): string {\n const timestamp = dayjs().format(\"YYYY-MM-DD HH:mm:ss\");\n const terminalWidth = process.stdout.columns || 80;\n const timeStr = ` ${timestamp}`;\n const timeWidth = getVisualWidth(timeStr);\n const maxMessageWidth = terminalWidth - timeWidth - 2;\n\n let displayMessage = message;\n const messageWidth = getVisualWidth(displayMessage);\n\n if (messageWidth > maxMessageWidth) {\n displayMessage = truncateToWidth(displayMessage, maxMessageWidth);\n }\n\n const currentMsgWidth = getVisualWidth(displayMessage);\n const paddingCount = Math.max(0, terminalWidth - currentMsgWidth - timeWidth);\n const padding = \" \".repeat(paddingCount);\n\n return `${COLORS[level]}${displayMessage}${padding}${timeStr}${COLORS.reset}`;\n}\n\nconst startupTime = Date.now();\n\n// 标签填充函数(目标显示宽度 8,空格分散到字符间)\nfunction padTag(tag: string, targetWidth = 8): string {\n const currentWidth = getVisualWidth(tag);\n const padding = Math.max(0, targetWidth - currentWidth);\n\n if (padding === 0) return tag;\n\n // 将空格均匀分散到字符之间\n const chars = [...tag]; // 按码点分割\n const gapCount = chars.length + 1; // 间隙数 = 字符数 + 1(前后和中间)\n\n // 计算每个间隙的空格数\n const baseSpaces = Math.floor(padding / gapCount);\n const extraSpaces = padding % gapCount;\n\n let result = \"\";\n for (let i = 0; i < chars.length; i++) {\n // 每个间隙的空格 = 基础空格 + 额外空格(前 extraSpaces 个间隙多1个)\n const spaces = baseSpaces + (i < extraSpaces ? 1 : 0);\n result += \" \".repeat(spaces) + chars[i];\n }\n // 最后一个间隙\n result += \" \".repeat(baseSpaces + (chars.length < extraSpaces ? 1 : 0));\n\n return result;\n}\n\nfunction startupMessage(message: string, tag?: string): string {\n const diff = Date.now() - startupTime;\n const timeStr = diff.toString().padStart(6, \"0\");\n const tagStr = tag ? `【${padTag(tag)}】` : \"\";\n return `${COLORS[\"warn\"]}[${timeStr}] ${tagStr}${message}${COLORS[\"reset\"]}`;\n}\n\nfunction shouldLog(level: LogLevel): boolean {\n return LOG_LEVELS[level] >= LOG_LEVELS[currentLogLevel];\n}\n\nfunction formatArgs(args: any[]): string {\n return args\n .map((arg) => {\n if (arg instanceof Error) {\n return arg.message;\n }\n if (typeof arg === \"object\") {\n return JSON.stringify(arg, null, 2);\n }\n return String(arg);\n })\n .join(\" \");\n}\n\nexport const logger = {\n debug(...args: any[]): void {\n if (shouldLog(\"debug\")) {\n console.log(formatMessage(\"debug\", formatArgs(args)));\n }\n },\n\n info(...args: any[]): void {\n if (shouldLog(\"info\")) {\n console.log(formatMessage(\"info\", formatArgs(args)));\n }\n },\n\n warn(...args: any[]): void {\n if (shouldLog(\"warn\")) {\n console.warn(formatMessage(\"warn\", formatArgs(args)));\n }\n },\n\n error(...args: any[]): void {\n if (shouldLog(\"error\")) {\n // 先打印带颜色的格式化消息\n console.error(formatMessage(\"error\", formatArgs(args)));\n // 如果有 Error 对象,用 console.error 单独打印以显示堆栈\n const errorArg = args.find((arg) => arg instanceof Error);\n if (errorArg) {\n console.error(errorArg);\n }\n }\n },\n\n startup(tagOrMessage: string, ...args: any[]): void {\n // 如果有额外参数,第一个是标签,其余是消息\n // 否则第一个参数是消息,无标签\n if (args.length > 0) {\n console.log(startupMessage(formatArgs(args), tagOrMessage));\n } else {\n console.log(startupMessage(tagOrMessage));\n }\n },\n\n setLevel(level: LogLevel): void {\n currentLogLevel = level;\n },\n\n getLevel(): LogLevel {\n return currentLogLevel;\n },\n};\n\nexport default logger;\n","import express, { Express } from \"express\";\nimport fs from \"fs\";\nimport cookieParser from \"cookie-parser\";\nimport cors from \"../middleware/Cors\";\nimport ipParser from \"../middleware/IpParser\";\nimport uaParser from \"../middleware/UaParser\";\nimport { AppState } from \"../types/Index\";\nimport logger from \"./Logger\";\n\nexport default function initExpress(mindBaseState: AppState): void {\n const app = mindBaseState.express;\n const options = mindBaseState.options;\n app.getDB = () => mindBaseState.db;\n app.configs = mindBaseState.options;\n app.disable(\"x-powered-by\");\n app.use(express.urlencoded({ extended: false, limit: \"10mb\" }));\n app.use(express.json({ limit: \"10mb\" }));\n app.use(cookieParser());\n if (options.staticPath) {\n if (!fs.existsSync(options.staticPath)) {\n fs.mkdirSync(options.staticPath, { recursive: true });\n }\n app.use(express.static(options.staticPath));\n logger.startup(\"设置\", `静态目录: ${options.staticPath}`);\n }\n if (options.cors) {\n app.use(cors);\n logger.startup(\"设置\", \"跨域请求头\");\n }\n if (options.ip) {\n logger.startup(\"设置\", \"IP地址解析\");\n app.use(ipParser);\n }\n if (options.userAgent) {\n logger.startup(\"设置\", \"用户代理解析\");\n app.use(uaParser);\n }\n}\n","import { NextFunction, Request, Response } from \"express\";\n\n/**\n * 跨域处理\n * @description 为API请求添加处理跨域请求头,并处理Options 预请求\n */\nexport default function (req: Request, res: Response, next: NextFunction) {\n res.header(\"Access-Control-Allow-Origin\", \"*\");\n res.header(\"Access-Control-Allow-Credentials\", \"true\");\n res.header(\"Access-Control-Allow-Methods\", \"POST,GET,OPTIONS\");\n res.header(\"Access-Control-Allow-Headers\", \"Content-Type,Content-Length, Authorization, Accept,X-Requested-With\");\n if (req.method == \"OPTIONS\") {\n res.sendStatus(200);\n } else {\n next();\n }\n}\n","import { NextFunction, Request, Response } from \"express\";\nimport ipdb from \"ipip-ipdb\";\nimport { join } from \"path\";\nimport logger from \"../utils/Logger\";\n\n/**\n * IP 解析结果数据结构\n */\nexport interface IpInfo {\n address: string; // 原始 IP 地址\n location: string; // 格式化后的地理位置 (国家 省份 城市)\n country: string; // 国家\n province: string; // 省份/直辖市\n city: string; // 城市\n isp: string; // 运营商\n latitude: string; // 纬度\n longitude: string; // 经度\n isLocal: boolean; // 是否为本地/回环地址\n}\n\n// 预初始化数据库实例\nconst dbPath = join(process.cwd(), \"ipipfree.ipdb\");\nlet cityInstance: any;\n\ntry {\n cityInstance = new ipdb.City(dbPath);\n} catch (error) {\n logger.error(`[IpParser] Failed to load IP database at: ${dbPath}`);\n}\n\n/**\n * IP 解析中间件\n * 纯净实现:仅解析 IP 信息并打平数据结构,不包含冗余的向后兼容字段。\n */\nexport default function (req: Request, res: Response, next: NextFunction) {\n const ip = (req.headers[\"real-ip\"] || req.headers[\"x-real-ip\"] || req.ip) as string;\n\n const info: IpInfo = {\n address: ip,\n location: \"未知\",\n country: \"\",\n province: \"\",\n city: \"\",\n isp: \"\",\n latitude: \"\",\n longitude: \"\",\n isLocal: false,\n };\n\n // 处理本地回环地址\n const localIdentifiers = [\"127.0.0.1\", \"::1\", \"::ffff:127.0.0.1\", \"localhost\"];\n if (localIdentifiers.includes(ip)) {\n info.location = \"本机\";\n info.isLocal = true;\n res.locals.ip = info;\n return next();\n }\n\n // 数据库查询\n if (cityInstance) {\n try {\n const data = cityInstance.findMap(ip, \"CN\");\n if (data) {\n info.country = data.country_name || \"\";\n info.province = data.region_name || \"\";\n info.city = data.city_name || \"\";\n info.isp = data.isp_domain || \"\";\n info.latitude = data.latitude || \"\";\n info.longitude = data.longitude || \"\";\n\n const parts = [info.country, info.province, info.city].filter(Boolean);\n info.location = parts.join(\" \") || \"未知位置\";\n }\n } catch (err) {\n // 查询失败保持默认 info\n }\n }\n\n res.locals.ip = info;\n next();\n}\n","import { NextFunction, Request, Response } from \"express\";\nimport { UAParser } from \"ua-parser-js\";\n\nexport interface UaInfo {\n ua: string;\n browser: {\n name?: string;\n version?: string;\n major?: string;\n };\n engine: {\n name?: string;\n version?: string;\n };\n os: {\n name?: string;\n version?: string;\n };\n device: {\n model?: string;\n type?: string;\n vendor?: string;\n };\n cpu: {\n architecture?: string;\n };\n isMobile: boolean;\n}\n\n/**\n * UA 解析中间件\n * 纯净实现:仅解析 User-Agent 信息并存入 res.locals.UA\n */\nexport default function (req: Request, res: Response, next: NextFunction) {\n const parser = new UAParser(req.headers[\"user-agent\"] as string);\n const result = parser.getResult();\n\n const ua: UaInfo = {\n ua: result.ua,\n browser: result.browser,\n engine: result.engine,\n os: result.os,\n device: result.device,\n cpu: result.cpu,\n isMobile: result.device.type === \"mobile\",\n };\n\n res.locals.UA = ua;\n next();\n}\n","import path from \"path\";\nimport fs from \"fs\";\nimport { drizzle } from \"drizzle-orm/better-sqlite3\";\nimport { migrate } from \"drizzle-orm/better-sqlite3/migrator\";\nimport Database from \"better-sqlite3\";\nimport { AppState } from \"../core/state\";\nimport { ScanResult } from \"../types/Index\";\nimport logger from \"./Logger\";\n\n/**\n * 封装细节:从扫描结果中提取 Schema 并初始化数据库\n * @param state 应用状态\n * @param scannedResults 扫描结果\n * @returns 数据库实例\n * @throws 如果数据库设置失败\n */\nexport function setupDatabase(state: AppState, scannedResults: ScanResult[]) {\n try {\n if (!state) {\n throw new Error(\"应用状态对象不能为空\");\n }\n\n if (!Array.isArray(scannedResults)) {\n throw new Error(\"扫描结果必须是一个数组\");\n }\n\n const schemas: Record<string, any> = {};\n for (const item of scannedResults) {\n if (item.type === \"schema\" && item.allExports) {\n try {\n Object.assign(schemas, item.allExports);\n } catch (e) {\n logger.warn(`处理 Schema 文件失败: ${item.filePath}`, e);\n }\n }\n }\n state.schemas = schemas;\n\n logger.startup(\"扫描\", `提取到 ${Object.keys(schemas).length} 个 Schema 定义`);\n\n return initDatabase({\n schemas,\n state,\n });\n } catch (error) {\n logger.error(\"数据库设置失败:\", error);\n throw new Error(`数据库设置失败:${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * 初始化 SQLite 数据库\n * @param options 配置选项\n * @returns 数据库实例\n * @throws 如果数据库初始化失败\n */\nexport function initDatabase(options: { schemas: Record<string, any>; dbPath?: string; state?: AppState }): any {\n if (!options) {\n throw new Error(\"初始化选项不能为空\");\n }\n\n try {\n const currentDir = process.cwd();\n const dbPath = options.dbPath || options.state?.options?.database?.path || \"./data/app.db\";\n const absoluteDbPath = path.resolve(currentDir, dbPath);\n const dbDir = path.dirname(absoluteDbPath);\n\n logger.startup(\"数据库\", `初始化:路径=${absoluteDbPath}`);\n\n // 确保目录存在\n try {\n if (!fs.existsSync(dbDir)) {\n logger.startup(\"数据库\", `创建目录:${dbDir}`);\n fs.mkdirSync(dbDir, { recursive: true });\n }\n } catch (e) {\n throw new Error(`创建数据库目录失败:${e instanceof Error ? e.message : String(e)}`);\n }\n\n // 初始化 SQLite 数据库\n let sqlite: Database.Database;\n try {\n sqlite = new Database(absoluteDbPath);\n } catch (e) {\n throw new Error(`连接数据库失败:${e instanceof Error ? e.message : String(e)}`);\n }\n\n // SQLite 性能优化设置\n try {\n // 写前日志模式(提升并发性能)\n sqlite.pragma(\"journal_mode = WAL\");\n // 同步模式(安全性与性能平衡)\n sqlite.pragma(\"synchronous = NORMAL\");\n // 页面缓存:1GB(负值表示 KB)\n sqlite.pragma(\"cache_size = -1048576\");\n // 临时表使用内存\n sqlite.pragma(\"temp_store = MEMORY\");\n // 页面大小:4KB\n sqlite.pragma(\"page_size = 4096\");\n // WAL 自动检查点阈值(减少刷盘频率)\n sqlite.pragma(\"wal_autocheckpoint = 10000\");\n // 忙等待超时:5秒\n sqlite.pragma(\"busy_timeout = 5000\");\n } catch (e) {\n logger.warn(\"设置 SQLite 性能参数失败:\", e);\n // 继续执行,不中断初始化\n }\n\n // 初始化 Drizzle\n let db: any;\n try {\n db = drizzle(sqlite, { schema: options.schemas || {} });\n } catch (e) {\n // 关闭 SQLite 连接\n try {\n sqlite.close();\n } catch (closeError) {\n logger.warn(\"关闭数据库连接失败:\", closeError);\n }\n throw new Error(`初始化 Drizzle ORM 失败:${e instanceof Error ? e.message : String(e)}`);\n }\n\n // 如果提供了状态对象,更新它\n if (options.state) {\n options.state.db = db;\n }\n\n return db;\n } catch (error) {\n logger.error(\"数据库初始化失败:\", error);\n throw new Error(`数据库初始化失败:${error instanceof Error ? error.message : String(error)}`);\n }\n}\n","import { Express } from \"express\";\nimport { ScanResult } from \"../types/Index\";\nimport logger from \"./Logger\";\n\nexport async function registerMiddleware(app: Express, config: ScanResult): Promise<void> {\n const { fileName = \"anonymous\", defaultExport: handler } = config;\n\n try {\n app.use(handler);\n logger.startup(\"中间件\", `注册: ${fileName}`);\n } catch (error) {\n logger.error(`注册中间件失败 ${fileName}:`, error);\n }\n}\n","import {\n Project,\n SyntaxKind,\n Node,\n SourceFile,\n StringLiteral,\n ModuleKind,\n ScriptTarget,\n JSDoc,\n} from \"ts-morph\";\nimport * as path from \"path\";\nimport { RouteInfo, RequestSchema, ResponseSchema, FieldValidation } from \"../types/DocTypes\";\nimport logger from \"./Logger\";\nimport { ZodSchemaParser } from \"./ZodSchemaParser\";\nimport { TSTypeParser } from \"./TSTypeParser\";\n\n/**\n * apidoc 标签解析结果\n */\ninterface ApiDocTags {\n params: Array<{\n name: string;\n type: string;\n description: string;\n required: boolean;\n enumValues?: string[];\n }>;\n success: Array<{\n name: string;\n type: string;\n description: string;\n parent?: string;\n }>;\n}\n\n/**\n * 路由解析器\n * 使用 ts-morph 解析路由文件,提取路由信息\n */\nexport class RouteParser {\n private project: Project;\n private schemaParser: ZodSchemaParser;\n private tsTypeParser: TSTypeParser;\n\n constructor() {\n this.project = new Project({\n compilerOptions: {\n module: ModuleKind.CommonJS,\n target: ScriptTarget.ES2018,\n allowJs: true,\n },\n });\n this.schemaParser = new ZodSchemaParser();\n this.tsTypeParser = new TSTypeParser();\n }\n\n /**\n * 解析单个路由文件\n * @param filePath 路由文件路径\n * @returns 路由信息数组\n */\n public parseRouteFile(filePath: string): RouteInfo[] {\n try {\n const sourceFile = this.project.addSourceFileAtPath(filePath);\n const routes: RouteInfo[] = [];\n\n // 获取所有导入的 schema 文件映射\n const schemaFiles = this.getImportedSchemaFiles(sourceFile, filePath);\n\n // 获取所有类型导入映射(用于响应类型解析)\n const typeImports = this.getTypeImports(sourceFile, filePath);\n\n // 查找所有路由调用\n sourceFile.forEachDescendant((node) => {\n const callExpr = node as any;\n if (callExpr.isKind && callExpr.isKind(SyntaxKind.CallExpression) && callExpr.getExpression && callExpr.getExpression().isKind(SyntaxKind.PropertyAccessExpression)) {\n const propAccess = callExpr.getExpression();\n const object = propAccess.getExpression && propAccess.getExpression().getText();\n const method = propAccess.getName && propAccess.getName();\n\n // 检查是否是 router 的 HTTP 方法调用\n if (object === \"router\" && [\"get\", \"post\", \"put\", \"delete\", \"patch\"].includes(method)) {\n // 提取路由路径\n const args = callExpr.getArguments && callExpr.getArguments();\n if (args && args.length > 0) {\n const pathArg = args[0];\n if (pathArg.isKind && pathArg.isKind(SyntaxKind.StringLiteral)) {\n const routePath = pathArg.getText && pathArg.getText().replace(/['\"]/g, \"\");\n\n // 提取 JSDoc 注释\n const jsDoc = callExpr.getPreviousSiblingIfKind && callExpr.getPreviousSiblingIfKind(SyntaxKind.JSDocComment);\n let summary = \"\";\n let description = \"\";\n let requestSchema: RequestSchema | undefined;\n let responseSchema: ResponseSchema | undefined;\n\n if (jsDoc) {\n const commentText = jsDoc.getCommentText && jsDoc.getCommentText();\n if (commentText) {\n const lines = commentText.split(\"\\n\").map((line) => line.trim());\n summary = lines[0] || \"\";\n description = lines.slice(1).join(\"\\n\").trim() || summary;\n }\n\n // 解析 apidoc 格式的注释标签\n try {\n const fullCommentText = jsDoc.getFullText?.() || commentText || \"\";\n const apiDocTags = this.parseApiDocTags(fullCommentText);\n\n // 从 @apiParam 构建请求 Schema(优先级高于 validate 中间件)\n if (apiDocTags.params.length > 0) {\n requestSchema = this.buildRequestSchemaFromTags(apiDocTags.params);\n }\n\n // 从 @apiSuccess 构建响应 Schema\n if (apiDocTags.success.length > 0) {\n responseSchema = this.buildResponseSchemaFromTags(apiDocTags.success);\n }\n } catch (error) {\n logger.warn(`解析 apidoc 注释失败: ${filePath}:${routePath}`, error);\n }\n\n // 如果没有 @apiSuccess,尝试提取 @returns 标签(降级方案)\n if (!responseSchema) {\n responseSchema = this.extractResponseSchema(jsDoc, sourceFile, typeImports);\n }\n }\n\n // 提取中间件信息\n const middlewares: string[] = [];\n for (let i = 1; i < args.length - 1; i++) {\n const arg = args[i];\n if (arg.isKind(SyntaxKind.CallExpression)) {\n const mwCallExpr = arg as any;\n const expr = mwCallExpr.getExpression();\n if (expr.isKind(SyntaxKind.Identifier)) {\n middlewares.push(expr.getText());\n } else if (expr.isKind(SyntaxKind.PropertyAccessExpression)) {\n middlewares.push(expr.getText());\n }\n }\n }\n\n // 如果没有从注释获取到请求 Schema,尝试从 validate 中间件获取(降级方案)\n if (!requestSchema) {\n requestSchema = this.extractRequestSchema(args, schemaFiles);\n }\n\n const routeInfo: RouteInfo = {\n module: path.basename(path.dirname(filePath)).toLowerCase(),\n method: method.toUpperCase(),\n path: routePath,\n fullPath: \"\", // 完整路径会在注册时填充\n summary,\n description,\n requestSchema,\n responseSchema,\n middlewares,\n filePath,\n };\n\n routes.push(routeInfo);\n }\n }\n }\n }\n });\n\n return routes;\n } catch (error) {\n logger.error(`解析路由文件失败: ${filePath}`, error);\n return [];\n }\n }\n\n /**\n * 获取导入的 schema 文件映射\n * @returns Map<变量名, 文件绝对路径>\n */\n private getImportedSchemaFiles(\n sourceFile: SourceFile,\n currentFilePath: string\n ): Map<string, string> {\n const schemaFiles = new Map<string, string>();\n\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const source = importDecl.getModuleSpecifierValue();\n\n // 检查是否是 schema 相关的导入\n if (source.includes(\".schema\") || source.includes(\"/zod/\") || source.includes(\"\\\\zod\\\\\")) {\n // 解析相对路径为绝对路径\n const absolutePath = this.resolveImportPath(\n currentFilePath,\n source\n );\n if (absolutePath) {\n // 记录导入的变量名 -> 文件路径映射\n for (const specifier of importDecl.getNamedImports()) {\n logger.debug(`发现 schema 导入: ${specifier.getName()} -> ${absolutePath}`);\n schemaFiles.set(specifier.getName(), absolutePath);\n }\n } else {\n logger.debug(`无法解析 schema 导入路径: ${source}`);\n }\n }\n }\n\n return schemaFiles;\n }\n\n /**\n * 获取所有类型导入映射(用于响应类型解析)\n * @returns Map<类型名, 文件绝对路径>\n */\n private getTypeImports(\n sourceFile: SourceFile,\n currentFilePath: string\n ): Map<string, string> {\n const typeImports = new Map<string, string>();\n\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const source = importDecl.getModuleSpecifierValue();\n\n // 解析相对路径为绝对路径\n const absolutePath = this.resolveImportPath(currentFilePath, source);\n if (absolutePath) {\n // 记录所有命名导入\n for (const specifier of importDecl.getNamedImports()) {\n typeImports.set(specifier.getName(), absolutePath);\n }\n }\n }\n\n return typeImports;\n }\n\n /**\n * 从 JSDoc 中提取响应 Schema\n */\n private extractResponseSchema(\n jsDoc: JSDoc,\n sourceFile: SourceFile,\n typeImports: Map<string, string>\n ): ResponseSchema | undefined {\n // 获取所有 JSDoc 标签\n const tags = jsDoc.getTags();\n\n for (const tag of tags) {\n const tagName = tag.getTagName();\n\n // 检查 @returns 或 @return 标签\n if (tagName === \"returns\" || tagName === \"return\") {\n // 获取标签的完整文本\n const tagText = tag.getText?.() || \"\";\n logger.debug(`@returns 标签文本: ${tagText}`);\n\n // 尝试从标签文本中提取类型 {TypeName}\n const typeMatch = tagText.match(/@\\s*returns?\\s*\\{([^}]+)\\}/i);\n if (typeMatch) {\n const typeString = typeMatch[1].trim();\n logger.debug(`从标签文本提取类型: ${typeString}`);\n\n const responseSchema = this.tsTypeParser.parseResponseType(\n sourceFile,\n typeString,\n typeImports\n );\n\n if (responseSchema) {\n return responseSchema;\n }\n }\n\n // 尝试从注释中提取类型\n const comment = tag.getCommentText?.();\n if (comment) {\n const commentMatch = comment.match(/^\\{([^}]+)\\}/);\n if (commentMatch) {\n const typeString = commentMatch[1].trim();\n logger.debug(`从注释提取类型: ${typeString}`);\n\n const responseSchema = this.tsTypeParser.parseResponseType(\n sourceFile,\n typeString,\n typeImports\n );\n\n if (responseSchema) {\n return responseSchema;\n }\n }\n }\n\n // 尝试使用 ts-morph 的类型表达式\n const typeExpression = (tag as any).getTypeExpression?.();\n if (typeExpression) {\n const typeNode = typeExpression.getType?.();\n if (typeNode) {\n const typeString = typeNode.getText();\n logger.debug(`从类型表达式提取类型: ${typeString}`);\n\n if (typeString && typeString !== \"any\") {\n const responseSchema = this.tsTypeParser.parseResponseType(\n sourceFile,\n typeString,\n typeImports\n );\n\n if (responseSchema) {\n return responseSchema;\n }\n }\n }\n }\n }\n }\n\n return undefined;\n }\n\n /**\n * 解析导入路径为绝对路径\n */\n private resolveImportPath(\n currentFilePath: string,\n importPath: string\n ): string | null {\n try {\n // 处理相对路径\n if (importPath.startsWith(\".\")) {\n const currentDir = path.dirname(currentFilePath);\n const absolutePath = path.resolve(currentDir, importPath);\n\n // 尝试添加 .ts 扩展名\n const tsPath = absolutePath.endsWith(\".ts\")\n ? absolutePath\n : `${absolutePath}.ts`;\n return tsPath;\n }\n\n // 非相对路径暂不处理\n return null;\n } catch (error) {\n logger.warn(`解析导入路径失败: ${importPath}`);\n return null;\n }\n }\n\n /**\n * 提取请求 Schema\n */\n private extractRequestSchema(\n args: any[],\n schemaFiles: Map<string, string>\n ): RequestSchema | undefined {\n for (const arg of args) {\n // 路由参数可能是 validate(...) 或 validate(...) as any\n // 需要先处理 as any 类型断言\n let targetArg = arg;\n if (\n arg.isKind &&\n arg.isKind(SyntaxKind.AsExpression)\n ) {\n targetArg = arg.getExpression();\n }\n\n // 检查是否是 validate 调用\n if (\n targetArg.isKind &&\n targetArg.isKind(SyntaxKind.CallExpression) &&\n targetArg.getExpression &&\n targetArg.getExpression().isKind &&\n targetArg.getExpression().isKind(SyntaxKind.Identifier) &&\n targetArg.getExpression().getText() === \"validate\"\n ) {\n const validateArgs = targetArg.getArguments();\n if (validateArgs.length === 0) continue;\n\n // 获取 schema 变量名\n const schemaArg = validateArgs[0];\n let schemaName: string;\n\n // 处理 schema 参数中的 as any 类型断言\n if (\n schemaArg.isKind &&\n schemaArg.isKind(SyntaxKind.AsExpression)\n ) {\n schemaName = schemaArg.getExpression().getText();\n } else {\n schemaName = schemaArg.getText();\n }\n\n // 获取 target 参数\n let target: \"body\" | \"query\" | \"params\" = \"body\";\n if (validateArgs.length > 1) {\n const targetArgParam = validateArgs[1];\n if (\n targetArgParam.isKind &&\n targetArgParam.isKind(SyntaxKind.StringLiteral)\n ) {\n target = (targetArgParam as StringLiteral).getLiteralValue() as\n | \"body\"\n | \"query\"\n | \"params\";\n }\n }\n\n // 解析 schema 文件\n const schemaFilePath = schemaFiles.get(schemaName);\n if (schemaFilePath) {\n try {\n const schemaSourceFile =\n this.project.addSourceFileAtPath(schemaFilePath);\n const fields = this.schemaParser.parseSchemaVariable(\n schemaSourceFile,\n schemaName\n );\n\n if (fields) {\n return { target, fields };\n }\n } catch (error) {\n logger.warn(`解析 schema 文件失败: ${schemaFilePath}`, error);\n }\n } else {\n logger.debug(`未找到 schema 文件映射: ${schemaName}`);\n }\n }\n }\n\n return undefined;\n }\n\n /**\n * 解析多个路由文件\n * @param filePaths 路由文件路径数组\n * @returns 路由信息数组\n */\n public parseRouteFiles(filePaths: string[]): RouteInfo[] {\n const allRoutes: RouteInfo[] = [];\n for (const filePath of filePaths) {\n const routes = this.parseRouteFile(filePath);\n allRoutes.push(...routes);\n }\n return allRoutes;\n }\n\n /**\n * 解析 apidoc 格式的注释标签\n * @param commentText JSDoc 注释文本\n * @returns 解析出的标签信息\n */\n private parseApiDocTags(commentText: string): ApiDocTags {\n const tags: ApiDocTags = { params: [], success: [] };\n\n // 解析 @apiParam 标签\n // 格式: @apiParam {type} [name] description\n const paramRegex = /@apiParam\\s+\\{([^}]+)\\}\\s*(?:\\[([^\\]]+)\\]|(\\S+))\\s*(.*)/g;\n let match;\n while ((match = paramRegex.exec(commentText)) !== null) {\n const [, typeStr, optionalName, requiredName, description] = match;\n const name = optionalName || requiredName;\n const required = !optionalName;\n\n // 解析类型字符串\n const typeInfo = this.parseParamType(typeStr);\n\n tags.params.push({\n name,\n type: typeInfo.type,\n description: description.trim(),\n required,\n enumValues: typeInfo.enumValues,\n });\n }\n\n // 解析 @apiSuccess 标签\n // 格式: @apiSuccess {type} field 或 @apiSuccess {type} parent.field\n const successRegex = /@apiSuccess\\s+\\{([^}]+)\\}\\s+([^\\s]+)\\s*(.*)/g;\n while ((match = successRegex.exec(commentText)) !== null) {\n const [, typeStr, fieldPath, description] = match;\n\n // 解析字段路径 (如 \"data.user.id\")\n const parts = fieldPath.split(\".\");\n const name = parts[parts.length - 1];\n const parent = parts.length > 1 ? parts.slice(0, -1).join(\".\") : undefined;\n\n // 解析类型字符串\n const typeInfo = this.parseParamType(typeStr);\n\n tags.success.push({\n name,\n type: typeInfo.type,\n description: description.trim(),\n parent,\n });\n }\n\n return tags;\n }\n\n /**\n * 解析 apidoc 类型字符串\n * @param typeStr 类型字符串,如 \"string\", \"string=\", \"number[]\", {string=\"a\",\"b\"}\n * @returns 解析后的类型信息\n */\n private parseParamType(typeStr: string): {\n type: FieldValidation[\"type\"];\n array?: boolean;\n enumValues?: string[];\n } {\n typeStr = typeStr.trim();\n\n // 处理枚举类型: {string=\"a\",\"b\"}\n const enumMatch = typeStr.match(/^(\\w+)=(.+)$/);\n if (enumMatch) {\n const baseType = enumMatch[1];\n const enumValues = enumMatch[2]\n .split(\",\")\n .map((v) => v.trim().replace(/^[\"']|[\"']$/g, \"\"));\n\n return {\n type: this.mapTypeName(baseType),\n enumValues,\n };\n }\n\n // 处理数组类型: number[]\n if (typeStr.endsWith(\"[]\")) {\n const baseType = typeStr.slice(0, -2);\n return {\n type: this.mapTypeName(baseType),\n array: true,\n };\n }\n\n // 处理可空类型: string?\n if (typeStr.endsWith(\"?\")) {\n const baseType = typeStr.slice(0, -1);\n return {\n type: this.mapTypeName(baseType),\n };\n }\n\n // 基础类型\n return {\n type: this.mapTypeName(typeStr),\n };\n }\n\n /**\n * 映射类型名称到 FieldValidation 类型\n */\n private mapTypeName(typeName: string): FieldValidation[\"type\"] {\n const typeMap: Record<string, FieldValidation[\"type\"]> = {\n string: \"string\",\n number: \"number\",\n integer: \"number\",\n boolean: \"boolean\",\n array: \"array\",\n object: \"object\",\n file: \"file\",\n date: \"date\",\n };\n\n return typeMap[typeName.toLowerCase()] || \"any\";\n }\n\n /**\n * 从 @apiParam 标签构建请求 Schema\n */\n private buildRequestSchemaFromTags(\n params: ApiDocTags[\"params\"]\n ): RequestSchema {\n const fields: Record<string, FieldValidation> = {};\n\n for (const param of params) {\n fields[param.name] = {\n type: param.type as FieldValidation[\"type\"],\n required: param.required,\n constraints: param.enumValues\n ? { custom: [`可选值: ${param.enumValues.join(\", \")}`] }\n : undefined,\n };\n }\n\n return { target: \"body\", fields };\n }\n\n /**\n * 从 @apiSuccess 标签构建响应 Schema\n */\n private buildResponseSchemaFromTags(\n success: ApiDocTags[\"success\"]\n ): ResponseSchema {\n const fields: Record<string, FieldValidation> = {};\n\n // 先处理所有顶级字段,为嵌套字段做准备\n for (const field of success) {\n if (!field.parent && !fields[field.name]) {\n // 顶级字段,如果是 object 类型,添加 properties 属性\n if (field.type === \"object\") {\n fields[field.name] = {\n type: \"object\",\n required: true,\n properties: {},\n };\n } else {\n fields[field.name] = {\n type: field.type as FieldValidation[\"type\"],\n required: true,\n };\n }\n }\n }\n\n // 处理嵌套字段\n for (const field of success) {\n if (field.parent) {\n // 处理嵌套字段 (如 data.user.id)\n const parts = field.parent.split(\".\");\n let current = fields;\n\n // 创建/获取父级对象链\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n if (!current[part]) {\n // 如果父级字段不存在,创建它\n current[part] = {\n type: \"object\",\n required: true,\n properties: {},\n };\n } else if (!current[part].properties) {\n // 如果父级字段存在但没有 properties(作为顶级字段创建的),添加 properties\n current[part].properties = {};\n }\n // 进入到下一级的 properties\n current = current[part].properties!;\n }\n\n // 添加叶子节点到最内层对象的 properties\n current[field.name] = {\n type: field.type as FieldValidation[\"type\"],\n required: true,\n };\n }\n }\n\n return { fields };\n }\n}\n\n// 导出单例实例\nexport const routeParser = new RouteParser();\n","import {\n Node,\n SyntaxKind,\n SourceFile,\n VariableDeclaration,\n CallExpression,\n ObjectLiteralExpression,\n PropertyAccessExpression,\n Identifier,\n StringLiteral,\n NumericLiteral,\n AsExpression,\n} from \"ts-morph\";\nimport { FieldValidation, FieldConstraints } from \"../types/DocTypes\";\nimport logger from \"./Logger\";\n\n/**\n * Zod Schema AST 解析器\n * 从 Zod schema 变量定义中提取字段结构\n */\nexport class ZodSchemaParser {\n /**\n * 解析 schema 变量,返回字段结构\n */\n public parseSchemaVariable(\n sourceFile: SourceFile,\n schemaName: string\n ): Record<string, FieldValidation> | null {\n try {\n // 1. 查找 schema 变量声明\n const variableDecl = this.findVariableDeclaration(sourceFile, schemaName);\n if (!variableDecl) {\n logger.warn(`未找到 schema 变量: ${schemaName}`);\n return null;\n }\n\n // 2. 获取初始化表达式\n const initializer = variableDecl.getInitializer();\n if (!initializer) {\n logger.warn(`schema 变量 ${schemaName} 没有初始化表达式`);\n return null;\n }\n\n // 3. 解析 z.object({...}) 调用\n return this.parseZodObject(initializer);\n } catch (error) {\n logger.error(`解析 schema 变量失败: ${schemaName}`, error);\n return null;\n }\n }\n\n /**\n * 查找变量声明\n */\n private findVariableDeclaration(\n sourceFile: SourceFile,\n name: string\n ): VariableDeclaration | null {\n for (const decl of sourceFile.getVariableDeclarations()) {\n if (decl.getName() === name) {\n return decl;\n }\n }\n return null;\n }\n\n /**\n * 解析 z.object({...}) 调用\n */\n private parseZodObject(node: Node): Record<string, FieldValidation> | null {\n // 处理 as any 类型断言\n let targetNode = node;\n if (Node.isAsExpression(node)) {\n targetNode = node.getExpression();\n }\n\n // 检查是否是 z.object() 调用\n if (Node.isCallExpression(targetNode)) {\n const expr = targetNode.getExpression();\n if (Node.isPropertyAccessExpression(expr)) {\n const propText = expr.getText();\n if (propText === \"z.object\") {\n const args = targetNode.getArguments();\n if (args.length > 0 && Node.isObjectLiteralExpression(args[0])) {\n return this.parseObjectLiteral(args[0]);\n }\n }\n }\n }\n return null;\n }\n\n /**\n * 解析对象字面量中的字段定义\n */\n private parseObjectLiteral(\n objLit: ObjectLiteralExpression\n ): Record<string, FieldValidation> {\n const fields: Record<string, FieldValidation> = {};\n\n for (const prop of objLit.getProperties()) {\n if (Node.isPropertyAssignment(prop)) {\n const fieldName = prop.getName();\n const initializer = prop.getInitializer();\n if (initializer) {\n fields[fieldName] = this.parseZodField(initializer);\n }\n }\n }\n\n return fields;\n }\n\n /**\n * 解析单个 Zod 字段定义\n */\n private parseZodField(node: Node): FieldValidation {\n const field: FieldValidation = {\n type: \"any\",\n required: true,\n };\n\n // 处理 as any 类型断言\n let targetNode = node;\n if (Node.isAsExpression(node)) {\n targetNode = node.getExpression();\n }\n\n // 收集方法调用链\n const callChain = this.collectCallChain(targetNode);\n\n // 解析类型和约束\n for (const call of callChain) {\n this.applyZodMethod(field, call);\n }\n\n return field;\n }\n\n /**\n * 收集方法调用链\n * 例如: z.string().min(1).optional() -> [{method: \"z.string\", args: []}, {method: \"min\", args: [...]}, {method: \"optional\", args: []}]\n */\n private collectCallChain(\n node: Node\n ): Array<{ method: string; args: Node[] }> {\n const chain: Array<{ method: string; args: Node[] }> = [];\n\n let current: Node | undefined = node;\n while (current && Node.isCallExpression(current)) {\n const expr = current.getExpression();\n const args = current.getArguments();\n\n if (Node.isPropertyAccessExpression(expr)) {\n const methodName = expr.getName();\n chain.unshift({ method: methodName, args: [...args] });\n current = expr.getExpression();\n } else if (Node.isIdentifier(expr)) {\n // z.string, z.number 等基础类型\n chain.unshift({ method: expr.getText(), args: [] });\n break;\n } else if (Node.isPropertyAccessExpression(expr)) {\n // 处理 z.coerce.number() 这种链式\n chain.unshift({\n method: (expr as PropertyAccessExpression).getName(),\n args: [],\n });\n current = (expr as PropertyAccessExpression).getExpression();\n } else {\n break;\n }\n }\n\n return chain;\n }\n\n /**\n * 应用 Zod 方法到字段定义\n */\n private applyZodMethod(\n field: FieldValidation,\n call: { method: string; args: Node[] }\n ): void {\n const { method, args } = call;\n\n switch (method) {\n // 类型定义\n case \"z.string\":\n case \"string\":\n field.type = \"string\";\n break;\n case \"z.number\":\n case \"number\":\n field.type = \"number\";\n break;\n case \"z.boolean\":\n case \"boolean\":\n field.type = \"boolean\";\n break;\n case \"z.array\":\n case \"array\":\n field.type = \"array\";\n // 尝试解析数组元素类型\n if (args.length > 0) {\n field.items = this.parseZodField(args[0]);\n }\n break;\n case \"z.object\":\n case \"object\":\n field.type = \"object\";\n // 尝试解析对象属性\n if (args.length > 0 && Node.isObjectLiteralExpression(args[0])) {\n field.properties = this.parseObjectLiteral(args[0]);\n }\n break;\n case \"z.date\":\n case \"date\":\n field.type = \"date\";\n break;\n case \"z.any\":\n case \"any\":\n field.type = \"any\";\n break;\n case \"z.unknown\":\n case \"unknown\":\n field.type = \"any\";\n break;\n case \"z.undefined\":\n case \"undefined\":\n field.required = false;\n field.optional = true;\n break;\n case \"z.null\":\n case \"null\":\n field.nullable = true;\n break;\n case \"z.void\":\n case \"void\":\n field.type = \"any\";\n break;\n case \"z.nativeEnum\":\n case \"nativeEnum\":\n case \"z.enum\":\n case \"enum\":\n field.type = \"string\";\n break;\n case \"coerce\":\n // z.coerce 是属性访问,不做处理,后续调用会设置类型\n break;\n\n // 可选性\n case \"optional\":\n field.required = false;\n field.optional = true;\n break;\n case \"nullable\":\n field.nullable = true;\n break;\n case \"nullish\":\n field.required = false;\n field.optional = true;\n field.nullable = true;\n break;\n\n // 默认值\n case \"default\":\n if (args.length > 0) {\n field.defaultValue = this.parseArgumentValue(args[0]);\n field.required = false;\n }\n break;\n\n // 约束 - 通用\n case \"min\":\n if (args.length > 0) {\n const minVal = this.parseArgumentValue(args[0]);\n field.constraints = field.constraints || {};\n if (field.type === \"string\") {\n field.constraints.minLength = minVal;\n } else if (field.type === \"number\") {\n field.constraints.min = minVal;\n }\n // 提取错误消息\n if (args.length > 1) {\n const msg = this.parseArgumentValue(args[1]);\n if (typeof msg === \"string\") {\n field.constraints.custom = field.constraints.custom || [];\n field.constraints.custom.push(msg);\n }\n }\n }\n break;\n case \"max\":\n if (args.length > 0) {\n const maxVal = this.parseArgumentValue(args[0]);\n field.constraints = field.constraints || {};\n if (field.type === \"string\") {\n field.constraints.maxLength = maxVal;\n } else if (field.type === \"number\") {\n field.constraints.max = maxVal;\n }\n }\n break;\n case \"length\":\n if (args.length > 0) {\n const lenVal = this.parseArgumentValue(args[0]);\n field.constraints = field.constraints || {};\n field.constraints.minLength = lenVal;\n field.constraints.maxLength = lenVal;\n }\n break;\n\n // 约束 - 字符串\n case \"email\":\n field.constraints = field.constraints || {};\n field.constraints.email = true;\n break;\n case \"url\":\n field.constraints = field.constraints || {};\n field.constraints.url = true;\n break;\n case \"uuid\":\n field.constraints = field.constraints || {};\n field.constraints.uuid = true;\n break;\n case \"regex\":\n case \"pattern\":\n if (args.length > 0) {\n field.constraints = field.constraints || {};\n field.constraints.pattern = args[0].getText();\n }\n break;\n case \"startsWith\":\n case \"endsWith\":\n case \"includes\":\n case \"trim\":\n case \"toLowerCase\":\n case \"toUpperCase\":\n // 字符串转换方法,暂不处理\n break;\n\n // 约束 - 数字\n case \"int\":\n field.constraints = field.constraints || {};\n field.constraints.int = true;\n break;\n case \"positive\":\n field.constraints = field.constraints || {};\n field.constraints.positive = true;\n break;\n case \"nonnegative\":\n field.constraints = field.constraints || {};\n field.constraints.nonnegative = true;\n break;\n case \"negative\":\n field.constraints = field.constraints || {};\n field.constraints.max = -1;\n break;\n case \"nonpositive\":\n field.constraints = field.constraints || {};\n field.constraints.max = 0;\n break;\n case \"finite\":\n case \"safe\":\n // 数字安全检查,暂不处理\n break;\n\n // 约束 - 数组\n case \"nonempty\":\n field.constraints = field.constraints || {};\n field.constraints.minLength = 1;\n break;\n\n // 其他方法\n case \"refine\":\n case \"superRefine\":\n case \"transform\":\n case \"pipe\":\n case \" preprocess\":\n case \"omit\":\n case \"pick\":\n case \"partial\":\n case \"required\":\n case \"strict\":\n case \"passthrough\":\n case \"extend\":\n case \"merge\":\n case \"keyof\":\n // 高级方法,暂不处理\n break;\n }\n }\n\n /**\n * 解析参数值\n */\n private parseArgumentValue(node: Node): any {\n if (Node.isStringLiteral(node)) {\n return node.getLiteralValue();\n } else if (Node.isNumericLiteral(node)) {\n return node.getLiteralValue();\n } else if (Node.isTrueLiteral(node)) {\n return true;\n } else if (Node.isFalseLiteral(node)) {\n return false;\n } else if (Node.isIdentifier(node)) {\n return node.getText();\n } else if (Node.isObjectLiteralExpression(node)) {\n // 返回对象字面量的文本表示\n return node.getText();\n } else if (Node.isArrayLiteralExpression(node)) {\n // 返回数组字面量的文本表示\n return node.getText();\n }\n return node.getText();\n }\n}\n\n// 导出单例实例\nexport const zodSchemaParser = new ZodSchemaParser();\n","import {\n Node,\n SyntaxKind,\n SourceFile,\n InterfaceDeclaration,\n TypeAliasDeclaration,\n PropertySignature,\n TypeReferenceNode,\n ArrayTypeNode,\n UnionTypeNode,\n IntersectionTypeNode,\n LiteralTypeNode,\n Identifier,\n} from \"ts-morph\";\nimport { FieldValidation, ResponseSchema } from \"../types/DocTypes\";\nimport logger from \"./Logger\";\n\n/**\n * 类型引用解析结果\n */\ninterface TypeRef {\n typeName: string;\n typeArgs: string[]; // 泛型参数\n}\n\n/**\n * TypeScript 类型解析器\n * 从 interface/type 定义中提取字段结构\n */\nexport class TSTypeParser {\n /**\n * 解析类型引用字符串\n * 例如: \"ApiResponse<User[]>\" -> { typeName: \"ApiResponse\", typeArgs: [\"User[]\"] }\n */\n public parseTypeRef(typeString: string): TypeRef | null {\n // 移除花括号内的内容(如果有)\n typeString = typeString.trim();\n\n // 匹配泛型: TypeName<Arg1, Arg2>\n const genericMatch = typeString.match(/^(\\w+)<(.+)>$/);\n if (genericMatch) {\n const typeName = genericMatch[1];\n const argsStr = genericMatch[2];\n // 简单分割泛型参数(不支持嵌套泛型)\n const typeArgs = argsStr.split(\",\").map((s) => s.trim());\n return { typeName, typeArgs };\n }\n\n // 简单类型引用\n if (/^\\w+$/.test(typeString)) {\n return { typeName: typeString, typeArgs: [] };\n }\n\n // 数组类型: User[]\n const arrayMatch = typeString.match(/^(\\w+)\\[\\]$/);\n if (arrayMatch) {\n return { typeName: \"Array\", typeArgs: [arrayMatch[1]] };\n }\n\n return null;\n }\n\n /**\n * 解析响应类型\n * @param sourceFile 源文件\n * @param typeString 类型字符串如 \"ApiResponse<User[]>\"\n * @param imports 导入映射 (类型名 -> 文件路径)\n */\n public parseResponseType(\n sourceFile: SourceFile,\n typeString: string,\n imports: Map<string, string>\n ): ResponseSchema | null {\n const typeRef = this.parseTypeRef(typeString);\n if (!typeRef) {\n logger.debug(`无法解析类型引用: ${typeString}`);\n return null;\n }\n\n // 内置类型处理: ApiResponse<T>\n if (typeRef.typeName === \"ApiResponse\") {\n return this.parseApiResponse(sourceFile, typeRef.typeArgs, imports);\n }\n\n // 查找类型定义\n const typeDecl = this.findTypeDeclaration(sourceFile, typeRef.typeName, imports);\n if (!typeDecl) {\n logger.debug(`未找到类型定义: ${typeRef.typeName}`);\n return null;\n }\n\n // 解析字段\n const fields = this.extractFieldsFromType(typeDecl, typeRef.typeArgs, imports);\n\n return { fields };\n }\n\n /**\n * 解析 ApiResponse<T> 类型\n * ApiResponse 是标准的 API 响应包装器,包含 code, data, msg 字段\n */\n private parseApiResponse(\n sourceFile: SourceFile,\n typeArgs: string[],\n imports: Map<string, string>\n ): ResponseSchema {\n const fields: Record<string, FieldValidation> = {\n code: { type: \"number\", required: true },\n msg: { type: \"string\", required: true },\n };\n\n // 解析 data 字段的类型\n if (typeArgs.length > 0) {\n const dataType = typeArgs[0];\n const dataField = this.parseDataType(sourceFile, dataType, imports);\n fields.data = dataField;\n } else {\n fields.data = { type: \"any\", required: true };\n }\n\n return { fields };\n }\n\n /**\n * 解析 data 字段的类型\n */\n private parseDataType(\n sourceFile: SourceFile,\n typeString: string,\n imports: Map<string, string>\n ): FieldValidation {\n // 基础类型\n if (typeString === \"string\") {\n return { type: \"string\", required: true };\n } else if (typeString === \"number\") {\n return { type: \"number\", required: true };\n } else if (typeString === \"boolean\") {\n return { type: \"boolean\", required: true };\n } else if (typeString === \"any\") {\n return { type: \"any\", required: true };\n }\n\n // 数组类型: User[]\n const arrayMatch = typeString.match(/^(\\w+)\\[\\]$/);\n if (arrayMatch) {\n const elementType = arrayMatch[1];\n const elementField = this.parseDataType(sourceFile, elementType, imports);\n return {\n type: \"array\",\n required: true,\n items: elementField,\n };\n }\n\n // 类型引用: LoginResult\n const typeDecl = this.findTypeDeclaration(sourceFile, typeString, imports);\n if (typeDecl) {\n const fields = this.extractFieldsFromType(typeDecl, [], imports);\n return {\n type: \"object\",\n required: true,\n properties: fields,\n };\n }\n\n // 默认返回 any\n return { type: \"any\", required: true };\n }\n\n /**\n * 查找类型声明\n */\n private findTypeDeclaration(\n sourceFile: SourceFile,\n typeName: string,\n imports: Map<string, string>\n ): InterfaceDeclaration | TypeAliasDeclaration | null {\n // 先在当前文件中查找\n const interfaceDecl = sourceFile.getInterface(typeName);\n if (interfaceDecl) return interfaceDecl;\n\n const typeAlias = sourceFile.getTypeAlias(typeName);\n if (typeAlias) return typeAlias;\n\n // 在导入的文件中查找\n const importPath = imports.get(typeName);\n if (importPath) {\n try {\n const importedFile = sourceFile.getProject().addSourceFileAtPath(importPath);\n\n const importedInterface = importedFile.getInterface(typeName);\n if (importedInterface) return importedInterface;\n\n const importedTypeAlias = importedFile.getTypeAlias(typeName);\n if (importedTypeAlias) return importedTypeAlias;\n } catch (error) {\n logger.warn(`无法加载导入文件: ${importPath}`);\n }\n }\n\n return null;\n }\n\n /**\n * 从类型声明中提取字段\n */\n private extractFieldsFromType(\n typeDecl: InterfaceDeclaration | TypeAliasDeclaration,\n typeArgs: string[],\n imports: Map<string, string>\n ): Record<string, FieldValidation> {\n const fields: Record<string, FieldValidation> = {};\n\n // 获取类型节点\n let typeNode: Node | undefined;\n\n if (Node.isInterfaceDeclaration(typeDecl)) {\n // 接口: 直接遍历属性\n for (const prop of typeDecl.getProperties()) {\n const fieldName = prop.getName();\n const fieldType = prop.getType();\n fields[fieldName] = this.parsePropertyType(prop, typeArgs, imports);\n }\n return fields;\n } else if (Node.isTypeAliasDeclaration(typeDecl)) {\n typeNode = typeDecl.getTypeNode();\n }\n\n if (!typeNode) return fields;\n\n // 处理类型别名 - 使用 getKind() 检查节点类型\n if (typeNode.getKind() === SyntaxKind.TypeReference) {\n // 如果是类型引用,可能需要展开\n return this.extractFieldsFromTypeReference(typeNode as TypeReferenceNode, typeArgs, imports);\n } else if (typeNode.getKind() === SyntaxKind.IntersectionType) {\n // 交叉类型: 合并所有类型的字段\n for (const child of (typeNode as IntersectionTypeNode).getTypeNodes()) {\n const childFields = this.extractFieldsFromTypeNode(child, typeArgs, imports);\n Object.assign(fields, childFields);\n }\n } else if (typeNode.getKind() === SyntaxKind.UnionType) {\n // 联合类型: 取第一个类型的字段(简化处理)\n const firstType = (typeNode as UnionTypeNode).getTypeNodes()[0];\n if (firstType) {\n return this.extractFieldsFromTypeNode(firstType, typeArgs, imports);\n }\n } else {\n return this.extractFieldsFromTypeNode(typeNode, typeArgs, imports);\n }\n\n return fields;\n }\n\n /**\n * 从类型节点提取字段\n */\n private extractFieldsFromTypeNode(\n typeNode: Node,\n typeArgs: string[],\n imports: Map<string, string>\n ): Record<string, FieldValidation> {\n const fields: Record<string, FieldValidation> = {};\n\n if (typeNode.getKind() === SyntaxKind.TypeReference) {\n return this.extractFieldsFromTypeReference(typeNode as TypeReferenceNode, typeArgs, imports);\n } else if (typeNode.getKind() === SyntaxKind.IntersectionType) {\n for (const child of (typeNode as IntersectionTypeNode).getTypeNodes()) {\n const childFields = this.extractFieldsFromTypeNode(child, typeArgs, imports);\n Object.assign(fields, childFields);\n }\n }\n\n return fields;\n }\n\n /**\n * 从类型引用提取字段\n */\n private extractFieldsFromTypeReference(\n typeRefNode: TypeReferenceNode,\n typeArgs: string[],\n imports: Map<string, string>\n ): Record<string, FieldValidation> {\n const fields: Record<string, FieldValidation> = {};\n const typeName = typeRefNode.getTypeName().getText();\n\n // 特殊处理泛型参数\n if (typeName === \"Array\" || typeName === \"ReadonlyArray\") {\n // 数组类型,返回 items 信息\n const typeArgsNodes = typeRefNode.getTypeArguments();\n if (typeArgsNodes.length > 0) {\n const elementType = typeArgsNodes[0];\n fields[\"[]\"] = {\n type: \"array\",\n required: true,\n items: this.parseTypeNodeToFieldValidation(elementType, typeArgs, imports),\n };\n }\n return fields;\n }\n\n // 处理 Promise<T> - 提取 T\n if (typeName === \"Promise\") {\n const typeArgsNodes = typeRefNode.getTypeArguments();\n if (typeArgsNodes.length > 0) {\n return this.extractFieldsFromTypeNode(typeArgsNodes[0], typeArgs, imports);\n }\n }\n\n // 处理泛型参数 T, K 等\n if (typeArgs.includes(typeName) && typeArgs.length > 0) {\n // 使用实际类型参数\n const actualType = typeArgs[0]; // 简化处理,取第一个\n // 这里可以递归解析实际类型\n }\n\n // 解析类型定义\n const sourceFile = typeRefNode.getSourceFile();\n const typeDecl = this.findTypeDeclarationInFile(sourceFile, typeName);\n\n if (typeDecl) {\n return this.extractFieldsFromType(typeDecl, typeArgs, imports);\n }\n\n return fields;\n }\n\n /**\n * 在文件中查找类型声明\n */\n private findTypeDeclarationInFile(\n sourceFile: SourceFile,\n typeName: string\n ): InterfaceDeclaration | TypeAliasDeclaration | null {\n const interfaceDecl = sourceFile.getInterface(typeName);\n if (interfaceDecl) return interfaceDecl;\n\n const typeAlias = sourceFile.getTypeAlias(typeName);\n if (typeAlias) return typeAlias;\n\n return null;\n }\n\n /**\n * 解析属性类型\n */\n private parsePropertyType(\n prop: PropertySignature,\n typeArgs: string[],\n imports: Map<string, string>\n ): FieldValidation {\n const type = prop.getType();\n const isOptional = prop.hasQuestionToken();\n\n // 获取类型文本\n const typeText = type.getText();\n\n // 基础类型判断\n if (type.isString()) {\n return { type: \"string\", required: !isOptional };\n } else if (type.isNumber()) {\n return { type: \"number\", required: !isOptional };\n } else if (type.isBoolean()) {\n return { type: \"boolean\", required: !isOptional };\n } else if (type.isArray()) {\n const elementType = type.getArrayElementType();\n let items: FieldValidation | undefined;\n if (elementType) {\n items = {\n type: this.mapTypeToString(elementType),\n required: !elementType.isUndefined() && !elementType.isNull(),\n };\n }\n return { type: \"array\", required: !isOptional, items };\n } else if (type.isObject()) {\n // 尝试获取对象属性\n const properties = type.getProperties();\n if (properties.length > 0) {\n const props: Record<string, FieldValidation> = {};\n for (const prop of properties) {\n const propName = prop.getName();\n const propType = prop.getTypeAtLocation(prop.getValueDeclaration() || prop.getDeclarations()[0]);\n props[propName] = {\n type: this.mapTypeToString(propType),\n required: !prop.isOptional(),\n };\n }\n return { type: \"object\", required: !isOptional, properties: props };\n }\n return { type: \"object\", required: !isOptional };\n } else if (type.isNull()) {\n return { type: \"any\", required: false, nullable: true };\n } else if (type.isUndefined()) {\n return { type: \"any\", required: false, optional: true };\n } else if (type.isAny()) {\n return { type: \"any\", required: !isOptional };\n }\n\n // 其他类型,使用类型文本\n return { type: \"any\", required: !isOptional };\n }\n\n /**\n * 将类型映射为字符串\n */\n private mapTypeToString(type: any): FieldValidation[\"type\"] {\n if (type.isString()) return \"string\";\n if (type.isNumber()) return \"number\";\n if (type.isBoolean()) return \"boolean\";\n if (type.isArray()) return \"array\";\n if (type.isObject()) return \"object\";\n if (type.isDate()) return \"date\";\n return \"any\";\n }\n\n /**\n * 从类型节点创建 FieldValidation\n */\n private parseTypeNodeToFieldValidation(\n typeNode: Node,\n typeArgs: string[],\n imports: Map<string, string>\n ): FieldValidation {\n if (Node.isStringKeyword(typeNode)) {\n return { type: \"string\", required: true };\n } else if (Node.isNumberKeyword(typeNode)) {\n return { type: \"number\", required: true };\n } else if (Node.isBooleanKeyword(typeNode)) {\n return { type: \"boolean\", required: true };\n } else if (Node.isArrayTypeNode(typeNode)) {\n const elementType = (typeNode as ArrayTypeNode).getElementTypeNode();\n return {\n type: \"array\",\n required: true,\n items: this.parseTypeNodeToFieldValidation(elementType, typeArgs, imports),\n };\n } else if (typeNode.getKind() === SyntaxKind.TypeReference) {\n const refNode = typeNode as TypeReferenceNode;\n const typeName = refNode.getTypeName().getText();\n const sourceFile = refNode.getSourceFile();\n const typeDecl = this.findTypeDeclarationInFile(sourceFile, typeName);\n\n if (typeDecl) {\n const fields = this.extractFieldsFromType(typeDecl, typeArgs, imports);\n return { type: \"object\", required: true, properties: fields };\n }\n\n return { type: \"any\", required: true };\n }\n\n return { type: \"any\", required: true };\n }\n}\n\n// 导出单例实例\nexport const tsTypeParser = new TSTypeParser();\n","import Database from \"better-sqlite3\";\nimport { Database as DatabaseType } from \"better-sqlite3\";\nimport * as path from \"path\";\nimport * as fs from \"fs\";\nimport { RouteInfo, ModuleItem, DocDatabaseConfig } from \"../types/DocTypes\";\nimport logger from \"./Logger\";\n\n/**\n * 文档管理器\n * 管理文档数据,与独立的 SQLite 数据库交互\n */\nexport class DocManager {\n private db: DatabaseType | null = null;\n private config: DocDatabaseConfig;\n\n constructor(config: DocDatabaseConfig) {\n this.config = config;\n this.init();\n }\n\n /**\n * 初始化数据库\n */\n public init(): void {\n try {\n // 确保数据库目录存在\n const dbDir = path.dirname(this.config.path);\n if (!fs.existsSync(dbDir)) {\n fs.mkdirSync(dbDir, { recursive: true });\n }\n\n // 连接数据库\n this.db = new Database(this.config.path);\n\n // 创建表结构\n this.createTables();\n } catch (error) {\n logger.error(\"文档数据库初始化失败:\", error);\n this.db = null;\n }\n }\n\n /**\n * 创建表结构\n */\n private createTables(): void {\n if (!this.db) return;\n\n // 创建 doc_routes 表\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS doc_routes (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n module TEXT NOT NULL,\n method TEXT NOT NULL,\n path TEXT NOT NULL,\n full_path TEXT NOT NULL,\n summary TEXT,\n description TEXT,\n request_schema TEXT,\n response_schema TEXT,\n middlewares TEXT,\n file_path TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n UNIQUE(module, method, path)\n );\n `);\n\n // 创建索引\n this.db.exec(`\n CREATE INDEX IF NOT EXISTS idx_doc_routes_module ON doc_routes(module);\n CREATE INDEX IF NOT EXISTS idx_doc_routes_full_path ON doc_routes(full_path);\n `);\n }\n\n /**\n * 保存路由信息\n * @param routeInfo 路由信息\n * @param apiPrefix API 前缀\n * @param moduleName 模块名称\n */\n public saveRoute(routeInfo: RouteInfo, apiPrefix: string = \"/api\", moduleName: string): void {\n if (!this.db) return;\n\n try {\n // 计算完整路径\n const fullPath = `${apiPrefix}/${moduleName}${routeInfo.path}`.replace(/\\/+/g, \"/\");\n\n // 准备数据\n const now = Date.now();\n const data = {\n module: moduleName,\n method: routeInfo.method,\n path: routeInfo.path,\n full_path: fullPath,\n summary: routeInfo.summary,\n description: routeInfo.description,\n request_schema: routeInfo.requestSchema ? JSON.stringify(routeInfo.requestSchema) : null,\n response_schema: routeInfo.responseSchema ? JSON.stringify(routeInfo.responseSchema) : null,\n middlewares: routeInfo.middlewares ? JSON.stringify(routeInfo.middlewares) : null,\n file_path: routeInfo.filePath,\n created_at: now,\n updated_at: now,\n };\n\n // 插入或更新数据\n const stmt = this.db.prepare(`\n INSERT INTO doc_routes (\n module, method, path, full_path, summary, description,\n request_schema, response_schema, middlewares, file_path, created_at, updated_at\n ) VALUES (\n @module, @method, @path, @full_path, @summary, @description,\n @request_schema, @response_schema, @middlewares, @file_path, @created_at, @updated_at\n ) ON CONFLICT(module, method, path) DO UPDATE SET\n full_path = @full_path,\n summary = @summary,\n description = @description,\n request_schema = @request_schema,\n response_schema = @response_schema,\n middlewares = @middlewares,\n file_path = @file_path,\n updated_at = @updated_at\n `);\n\n stmt.run(data);\n } catch (error) {\n logger.error(\"保存路由信息失败:\", error);\n }\n }\n\n /**\n * 获取模块列表\n * @returns 模块列表\n */\n public getModules(): ModuleItem[] {\n if (!this.db) return [];\n\n try {\n const stmt = this.db.prepare(`\n SELECT module, COUNT(*) as count \n FROM doc_routes \n GROUP BY module \n ORDER BY module\n `);\n\n return stmt.all() as ModuleItem[];\n } catch (error) {\n logger.error(\"获取模块列表失败:\", error);\n return [];\n }\n }\n\n /**\n * 获取路由列表\n * @param module 模块名称(可选)\n * @returns 路由列表\n */\n public getRoutes(module?: string): RouteInfo[] {\n if (!this.db) return [];\n\n try {\n let query = `\n SELECT id, module, method, path, full_path, summary, description,\n request_schema, response_schema, middlewares, file_path, created_at, updated_at\n FROM doc_routes\n `;\n\n const params: any = {};\n\n if (module) {\n query += \" WHERE module = @module\";\n params.module = module;\n }\n\n query += \" ORDER BY module, method, path\";\n\n const stmt = this.db.prepare(query);\n const rows = stmt.all(params) as any[];\n\n // 转换数据格式\n return rows.map((row) => ({\n id: row.id,\n module: row.module,\n method: row.method,\n path: row.path,\n fullPath: row.full_path,\n summary: row.summary,\n description: row.description,\n requestSchema: row.request_schema ? JSON.parse(row.request_schema) : undefined,\n responseSchema: row.response_schema ? JSON.parse(row.response_schema) : undefined,\n middlewares: row.middlewares ? JSON.parse(row.middlewares) : undefined,\n filePath: row.file_path,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n }));\n } catch (error) {\n logger.error(\"获取路由列表失败:\", error);\n return [];\n }\n }\n\n /**\n * 获取路由详情\n * @param id 路由 ID\n * @returns 路由详情\n */\n public getRouteById(id: number): RouteInfo | null {\n if (!this.db) return null;\n\n try {\n const stmt = this.db.prepare(`\n SELECT id, module, method, path, full_path, summary, description,\n request_schema, response_schema, middlewares, file_path, created_at, updated_at\n FROM doc_routes\n WHERE id = @id\n `);\n\n const row = stmt.get({ id }) as any;\n\n if (!row) return null;\n\n // 转换数据格式\n return {\n id: row.id,\n module: row.module,\n method: row.method,\n path: row.path,\n fullPath: row.full_path,\n summary: row.summary,\n description: row.description,\n requestSchema: row.request_schema ? JSON.parse(row.request_schema) : undefined,\n responseSchema: row.response_schema ? JSON.parse(row.response_schema) : undefined,\n middlewares: row.middlewares ? JSON.parse(row.middlewares) : undefined,\n filePath: row.file_path,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n } catch (error) {\n logger.error(\"获取路由详情失败:\", error);\n return null;\n }\n }\n\n /**\n * 清空所有路由数据\n */\n public clearAllRoutes(): void {\n if (!this.db) return;\n\n try {\n this.db.exec(\"DELETE FROM doc_routes\");\n } catch (error) {\n logger.error(\"清空路由数据失败:\", error);\n }\n }\n\n /**\n * 关闭数据库连接\n */\n public close(): void {\n if (this.db) {\n this.db.close();\n this.db = null;\n logger.info(\"文档数据库连接已关闭\");\n }\n }\n}\n\n// 导出单例实例\nexport let docManager: DocManager;\n\n/**\n * 初始化文档管理器\n * @param config 配置\n */\nexport function initDocManager(config: DocDatabaseConfig): DocManager {\n docManager = new DocManager(config);\n return docManager;\n}\n","import { Express, Router } from \"express\";\nimport { ScanResult } from \"../types/Index\";\nimport logger from \"./Logger\";\nimport { routeParser } from \"./RouteParser\";\nimport { docManager } from \"./DocManager\";\nimport path from \"path\";\n\n/**\n * 递归提取 Router 中注册的所有路由路径\n */\nfunction getRoutes(router: any, prefix: string = \"\"): { path: string; method: string }[] {\n const routes: { path: string; method: string }[] = [];\n\n if (router && router.stack) {\n router.stack.forEach((layer: any) => {\n if (layer.route) {\n // 处理直接定义的路由 (如 router.get('/hello'))\n const path = (prefix + layer.route.path).replace(/\\/+/g, \"/\");\n const methods = Object.keys(layer.route.methods).map((m) => m.toUpperCase());\n methods.forEach((method) => {\n routes.push({ path, method });\n });\n } else if (layer.name === \"router\" && layer.handle && layer.handle.stack) {\n // 处理嵌套的 Router (如 router.use('/sub', subRouter))\n const newPrefix = (prefix + (layer.regexp.source.replace(\"^\\\\/\", \"\").replace(\"\\\\/?(?=\\\\/|$)\", \"\") || \"\")).replace(/\\/+/g, \"/\");\n routes.push(...getRoutes(layer.handle, newPrefix));\n }\n });\n }\n\n return routes;\n}\n\nexport async function registerRoute(app: Express, config: ScanResult, apiPrefix: string = \"/api\"): Promise<void> {\n const { fileName, defaultExport: handler, filePath, cacheHit } = config;\n\n try {\n const lowercaseModuleName = fileName.toLowerCase();\n\n // 缓存未命中时才解析和保存文档\n if (!cacheHit) {\n const routes = routeParser.parseRouteFile(filePath);\n routes.forEach((route) => {\n docManager.saveRoute(route, apiPrefix, lowercaseModuleName);\n });\n }\n\n // ===== 支持从子目录生成嵌套 URL =====\n // 例如:d:/packages/auth/routes/auth/user.route.ts → /api/auth/user\n\n // 正确找到 routes 目录位置\n const filePathParts = filePath.split(path.sep);\n const routesIndex = filePathParts.lastIndexOf(\"routes\");\n if (routesIndex === -1) {\n throw new Error(`路由文件必须在 routes 目录下: ${filePath}`);\n }\n const routesDir = filePathParts.slice(0, routesIndex + 1).join(path.sep);\n\n // 获取相对于 routes 目录的路径\n const fileDir = path.dirname(filePath);\n const relativePath = path.relative(routesDir, fileDir);\n\n // 构建路径部分\n let pathParts: string[] = [];\n if (relativePath && relativePath !== \".\") {\n pathParts = relativePath.split(path.sep).map(p => p.toLowerCase());\n }\n // 添加文件名作为最后一部分\n pathParts.push(lowercaseModuleName);\n\n const baseRoutePath = `${apiPrefix}/${pathParts.join(\"/\")}`.replace(/\\/+/g, \"/\");\n // ===== 嵌套 URL 支持结束 =====\n\n app.use(baseRoutePath, handler);\n\n // 提取并打印所有子路由\n const subRoutes = getRoutes(handler);\n if (subRoutes.length > 0) {\n logger.startup(\"路由\", `${baseRoutePath} (${subRoutes.length} 个端点)`);\n subRoutes.forEach((route) => {\n const fullPath = `${baseRoutePath}${route.path}`.replace(/\\/+/g, \"/\");\n // Method 填充到 6 字符宽度,保证 path 对齐\n const method = route.method.padEnd(6, \" \");\n logger.startup(` └─ ${method} ${fullPath}`);\n });\n } else {\n logger.startup(\"路由\", `${baseRoutePath} (无端点)`);\n }\n } catch (error) {\n logger.error(`注册路由失败[${fileName.toLowerCase()}]: ${error}`);\n }\n}\n","import { AppState } from \"../core/state\";\nimport { ScanResult } from \"../types/Index\";\nimport { registerMiddleware } from \"./MiddlewareRegistry\";\nimport { registerRoute } from \"./RouteRegistry\";\nimport logger from \"./Logger\";\n\n/**\n * 封装细节:遍历扫描结果并注册所有组件(中间件和路由)\n */\nexport async function registerComponents(state: AppState, scannedResults: ScanResult[]) {\n // 1. 先注册所有中间件\n for (const item of scannedResults) {\n if (item.type === \"middleware\") {\n registerMiddleware(state.express, item);\n }\n }\n\n // 2. 再注册所有路由\n for (const item of scannedResults) {\n if (item.type === \"route\") {\n registerRoute(state.express, item, state.options.apiPrefix);\n }\n }\n\n // 3. 所有组件注册完成后,触发路由资源同步(如果有)\n const syncAppRoutes = state.express.get(\"syncAppRoutes\");\n if (syncAppRoutes && typeof syncAppRoutes === \"function\") {\n try {\n await syncAppRoutes();\n } catch (error) {\n logger.error(\"[ComponentRegistry] 路由资源同步失败:\", error);\n }\n }\n}\n","import { Request, Response, NextFunction, Express } from \"express\";\nimport { ZodError } from \"zod\";\nimport logger from \"./Logger\";\n\n/**\n * 检测是否为 SQL 相关错误(表/字段不存在)\n */\nfunction isSQLError(err: any): boolean {\n if (!err) return false;\n const msg = err.message || err.toString() || \"\";\n return /no such table|table.*does not exist|column.*does not exist|database schema has changed/i.test(msg);\n}\n\n/**\n * 封装细节:初始化错误处理和 404 中间件\n */\nexport function setupErrorHandlers(app: Express, logging?: boolean) {\n // 404 处理\n app.use((req: Request, res: Response) => {\n res.status(404).json({\n code: 404,\n data: null,\n msg: \"资源不存在\",\n error: \"Not Found\",\n fields: {},\n });\n });\n\n // 错误处理\n app.use((err: any, req: Request, res: Response, next: NextFunction) => {\n // 处理业务错误(带有 isAppError 标记或 4xx 状态码)\n if (err.isAppError || (err.statusCode && err.statusCode >= 400 && err.statusCode < 500)) {\n return res.status(err.statusCode).json({\n code: err.statusCode,\n data: null,\n msg: err.message,\n error: \"BusinessError\",\n fields: {},\n });\n }\n\n // 处理 Zod 校验错误\n if (err instanceof ZodError) {\n const fields: Record<string, string> = {};\n err.errors.forEach((e) => {\n const path = e.path.join(\".\");\n fields[path] = e.message;\n });\n\n return res.status(400).json({\n code: 400,\n data: null,\n msg: \"参数校验失败\",\n error: \"ZodValidationError\",\n fields,\n });\n }\n\n // 处理 SQL 错误(给出友好提示)\n if (isSQLError(err)) {\n logger.error(\"\");\n logger.error(\"❌ 数据库结构可能已变化,请运行以下命令同步:\");\n logger.error(\"\");\n logger.error(\" npm run db:migrate\");\n logger.error(\"\");\n }\n\n // 处理普通错误\n const statusCode = err.status || err.statusCode || 500;\n if (!isSQLError(err)) {\n logger.error(\"系统错误:\", err);\n }\n\n res.status(statusCode).json({\n code: statusCode,\n data: null,\n msg: err.message || \"服务器内部错误\",\n error: logging ? err.stack : \"InternalServerError\",\n fields: {},\n });\n });\n}\n","import { Express } from \"express\";\nimport logger from \"./Logger\";\n\n/**\n * 启动 HTTP 服务\n * @param app Express 实例\n * @param port 监听端口\n * @returns Promise<void>\n * @throws 如果服务器启动失败\n */\nexport async function startServer(app: Express, port: number): Promise<void> {\n if (!app) {\n throw new Error(\"Express 实例不能为空\");\n }\n\n if (!port || typeof port !== \"number\" || port <= 0 || port > 65535) {\n throw new Error(`无效的端口号: ${port}`);\n }\n\n return new Promise<void>((resolve, reject) => {\n try {\n const server = app.listen(port, () => {\n resolve();\n });\n\n // 处理服务器错误\n server.on(\"error\", (error) => {\n logger.error(\"服务器启动失败:\", error);\n reject(new Error(`服务器启动失败:${error instanceof Error ? error.message : String(error)}`));\n });\n\n // 处理服务器关闭\n server.on(\"close\", () => {\n logger.info(\"服务器已关闭\");\n });\n } catch (error) {\n logger.error(\"服务器启动异常:\", error);\n reject(new Error(`服务器启动异常:${error instanceof Error ? error.message : String(error)}`));\n }\n });\n}\n","import { Router, Request, Response } from \"express\";\nimport { docManager } from \"../utils/DocManager\";\nimport { validate } from \"../utils/Validate\";\nimport { routeIdParamsSchema } from \"../zod/Doc.schema\";\nimport { ApiResponse, ModuleItem, RouteInfo } from \"../types/DocTypes\";\n\nconst router = Router();\n\n/**\n * 获取模块列表\n * @apiSuccess {number} code 状态码\n * @apiSuccess {string} msg 消息\n * @apiSuccess {Object[]} data 模块列表\n */\nrouter.get(\"/modules\", (req: Request, res: Response) => {\n try {\n const modules = docManager.getModules();\n const response: ApiResponse = {\n code: 200,\n data: modules,\n msg: \"success\",\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n code: 500,\n data: null,\n msg: \"获取模块列表失败\",\n };\n res.json(response);\n }\n});\n\n/**\n * 获取路由列表\n * @apiParam {string} [module] 模块名称(可选)\n * @apiSuccess {number} code 状态码\n * @apiSuccess {string} msg 消息\n * @apiSuccess {Object[]} data 路由列表\n */\nrouter.get(\"/routes\", (req: Request, res: Response) => {\n try {\n const module = req.query.module as string;\n const routes = docManager.getRoutes(module);\n const response: ApiResponse = {\n code: 200,\n data: routes,\n msg: \"success\",\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n code: 500,\n data: null,\n msg: \"获取路由列表失败\",\n };\n res.json(response);\n }\n});\n\n/**\n * 获取路由详情\n * @apiParam {string} id 路由ID(路径参数,必填)\n * @apiSuccess {number} code 状态码\n * @apiSuccess {string} msg 消息\n * @apiSuccess {Object} data 路由详情\n */\nrouter.get(\"/routes/:id\", validate(routeIdParamsSchema as any, \"params\"), (req: Request, res: Response) => {\n try {\n const { id } = req.params as any;\n const route = docManager.getRouteById(id);\n if (!route) {\n const response: ApiResponse = {\n code: 404,\n data: null,\n msg: \"路由不存在\",\n };\n return res.json(response);\n }\n\n const response: ApiResponse = {\n code: 200,\n data: route,\n msg: \"success\",\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n code: 500,\n data: null,\n msg: \"获取路由详情失败\",\n };\n res.json(response);\n }\n});\n\n/**\n * 手动同步文档数据\n * @apiSuccess {number} code 状态码\n * @apiSuccess {string} msg 消息\n * @apiSuccess {boolean} data 是否同步成功\n */\nrouter.post(\"/sync\", (req: Request, res: Response) => {\n try {\n // 这里可以实现手动同步逻辑\n // 例如:重新扫描所有路由文件并更新文档数据\n const response: ApiResponse = {\n code: 200,\n data: true,\n msg: \"同步成功\",\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n code: 500,\n data: null,\n msg: \"同步失败\",\n };\n res.json(response);\n }\n});\n\nexport default router;\n","import { Request, Response, NextFunction } from \"express\";\nimport { AnyZodObject, ZodError, ZodSchema } from \"zod\";\n\n/**\n * 验证位置类型\n */\nexport type ValidationTarget = \"body\" | \"query\" | \"params\";\n\n/**\n * Zod 验证中间件\n * @param schema Zod Schema\n * @param target 验证目标 (默认 body)\n */\nexport const validate = (schema: ZodSchema, target: ValidationTarget = \"body\") => {\n return async (req: Request, res: Response, next: NextFunction) => {\n try {\n await schema.parseAsync(req[target]);\n // 注意: req.query 和 req.params 是只读的,无法赋值\n // 只有 req.body 可以赋值,但通常 parse 验证后类型转换已生效\n next();\n } catch (error) {\n next(error);\n }\n };\n};\n","import { z } from \"zod\";\n\n// 路由ID参数\nexport const routeIdParamsSchema = z.object({\n id: z.coerce.number().int().positive(\"无效的路由ID\"),\n});\n\n// 类型导出\nexport type RouteIdParams = z.infer<typeof routeIdParamsSchema>;\n","import { Express } from \"express\";\nimport { createState } from \"./state\";\nimport { setBaseDir, scan, addScanPath } from \"../feature/scanner/FileScanner\";\nimport { MindBaseAppOptions } from \"../types/Index\";\nimport initExpress from \"../utils/InitExpress\";\nimport { setupDatabase } from \"../utils/InitDatabase\";\nimport { registerComponents } from \"../utils/ComponentRegistry\";\nimport { setupErrorHandlers } from \"../utils/InitErrorHandler\";\nimport { startServer } from \"../utils/HttpServer\";\nimport logger from \"../utils/Logger\";\nimport { initDocManager } from \"../utils/DocManager\";\nimport docRouter from \"../routes/Doc.route\";\n\n/**\n * MindBase 应用实例\n */\nexport interface MindBaseApp {\n /** 注册插件模块 */\n use(plugin: any): void;\n /** 启动应用(初始化数据库、注册路由、启动 HTTP 服务) */\n startup(): Promise<void>;\n /** 获取 Express 实例 */\n getApp(): Express;\n /** 获取 Drizzle 数据库实例 */\n getDB(): any;\n /** 获取应用配置选项 */\n getOptions(): MindBaseAppOptions;\n}\n\n/**\n * 创建 MindBase 应用实例\n * @param options 应用配置选项\n * @returns MindBase 应用实例\n * @example\n * const app = createApp({\n * port: 3000,\n * logLevel: \"debug\",\n * });\n * app.use(auth);\n * await app.startup();\n */\nexport function createApp(options: MindBaseAppOptions = {}): MindBaseApp {\n logger.startup(\"初始化\", \"应用初始化……\");\n const stateInstance = createState(options);\n const plugins: any[] = [];\n\n // 初始化日志级别\n if (stateInstance.options.logLevel) {\n logger.setLevel(stateInstance.options.logLevel);\n }\n\n const app: MindBaseApp = {\n use: async (plugin) => {\n if (typeof plugin.install === \"function\") {\n plugins.push(plugin);\n }\n if (typeof plugin.__modulePath === \"string\") {\n logger.startup(\"模块\", `注册:${plugin.__modulePath}`);\n addScanPath(plugin.__modulePath);\n }\n },\n startup: async () => {\n // 0. 初始化 Express 基础配置\n initExpress(stateInstance);\n\n // 1. 准备扫描环境\n await prepareScanEnvironment();\n\n // 2. 扫描组件\n const scannedResults = await scanComponents();\n\n // 3. 初始化数据库\n await initializeDataStorage(scannedResults);\n\n // 4. 初始化模块\n await installPlugins();\n\n // 5. 注册组件\n\n registerComponents(stateInstance, scannedResults);\n\n // 6. 注册文档路由\n registerDocRoutes();\n\n // 7. 注册错误处理\n setupErrorHandlers(stateInstance.express, stateInstance.options.logging);\n\n // 8. 启动 HTTP 服务\n await startHttpServer();\n\n logger.startup(\"初始化\", \"✅ 应用启动完成\");\n },\n\n getApp: () => stateInstance.express,\n getDB: () => stateInstance.db,\n getOptions: () => stateInstance.options,\n };\n\n // 准备扫描环境\n async function prepareScanEnvironment() {\n setBaseDir(process.cwd());\n logger.startup(\"扫描\", `基准目录: ${process.cwd()}`);\n }\n\n // 扫描组件\n async function scanComponents() {\n const scannedResults = await scan();\n\n // 统计缓存命中情况\n const routeFiles = scannedResults.filter((r) => r.type === \"route\");\n const cacheHits = routeFiles.filter((r) => r.cacheHit).length;\n const total = routeFiles.length;\n\n if (cacheHits > 0) {\n logger.startup(\"扫描\", `发现 ${scannedResults.length} 个组件文件 (缓存命中: ${cacheHits}/${total})`);\n } else {\n logger.startup(\"扫描\", `发现 ${scannedResults.length} 个组件文件`);\n }\n\n return scannedResults;\n }\n\n // 初始化数据存储\n async function initializeDataStorage(scannedResults) {\n // 初始化数据库与 Schema\n setupDatabase(stateInstance, scannedResults);\n stateInstance.express.set(\"db\", stateInstance.db);\n\n // 收集数据库信息\n if (stateInstance.db) {\n const dbPath = stateInstance.options.database?.path || \"./data/app.db\";\n logger.startup(\"数据库\", `已连接: SQLite (${dbPath})`);\n }\n\n // 初始化文档管理器\n const docDbPath = stateInstance.options.database?.path\n ? stateInstance.options.database.path.replace(/app\\.db$/, \"doc.db\")\n : \"./data/doc.db\";\n initDocManager({ path: docDbPath });\n logger.startup(\"数据库\", `文档库已初始化: ${docDbPath}`);\n }\n\n // 执行插件安装\n async function installPlugins() {\n for (const plugin of plugins) {\n await plugin.install(app);\n }\n }\n\n // 启动 HTTP 服务\n async function startHttpServer() {\n const listenPort = stateInstance.options.port || 3000;\n await startServer(stateInstance.express, listenPort);\n\n // 打印服务器启动信息\n const serverUrl = `http://${stateInstance.options.host}:${listenPort}`;\n logger.startup(\"服务\", `访问地址: ${serverUrl}`);\n }\n\n // 注册文档路由\n function registerDocRoutes() {\n const apiPrefix = stateInstance.options.apiPrefix || \"/api\";\n const docRoutePath = `${apiPrefix}/doc`.replace(/\\/+/g, \"/\");\n stateInstance.express.use(docRoutePath, docRouter);\n stateInstance.options.authWhitelist.push(`${docRoutePath}/modules`);\n logger.startup(\"路由\", `${docRoutePath}/modules (GET)`);\n stateInstance.options.authWhitelist.push(`${docRoutePath}/routes`);\n logger.startup(\"路由\", `${docRoutePath}/routes (GET)`);\n stateInstance.options.authWhitelist.push(new RegExp(`^${docRoutePath}/routes/[^/]+$`));\n logger.startup(\"路由\", `${docRoutePath}/routes/:id (GET)`);\n stateInstance.options.authWhitelist.push(`${docRoutePath}/sync`);\n logger.startup(\"路由\", `${docRoutePath}/sync (POST)`);\n }\n\n return app;\n}\n","import path from \"path\";\nimport { setBaseDir, scan } from \"../feature/scanner/FileScanner\";\nimport { initDatabase } from \"../utils/InitDatabase\";\nimport logger from \"../utils/Logger\";\n\n/**\n * 准备命令\n *\n * 初始化数据库并预热缓存,但不启动服务器\n * 用于在构建/初始化阶段准备环境\n */\nexport async function prepare(cwd: string = process.cwd()): Promise<void> {\n console.log(\"🚀 MindBase 环境准备工具\");\n console.log(`工作目录: ${cwd}\\n`);\n\n // 设置基础目录\n setBaseDir(cwd);\n\n try {\n // 1. 扫描组件(获取 schemas 用于数据库初始化)\n console.log(\"📂 扫描组件文件...\");\n const results = await scan();\n\n const routeFiles = results.filter((r) => r.type === \"route\");\n const middlewareFiles = results.filter((r) => r.type === \"middleware\");\n const schemaFiles = results.filter((r) => r.type === \"schema\");\n\n console.log(` 发现 ${results.length} 个组件文件`);\n console.log(` - 路由: ${routeFiles.length}`);\n console.log(` - 中间件: ${middlewareFiles.length}`);\n console.log(` - Schema: ${schemaFiles.length}\\n`);\n\n // 2. 提取 schemas\n const schemas: Record<string, any> = {};\n for (const item of results) {\n if (item.type === \"schema\" && item.allExports) {\n try {\n Object.assign(schemas, item.allExports);\n } catch (e) {\n logger.warn(`处理 Schema 文件失败: ${item.filePath}`, e);\n }\n }\n }\n\n // 3. 初始化数据库(会自动创建目录和数据库文件)\n console.log(\"💾 初始化数据库...\");\n const db = initDatabase({\n dbPath: process.env.DB_PATH || \"./data/app.db\",\n schemas,\n });\n console.log(` 数据库已初始化\\n`);\n\n // 4. 显示缓存信息\n const cacheFile = path.join(cwd, \"node_modules/.cache/mindbase/startup-cache.json\");\n console.log(\"✅ 环境准备完成!\");\n console.log(`\\n📦 缓存文件: ${cacheFile}`);\n console.log(`💾 数据库: ${process.env.DB_PATH || \"./data/app.db\"}`);\n console.log(\"\\n💡 提示: 现在可以运行 db push、init-admin 等命令了\");\n } catch (error) {\n console.error(\"\\n❌ 准备失败:\", error);\n process.exit(1);\n }\n}\n\n// 兼容旧代码:保留 precache 别名\nexport async function precache(cwd?: string): Promise<void> {\n return prepare(cwd);\n}\n\n// 如果直接运行此脚本\nif (require.main === module) {\n const cwd = process.argv[2] || process.cwd();\n prepare(cwd);\n}\n","import { CronJob } from \"cron\";\nimport { randomUUID } from \"crypto\";\n\ninterface CronConfig {\n timezone?: string;\n}\n\ninterface CronJobMap {\n [id: string]: CronJob;\n}\n\nlet jobs: CronJobMap = {};\nlet config: CronConfig = {\n timezone: \"Asia/Shanghai\",\n};\n\nexport function setConfig(newConfig: CronConfig): void {\n config = {\n ...config,\n ...newConfig,\n };\n}\n\nexport function addCron(pattern: string, handler: () => void | Promise<void>, customId?: string): string {\n const id = customId || generateId();\n if (jobs[id]) {\n jobs[id].stop();\n }\n const job = new CronJob(pattern, handler, null, true, config.timezone);\n jobs[id] = job;\n return id;\n}\n\nexport function stopCron(id: string): boolean {\n const job = jobs[id];\n if (job) {\n job.stop();\n delete jobs[id];\n return true;\n }\n return false;\n}\n\nexport function stopAllCron(): void {\n Object.values(jobs).forEach((job) => {\n job.stop();\n });\n jobs = {};\n}\n\nfunction generateId(): string {\n return randomUUID();\n}\n\nconst CronManager = {\n setConfig,\n addCron,\n stopCron,\n stopAllCron,\n};\n\nexport default CronManager;\nexport type { CronConfig };\n","import path from \"path\";\nimport fs from \"fs\";\n\n/**\n * 查找包含 package.json 的根目录\n * @param startPath 开始查找的路径\n * @returns 包含 package.json 的目录路径\n * @throws 如果输入路径无效\n */\nexport function findPackageRoot(startPath: string): string {\n // 验证输入路径\n if (!startPath || typeof startPath !== \"string\") {\n throw new Error(\"无效的起始路径:路径必须是非空字符串\");\n }\n\n // 确保路径是绝对路径\n let currentPath: string;\n try {\n currentPath = path.isAbsolute(startPath) ? startPath : path.resolve(startPath);\n } catch (e) {\n throw new Error(`无法解析路径:${startPath}`);\n }\n\n // 验证路径是否存在\n try {\n if (!fs.existsSync(currentPath)) {\n throw new Error(`路径不存在:${currentPath}`);\n }\n\n // 如果是文件,从其父目录开始查找\n const stat = fs.statSync(currentPath);\n if (stat.isFile()) {\n currentPath = path.dirname(currentPath);\n }\n } catch (e) {\n throw new Error(`路径验证失败:${e instanceof Error ? e.message : String(e)}`);\n }\n\n // 向上查找 package.json\n while (currentPath !== path.parse(currentPath).root) {\n try {\n const pkgJsonPath = path.join(currentPath, \"package.json\");\n if (fs.existsSync(pkgJsonPath)) {\n // 验证找到的 package.json 是否是文件\n const pkgStat = fs.statSync(pkgJsonPath);\n if (pkgStat.isFile()) {\n return currentPath;\n }\n }\n } catch (e) {\n // 忽略单个路径的访问错误,继续向上查找\n }\n currentPath = path.dirname(currentPath);\n }\n\n // 如果没有找到 package.json,返回起始路径的父目录\n return path.dirname(startPath);\n}\n","import * as path from \"path\";\n\n/**\n * 获取当前模块的路径\n * @returns 当前模块的绝对路径\n * @throws 如果无法确定模块路径\n */\nexport function getModulePath(): string {\n // 从调用栈中提取调用者的路径\n try {\n const error = new Error();\n if (error.stack) {\n console.log(\"DEBUG STACK:\", error.stack);\n const stackLines = error.stack.split(\"\\n\");\n\n // 跳过内部调用,找到真正的调用者\n // 需要跳过:getModulePath, createModule, ts-node, node:internal\n for (const line of stackLines) {\n // 跳过内部函数和 Node.js/ts-node 的调用\n if (!line.includes(\"at\") ||\n line.includes(\"getModulePath\") ||\n line.includes(\"createModule\") ||\n line.includes(\"CreateModule.ts\") ||\n line.includes(\"ts-node\") ||\n line.includes(\"node:internal\")) {\n continue;\n }\n\n // 提取文件路径\n // 格式可能是:at xxx (/path/to/file.ts:1:2) 或 at /path/to/file.ts:1:2\n const match = line.match(/\\(([^:]+\\.ts)/) || line.match(/at\\s+([^:]+\\.ts)/);\n if (match && match[1]) {\n const filePath = match[1];\n console.log(\"提取到的路径:\", filePath);\n return path.resolve(filePath);\n }\n }\n }\n } catch (e) {\n // 忽略提取 stack 时的错误\n }\n\n throw new Error(\"无法确定模块路径:当前环境不支持 __filename 且无法从调用栈中提取路径\");\n}\n\n/**\n * 获取当前模块所在的目录\n * @returns 当前模块的目录路径\n * @throws 如果无法确定模块路径\n */\nexport function getModuleDir(): string {\n try {\n const modulePath = getModulePath();\n return path.dirname(modulePath);\n } catch (error) {\n throw new Error(`无法获取模块目录:${error instanceof Error ? error.message : String(error)}`);\n }\n}\n","import { findPackageRoot } from \"./FindPackageRoot\";\nimport { getModulePath } from \"./GetModulePath\";\nimport { MindBaseApp } from \"../../types\";\nimport logger from \"../../utils/Logger\";\n\nexport interface LightUpModule {\n install(app: MindBaseApp): Promise<void>;\n __modulePath: string;\n}\n\n/**\n * 创建一个 LightUp 模块\n * @param install 模块安装函数\n * @param callerPath 调用者的文件路径(通常是 __filename),如果不提供则尝试通过调用栈获取\n * @returns LightUp 模块实例\n * @throws 如果模块创建失败\n */\nexport function createModule(install, callerPath?: string): LightUpModule {\n if (typeof install !== \"function\") {\n throw new Error(\"模块安装函数必须是一个函数\");\n }\n\n try {\n // 优先使用传入的 callerPath,否则通过调用栈获取\n const modulePath = callerPath || getModulePath();\n const packageRoot = findPackageRoot(modulePath);\n\n logger.debug(`创建模块:路径=${modulePath},包根目录=${packageRoot}`);\n\n return {\n install,\n __modulePath: packageRoot,\n };\n } catch (error) {\n logger.error(\"模块创建失败:\", error);\n throw new Error(`模块创建失败:${error instanceof Error ? error.message : String(error)}`);\n }\n}\n","/**\n * 创建业务错误\n * @param code HTTP 状态码\n * @param msg 错误消息\n */\nexport function createAppError(code: number, msg: string): Error {\n const err = new Error(msg);\n (err as any).statusCode = code;\n (err as any).isAppError = true;\n return err;\n}\n\n/**\n * 便捷工厂函数\n */\nexport const Errors = {\n badRequest: (msg: string) => createAppError(400, msg),\n unauthorized: (msg: string) => createAppError(401, msg),\n forbidden: (msg: string) => createAppError(403, msg),\n notFound: (msg: string) => createAppError(404, msg),\n};\n"],"mappings":"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","names":["module","express","fs","express","fs","path","fs","state","dbPath","path","fs","config","SyntaxKind","path","Node","SyntaxKind","Node","SyntaxKind","prop","SyntaxKind","Database","path","fs","config","Database","module","path","router","config","state","path","resolve","module","response","dbPath","path","path","path","fs","path"]}
1
+ {"version":3,"sources":["../core/state.ts","../feature/scanner/FileScanner.ts","../utils/Dayjs.ts","../utils/Logger.ts","../utils/InitExpress.ts","../middleware/Cors.ts","../middleware/IpParser.ts","../middleware/UaParser.ts","../utils/InitDatabase.ts","../utils/MiddlewareRegistry.ts","../utils/RouteParser.ts","../utils/ZodSchemaParser.ts","../utils/TSTypeParser.ts","../utils/DocManager.ts","../utils/RouteRegistry.ts","../utils/ComponentRegistry.ts","../utils/InitErrorHandler.ts","../utils/HttpServer.ts","../routes/Doc.route.ts","../utils/Validate.ts","../zod/Doc.schema.ts","../core/app.ts","../commands/prepare.ts","../feature/cron/CronManager.ts","../core/module/FindPackageRoot.ts","../core/module/GetModulePath.ts","../core/module/CreateModule.ts","../utils/AppError.ts"],"sourcesContent":["import express, { Express } from \"express\";\nimport type { BetterSQLite3Database } from \"drizzle-orm/better-sqlite3\";\nimport { LogLevel } from \"../types\";\n\nexport interface MindBaseAppOptions {\n /** 服务监听主机名 @default 127.0.0.1 */\n host?: string;\n /** 服务监听端口 @default 3000 */\n port?: number;\n /** 是否启用请求日志 @default true */\n logging?: boolean;\n /** 静态文件目录路径 */\n staticPath?: string;\n /** 是否解析 User-Agent 信息 @default true */\n userAgent?: boolean;\n /** 是否解析 IP 地理位置信息 @default true */\n ip?: boolean;\n /** 是否启用 CORS 跨域 @default true */\n cors?: boolean;\n /** API 路由前缀,如 \"/api\" */\n apiPrefix?: string;\n /**\n * 日志级别(优先级从低到高):\n * - debug: 调试信息(显示所有)\n * - info: 普通信息(隐藏 debug)\n * - warn: 警告信息(隐藏 debug、info)\n * - error: 错误信息(隐藏 debug、info、warn)\n * - silent: 静默模式(隐藏所有)\n * @default \"info\"\n */\n logLevel?: LogLevel;\n /** 数据库配置 */\n database?: {\n /** SQLite 数据库文件路径 @default \"./data/app.db\" */\n path?: string;\n };\n /** 认证白名单路径(支持字符串和正则表达式) */\n authWhitelist?: (string | RegExp)[];\n}\nexport interface AppState {\n options: MindBaseAppOptions;\n express: Express;\n db?: BetterSQLite3Database<Record<string, any>>; // Drizzle 数据库实例\n schemas?: Record<string, any>; // 合并后的所有 schema\n}\n\nexport function createState(options: MindBaseAppOptions = {}): AppState {\n return {\n options: {\n host: options.host || \"127.0.0.1\",\n port: options.port || 3000,\n logging: options.logging !== false,\n staticPath: options.staticPath,\n userAgent: options.userAgent !== false,\n ip: options.ip !== false,\n cors: options.cors !== false,\n apiPrefix: options.apiPrefix,\n logLevel: options.logLevel || \"info\",\n authWhitelist: [],\n database: {\n path: options.database?.path || \"./data/app.db\",\n },\n },\n express: express(),\n schemas: {},\n };\n}\n","import { glob } from \"glob\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport { pathToFileURL } from \"url\";\nimport logger from \"../../utils/Logger\";\n\nconst CACHE_VERSION = \"2.0\";\nconst CACHE_DIR = path.join(process.cwd(), \"node_modules/.cache/mindbase\");\nconst CACHE_FILE = path.join(CACHE_DIR, \"startup-cache.json\");\n\n/**\n * 缓存条目接口\n */\ninterface CacheEntry {\n filePath: string;\n mtime: number;\n}\n\n/**\n * 缓存数据接口\n */\ninterface CacheData {\n version: string;\n entries: Map<string, CacheEntry>;\n}\n\n// 全局缓存数据\nlet cacheData: CacheData | null = null;\n\n/**\n * 扫描结果接口\n */\nexport interface ScanResult {\n fileName: string;\n defaultExport: any;\n allExports?: any;\n type: \"route\" | \"middleware\" | \"schema\";\n filePath: string;\n /** 缓存命中标志(文档已在数据库) */\n cacheHit?: boolean;\n}\n\n/**\n * 扫描器状态接口\n */\ninterface ScannerState {\n scanPaths: string[]; // 要扫描的目录数组\n baseDir: string; // 基础目录(最后扫描)\n}\n\n// 初始化扫描器状态\nconst state: ScannerState = {\n scanPaths: [],\n baseDir: \"\",\n};\n\n/**\n * 设置基础目录\n * @param baseDir 基础目录路径\n */\nexport function setBaseDir(baseDir: string): void {\n state.baseDir = baseDir;\n}\n\n/**\n * 添加扫描目录\n * @param dirPath 要添加的目录绝对路径\n * @throws 如果路径不是目录或不存在\n */\nexport function addScanPath(dirPath: string): void {\n // 验证路径是否为绝对路径\n if (!path.isAbsolute(dirPath)) {\n throw new Error(`路径必须是绝对路径: ${dirPath}`);\n }\n\n // 验证路径是否存在且为目录\n if (!fs.existsSync(dirPath)) {\n throw new Error(`目录不存在: ${dirPath}`);\n }\n\n if (!fs.statSync(dirPath).isDirectory()) {\n throw new Error(`路径不是目录: ${dirPath}`);\n }\n\n // 去重:检查路径是否已经存在\n if (state.scanPaths.includes(dirPath)) {\n return;\n }\n\n // 检查是否是基础目录的子目录,如果是则跳过\n if (state.baseDir && dirPath.startsWith(state.baseDir)) {\n return;\n }\n\n // 检查是否是其他已添加路径的子目录,如果是则跳过\n for (const existingPath of state.scanPaths) {\n if (dirPath.startsWith(existingPath)) {\n return;\n }\n }\n\n // 添加到扫描路径数组\n state.scanPaths.push(dirPath);\n}\n\n/**\n * 验证路径是否为有效目录\n * @param dirPath 目录路径\n * @returns 是否为有效目录\n */\nfunction isValidDirectory(dirPath: string): boolean {\n try {\n return fs.statSync(dirPath).isDirectory();\n } catch {\n return false;\n }\n}\n\n/**\n * 从文件路径提取文件名(不含扩展名)\n * @param filePath 文件路径\n * @returns 文件名(不含扩展名)\n */\nfunction extractFileName(filePath: string): string {\n const fileName = path.basename(filePath);\n // 移除 .route.ts, .middleware.ts 或 .schema.ts 扩展名\n return fileName.replace(/\\.(route|middleware|schema)\\.ts$/, \"\");\n}\n\n/**\n * 加载缓存数据\n * @returns 缓存数据对象,加载失败返回 null\n */\nasync function loadCache(): Promise<void> {\n try {\n if (!fs.existsSync(CACHE_FILE)) {\n cacheData = { version: CACHE_VERSION, entries: new Map() };\n return;\n }\n\n const json = fs.readFileSync(CACHE_FILE, \"utf-8\");\n const data = JSON.parse(json);\n\n // 检查缓存版本\n if (data.version !== CACHE_VERSION) {\n logger.debug(`缓存版本不匹配 (${data.version} vs ${CACHE_VERSION}),将重新构建`);\n cacheData = { version: CACHE_VERSION, entries: new Map() };\n return;\n }\n\n // 重建 Map\n cacheData = {\n version: data.version,\n entries: new Map(Object.entries(data.entries).map(([k, v]: [string, any]) => [k, v])),\n };\n\n logger.debug(`已加载缓存,包含 ${cacheData.entries.size} 个文件条目`);\n } catch (error) {\n logger.warn(`加载缓存失败,将重新构建: ${error}`);\n cacheData = { version: CACHE_VERSION, entries: new Map() };\n }\n}\n\n/**\n * 保存缓存数据\n */\nasync function saveCache(): Promise<void> {\n try {\n if (!cacheData) return;\n\n // 确保目录存在\n if (!fs.existsSync(CACHE_DIR)) {\n fs.mkdirSync(CACHE_DIR, { recursive: true });\n }\n\n // 序列化 Map 为普通对象\n const data = {\n version: cacheData.version,\n entries: Object.fromEntries(cacheData.entries),\n };\n\n fs.writeFileSync(CACHE_FILE, JSON.stringify(data, null, 2), \"utf-8\");\n logger.debug(`缓存已保存,包含 ${cacheData.entries.size} 个文件条目`);\n } catch (error) {\n logger.warn(`保存缓存失败: ${error}`);\n }\n}\n\n/**\n * 启动扫描目录\n * @param onlyPaths 是否仅返回路径,不导入模块\n * @returns 扫描结果数组\n */\nexport async function scan(onlyPaths: boolean = false): Promise<ScanResult[]> {\n // 加载缓存\n await loadCache();\n\n const results: ScanResult[] = [];\n const allScanPaths = [...state.scanPaths];\n const processedFiles = new Set<string>();\n\n // 如果设置了基础目录,将其添加到最后扫描\n if (state.baseDir) {\n allScanPaths.push(state.baseDir);\n }\n\n // 循环扫描所有目录\n for (const dirPath of allScanPaths) {\n if (!isValidDirectory(dirPath)) {\n logger.warn(`跳过无效目录: ${dirPath}`);\n continue;\n }\n\n // 构建 glob 模式\n const patterns = [\n { type: \"middleware\" as const, pattern: \"**/*.middleware.ts\" },\n { type: \"route\" as const, pattern: \"**/*.route.ts\" },\n { type: \"schema\" as const, pattern: \"**/*.schema.ts\" },\n ];\n\n for (const { type, pattern } of patterns) {\n const globPattern = path.join(dirPath, pattern).replace(/\\\\/g, \"/\");\n try {\n const files = await glob(globPattern, { absolute: true });\n for (const file of files) {\n // 去重:跳过已处理的文件\n if (processedFiles.has(file)) {\n continue;\n }\n processedFiles.add(file);\n\n try {\n const fileName = extractFileName(file);\n\n if (onlyPaths) {\n results.push({\n fileName,\n type,\n filePath: file,\n defaultExport: null,\n allExports: null,\n });\n continue;\n }\n\n // 检查文件修改时间\n const stats = await fs.promises.stat(file);\n const mtime = stats.mtimeMs;\n\n // 检查缓存命中\n const cached = cacheData?.entries.get(file);\n const cacheHit = cached && cached.mtime === mtime;\n\n if (cacheHit) {\n // 缓存命中,文档已在数据库\n logger.debug(`缓存命中: ${file}`);\n }\n\n // 导入模块(必须执行,获取 handler 用于 app.use)\n const module = await import(pathToFileURL(file).href);\n const scanResult: ScanResult = {\n fileName,\n defaultExport: module.default,\n allExports: module,\n type,\n filePath: file,\n cacheHit,\n };\n results.push(scanResult);\n\n // 更新缓存(无论是否命中,都更新 mtime)\n if (cacheData) {\n cacheData.entries.set(file, { filePath: file, mtime });\n }\n } catch (error) {\n logger.warn(`处理文件失败: ${file}`, error);\n }\n }\n } catch (error) {\n logger.warn(`扫描目录失败: ${dirPath} (Pattern: ${pattern})`, error);\n }\n }\n }\n\n // 保存缓存\n await saveCache();\n\n return results;\n}\n","import dayjs from \"dayjs\";\nimport \"dayjs/locale/zh-cn\";\nimport duration from \"dayjs/plugin/duration\";\nimport relativeTime from \"dayjs/plugin/relativeTime\";\nimport utc from \"dayjs/plugin/utc\";\n\n// 设置中文语言包\ndayjs.locale(\"zh-cn\");\n\n// 注册常用插件\ndayjs.extend(utc);\ndayjs.extend(duration);\ndayjs.extend(relativeTime);\n\nexport default dayjs;\nexport { dayjs };\n","import dayjs from \"./Dayjs\";\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\" | \"silent\";\n\nconst LOG_LEVELS = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n} as const;\n\nlet currentLogLevel: LogLevel = \"info\";\n\nconst COLORS = {\n debug: \"\\x1b[36m\",\n info: \"\\x1b[32m\",\n warn: \"\\x1b[33m\",\n error: \"\\x1b[31m\",\n reset: \"\\x1b[0m\",\n} as const;\n\n/**\n * 计算字符串在终端中的视觉宽度\n * 修复:区分单宽符号 (如 ✓) 和双宽符号 (如 中文、Emoji)\n */\nfunction getVisualWidth(str: string): number {\n let width = 0;\n const segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n for (const { segment } of segmenter.segment(str)) {\n const charCode = segment.charCodeAt(0);\n\n // 1. 基础 ASCII\n if (charCode <= 255) {\n width += 1;\n continue;\n }\n\n // 2. CJK 字符集范围 (常用中文、标点、全角符号)\n const isCJK =\n (charCode >= 0x4e00 && charCode <= 0x9fff) || // CJK Unified Ideographs\n (charCode >= 0x3000 && charCode <= 0x303f) || // CJK Symbols and Punctuation\n (charCode >= 0xff00 && charCode <= 0xffef); // Fullwidth Forms\n\n // 3. Emoji 或代理对 (通常 segment.length > 1)\n const isMultiByte = segment.length > 1;\n\n if (isCJK || isMultiByte) {\n width += 2;\n } else {\n // 4. 其他特殊符号 (如 ✓, ★, ☎) 在大多数终端占 1 格\n width += 1;\n }\n }\n return width;\n}\n\n/**\n * 截断字符串以适应视觉宽度,从头部截断并保留末尾\n */\nfunction truncateToWidth(str: string, maxWidth: number): string {\n const segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n const segments = Array.from(segmenter.segment(str)).map((s) => s.segment);\n\n if (getVisualWidth(str) <= maxWidth) return str;\n\n let currentWidth = 3; // 为 \"...\" 预留\n let result = \"\";\n\n // 从后往前遍历 segments\n for (let i = segments.length - 1; i >= 0; i--) {\n const segment = segments[i];\n const segmentWidth = getVisualWidth(segment);\n if (currentWidth + segmentWidth > maxWidth) break;\n result = segment + result;\n currentWidth += segmentWidth;\n }\n return \"...\" + result;\n}\n\nfunction formatMessage(level: LogLevel, message: string): string {\n const timestamp = dayjs().format(\"YYYY-MM-DD HH:mm:ss\");\n const terminalWidth = process.stdout.columns || 80;\n const timeStr = ` ${timestamp}`;\n const timeWidth = getVisualWidth(timeStr);\n const maxMessageWidth = terminalWidth - timeWidth - 2;\n\n let displayMessage = message;\n const messageWidth = getVisualWidth(displayMessage);\n\n if (messageWidth > maxMessageWidth) {\n displayMessage = truncateToWidth(displayMessage, maxMessageWidth);\n }\n\n const currentMsgWidth = getVisualWidth(displayMessage);\n const paddingCount = Math.max(0, terminalWidth - currentMsgWidth - timeWidth);\n const padding = \" \".repeat(paddingCount);\n\n return `${COLORS[level]}${displayMessage}${padding}${timeStr}${COLORS.reset}`;\n}\n\nconst startupTime = Date.now();\n\n// 标签填充函数(目标显示宽度 8,空格分散到字符间)\nfunction padTag(tag: string, targetWidth = 8): string {\n const currentWidth = getVisualWidth(tag);\n const padding = Math.max(0, targetWidth - currentWidth);\n\n if (padding === 0) return tag;\n\n // 将空格均匀分散到字符之间\n const chars = [...tag]; // 按码点分割\n const gapCount = chars.length + 1; // 间隙数 = 字符数 + 1(前后和中间)\n\n // 计算每个间隙的空格数\n const baseSpaces = Math.floor(padding / gapCount);\n const extraSpaces = padding % gapCount;\n\n let result = \"\";\n for (let i = 0; i < chars.length; i++) {\n // 每个间隙的空格 = 基础空格 + 额外空格(前 extraSpaces 个间隙多1个)\n const spaces = baseSpaces + (i < extraSpaces ? 1 : 0);\n result += \" \".repeat(spaces) + chars[i];\n }\n // 最后一个间隙\n result += \" \".repeat(baseSpaces + (chars.length < extraSpaces ? 1 : 0));\n\n return result;\n}\n\nfunction startupMessage(message: string, tag?: string): string {\n const diff = Date.now() - startupTime;\n const timeStr = diff.toString().padStart(6, \"0\");\n const tagStr = tag ? `【${padTag(tag)}】` : \"\";\n return `${COLORS[\"warn\"]}[${timeStr}] ${tagStr}${message}${COLORS[\"reset\"]}`;\n}\n\nfunction shouldLog(level: LogLevel): boolean {\n return LOG_LEVELS[level] >= LOG_LEVELS[currentLogLevel];\n}\n\nfunction formatArgs(args: any[]): string {\n return args\n .map((arg) => {\n if (arg instanceof Error) {\n return arg.message;\n }\n if (typeof arg === \"object\") {\n return JSON.stringify(arg, null, 2);\n }\n return String(arg);\n })\n .join(\" \");\n}\n\nexport const logger = {\n debug(...args: any[]): void {\n if (shouldLog(\"debug\")) {\n console.log(formatMessage(\"debug\", formatArgs(args)));\n }\n },\n\n info(...args: any[]): void {\n if (shouldLog(\"info\")) {\n console.log(formatMessage(\"info\", formatArgs(args)));\n }\n },\n\n warn(...args: any[]): void {\n if (shouldLog(\"warn\")) {\n console.warn(formatMessage(\"warn\", formatArgs(args)));\n }\n },\n\n error(...args: any[]): void {\n if (shouldLog(\"error\")) {\n // 先打印带颜色的格式化消息\n console.error(formatMessage(\"error\", formatArgs(args)));\n // 如果有 Error 对象,用 console.error 单独打印以显示堆栈\n const errorArg = args.find((arg) => arg instanceof Error);\n if (errorArg) {\n console.error(errorArg);\n }\n }\n },\n\n startup(tagOrMessage: string, ...args: any[]): void {\n // 如果有额外参数,第一个是标签,其余是消息\n // 否则第一个参数是消息,无标签\n if (args.length > 0) {\n console.log(startupMessage(formatArgs(args), tagOrMessage));\n } else {\n console.log(startupMessage(tagOrMessage));\n }\n },\n\n setLevel(level: LogLevel): void {\n currentLogLevel = level;\n },\n\n getLevel(): LogLevel {\n return currentLogLevel;\n },\n};\n\nexport default logger;\n","import express, { Express } from \"express\";\nimport fs from \"fs\";\nimport cookieParser from \"cookie-parser\";\nimport cors from \"../middleware/Cors\";\nimport ipParser from \"../middleware/IpParser\";\nimport uaParser from \"../middleware/UaParser\";\nimport { AppState } from \"../types/Index\";\nimport logger from \"./Logger\";\n\nexport default function initExpress(mindBaseState: AppState): void {\n const app = mindBaseState.express;\n const options = mindBaseState.options;\n app.getDB = () => mindBaseState.db;\n app.configs = mindBaseState.options;\n app.disable(\"x-powered-by\");\n app.use(express.urlencoded({ extended: false, limit: \"10mb\" }));\n app.use(express.json({ limit: \"10mb\" }));\n app.use(cookieParser());\n if (options.staticPath) {\n if (!fs.existsSync(options.staticPath)) {\n fs.mkdirSync(options.staticPath, { recursive: true });\n }\n app.use(express.static(options.staticPath));\n logger.startup(\"设置\", `静态目录: ${options.staticPath}`);\n }\n if (options.cors) {\n app.use(cors);\n logger.startup(\"设置\", \"跨域请求头\");\n }\n if (options.ip) {\n logger.startup(\"设置\", \"IP地址解析\");\n app.use(ipParser);\n }\n if (options.userAgent) {\n logger.startup(\"设置\", \"用户代理解析\");\n app.use(uaParser);\n }\n}\n","import { NextFunction, Request, Response } from \"express\";\n\n/**\n * 跨域处理\n * @description 为API请求添加处理跨域请求头,并处理Options 预请求\n */\nexport default function (req: Request, res: Response, next: NextFunction) {\n res.header(\"Access-Control-Allow-Origin\", \"*\");\n res.header(\"Access-Control-Allow-Credentials\", \"true\");\n res.header(\"Access-Control-Allow-Methods\", \"POST,GET,OPTIONS\");\n res.header(\"Access-Control-Allow-Headers\", \"Content-Type,Content-Length, Authorization, Accept,X-Requested-With\");\n if (req.method == \"OPTIONS\") {\n res.sendStatus(200);\n } else {\n next();\n }\n}\n","import { NextFunction, Request, Response } from \"express\";\nimport ipdb from \"ipip-ipdb\";\nimport { join } from \"path\";\nimport logger from \"../utils/Logger\";\n\n/**\n * IP 解析结果数据结构\n */\nexport interface IpInfo {\n address: string; // 原始 IP 地址\n location: string; // 格式化后的地理位置 (国家 省份 城市)\n country: string; // 国家\n province: string; // 省份/直辖市\n city: string; // 城市\n isp: string; // 运营商\n latitude: string; // 纬度\n longitude: string; // 经度\n isLocal: boolean; // 是否为本地/回环地址\n}\n\n// 预初始化数据库实例\nconst dbPath = join(process.cwd(), \"ipipfree.ipdb\");\nlet cityInstance: any;\n\ntry {\n cityInstance = new ipdb.City(dbPath);\n} catch (error) {\n logger.error(`[IpParser] Failed to load IP database at: ${dbPath}`);\n}\n\n/**\n * IP 解析中间件\n * 纯净实现:仅解析 IP 信息并打平数据结构,不包含冗余的向后兼容字段。\n */\nexport default function (req: Request, res: Response, next: NextFunction) {\n const ip = (req.headers[\"real-ip\"] || req.headers[\"x-real-ip\"] || req.ip) as string;\n\n const info: IpInfo = {\n address: ip,\n location: \"未知\",\n country: \"\",\n province: \"\",\n city: \"\",\n isp: \"\",\n latitude: \"\",\n longitude: \"\",\n isLocal: false,\n };\n\n // 处理本地回环地址\n const localIdentifiers = [\"127.0.0.1\", \"::1\", \"::ffff:127.0.0.1\", \"localhost\"];\n if (localIdentifiers.includes(ip)) {\n info.location = \"本机\";\n info.isLocal = true;\n res.locals.ip = info;\n return next();\n }\n\n // 数据库查询\n if (cityInstance) {\n try {\n const data = cityInstance.findMap(ip, \"CN\");\n if (data) {\n info.country = data.country_name || \"\";\n info.province = data.region_name || \"\";\n info.city = data.city_name || \"\";\n info.isp = data.isp_domain || \"\";\n info.latitude = data.latitude || \"\";\n info.longitude = data.longitude || \"\";\n\n const parts = [info.country, info.province, info.city].filter(Boolean);\n info.location = parts.join(\" \") || \"未知位置\";\n }\n } catch (err) {\n // 查询失败保持默认 info\n }\n }\n\n res.locals.ip = info;\n next();\n}\n","import { NextFunction, Request, Response } from \"express\";\nimport { UAParser } from \"ua-parser-js\";\n\nexport interface UaInfo {\n ua: string;\n browser: {\n name?: string;\n version?: string;\n major?: string;\n };\n engine: {\n name?: string;\n version?: string;\n };\n os: {\n name?: string;\n version?: string;\n };\n device: {\n model?: string;\n type?: string;\n vendor?: string;\n };\n cpu: {\n architecture?: string;\n };\n isMobile: boolean;\n}\n\n/**\n * UA 解析中间件\n * 纯净实现:仅解析 User-Agent 信息并存入 res.locals.UA\n */\nexport default function (req: Request, res: Response, next: NextFunction) {\n const parser = new UAParser(req.headers[\"user-agent\"] as string);\n const result = parser.getResult();\n\n const ua: UaInfo = {\n ua: result.ua,\n browser: result.browser,\n engine: result.engine,\n os: result.os,\n device: result.device,\n cpu: result.cpu,\n isMobile: result.device.type === \"mobile\",\n };\n\n res.locals.UA = ua;\n next();\n}\n","import path from \"path\";\nimport fs from \"fs\";\nimport { drizzle } from \"drizzle-orm/better-sqlite3\";\nimport { migrate } from \"drizzle-orm/better-sqlite3/migrator\";\nimport Database from \"better-sqlite3\";\nimport { AppState } from \"../core/state\";\nimport { ScanResult } from \"../types/Index\";\nimport logger from \"./Logger\";\n\n/**\n * 封装细节:从扫描结果中提取 Schema 并初始化数据库\n * @param state 应用状态\n * @param scannedResults 扫描结果\n * @returns 数据库实例\n * @throws 如果数据库设置失败\n */\nexport function setupDatabase(state: AppState, scannedResults: ScanResult[]) {\n try {\n if (!state) {\n throw new Error(\"应用状态对象不能为空\");\n }\n\n if (!Array.isArray(scannedResults)) {\n throw new Error(\"扫描结果必须是一个数组\");\n }\n\n const schemas: Record<string, any> = {};\n for (const item of scannedResults) {\n if (item.type === \"schema\" && item.allExports) {\n try {\n Object.assign(schemas, item.allExports);\n } catch (e) {\n logger.warn(`处理 Schema 文件失败: ${item.filePath}`, e);\n }\n }\n }\n state.schemas = schemas;\n\n logger.startup(\"扫描\", `提取到 ${Object.keys(schemas).length} 个 Schema 定义`);\n\n return initDatabase({\n schemas,\n state,\n });\n } catch (error) {\n logger.error(\"数据库设置失败:\", error);\n throw new Error(`数据库设置失败:${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * 初始化 SQLite 数据库\n * @param options 配置选项\n * @returns 数据库实例\n * @throws 如果数据库初始化失败\n */\nexport function initDatabase(options: { schemas: Record<string, any>; dbPath?: string; state?: AppState }): any {\n if (!options) {\n throw new Error(\"初始化选项不能为空\");\n }\n\n try {\n const currentDir = process.cwd();\n const dbPath = options.dbPath || options.state?.options?.database?.path || \"./data/app.db\";\n const absoluteDbPath = path.resolve(currentDir, dbPath);\n const dbDir = path.dirname(absoluteDbPath);\n\n logger.startup(\"数据库\", `初始化:路径=${absoluteDbPath}`);\n\n // 确保目录存在\n try {\n if (!fs.existsSync(dbDir)) {\n logger.startup(\"数据库\", `创建目录:${dbDir}`);\n fs.mkdirSync(dbDir, { recursive: true });\n }\n } catch (e) {\n throw new Error(`创建数据库目录失败:${e instanceof Error ? e.message : String(e)}`);\n }\n\n // 初始化 SQLite 数据库\n let sqlite: Database.Database;\n try {\n sqlite = new Database(absoluteDbPath);\n } catch (e) {\n throw new Error(`连接数据库失败:${e instanceof Error ? e.message : String(e)}`);\n }\n\n // SQLite 性能优化设置\n try {\n // 写前日志模式(提升并发性能)\n sqlite.pragma(\"journal_mode = WAL\");\n // 同步模式(安全性与性能平衡)\n sqlite.pragma(\"synchronous = NORMAL\");\n // 页面缓存:1GB(负值表示 KB)\n sqlite.pragma(\"cache_size = -1048576\");\n // 临时表使用内存\n sqlite.pragma(\"temp_store = MEMORY\");\n // 页面大小:4KB\n sqlite.pragma(\"page_size = 4096\");\n // WAL 自动检查点阈值(减少刷盘频率)\n sqlite.pragma(\"wal_autocheckpoint = 10000\");\n // 忙等待超时:5秒\n sqlite.pragma(\"busy_timeout = 5000\");\n } catch (e) {\n logger.warn(\"设置 SQLite 性能参数失败:\", e);\n // 继续执行,不中断初始化\n }\n\n // 初始化 Drizzle\n let db: any;\n try {\n db = drizzle(sqlite, { schema: options.schemas || {} });\n } catch (e) {\n // 关闭 SQLite 连接\n try {\n sqlite.close();\n } catch (closeError) {\n logger.warn(\"关闭数据库连接失败:\", closeError);\n }\n throw new Error(`初始化 Drizzle ORM 失败:${e instanceof Error ? e.message : String(e)}`);\n }\n\n // 如果提供了状态对象,更新它\n if (options.state) {\n options.state.db = db;\n }\n\n return db;\n } catch (error) {\n logger.error(\"数据库初始化失败:\", error);\n throw new Error(`数据库初始化失败:${error instanceof Error ? error.message : String(error)}`);\n }\n}\n","import { Express } from \"express\";\nimport { ScanResult } from \"../types/Index\";\nimport logger from \"./Logger\";\n\nexport async function registerMiddleware(app: Express, config: ScanResult): Promise<void> {\n const { fileName = \"anonymous\", defaultExport: handler } = config;\n\n try {\n app.use(handler);\n logger.startup(\"中间件\", `注册: ${fileName}`);\n } catch (error) {\n logger.error(`注册中间件失败 ${fileName}:`, error);\n }\n}\n","import {\n Project,\n SyntaxKind,\n Node,\n SourceFile,\n StringLiteral,\n ModuleKind,\n ScriptTarget,\n JSDoc,\n} from \"ts-morph\";\nimport * as path from \"path\";\nimport { RouteInfo, RequestSchema, ResponseSchema, FieldValidation } from \"../types/DocTypes\";\nimport logger from \"./Logger\";\nimport { ZodSchemaParser } from \"./ZodSchemaParser\";\nimport { TSTypeParser } from \"./TSTypeParser\";\n\n/**\n * apidoc 标签解析结果\n */\ninterface ApiDocTags {\n params: Array<{\n name: string;\n type: string;\n description: string;\n required: boolean;\n enumValues?: string[];\n }>;\n success: Array<{\n name: string;\n type: string;\n description: string;\n parent?: string;\n }>;\n}\n\n/**\n * 路由解析器\n * 使用 ts-morph 解析路由文件,提取路由信息\n */\nexport class RouteParser {\n private project: Project;\n private schemaParser: ZodSchemaParser;\n private tsTypeParser: TSTypeParser;\n\n constructor() {\n this.project = new Project({\n compilerOptions: {\n module: ModuleKind.CommonJS,\n target: ScriptTarget.ES2018,\n allowJs: true,\n },\n });\n this.schemaParser = new ZodSchemaParser();\n this.tsTypeParser = new TSTypeParser();\n }\n\n /**\n * 解析单个路由文件\n * @param filePath 路由文件路径\n * @returns 路由信息数组\n */\n public parseRouteFile(filePath: string): RouteInfo[] {\n try {\n const sourceFile = this.project.addSourceFileAtPath(filePath);\n const routes: RouteInfo[] = [];\n\n // 获取所有导入的 schema 文件映射\n const schemaFiles = this.getImportedSchemaFiles(sourceFile, filePath);\n\n // 获取所有类型导入映射(用于响应类型解析)\n const typeImports = this.getTypeImports(sourceFile, filePath);\n\n // 查找所有路由调用\n sourceFile.forEachDescendant((node) => {\n const callExpr = node as any;\n if (callExpr.isKind && callExpr.isKind(SyntaxKind.CallExpression) && callExpr.getExpression && callExpr.getExpression().isKind(SyntaxKind.PropertyAccessExpression)) {\n const propAccess = callExpr.getExpression();\n const object = propAccess.getExpression && propAccess.getExpression().getText();\n const method = propAccess.getName && propAccess.getName();\n\n // 检查是否是 router 的 HTTP 方法调用\n if (object === \"router\" && [\"get\", \"post\", \"put\", \"delete\", \"patch\"].includes(method)) {\n // 提取路由路径\n const args = callExpr.getArguments && callExpr.getArguments();\n if (args && args.length > 0) {\n const pathArg = args[0];\n if (pathArg.isKind && pathArg.isKind(SyntaxKind.StringLiteral)) {\n const routePath = pathArg.getText && pathArg.getText().replace(/['\"]/g, \"\");\n\n // 提取 JSDoc 注释\n const jsDoc = callExpr.getPreviousSiblingIfKind && callExpr.getPreviousSiblingIfKind(SyntaxKind.JSDocComment);\n let summary = \"\";\n let description = \"\";\n let requestSchema: RequestSchema | undefined;\n let responseSchema: ResponseSchema | undefined;\n\n if (jsDoc) {\n const commentText = jsDoc.getCommentText && jsDoc.getCommentText();\n if (commentText) {\n const lines = commentText.split(\"\\n\").map((line) => line.trim());\n summary = lines[0] || \"\";\n description = lines.slice(1).join(\"\\n\").trim() || summary;\n }\n\n // 解析 apidoc 格式的注释标签\n try {\n const fullCommentText = jsDoc.getFullText?.() || commentText || \"\";\n const apiDocTags = this.parseApiDocTags(fullCommentText);\n\n // 从 @apiParam 构建请求 Schema(优先级高于 validate 中间件)\n if (apiDocTags.params.length > 0) {\n requestSchema = this.buildRequestSchemaFromTags(apiDocTags.params);\n }\n\n // 从 @apiSuccess 构建响应 Schema\n if (apiDocTags.success.length > 0) {\n responseSchema = this.buildResponseSchemaFromTags(apiDocTags.success);\n }\n } catch (error) {\n logger.warn(`解析 apidoc 注释失败: ${filePath}:${routePath}`, error);\n }\n\n // 如果没有 @apiSuccess,尝试提取 @returns 标签(降级方案)\n if (!responseSchema) {\n responseSchema = this.extractResponseSchema(jsDoc, sourceFile, typeImports);\n }\n }\n\n // 提取中间件信息\n const middlewares: string[] = [];\n for (let i = 1; i < args.length - 1; i++) {\n const arg = args[i];\n if (arg.isKind(SyntaxKind.CallExpression)) {\n const mwCallExpr = arg as any;\n const expr = mwCallExpr.getExpression();\n if (expr.isKind(SyntaxKind.Identifier)) {\n middlewares.push(expr.getText());\n } else if (expr.isKind(SyntaxKind.PropertyAccessExpression)) {\n middlewares.push(expr.getText());\n }\n }\n }\n\n // 如果没有从注释获取到请求 Schema,尝试从 validate 中间件获取(降级方案)\n if (!requestSchema) {\n requestSchema = this.extractRequestSchema(args, schemaFiles);\n }\n\n const routeInfo: RouteInfo = {\n module: path.basename(path.dirname(filePath)).toLowerCase(),\n method: method.toUpperCase(),\n path: routePath,\n fullPath: \"\", // 完整路径会在注册时填充\n summary,\n description,\n requestSchema,\n responseSchema,\n middlewares,\n filePath,\n };\n\n routes.push(routeInfo);\n }\n }\n }\n }\n });\n\n return routes;\n } catch (error) {\n logger.error(`解析路由文件失败: ${filePath}`, error);\n return [];\n }\n }\n\n /**\n * 获取导入的 schema 文件映射\n * @returns Map<变量名, 文件绝对路径>\n */\n private getImportedSchemaFiles(\n sourceFile: SourceFile,\n currentFilePath: string\n ): Map<string, string> {\n const schemaFiles = new Map<string, string>();\n\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const source = importDecl.getModuleSpecifierValue();\n\n // 检查是否是 schema 相关的导入\n if (source.includes(\".schema\") || source.includes(\"/zod/\") || source.includes(\"\\\\zod\\\\\")) {\n // 解析相对路径为绝对路径\n const absolutePath = this.resolveImportPath(\n currentFilePath,\n source\n );\n if (absolutePath) {\n // 记录导入的变量名 -> 文件路径映射\n for (const specifier of importDecl.getNamedImports()) {\n logger.debug(`发现 schema 导入: ${specifier.getName()} -> ${absolutePath}`);\n schemaFiles.set(specifier.getName(), absolutePath);\n }\n } else {\n logger.debug(`无法解析 schema 导入路径: ${source}`);\n }\n }\n }\n\n return schemaFiles;\n }\n\n /**\n * 获取所有类型导入映射(用于响应类型解析)\n * @returns Map<类型名, 文件绝对路径>\n */\n private getTypeImports(\n sourceFile: SourceFile,\n currentFilePath: string\n ): Map<string, string> {\n const typeImports = new Map<string, string>();\n\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const source = importDecl.getModuleSpecifierValue();\n\n // 解析相对路径为绝对路径\n const absolutePath = this.resolveImportPath(currentFilePath, source);\n if (absolutePath) {\n // 记录所有命名导入\n for (const specifier of importDecl.getNamedImports()) {\n typeImports.set(specifier.getName(), absolutePath);\n }\n }\n }\n\n return typeImports;\n }\n\n /**\n * 从 JSDoc 中提取响应 Schema\n */\n private extractResponseSchema(\n jsDoc: JSDoc,\n sourceFile: SourceFile,\n typeImports: Map<string, string>\n ): ResponseSchema | undefined {\n // 获取所有 JSDoc 标签\n const tags = jsDoc.getTags();\n\n for (const tag of tags) {\n const tagName = tag.getTagName();\n\n // 检查 @returns 或 @return 标签\n if (tagName === \"returns\" || tagName === \"return\") {\n // 获取标签的完整文本\n const tagText = tag.getText?.() || \"\";\n logger.debug(`@returns 标签文本: ${tagText}`);\n\n // 尝试从标签文本中提取类型 {TypeName}\n const typeMatch = tagText.match(/@\\s*returns?\\s*\\{([^}]+)\\}/i);\n if (typeMatch) {\n const typeString = typeMatch[1].trim();\n logger.debug(`从标签文本提取类型: ${typeString}`);\n\n const responseSchema = this.tsTypeParser.parseResponseType(\n sourceFile,\n typeString,\n typeImports\n );\n\n if (responseSchema) {\n return responseSchema;\n }\n }\n\n // 尝试从注释中提取类型\n const comment = tag.getCommentText?.();\n if (comment) {\n const commentMatch = comment.match(/^\\{([^}]+)\\}/);\n if (commentMatch) {\n const typeString = commentMatch[1].trim();\n logger.debug(`从注释提取类型: ${typeString}`);\n\n const responseSchema = this.tsTypeParser.parseResponseType(\n sourceFile,\n typeString,\n typeImports\n );\n\n if (responseSchema) {\n return responseSchema;\n }\n }\n }\n\n // 尝试使用 ts-morph 的类型表达式\n const typeExpression = (tag as any).getTypeExpression?.();\n if (typeExpression) {\n const typeNode = typeExpression.getType?.();\n if (typeNode) {\n const typeString = typeNode.getText();\n logger.debug(`从类型表达式提取类型: ${typeString}`);\n\n if (typeString && typeString !== \"any\") {\n const responseSchema = this.tsTypeParser.parseResponseType(\n sourceFile,\n typeString,\n typeImports\n );\n\n if (responseSchema) {\n return responseSchema;\n }\n }\n }\n }\n }\n }\n\n return undefined;\n }\n\n /**\n * 解析导入路径为绝对路径\n */\n private resolveImportPath(\n currentFilePath: string,\n importPath: string\n ): string | null {\n try {\n // 处理相对路径\n if (importPath.startsWith(\".\")) {\n const currentDir = path.dirname(currentFilePath);\n const absolutePath = path.resolve(currentDir, importPath);\n\n // 尝试添加 .ts 扩展名\n const tsPath = absolutePath.endsWith(\".ts\")\n ? absolutePath\n : `${absolutePath}.ts`;\n return tsPath;\n }\n\n // 非相对路径暂不处理\n return null;\n } catch (error) {\n logger.warn(`解析导入路径失败: ${importPath}`);\n return null;\n }\n }\n\n /**\n * 提取请求 Schema\n */\n private extractRequestSchema(\n args: any[],\n schemaFiles: Map<string, string>\n ): RequestSchema | undefined {\n for (const arg of args) {\n // 路由参数可能是 validate(...) 或 validate(...) as any\n // 需要先处理 as any 类型断言\n let targetArg = arg;\n if (\n arg.isKind &&\n arg.isKind(SyntaxKind.AsExpression)\n ) {\n targetArg = arg.getExpression();\n }\n\n // 检查是否是 validate 调用\n if (\n targetArg.isKind &&\n targetArg.isKind(SyntaxKind.CallExpression) &&\n targetArg.getExpression &&\n targetArg.getExpression().isKind &&\n targetArg.getExpression().isKind(SyntaxKind.Identifier) &&\n targetArg.getExpression().getText() === \"validate\"\n ) {\n const validateArgs = targetArg.getArguments();\n if (validateArgs.length === 0) continue;\n\n // 获取 schema 变量名\n const schemaArg = validateArgs[0];\n let schemaName: string;\n\n // 处理 schema 参数中的 as any 类型断言\n if (\n schemaArg.isKind &&\n schemaArg.isKind(SyntaxKind.AsExpression)\n ) {\n schemaName = schemaArg.getExpression().getText();\n } else {\n schemaName = schemaArg.getText();\n }\n\n // 获取 target 参数\n let target: \"body\" | \"query\" | \"params\" = \"body\";\n if (validateArgs.length > 1) {\n const targetArgParam = validateArgs[1];\n if (\n targetArgParam.isKind &&\n targetArgParam.isKind(SyntaxKind.StringLiteral)\n ) {\n target = (targetArgParam as StringLiteral).getLiteralValue() as\n | \"body\"\n | \"query\"\n | \"params\";\n }\n }\n\n // 解析 schema 文件\n const schemaFilePath = schemaFiles.get(schemaName);\n if (schemaFilePath) {\n try {\n const schemaSourceFile =\n this.project.addSourceFileAtPath(schemaFilePath);\n const fields = this.schemaParser.parseSchemaVariable(\n schemaSourceFile,\n schemaName\n );\n\n if (fields) {\n return { target, fields };\n }\n } catch (error) {\n logger.warn(`解析 schema 文件失败: ${schemaFilePath}`, error);\n }\n } else {\n logger.debug(`未找到 schema 文件映射: ${schemaName}`);\n }\n }\n }\n\n return undefined;\n }\n\n /**\n * 解析多个路由文件\n * @param filePaths 路由文件路径数组\n * @returns 路由信息数组\n */\n public parseRouteFiles(filePaths: string[]): RouteInfo[] {\n const allRoutes: RouteInfo[] = [];\n for (const filePath of filePaths) {\n const routes = this.parseRouteFile(filePath);\n allRoutes.push(...routes);\n }\n return allRoutes;\n }\n\n /**\n * 解析 apidoc 格式的注释标签\n * @param commentText JSDoc 注释文本\n * @returns 解析出的标签信息\n */\n private parseApiDocTags(commentText: string): ApiDocTags {\n const tags: ApiDocTags = { params: [], success: [] };\n\n // 解析 @apiParam 标签\n // 格式: @apiParam {type} [name] description\n const paramRegex = /@apiParam\\s+\\{([^}]+)\\}\\s*(?:\\[([^\\]]+)\\]|(\\S+))\\s*(.*)/g;\n let match;\n while ((match = paramRegex.exec(commentText)) !== null) {\n const [, typeStr, optionalName, requiredName, description] = match;\n const name = optionalName || requiredName;\n const required = !optionalName;\n\n // 解析类型字符串\n const typeInfo = this.parseParamType(typeStr);\n\n tags.params.push({\n name,\n type: typeInfo.type,\n description: description.trim(),\n required,\n enumValues: typeInfo.enumValues,\n });\n }\n\n // 解析 @apiSuccess 标签\n // 格式: @apiSuccess {type} field 或 @apiSuccess {type} parent.field\n const successRegex = /@apiSuccess\\s+\\{([^}]+)\\}\\s+([^\\s]+)\\s*(.*)/g;\n while ((match = successRegex.exec(commentText)) !== null) {\n const [, typeStr, fieldPath, description] = match;\n\n // 解析字段路径 (如 \"data.user.id\")\n const parts = fieldPath.split(\".\");\n const name = parts[parts.length - 1];\n const parent = parts.length > 1 ? parts.slice(0, -1).join(\".\") : undefined;\n\n // 解析类型字符串\n const typeInfo = this.parseParamType(typeStr);\n\n tags.success.push({\n name,\n type: typeInfo.type,\n description: description.trim(),\n parent,\n });\n }\n\n return tags;\n }\n\n /**\n * 解析 apidoc 类型字符串\n * @param typeStr 类型字符串,如 \"string\", \"string=\", \"number[]\", {string=\"a\",\"b\"}\n * @returns 解析后的类型信息\n */\n private parseParamType(typeStr: string): {\n type: FieldValidation[\"type\"];\n array?: boolean;\n enumValues?: string[];\n } {\n typeStr = typeStr.trim();\n\n // 处理枚举类型: {string=\"a\",\"b\"}\n const enumMatch = typeStr.match(/^(\\w+)=(.+)$/);\n if (enumMatch) {\n const baseType = enumMatch[1];\n const enumValues = enumMatch[2]\n .split(\",\")\n .map((v) => v.trim().replace(/^[\"']|[\"']$/g, \"\"));\n\n return {\n type: this.mapTypeName(baseType),\n enumValues,\n };\n }\n\n // 处理数组类型: number[]\n if (typeStr.endsWith(\"[]\")) {\n const baseType = typeStr.slice(0, -2);\n return {\n type: this.mapTypeName(baseType),\n array: true,\n };\n }\n\n // 处理可空类型: string?\n if (typeStr.endsWith(\"?\")) {\n const baseType = typeStr.slice(0, -1);\n return {\n type: this.mapTypeName(baseType),\n };\n }\n\n // 基础类型\n return {\n type: this.mapTypeName(typeStr),\n };\n }\n\n /**\n * 映射类型名称到 FieldValidation 类型\n */\n private mapTypeName(typeName: string): FieldValidation[\"type\"] {\n const typeMap: Record<string, FieldValidation[\"type\"]> = {\n string: \"string\",\n number: \"number\",\n integer: \"number\",\n boolean: \"boolean\",\n array: \"array\",\n object: \"object\",\n file: \"file\",\n date: \"date\",\n };\n\n return typeMap[typeName.toLowerCase()] || \"any\";\n }\n\n /**\n * 从 @apiParam 标签构建请求 Schema\n */\n private buildRequestSchemaFromTags(\n params: ApiDocTags[\"params\"]\n ): RequestSchema {\n const fields: Record<string, FieldValidation> = {};\n\n for (const param of params) {\n fields[param.name] = {\n type: param.type as FieldValidation[\"type\"],\n required: param.required,\n constraints: param.enumValues\n ? { custom: [`可选值: ${param.enumValues.join(\", \")}`] }\n : undefined,\n };\n }\n\n return { target: \"body\", fields };\n }\n\n /**\n * 从 @apiSuccess 标签构建响应 Schema\n */\n private buildResponseSchemaFromTags(\n success: ApiDocTags[\"success\"]\n ): ResponseSchema {\n const fields: Record<string, FieldValidation> = {};\n\n // 先处理所有顶级字段,为嵌套字段做准备\n for (const field of success) {\n if (!field.parent && !fields[field.name]) {\n // 顶级字段,如果是 object 类型,添加 properties 属性\n if (field.type === \"object\") {\n fields[field.name] = {\n type: \"object\",\n required: true,\n properties: {},\n };\n } else {\n fields[field.name] = {\n type: field.type as FieldValidation[\"type\"],\n required: true,\n };\n }\n }\n }\n\n // 处理嵌套字段\n for (const field of success) {\n if (field.parent) {\n // 处理嵌套字段 (如 data.user.id)\n const parts = field.parent.split(\".\");\n let current = fields;\n\n // 创建/获取父级对象链\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n if (!current[part]) {\n // 如果父级字段不存在,创建它\n current[part] = {\n type: \"object\",\n required: true,\n properties: {},\n };\n } else if (!current[part].properties) {\n // 如果父级字段存在但没有 properties(作为顶级字段创建的),添加 properties\n current[part].properties = {};\n }\n // 进入到下一级的 properties\n current = current[part].properties!;\n }\n\n // 添加叶子节点到最内层对象的 properties\n current[field.name] = {\n type: field.type as FieldValidation[\"type\"],\n required: true,\n };\n }\n }\n\n return { fields };\n }\n}\n\n// 导出单例实例\nexport const routeParser = new RouteParser();\n","import {\n Node,\n SyntaxKind,\n SourceFile,\n VariableDeclaration,\n CallExpression,\n ObjectLiteralExpression,\n PropertyAccessExpression,\n Identifier,\n StringLiteral,\n NumericLiteral,\n AsExpression,\n} from \"ts-morph\";\nimport { FieldValidation, FieldConstraints } from \"../types/DocTypes\";\nimport logger from \"./Logger\";\n\n/**\n * Zod Schema AST 解析器\n * 从 Zod schema 变量定义中提取字段结构\n */\nexport class ZodSchemaParser {\n /**\n * 解析 schema 变量,返回字段结构\n */\n public parseSchemaVariable(\n sourceFile: SourceFile,\n schemaName: string\n ): Record<string, FieldValidation> | null {\n try {\n // 1. 查找 schema 变量声明\n const variableDecl = this.findVariableDeclaration(sourceFile, schemaName);\n if (!variableDecl) {\n logger.warn(`未找到 schema 变量: ${schemaName}`);\n return null;\n }\n\n // 2. 获取初始化表达式\n const initializer = variableDecl.getInitializer();\n if (!initializer) {\n logger.warn(`schema 变量 ${schemaName} 没有初始化表达式`);\n return null;\n }\n\n // 3. 解析 z.object({...}) 调用\n return this.parseZodObject(initializer);\n } catch (error) {\n logger.error(`解析 schema 变量失败: ${schemaName}`, error);\n return null;\n }\n }\n\n /**\n * 查找变量声明\n */\n private findVariableDeclaration(\n sourceFile: SourceFile,\n name: string\n ): VariableDeclaration | null {\n for (const decl of sourceFile.getVariableDeclarations()) {\n if (decl.getName() === name) {\n return decl;\n }\n }\n return null;\n }\n\n /**\n * 解析 z.object({...}) 调用\n */\n private parseZodObject(node: Node): Record<string, FieldValidation> | null {\n // 处理 as any 类型断言\n let targetNode = node;\n if (Node.isAsExpression(node)) {\n targetNode = node.getExpression();\n }\n\n // 检查是否是 z.object() 调用\n if (Node.isCallExpression(targetNode)) {\n const expr = targetNode.getExpression();\n if (Node.isPropertyAccessExpression(expr)) {\n const propText = expr.getText();\n if (propText === \"z.object\") {\n const args = targetNode.getArguments();\n if (args.length > 0 && Node.isObjectLiteralExpression(args[0])) {\n return this.parseObjectLiteral(args[0]);\n }\n }\n }\n }\n return null;\n }\n\n /**\n * 解析对象字面量中的字段定义\n */\n private parseObjectLiteral(\n objLit: ObjectLiteralExpression\n ): Record<string, FieldValidation> {\n const fields: Record<string, FieldValidation> = {};\n\n for (const prop of objLit.getProperties()) {\n if (Node.isPropertyAssignment(prop)) {\n const fieldName = prop.getName();\n const initializer = prop.getInitializer();\n if (initializer) {\n fields[fieldName] = this.parseZodField(initializer);\n }\n }\n }\n\n return fields;\n }\n\n /**\n * 解析单个 Zod 字段定义\n */\n private parseZodField(node: Node): FieldValidation {\n const field: FieldValidation = {\n type: \"any\",\n required: true,\n };\n\n // 处理 as any 类型断言\n let targetNode = node;\n if (Node.isAsExpression(node)) {\n targetNode = node.getExpression();\n }\n\n // 收集方法调用链\n const callChain = this.collectCallChain(targetNode);\n\n // 解析类型和约束\n for (const call of callChain) {\n this.applyZodMethod(field, call);\n }\n\n return field;\n }\n\n /**\n * 收集方法调用链\n * 例如: z.string().min(1).optional() -> [{method: \"z.string\", args: []}, {method: \"min\", args: [...]}, {method: \"optional\", args: []}]\n */\n private collectCallChain(\n node: Node\n ): Array<{ method: string; args: Node[] }> {\n const chain: Array<{ method: string; args: Node[] }> = [];\n\n let current: Node | undefined = node;\n while (current && Node.isCallExpression(current)) {\n const expr = current.getExpression();\n const args = current.getArguments();\n\n if (Node.isPropertyAccessExpression(expr)) {\n const methodName = expr.getName();\n chain.unshift({ method: methodName, args: [...args] });\n current = expr.getExpression();\n } else if (Node.isIdentifier(expr)) {\n // z.string, z.number 等基础类型\n chain.unshift({ method: expr.getText(), args: [] });\n break;\n } else if (Node.isPropertyAccessExpression(expr)) {\n // 处理 z.coerce.number() 这种链式\n chain.unshift({\n method: (expr as PropertyAccessExpression).getName(),\n args: [],\n });\n current = (expr as PropertyAccessExpression).getExpression();\n } else {\n break;\n }\n }\n\n return chain;\n }\n\n /**\n * 应用 Zod 方法到字段定义\n */\n private applyZodMethod(\n field: FieldValidation,\n call: { method: string; args: Node[] }\n ): void {\n const { method, args } = call;\n\n switch (method) {\n // 类型定义\n case \"z.string\":\n case \"string\":\n field.type = \"string\";\n break;\n case \"z.number\":\n case \"number\":\n field.type = \"number\";\n break;\n case \"z.boolean\":\n case \"boolean\":\n field.type = \"boolean\";\n break;\n case \"z.array\":\n case \"array\":\n field.type = \"array\";\n // 尝试解析数组元素类型\n if (args.length > 0) {\n field.items = this.parseZodField(args[0]);\n }\n break;\n case \"z.object\":\n case \"object\":\n field.type = \"object\";\n // 尝试解析对象属性\n if (args.length > 0 && Node.isObjectLiteralExpression(args[0])) {\n field.properties = this.parseObjectLiteral(args[0]);\n }\n break;\n case \"z.date\":\n case \"date\":\n field.type = \"date\";\n break;\n case \"z.any\":\n case \"any\":\n field.type = \"any\";\n break;\n case \"z.unknown\":\n case \"unknown\":\n field.type = \"any\";\n break;\n case \"z.undefined\":\n case \"undefined\":\n field.required = false;\n field.optional = true;\n break;\n case \"z.null\":\n case \"null\":\n field.nullable = true;\n break;\n case \"z.void\":\n case \"void\":\n field.type = \"any\";\n break;\n case \"z.nativeEnum\":\n case \"nativeEnum\":\n case \"z.enum\":\n case \"enum\":\n field.type = \"string\";\n break;\n case \"coerce\":\n // z.coerce 是属性访问,不做处理,后续调用会设置类型\n break;\n\n // 可选性\n case \"optional\":\n field.required = false;\n field.optional = true;\n break;\n case \"nullable\":\n field.nullable = true;\n break;\n case \"nullish\":\n field.required = false;\n field.optional = true;\n field.nullable = true;\n break;\n\n // 默认值\n case \"default\":\n if (args.length > 0) {\n field.defaultValue = this.parseArgumentValue(args[0]);\n field.required = false;\n }\n break;\n\n // 约束 - 通用\n case \"min\":\n if (args.length > 0) {\n const minVal = this.parseArgumentValue(args[0]);\n field.constraints = field.constraints || {};\n if (field.type === \"string\") {\n field.constraints.minLength = minVal;\n } else if (field.type === \"number\") {\n field.constraints.min = minVal;\n }\n // 提取错误消息\n if (args.length > 1) {\n const msg = this.parseArgumentValue(args[1]);\n if (typeof msg === \"string\") {\n field.constraints.custom = field.constraints.custom || [];\n field.constraints.custom.push(msg);\n }\n }\n }\n break;\n case \"max\":\n if (args.length > 0) {\n const maxVal = this.parseArgumentValue(args[0]);\n field.constraints = field.constraints || {};\n if (field.type === \"string\") {\n field.constraints.maxLength = maxVal;\n } else if (field.type === \"number\") {\n field.constraints.max = maxVal;\n }\n }\n break;\n case \"length\":\n if (args.length > 0) {\n const lenVal = this.parseArgumentValue(args[0]);\n field.constraints = field.constraints || {};\n field.constraints.minLength = lenVal;\n field.constraints.maxLength = lenVal;\n }\n break;\n\n // 约束 - 字符串\n case \"email\":\n field.constraints = field.constraints || {};\n field.constraints.email = true;\n break;\n case \"url\":\n field.constraints = field.constraints || {};\n field.constraints.url = true;\n break;\n case \"uuid\":\n field.constraints = field.constraints || {};\n field.constraints.uuid = true;\n break;\n case \"regex\":\n case \"pattern\":\n if (args.length > 0) {\n field.constraints = field.constraints || {};\n field.constraints.pattern = args[0].getText();\n }\n break;\n case \"startsWith\":\n case \"endsWith\":\n case \"includes\":\n case \"trim\":\n case \"toLowerCase\":\n case \"toUpperCase\":\n // 字符串转换方法,暂不处理\n break;\n\n // 约束 - 数字\n case \"int\":\n field.constraints = field.constraints || {};\n field.constraints.int = true;\n break;\n case \"positive\":\n field.constraints = field.constraints || {};\n field.constraints.positive = true;\n break;\n case \"nonnegative\":\n field.constraints = field.constraints || {};\n field.constraints.nonnegative = true;\n break;\n case \"negative\":\n field.constraints = field.constraints || {};\n field.constraints.max = -1;\n break;\n case \"nonpositive\":\n field.constraints = field.constraints || {};\n field.constraints.max = 0;\n break;\n case \"finite\":\n case \"safe\":\n // 数字安全检查,暂不处理\n break;\n\n // 约束 - 数组\n case \"nonempty\":\n field.constraints = field.constraints || {};\n field.constraints.minLength = 1;\n break;\n\n // 其他方法\n case \"refine\":\n case \"superRefine\":\n case \"transform\":\n case \"pipe\":\n case \" preprocess\":\n case \"omit\":\n case \"pick\":\n case \"partial\":\n case \"required\":\n case \"strict\":\n case \"passthrough\":\n case \"extend\":\n case \"merge\":\n case \"keyof\":\n // 高级方法,暂不处理\n break;\n }\n }\n\n /**\n * 解析参数值\n */\n private parseArgumentValue(node: Node): any {\n if (Node.isStringLiteral(node)) {\n return node.getLiteralValue();\n } else if (Node.isNumericLiteral(node)) {\n return node.getLiteralValue();\n } else if (Node.isTrueLiteral(node)) {\n return true;\n } else if (Node.isFalseLiteral(node)) {\n return false;\n } else if (Node.isIdentifier(node)) {\n return node.getText();\n } else if (Node.isObjectLiteralExpression(node)) {\n // 返回对象字面量的文本表示\n return node.getText();\n } else if (Node.isArrayLiteralExpression(node)) {\n // 返回数组字面量的文本表示\n return node.getText();\n }\n return node.getText();\n }\n}\n\n// 导出单例实例\nexport const zodSchemaParser = new ZodSchemaParser();\n","import {\n Node,\n SyntaxKind,\n SourceFile,\n InterfaceDeclaration,\n TypeAliasDeclaration,\n PropertySignature,\n TypeReferenceNode,\n ArrayTypeNode,\n UnionTypeNode,\n IntersectionTypeNode,\n LiteralTypeNode,\n Identifier,\n} from \"ts-morph\";\nimport { FieldValidation, ResponseSchema } from \"../types/DocTypes\";\nimport logger from \"./Logger\";\n\n/**\n * 类型引用解析结果\n */\ninterface TypeRef {\n typeName: string;\n typeArgs: string[]; // 泛型参数\n}\n\n/**\n * TypeScript 类型解析器\n * 从 interface/type 定义中提取字段结构\n */\nexport class TSTypeParser {\n /**\n * 解析类型引用字符串\n * 例如: \"ApiResponse<User[]>\" -> { typeName: \"ApiResponse\", typeArgs: [\"User[]\"] }\n */\n public parseTypeRef(typeString: string): TypeRef | null {\n // 移除花括号内的内容(如果有)\n typeString = typeString.trim();\n\n // 匹配泛型: TypeName<Arg1, Arg2>\n const genericMatch = typeString.match(/^(\\w+)<(.+)>$/);\n if (genericMatch) {\n const typeName = genericMatch[1];\n const argsStr = genericMatch[2];\n // 简单分割泛型参数(不支持嵌套泛型)\n const typeArgs = argsStr.split(\",\").map((s) => s.trim());\n return { typeName, typeArgs };\n }\n\n // 简单类型引用\n if (/^\\w+$/.test(typeString)) {\n return { typeName: typeString, typeArgs: [] };\n }\n\n // 数组类型: User[]\n const arrayMatch = typeString.match(/^(\\w+)\\[\\]$/);\n if (arrayMatch) {\n return { typeName: \"Array\", typeArgs: [arrayMatch[1]] };\n }\n\n return null;\n }\n\n /**\n * 解析响应类型\n * @param sourceFile 源文件\n * @param typeString 类型字符串如 \"ApiResponse<User[]>\"\n * @param imports 导入映射 (类型名 -> 文件路径)\n */\n public parseResponseType(\n sourceFile: SourceFile,\n typeString: string,\n imports: Map<string, string>\n ): ResponseSchema | null {\n const typeRef = this.parseTypeRef(typeString);\n if (!typeRef) {\n logger.debug(`无法解析类型引用: ${typeString}`);\n return null;\n }\n\n // 内置类型处理: ApiResponse<T>\n if (typeRef.typeName === \"ApiResponse\") {\n return this.parseApiResponse(sourceFile, typeRef.typeArgs, imports);\n }\n\n // 查找类型定义\n const typeDecl = this.findTypeDeclaration(sourceFile, typeRef.typeName, imports);\n if (!typeDecl) {\n logger.debug(`未找到类型定义: ${typeRef.typeName}`);\n return null;\n }\n\n // 解析字段\n const fields = this.extractFieldsFromType(typeDecl, typeRef.typeArgs, imports);\n\n return { fields };\n }\n\n /**\n * 解析 ApiResponse<T> 类型\n * ApiResponse 是标准的 API 响应包装器,包含 code, data, msg 字段\n */\n private parseApiResponse(\n sourceFile: SourceFile,\n typeArgs: string[],\n imports: Map<string, string>\n ): ResponseSchema {\n const fields: Record<string, FieldValidation> = {\n code: { type: \"number\", required: true },\n msg: { type: \"string\", required: true },\n };\n\n // 解析 data 字段的类型\n if (typeArgs.length > 0) {\n const dataType = typeArgs[0];\n const dataField = this.parseDataType(sourceFile, dataType, imports);\n fields.data = dataField;\n } else {\n fields.data = { type: \"any\", required: true };\n }\n\n return { fields };\n }\n\n /**\n * 解析 data 字段的类型\n */\n private parseDataType(\n sourceFile: SourceFile,\n typeString: string,\n imports: Map<string, string>\n ): FieldValidation {\n // 基础类型\n if (typeString === \"string\") {\n return { type: \"string\", required: true };\n } else if (typeString === \"number\") {\n return { type: \"number\", required: true };\n } else if (typeString === \"boolean\") {\n return { type: \"boolean\", required: true };\n } else if (typeString === \"any\") {\n return { type: \"any\", required: true };\n }\n\n // 数组类型: User[]\n const arrayMatch = typeString.match(/^(\\w+)\\[\\]$/);\n if (arrayMatch) {\n const elementType = arrayMatch[1];\n const elementField = this.parseDataType(sourceFile, elementType, imports);\n return {\n type: \"array\",\n required: true,\n items: elementField,\n };\n }\n\n // 类型引用: LoginResult\n const typeDecl = this.findTypeDeclaration(sourceFile, typeString, imports);\n if (typeDecl) {\n const fields = this.extractFieldsFromType(typeDecl, [], imports);\n return {\n type: \"object\",\n required: true,\n properties: fields,\n };\n }\n\n // 默认返回 any\n return { type: \"any\", required: true };\n }\n\n /**\n * 查找类型声明\n */\n private findTypeDeclaration(\n sourceFile: SourceFile,\n typeName: string,\n imports: Map<string, string>\n ): InterfaceDeclaration | TypeAliasDeclaration | null {\n // 先在当前文件中查找\n const interfaceDecl = sourceFile.getInterface(typeName);\n if (interfaceDecl) return interfaceDecl;\n\n const typeAlias = sourceFile.getTypeAlias(typeName);\n if (typeAlias) return typeAlias;\n\n // 在导入的文件中查找\n const importPath = imports.get(typeName);\n if (importPath) {\n try {\n const importedFile = sourceFile.getProject().addSourceFileAtPath(importPath);\n\n const importedInterface = importedFile.getInterface(typeName);\n if (importedInterface) return importedInterface;\n\n const importedTypeAlias = importedFile.getTypeAlias(typeName);\n if (importedTypeAlias) return importedTypeAlias;\n } catch (error) {\n logger.warn(`无法加载导入文件: ${importPath}`);\n }\n }\n\n return null;\n }\n\n /**\n * 从类型声明中提取字段\n */\n private extractFieldsFromType(\n typeDecl: InterfaceDeclaration | TypeAliasDeclaration,\n typeArgs: string[],\n imports: Map<string, string>\n ): Record<string, FieldValidation> {\n const fields: Record<string, FieldValidation> = {};\n\n // 获取类型节点\n let typeNode: Node | undefined;\n\n if (Node.isInterfaceDeclaration(typeDecl)) {\n // 接口: 直接遍历属性\n for (const prop of typeDecl.getProperties()) {\n const fieldName = prop.getName();\n const fieldType = prop.getType();\n fields[fieldName] = this.parsePropertyType(prop, typeArgs, imports);\n }\n return fields;\n } else if (Node.isTypeAliasDeclaration(typeDecl)) {\n typeNode = typeDecl.getTypeNode();\n }\n\n if (!typeNode) return fields;\n\n // 处理类型别名 - 使用 getKind() 检查节点类型\n if (typeNode.getKind() === SyntaxKind.TypeReference) {\n // 如果是类型引用,可能需要展开\n return this.extractFieldsFromTypeReference(typeNode as TypeReferenceNode, typeArgs, imports);\n } else if (typeNode.getKind() === SyntaxKind.IntersectionType) {\n // 交叉类型: 合并所有类型的字段\n for (const child of (typeNode as IntersectionTypeNode).getTypeNodes()) {\n const childFields = this.extractFieldsFromTypeNode(child, typeArgs, imports);\n Object.assign(fields, childFields);\n }\n } else if (typeNode.getKind() === SyntaxKind.UnionType) {\n // 联合类型: 取第一个类型的字段(简化处理)\n const firstType = (typeNode as UnionTypeNode).getTypeNodes()[0];\n if (firstType) {\n return this.extractFieldsFromTypeNode(firstType, typeArgs, imports);\n }\n } else {\n return this.extractFieldsFromTypeNode(typeNode, typeArgs, imports);\n }\n\n return fields;\n }\n\n /**\n * 从类型节点提取字段\n */\n private extractFieldsFromTypeNode(\n typeNode: Node,\n typeArgs: string[],\n imports: Map<string, string>\n ): Record<string, FieldValidation> {\n const fields: Record<string, FieldValidation> = {};\n\n if (typeNode.getKind() === SyntaxKind.TypeReference) {\n return this.extractFieldsFromTypeReference(typeNode as TypeReferenceNode, typeArgs, imports);\n } else if (typeNode.getKind() === SyntaxKind.IntersectionType) {\n for (const child of (typeNode as IntersectionTypeNode).getTypeNodes()) {\n const childFields = this.extractFieldsFromTypeNode(child, typeArgs, imports);\n Object.assign(fields, childFields);\n }\n }\n\n return fields;\n }\n\n /**\n * 从类型引用提取字段\n */\n private extractFieldsFromTypeReference(\n typeRefNode: TypeReferenceNode,\n typeArgs: string[],\n imports: Map<string, string>\n ): Record<string, FieldValidation> {\n const fields: Record<string, FieldValidation> = {};\n const typeName = typeRefNode.getTypeName().getText();\n\n // 特殊处理泛型参数\n if (typeName === \"Array\" || typeName === \"ReadonlyArray\") {\n // 数组类型,返回 items 信息\n const typeArgsNodes = typeRefNode.getTypeArguments();\n if (typeArgsNodes.length > 0) {\n const elementType = typeArgsNodes[0];\n fields[\"[]\"] = {\n type: \"array\",\n required: true,\n items: this.parseTypeNodeToFieldValidation(elementType, typeArgs, imports),\n };\n }\n return fields;\n }\n\n // 处理 Promise<T> - 提取 T\n if (typeName === \"Promise\") {\n const typeArgsNodes = typeRefNode.getTypeArguments();\n if (typeArgsNodes.length > 0) {\n return this.extractFieldsFromTypeNode(typeArgsNodes[0], typeArgs, imports);\n }\n }\n\n // 处理泛型参数 T, K 等\n if (typeArgs.includes(typeName) && typeArgs.length > 0) {\n // 使用实际类型参数\n const actualType = typeArgs[0]; // 简化处理,取第一个\n // 这里可以递归解析实际类型\n }\n\n // 解析类型定义\n const sourceFile = typeRefNode.getSourceFile();\n const typeDecl = this.findTypeDeclarationInFile(sourceFile, typeName);\n\n if (typeDecl) {\n return this.extractFieldsFromType(typeDecl, typeArgs, imports);\n }\n\n return fields;\n }\n\n /**\n * 在文件中查找类型声明\n */\n private findTypeDeclarationInFile(\n sourceFile: SourceFile,\n typeName: string\n ): InterfaceDeclaration | TypeAliasDeclaration | null {\n const interfaceDecl = sourceFile.getInterface(typeName);\n if (interfaceDecl) return interfaceDecl;\n\n const typeAlias = sourceFile.getTypeAlias(typeName);\n if (typeAlias) return typeAlias;\n\n return null;\n }\n\n /**\n * 解析属性类型\n */\n private parsePropertyType(\n prop: PropertySignature,\n typeArgs: string[],\n imports: Map<string, string>\n ): FieldValidation {\n const type = prop.getType();\n const isOptional = prop.hasQuestionToken();\n\n // 获取类型文本\n const typeText = type.getText();\n\n // 基础类型判断\n if (type.isString()) {\n return { type: \"string\", required: !isOptional };\n } else if (type.isNumber()) {\n return { type: \"number\", required: !isOptional };\n } else if (type.isBoolean()) {\n return { type: \"boolean\", required: !isOptional };\n } else if (type.isArray()) {\n const elementType = type.getArrayElementType();\n let items: FieldValidation | undefined;\n if (elementType) {\n items = {\n type: this.mapTypeToString(elementType),\n required: !elementType.isUndefined() && !elementType.isNull(),\n };\n }\n return { type: \"array\", required: !isOptional, items };\n } else if (type.isObject()) {\n // 尝试获取对象属性\n const properties = type.getProperties();\n if (properties.length > 0) {\n const props: Record<string, FieldValidation> = {};\n for (const prop of properties) {\n const propName = prop.getName();\n const propType = prop.getTypeAtLocation(prop.getValueDeclaration() || prop.getDeclarations()[0]);\n props[propName] = {\n type: this.mapTypeToString(propType),\n required: !prop.isOptional(),\n };\n }\n return { type: \"object\", required: !isOptional, properties: props };\n }\n return { type: \"object\", required: !isOptional };\n } else if (type.isNull()) {\n return { type: \"any\", required: false, nullable: true };\n } else if (type.isUndefined()) {\n return { type: \"any\", required: false, optional: true };\n } else if (type.isAny()) {\n return { type: \"any\", required: !isOptional };\n }\n\n // 其他类型,使用类型文本\n return { type: \"any\", required: !isOptional };\n }\n\n /**\n * 将类型映射为字符串\n */\n private mapTypeToString(type: any): FieldValidation[\"type\"] {\n if (type.isString()) return \"string\";\n if (type.isNumber()) return \"number\";\n if (type.isBoolean()) return \"boolean\";\n if (type.isArray()) return \"array\";\n if (type.isObject()) return \"object\";\n if (type.isDate()) return \"date\";\n return \"any\";\n }\n\n /**\n * 从类型节点创建 FieldValidation\n */\n private parseTypeNodeToFieldValidation(\n typeNode: Node,\n typeArgs: string[],\n imports: Map<string, string>\n ): FieldValidation {\n if (Node.isStringKeyword(typeNode)) {\n return { type: \"string\", required: true };\n } else if (Node.isNumberKeyword(typeNode)) {\n return { type: \"number\", required: true };\n } else if (Node.isBooleanKeyword(typeNode)) {\n return { type: \"boolean\", required: true };\n } else if (Node.isArrayTypeNode(typeNode)) {\n const elementType = (typeNode as ArrayTypeNode).getElementTypeNode();\n return {\n type: \"array\",\n required: true,\n items: this.parseTypeNodeToFieldValidation(elementType, typeArgs, imports),\n };\n } else if (typeNode.getKind() === SyntaxKind.TypeReference) {\n const refNode = typeNode as TypeReferenceNode;\n const typeName = refNode.getTypeName().getText();\n const sourceFile = refNode.getSourceFile();\n const typeDecl = this.findTypeDeclarationInFile(sourceFile, typeName);\n\n if (typeDecl) {\n const fields = this.extractFieldsFromType(typeDecl, typeArgs, imports);\n return { type: \"object\", required: true, properties: fields };\n }\n\n return { type: \"any\", required: true };\n }\n\n return { type: \"any\", required: true };\n }\n}\n\n// 导出单例实例\nexport const tsTypeParser = new TSTypeParser();\n","import Database from \"better-sqlite3\";\nimport { Database as DatabaseType } from \"better-sqlite3\";\nimport * as path from \"path\";\nimport * as fs from \"fs\";\nimport { RouteInfo, ModuleItem, DocDatabaseConfig } from \"../types/DocTypes\";\nimport logger from \"./Logger\";\n\n/**\n * 文档管理器\n * 管理文档数据,与独立的 SQLite 数据库交互\n */\nexport class DocManager {\n private db: DatabaseType | null = null;\n private config: DocDatabaseConfig;\n\n constructor(config: DocDatabaseConfig) {\n this.config = config;\n this.init();\n }\n\n /**\n * 初始化数据库\n */\n public init(): void {\n try {\n // 确保数据库目录存在\n const dbDir = path.dirname(this.config.path);\n if (!fs.existsSync(dbDir)) {\n fs.mkdirSync(dbDir, { recursive: true });\n }\n\n // 连接数据库\n this.db = new Database(this.config.path);\n\n // 创建表结构\n this.createTables();\n } catch (error) {\n logger.error(\"文档数据库初始化失败:\", error);\n this.db = null;\n }\n }\n\n /**\n * 创建表结构\n */\n private createTables(): void {\n if (!this.db) return;\n\n // 创建 doc_routes 表\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS doc_routes (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n module TEXT NOT NULL,\n method TEXT NOT NULL,\n path TEXT NOT NULL,\n full_path TEXT NOT NULL,\n summary TEXT,\n description TEXT,\n request_schema TEXT,\n response_schema TEXT,\n middlewares TEXT,\n file_path TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n UNIQUE(module, method, path)\n );\n `);\n\n // 创建索引\n this.db.exec(`\n CREATE INDEX IF NOT EXISTS idx_doc_routes_module ON doc_routes(module);\n CREATE INDEX IF NOT EXISTS idx_doc_routes_full_path ON doc_routes(full_path);\n `);\n }\n\n /**\n * 保存路由信息\n * @param routeInfo 路由信息\n * @param apiPrefix API 前缀\n * @param moduleName 模块名称\n */\n public saveRoute(routeInfo: RouteInfo, apiPrefix: string = \"/api\", moduleName: string): void {\n if (!this.db) return;\n\n try {\n // 计算完整路径\n const fullPath = `${apiPrefix}/${moduleName}${routeInfo.path}`.replace(/\\/+/g, \"/\");\n\n // 准备数据\n const now = Date.now();\n const data = {\n module: moduleName,\n method: routeInfo.method,\n path: routeInfo.path,\n full_path: fullPath,\n summary: routeInfo.summary,\n description: routeInfo.description,\n request_schema: routeInfo.requestSchema ? JSON.stringify(routeInfo.requestSchema) : null,\n response_schema: routeInfo.responseSchema ? JSON.stringify(routeInfo.responseSchema) : null,\n middlewares: routeInfo.middlewares ? JSON.stringify(routeInfo.middlewares) : null,\n file_path: routeInfo.filePath,\n created_at: now,\n updated_at: now,\n };\n\n // 插入或更新数据\n const stmt = this.db.prepare(`\n INSERT INTO doc_routes (\n module, method, path, full_path, summary, description,\n request_schema, response_schema, middlewares, file_path, created_at, updated_at\n ) VALUES (\n @module, @method, @path, @full_path, @summary, @description,\n @request_schema, @response_schema, @middlewares, @file_path, @created_at, @updated_at\n ) ON CONFLICT(module, method, path) DO UPDATE SET\n full_path = @full_path,\n summary = @summary,\n description = @description,\n request_schema = @request_schema,\n response_schema = @response_schema,\n middlewares = @middlewares,\n file_path = @file_path,\n updated_at = @updated_at\n `);\n\n stmt.run(data);\n } catch (error) {\n logger.error(\"保存路由信息失败:\", error);\n }\n }\n\n /**\n * 获取模块列表\n * @returns 模块列表\n */\n public getModules(): ModuleItem[] {\n if (!this.db) return [];\n\n try {\n const stmt = this.db.prepare(`\n SELECT module, COUNT(*) as count \n FROM doc_routes \n GROUP BY module \n ORDER BY module\n `);\n\n return stmt.all() as ModuleItem[];\n } catch (error) {\n logger.error(\"获取模块列表失败:\", error);\n return [];\n }\n }\n\n /**\n * 获取路由列表\n * @param module 模块名称(可选)\n * @returns 路由列表\n */\n public getRoutes(module?: string): RouteInfo[] {\n if (!this.db) return [];\n\n try {\n let query = `\n SELECT id, module, method, path, full_path, summary, description,\n request_schema, response_schema, middlewares, file_path, created_at, updated_at\n FROM doc_routes\n `;\n\n const params: any = {};\n\n if (module) {\n query += \" WHERE module = @module\";\n params.module = module;\n }\n\n query += \" ORDER BY module, method, path\";\n\n const stmt = this.db.prepare(query);\n const rows = stmt.all(params) as any[];\n\n // 转换数据格式\n return rows.map((row) => ({\n id: row.id,\n module: row.module,\n method: row.method,\n path: row.path,\n fullPath: row.full_path,\n summary: row.summary,\n description: row.description,\n requestSchema: row.request_schema ? JSON.parse(row.request_schema) : undefined,\n responseSchema: row.response_schema ? JSON.parse(row.response_schema) : undefined,\n middlewares: row.middlewares ? JSON.parse(row.middlewares) : undefined,\n filePath: row.file_path,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n }));\n } catch (error) {\n logger.error(\"获取路由列表失败:\", error);\n return [];\n }\n }\n\n /**\n * 获取路由详情\n * @param id 路由 ID\n * @returns 路由详情\n */\n public getRouteById(id: number): RouteInfo | null {\n if (!this.db) return null;\n\n try {\n const stmt = this.db.prepare(`\n SELECT id, module, method, path, full_path, summary, description,\n request_schema, response_schema, middlewares, file_path, created_at, updated_at\n FROM doc_routes\n WHERE id = @id\n `);\n\n const row = stmt.get({ id }) as any;\n\n if (!row) return null;\n\n // 转换数据格式\n return {\n id: row.id,\n module: row.module,\n method: row.method,\n path: row.path,\n fullPath: row.full_path,\n summary: row.summary,\n description: row.description,\n requestSchema: row.request_schema ? JSON.parse(row.request_schema) : undefined,\n responseSchema: row.response_schema ? JSON.parse(row.response_schema) : undefined,\n middlewares: row.middlewares ? JSON.parse(row.middlewares) : undefined,\n filePath: row.file_path,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n } catch (error) {\n logger.error(\"获取路由详情失败:\", error);\n return null;\n }\n }\n\n /**\n * 清空所有路由数据\n */\n public clearAllRoutes(): void {\n if (!this.db) return;\n\n try {\n this.db.exec(\"DELETE FROM doc_routes\");\n } catch (error) {\n logger.error(\"清空路由数据失败:\", error);\n }\n }\n\n /**\n * 关闭数据库连接\n */\n public close(): void {\n if (this.db) {\n this.db.close();\n this.db = null;\n logger.info(\"文档数据库连接已关闭\");\n }\n }\n}\n\n// 导出单例实例\nexport let docManager: DocManager;\n\n/**\n * 初始化文档管理器\n * @param config 配置\n */\nexport function initDocManager(config: DocDatabaseConfig): DocManager {\n docManager = new DocManager(config);\n return docManager;\n}\n","import { Express, Router } from \"express\";\nimport { ScanResult } from \"../types/Index\";\nimport logger from \"./Logger\";\nimport { routeParser } from \"./RouteParser\";\nimport { docManager } from \"./DocManager\";\nimport path from \"path\";\n\n/**\n * 递归提取 Router 中注册的所有路由路径\n */\nfunction getRoutes(router: any, prefix: string = \"\"): { path: string; method: string }[] {\n const routes: { path: string; method: string }[] = [];\n\n if (router && router.stack) {\n router.stack.forEach((layer: any) => {\n if (layer.route) {\n // 处理直接定义的路由 (如 router.get('/hello'))\n const path = (prefix + layer.route.path).replace(/\\/+/g, \"/\");\n const methods = Object.keys(layer.route.methods).map((m) => m.toUpperCase());\n methods.forEach((method) => {\n routes.push({ path, method });\n });\n } else if (layer.name === \"router\" && layer.handle && layer.handle.stack) {\n // 处理嵌套的 Router (如 router.use('/sub', subRouter))\n const newPrefix = (prefix + (layer.regexp.source.replace(\"^\\\\/\", \"\").replace(\"\\\\/?(?=\\\\/|$)\", \"\") || \"\")).replace(/\\/+/g, \"/\");\n routes.push(...getRoutes(layer.handle, newPrefix));\n }\n });\n }\n\n return routes;\n}\n\nexport async function registerRoute(app: Express, config: ScanResult, apiPrefix: string = \"/api\"): Promise<void> {\n const { fileName, defaultExport: handler, filePath, cacheHit } = config;\n\n try {\n const lowercaseModuleName = fileName.toLowerCase();\n\n // 缓存未命中时才解析和保存文档\n if (!cacheHit) {\n const routes = routeParser.parseRouteFile(filePath);\n routes.forEach((route) => {\n docManager.saveRoute(route, apiPrefix, lowercaseModuleName);\n });\n }\n\n // ===== 支持从子目录生成嵌套 URL =====\n // 例如:d:/packages/auth/routes/auth/user.route.ts → /api/auth/user\n\n // 正确找到 routes 目录位置\n const filePathParts = filePath.split(path.sep);\n const routesIndex = filePathParts.lastIndexOf(\"routes\");\n if (routesIndex === -1) {\n throw new Error(`路由文件必须在 routes 目录下: ${filePath}`);\n }\n const routesDir = filePathParts.slice(0, routesIndex + 1).join(path.sep);\n\n // 获取相对于 routes 目录的路径\n const fileDir = path.dirname(filePath);\n const relativePath = path.relative(routesDir, fileDir);\n\n // 构建路径部分\n let pathParts: string[] = [];\n if (relativePath && relativePath !== \".\") {\n pathParts = relativePath.split(path.sep).map(p => p.toLowerCase());\n }\n // 添加文件名作为最后一部分\n pathParts.push(lowercaseModuleName);\n\n const baseRoutePath = `${apiPrefix}/${pathParts.join(\"/\")}`.replace(/\\/+/g, \"/\");\n // ===== 嵌套 URL 支持结束 =====\n\n app.use(baseRoutePath, handler);\n\n // 提取并打印所有子路由\n const subRoutes = getRoutes(handler);\n if (subRoutes.length > 0) {\n logger.startup(\"路由\", `${baseRoutePath} (${subRoutes.length} 个端点)`);\n subRoutes.forEach((route) => {\n const fullPath = `${baseRoutePath}${route.path}`.replace(/\\/+/g, \"/\");\n // Method 填充到 6 字符宽度,保证 path 对齐\n const method = route.method.padEnd(6, \" \");\n logger.startup(` └─ ${method} ${fullPath}`);\n });\n } else {\n logger.startup(\"路由\", `${baseRoutePath} (无端点)`);\n }\n } catch (error) {\n logger.error(`注册路由失败[${fileName.toLowerCase()}]: ${error}`);\n }\n}\n","import { AppState } from \"../core/state\";\nimport { ScanResult } from \"../types/Index\";\nimport { registerMiddleware } from \"./MiddlewareRegistry\";\nimport { registerRoute } from \"./RouteRegistry\";\nimport logger from \"./Logger\";\n\n/**\n * 封装细节:遍历扫描结果并注册所有组件(中间件和路由)\n */\nexport async function registerComponents(state: AppState, scannedResults: ScanResult[]) {\n // 1. 先注册所有中间件\n for (const item of scannedResults) {\n if (item.type === \"middleware\") {\n registerMiddleware(state.express, item);\n }\n }\n\n // 2. 再注册所有路由\n for (const item of scannedResults) {\n if (item.type === \"route\") {\n registerRoute(state.express, item, state.options.apiPrefix);\n }\n }\n\n // 3. 所有组件注册完成后,触发路由资源同步(如果有)\n const syncAppRoutes = state.express.get(\"syncAppRoutes\");\n if (syncAppRoutes && typeof syncAppRoutes === \"function\") {\n try {\n await syncAppRoutes();\n } catch (error) {\n logger.error(\"[ComponentRegistry] 路由资源同步失败:\", error);\n }\n }\n}\n","import { Request, Response, NextFunction, Express } from \"express\";\nimport { ZodError } from \"zod\";\nimport logger from \"./Logger\";\n\n/**\n * 检测是否为 SQL 相关错误(表/字段不存在)\n */\nfunction isSQLError(err: any): boolean {\n if (!err) return false;\n const msg = err.message || err.toString() || \"\";\n return /no such table|table.*does not exist|column.*does not exist|database schema has changed/i.test(msg);\n}\n\n/**\n * 封装细节:初始化错误处理和 404 中间件\n */\nexport function setupErrorHandlers(app: Express, logging?: boolean) {\n // 404 处理\n app.use((req: Request, res: Response) => {\n res.status(404).json({\n code: 404,\n data: null,\n msg: \"资源不存在\",\n error: \"Not Found\",\n fields: {},\n });\n });\n\n // 错误处理\n app.use((err: any, req: Request, res: Response, next: NextFunction) => {\n // 处理业务错误(带有 isAppError 标记或 4xx 状态码)\n if (err.isAppError || (err.statusCode && err.statusCode >= 400 && err.statusCode < 500)) {\n return res.status(err.statusCode).json({\n code: err.statusCode,\n data: null,\n msg: err.message,\n error: \"BusinessError\",\n fields: {},\n });\n }\n\n // 处理 Zod 校验错误\n if (err instanceof ZodError) {\n const fields: Record<string, string> = {};\n err.errors.forEach((e) => {\n const path = e.path.join(\".\");\n fields[path] = e.message;\n });\n\n return res.status(400).json({\n code: 400,\n data: null,\n msg: \"参数校验失败\",\n error: \"ZodValidationError\",\n fields,\n });\n }\n\n // 处理 SQL 错误(给出友好提示)\n if (isSQLError(err)) {\n logger.error(\"\");\n logger.error(\"❌ 数据库结构可能已变化,请运行以下命令同步:\");\n logger.error(\"\");\n logger.error(\" npm run db:migrate\");\n logger.error(\"\");\n }\n\n // 处理普通错误\n const statusCode = err.status || err.statusCode || 500;\n if (!isSQLError(err)) {\n logger.error(\"系统错误:\", err);\n }\n\n res.status(statusCode).json({\n code: statusCode,\n data: null,\n msg: err.message || \"服务器内部错误\",\n error: logging ? err.stack : \"InternalServerError\",\n fields: {},\n });\n });\n}\n","import { Express } from \"express\";\nimport logger from \"./Logger\";\n\n/**\n * 启动 HTTP 服务\n * @param app Express 实例\n * @param port 监听端口\n * @returns Promise<void>\n * @throws 如果服务器启动失败\n */\nexport async function startServer(app: Express, port: number): Promise<void> {\n if (!app) {\n throw new Error(\"Express 实例不能为空\");\n }\n\n if (!port || typeof port !== \"number\" || port <= 0 || port > 65535) {\n throw new Error(`无效的端口号: ${port}`);\n }\n\n return new Promise<void>((resolve, reject) => {\n try {\n const server = app.listen(port, () => {\n resolve();\n });\n\n // 处理服务器错误\n server.on(\"error\", (error) => {\n logger.error(\"服务器启动失败:\", error);\n reject(new Error(`服务器启动失败:${error instanceof Error ? error.message : String(error)}`));\n });\n\n // 处理服务器关闭\n server.on(\"close\", () => {\n logger.info(\"服务器已关闭\");\n });\n } catch (error) {\n logger.error(\"服务器启动异常:\", error);\n reject(new Error(`服务器启动异常:${error instanceof Error ? error.message : String(error)}`));\n }\n });\n}\n","import { Router, Request, Response } from \"express\";\nimport { docManager } from \"../utils/DocManager\";\nimport { validate } from \"../utils/Validate\";\nimport { routeIdParamsSchema } from \"../zod/Doc.schema\";\nimport { ApiResponse, ModuleItem, RouteInfo } from \"../types/DocTypes\";\n\nconst router = Router();\n\n/**\n * 获取模块列表\n * @apiSuccess {number} code 状态码\n * @apiSuccess {string} msg 消息\n * @apiSuccess {Object[]} data 模块列表\n */\nrouter.get(\"/modules\", (req: Request, res: Response) => {\n try {\n const modules = docManager.getModules();\n const response: ApiResponse = {\n code: 200,\n data: modules,\n msg: \"success\",\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n code: 500,\n data: null,\n msg: \"获取模块列表失败\",\n };\n res.json(response);\n }\n});\n\n/**\n * 获取路由列表\n * @apiParam {string} [module] 模块名称(可选)\n * @apiSuccess {number} code 状态码\n * @apiSuccess {string} msg 消息\n * @apiSuccess {Object[]} data 路由列表\n */\nrouter.get(\"/routes\", (req: Request, res: Response) => {\n try {\n const module = req.query.module as string;\n const routes = docManager.getRoutes(module);\n const response: ApiResponse = {\n code: 200,\n data: routes,\n msg: \"success\",\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n code: 500,\n data: null,\n msg: \"获取路由列表失败\",\n };\n res.json(response);\n }\n});\n\n/**\n * 获取路由详情\n * @apiParam {string} id 路由ID(路径参数,必填)\n * @apiSuccess {number} code 状态码\n * @apiSuccess {string} msg 消息\n * @apiSuccess {Object} data 路由详情\n */\nrouter.get(\"/routes/:id\", validate(routeIdParamsSchema as any, \"params\"), (req: Request, res: Response) => {\n try {\n const { id } = req.params as any;\n const route = docManager.getRouteById(id);\n if (!route) {\n const response: ApiResponse = {\n code: 404,\n data: null,\n msg: \"路由不存在\",\n };\n return res.json(response);\n }\n\n const response: ApiResponse = {\n code: 200,\n data: route,\n msg: \"success\",\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n code: 500,\n data: null,\n msg: \"获取路由详情失败\",\n };\n res.json(response);\n }\n});\n\n/**\n * 手动同步文档数据\n * @apiSuccess {number} code 状态码\n * @apiSuccess {string} msg 消息\n * @apiSuccess {boolean} data 是否同步成功\n */\nrouter.post(\"/sync\", (req: Request, res: Response) => {\n try {\n // 这里可以实现手动同步逻辑\n // 例如:重新扫描所有路由文件并更新文档数据\n const response: ApiResponse = {\n code: 200,\n data: true,\n msg: \"同步成功\",\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n code: 500,\n data: null,\n msg: \"同步失败\",\n };\n res.json(response);\n }\n});\n\nexport default router;\n","import { Request, Response, NextFunction } from \"express\";\nimport { AnyZodObject, ZodError, ZodSchema } from \"zod\";\n\n/**\n * 验证位置类型\n */\nexport type ValidationTarget = \"body\" | \"query\" | \"params\";\n\n/**\n * Zod 验证中间件\n * @param schema Zod Schema\n * @param target 验证目标 (默认 body)\n */\nexport const validate = (schema: ZodSchema, target: ValidationTarget = \"body\") => {\n return async (req: Request, res: Response, next: NextFunction) => {\n try {\n await schema.parseAsync(req[target]);\n // 注意: req.query 和 req.params 是只读的,无法赋值\n // 只有 req.body 可以赋值,但通常 parse 验证后类型转换已生效\n next();\n } catch (error) {\n next(error);\n }\n };\n};\n","import { z } from \"zod\";\n\n// 路由ID参数\nexport const routeIdParamsSchema = z.object({\n id: z.coerce.number().int().positive(\"无效的路由ID\"),\n});\n\n// 类型导出\nexport type RouteIdParams = z.infer<typeof routeIdParamsSchema>;\n","import { Express } from \"express\";\nimport { createState } from \"./state\";\nimport { setBaseDir, scan, addScanPath } from \"../feature/scanner/FileScanner\";\nimport { MindBaseAppOptions } from \"../types/Index\";\nimport initExpress from \"../utils/InitExpress\";\nimport { setupDatabase } from \"../utils/InitDatabase\";\nimport { registerComponents } from \"../utils/ComponentRegistry\";\nimport { setupErrorHandlers } from \"../utils/InitErrorHandler\";\nimport { startServer } from \"../utils/HttpServer\";\nimport logger from \"../utils/Logger\";\nimport { initDocManager } from \"../utils/DocManager\";\nimport docRouter from \"../routes/Doc.route\";\n\n/**\n * MindBase 应用实例\n */\nexport interface MindBaseApp {\n /** 注册插件模块 */\n use(plugin: any): void;\n /** 启动应用(初始化数据库、注册路由、启动 HTTP 服务) */\n startup(): Promise<void>;\n /** 获取 Express 实例 */\n getApp(): Express;\n /** 获取 Drizzle 数据库实例 */\n getDB(): any;\n /** 获取应用配置选项 */\n getOptions(): MindBaseAppOptions;\n}\n\n/**\n * 创建 MindBase 应用实例\n * @param options 应用配置选项\n * @returns MindBase 应用实例\n * @example\n * const app = createApp({\n * port: 3000,\n * logLevel: \"debug\",\n * });\n * app.use(auth);\n * await app.startup();\n */\nexport function createApp(options: MindBaseAppOptions = {}): MindBaseApp {\n logger.startup(\"初始化\", \"应用初始化……\");\n const stateInstance = createState(options);\n const plugins: any[] = [];\n\n // 初始化日志级别\n if (stateInstance.options.logLevel) {\n logger.setLevel(stateInstance.options.logLevel);\n }\n\n const app: MindBaseApp = {\n use: async (plugin) => {\n if (typeof plugin.install === \"function\") {\n plugins.push(plugin);\n }\n if (typeof plugin.__modulePath === \"string\") {\n logger.startup(\"模块\", `注册:${plugin.__modulePath}`);\n addScanPath(plugin.__modulePath);\n }\n },\n startup: async () => {\n // 0. 初始化 Express 基础配置\n initExpress(stateInstance);\n\n // 1. 准备扫描环境\n await prepareScanEnvironment();\n\n // 2. 扫描组件\n const scannedResults = await scanComponents();\n\n // 3. 初始化数据库\n await initializeDataStorage(scannedResults);\n\n // 4. 初始化模块\n await installPlugins();\n\n // 5. 注册组件\n\n registerComponents(stateInstance, scannedResults);\n\n // 6. 注册文档路由\n registerDocRoutes();\n\n // 7. 注册错误处理\n setupErrorHandlers(stateInstance.express, stateInstance.options.logging);\n\n // 8. 启动 HTTP 服务\n await startHttpServer();\n\n logger.startup(\"初始化\", \"✅ 应用启动完成\");\n },\n\n getApp: () => stateInstance.express,\n getDB: () => stateInstance.db,\n getOptions: () => stateInstance.options,\n };\n\n // 准备扫描环境\n async function prepareScanEnvironment() {\n setBaseDir(process.cwd());\n logger.startup(\"扫描\", `基准目录: ${process.cwd()}`);\n }\n\n // 扫描组件\n async function scanComponents() {\n const scannedResults = await scan();\n\n // 统计缓存命中情况\n const routeFiles = scannedResults.filter((r) => r.type === \"route\");\n const cacheHits = routeFiles.filter((r) => r.cacheHit).length;\n const total = routeFiles.length;\n\n if (cacheHits > 0) {\n logger.startup(\"扫描\", `发现 ${scannedResults.length} 个组件文件 (缓存命中: ${cacheHits}/${total})`);\n } else {\n logger.startup(\"扫描\", `发现 ${scannedResults.length} 个组件文件`);\n }\n\n return scannedResults;\n }\n\n // 初始化数据存储\n async function initializeDataStorage(scannedResults) {\n // 初始化数据库与 Schema\n setupDatabase(stateInstance, scannedResults);\n stateInstance.express.set(\"db\", stateInstance.db);\n\n // 收集数据库信息\n if (stateInstance.db) {\n const dbPath = stateInstance.options.database?.path || \"./data/app.db\";\n logger.startup(\"数据库\", `已连接: SQLite (${dbPath})`);\n }\n\n // 初始化文档管理器\n const docDbPath = stateInstance.options.database?.path\n ? stateInstance.options.database.path.replace(/app\\.db$/, \"doc.db\")\n : \"./data/doc.db\";\n initDocManager({ path: docDbPath });\n logger.startup(\"数据库\", `文档库已初始化: ${docDbPath}`);\n }\n\n // 执行插件安装\n async function installPlugins() {\n for (const plugin of plugins) {\n await plugin.install(app);\n }\n }\n\n // 启动 HTTP 服务\n async function startHttpServer() {\n const listenPort = stateInstance.options.port || 3000;\n await startServer(stateInstance.express, listenPort);\n\n // 打印服务器启动信息\n const serverUrl = `http://${stateInstance.options.host}:${listenPort}`;\n logger.startup(\"服务\", `访问地址: ${serverUrl}`);\n }\n\n // 注册文档路由\n function registerDocRoutes() {\n const apiPrefix = stateInstance.options.apiPrefix || \"/api\";\n const docRoutePath = `${apiPrefix}/doc`.replace(/\\/+/g, \"/\");\n stateInstance.express.use(docRoutePath, docRouter);\n stateInstance.options.authWhitelist.push(`${docRoutePath}/modules`);\n logger.startup(\"路由\", `${docRoutePath}/modules (GET)`);\n stateInstance.options.authWhitelist.push(`${docRoutePath}/routes`);\n logger.startup(\"路由\", `${docRoutePath}/routes (GET)`);\n stateInstance.options.authWhitelist.push(new RegExp(`^${docRoutePath}/routes/[^/]+$`));\n logger.startup(\"路由\", `${docRoutePath}/routes/:id (GET)`);\n stateInstance.options.authWhitelist.push(`${docRoutePath}/sync`);\n logger.startup(\"路由\", `${docRoutePath}/sync (POST)`);\n }\n\n return app;\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport { setBaseDir, scan } from \"../feature/scanner/FileScanner\";\nimport { initDatabase } from \"../utils/InitDatabase\";\nimport logger from \"../utils/Logger\";\n\n/**\n * 准备命令\n *\n * 初始化数据库并预热缓存,但不启动服务器\n * 用于在构建/初始化阶段准备环境\n */\nexport async function prepare(cwd: string = process.cwd()): Promise<void> {\n console.log(\"🚀 MindBase 环境准备工具\");\n console.log(`工作目录: ${cwd}\\n`);\n\n // 设置基础目录\n setBaseDir(cwd);\n\n try {\n // 1. 扫描组件(获取 schemas 用于数据库初始化)\n console.log(\"📂 扫描组件文件...\");\n const results = await scan();\n\n const routeFiles = results.filter((r) => r.type === \"route\");\n const middlewareFiles = results.filter((r) => r.type === \"middleware\");\n const schemaFiles = results.filter((r) => r.type === \"schema\");\n\n console.log(` 发现 ${results.length} 个组件文件`);\n console.log(` - 路由: ${routeFiles.length}`);\n console.log(` - 中间件: ${middlewareFiles.length}`);\n console.log(` - Schema: ${schemaFiles.length}`);\n\n // 生成 .drizzle-schemas.json 供 drizzle.config.ts 使用\n if (schemaFiles.length > 0) {\n const schemaJsonPath = path.join(cwd, \".drizzle-schemas.json\");\n const relativeSchemaPaths = schemaFiles.map((f) =>\n path.relative(cwd, f.filePath).replace(/\\\\/g, \"/\")\n );\n fs.writeFileSync(schemaJsonPath, JSON.stringify(relativeSchemaPaths, null, 2));\n console.log(` 已生成 schema 清单: .drizzle-schemas.json\\n`);\n } else {\n console.log(\" 警告: 未找到 schema 文件\\n\");\n }\n\n // 2. 提取 schemas\n const schemas: Record<string, any> = {};\n for (const item of results) {\n if (item.type === \"schema\" && item.allExports) {\n try {\n Object.assign(schemas, item.allExports);\n } catch (e) {\n logger.warn(`处理 Schema 文件失败: ${item.filePath}`, e);\n }\n }\n }\n\n // 3. 初始化数据库(会自动创建目录和数据库文件)\n console.log(\"💾 初始化数据库...\");\n const db = initDatabase({\n dbPath: process.env.DB_PATH || \"./data/app.db\",\n schemas,\n });\n console.log(` 数据库已初始化\\n`);\n\n // 4. 显示缓存信息\n const cacheFile = path.join(cwd, \"node_modules/.cache/mindbase/startup-cache.json\");\n console.log(\"✅ 环境准备完成!\");\n console.log(`\\n📦 缓存文件: ${cacheFile}`);\n console.log(`💾 数据库: ${process.env.DB_PATH || \"./data/app.db\"}`);\n console.log(\"\\n💡 提示: 现在可以运行 db push、init-admin 等命令了\");\n } catch (error) {\n console.error(\"\\n❌ 准备失败:\", error);\n process.exit(1);\n }\n}\n\n// 兼容旧代码:保留 precache 别名\nexport async function precache(cwd?: string): Promise<void> {\n return prepare(cwd);\n}\n","import { CronJob } from \"cron\";\nimport { randomUUID } from \"crypto\";\n\ninterface CronConfig {\n timezone?: string;\n}\n\ninterface CronJobMap {\n [id: string]: CronJob;\n}\n\nlet jobs: CronJobMap = {};\nlet config: CronConfig = {\n timezone: \"Asia/Shanghai\",\n};\n\nexport function setConfig(newConfig: CronConfig): void {\n config = {\n ...config,\n ...newConfig,\n };\n}\n\nexport function addCron(pattern: string, handler: () => void | Promise<void>, customId?: string): string {\n const id = customId || generateId();\n if (jobs[id]) {\n jobs[id].stop();\n }\n const job = new CronJob(pattern, handler, null, true, config.timezone);\n jobs[id] = job;\n return id;\n}\n\nexport function stopCron(id: string): boolean {\n const job = jobs[id];\n if (job) {\n job.stop();\n delete jobs[id];\n return true;\n }\n return false;\n}\n\nexport function stopAllCron(): void {\n Object.values(jobs).forEach((job) => {\n job.stop();\n });\n jobs = {};\n}\n\nfunction generateId(): string {\n return randomUUID();\n}\n\nconst CronManager = {\n setConfig,\n addCron,\n stopCron,\n stopAllCron,\n};\n\nexport default CronManager;\nexport type { CronConfig };\n","import path from \"path\";\nimport fs from \"fs\";\n\n/**\n * 查找包含 package.json 的根目录\n * @param startPath 开始查找的路径\n * @returns 包含 package.json 的目录路径\n * @throws 如果输入路径无效\n */\nexport function findPackageRoot(startPath: string): string {\n // 验证输入路径\n if (!startPath || typeof startPath !== \"string\") {\n throw new Error(\"无效的起始路径:路径必须是非空字符串\");\n }\n\n // 确保路径是绝对路径\n let currentPath: string;\n try {\n currentPath = path.isAbsolute(startPath) ? startPath : path.resolve(startPath);\n } catch (e) {\n throw new Error(`无法解析路径:${startPath}`);\n }\n\n // 验证路径是否存在\n try {\n if (!fs.existsSync(currentPath)) {\n throw new Error(`路径不存在:${currentPath}`);\n }\n\n // 如果是文件,从其父目录开始查找\n const stat = fs.statSync(currentPath);\n if (stat.isFile()) {\n currentPath = path.dirname(currentPath);\n }\n } catch (e) {\n throw new Error(`路径验证失败:${e instanceof Error ? e.message : String(e)}`);\n }\n\n // 向上查找 package.json\n while (currentPath !== path.parse(currentPath).root) {\n try {\n const pkgJsonPath = path.join(currentPath, \"package.json\");\n if (fs.existsSync(pkgJsonPath)) {\n // 验证找到的 package.json 是否是文件\n const pkgStat = fs.statSync(pkgJsonPath);\n if (pkgStat.isFile()) {\n return currentPath;\n }\n }\n } catch (e) {\n // 忽略单个路径的访问错误,继续向上查找\n }\n currentPath = path.dirname(currentPath);\n }\n\n // 如果没有找到 package.json,返回起始路径的父目录\n return path.dirname(startPath);\n}\n","import * as path from \"path\";\n\n/**\n * 获取当前模块的路径\n * @returns 当前模块的绝对路径\n * @throws 如果无法确定模块路径\n */\nexport function getModulePath(): string {\n // 从调用栈中提取调用者的路径\n try {\n const error = new Error();\n if (error.stack) {\n console.log(\"DEBUG STACK:\", error.stack);\n const stackLines = error.stack.split(\"\\n\");\n\n // 跳过内部调用,找到真正的调用者\n // 需要跳过:getModulePath, createModule, ts-node, node:internal\n for (const line of stackLines) {\n // 跳过内部函数和 Node.js/ts-node 的调用\n if (!line.includes(\"at\") ||\n line.includes(\"getModulePath\") ||\n line.includes(\"createModule\") ||\n line.includes(\"CreateModule.ts\") ||\n line.includes(\"ts-node\") ||\n line.includes(\"node:internal\")) {\n continue;\n }\n\n // 提取文件路径\n // 格式可能是:at xxx (/path/to/file.ts:1:2) 或 at /path/to/file.ts:1:2\n const match = line.match(/\\(([^:]+\\.ts)/) || line.match(/at\\s+([^:]+\\.ts)/);\n if (match && match[1]) {\n const filePath = match[1];\n console.log(\"提取到的路径:\", filePath);\n return path.resolve(filePath);\n }\n }\n }\n } catch (e) {\n // 忽略提取 stack 时的错误\n }\n\n throw new Error(\"无法确定模块路径:当前环境不支持 __filename 且无法从调用栈中提取路径\");\n}\n\n/**\n * 获取当前模块所在的目录\n * @returns 当前模块的目录路径\n * @throws 如果无法确定模块路径\n */\nexport function getModuleDir(): string {\n try {\n const modulePath = getModulePath();\n return path.dirname(modulePath);\n } catch (error) {\n throw new Error(`无法获取模块目录:${error instanceof Error ? error.message : String(error)}`);\n }\n}\n","import { findPackageRoot } from \"./FindPackageRoot\";\nimport { getModulePath } from \"./GetModulePath\";\nimport { MindBaseApp } from \"../../types\";\nimport logger from \"../../utils/Logger\";\n\nexport interface LightUpModule {\n install(app: MindBaseApp): Promise<void>;\n __modulePath: string;\n}\n\n/**\n * 创建一个 LightUp 模块\n * @param install 模块安装函数\n * @param callerPath 调用者的文件路径(通常是 __filename),如果不提供则尝试通过调用栈获取\n * @returns LightUp 模块实例\n * @throws 如果模块创建失败\n */\nexport function createModule(install, callerPath?: string): LightUpModule {\n if (typeof install !== \"function\") {\n throw new Error(\"模块安装函数必须是一个函数\");\n }\n\n try {\n // 优先使用传入的 callerPath,否则通过调用栈获取\n const modulePath = callerPath || getModulePath();\n const packageRoot = findPackageRoot(modulePath);\n\n logger.debug(`创建模块:路径=${modulePath},包根目录=${packageRoot}`);\n\n return {\n install,\n __modulePath: packageRoot,\n };\n } catch (error) {\n logger.error(\"模块创建失败:\", error);\n throw new Error(`模块创建失败:${error instanceof Error ? error.message : String(error)}`);\n }\n}\n","/**\n * 创建业务错误\n * @param code HTTP 状态码\n * @param msg 错误消息\n */\nexport function createAppError(code: number, msg: string): Error {\n const err = new Error(msg);\n (err as any).statusCode = code;\n (err as any).isAppError = true;\n return err;\n}\n\n/**\n * 便捷工厂函数\n */\nexport const Errors = {\n badRequest: (msg: string) => createAppError(400, msg),\n unauthorized: (msg: string) => createAppError(401, msg),\n forbidden: (msg: string) => createAppError(403, msg),\n notFound: (msg: string) => createAppError(404, msg),\n};\n"],"mappings":"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","names":["express","fs","express","fs","path","fs","state","dbPath","path","fs","config","SyntaxKind","path","Node","SyntaxKind","Node","SyntaxKind","prop","SyntaxKind","Database","path","fs","config","Database","path","router","config","state","path","resolve","response","dbPath","fs","path","path","fs","path","fs","path"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindbase/express-common",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "exports": {
5
5
  ".": {
6
6
  "development": "./index.ts",