vafast 0.3.11 → 0.4.1
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/README.md +61 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +168 -1
- package/dist/index.js.map +1 -1
- package/dist/monitoring/index.js +151 -1
- package/dist/monitoring/index.js.map +1 -1
- package/dist/monitoring/native-monitor.js +151 -1
- package/dist/monitoring/native-monitor.js.map +1 -1
- package/dist/router/index.js +2 -1
- package/dist/router/index.js.map +1 -1
- package/dist/router.js +2 -1
- package/dist/router.js.map +1 -1
- package/dist/server/index.js +144 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/server-factory.js +144 -1
- package/dist/server/server-factory.js.map +1 -1
- package/dist/server/server.d.ts +15 -1
- package/dist/server/server.js +144 -1
- package/dist/server/server.js.map +1 -1
- package/dist/types/types.d.ts +12 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +146 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/route-registry.d.ts +195 -0
- package/dist/utils/route-registry.js +152 -0
- package/dist/utils/route-registry.js.map +1 -0
- package/package.json +1 -1
package/dist/router/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/router/radix-tree.ts","../../src/router.ts"],"sourcesContent":["/**\n * Radix Tree 路由匹配器\n *\n * 高性能路由匹配实现,时间复杂度 O(k),k 为路径段数\n *\n * 支持的路由模式:\n * - 静态路径: /users, /api/v1/health\n * - 动态参数: /users/:id, /posts/:postId/comments/:commentId\n * - 通配符: /files/*, /static/*filepath\n */\n\nimport type { Handler, Middleware, Method } from \"../types\";\n\n/** 预编译的处理器类型 */\ntype CompiledHandler = (req: Request) => Promise<Response>;\n\n/** 路由处理信息 */\ninterface RouteHandler {\n handler: Handler;\n middleware: Middleware[];\n /** 预编译后的完整处理链(包含中间件) */\n compiled?: CompiledHandler;\n}\n\n/** Radix Tree 节点 */\ninterface RadixNode {\n path: string;\n children: Record<string, RadixNode>;\n paramChild?: RadixNode;\n wildcardChild?: RadixNode;\n paramName?: string;\n handlers: Record<Method, RouteHandler | undefined>;\n}\n\n/** 路由匹配结果 */\nexport interface MatchResult {\n handler: Handler;\n middleware: Middleware[];\n params: Record<string, string>;\n /** 预编译后的完整处理链 */\n compiled?: CompiledHandler;\n}\n\n/**\n * Radix Tree 路由器\n *\n * @example\n * ```typescript\n * const router = new RadixRouter();\n * router.register(\"GET\", \"/users/:id\", handler);\n * const result = router.match(\"GET\", \"/users/123\");\n * // result.params = { id: \"123\" }\n * ```\n */\nexport class RadixRouter {\n private root: RadixNode;\n\n constructor() {\n this.root = this.createNode(\"\");\n }\n\n private createNode(path: string): RadixNode {\n return {\n path,\n children: Object.create(null),\n handlers: Object.create(null),\n };\n }\n\n /** 分割路径 */\n private splitPath(path: string): string[] {\n return path.split(\"/\").filter(Boolean);\n }\n\n /** 编译器函数 - 用于预编译中间件链 */\n private compiler?: (\n middleware: Middleware[],\n handler: Handler,\n ) => CompiledHandler;\n\n /** 设置中间件编译器 */\n setCompiler(\n compiler: (middleware: Middleware[], handler: Handler) => CompiledHandler,\n ): void {\n this.compiler = compiler;\n }\n\n /** 注册路由 */\n register(\n method: Method,\n pattern: string,\n handler: Handler,\n middleware: Middleware[] = [],\n ): void {\n const segments = this.splitPath(pattern);\n let node = this.root;\n\n for (const segment of segments) {\n const firstChar = segment[0];\n\n if (firstChar === \":\") {\n // 动态参数节点\n if (!node.paramChild) {\n node.paramChild = this.createNode(segment);\n node.paramChild.paramName = segment.substring(1);\n }\n node = node.paramChild;\n } else if (firstChar === \"*\") {\n // 通配符节点\n if (!node.wildcardChild) {\n node.wildcardChild = this.createNode(segment);\n node.wildcardChild.paramName =\n segment.length > 1 ? segment.substring(1) : \"*\";\n }\n node = node.wildcardChild;\n break;\n } else {\n // 静态路径节点\n if (!node.children[segment]) {\n node.children[segment] = this.createNode(segment);\n }\n node = node.children[segment];\n }\n }\n\n const routeHandler: RouteHandler = { handler, middleware };\n\n // 如果没有全局中间件且设置了编译器,预编译处理链\n if (this.compiler && middleware.length === 0) {\n routeHandler.compiled = this.compiler([], handler);\n }\n\n node.handlers[method] = routeHandler;\n }\n\n /** 预编译所有路由(在添加全局中间件后调用) */\n precompileAll(globalMiddleware: Middleware[]): void {\n if (!this.compiler) return;\n this.precompileNode(this.root, globalMiddleware);\n }\n\n private precompileNode(\n node: RadixNode,\n globalMiddleware: Middleware[],\n ): void {\n for (const method in node.handlers) {\n const routeHandler = node.handlers[method as Method];\n if (routeHandler) {\n const allMiddleware = [...globalMiddleware, ...routeHandler.middleware];\n routeHandler.compiled = this.compiler!(\n allMiddleware,\n routeHandler.handler,\n );\n }\n }\n\n for (const key in node.children) {\n this.precompileNode(node.children[key], globalMiddleware);\n }\n\n if (node.paramChild) {\n this.precompileNode(node.paramChild, globalMiddleware);\n }\n\n if (node.wildcardChild) {\n this.precompileNode(node.wildcardChild, globalMiddleware);\n }\n }\n\n /** 匹配路由 */\n match(method: Method, path: string): MatchResult | null {\n const segments = this.splitPath(path);\n const params: Record<string, string> = Object.create(null);\n\n const node = this.matchNode(this.root, segments, 0, params);\n if (!node) return null;\n\n const routeHandler = node.handlers[method];\n if (!routeHandler) return null;\n\n return {\n handler: routeHandler.handler,\n middleware: routeHandler.middleware,\n params,\n compiled: routeHandler.compiled,\n };\n }\n\n /** 递归匹配节点 (优先级: 静态 > 动态参数 > 通配符) */\n private matchNode(\n node: RadixNode,\n segments: string[],\n index: number,\n params: Record<string, string>,\n ): RadixNode | null {\n if (index === segments.length) {\n for (const method in node.handlers) {\n if (node.handlers[method as Method]) return node;\n }\n return null;\n }\n\n const segment = segments[index];\n\n // 1. 静态路径\n const staticChild = node.children[segment];\n if (staticChild) {\n const result = this.matchNode(staticChild, segments, index + 1, params);\n if (result) return result;\n }\n\n // 2. 动态参数\n if (node.paramChild) {\n const paramName = node.paramChild.paramName!;\n const oldValue = params[paramName];\n\n params[paramName] = segment;\n const result = this.matchNode(\n node.paramChild,\n segments,\n index + 1,\n params,\n );\n\n if (result) return result;\n\n // 回溯\n if (oldValue === undefined) {\n delete params[paramName];\n } else {\n params[paramName] = oldValue;\n }\n }\n\n // 3. 通配符\n if (node.wildcardChild) {\n params[node.wildcardChild.paramName || \"*\"] = segments\n .slice(index)\n .join(\"/\");\n return node.wildcardChild;\n }\n\n return null;\n }\n\n /** 获取路径允许的 HTTP 方法 */\n getAllowedMethods(path: string): Method[] {\n const segments = this.splitPath(path);\n const node = this.findNode(segments);\n if (!node) return [];\n\n const methods: Method[] = [];\n for (const method in node.handlers) {\n if (node.handlers[method as Method]) {\n methods.push(method as Method);\n }\n }\n return methods;\n }\n\n /** 查找节点(不提取参数) */\n private findNode(segments: string[]): RadixNode | null {\n let node = this.root;\n\n for (const segment of segments) {\n if (node.children[segment]) {\n node = node.children[segment];\n } else if (node.paramChild) {\n node = node.paramChild;\n } else if (node.wildcardChild) {\n return node.wildcardChild;\n } else {\n return null;\n }\n }\n\n return node;\n }\n\n /** 获取所有已注册的路由 */\n getRoutes(): Array<{ method: Method; path: string }> {\n const routes: Array<{ method: Method; path: string }> = [];\n this.collectRoutes(this.root, \"\", routes);\n return routes;\n }\n\n private collectRoutes(\n node: RadixNode,\n prefix: string,\n routes: Array<{ method: Method; path: string }>,\n ): void {\n const currentPath = prefix + (node.path ? \"/\" + node.path : \"\");\n\n for (const method in node.handlers) {\n if (node.handlers[method as Method]) {\n routes.push({ method: method as Method, path: currentPath || \"/\" });\n }\n }\n\n for (const key in node.children) {\n this.collectRoutes(node.children[key], currentPath, routes);\n }\n\n if (node.paramChild) {\n this.collectRoutes(node.paramChild, currentPath, routes);\n }\n\n if (node.wildcardChild) {\n this.collectRoutes(node.wildcardChild, currentPath, routes);\n }\n }\n}\n","/**\n * 路由工具函数\n *\n * 提供路由处理的基础工具\n */\n\nimport type { Route, NestedRoute, FlattenedRoute, Middleware } from \"./types\";\n\n/**\n * 扁平化嵌套路由\n *\n * 将嵌套路由结构转换为扁平数组,计算完整路径和中间件链\n *\n * @example\n * ```typescript\n * const routes = flattenNestedRoutes([\n * {\n * path: \"/api\",\n * middleware: [authMiddleware],\n * children: [\n * { path: \"/users\", method: \"GET\", handler: getUsers },\n * { path: \"/users/:id\", method: \"GET\", handler: getUser },\n * ],\n * },\n * ]);\n * // 结果:\n * // [\n * // { fullPath: \"/api/users\", method: \"GET\", ... },\n * // { fullPath: \"/api/users/:id\", method: \"GET\", ... },\n * // ]\n * ```\n */\nexport function flattenNestedRoutes(\n routes: (Route | NestedRoute)[],\n): FlattenedRoute[] {\n const flattened: FlattenedRoute[] = [];\n\n function processRoute(\n route: Route | NestedRoute,\n parentPath = \"\",\n parentMiddleware: Middleware[] = [],\n ): void {\n // 计算当前完整路径\n const currentPath = normalizePath(parentPath + route.path);\n // 合并中间件链\n const currentMiddleware = [\n ...parentMiddleware,\n ...(route.middleware || []),\n ];\n\n if (\"method\" in route && \"handler\" in route) {\n // 叶子路由(有处理函数)\n flattened.push({\n ...route,\n fullPath: currentPath,\n middlewareChain: currentMiddleware,\n });\n } else if (\"children\" in route && route.children) {\n // 分组路由,递归处理子路由\n for (const child of route.children) {\n processRoute(child, currentPath, currentMiddleware);\n }\n }\n }\n\n for (const route of routes) {\n processRoute(route);\n }\n\n return flattened;\n}\n\n/**\n * 标准化路径\n *\n * - 解码 URL 编码字符\n * - 去除重复斜杠\n * - 处理结尾斜杠\n *\n * @example\n * ```typescript\n * normalizePath(\"//api//users/\") // \"/api/users\"\n * normalizePath(\"/api/%20test\") // \"/api/ test\"\n * ```\n */\nexport function normalizePath(path: string): string {\n // 解码 URL 编码\n let normalized = decodeURIComponent(path);\n\n // 去除重复斜杠\n normalized = normalized.replace(/\\/+/g, \"/\");\n\n // 空路径转为根路径\n if (normalized === \"\") return \"/\";\n\n // 去除结尾斜杠(根路径除外)\n if (normalized !== \"/\" && normalized.endsWith(\"/\")) {\n normalized = normalized.slice(0, -1);\n }\n\n return normalized;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/router/radix-tree.ts","../../src/router.ts"],"sourcesContent":["/**\n * Radix Tree 路由匹配器\n *\n * 高性能路由匹配实现,时间复杂度 O(k),k 为路径段数\n *\n * 支持的路由模式:\n * - 静态路径: /users, /api/v1/health\n * - 动态参数: /users/:id, /posts/:postId/comments/:commentId\n * - 通配符: /files/*, /static/*filepath\n */\n\nimport type { Handler, Middleware, Method } from \"../types\";\n\n/** 预编译的处理器类型 */\ntype CompiledHandler = (req: Request) => Promise<Response>;\n\n/** 路由处理信息 */\ninterface RouteHandler {\n handler: Handler;\n middleware: Middleware[];\n /** 预编译后的完整处理链(包含中间件) */\n compiled?: CompiledHandler;\n}\n\n/** Radix Tree 节点 */\ninterface RadixNode {\n path: string;\n children: Record<string, RadixNode>;\n paramChild?: RadixNode;\n wildcardChild?: RadixNode;\n paramName?: string;\n handlers: Record<Method, RouteHandler | undefined>;\n}\n\n/** 路由匹配结果 */\nexport interface MatchResult {\n handler: Handler;\n middleware: Middleware[];\n params: Record<string, string>;\n /** 预编译后的完整处理链 */\n compiled?: CompiledHandler;\n}\n\n/**\n * Radix Tree 路由器\n *\n * @example\n * ```typescript\n * const router = new RadixRouter();\n * router.register(\"GET\", \"/users/:id\", handler);\n * const result = router.match(\"GET\", \"/users/123\");\n * // result.params = { id: \"123\" }\n * ```\n */\nexport class RadixRouter {\n private root: RadixNode;\n\n constructor() {\n this.root = this.createNode(\"\");\n }\n\n private createNode(path: string): RadixNode {\n return {\n path,\n children: Object.create(null),\n handlers: Object.create(null),\n };\n }\n\n /** 分割路径 */\n private splitPath(path: string): string[] {\n return path.split(\"/\").filter(Boolean);\n }\n\n /** 编译器函数 - 用于预编译中间件链 */\n private compiler?: (\n middleware: Middleware[],\n handler: Handler,\n ) => CompiledHandler;\n\n /** 设置中间件编译器 */\n setCompiler(\n compiler: (middleware: Middleware[], handler: Handler) => CompiledHandler,\n ): void {\n this.compiler = compiler;\n }\n\n /** 注册路由 */\n register(\n method: Method,\n pattern: string,\n handler: Handler,\n middleware: Middleware[] = [],\n ): void {\n const segments = this.splitPath(pattern);\n let node = this.root;\n\n for (const segment of segments) {\n const firstChar = segment[0];\n\n if (firstChar === \":\") {\n // 动态参数节点\n if (!node.paramChild) {\n node.paramChild = this.createNode(segment);\n node.paramChild.paramName = segment.substring(1);\n }\n node = node.paramChild;\n } else if (firstChar === \"*\") {\n // 通配符节点\n if (!node.wildcardChild) {\n node.wildcardChild = this.createNode(segment);\n node.wildcardChild.paramName =\n segment.length > 1 ? segment.substring(1) : \"*\";\n }\n node = node.wildcardChild;\n break;\n } else {\n // 静态路径节点\n if (!node.children[segment]) {\n node.children[segment] = this.createNode(segment);\n }\n node = node.children[segment];\n }\n }\n\n const routeHandler: RouteHandler = { handler, middleware };\n\n // 如果没有全局中间件且设置了编译器,预编译处理链\n if (this.compiler && middleware.length === 0) {\n routeHandler.compiled = this.compiler([], handler);\n }\n\n node.handlers[method] = routeHandler;\n }\n\n /** 预编译所有路由(在添加全局中间件后调用) */\n precompileAll(globalMiddleware: Middleware[]): void {\n if (!this.compiler) return;\n this.precompileNode(this.root, globalMiddleware);\n }\n\n private precompileNode(\n node: RadixNode,\n globalMiddleware: Middleware[],\n ): void {\n for (const method in node.handlers) {\n const routeHandler = node.handlers[method as Method];\n if (routeHandler) {\n const allMiddleware = [...globalMiddleware, ...routeHandler.middleware];\n routeHandler.compiled = this.compiler!(\n allMiddleware,\n routeHandler.handler,\n );\n }\n }\n\n for (const key in node.children) {\n this.precompileNode(node.children[key], globalMiddleware);\n }\n\n if (node.paramChild) {\n this.precompileNode(node.paramChild, globalMiddleware);\n }\n\n if (node.wildcardChild) {\n this.precompileNode(node.wildcardChild, globalMiddleware);\n }\n }\n\n /** 匹配路由 */\n match(method: Method, path: string): MatchResult | null {\n const segments = this.splitPath(path);\n const params: Record<string, string> = Object.create(null);\n\n const node = this.matchNode(this.root, segments, 0, params);\n if (!node) return null;\n\n const routeHandler = node.handlers[method];\n if (!routeHandler) return null;\n\n return {\n handler: routeHandler.handler,\n middleware: routeHandler.middleware,\n params,\n compiled: routeHandler.compiled,\n };\n }\n\n /** 递归匹配节点 (优先级: 静态 > 动态参数 > 通配符) */\n private matchNode(\n node: RadixNode,\n segments: string[],\n index: number,\n params: Record<string, string>,\n ): RadixNode | null {\n if (index === segments.length) {\n for (const method in node.handlers) {\n if (node.handlers[method as Method]) return node;\n }\n return null;\n }\n\n const segment = segments[index];\n\n // 1. 静态路径\n const staticChild = node.children[segment];\n if (staticChild) {\n const result = this.matchNode(staticChild, segments, index + 1, params);\n if (result) return result;\n }\n\n // 2. 动态参数\n if (node.paramChild) {\n const paramName = node.paramChild.paramName!;\n const oldValue = params[paramName];\n\n params[paramName] = segment;\n const result = this.matchNode(\n node.paramChild,\n segments,\n index + 1,\n params,\n );\n\n if (result) return result;\n\n // 回溯\n if (oldValue === undefined) {\n delete params[paramName];\n } else {\n params[paramName] = oldValue;\n }\n }\n\n // 3. 通配符\n if (node.wildcardChild) {\n params[node.wildcardChild.paramName || \"*\"] = segments\n .slice(index)\n .join(\"/\");\n return node.wildcardChild;\n }\n\n return null;\n }\n\n /** 获取路径允许的 HTTP 方法 */\n getAllowedMethods(path: string): Method[] {\n const segments = this.splitPath(path);\n const node = this.findNode(segments);\n if (!node) return [];\n\n const methods: Method[] = [];\n for (const method in node.handlers) {\n if (node.handlers[method as Method]) {\n methods.push(method as Method);\n }\n }\n return methods;\n }\n\n /** 查找节点(不提取参数) */\n private findNode(segments: string[]): RadixNode | null {\n let node = this.root;\n\n for (const segment of segments) {\n if (node.children[segment]) {\n node = node.children[segment];\n } else if (node.paramChild) {\n node = node.paramChild;\n } else if (node.wildcardChild) {\n return node.wildcardChild;\n } else {\n return null;\n }\n }\n\n return node;\n }\n\n /** 获取所有已注册的路由 */\n getRoutes(): Array<{ method: Method; path: string }> {\n const routes: Array<{ method: Method; path: string }> = [];\n this.collectRoutes(this.root, \"\", routes);\n return routes;\n }\n\n private collectRoutes(\n node: RadixNode,\n prefix: string,\n routes: Array<{ method: Method; path: string }>,\n ): void {\n const currentPath = prefix + (node.path ? \"/\" + node.path : \"\");\n\n for (const method in node.handlers) {\n if (node.handlers[method as Method]) {\n routes.push({ method: method as Method, path: currentPath || \"/\" });\n }\n }\n\n for (const key in node.children) {\n this.collectRoutes(node.children[key], currentPath, routes);\n }\n\n if (node.paramChild) {\n this.collectRoutes(node.paramChild, currentPath, routes);\n }\n\n if (node.wildcardChild) {\n this.collectRoutes(node.wildcardChild, currentPath, routes);\n }\n }\n}\n","/**\n * 路由工具函数\n *\n * 提供路由处理的基础工具\n */\n\nimport type { Route, NestedRoute, FlattenedRoute, Middleware } from \"./types\";\n\n/**\n * 扁平化嵌套路由\n *\n * 将嵌套路由结构转换为扁平数组,计算完整路径和中间件链\n *\n * @example\n * ```typescript\n * const routes = flattenNestedRoutes([\n * {\n * path: \"/api\",\n * middleware: [authMiddleware],\n * children: [\n * { path: \"/users\", method: \"GET\", handler: getUsers },\n * { path: \"/users/:id\", method: \"GET\", handler: getUser },\n * ],\n * },\n * ]);\n * // 结果:\n * // [\n * // { fullPath: \"/api/users\", method: \"GET\", ... },\n * // { fullPath: \"/api/users/:id\", method: \"GET\", ... },\n * // ]\n * ```\n */\nexport function flattenNestedRoutes(\n routes: (Route | NestedRoute)[],\n): FlattenedRoute[] {\n const flattened: FlattenedRoute[] = [];\n\n function processRoute(\n route: Route | NestedRoute,\n parentPath = \"\",\n parentMiddleware: Middleware[] = [],\n ): void {\n // 计算当前完整路径\n const currentPath = normalizePath(parentPath + route.path);\n // 合并中间件链\n const currentMiddleware = [\n ...parentMiddleware,\n ...(route.middleware || []),\n ];\n\n if (\"method\" in route && \"handler\" in route) {\n // 叶子路由(有处理函数)\n const leafRoute = route as Route;\n flattened.push({\n ...leafRoute,\n fullPath: currentPath,\n middlewareChain: currentMiddleware,\n });\n } else if (\"children\" in route && route.children) {\n // 分组路由,递归处理子路由\n for (const child of route.children) {\n processRoute(child, currentPath, currentMiddleware);\n }\n }\n }\n\n for (const route of routes) {\n processRoute(route);\n }\n\n return flattened;\n}\n\n/**\n * 标准化路径\n *\n * - 解码 URL 编码字符\n * - 去除重复斜杠\n * - 处理结尾斜杠\n *\n * @example\n * ```typescript\n * normalizePath(\"//api//users/\") // \"/api/users\"\n * normalizePath(\"/api/%20test\") // \"/api/ test\"\n * ```\n */\nexport function normalizePath(path: string): string {\n // 解码 URL 编码\n let normalized = decodeURIComponent(path);\n\n // 去除重复斜杠\n normalized = normalized.replace(/\\/+/g, \"/\");\n\n // 空路径转为根路径\n if (normalized === \"\") return \"/\";\n\n // 去除结尾斜杠(根路径除外)\n if (normalized !== \"/\" && normalized.endsWith(\"/\")) {\n normalized = normalized.slice(0, -1);\n }\n\n return normalized;\n}\n"],"mappings":";AAsDO,IAAM,cAAN,MAAkB;AAAA,EACf;AAAA,EAER,cAAc;AACZ,SAAK,OAAO,KAAK,WAAW,EAAE;AAAA,EAChC;AAAA,EAEQ,WAAW,MAAyB;AAC1C,WAAO;AAAA,MACL;AAAA,MACA,UAAU,uBAAO,OAAO,IAAI;AAAA,MAC5B,UAAU,uBAAO,OAAO,IAAI;AAAA,IAC9B;AAAA,EACF;AAAA;AAAA,EAGQ,UAAU,MAAwB;AACxC,WAAO,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAAA,EACvC;AAAA;AAAA,EAGQ;AAAA;AAAA,EAMR,YACE,UACM;AACN,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA,EAGA,SACE,QACA,SACA,SACA,aAA2B,CAAC,GACtB;AACN,UAAM,WAAW,KAAK,UAAU,OAAO;AACvC,QAAI,OAAO,KAAK;AAEhB,eAAW,WAAW,UAAU;AAC9B,YAAM,YAAY,QAAQ,CAAC;AAE3B,UAAI,cAAc,KAAK;AAErB,YAAI,CAAC,KAAK,YAAY;AACpB,eAAK,aAAa,KAAK,WAAW,OAAO;AACzC,eAAK,WAAW,YAAY,QAAQ,UAAU,CAAC;AAAA,QACjD;AACA,eAAO,KAAK;AAAA,MACd,WAAW,cAAc,KAAK;AAE5B,YAAI,CAAC,KAAK,eAAe;AACvB,eAAK,gBAAgB,KAAK,WAAW,OAAO;AAC5C,eAAK,cAAc,YACjB,QAAQ,SAAS,IAAI,QAAQ,UAAU,CAAC,IAAI;AAAA,QAChD;AACA,eAAO,KAAK;AACZ;AAAA,MACF,OAAO;AAEL,YAAI,CAAC,KAAK,SAAS,OAAO,GAAG;AAC3B,eAAK,SAAS,OAAO,IAAI,KAAK,WAAW,OAAO;AAAA,QAClD;AACA,eAAO,KAAK,SAAS,OAAO;AAAA,MAC9B;AAAA,IACF;AAEA,UAAM,eAA6B,EAAE,SAAS,WAAW;AAGzD,QAAI,KAAK,YAAY,WAAW,WAAW,GAAG;AAC5C,mBAAa,WAAW,KAAK,SAAS,CAAC,GAAG,OAAO;AAAA,IACnD;AAEA,SAAK,SAAS,MAAM,IAAI;AAAA,EAC1B;AAAA;AAAA,EAGA,cAAc,kBAAsC;AAClD,QAAI,CAAC,KAAK,SAAU;AACpB,SAAK,eAAe,KAAK,MAAM,gBAAgB;AAAA,EACjD;AAAA,EAEQ,eACN,MACA,kBACM;AACN,eAAW,UAAU,KAAK,UAAU;AAClC,YAAM,eAAe,KAAK,SAAS,MAAgB;AACnD,UAAI,cAAc;AAChB,cAAM,gBAAgB,CAAC,GAAG,kBAAkB,GAAG,aAAa,UAAU;AACtE,qBAAa,WAAW,KAAK;AAAA,UAC3B;AAAA,UACA,aAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAEA,eAAW,OAAO,KAAK,UAAU;AAC/B,WAAK,eAAe,KAAK,SAAS,GAAG,GAAG,gBAAgB;AAAA,IAC1D;AAEA,QAAI,KAAK,YAAY;AACnB,WAAK,eAAe,KAAK,YAAY,gBAAgB;AAAA,IACvD;AAEA,QAAI,KAAK,eAAe;AACtB,WAAK,eAAe,KAAK,eAAe,gBAAgB;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,QAAgB,MAAkC;AACtD,UAAM,WAAW,KAAK,UAAU,IAAI;AACpC,UAAM,SAAiC,uBAAO,OAAO,IAAI;AAEzD,UAAM,OAAO,KAAK,UAAU,KAAK,MAAM,UAAU,GAAG,MAAM;AAC1D,QAAI,CAAC,KAAM,QAAO;AAElB,UAAM,eAAe,KAAK,SAAS,MAAM;AACzC,QAAI,CAAC,aAAc,QAAO;AAE1B,WAAO;AAAA,MACL,SAAS,aAAa;AAAA,MACtB,YAAY,aAAa;AAAA,MACzB;AAAA,MACA,UAAU,aAAa;AAAA,IACzB;AAAA,EACF;AAAA;AAAA,EAGQ,UACN,MACA,UACA,OACA,QACkB;AAClB,QAAI,UAAU,SAAS,QAAQ;AAC7B,iBAAW,UAAU,KAAK,UAAU;AAClC,YAAI,KAAK,SAAS,MAAgB,EAAG,QAAO;AAAA,MAC9C;AACA,aAAO;AAAA,IACT;AAEA,UAAM,UAAU,SAAS,KAAK;AAG9B,UAAM,cAAc,KAAK,SAAS,OAAO;AACzC,QAAI,aAAa;AACf,YAAM,SAAS,KAAK,UAAU,aAAa,UAAU,QAAQ,GAAG,MAAM;AACtE,UAAI,OAAQ,QAAO;AAAA,IACrB;AAGA,QAAI,KAAK,YAAY;AACnB,YAAM,YAAY,KAAK,WAAW;AAClC,YAAM,WAAW,OAAO,SAAS;AAEjC,aAAO,SAAS,IAAI;AACpB,YAAM,SAAS,KAAK;AAAA,QAClB,KAAK;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,QACR;AAAA,MACF;AAEA,UAAI,OAAQ,QAAO;AAGnB,UAAI,aAAa,QAAW;AAC1B,eAAO,OAAO,SAAS;AAAA,MACzB,OAAO;AACL,eAAO,SAAS,IAAI;AAAA,MACtB;AAAA,IACF;AAGA,QAAI,KAAK,eAAe;AACtB,aAAO,KAAK,cAAc,aAAa,GAAG,IAAI,SAC3C,MAAM,KAAK,EACX,KAAK,GAAG;AACX,aAAO,KAAK;AAAA,IACd;AAEA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,kBAAkB,MAAwB;AACxC,UAAM,WAAW,KAAK,UAAU,IAAI;AACpC,UAAM,OAAO,KAAK,SAAS,QAAQ;AACnC,QAAI,CAAC,KAAM,QAAO,CAAC;AAEnB,UAAM,UAAoB,CAAC;AAC3B,eAAW,UAAU,KAAK,UAAU;AAClC,UAAI,KAAK,SAAS,MAAgB,GAAG;AACnC,gBAAQ,KAAK,MAAgB;AAAA,MAC/B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,SAAS,UAAsC;AACrD,QAAI,OAAO,KAAK;AAEhB,eAAW,WAAW,UAAU;AAC9B,UAAI,KAAK,SAAS,OAAO,GAAG;AAC1B,eAAO,KAAK,SAAS,OAAO;AAAA,MAC9B,WAAW,KAAK,YAAY;AAC1B,eAAO,KAAK;AAAA,MACd,WAAW,KAAK,eAAe;AAC7B,eAAO,KAAK;AAAA,MACd,OAAO;AACL,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,YAAqD;AACnD,UAAM,SAAkD,CAAC;AACzD,SAAK,cAAc,KAAK,MAAM,IAAI,MAAM;AACxC,WAAO;AAAA,EACT;AAAA,EAEQ,cACN,MACA,QACA,QACM;AACN,UAAM,cAAc,UAAU,KAAK,OAAO,MAAM,KAAK,OAAO;AAE5D,eAAW,UAAU,KAAK,UAAU;AAClC,UAAI,KAAK,SAAS,MAAgB,GAAG;AACnC,eAAO,KAAK,EAAE,QAA0B,MAAM,eAAe,IAAI,CAAC;AAAA,MACpE;AAAA,IACF;AAEA,eAAW,OAAO,KAAK,UAAU;AAC/B,WAAK,cAAc,KAAK,SAAS,GAAG,GAAG,aAAa,MAAM;AAAA,IAC5D;AAEA,QAAI,KAAK,YAAY;AACnB,WAAK,cAAc,KAAK,YAAY,aAAa,MAAM;AAAA,IACzD;AAEA,QAAI,KAAK,eAAe;AACtB,WAAK,cAAc,KAAK,eAAe,aAAa,MAAM;AAAA,IAC5D;AAAA,EACF;AACF;;;ACvRO,SAAS,oBACd,QACkB;AAClB,QAAM,YAA8B,CAAC;AAErC,WAAS,aACP,OACA,aAAa,IACb,mBAAiC,CAAC,GAC5B;AAEN,UAAM,cAAc,cAAc,aAAa,MAAM,IAAI;AAEzD,UAAM,oBAAoB;AAAA,MACxB,GAAG;AAAA,MACH,GAAI,MAAM,cAAc,CAAC;AAAA,IAC3B;AAEA,QAAI,YAAY,SAAS,aAAa,OAAO;AAE3C,YAAM,YAAY;AAClB,gBAAU,KAAK;AAAA,QACb,GAAG;AAAA,QACH,UAAU;AAAA,QACV,iBAAiB;AAAA,MACnB,CAAC;AAAA,IACH,WAAW,cAAc,SAAS,MAAM,UAAU;AAEhD,iBAAW,SAAS,MAAM,UAAU;AAClC,qBAAa,OAAO,aAAa,iBAAiB;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AAEA,aAAW,SAAS,QAAQ;AAC1B,iBAAa,KAAK;AAAA,EACpB;AAEA,SAAO;AACT;AAeO,SAAS,cAAc,MAAsB;AAElD,MAAI,aAAa,mBAAmB,IAAI;AAGxC,eAAa,WAAW,QAAQ,QAAQ,GAAG;AAG3C,MAAI,eAAe,GAAI,QAAO;AAG9B,MAAI,eAAe,OAAO,WAAW,SAAS,GAAG,GAAG;AAClD,iBAAa,WAAW,MAAM,GAAG,EAAE;AAAA,EACrC;AAEA,SAAO;AACT;","names":[]}
|
package/dist/router.js
CHANGED
|
@@ -8,8 +8,9 @@ function flattenNestedRoutes(routes) {
|
|
|
8
8
|
...route.middleware || []
|
|
9
9
|
];
|
|
10
10
|
if ("method" in route && "handler" in route) {
|
|
11
|
+
const leafRoute = route;
|
|
11
12
|
flattened.push({
|
|
12
|
-
...
|
|
13
|
+
...leafRoute,
|
|
13
14
|
fullPath: currentPath,
|
|
14
15
|
middlewareChain: currentMiddleware
|
|
15
16
|
});
|
package/dist/router.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/router.ts"],"sourcesContent":["/**\n * 路由工具函数\n *\n * 提供路由处理的基础工具\n */\n\nimport type { Route, NestedRoute, FlattenedRoute, Middleware } from \"./types\";\n\n/**\n * 扁平化嵌套路由\n *\n * 将嵌套路由结构转换为扁平数组,计算完整路径和中间件链\n *\n * @example\n * ```typescript\n * const routes = flattenNestedRoutes([\n * {\n * path: \"/api\",\n * middleware: [authMiddleware],\n * children: [\n * { path: \"/users\", method: \"GET\", handler: getUsers },\n * { path: \"/users/:id\", method: \"GET\", handler: getUser },\n * ],\n * },\n * ]);\n * // 结果:\n * // [\n * // { fullPath: \"/api/users\", method: \"GET\", ... },\n * // { fullPath: \"/api/users/:id\", method: \"GET\", ... },\n * // ]\n * ```\n */\nexport function flattenNestedRoutes(\n routes: (Route | NestedRoute)[],\n): FlattenedRoute[] {\n const flattened: FlattenedRoute[] = [];\n\n function processRoute(\n route: Route | NestedRoute,\n parentPath = \"\",\n parentMiddleware: Middleware[] = [],\n ): void {\n // 计算当前完整路径\n const currentPath = normalizePath(parentPath + route.path);\n // 合并中间件链\n const currentMiddleware = [\n ...parentMiddleware,\n ...(route.middleware || []),\n ];\n\n if (\"method\" in route && \"handler\" in route) {\n // 叶子路由(有处理函数)\n flattened.push({\n ...
|
|
1
|
+
{"version":3,"sources":["../src/router.ts"],"sourcesContent":["/**\n * 路由工具函数\n *\n * 提供路由处理的基础工具\n */\n\nimport type { Route, NestedRoute, FlattenedRoute, Middleware } from \"./types\";\n\n/**\n * 扁平化嵌套路由\n *\n * 将嵌套路由结构转换为扁平数组,计算完整路径和中间件链\n *\n * @example\n * ```typescript\n * const routes = flattenNestedRoutes([\n * {\n * path: \"/api\",\n * middleware: [authMiddleware],\n * children: [\n * { path: \"/users\", method: \"GET\", handler: getUsers },\n * { path: \"/users/:id\", method: \"GET\", handler: getUser },\n * ],\n * },\n * ]);\n * // 结果:\n * // [\n * // { fullPath: \"/api/users\", method: \"GET\", ... },\n * // { fullPath: \"/api/users/:id\", method: \"GET\", ... },\n * // ]\n * ```\n */\nexport function flattenNestedRoutes(\n routes: (Route | NestedRoute)[],\n): FlattenedRoute[] {\n const flattened: FlattenedRoute[] = [];\n\n function processRoute(\n route: Route | NestedRoute,\n parentPath = \"\",\n parentMiddleware: Middleware[] = [],\n ): void {\n // 计算当前完整路径\n const currentPath = normalizePath(parentPath + route.path);\n // 合并中间件链\n const currentMiddleware = [\n ...parentMiddleware,\n ...(route.middleware || []),\n ];\n\n if (\"method\" in route && \"handler\" in route) {\n // 叶子路由(有处理函数)\n const leafRoute = route as Route;\n flattened.push({\n ...leafRoute,\n fullPath: currentPath,\n middlewareChain: currentMiddleware,\n });\n } else if (\"children\" in route && route.children) {\n // 分组路由,递归处理子路由\n for (const child of route.children) {\n processRoute(child, currentPath, currentMiddleware);\n }\n }\n }\n\n for (const route of routes) {\n processRoute(route);\n }\n\n return flattened;\n}\n\n/**\n * 标准化路径\n *\n * - 解码 URL 编码字符\n * - 去除重复斜杠\n * - 处理结尾斜杠\n *\n * @example\n * ```typescript\n * normalizePath(\"//api//users/\") // \"/api/users\"\n * normalizePath(\"/api/%20test\") // \"/api/ test\"\n * ```\n */\nexport function normalizePath(path: string): string {\n // 解码 URL 编码\n let normalized = decodeURIComponent(path);\n\n // 去除重复斜杠\n normalized = normalized.replace(/\\/+/g, \"/\");\n\n // 空路径转为根路径\n if (normalized === \"\") return \"/\";\n\n // 去除结尾斜杠(根路径除外)\n if (normalized !== \"/\" && normalized.endsWith(\"/\")) {\n normalized = normalized.slice(0, -1);\n }\n\n return normalized;\n}\n"],"mappings":";AAgCO,SAAS,oBACd,QACkB;AAClB,QAAM,YAA8B,CAAC;AAErC,WAAS,aACP,OACA,aAAa,IACb,mBAAiC,CAAC,GAC5B;AAEN,UAAM,cAAc,cAAc,aAAa,MAAM,IAAI;AAEzD,UAAM,oBAAoB;AAAA,MACxB,GAAG;AAAA,MACH,GAAI,MAAM,cAAc,CAAC;AAAA,IAC3B;AAEA,QAAI,YAAY,SAAS,aAAa,OAAO;AAE3C,YAAM,YAAY;AAClB,gBAAU,KAAK;AAAA,QACb,GAAG;AAAA,QACH,UAAU;AAAA,QACV,iBAAiB;AAAA,MACnB,CAAC;AAAA,IACH,WAAW,cAAc,SAAS,MAAM,UAAU;AAEhD,iBAAW,SAAS,MAAM,UAAU;AAClC,qBAAa,OAAO,aAAa,iBAAiB;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AAEA,aAAW,SAAS,QAAQ;AAC1B,iBAAa,KAAK;AAAA,EACpB;AAEA,SAAO;AACT;AAeO,SAAS,cAAc,MAAsB;AAElD,MAAI,aAAa,mBAAmB,IAAI;AAGxC,eAAa,WAAW,QAAQ,QAAQ,GAAG;AAG3C,MAAI,eAAe,GAAI,QAAO;AAG9B,MAAI,eAAe,OAAO,WAAW,SAAS,GAAG,GAAG;AAClD,iBAAa,WAAW,MAAM,GAAG,EAAE;AAAA,EACrC;AAEA,SAAO;AACT;","names":[]}
|
package/dist/server/index.js
CHANGED
|
@@ -8,8 +8,9 @@ function flattenNestedRoutes(routes) {
|
|
|
8
8
|
...route.middleware || []
|
|
9
9
|
];
|
|
10
10
|
if ("method" in route && "handler" in route) {
|
|
11
|
+
const leafRoute = route;
|
|
11
12
|
flattened.push({
|
|
12
|
-
...
|
|
13
|
+
...leafRoute,
|
|
13
14
|
fullPath: currentPath,
|
|
14
15
|
middlewareChain: currentMiddleware
|
|
15
16
|
});
|
|
@@ -450,6 +451,131 @@ var RadixRouter = class {
|
|
|
450
451
|
}
|
|
451
452
|
};
|
|
452
453
|
|
|
454
|
+
// src/utils/route-registry.ts
|
|
455
|
+
var RouteRegistry = class {
|
|
456
|
+
/** 所有路由元信息 */
|
|
457
|
+
routes = [];
|
|
458
|
+
/** 路由映射表:METHOD:fullPath -> RouteMeta */
|
|
459
|
+
routeMap = /* @__PURE__ */ new Map();
|
|
460
|
+
/** 分类映射表:category -> RouteMeta[] */
|
|
461
|
+
categoryMap = /* @__PURE__ */ new Map();
|
|
462
|
+
constructor(routes) {
|
|
463
|
+
this.buildRegistry(routes);
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* 构建注册表
|
|
467
|
+
*/
|
|
468
|
+
buildRegistry(routes) {
|
|
469
|
+
for (const route of routes) {
|
|
470
|
+
const meta = {
|
|
471
|
+
method: route.method,
|
|
472
|
+
path: route.path,
|
|
473
|
+
fullPath: route.fullPath,
|
|
474
|
+
name: route.name,
|
|
475
|
+
description: route.description
|
|
476
|
+
};
|
|
477
|
+
for (const key of Object.keys(route)) {
|
|
478
|
+
if (!["method", "path", "fullPath", "name", "description", "handler", "middleware", "middlewareChain"].includes(key)) {
|
|
479
|
+
meta[key] = route[key];
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
this.routes.push(meta);
|
|
483
|
+
this.routeMap.set(`${route.method}:${route.fullPath}`, meta);
|
|
484
|
+
const category = this.extractCategory(route.fullPath);
|
|
485
|
+
if (!this.categoryMap.has(category)) {
|
|
486
|
+
this.categoryMap.set(category, []);
|
|
487
|
+
}
|
|
488
|
+
this.categoryMap.get(category).push(meta);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* 提取分类(第一段路径)
|
|
493
|
+
*/
|
|
494
|
+
extractCategory(path) {
|
|
495
|
+
const segments = path.split("/").filter(Boolean);
|
|
496
|
+
return segments[0] || "root";
|
|
497
|
+
}
|
|
498
|
+
// ============================================
|
|
499
|
+
// 查询接口
|
|
500
|
+
// ============================================
|
|
501
|
+
/**
|
|
502
|
+
* 获取所有路由元信息
|
|
503
|
+
*/
|
|
504
|
+
getAll() {
|
|
505
|
+
return [...this.routes];
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* 按 method + path 查询路由
|
|
509
|
+
*/
|
|
510
|
+
get(method, path) {
|
|
511
|
+
return this.routeMap.get(`${method}:${path}`);
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* 检查路由是否存在
|
|
515
|
+
*/
|
|
516
|
+
has(method, path) {
|
|
517
|
+
return this.routeMap.has(`${method}:${path}`);
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* 按分类获取路由
|
|
521
|
+
*/
|
|
522
|
+
getByCategory(category) {
|
|
523
|
+
return this.categoryMap.get(category) || [];
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* 获取所有分类
|
|
527
|
+
*/
|
|
528
|
+
getCategories() {
|
|
529
|
+
return Array.from(this.categoryMap.keys()).sort();
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* 筛选有特定字段的路由
|
|
533
|
+
*
|
|
534
|
+
* @example
|
|
535
|
+
* ```typescript
|
|
536
|
+
* // 获取所有配置了 webhook 的路由
|
|
537
|
+
* const webhookRoutes = registry.filter('webhook')
|
|
538
|
+
* ```
|
|
539
|
+
*/
|
|
540
|
+
filter(field) {
|
|
541
|
+
return this.routes.filter((r) => field in r && r[field] !== void 0);
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* 按条件筛选路由
|
|
545
|
+
*
|
|
546
|
+
* @example
|
|
547
|
+
* ```typescript
|
|
548
|
+
* // 获取所有 POST 请求
|
|
549
|
+
* const postRoutes = registry.filterBy(r => r.method === 'POST')
|
|
550
|
+
* ```
|
|
551
|
+
*/
|
|
552
|
+
filterBy(predicate) {
|
|
553
|
+
return this.routes.filter(predicate);
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* 获取路由数量
|
|
557
|
+
*/
|
|
558
|
+
get size() {
|
|
559
|
+
return this.routes.length;
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* 遍历所有路由
|
|
563
|
+
*/
|
|
564
|
+
forEach(callback) {
|
|
565
|
+
this.routes.forEach(callback);
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* 映射所有路由
|
|
569
|
+
*/
|
|
570
|
+
map(callback) {
|
|
571
|
+
return this.routes.map(callback);
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
var globalRegistry = null;
|
|
575
|
+
function setGlobalRegistry(registry) {
|
|
576
|
+
globalRegistry = registry;
|
|
577
|
+
}
|
|
578
|
+
|
|
453
579
|
// src/server/server.ts
|
|
454
580
|
var Server = class extends BaseServer {
|
|
455
581
|
router;
|
|
@@ -495,6 +621,7 @@ var Server = class extends BaseServer {
|
|
|
495
621
|
if (this.globalMiddleware.length === 0 && !this.isCompiled) {
|
|
496
622
|
this.compile();
|
|
497
623
|
}
|
|
624
|
+
setGlobalRegistry(new RouteRegistry(this.routes));
|
|
498
625
|
}
|
|
499
626
|
/** 快速提取 pathname */
|
|
500
627
|
extractPathname(url) {
|
|
@@ -584,6 +711,22 @@ var Server = class extends BaseServer {
|
|
|
584
711
|
getRoutes() {
|
|
585
712
|
return this.router.getRoutes();
|
|
586
713
|
}
|
|
714
|
+
/**
|
|
715
|
+
* 获取完整的路由元信息(不含 handler 和 middleware)
|
|
716
|
+
*
|
|
717
|
+
* 用于 API 文档生成、Webhook 事件注册、权限检查等场景
|
|
718
|
+
*
|
|
719
|
+
* @example
|
|
720
|
+
* ```typescript
|
|
721
|
+
* const routes = server.getRoutesWithMeta()
|
|
722
|
+
* for (const route of routes) {
|
|
723
|
+
* console.log(route.fullPath, route.name, route.description)
|
|
724
|
+
* }
|
|
725
|
+
* ```
|
|
726
|
+
*/
|
|
727
|
+
getRoutesWithMeta() {
|
|
728
|
+
return this.routes;
|
|
729
|
+
}
|
|
587
730
|
};
|
|
588
731
|
|
|
589
732
|
// src/middleware/component-router.ts
|