bun-serve-route-plus
Version:
Middleware & route group system for Bun's HTTP server
84 lines (81 loc) • 2.9 kB
text/typescript
type HTTPMethodHandler = (request: Request, env?:any, ctx?:any) => Promise<Response> | Response;
type HTTPMethod = {
GET?: HTTPMethodHandler;
POST?: HTTPMethodHandler;
OPTIONS?: HTTPMethodHandler;
HEAD?: HTTPMethodHandler;
DELETE?: HTTPMethodHandler;
PATCH?: HTTPMethodHandler;
PUT?: HTTPMethodHandler;
} | HTTPMethodHandler;
export type BunRoutes = {
[x: string]: HTTPMethod;
};
type ResponseHandler = (response:Response) => Promise<Response> | Response
type RequestHandler = (request:Request, env?:any, ctx?:any) => Promise<Response> | Response | void
class BeforeRequest {
private middlewareList: RequestHandler[];
constructor() {
this.middlewareList = [];
}
use(func: RequestHandler) {
this.middlewareList.push(func);
}
async execute(request: Request, env: any, ctx: any): Promise<Response | null> {
for (const middleware of this.middlewareList) {
const result = await middleware(request, env, ctx);
if (result instanceof Response) {
return result;
}
}
return null;
}
}
class BeforeResponse {
private middlewareList: ResponseHandler[];
constructor() {
this.middlewareList = [];
}
use(func: ResponseHandler) {
this.middlewareList.push(func);
}
async execute(response: Response): Promise<Response> {
for (const middleware of this.middlewareList) {
response = await middleware(response);
}
return response;
}
}
export const useMiddleware = (...args:BunRoutes[]):BunRoutes => {
const excu = (func:HTTPMethodHandler) => async (request: Request, env: any, ctx: any) => {
const requestMiddlewareResponse = await beforeRequest.execute(request, env, ctx);
if (requestMiddlewareResponse) {
return requestMiddlewareResponse;
}
const response = await func(request, env, ctx);
return await beforeResponse.execute(response)
}
const handleMethods = (methods: HTTPMethod):HTTPMethod =>
typeof methods == 'function' ?
excu(methods) :
Object.fromEntries(
Object.entries(methods)
.filter(([_method, handler]) => !!handler)
.concat([['OPTIONS', () => new Response()]])
.map(([method, handler]) => [method,excu(handler!)])
)
const BunRoutesr:BunRoutes = Object.assign({}, ...args)
return Object.fromEntries(
Object.entries(BunRoutesr).map(([route, methods]) => [route, handleMethods(methods)])
)
}
export const useGroup = (prefix:string = '', ...args: BunRoutes[] ) => {
const routes:BunRoutes = Object.assign({}, ...args)
return Object.fromEntries(
Object.entries(routes).map(([route, methods]) => [('/'+ prefix + route).replace('//','/'), methods])
)
}
export const beforeRequest = new BeforeRequest()
export const beforeResponse = new BeforeResponse()
export const m = useMiddleware
export const g = useGroup