@bureaudouble/routeur@0.1.12
latest
It is unknown whether this package works with Cloudflare Workers, Node.js, Deno, Bun, Browsers




JSR Score
35%
Published
2 months ago (0.1.12)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162import { type Route as StdRoute, route } from "jsr:/@std/http@^1.0.20/unstable-route"; export interface Route<TState = unknown> extends Omit<StdRoute, "handler"> { handler: HandleRequest<TState>; } export interface Context<TState = unknown> { request: Request; params: URLPatternResult | undefined; next: () => Promise<Response>; url: URL; info: Deno.ServeHandlerInfo | undefined; state: TState; } export type HandleRequest<TState = unknown> = ( context: Context<TState>, ) => Response | Promise<Response>; export type HandleDefault = () => Response | Promise<Response>; export type HandleError = (error: Error) => Response | Promise<Response>; // Router interface that defines the shape of the router object export interface Router<TState = unknown> { routes: Route<TState>[]; initializeState: () => TState; handleDefault: HandleDefault; handleError: HandleError; fetch: ( request: Request, info?: Deno.ServeHandlerInfo, state?: TState, ) => Promise<Response>; state: (defaultState: () => TState) => Router<TState>; with: (route: Route<TState>) => Router<TState>; on: ( method: string | string[] | undefined, pathname: string, handler: HandleRequest<TState>, ) => Router<TState>; use: (data: Route<TState>[] | Router<TState>) => Router<TState>; default: (handle: HandleDefault) => Router<TState>; error: (handle: HandleError) => Router<TState>; connect: (pathname: string, handler: HandleRequest<TState>) => Router<TState>; delete: (pathname: string, handler: HandleRequest<TState>) => Router<TState>; get: (pathname: string, handler: HandleRequest<TState>) => Router<TState>; head: (pathname: string, handler: HandleRequest<TState>) => Router<TState>; options: (pathname: string, handler: HandleRequest<TState>) => Router<TState>; patch: (pathname: string, handler: HandleRequest<TState>) => Router<TState>; post: (pathname: string, handler: HandleRequest<TState>) => Router<TState>; put: (pathname: string, handler: HandleRequest<TState>) => Router<TState>; trace: (pathname: string, handler: HandleRequest<TState>) => Router<TState>; } // Default handlers const defaultNotFoundHandler = (): Response => new Response("Not found", { status: 404 }); const defaultErrorHandler = (error: Error): Response => new Response(error.message, { status: 500 }); // Create router function with explicit return type export const createRouter = <TState = unknown>(): Router<TState> => { // Execute function (implementation detail) const execute = ( router: Router<TState>, i: number, request: Request, info: Deno.ServeHandlerInfo | undefined, state: TState, ): Response | Promise<Response> => { if (i >= router.routes.length) { return router.handleDefault(); } const next = async () => await execute(router, i + 1, request, info, state); const { method, pattern, handler } = router.routes[i]; const handle = route( [ { method, pattern, handler: (request, params, info) => { const url = new URL(request.url); return handler({ request, params, url, info, next, state }); }, }, ], () => next(), ); return handle(request, info); }; // Create the router object const router: Router<TState> = { routes: [], initializeState: () => ({}) as TState, handleDefault: defaultNotFoundHandler, handleError: defaultErrorHandler, fetch: async (request, info, state) => { try { return await execute( router, 0, request, info, state ?? router.initializeState(), ); } catch (error) { if (error instanceof Error) { return await router.handleError(error); } throw error; } }, state: (defaultState) => { router.initializeState = defaultState; return router; }, with: (routeToAdd) => { router.routes.push(routeToAdd); return router; }, on: (method, pathname, handler) => { const pattern = new URLPattern({ pathname }); return router.with({ method, pattern, handler }); }, use: (data) => { if (Array.isArray(data)) { router.routes.push(...data); } else { router.routes.push(...data.routes); } return router; }, default: (handle) => { router.handleDefault = handle; return router; }, error: (handle) => { router.handleError = handle; return router; }, connect: (pathname, handler) => router.on("CONNECT", pathname, handler), delete: (pathname, handler) => router.on("DELETE", pathname, handler), get: (pathname, handler) => router.on("GET", pathname, handler), head: (pathname, handler) => router.on("HEAD", pathname, handler), options: (pathname, handler) => router.on("OPTIONS", pathname, handler), patch: (pathname, handler) => router.on("PATCH", pathname, handler), post: (pathname, handler) => router.on("POST", pathname, handler), put: (pathname, handler) => router.on("PUT", pathname, handler), trace: (pathname, handler) => router.on("TRACE", pathname, handler), }; return router satisfies Deno.ServeDefaultExport; };