diesel-core 0.0.10 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,56 +1,149 @@
1
1
  # DieselJS
2
2
 
3
- **Diesel** is a simple and lightweight HTTP server library for Bunjs, designed to give you control over your API routes and middleware in an intuitive and efficient way. With DieselJS, you can quickly set up a server, define routes, and optimize important routes for faster response times.
3
+ **made only for bun***
4
4
 
5
+ **Diesel** is a simple and lightweight HTTP server library for Bun.js that provides you with complete control over your API routes and middleware. It is designed to be intuitive and efficient, allowing you to quickly set up a server, define routes, and optimize important paths for faster response times.
6
+
7
+ With built-in support for TypeScript, DieselJS ensures type safety and improved developer experience, making it easier to catch errors during development. Whether you are building a small application or a large API, DieselJS helps you manage your routes and middleware seamlessly.
5
8
 
6
- ## Installation
7
9
 
8
- Install diesel-core via bun, npm , yarn , pnpm :
10
+ ## Installation
11
+ Install diesel-core via bun | npm | yarn | pnpm
9
12
 
10
13
  ```bash
11
14
  npm install diesel-core
15
+ ```
16
+ ```bash
17
+ bun add diesel-core
18
+ ```
12
19
 
13
- import diesel from "diesel-core";
14
- import { hello } from "./hello.js";
15
-
16
- const maya = new diesel();
17
- const port = 3000;
18
-
19
- // Middleware example
20
- app.use(hello);
20
+ ### Code Example
21
+ ```javascript
22
+ import { Diesel } from "diesel-core"
21
23
 
24
+ const app = new Diesel()
25
+ const port = 3000
22
26
 
23
27
  app.get("/", async (xl) => {
24
28
  return xl.status(200).text("Hello world...!")
25
- OR
26
- return xl.text("Hello world!")
27
- OR
28
- return new Response("Hello world")
29
- });
29
+ // OR
30
+ // return xl.text("Hello world!")
31
+ // OR
32
+ // return new Response("Hello world")
33
+ })
30
34
 
31
- // Render a HTML page
32
- app.get("/render",async (xl) => {
33
- return xl.html(`${import.meta.dir}/index.html`);
35
+ // Start the server
36
+ app.listen(port, () => {
37
+ console.log(`diesel is running on port ${port}`)
38
+ })
39
+
40
+ ```
41
+
42
+ ## Using Hooks in DieselJS
43
+
44
+ DieselJS allows you to enhance your request handling by utilizing hooks at various stages of the request lifecycle. This gives you the flexibility to execute custom logic for logging, authentication, data manipulation, and more.
45
+
46
+ ### Available Hooks
47
+
48
+ 1. **onRequest**: Triggered when a request is received.
49
+ 2. **preHandler**: Invoked just before the request handler executes.
50
+ 3. **postHandler**: Executed after the request handler completes but before sending the response.
51
+ 4. **onSend**: Called just before the response is sent to the client.
52
+
53
+ ### How to Define Hooks
54
+
55
+ To define hooks in your DieselJS application, you can add them directly to your `Diesel` instance. Here's how to set up and use each hook:
56
+
57
+ ### Example Usage
58
+
59
+ ```javascript
60
+ // Define an onRequest hook
61
+ app.addHooks("onRequest",(xl) =>{
62
+ console.log(`Request received: ${xl.req.method} ${xl.req.url}`);
63
+ })
64
+
65
+ // Define a preHandler hook
66
+ app.addHooks("preHandler",(xl) =>{
67
+ // Check for authentication token
68
+ const authToken = ctx.req.headers.get("Authorization");
69
+ if (!authToken) {
70
+ return new Response("Unauthorized", { status: 401 });
71
+ }
72
+ })
73
+
74
+ // Define a postHandler hook
75
+ app.addHooks('postHandler', async (ctx) => {
76
+ console.log(`Response sent for: ${ctx.req.url}`);
34
77
  });
35
78
 
36
- app.get("/async-test",async (xl) => {
37
- await new Promise((resolve) => setTimeout(resolve, 1000));
38
- return xl.json({ message: "Async operation completed" },200);
79
+ // Define an onSend hook
80
+ app.addHooks('onSend',async (ctx, result) => {
81
+ console.log(`Sending response with status: ${result.status}`);
82
+ return result; // You can modify the response here if needed
39
83
  });
84
+ ```
85
+
86
+ # Middleware example
87
+
88
+ ```javascript
89
+ function h (xl) => {
90
+ return xl.status(200).text("hi im from middleware")
91
+ }
92
+ app.use(hello)
93
+
94
+ // path middleware example
95
+ app.use("/user",authJWT)
96
+
97
+ ```
98
+
99
+ # set cookies
100
+
101
+ ```javascript
102
+ app.get("/set-cookie", async(xl) => {
103
+ const user = {
104
+ name: "pk",
105
+ age: 22,
106
+ }
107
+
108
+ const accessToken = jwt.sign(user, secret, { expiresIn: "1d" })
109
+
110
+ const refreshToken = jwt.sign(user, secret ,{ expiresIn: "10d" })
111
+
112
+ const options = {
113
+ httpOnly: true,
114
+ secure: true,
115
+ maxAge: 24 * 60 * 60 * 1000,
116
+ sameSite: "Strict",
117
+ path: "/",
118
+ }
40
119
 
120
+ await xl.cookie("accessToken", accessToken, options)
41
121
 
122
+ await xl.cookie("refreshToken", refreshToken, options)
123
+
124
+ return xl.json({msg:"setting cookies"})
125
+ })
126
+ ```
127
+
128
+ # Render a HTML page
129
+ ```javascript
130
+ app.get("/render",async (xl) => {
131
+ return xl.html(`${import.meta.dir}/index.html`)
132
+ })
133
+ ```
134
+ # redirect
135
+ ```javascript
42
136
  app.get("/redirect",(xl) => {
43
137
  return xl.redirect("/");
44
- });
45
-
138
+ })
139
+ ```
140
+ # get params
141
+ ```javascript
46
142
  app.get("/hello/:id",(xl) => {
47
143
  const id = xl.getParams("id")
144
+ const query = xl.getQuery() // you can pass query name also , you wanna get
48
145
  return xl.json({ msg: "Hello", id });
49
- });
50
-
146
+ })
147
+ ```
51
148
 
52
- // Start the server
53
- app.listen(port, () => {
54
- console.log(`diesel is running on port ${port}`);
55
- });
56
149
 
package/dist/ctx.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { Server } from "bun";
2
+ import type { ContextType } from "./types";
3
+ export default function createCtx(req: Request, server: Server, url: URL): ContextType;
package/dist/ctx.js CHANGED
@@ -1 +1 @@
1
- async function E(I){const G={};if(!I)return G;return I.split(";").forEach((M)=>{const[U,L]=M?.trim()?.split("=");if(U&&L)G[U.trim()]=L.split(" ")[0].trim()}),G}function K(I,G){const z={},M=I.split("/"),[U]=G.split("?"),L=U.split("/");if(M.length!==L.length)return null;return M.forEach((X,Z)=>{if(X.startsWith(":")){const Y=X.slice(1);z[Y]=L[Z]}}),z}async function W(I){const G=I.headers.get("Content-Type")||"";if(!G)return{};try{if(G.startsWith("application/json"))return await I.json();if(G.startsWith("application/x-www-form-urlencoded")){const z=await I.text();return Object.fromEntries(new URLSearchParams(z))}if(G.startsWith("multipart/form-data")){const z=await I.formData();return A(z)}return{error:"Unknown request body type"}}catch(z){return{error:"Invalid request body format"}}}function A(I){const G={};for(let[z,M]of I.entries())G[z]=M;return G}function $(I,G){let z=new Headers,M={},U=!1,L=null,X=null,Z=null,Y,_=200;return{req:I,url:G,next:()=>{},status(w){return _=w,this},async body(){if(!Y)Y=await W(I);if(Y.error)return new Response(JSON.stringify({error:Y.error}),{status:400});return Y},setHeader(w,F){return z.set(w,F),this},set(w,F){return M[w]=F,this},get(w){return M[w]||null},setAuth(w){return U=w,this},getAuth(){return U},text(w,F){return new Response(w,{status:F??_,headers:z})},json(w,F){return new Response(JSON.stringify(w),{status:F??_,headers:z})},html(w,F){return new Response(Bun.file(w),{status:F??_,headers:z})},file(w,F){return new Response(Bun.file(w),{status:F??_,headers:z})},redirect(w,F){return z.set("Location",w),new Response(null,{status:F??302,headers:z})},getParams(w){if(!Z)Z=K(I?.routePattern,G?.pathname);return w?Z[w]||null:Z},getQuery(w){if(!L)L=Object.fromEntries(G.searchParams);return w?L[w]||null:L},async cookie(w,F,J={}){let R=`${encodeURIComponent(w)}=${encodeURIComponent(F)}`;if(J.maxAge)R+=`; Max-Age=${J.maxAge}`;if(J.expires)R+=`; Expires=${J.expires.toUTCString()}`;if(J.path)R+=`; Path=${J.path}`;if(J.domain)R+=`; Domain=${J.domain}`;if(J.secure)R+="; Secure";if(J.httpOnly)R+="; HttpOnly";if(J.sameSite)R+=`; SameSite=${J.sameSite}`;return z?.append("Set-Cookie",R),this},async getCookie(w){if(!X){const F=I.headers.get("cookie");if(F)X=await E(F)}return w?X[w]||null:X}}}export{$ as default};
1
+ function $(E,F,I){let G=new Headers,R={},L=!1,U=null,X=null,Y=null,Z,_=200;return{req:E,server:F,url:I,next:()=>{},status(w){return _=w,this},getIP(){return this.server.requestIP(this.req)},async body(){if(!Z)Z=await O(E);if(Z.error)return new Response(JSON.stringify({error:Z.error}),{status:400});return Z},setHeader(w,z){return G.set(w,z),this},set(w,z){return R[w]=z,this},get(w){return R[w]||null},setAuth(w){return L=w,this},getAuth(){return L},text(w,z){return new Response(w,{status:z??_,headers:G})},json(w,z){return new Response(JSON.stringify(w),{status:z??_,headers:G})},html(w,z){return new Response(Bun.file(w),{status:z??_,headers:G})},file(w,z){return new Response(Bun.file(w),{status:z??_,headers:G})},redirect(w,z){return G.set("Location",w),new Response(null,{status:z??302,headers:G})},getParams(w){if(!Y)Y=W(E?.routePattern,I?.pathname);return w?Y[w]||null:Y},getQuery(w){if(!U)U=Object.fromEntries(I.searchParams);return w?U[w]||null:U},async cookie(w,z,J={}){let M=`${encodeURIComponent(w)}=${encodeURIComponent(z)}`;if(J.maxAge)M+=`; Max-Age=${J.maxAge}`;if(J.expires)M+=`; Expires=${J.expires.toUTCString()}`;if(J.path)M+=`; Path=${J.path}`;if(J.domain)M+=`; Domain=${J.domain}`;if(J.secure)M+="; Secure";if(J.httpOnly)M+="; HttpOnly";if(J.sameSite)M+=`; SameSite=${J.sameSite}`;return G?.append("Set-Cookie",M),this},async getCookie(w){if(!X){let z=E.headers.get("cookie");if(z)X=await K(z)}return w?X[w]||null:X}}}async function K(E){let F={};if(!E)return F;return E.split(";").forEach((G)=>{let[R,L]=G?.trim()?.split("=");if(R&&L)F[R.trim()]=L.split(" ")[0].trim()}),F}function W(E,F){let I={},G=E.split("/"),[R]=F.split("?"),L=R.split("/");if(G.length!==L.length)return null;return G.forEach((U,X)=>{if(U.startsWith(":")){let Y=U.slice(1);I[Y]=L[X]}}),I}async function O(E){let F=E.headers.get("Content-Type")||"";if(!F)return{};try{if(F.startsWith("application/json"))return await E.json();if(F.startsWith("application/x-www-form-urlencoded")){let I=await E.text();return Object.fromEntries(new URLSearchParams(I))}if(F.startsWith("multipart/form-data")){let I=await E.formData();return A(I)}return{error:"Unknown request body type"}}catch(I){return{error:"Invalid request body format"}}}function A(E){let F={};for(let[I,G]of E.entries())F[I]=G;return F}export{$ as default};
@@ -0,0 +1,3 @@
1
+ import { Server } from "bun";
2
+ import type { DieselT } from "./types";
3
+ export default function handleRequest(req: Request, server: Server, url: URL, diesel: DieselT): Promise<Response>;
@@ -1 +1 @@
1
- async function A(I){const G={};if(!I)return G;return I.split(";").forEach((J)=>{const[X,L]=J?.trim()?.split("=");if(X&&L)G[X.trim()]=L.split(" ")[0].trim()}),G}function O(I,G){const z={},J=I.split("/"),[X]=G.split("?"),L=X.split("/");if(J.length!==L.length)return null;return J.forEach((Y,E)=>{if(Y.startsWith(":")){const $=Y.slice(1);z[$]=L[E]}}),z}async function V(I){const G=I.headers.get("Content-Type")||"";if(!G)return{};try{if(G.startsWith("application/json"))return await I.json();if(G.startsWith("application/x-www-form-urlencoded")){const z=await I.text();return Object.fromEntries(new URLSearchParams(z))}if(G.startsWith("multipart/form-data")){const z=await I.formData();return D(z)}return{error:"Unknown request body type"}}catch(z){return{error:"Invalid request body format"}}}function D(I){const G={};for(let[z,J]of I.entries())G[z]=J;return G}function M(I,G){let z=new Headers,J={},X=!1,L=null,Y=null,E=null,$,K=200;return{req:I,url:G,next:()=>{},status(F){return K=F,this},async body(){if(!$)$=await V(I);if($.error)return new Response(JSON.stringify({error:$.error}),{status:400});return $},setHeader(F,U){return z.set(F,U),this},set(F,U){return J[F]=U,this},get(F){return J[F]||null},setAuth(F){return X=F,this},getAuth(){return X},text(F,U){return new Response(F,{status:U??K,headers:z})},json(F,U){return new Response(JSON.stringify(F),{status:U??K,headers:z})},html(F,U){return new Response(Bun.file(F),{status:U??K,headers:z})},file(F,U){return new Response(Bun.file(F),{status:U??K,headers:z})},redirect(F,U){return z.set("Location",F),new Response(null,{status:U??302,headers:z})},getParams(F){if(!E)E=O(I?.routePattern,G?.pathname);return F?E[F]||null:E},getQuery(F){if(!L)L=Object.fromEntries(G.searchParams);return F?L[F]||null:L},async cookie(F,U,Z={}){let _=`${encodeURIComponent(F)}=${encodeURIComponent(U)}`;if(Z.maxAge)_+=`; Max-Age=${Z.maxAge}`;if(Z.expires)_+=`; Expires=${Z.expires.toUTCString()}`;if(Z.path)_+=`; Path=${Z.path}`;if(Z.domain)_+=`; Domain=${Z.domain}`;if(Z.secure)_+="; Secure";if(Z.httpOnly)_+="; HttpOnly";if(Z.sameSite)_+=`; SameSite=${Z.sameSite}`;return z?.append("Set-Cookie",_),this},async getCookie(F){if(!Y){const U=I.headers.get("cookie");if(U)Y=await A(U)}return F?Y[F]||null:Y}}}async function R(I,G){for(let z of I){const J=await z(G);if(J)return J}}var W={};async function Q(I,G,z){const J=M(I,G);if(z.hasOnReqHook)await z.hooks.onRequest(J);if(z.hasMiddleware){const L=[...z.globalMiddlewares,...z.middlewares.get(G.pathname)||[]],Y=await R(L,J);if(Y)return Y}let X;if(W[G.pathname+I.method])X=W[G.pathname+I.method];else X=z.trie.search(G.pathname,I.method),W[G.pathname+I.method]=X;if(!X||!X.handler)return new Response(`Route not found for ${G.pathname}`,{status:404});if(X.method!==I.method)return new Response("Method not allowed",{status:405});if(X.isDynamic)I.routePattern=X.path;if(z.hasPreHandlerHook){const L=await z.hooks.preHandler(J);if(L)return L}try{const L=await X.handler(J);if(z.hasPostHandlerHook)await z.hooks.postHandler(J);if(z.hasOnSendHook){const Y=await z.hooks.onSend(L,J);if(Y)return Y}return L??new Response("No response from handler",{status:204})}catch(L){return new Response("Internal Server Error",{status:500})}}export{Q as default};
1
+ function W(G,E,I){let z=new Headers,J={},X=!1,L=null,Z=null,Y=null,K,M=200;return{req:G,server:E,url:I,next:()=>{},status(F){return M=F,this},getIP(){return this.server.requestIP(this.req)},async body(){if(!K)K=await j(G);if(K.error)return new Response(JSON.stringify({error:K.error}),{status:400});return K},setHeader(F,U){return z.set(F,U),this},set(F,U){return J[F]=U,this},get(F){return J[F]||null},setAuth(F){return X=F,this},getAuth(){return X},text(F,U){return new Response(F,{status:U??M,headers:z})},json(F,U){return new Response(JSON.stringify(F),{status:U??M,headers:z})},html(F,U){return new Response(Bun.file(F),{status:U??M,headers:z})},file(F,U){return new Response(Bun.file(F),{status:U??M,headers:z})},redirect(F,U){return z.set("Location",F),new Response(null,{status:U??302,headers:z})},getParams(F){if(!Y)Y=V(G?.routePattern,I?.pathname);return F?Y[F]||null:Y},getQuery(F){if(!L)L=Object.fromEntries(I.searchParams);return F?L[F]||null:L},async cookie(F,U,_={}){let $=`${encodeURIComponent(F)}=${encodeURIComponent(U)}`;if(_.maxAge)$+=`; Max-Age=${_.maxAge}`;if(_.expires)$+=`; Expires=${_.expires.toUTCString()}`;if(_.path)$+=`; Path=${_.path}`;if(_.domain)$+=`; Domain=${_.domain}`;if(_.secure)$+="; Secure";if(_.httpOnly)$+="; HttpOnly";if(_.sameSite)$+=`; SameSite=${_.sameSite}`;return z?.append("Set-Cookie",$),this},async getCookie(F){if(!Z){let U=G.headers.get("cookie");if(U)Z=await A(U)}return F?Z[F]||null:Z}}}async function A(G){let E={};if(!G)return E;return G.split(";").forEach((z)=>{let[J,X]=z?.trim()?.split("=");if(J&&X)E[J.trim()]=X.split(" ")[0].trim()}),E}function V(G,E){let I={},z=G.split("/"),[J]=E.split("?"),X=J.split("/");if(z.length!==X.length)return null;return z.forEach((L,Z)=>{if(L.startsWith(":")){let Y=L.slice(1);I[Y]=X[Z]}}),I}async function j(G){let E=G.headers.get("Content-Type")||"";if(!E)return{};try{if(E.startsWith("application/json"))return await G.json();if(E.startsWith("application/x-www-form-urlencoded")){let I=await G.text();return Object.fromEntries(new URLSearchParams(I))}if(E.startsWith("multipart/form-data")){let I=await G.formData();return D(I)}return{error:"Unknown request body type"}}catch(I){return{error:"Invalid request body format"}}}function D(G){let E={};for(let[I,z]of G.entries())E[I]=z;return E}async function Q(G,E,I,z){let J=W(G,E,I),X=z.trie.search(I.pathname,G.method);if(!X||!X.handler)return new Response(`Route not found for ${I.pathname}`,{status:404});if(X.method!==G.method)return new Response("Method not allowed",{status:405});if(X.isDynamic)G.routePattern=X.path;if(z.corsConfig){let L=await T(G,J,z.corsConfig);if(L)return L}if(z.hasOnReqHook&&z.hooks.onRequest)z.hooks.onRequest(J,E);if(z.filters.length>0){let L=G.routePattern??I.pathname;if(z.filters.includes(L)===!1)if(z.filterFunction){let Y=await z?.filterFunction(J);if(Y)return Y}else return new Response(JSON.stringify({message:"Authentication required"}),{status:400})}if(z.hasMiddleware){let L=[...z.globalMiddlewares,...z.middlewares.get(I.pathname)||[]];for(let Z of L){let Y=await Z(J,E);if(Y)return Y}}if(z.hasPreHandlerHook&&z.hooks.preHandler){let L=await z.hooks.preHandler(J);if(L)return L}try{let L=await X.handler(J);if(z.hasPostHandlerHook&&z.hooks.postHandler)await z.hooks.postHandler(J);if(z.hasOnSendHook&&z.hooks.onSend){let Z=await z.hooks.onSend(J,L);if(Z)return Z}return L??new Response("No response from handler",{status:204})}catch(L){return new Response("Internal Server Error",{status:500})}}async function T(G,E,I={}){let z=G.headers.get("origin")??"*",J=I?.origin,X=I?.allowedHeaders??["Content-Type","Authorization"],L=I?.methods??["GET","POST","PUT","DELETE","OPTIONS"],Z=I?.credentials??!1,Y=I?.exposedHeaders??[];if(E.setHeader("Access-Control-Allow-Methods",L),E.setHeader("Access-Control-Allow-Headers",X),E.setHeader("Access-Control-Allow-Credentials",Z),Y.length)E.setHeader("Access-Control-Expose-Headers",Y);if(J==="*")E.setHeader("Access-Control-Allow-Origin","*");else if(Array.isArray(J))if(z&&J.includes(z))E.setHeader("Access-Control-Allow-Origin",z);else if(J.includes("*"))E.setHeader("Access-Control-Allow-Origin","*");else return E.status(403).json({message:"CORS not allowed"});else if(typeof J==="string")if(z===J)E.setHeader("Access-Control-Allow-Origin",z);else return E.status(403).json({message:"CORS not allowed"});else return E.status(403).json({message:"CORS not allowed"});if(E.setHeader("Access-Control-Allow-Origin",z),G.method==="OPTIONS")return E.setHeader("Access-Control-Max-Age","86400"),E.status(204).text("");return null}export{Q as default};
package/dist/main.d.ts ADDED
@@ -0,0 +1,34 @@
1
+ import Trie from "./trie.js";
2
+ import rateLimit from "./utils.js";
3
+ import { corsT, FilterMethods, HookFunction, HookType, middlewareFunc, type handlerFunction, type Hooks, type listenCalllBackType } from "./types.js";
4
+ import { Server } from "bun";
5
+ declare class Diesel {
6
+ #private;
7
+ routes: string[] | undefined;
8
+ globalMiddlewares: middlewareFunc[];
9
+ middlewares: Map<string, middlewareFunc[]>;
10
+ trie: Trie;
11
+ hasOnReqHook: boolean;
12
+ hasMiddleware: boolean;
13
+ hasPreHandlerHook: boolean;
14
+ hasPostHandlerHook: boolean;
15
+ hasOnSendHook: boolean;
16
+ hooks: Hooks;
17
+ corsConfig: corsT;
18
+ filters: string[];
19
+ filterFunction: middlewareFunc | null;
20
+ constructor();
21
+ filter(): FilterMethods;
22
+ cors(corsConfig: corsT): void;
23
+ addHooks(typeOfHook: HookType, fnc: HookFunction): void;
24
+ compile(): void;
25
+ listen(port: number, callback?: listenCalllBackType, { sslCert, sslKey }?: any): Server | void;
26
+ register(pathPrefix: string, handlerInstance: any): void;
27
+ use(pathORHandler?: string | middlewareFunc, handler?: middlewareFunc): void;
28
+ get(path: string, ...handlers: handlerFunction[]): this;
29
+ post(path: string, ...handlers: handlerFunction[]): this;
30
+ put(path: string, ...handlers: handlerFunction[]): this;
31
+ patch(path: string, ...handlers: handlerFunction[]): this;
32
+ delete(path: any, ...handlers: handlerFunction[]): this;
33
+ }
34
+ export { Diesel, rateLimit, };
package/dist/main.js CHANGED
@@ -1 +1 @@
1
- class Q{children;isEndOfWord;handler;isDynamic;pattern;path;method;subMiddlewares;constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class V{root;constructor(){this.root=new Q}insert(F,G){let z=this.root;const U=F.split("/").filter(Boolean);if(F==="/"){z.isEndOfWord=!0,z.handler.push(G.handler),z.path=F,z.method.push(G.method);return}for(let J of U){let L=!1,Y=J;if(J.startsWith(":"))L=!0,Y=":";if(!z.children[Y])z.children[Y]=new Q;z=z.children[Y],z.isDynamic=L,z.pattern=J}z.isEndOfWord=!0,z.method.push(G.method),z.handler.push(G.handler),z.path=F}search(F,G){let z=this.root;const U=F.split("/").filter(Boolean);for(let L of U){let Y=L;if(!z.children[Y])if(z.children[":"])z=z.children[":"];else return null;else z=z.children[Y]}let J=z.method.indexOf(G);if(J!==-1)return{path:z.path,handler:z.handler[J],isDynamic:z.isDynamic,pattern:z.pattern,method:z.method[J]};return{path:z.path,handler:z.handler,isDynamic:z.isDynamic,pattern:z.pattern,method:z.method[J]}}}async function D(F){const G={};if(!F)return G;return F.split(";").forEach((U)=>{const[J,L]=U?.trim()?.split("=");if(J&&L)G[J.trim()]=L.split(" ")[0].trim()}),G}function v(F,G){const z={},U=F.split("/"),[J]=G.split("?"),L=J.split("/");if(U.length!==L.length)return null;return U.forEach((Y,$)=>{if(Y.startsWith(":")){const W=Y.slice(1);z[W]=L[$]}}),z}async function T(F){const G=F.headers.get("Content-Type")||"";if(!G)return{};try{if(G.startsWith("application/json"))return await F.json();if(G.startsWith("application/x-www-form-urlencoded")){const z=await F.text();return Object.fromEntries(new URLSearchParams(z))}if(G.startsWith("multipart/form-data")){const z=await F.formData();return b(z)}return{error:"Unknown request body type"}}catch(z){return{error:"Invalid request body format"}}}function b(F){const G={};for(let[z,U]of F.entries())G[z]=U;return G}function M(F,G){let z=new Headers,U={},J=!1,L=null,Y=null,$=null,W,E=200;return{req:F,url:G,next:()=>{},status(X){return E=X,this},async body(){if(!W)W=await T(F);if(W.error)return new Response(JSON.stringify({error:W.error}),{status:400});return W},setHeader(X,Z){return z.set(X,Z),this},set(X,Z){return U[X]=Z,this},get(X){return U[X]||null},setAuth(X){return J=X,this},getAuth(){return J},text(X,Z){return new Response(X,{status:Z??E,headers:z})},json(X,Z){return new Response(JSON.stringify(X),{status:Z??E,headers:z})},html(X,Z){return new Response(Bun.file(X),{status:Z??E,headers:z})},file(X,Z){return new Response(Bun.file(X),{status:Z??E,headers:z})},redirect(X,Z){return z.set("Location",X),new Response(null,{status:Z??302,headers:z})},getParams(X){if(!$)$=v(F?.routePattern,G?.pathname);return X?$[X]||null:$},getQuery(X){if(!L)L=Object.fromEntries(G.searchParams);return X?L[X]||null:L},async cookie(X,Z,_={}){let A=`${encodeURIComponent(X)}=${encodeURIComponent(Z)}`;if(_.maxAge)A+=`; Max-Age=${_.maxAge}`;if(_.expires)A+=`; Expires=${_.expires.toUTCString()}`;if(_.path)A+=`; Path=${_.path}`;if(_.domain)A+=`; Domain=${_.domain}`;if(_.secure)A+="; Secure";if(_.httpOnly)A+="; HttpOnly";if(_.sameSite)A+=`; SameSite=${_.sameSite}`;return z?.append("Set-Cookie",A),this},async getCookie(X){if(!Y){const Z=F.headers.get("cookie");if(Z)Y=await D(Z)}return X?Y[X]||null:Y}}}async function N(F,G){for(let z of F){const U=await z(G);if(U)return U}}var B={};async function K(F,G,z){const U=M(F,G);if(z.hasOnReqHook)await z.hooks.onRequest(U);if(z.hasMiddleware){const L=[...z.globalMiddlewares,...z.middlewares.get(G.pathname)||[]],Y=await N(L,U);if(Y)return Y}let J;if(B[G.pathname+F.method])J=B[G.pathname+F.method];else J=z.trie.search(G.pathname,F.method),B[G.pathname+F.method]=J;if(!J||!J.handler)return new Response(`Route not found for ${G.pathname}`,{status:404});if(J.method!==F.method)return new Response("Method not allowed",{status:405});if(J.isDynamic)F.routePattern=J.path;if(z.hasPreHandlerHook){const L=await z.hooks.preHandler(U);if(L)return L}try{const L=await J.handler(U);if(z.hasPostHandlerHook)await z.hooks.postHandler(U);if(z.hasOnSendHook){const Y=await z.hooks.onSend(L,U);if(Y)return Y}return L??new Response("No response from handler",{status:204})}catch(L){return new Response("Internal Server Error",{status:500})}}class j{routes;globalMiddlewares;middlewares;trie;hasOnReqHook;hasMiddleware;hasPreHandlerHook;hasPostHandlerHook;hasOnSendHook;hooks;constructor(){this.routes=new Map,this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new V,this.hasMiddleware=!1,this.hasOnReqHook=!1,this.hasPreHandlerHook=!1,this.hasPostHandlerHook=!1,this.hasOnSendHook=!1,this.hooks={onRequest:null,preHandler:null,postHandler:null,onSend:null,onError:null,onClose:null}}addHooks(F,G){if(typeof F!=="string")throw new Error("hookName must be a string");if(typeof G!=="function")throw new Error("callback must be a instance of function");if(this.hooks.hasOwnProperty(F))this.hooks[F]=G;else throw new Error(`Unknown hook type: ${F}`)}compile(){if(this.globalMiddlewares.length>0)this.hasMiddleware=!0;for(let[F,G]of this.middlewares.entries())if(G.length>0){this.hasMiddleware=!0;break}if(this.hooks.onRequest)this.hasOnReqHook=!0;if(this.hooks.preHandler)this.hasPreHandlerHook=!0;if(this.hooks.postHandler)this.hasPostHandlerHook=!0;if(this.hooks.onSend)this.hasOnSendHook=!0}listen(F,G,{sslCert:z=null,sslKey:U=null}={}){if(typeof Bun==="undefined")throw new Error(".listen() is designed to run on Bun only...");if(typeof F!=="number")throw new Error("Port must be a numeric value");this.compile();const J={port:F,fetch:async(Y)=>{const $=new URL(Y.url);try{return await K(Y,$,this)}catch(W){return new Response("Internal Server Error",{status:500})}},onClose(){console.log("Server is shutting down...")}};if(z&&U)J.certFile=z,J.keyFile=U;const L=Bun.serve(J);if(typeof G==="function")return G();if(z&&U)console.log(`HTTPS server is running on https://localhost:${F}`);else console.log(`HTTP server is running on http://localhost:${F}`);return L}register(F,G){if(typeof F!=="string")throw new Error("path must be a string");if(typeof G!=="object")throw new Error("handler parameter should be a instance of router object",G);const z=Object.entries(G.trie.root.children);G.trie.root.subMiddlewares.forEach((U,J)=>{if(!this.middlewares.has(F+J))this.middlewares.set(F+J,[]);U?.forEach((L)=>{if(!this.middlewares.get(F+J)?.includes(L))this.middlewares.get(F+J)?.push(L)})});for(let[U,J]of z){const L=F+J?.path,Y=J.handler[0],$=J.method[0];this.trie.insert(L,{handler:Y,method:$})}G.trie=new V}#z(F,G,z){if(typeof G!=="string")throw new Error("Path must be a string type");if(typeof F!=="string")throw new Error("method must be a string type");const U=z.slice(0,-1),J=z[z.length-1];if(!this.middlewares.has(G))this.middlewares.set(G,[]);U.forEach((L)=>{if(G==="/"){if(!this.globalMiddlewares.includes(L))this.globalMiddlewares.push(L)}else if(!this.middlewares.get(G)?.includes(L))this.middlewares.get(G)?.push(L)}),this.trie.insert(G,{handler:J,method:F})}use(F,G){if(typeof F==="function"){if(!this.globalMiddlewares.includes(F))return this.globalMiddlewares.push(F)}const z=F;if(!this.middlewares.has(z))this.middlewares.set(z,[]);if(!this.middlewares.get(z)?.includes(G))this.middlewares.get(z)?.push(G)}get(F,...G){return this.#z("GET",F,G),this}post(F,...G){return this.#z("POST",F,G),this}put(F,...G){return this.#z("PUT",F,G),this}patch(F,...G){return this.#z("PATCH",F,G),this}delete(F,...G){return this.#z("DELETE",F,G),this}}var g=j;export{g as default};
1
+ class K{children;isEndOfWord;handler;isDynamic;pattern;path;method;subMiddlewares;constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class Q{root;constructor(){this.root=new K}insert(z,F){let G=this.root,J=z.split("/").filter(Boolean);if(z==="/"){G.isEndOfWord=!0,G.handler.push(F.handler),G.path=z,G.method.push(F.method);return}for(let U of J){let X=!1,Y=U;if(U.startsWith(":"))X=!0,Y=":";if(!G.children[Y])G.children[Y]=new K;G=G.children[Y],G.isDynamic=X,G.pattern=U}G.isEndOfWord=!0,G.method.push(F.method),G.handler.push(F.handler),G.path=z}search(z,F){let G=this.root,J=z.split("/").filter(Boolean);for(let X of J){let Y=X;if(!G.children[Y])if(G.children[":"])G=G.children[":"];else return null;else G=G.children[Y]}let U=G.method.indexOf(F);if(U!==-1)return{path:G.path,handler:G.handler[U],isDynamic:G.isDynamic,pattern:G.pattern,method:G.method[U]};return{path:G.path,handler:G.handler,isDynamic:G.isDynamic,pattern:G.pattern,method:G.method[U]}}}function M(z,F,G){let J=new Headers,U={},X=!1,Y=null,$=null,_=null,A,V=200;return{req:z,server:F,url:G,next:()=>{},status(Z){return V=Z,this},getIP(){return this.server.requestIP(this.req)},async body(){if(!A)A=await T(z);if(A.error)return new Response(JSON.stringify({error:A.error}),{status:400});return A},setHeader(Z,E){return J.set(Z,E),this},set(Z,E){return U[Z]=E,this},get(Z){return U[Z]||null},setAuth(Z){return X=Z,this},getAuth(){return X},text(Z,E){return new Response(Z,{status:E??V,headers:J})},json(Z,E){return new Response(JSON.stringify(Z),{status:E??V,headers:J})},html(Z,E){return new Response(Bun.file(Z),{status:E??V,headers:J})},file(Z,E){return new Response(Bun.file(Z),{status:E??V,headers:J})},redirect(Z,E){return J.set("Location",Z),new Response(null,{status:E??302,headers:J})},getParams(Z){if(!_)_=N(z?.routePattern,G?.pathname);return Z?_[Z]||null:_},getQuery(Z){if(!Y)Y=Object.fromEntries(G.searchParams);return Z?Y[Z]||null:Y},async cookie(Z,E,L={}){let W=`${encodeURIComponent(Z)}=${encodeURIComponent(E)}`;if(L.maxAge)W+=`; Max-Age=${L.maxAge}`;if(L.expires)W+=`; Expires=${L.expires.toUTCString()}`;if(L.path)W+=`; Path=${L.path}`;if(L.domain)W+=`; Domain=${L.domain}`;if(L.secure)W+="; Secure";if(L.httpOnly)W+="; HttpOnly";if(L.sameSite)W+=`; SameSite=${L.sameSite}`;return J?.append("Set-Cookie",W),this},async getCookie(Z){if(!$){let E=z.headers.get("cookie");if(E)$=await D(E)}return Z?$[Z]||null:$}}}async function D(z){let F={};if(!z)return F;return z.split(";").forEach((J)=>{let[U,X]=J?.trim()?.split("=");if(U&&X)F[U.trim()]=X.split(" ")[0].trim()}),F}function N(z,F){let G={},J=z.split("/"),[U]=F.split("?"),X=U.split("/");if(J.length!==X.length)return null;return J.forEach((Y,$)=>{if(Y.startsWith(":")){let _=Y.slice(1);G[_]=X[$]}}),G}async function T(z){let F=z.headers.get("Content-Type")||"";if(!F)return{};try{if(F.startsWith("application/json"))return await z.json();if(F.startsWith("application/x-www-form-urlencoded")){let G=await z.text();return Object.fromEntries(new URLSearchParams(G))}if(F.startsWith("multipart/form-data")){let G=await z.formData();return b(G)}return{error:"Unknown request body type"}}catch(G){return{error:"Invalid request body format"}}}function b(z){let F={};for(let[G,J]of z.entries())F[G]=J;return F}async function B(z,F,G,J){let U=M(z,F,G),X=J.trie.search(G.pathname,z.method);if(!X||!X.handler)return new Response(`Route not found for ${G.pathname}`,{status:404});if(X.method!==z.method)return new Response("Method not allowed",{status:405});if(X.isDynamic)z.routePattern=X.path;if(J.corsConfig){let Y=await C(z,U,J.corsConfig);if(Y)return Y}if(J.hasOnReqHook&&J.hooks.onRequest)J.hooks.onRequest(U,F);if(J.filters.length>0){let Y=z.routePattern??G.pathname;if(J.filters.includes(Y)===!1)if(J.filterFunction){let _=await J?.filterFunction(U);if(_)return _}else return new Response(JSON.stringify({message:"Authentication required"}),{status:400})}if(J.hasMiddleware){let Y=[...J.globalMiddlewares,...J.middlewares.get(G.pathname)||[]];for(let $ of Y){let _=await $(U,F);if(_)return _}}if(J.hasPreHandlerHook&&J.hooks.preHandler){let Y=await J.hooks.preHandler(U);if(Y)return Y}try{let Y=await X.handler(U);if(J.hasPostHandlerHook&&J.hooks.postHandler)await J.hooks.postHandler(U);if(J.hasOnSendHook&&J.hooks.onSend){let $=await J.hooks.onSend(U,Y);if($)return $}return Y??new Response("No response from handler",{status:204})}catch(Y){return new Response("Internal Server Error",{status:500})}}async function C(z,F,G={}){let J=z.headers.get("origin")??"*",U=G?.origin,X=G?.allowedHeaders??["Content-Type","Authorization"],Y=G?.methods??["GET","POST","PUT","DELETE","OPTIONS"],$=G?.credentials??!1,_=G?.exposedHeaders??[];if(F.setHeader("Access-Control-Allow-Methods",Y),F.setHeader("Access-Control-Allow-Headers",X),F.setHeader("Access-Control-Allow-Credentials",$),_.length)F.setHeader("Access-Control-Expose-Headers",_);if(U==="*")F.setHeader("Access-Control-Allow-Origin","*");else if(Array.isArray(U))if(J&&U.includes(J))F.setHeader("Access-Control-Allow-Origin",J);else if(U.includes("*"))F.setHeader("Access-Control-Allow-Origin","*");else return F.status(403).json({message:"CORS not allowed"});else if(typeof U==="string")if(J===U)F.setHeader("Access-Control-Allow-Origin",J);else return F.status(403).json({message:"CORS not allowed"});else return F.status(403).json({message:"CORS not allowed"});if(F.setHeader("Access-Control-Allow-Origin",J),z.method==="OPTIONS")return F.setHeader("Access-Control-Max-Age","86400"),F.status(204).text("");return null}function j(z){let{time:F=60000,max:G=100,message:J="Rate limit exceeded. Please try again later."}=z,U=new Map;return(X)=>{let Y=new Date,$=X.getIP().address;if(!U.has($))U.set($,{count:0,startTime:Y});let _=U.get($);if(_)if(Y-_.startTime>F)_.count=1,_.startTime=Y;else _.count++;if(_&&_.count>G)return X.status(429).json({error:J});X.next()}}class v{routes;globalMiddlewares;middlewares;trie;hasOnReqHook;hasMiddleware;hasPreHandlerHook;hasPostHandlerHook;hasOnSendHook;hooks;corsConfig;filters;filterFunction;constructor(){this.routes=[],this.filters=[],this.filterFunction=null,this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new Q,this.corsConfig=null,this.hasMiddleware=!1,this.hasOnReqHook=!1,this.hasPreHandlerHook=!1,this.hasPostHandlerHook=!1,this.hasOnSendHook=!1,this.hooks={onRequest:null,preHandler:null,postHandler:null,onSend:null,onError:null,onClose:null}}filter(){return{routeMatcher:(...z)=>{return this.routes=z.sort(),this.filter()},permitAll:()=>{for(let z of this?.routes)this.filters.push(z);return this.filter()},require:(z)=>{if(!z||typeof z!=="function")return new Response(JSON.stringify({message:"Authentication required"}),{status:400});this.filterFunction=z}}}cors(z){this.corsConfig=z}addHooks(z,F){if(typeof z!=="string")throw new Error("hookName must be a string");if(typeof F!=="function")throw new Error("callback must be a instance of function");if(this.hooks.hasOwnProperty(z))this.hooks[z]=F;else throw new Error(`Unknown hook type: ${z}`)}compile(){if(this.globalMiddlewares.length>0)this.hasMiddleware=!0;for(let[z,F]of this.middlewares.entries())if(F.length>0){this.hasMiddleware=!0;break}if(this.hooks.onRequest)this.hasOnReqHook=!0;if(this.hooks.preHandler)this.hasPreHandlerHook=!0;if(this.hooks.postHandler)this.hasPostHandlerHook=!0;if(this.hooks.onSend)this.hasOnSendHook=!0}listen(z,F,{sslCert:G=null,sslKey:J=null}={}){if(typeof Bun==="undefined")throw new Error(".listen() is designed to run on Bun only...");if(typeof z!=="number")throw new Error("Port must be a numeric value");this.compile();let U=this,X={port:z,fetch:async($,_)=>{let A=new URL($.url);try{return await B($,_,A,this)}catch(V){return new Response("Internal Server Error",{status:500})}},onClose(){console.log("Server is shutting down...")}};if(G&&J)X.certFile=G,X.keyFile=J;let Y=Bun.serve(X);if(typeof F==="function")return F();if(G&&J)console.log(`HTTPS server is running on https://localhost:${z}`);else console.log(`HTTP server is running on http://localhost:${z}`);return Y}register(z,F){if(typeof z!=="string")throw new Error("path must be a string");if(typeof F!=="object")throw new Error("handler parameter should be a instance of router object",F);let G=Object.entries(F.trie.root.children);F.trie.root.subMiddlewares.forEach((J,U)=>{if(!this.middlewares.has(z+U))this.middlewares.set(z+U,[]);J?.forEach((X)=>{if(!this.middlewares.get(z+U)?.includes(X))this.middlewares.get(z+U)?.push(X)})});for(let[J,U]of G){let X=z+U?.path,Y=U.handler[0],$=U.method[0];this.trie.insert(X,{handler:Y,method:$})}F.trie=new Q}#z(z,F,G){if(typeof F!=="string")throw new Error("Path must be a string type");if(typeof z!=="string")throw new Error("method must be a string type");let J=G.slice(0,-1),U=G[G.length-1];if(!this.middlewares.has(F))this.middlewares.set(F,[]);J.forEach((X)=>{if(F==="/"){if(!this.globalMiddlewares.includes(X))this.globalMiddlewares.push(X)}else if(!this.middlewares.get(F)?.includes(X))this.middlewares.get(F)?.push(X)}),this.trie.insert(F,{handler:U,method:z})}use(z,F){if(typeof z==="function"){if(!this.globalMiddlewares.includes(z))this.globalMiddlewares.push(z);return}let G=z;if(!this.middlewares.has(G))this.middlewares.set(G,[]);if(F){if(!this.middlewares.get(G)?.includes(F))this.middlewares.get(G)?.push(F)}}get(z,...F){return this.#z("GET",z,F),this}post(z,...F){return this.#z("POST",z,F),this}put(z,...F){return this.#z("PUT",z,F),this}patch(z,...F){return this.#z("PATCH",z,F),this}delete(z,...F){return this.#z("DELETE",z,F),this}}export{j as rateLimit,v as Diesel};
@@ -0,0 +1,12 @@
1
+ import { Diesel } from "./main";
2
+ import type { handlerFunction } from "./types";
3
+ declare class Router extends Diesel {
4
+ #private;
5
+ constructor();
6
+ get(path: string, ...handlers: handlerFunction[]): this;
7
+ post(path: string, ...handlers: handlerFunction[]): this;
8
+ put(path: string, ...handlers: handlerFunction[]): this;
9
+ patch(path: string, ...handlers: handlerFunction[]): this;
10
+ delete(path: string, ...handlers: handlerFunction[]): this;
11
+ }
12
+ export default Router;
package/dist/router.js CHANGED
@@ -1 +1 @@
1
- class Q{children;isEndOfWord;handler;isDynamic;pattern;path;method;subMiddlewares;constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class V{root;constructor(){this.root=new Q}insert(G,F){let z=this.root;const U=G.split("/").filter(Boolean);if(G==="/"){z.isEndOfWord=!0,z.handler.push(F.handler),z.path=G,z.method.push(F.method);return}for(let J of U){let L=!1,Y=J;if(J.startsWith(":"))L=!0,Y=":";if(!z.children[Y])z.children[Y]=new Q;z=z.children[Y],z.isDynamic=L,z.pattern=J}z.isEndOfWord=!0,z.method.push(F.method),z.handler.push(F.handler),z.path=G}search(G,F){let z=this.root;const U=G.split("/").filter(Boolean);for(let L of U){let Y=L;if(!z.children[Y])if(z.children[":"])z=z.children[":"];else return null;else z=z.children[Y]}let J=z.method.indexOf(F);if(J!==-1)return{path:z.path,handler:z.handler[J],isDynamic:z.isDynamic,pattern:z.pattern,method:z.method[J]};return{path:z.path,handler:z.handler,isDynamic:z.isDynamic,pattern:z.pattern,method:z.method[J]}}}async function T(G){const F={};if(!G)return F;return G.split(";").forEach((U)=>{const[J,L]=U?.trim()?.split("=");if(J&&L)F[J.trim()]=L.split(" ")[0].trim()}),F}function b(G,F){const z={},U=G.split("/"),[J]=F.split("?"),L=J.split("/");if(U.length!==L.length)return null;return U.forEach((Y,$)=>{if(Y.startsWith(":")){const W=Y.slice(1);z[W]=L[$]}}),z}async function N(G){const F=G.headers.get("Content-Type")||"";if(!F)return{};try{if(F.startsWith("application/json"))return await G.json();if(F.startsWith("application/x-www-form-urlencoded")){const z=await G.text();return Object.fromEntries(new URLSearchParams(z))}if(F.startsWith("multipart/form-data")){const z=await G.formData();return I(z)}return{error:"Unknown request body type"}}catch(z){return{error:"Invalid request body format"}}}function I(G){const F={};for(let[z,U]of G.entries())F[z]=U;return F}function B(G,F){let z=new Headers,U={},J=!1,L=null,Y=null,$=null,W,E=200;return{req:G,url:F,next:()=>{},status(X){return E=X,this},async body(){if(!W)W=await N(G);if(W.error)return new Response(JSON.stringify({error:W.error}),{status:400});return W},setHeader(X,Z){return z.set(X,Z),this},set(X,Z){return U[X]=Z,this},get(X){return U[X]||null},setAuth(X){return J=X,this},getAuth(){return J},text(X,Z){return new Response(X,{status:Z??E,headers:z})},json(X,Z){return new Response(JSON.stringify(X),{status:Z??E,headers:z})},html(X,Z){return new Response(Bun.file(X),{status:Z??E,headers:z})},file(X,Z){return new Response(Bun.file(X),{status:Z??E,headers:z})},redirect(X,Z){return z.set("Location",X),new Response(null,{status:Z??302,headers:z})},getParams(X){if(!$)$=b(G?.routePattern,F?.pathname);return X?$[X]||null:$},getQuery(X){if(!L)L=Object.fromEntries(F.searchParams);return X?L[X]||null:L},async cookie(X,Z,_={}){let A=`${encodeURIComponent(X)}=${encodeURIComponent(Z)}`;if(_.maxAge)A+=`; Max-Age=${_.maxAge}`;if(_.expires)A+=`; Expires=${_.expires.toUTCString()}`;if(_.path)A+=`; Path=${_.path}`;if(_.domain)A+=`; Domain=${_.domain}`;if(_.secure)A+="; Secure";if(_.httpOnly)A+="; HttpOnly";if(_.sameSite)A+=`; SameSite=${_.sameSite}`;return z?.append("Set-Cookie",A),this},async getCookie(X){if(!Y){const Z=G.headers.get("cookie");if(Z)Y=await T(Z)}return X?Y[X]||null:Y}}}async function C(G,F){for(let z of G){const U=await z(F);if(U)return U}}var K={};async function j(G,F,z){const U=B(G,F);if(z.hasOnReqHook)await z.hooks.onRequest(U);if(z.hasMiddleware){const L=[...z.globalMiddlewares,...z.middlewares.get(F.pathname)||[]],Y=await C(L,U);if(Y)return Y}let J;if(K[F.pathname+G.method])J=K[F.pathname+G.method];else J=z.trie.search(F.pathname,G.method),K[F.pathname+G.method]=J;if(!J||!J.handler)return new Response(`Route not found for ${F.pathname}`,{status:404});if(J.method!==G.method)return new Response("Method not allowed",{status:405});if(J.isDynamic)G.routePattern=J.path;if(z.hasPreHandlerHook){const L=await z.hooks.preHandler(U);if(L)return L}try{const L=await J.handler(U);if(z.hasPostHandlerHook)await z.hooks.postHandler(U);if(z.hasOnSendHook){const Y=await z.hooks.onSend(L,U);if(Y)return Y}return L??new Response("No response from handler",{status:204})}catch(L){return new Response("Internal Server Error",{status:500})}}class D{routes;globalMiddlewares;middlewares;trie;hasOnReqHook;hasMiddleware;hasPreHandlerHook;hasPostHandlerHook;hasOnSendHook;hooks;constructor(){this.routes=new Map,this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new V,this.hasMiddleware=!1,this.hasOnReqHook=!1,this.hasPreHandlerHook=!1,this.hasPostHandlerHook=!1,this.hasOnSendHook=!1,this.hooks={onRequest:null,preHandler:null,postHandler:null,onSend:null,onError:null,onClose:null}}addHooks(G,F){if(typeof G!=="string")throw new Error("hookName must be a string");if(typeof F!=="function")throw new Error("callback must be a instance of function");if(this.hooks.hasOwnProperty(G))this.hooks[G]=F;else throw new Error(`Unknown hook type: ${G}`)}compile(){if(this.globalMiddlewares.length>0)this.hasMiddleware=!0;for(let[G,F]of this.middlewares.entries())if(F.length>0){this.hasMiddleware=!0;break}if(this.hooks.onRequest)this.hasOnReqHook=!0;if(this.hooks.preHandler)this.hasPreHandlerHook=!0;if(this.hooks.postHandler)this.hasPostHandlerHook=!0;if(this.hooks.onSend)this.hasOnSendHook=!0}listen(G,F,{sslCert:z=null,sslKey:U=null}={}){if(typeof Bun==="undefined")throw new Error(".listen() is designed to run on Bun only...");if(typeof G!=="number")throw new Error("Port must be a numeric value");this.compile();const J={port:G,fetch:async(Y)=>{const $=new URL(Y.url);try{return await j(Y,$,this)}catch(W){return new Response("Internal Server Error",{status:500})}},onClose(){console.log("Server is shutting down...")}};if(z&&U)J.certFile=z,J.keyFile=U;const L=Bun.serve(J);if(typeof F==="function")return F();if(z&&U)console.log(`HTTPS server is running on https://localhost:${G}`);else console.log(`HTTP server is running on http://localhost:${G}`);return L}register(G,F){if(typeof G!=="string")throw new Error("path must be a string");if(typeof F!=="object")throw new Error("handler parameter should be a instance of router object",F);const z=Object.entries(F.trie.root.children);F.trie.root.subMiddlewares.forEach((U,J)=>{if(!this.middlewares.has(G+J))this.middlewares.set(G+J,[]);U?.forEach((L)=>{if(!this.middlewares.get(G+J)?.includes(L))this.middlewares.get(G+J)?.push(L)})});for(let[U,J]of z){const L=G+J?.path,Y=J.handler[0],$=J.method[0];this.trie.insert(L,{handler:Y,method:$})}F.trie=new V}#z(G,F,z){if(typeof F!=="string")throw new Error("Path must be a string type");if(typeof G!=="string")throw new Error("method must be a string type");const U=z.slice(0,-1),J=z[z.length-1];if(!this.middlewares.has(F))this.middlewares.set(F,[]);U.forEach((L)=>{if(F==="/"){if(!this.globalMiddlewares.includes(L))this.globalMiddlewares.push(L)}else if(!this.middlewares.get(F)?.includes(L))this.middlewares.get(F)?.push(L)}),this.trie.insert(F,{handler:J,method:G})}use(G,F){if(typeof G==="function"){if(!this.globalMiddlewares.includes(G))return this.globalMiddlewares.push(G)}const z=G;if(!this.middlewares.has(z))this.middlewares.set(z,[]);if(!this.middlewares.get(z)?.includes(F))this.middlewares.get(z)?.push(F)}get(G,...F){return this.#z("GET",G,F),this}post(G,...F){return this.#z("POST",G,F),this}put(G,...F){return this.#z("PUT",G,F),this}patch(G,...F){return this.#z("PATCH",G,F),this}delete(G,...F){return this.#z("DELETE",G,F),this}}var M=D;class v extends M{constructor(){super()}#z(G,F,z){if(!this.trie.root.subMiddlewares.has(F))this.trie.root.subMiddlewares.set(F,[]);const U=z.slice(0,-1),J=this.trie.root.subMiddlewares.get(F);U.forEach((Y)=>{if(!J?.includes(Y))J?.push(Y)});const L=z[z.length-1];this.trie.insert(F,{handler:L,method:G})}get(G,...F){return this.#z("GET",G,F),this}post(G,...F){return this.#z("POST",G,F),this}put(G,...F){return this.#z("PUT",G,F),this}patch(G,...F){return this.#z("PATCH",G,F),this}delete(G,...F){return this.#z("DELETE",G,F),this}}var f=v;export{f as default};
1
+ class K{children;isEndOfWord;handler;isDynamic;pattern;path;method;subMiddlewares;constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class Q{root;constructor(){this.root=new K}insert(F,z){let G=this.root,J=F.split("/").filter(Boolean);if(F==="/"){G.isEndOfWord=!0,G.handler.push(z.handler),G.path=F,G.method.push(z.method);return}for(let U of J){let X=!1,Y=U;if(U.startsWith(":"))X=!0,Y=":";if(!G.children[Y])G.children[Y]=new K;G=G.children[Y],G.isDynamic=X,G.pattern=U}G.isEndOfWord=!0,G.method.push(z.method),G.handler.push(z.handler),G.path=F}search(F,z){let G=this.root,J=F.split("/").filter(Boolean);for(let X of J){let Y=X;if(!G.children[Y])if(G.children[":"])G=G.children[":"];else return null;else G=G.children[Y]}let U=G.method.indexOf(z);if(U!==-1)return{path:G.path,handler:G.handler[U],isDynamic:G.isDynamic,pattern:G.pattern,method:G.method[U]};return{path:G.path,handler:G.handler,isDynamic:G.isDynamic,pattern:G.pattern,method:G.method[U]}}}function B(F,z,G){let J=new Headers,U={},X=!1,Y=null,$=null,_=null,A,V=200;return{req:F,server:z,url:G,next:()=>{},status(Z){return V=Z,this},getIP(){return this.server.requestIP(this.req)},async body(){if(!A)A=await b(F);if(A.error)return new Response(JSON.stringify({error:A.error}),{status:400});return A},setHeader(Z,E){return J.set(Z,E),this},set(Z,E){return U[Z]=E,this},get(Z){return U[Z]||null},setAuth(Z){return X=Z,this},getAuth(){return X},text(Z,E){return new Response(Z,{status:E??V,headers:J})},json(Z,E){return new Response(JSON.stringify(Z),{status:E??V,headers:J})},html(Z,E){return new Response(Bun.file(Z),{status:E??V,headers:J})},file(Z,E){return new Response(Bun.file(Z),{status:E??V,headers:J})},redirect(Z,E){return J.set("Location",Z),new Response(null,{status:E??302,headers:J})},getParams(Z){if(!_)_=C(F?.routePattern,G?.pathname);return Z?_[Z]||null:_},getQuery(Z){if(!Y)Y=Object.fromEntries(G.searchParams);return Z?Y[Z]||null:Y},async cookie(Z,E,L={}){let W=`${encodeURIComponent(Z)}=${encodeURIComponent(E)}`;if(L.maxAge)W+=`; Max-Age=${L.maxAge}`;if(L.expires)W+=`; Expires=${L.expires.toUTCString()}`;if(L.path)W+=`; Path=${L.path}`;if(L.domain)W+=`; Domain=${L.domain}`;if(L.secure)W+="; Secure";if(L.httpOnly)W+="; HttpOnly";if(L.sameSite)W+=`; SameSite=${L.sameSite}`;return J?.append("Set-Cookie",W),this},async getCookie(Z){if(!$){let E=F.headers.get("cookie");if(E)$=await T(E)}return Z?$[Z]||null:$}}}async function T(F){let z={};if(!F)return z;return F.split(";").forEach((J)=>{let[U,X]=J?.trim()?.split("=");if(U&&X)z[U.trim()]=X.split(" ")[0].trim()}),z}function C(F,z){let G={},J=F.split("/"),[U]=z.split("?"),X=U.split("/");if(J.length!==X.length)return null;return J.forEach((Y,$)=>{if(Y.startsWith(":")){let _=Y.slice(1);G[_]=X[$]}}),G}async function b(F){let z=F.headers.get("Content-Type")||"";if(!z)return{};try{if(z.startsWith("application/json"))return await F.json();if(z.startsWith("application/x-www-form-urlencoded")){let G=await F.text();return Object.fromEntries(new URLSearchParams(G))}if(z.startsWith("multipart/form-data")){let G=await F.formData();return v(G)}return{error:"Unknown request body type"}}catch(G){return{error:"Invalid request body format"}}}function v(F){let z={};for(let[G,J]of F.entries())z[G]=J;return z}async function j(F,z,G,J){let U=B(F,z,G),X=J.trie.search(G.pathname,F.method);if(!X||!X.handler)return new Response(`Route not found for ${G.pathname}`,{status:404});if(X.method!==F.method)return new Response("Method not allowed",{status:405});if(X.isDynamic)F.routePattern=X.path;if(J.corsConfig){let Y=await I(F,U,J.corsConfig);if(Y)return Y}if(J.hasOnReqHook&&J.hooks.onRequest)J.hooks.onRequest(U,z);if(J.filters.length>0){let Y=F.routePattern??G.pathname;if(J.filters.includes(Y)===!1)if(J.filterFunction){let _=await J?.filterFunction(U);if(_)return _}else return new Response(JSON.stringify({message:"Authentication required"}),{status:400})}if(J.hasMiddleware){let Y=[...J.globalMiddlewares,...J.middlewares.get(G.pathname)||[]];for(let $ of Y){let _=await $(U,z);if(_)return _}}if(J.hasPreHandlerHook&&J.hooks.preHandler){let Y=await J.hooks.preHandler(U);if(Y)return Y}try{let Y=await X.handler(U);if(J.hasPostHandlerHook&&J.hooks.postHandler)await J.hooks.postHandler(U);if(J.hasOnSendHook&&J.hooks.onSend){let $=await J.hooks.onSend(U,Y);if($)return $}return Y??new Response("No response from handler",{status:204})}catch(Y){return new Response("Internal Server Error",{status:500})}}async function I(F,z,G={}){let J=F.headers.get("origin")??"*",U=G?.origin,X=G?.allowedHeaders??["Content-Type","Authorization"],Y=G?.methods??["GET","POST","PUT","DELETE","OPTIONS"],$=G?.credentials??!1,_=G?.exposedHeaders??[];if(z.setHeader("Access-Control-Allow-Methods",Y),z.setHeader("Access-Control-Allow-Headers",X),z.setHeader("Access-Control-Allow-Credentials",$),_.length)z.setHeader("Access-Control-Expose-Headers",_);if(U==="*")z.setHeader("Access-Control-Allow-Origin","*");else if(Array.isArray(U))if(J&&U.includes(J))z.setHeader("Access-Control-Allow-Origin",J);else if(U.includes("*"))z.setHeader("Access-Control-Allow-Origin","*");else return z.status(403).json({message:"CORS not allowed"});else if(typeof U==="string")if(J===U)z.setHeader("Access-Control-Allow-Origin",J);else return z.status(403).json({message:"CORS not allowed"});else return z.status(403).json({message:"CORS not allowed"});if(z.setHeader("Access-Control-Allow-Origin",J),F.method==="OPTIONS")return z.setHeader("Access-Control-Max-Age","86400"),z.status(204).text("");return null}function M(F){let{time:z=60000,max:G=100,message:J="Rate limit exceeded. Please try again later."}=F,U=new Map;return(X)=>{let Y=new Date,$=X.getIP().address;if(!U.has($))U.set($,{count:0,startTime:Y});let _=U.get($);if(_)if(Y-_.startTime>z)_.count=1,_.startTime=Y;else _.count++;if(_&&_.count>G)return X.status(429).json({error:J});X.next()}}class D{routes;globalMiddlewares;middlewares;trie;hasOnReqHook;hasMiddleware;hasPreHandlerHook;hasPostHandlerHook;hasOnSendHook;hooks;corsConfig;filters;filterFunction;constructor(){this.routes=[],this.filters=[],this.filterFunction=null,this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new Q,this.corsConfig=null,this.hasMiddleware=!1,this.hasOnReqHook=!1,this.hasPreHandlerHook=!1,this.hasPostHandlerHook=!1,this.hasOnSendHook=!1,this.hooks={onRequest:null,preHandler:null,postHandler:null,onSend:null,onError:null,onClose:null}}filter(){return{routeMatcher:(...F)=>{return this.routes=F.sort(),this.filter()},permitAll:()=>{for(let F of this?.routes)this.filters.push(F);return this.filter()},require:(F)=>{if(!F||typeof F!=="function")return new Response(JSON.stringify({message:"Authentication required"}),{status:400});this.filterFunction=F}}}cors(F){this.corsConfig=F}addHooks(F,z){if(typeof F!=="string")throw new Error("hookName must be a string");if(typeof z!=="function")throw new Error("callback must be a instance of function");if(this.hooks.hasOwnProperty(F))this.hooks[F]=z;else throw new Error(`Unknown hook type: ${F}`)}compile(){if(this.globalMiddlewares.length>0)this.hasMiddleware=!0;for(let[F,z]of this.middlewares.entries())if(z.length>0){this.hasMiddleware=!0;break}if(this.hooks.onRequest)this.hasOnReqHook=!0;if(this.hooks.preHandler)this.hasPreHandlerHook=!0;if(this.hooks.postHandler)this.hasPostHandlerHook=!0;if(this.hooks.onSend)this.hasOnSendHook=!0}listen(F,z,{sslCert:G=null,sslKey:J=null}={}){if(typeof Bun==="undefined")throw new Error(".listen() is designed to run on Bun only...");if(typeof F!=="number")throw new Error("Port must be a numeric value");this.compile();let U=this,X={port:F,fetch:async($,_)=>{let A=new URL($.url);try{return await j($,_,A,this)}catch(V){return new Response("Internal Server Error",{status:500})}},onClose(){console.log("Server is shutting down...")}};if(G&&J)X.certFile=G,X.keyFile=J;let Y=Bun.serve(X);if(typeof z==="function")return z();if(G&&J)console.log(`HTTPS server is running on https://localhost:${F}`);else console.log(`HTTP server is running on http://localhost:${F}`);return Y}register(F,z){if(typeof F!=="string")throw new Error("path must be a string");if(typeof z!=="object")throw new Error("handler parameter should be a instance of router object",z);let G=Object.entries(z.trie.root.children);z.trie.root.subMiddlewares.forEach((J,U)=>{if(!this.middlewares.has(F+U))this.middlewares.set(F+U,[]);J?.forEach((X)=>{if(!this.middlewares.get(F+U)?.includes(X))this.middlewares.get(F+U)?.push(X)})});for(let[J,U]of G){let X=F+U?.path,Y=U.handler[0],$=U.method[0];this.trie.insert(X,{handler:Y,method:$})}z.trie=new Q}#z(F,z,G){if(typeof z!=="string")throw new Error("Path must be a string type");if(typeof F!=="string")throw new Error("method must be a string type");let J=G.slice(0,-1),U=G[G.length-1];if(!this.middlewares.has(z))this.middlewares.set(z,[]);J.forEach((X)=>{if(z==="/"){if(!this.globalMiddlewares.includes(X))this.globalMiddlewares.push(X)}else if(!this.middlewares.get(z)?.includes(X))this.middlewares.get(z)?.push(X)}),this.trie.insert(z,{handler:U,method:F})}use(F,z){if(typeof F==="function"){if(!this.globalMiddlewares.includes(F))this.globalMiddlewares.push(F);return}let G=F;if(!this.middlewares.has(G))this.middlewares.set(G,[]);if(z){if(!this.middlewares.get(G)?.includes(z))this.middlewares.get(G)?.push(z)}}get(F,...z){return this.#z("GET",F,z),this}post(F,...z){return this.#z("POST",F,z),this}put(F,...z){return this.#z("PUT",F,z),this}patch(F,...z){return this.#z("PATCH",F,z),this}delete(F,...z){return this.#z("DELETE",F,z),this}}class N extends D{constructor(){super()}#z(F,z,G){if(!this.trie.root.subMiddlewares.has(z))this.trie.root.subMiddlewares.set(z,[]);let J=G.slice(0,-1),U=this.trie.root.subMiddlewares.get(z);J.forEach((Y)=>{if(!U?.includes(Y))U?.push(Y)});let X=G[G.length-1];this.trie.insert(z,{handler:X,method:F})}get(F,...z){return this.#z("GET",F,z),this}post(F,...z){return this.#z("POST",F,z),this}put(F,...z){return this.#z("PUT",F,z),this}patch(F,...z){return this.#z("PATCH",F,z),this}delete(F,...z){return this.#z("DELETE",F,z),this}}var x=N;export{x as default};
package/dist/trie.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ import type { handlerFunction, HttpMethod, RouteT } from "./types";
2
+ declare class TrieNode {
3
+ children: Record<string, TrieNode>;
4
+ isEndOfWord: boolean;
5
+ handler: handlerFunction[];
6
+ isDynamic: boolean;
7
+ pattern: string;
8
+ path: string;
9
+ method: string[];
10
+ subMiddlewares: Map<string, handlerFunction[]>;
11
+ constructor();
12
+ }
13
+ export default class Trie {
14
+ root: TrieNode;
15
+ constructor();
16
+ insert(path: string, route: RouteT): void;
17
+ search(path: string, method: HttpMethod): {
18
+ path: string;
19
+ handler: handlerFunction;
20
+ isDynamic: boolean;
21
+ pattern: string;
22
+ method: string;
23
+ } | {
24
+ path: string;
25
+ handler: handlerFunction[];
26
+ isDynamic: boolean;
27
+ pattern: string;
28
+ method: string;
29
+ } | null;
30
+ }
31
+ export {};
package/dist/trie.js CHANGED
@@ -1 +1 @@
1
- class C{children;isEndOfWord;handler;isDynamic;pattern;path;method;subMiddlewares;constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class E{root;constructor(){this.root=new C}insert(w,z){let b=this.root;const B=w.split("/").filter(Boolean);if(w==="/"){b.isEndOfWord=!0,b.handler.push(z.handler),b.path=w,b.method.push(z.method);return}for(let j of B){let A=!1,q=j;if(j.startsWith(":"))A=!0,q=":";if(!b.children[q])b.children[q]=new C;b=b.children[q],b.isDynamic=A,b.pattern=j}b.isEndOfWord=!0,b.method.push(z.method),b.handler.push(z.handler),b.path=w}search(w,z){let b=this.root;const B=w.split("/").filter(Boolean);for(let A of B){let q=A;if(!b.children[q])if(b.children[":"])b=b.children[":"];else return null;else b=b.children[q]}let j=b.method.indexOf(z);if(j!==-1)return{path:b.path,handler:b.handler[j],isDynamic:b.isDynamic,pattern:b.pattern,method:b.method[j]};return{path:b.path,handler:b.handler,isDynamic:b.isDynamic,pattern:b.pattern,method:b.method[j]}}}export{E as default};
1
+ class C{children;isEndOfWord;handler;isDynamic;pattern;path;method;subMiddlewares;constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class E{root;constructor(){this.root=new C}insert(w,z){let b=this.root,B=w.split("/").filter(Boolean);if(w==="/"){b.isEndOfWord=!0,b.handler.push(z.handler),b.path=w,b.method.push(z.method);return}for(let j of B){let A=!1,q=j;if(j.startsWith(":"))A=!0,q=":";if(!b.children[q])b.children[q]=new C;b=b.children[q],b.isDynamic=A,b.pattern=j}b.isEndOfWord=!0,b.method.push(z.method),b.handler.push(z.handler),b.path=w}search(w,z){let b=this.root,B=w.split("/").filter(Boolean);for(let A of B){let q=A;if(!b.children[q])if(b.children[":"])b=b.children[":"];else return null;else b=b.children[q]}let j=b.method.indexOf(z);if(j!==-1)return{path:b.path,handler:b.handler[j],isDynamic:b.isDynamic,pattern:b.pattern,method:b.method[j]};return{path:b.path,handler:b.handler,isDynamic:b.isDynamic,pattern:b.pattern,method:b.method[j]}}}export{E as default};
@@ -0,0 +1,117 @@
1
+ import { Server } from "bun";
2
+ export type listenCalllBackType = () => void;
3
+ export type handlerFunction = (ctx: ContextType, server?: Server) => Response | Promise<Response | null | void>;
4
+ export type middlewareFunc = (ctx: ContextType, server?: Server) => void | Response | Promise<Response>;
5
+ export type HookFunction = (ctx: ContextType, result?: Response | null | void, server?: Server) => Response | Promise<Response | null | void>;
6
+ export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD";
7
+ export declare enum HookType {
8
+ onRequest = "onRequest",
9
+ preHandler = "preHandler",
10
+ postHandler = "postHandler",
11
+ onSend = "onSend",
12
+ onError = "onError",
13
+ onClose = "onClose"
14
+ }
15
+ export interface Hooks {
16
+ onRequest: HookFunction | null;
17
+ preHandler: HookFunction | null;
18
+ postHandler: HookFunction | null;
19
+ onSend: HookFunction | null;
20
+ onError: HookFunction | null;
21
+ onClose: HookFunction | null;
22
+ }
23
+ export interface ContextType {
24
+ req: Request;
25
+ server: Server;
26
+ url: URL;
27
+ next: () => void;
28
+ status: (status: number) => this;
29
+ getIP: () => any;
30
+ body: () => Promise<any>;
31
+ setHeader: (key: string, value: any) => this;
32
+ set: (key: string, value: any) => this;
33
+ get: (key: string) => any;
34
+ setAuth: (authStatus: boolean) => this;
35
+ getAuth: () => boolean;
36
+ json: (data: Object, status?: number) => Response;
37
+ text: (data: string, status?: number) => Response;
38
+ html: (filePath: string, status?: number) => Response;
39
+ file: (filePath: string, status?: number) => Response;
40
+ redirect: (path: string, status?: number) => Response;
41
+ getParams: (props?: any) => any;
42
+ getQuery: (props?: any) => any;
43
+ cookie: (name: string, value: string, options?: CookieOptions) => Promise<this>;
44
+ getCookie: (cookieName?: string) => Promise<any>;
45
+ }
46
+ export interface CookieOptions {
47
+ maxAge?: number;
48
+ expires?: Date;
49
+ path?: string;
50
+ domain?: string;
51
+ secure?: boolean;
52
+ httpOnly?: boolean;
53
+ sameSite?: "Strict" | "Lax" | "None";
54
+ }
55
+ export interface RouteNodeType {
56
+ path: string;
57
+ handler: Function[];
58
+ method: string[];
59
+ }
60
+ export interface RouteHandlerT {
61
+ method: string;
62
+ handler: (ctx: ContextType) => Promise<Response | null | void>;
63
+ isDynamic?: boolean;
64
+ path?: string;
65
+ }
66
+ export interface DieselT {
67
+ hasOnReqHook: boolean;
68
+ hasMiddleware: boolean;
69
+ hasPreHandlerHook: boolean;
70
+ hasPostHandlerHook: boolean;
71
+ hasOnSendHook: boolean;
72
+ hooks: {
73
+ onRequest: ((ctx: ContextType, serer?: Server) => void) | null;
74
+ preHandler: ((ctx: ContextType, serer?: Server) => Promise<Response | void | null>) | null;
75
+ postHandler: ((ctx: ContextType, serer?: Server) => Promise<Response | void | null>) | null;
76
+ onSend: ((ctx?: ContextType, result?: Response | null | void, serer?: Server) => Promise<Response | void | null>) | null;
77
+ };
78
+ filters: string[];
79
+ filterFunction: (ctx: ContextType) => void | Response | Promise<Response | void>;
80
+ corsConfig: corsT | null;
81
+ globalMiddlewares: Array<(ctx: ContextType, serer?: Server) => void | Promise<Response | null | void>>;
82
+ middlewares: Map<string, Array<(ctx: ContextType, serer?: Server) => void | Promise<Response | null | void>>>;
83
+ trie: {
84
+ search: (pathname: string, method: string) => RouteHandlerT | undefined;
85
+ };
86
+ }
87
+ export interface RouteCache {
88
+ [key: string]: RouteHandlerT | undefined;
89
+ }
90
+ declare global {
91
+ interface Request {
92
+ routePattern?: string;
93
+ }
94
+ }
95
+ export interface ParseBodyResult {
96
+ error?: string;
97
+ data?: any;
98
+ }
99
+ export interface RouteT {
100
+ method: string;
101
+ handler: handlerFunction;
102
+ }
103
+ export type corsT = {
104
+ origin?: string | string[] | null;
105
+ methods?: string | string[] | null;
106
+ allowedHeaders?: string | string[] | null;
107
+ exposedHeaders?: string | string[] | null;
108
+ credentials?: boolean | null;
109
+ maxAge?: number;
110
+ preflightContinue?: boolean;
111
+ optionsSuccessStatus?: number;
112
+ } | null;
113
+ export interface FilterMethods {
114
+ routeMatcher: (...routes: string[]) => FilterMethods;
115
+ permitAll: () => FilterMethods;
116
+ require: (fnc?: middlewareFunc) => Response | void;
117
+ }
@@ -0,0 +1,7 @@
1
+ import { ContextType } from "./types";
2
+ export default function rateLimit(props: {
3
+ time?: number;
4
+ max?: number;
5
+ message?: string;
6
+ }): (ctx: ContextType) => void | Response;
7
+ export declare const binaryS: (arr: string[], target: string, start: number, end: number) => boolean;
@@ -0,0 +1,52 @@
1
+ import {Diesel, rateLimit} from "../src/main";
2
+
3
+ const app = new Diesel()
4
+
5
+ // app.cors({
6
+ // origin: ['http://localhost:5173','*'],
7
+ // methods: 'GET,POST,PUT,DELETE',
8
+ // allowedHeaders: 'Content-Type,Authorization'
9
+ // })
10
+
11
+ function h() {
12
+ return new Response("hello world")
13
+ }
14
+
15
+ const limiter = rateLimit({
16
+ time: 60000, // Time window in milliseconds (e.g., 1 minute)
17
+ max: 10, // Maximum number of requests allowed in the time window
18
+ message: "Rate limit exceeded. Please try again later." // Custom error message
19
+ });
20
+ // app.use(h)
21
+ // app.use(limiter)
22
+
23
+ app
24
+ .filter()
25
+ .routeMatcher('/api/user/register','/api/user/login','/test/:id','/')
26
+ .permitAll()
27
+ .require()
28
+
29
+ // .require(you can pass jwt auth parser)
30
+
31
+ app.get("/", async(xl) => {
32
+ // const ip = xl.req
33
+ // console.log(ip)
34
+ return xl.json({
35
+ message: 'Hello from Express!',
36
+ author: 'Pradeep',
37
+ app: 'Express App',
38
+ features: ['Fast', 'Flexible', 'Lightweight']
39
+ });
40
+ });
41
+
42
+ app.get("/test/:id", async (xl) => {
43
+ const q = xl.getQuery();
44
+ const params = xl.getParams('id');
45
+ return new Response(JSON.stringify({ msg: "hello world", q, params }));
46
+ });
47
+
48
+ app.get("/ok",(xl)=>{
49
+ return xl.status(200).text("kaise ho??")
50
+ })
51
+
52
+ app.listen(3000)
@@ -3,7 +3,7 @@
3
3
  "version": "1.0.0",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
- "test": "echo \"Error: no test specified\" && exit 1"
6
+ "test": "bun test"
7
7
  },
8
8
  "keywords": [],
9
9
  "author": "",