tests passing
This commit is contained in:
115
router.new.ts
115
router.new.ts
@@ -1,11 +1,12 @@
|
||||
import type { RouterContext as oldContext } from "@bearmetal/router/types";
|
||||
import { joinPaths } from "./util/join.ts";
|
||||
import { InternalError, NotFound } from "@bearmetal/router/util/response";
|
||||
|
||||
type RouterContext = Omit<oldContext, "pattern">;
|
||||
type Handler = (
|
||||
req: Request,
|
||||
ctx: RouterContext,
|
||||
next: () => Promise<void | Response> | null,
|
||||
next: () => Promise<Response>,
|
||||
) => Promise<Response>;
|
||||
type RouteConfigurator = {
|
||||
get(handler: Handler): RouteConfigurator;
|
||||
@@ -95,44 +96,93 @@ export class Router {
|
||||
return configurator;
|
||||
}
|
||||
|
||||
get(path: string, handler: Handler) {
|
||||
path = fixPath(path);
|
||||
get(handler: Handler): void;
|
||||
get(path: string, handler: Handler): void;
|
||||
get(path: string | Handler, handler?: Handler): void {
|
||||
if (typeof path !== "string") {
|
||||
handler = path;
|
||||
path = "/.*";
|
||||
} else {
|
||||
path = fixPath(path);
|
||||
}
|
||||
const config = this.getOrCreateConfig(path);
|
||||
this.getOrCreateConfigHandlers(GET, config).push(handler);
|
||||
this.getOrCreateConfigHandlers(GET, config).push(handler!);
|
||||
}
|
||||
post(path: string, handler: Handler) {
|
||||
path = fixPath(path);
|
||||
post(handler: Handler): void;
|
||||
post(path: string, handler: Handler): void;
|
||||
post(path: string | Handler, handler?: Handler): void {
|
||||
if (typeof path !== "string") {
|
||||
handler = path;
|
||||
path = "/.*";
|
||||
} else {
|
||||
path = fixPath(path);
|
||||
}
|
||||
const config = this.getOrCreateConfig(path);
|
||||
this.getOrCreateConfigHandlers(POST, config).push(handler);
|
||||
this.getOrCreateConfigHandlers(POST, config).push(handler!);
|
||||
}
|
||||
put(path: string, handler: Handler) {
|
||||
path = fixPath(path);
|
||||
put(handler: Handler): void;
|
||||
put(path: string, handler: Handler): void;
|
||||
put(path: string | Handler, handler?: Handler): void {
|
||||
if (typeof path !== "string") {
|
||||
handler = path;
|
||||
path = "/.*";
|
||||
} else {
|
||||
path = fixPath(path);
|
||||
}
|
||||
const config = this.getOrCreateConfig(path);
|
||||
this.getOrCreateConfigHandlers(PUT, config).push(handler);
|
||||
this.getOrCreateConfigHandlers(PUT, config).push(handler!);
|
||||
}
|
||||
patch(path: string, handler: Handler) {
|
||||
path = fixPath(path);
|
||||
patch(handler: Handler): void;
|
||||
patch(path: string, handler: Handler): void;
|
||||
patch(path: string | Handler, handler?: Handler): void {
|
||||
if (typeof path !== "string") {
|
||||
handler = path;
|
||||
path = "/.*";
|
||||
} else {
|
||||
path = fixPath(path);
|
||||
}
|
||||
const config = this.getOrCreateConfig(path);
|
||||
this.getOrCreateConfigHandlers(PATCH, config).push(handler);
|
||||
this.getOrCreateConfigHandlers(PATCH, config).push(handler!);
|
||||
}
|
||||
delete(path: string, handler: Handler) {
|
||||
path = fixPath(path);
|
||||
delete(handler: Handler): void;
|
||||
delete(path: string, handler: Handler): void;
|
||||
delete(path: string | Handler, handler?: Handler): void {
|
||||
if (typeof path !== "string") {
|
||||
handler = path;
|
||||
path = "/.*";
|
||||
} else {
|
||||
path = fixPath(path);
|
||||
}
|
||||
const config = this.getOrCreateConfig(path);
|
||||
this.getOrCreateConfigHandlers(DELETE, config).push(handler);
|
||||
this.getOrCreateConfigHandlers(DELETE, config).push(handler!);
|
||||
}
|
||||
options(path: string, handler: Handler) {
|
||||
path = fixPath(path);
|
||||
options(handler: Handler): void;
|
||||
options(path: string, handler: Handler): void;
|
||||
options(path: string | Handler, handler?: Handler): void {
|
||||
if (typeof path !== "string") {
|
||||
handler = path;
|
||||
path = "/.*";
|
||||
} else {
|
||||
path = fixPath(path);
|
||||
}
|
||||
const config = this.getOrCreateConfig(path);
|
||||
this.getOrCreateConfigHandlers(OPTIONS, config).push(handler);
|
||||
this.getOrCreateConfigHandlers(OPTIONS, config).push(handler!);
|
||||
}
|
||||
|
||||
use(path: string, handler: Handler | Router) {
|
||||
path = fixPath(path);
|
||||
use(handler: Handler | Router): void;
|
||||
use(path: string, handler: Handler | Router): void;
|
||||
use(path: string | Handler | Router, handler?: Handler | Router): void {
|
||||
if (typeof path !== "string") {
|
||||
handler = path;
|
||||
path = "/.*";
|
||||
} else {
|
||||
path = fixPath(path);
|
||||
}
|
||||
if (handler instanceof Router) {
|
||||
return this.resolveRouterHandlerStack(path, handler);
|
||||
}
|
||||
const config = this.getOrCreateConfig(path);
|
||||
this.getOrCreateConfigHandlers(_use, config).push(handler);
|
||||
this.getOrCreateConfigHandlers(_use, config).push(handler!);
|
||||
}
|
||||
|
||||
private getOrCreateConfig(path: string): RouteConfig {
|
||||
@@ -142,6 +192,7 @@ export class Router {
|
||||
handlers: {},
|
||||
pattern: new URLPattern({ pathname: path }),
|
||||
};
|
||||
this.routes.set(path, config);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
@@ -172,12 +223,16 @@ export class Router {
|
||||
const url = new URL(req.url);
|
||||
const method = req.method;
|
||||
|
||||
const matchingRoutes = this.findMatchingRoutes(url).filter((r) =>
|
||||
Object.hasOwn(r.config.handlers, method) ||
|
||||
Object.hasOwn(r.config.handlers, _use)
|
||||
const matchingRoutes = this.findMatchingRoutes(url);
|
||||
if (!matchingRoutes.length) return NotFound();
|
||||
const matchingMethods = matchingRoutes.some((r) =>
|
||||
Object.hasOwn(r.config.handlers, method)
|
||||
);
|
||||
if (!matchingMethods) {
|
||||
return new Response("Method Not Allowed", { status: 405 });
|
||||
}
|
||||
const middlewareStack = matchingRoutes.flatMap((r) =>
|
||||
r.config.handlers[method]
|
||||
(r.config.handlers[_use] ?? []).concat(r.config.handlers[method] ?? [])
|
||||
);
|
||||
const ctx: RouterContext = {
|
||||
url,
|
||||
@@ -189,7 +244,11 @@ export class Router {
|
||||
let index = 0;
|
||||
const executeMiddleware = async (): Promise<Response> => {
|
||||
if (index < middlewareStack.length) {
|
||||
const res = await middlewareStack[index++](req, ctx, executeMiddleware);
|
||||
const res = await middlewareStack[index++]?.(
|
||||
req,
|
||||
ctx,
|
||||
executeMiddleware,
|
||||
);
|
||||
if (res instanceof Response) return res;
|
||||
}
|
||||
return new Response("End of stack", { status: 501 });
|
||||
@@ -197,7 +256,7 @@ export class Router {
|
||||
try {
|
||||
return await executeMiddleware();
|
||||
} catch {
|
||||
return new Response("Internal Server Error", { status: 500 });
|
||||
return InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user