X-Git-Url: https://git.ayoreis.com/relax.git/blobdiff_plain/d7baaea4f90491d77b416fbf53935e090bbf7f7f..fe577bd4aabb6f5e3f6c8a20bedb65c316bf1e23:/relax/router.ts?ds=inline diff --git a/relax/router.ts b/relax/router.ts index e69de29..b97794d 100644 --- a/relax/router.ts +++ b/relax/router.ts @@ -0,0 +1,77 @@ +import URLPatternList, { + type URLPatternListResult, +} from "./url-pattern-list.ts"; + +type MaybePromise = Promise | Type; +type Handler = ( + request: Request, + result: URLPatternListResult, +) => MaybePromise; + +interface Route { + readonly method: string; + readonly handler: Handler; +} + +type Pattern = URLPatternInit | string; + +export default class { + #list: URLPatternList | null = null; + #routes = new Map(); + + add(method: string, pattern: Pattern, handler: Handler) { + const url_pattern = typeof pattern === "string" + ? new URLPattern({ pathname: pattern }) + : new URLPattern(pattern); + this.#routes.set(url_pattern, { method, handler }); + this.#list = null; + } + + get(pattern: Pattern, handler: Handler) { + this.add("GET", pattern, handler); + } + + head(pattern: Pattern, handler: Handler) { + this.add("HEAD", pattern, handler); + } + + post(pattern: Pattern, handler: Handler) { + this.add("POST", pattern, handler); + } + + put(pattern: Pattern, handler: Handler) { + this.add("PUT", pattern, handler); + } + + delete(pattern: Pattern, handler: Handler) { + this.add("DELETE", pattern, handler); + } + + connect(pattern: Pattern, handler: Handler) { + this.add("CONNECT", pattern, handler); + } + + options(pattern: Pattern, handler: Handler) { + this.add("OPTIONS", pattern, handler); + } + + trace(pattern: Pattern, handler: Handler) { + this.add("TRACE", pattern, handler); + } + + patch(pattern: Pattern, handler: Handler) { + this.add("PATCH", pattern, handler); + } + + handle(request: Request) { + this.#list ??= new URLPatternList([...this.#routes.keys()]); + + for (const result of this.#list.exec(request.url)) { + const route = this.#routes.get(result.pattern)!; + if (route.method !== request.method) continue; + return route.handler(request, result); + } + + return new Response(null, { status: 404 }); + } +}