refactor router to use array for route storage and improve route handling
This commit is contained in:
		@@ -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