refactor router to use array for route storage and improve route handling
This commit is contained in:
		
							
								
								
									
										5
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							| @@ -50,9 +50,8 @@ export default class Flummpress { | ||||
|                 yield this.processPipeline(this.middleware, req, res); | ||||
|                 const route = this.router.getRoute(req.url.pathname, req.method); | ||||
|                 if (route) { | ||||
|                     const [pathPattern, methods] = route; | ||||
|                     const handler = methods[(_a = req.method) === null || _a === void 0 ? void 0 : _a.toLowerCase()]; | ||||
|                     req.params = ((_b = req.url.pathname.match(new RegExp(pathPattern))) === null || _b === void 0 ? void 0 : _b.groups) || {}; | ||||
|                     const handler = route.methods[(_a = req.method) === null || _a === void 0 ? void 0 : _a.toLowerCase()]; | ||||
|                     req.params = ((_b = req.url.pathname.match(new RegExp(route.path))) === null || _b === void 0 ? void 0 : _b.groups) || {}; | ||||
|                     req.post = yield this.readBody(req); | ||||
|                     yield this.processPipeline(handler, req, res); | ||||
|                 } | ||||
|   | ||||
							
								
								
									
										46
									
								
								dist/router.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										46
									
								
								dist/router.js
									
									
									
									
										vendored
									
									
								
							| @@ -12,7 +12,8 @@ import path from "node:path"; | ||||
| import Tpl from "./template.js"; | ||||
| export default class Router { | ||||
|     constructor() { | ||||
|         this.routes = new Map(); | ||||
|         this.routes = []; | ||||
|         this.routes; | ||||
|         this.mimes = new Map(); | ||||
|     } | ||||
|     importRoutesFromPath(p_1) { | ||||
| @@ -70,7 +71,6 @@ export default class Router { | ||||
|     } | ||||
|     use(obj) { | ||||
|         if (obj instanceof Router) { | ||||
|             this.routes = new Map([...this.routes, ...obj.routes]); | ||||
|             this.sortRoutes(); | ||||
|         } | ||||
|         if (obj instanceof Tpl) { | ||||
| @@ -102,27 +102,47 @@ export default class Router { | ||||
|         return this; | ||||
|     } | ||||
|     registerRoute(path, method, handler) { | ||||
|         var _a; | ||||
|         const route = (_a = this.routes.get(path)) !== null && _a !== void 0 ? _a : { | ||||
|             [method]: handler | ||||
|         }; | ||||
|         this.routes.set(path, route); | ||||
|         const existingRoute = this.routes.find(route => typeof route.path === "string" | ||||
|             ? route.path === path | ||||
|             : route.path instanceof RegExp && path instanceof RegExp && route.path.toString() === path.toString()); | ||||
|         if (existingRoute) { | ||||
|             existingRoute.methods[method] = [ | ||||
|                 ...(existingRoute.methods[method] || []), | ||||
|                 ...handler | ||||
|             ]; | ||||
|         } | ||||
|         else { | ||||
|             this.routes.push({ | ||||
|                 path, | ||||
|                 methods: { [method]: handler } | ||||
|             }); | ||||
|         } | ||||
|         console.log("route set:", method.toUpperCase(), path); | ||||
|         this.sortRoutes(); | ||||
|         return this; | ||||
|     } | ||||
|     getRoute(path, method) { | ||||
|         return [...this.routes.entries()] | ||||
|         return this.routes | ||||
|             .find(r => { | ||||
|             var _a, _b; | ||||
|             return typeof r[0] === "string" | ||||
|                 ? r[0] === path | ||||
|                 : ((_b = (_a = r[0]).exec) === null || _b === void 0 ? void 0 : _b.call(_a, path)) | ||||
|                     && r[1][method.toLowerCase()]; | ||||
|             return typeof r.path === "string" | ||||
|                 ? r.path === path | ||||
|                 : ((_b = (_a = r.path).exec) === null || _b === void 0 ? void 0 : _b.call(_a, path)) | ||||
|                     && r.methods[method.toLowerCase()]; | ||||
|         }); | ||||
|     } | ||||
|     sortRoutes() { | ||||
|         this.routes = new Map([...this.routes.entries()].sort().reverse()); | ||||
|         this.routes.sort((a, b) => { | ||||
|             const aLength = typeof a.path === "string" ? a.path.length : a.path.source.length; | ||||
|             const bLength = typeof b.path === "string" ? b.path.length : b.path.source.length; | ||||
|             if (typeof a.path === "string" && typeof b.path === "string") | ||||
|                 return bLength - aLength; | ||||
|             if (typeof a.path === "string") | ||||
|                 return -1; | ||||
|             if (typeof b.path === "string") | ||||
|                 return 1; | ||||
|             return bLength - aLength; | ||||
|         }); | ||||
|         return this; | ||||
|     } | ||||
|     readMimes(file = "/etc/mime.types") { | ||||
|   | ||||
| @@ -89,10 +89,9 @@ export default class Flummpress { | ||||
|         const route = this.router.getRoute(req.url.pathname, req.method!); | ||||
|    | ||||
|         if(route) { | ||||
|           const [pathPattern, methods] = route; | ||||
|           const handler = methods[req.method?.toLowerCase()!]; | ||||
|           const handler = route.methods[req.method?.toLowerCase()!]; | ||||
|    | ||||
|           req.params = req.url.pathname.match(new RegExp(pathPattern))?.groups || {}; | ||||
|           req.params = req.url.pathname.match(new RegExp(route.path))?.groups || {}; | ||||
|           req.post = await this.readBody(req); | ||||
|           await this.processPipeline(handler, req, res); | ||||
|         } | ||||
|   | ||||
| @@ -5,12 +5,11 @@ import Tpl from "./template.js"; | ||||
| import { Request, Response, Handler } from "./types.js"; | ||||
|  | ||||
| export default class Router { | ||||
|   private routes: Map<RegExp | string, { [key: string]: Handler[] }>; | ||||
|   private routes: Array<{ path: string | RegExp; methods: { [method: string]: Handler[] } }> = []; | ||||
|   private tpl?: Tpl; | ||||
|   private mimes: Map<string, string>; | ||||
|  | ||||
|   constructor() { | ||||
|     this.routes = new Map(); | ||||
|     this.mimes = new Map(); | ||||
|   } | ||||
|  | ||||
| @@ -96,7 +95,7 @@ export default class Router { | ||||
|    */ | ||||
|   use(obj: Router | Tpl): void { | ||||
|     if(obj instanceof Router) { | ||||
|       this.routes = new Map([...this.routes, ...obj.routes]); | ||||
|       this.routes = { ...this.routes, ...obj.routes }; | ||||
|       this.sortRoutes(); | ||||
|     } | ||||
|     if(obj instanceof Tpl) { | ||||
| @@ -181,10 +180,24 @@ export default class Router { | ||||
|     method: string, | ||||
|     handler: Handler[] | ||||
|   ): this { | ||||
|     const route: { [key: string]: Handler[] } = this.routes.get(path) ?? { | ||||
|       [ method ]: handler | ||||
|     }; | ||||
|     this.routes.set(path, route); | ||||
|     const route = this.routes.find(route => | ||||
|       typeof route.path === "string" | ||||
|         ? route.path === path | ||||
|         : route.path instanceof RegExp && path instanceof RegExp && route.path.toString() === path.toString() | ||||
|     ); | ||||
|    | ||||
|     if(route) { | ||||
|       route.methods[method] = [ | ||||
|         ...(route.methods[method] || []), | ||||
|         ...handler | ||||
|       ]; | ||||
|     } | ||||
|     else { | ||||
|       this.routes.push({ | ||||
|         path, | ||||
|         methods: { [method]: handler } | ||||
|       }); | ||||
|     } | ||||
|  | ||||
|     console.log("route set:", method.toUpperCase(), path); | ||||
|     this.sortRoutes(); | ||||
| @@ -198,11 +211,11 @@ export default class Router { | ||||
|    * @returns The matching route or undefined. | ||||
|    */ | ||||
|   getRoute(path: string, method: string): any { | ||||
|     return [...this.routes.entries()] | ||||
|       .find(r => typeof r[0] === "string" | ||||
|         ? r[0] === path | ||||
|         : r[0].exec?.(path) | ||||
|        && r[1][method.toLowerCase()] | ||||
|     return this.routes | ||||
|       .find(r => typeof r.path === "string" | ||||
|         ? r.path === path | ||||
|         : r.path.exec?.(path) | ||||
|       && r.methods[method.toLowerCase()] | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| @@ -211,7 +224,18 @@ export default class Router { | ||||
|    * @returns The Router instance for chaining. | ||||
|    */ | ||||
|   private sortRoutes(): this { | ||||
|     this.routes = new Map([...this.routes.entries()].sort().reverse()); | ||||
|     this.routes.sort((a, b) => { | ||||
|       const aLength = typeof a.path === "string" ? a.path.length : a.path.source.length; | ||||
|       const bLength = typeof b.path === "string" ? b.path.length : b.path.source.length; | ||||
|    | ||||
|       if(typeof a.path === "string" && typeof b.path === "string") | ||||
|         return bLength - aLength; | ||||
|       if(typeof a.path === "string") | ||||
|         return -1; | ||||
|       if(typeof b.path === "string") | ||||
|         return 1; | ||||
|       return bLength - aLength; | ||||
|     }); | ||||
|     return this; | ||||
|   } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user