diesel-core 0.0.17 → 0.0.19

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/CONTRIBUTING.md CHANGED
@@ -1,3 +1,3 @@
1
1
  only i know folder structure and codebase , if u dont understand it dont worry , just ping me.
2
2
 
3
- if you changes code OR fixing bugs so after doing make sure to run tsc
3
+ if you changes code OR fixing bugs so after doing make sure to run tsc and bun build.js
package/README.md CHANGED
@@ -19,26 +19,34 @@ bun add diesel-core
19
19
 
20
20
  ### Code Example
21
21
  ```javascript
22
- import Diesel from "diesel-core"
22
+ import {Diesel} from "diesel-core"
23
23
 
24
24
  const app = new Diesel()
25
25
  const port = 3000
26
26
 
27
27
  app.get("/", async (ctx:ContextType) => {
28
28
  return ctx.status(200).text("Hello world...!")
29
- // OR
30
- // return xl.text("Hello world!")
31
- // OR
32
- // return new Response("Hello world")
33
29
  })
34
30
 
35
31
  // Start the server
36
32
  app.listen(port, () => {
37
33
  console.log(`diesel is running on port ${port}`)
38
34
  })
35
+ ```
36
+
37
+ # CORS
39
38
 
39
+ ### Diesel supports cors out of the box
40
+
41
+ ``` javascript
42
+ app.cors({
43
+ origin: ['http://localhost:5173','*'],
44
+ methods: 'GET,POST,PUT,DELETE',
45
+ allowedHeaders: 'Content-Type,Authorization'
46
+ })
40
47
  ```
41
- ## Filter and Route Security
48
+
49
+ # Filter and Route Security
42
50
  **Diesel** provides a simple way to manage public and protected routes by using a filter() method. You can define specific routes to be publicly accessible, while others will require authentication or custom middleware functions.
43
51
 
44
52
  ### How to Use the Filter
@@ -47,7 +55,7 @@ The **filter()** method allows you to secure certain endpoints while keeping oth
47
55
 
48
56
  ### Example Usage
49
57
  ```javascript
50
- import Diesel from "diesel-core";
58
+ import {Diesel} from "diesel-core";
51
59
  import jwt from 'jsonwebtoken';
52
60
 
53
61
 
@@ -100,7 +108,7 @@ app.listen(port, () => {
100
108
  })
101
109
 
102
110
  ```
103
- ## Filter Methods
111
+ # Filter Methods
104
112
  1. **routeMatcher(...routes: string[])** : Passed endpoints in this routeMatcher will be ***Public*** means they don't need authentication, including those with dynamic parameters (e.g., /test/:id).
105
113
 
106
114
  ```javascript
@@ -122,7 +130,7 @@ app.listen(port, () => {
122
130
 
123
131
  * **Protected Routes** : For other routes ***(like /api/user/profile)***, you'll want to require authentication or custom middleware. Use require(authJwt) to ensure that the user is authenticated before accessing these routes.
124
132
 
125
- ## Using Hooks in DieselJS
133
+ # Using Hooks in DieselJS
126
134
 
127
135
  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.
128
136
 
@@ -133,6 +141,7 @@ DieselJS allows you to enhance your request handling by utilizing hooks at vario
133
141
  2. **preHandler**: Invoked just before the request handler executes.
134
142
  3. **postHandler**: Executed after the request handler completes but before sending the response.
135
143
  4. **onSend**: Called just before the response is sent to the client.
144
+ 5. **onError** : Executes if any error occurs
136
145
 
137
146
  ### How to Define Hooks
138
147
 
@@ -141,10 +150,19 @@ To define hooks in your DieselJS application, you can add them directly to your
141
150
  ### Example Usage
142
151
 
143
152
  ```javascript
153
+
154
+ // define and onError hook
155
+
156
+ app.addHooks("onError",(error,req,url,server) => {
157
+ console.log(`error occured ${error.message}`)
158
+ // retunr new Response(......)
159
+ })
160
+
144
161
  // Define an onRequest hook
145
- app.addHooks("onRequest",(xl) =>{
146
- console.log(`Request received: ${xl.req.method} ${xl.req.url}`);
162
+ app.addHooks("onRequest",(req,url,server) =>{
163
+ console.log(`Request received: ${req.method} ${url}`);
147
164
  })
165
+ // you get req,url & server instance in onReq
148
166
 
149
167
  // Define a preHandler hook
150
168
  app.addHooks("preHandler",(xl) =>{
@@ -218,9 +236,9 @@ app.get("/set-cookie", async(xl) => {
218
236
  path: "/",
219
237
  }
220
238
 
221
- await xl.cookie("accessToken", accessToken, options)
222
-
223
- await xl.cookie("refreshToken", refreshToken, options)
239
+ xl
240
+ .setCookie("accessToken", accessToken, options)
241
+ .setCookie("refreshToken", refreshToken, options)
224
242
 
225
243
  return xl.json({msg:"setting cookies"})
226
244
  })
@@ -239,8 +257,15 @@ app.get("/redirect",(xl) => {
239
257
  })
240
258
  ```
241
259
  # get params
260
+
261
+ **You can use set ***Multiparams***** , ***like this***
262
+
263
+ ```javascript
264
+ app.get("/product/:productId/:productName)
265
+ ```
266
+
242
267
  ```javascript
243
- app.get("/hello/:id",(xl) => {
268
+ app.get("/hello/:id/",(xl) => {
244
269
  const id = xl.getParams("id")
245
270
  const query = xl.getQuery() // you can pass query name also , you wanna get
246
271
  return xl.json({ msg: "Hello", id });
package/build.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import path from 'path';
2
2
  const entryPoints = [
3
- './main/main.js',
4
- './main/ctx.js',
5
- './main/handleRequest.js',
6
- './main/trie.js',
7
- './main/router.js',
8
- './main/utils.js'
3
+ './src/main.ts',
4
+ './src/ctx.ts',
5
+ './src/handleRequest.ts',
6
+ './src/trie.ts',
7
+ './src/router.ts',
8
+ './src/utils.ts'
9
9
  ];
10
10
 
11
11
  entryPoints.forEach(entry => {
@@ -21,4 +21,12 @@ entryPoints.forEach(entry => {
21
21
  }
22
22
  });
23
23
 
24
- // Bun.spawn(['rm','-rf','./main'])
24
+ // Bun.spawn(['rm','-rf','./main'])
25
+
26
+ // oha test
27
+ // oha -c 500 -n 100000 -H "Cookie: accessToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoicGsiLCJhZ2UiOjIyLCJpYXQiOjE3Mjk5MjQxOTQsImV4cCI6MTczMDAxMDU5NH0._dEjx5iUuOLoq15-xTPgXOemfzIPrg06Qmruiv-I5cc" http://localhost:3000/
28
+
29
+ // bombardier
30
+
31
+
32
+ // bombardier -c 500 -n 100000 -H "Cookie: accessToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoicGsiLCJhZ2UiOjIyLCJpYXQiOjE3Mjk5MjQxOTQsImV4cCI6MTczMDAxMDU5NH0._dEjx5iUuOLoq15-xTPgXOemfzIPrg06Qmruiv-I5cc" http://localhost:3000/
package/dist/ctx.js CHANGED
@@ -1 +1 @@
1
- var w=function(I,J,G,F){function Y(R){return R instanceof G?R:new G(function(L){L(R)})}return new(G||(G=Promise))(function(R,L){function X(U){try{Z(F.next(U))}catch(W){L(W)}}function $(U){try{Z(F.throw(U))}catch(W){L(W)}}function Z(U){U.done?R(U.value):Y(U.value).then(X,$)}Z((F=F.apply(I,J||[])).next())})};function O(I,J,G){let F=new Headers,Y={},R=!1,L,X=null,$,Z,U=200,W={};return{req:I,server:J,url:G,next:()=>{},getUser(){return W},setUser(z){if(z)W=z},status(z){return U=z,this},getIP(){return this.server.requestIP(this.req)},body(){return w(this,void 0,void 0,function*(){if(!Z)Z=yield V(I);if(Z.error)return new Response(JSON.stringify({error:Z.error}),{status:400});return Z})},setHeader(z,E){return F.set(z,E),this},set(z,E){return Y[z]=E,this},get(z){return Y[z]||null},setAuth(z){return R=z,this},getAuth(){return R},text(z,E){return new Response(z,{status:E!==null&&E!==void 0?E:U,headers:F})},json(z,E){return new Response(JSON.stringify(z),{status:E!==null&&E!==void 0?E:U,headers:F})},html(z,E){return new Response(Bun.file(z),{status:E!==null&&E!==void 0?E:U,headers:F})},file(z,E){return new Response(Bun.file(z),{status:E!==null&&E!==void 0?E:U,headers:F})},redirect(z,E){return F.set("Location",z),new Response(null,{status:E!==null&&E!==void 0?E:302,headers:F})},getParams(z){if(!$)$=x(I===null||I===void 0?void 0:I.routePattern,G===null||G===void 0?void 0:G.pathname);return z?$[z]||{}:$},getQuery(z){try{if(!L)L=Object.fromEntries(G.searchParams);return z?L[z]||{}:L}catch(E){return{}}},cookie(z,E,M={}){let K=`${encodeURIComponent(z)}=${encodeURIComponent(E)}`;if(M.maxAge)K+=`; Max-Age=${M.maxAge}`;if(M.expires)K+=`; Expires=${M.expires.toUTCString()}`;if(M.path)K+=`; Path=${M.path}`;if(M.domain)K+=`; Domain=${M.domain}`;if(M.secure)K+="; Secure";if(M.httpOnly)K+="; HttpOnly";if(M.sameSite)K+=`; SameSite=${M.sameSite}`;return F===null||F===void 0||F.append("Set-Cookie",K),this},getCookie(z){var E;if(!X||Object.keys(X).length===0){let M=(E=I.headers)===null||E===void 0?void 0:E.get("cookie");if(M)X=H(M);else return null}if(!X)return null;return z?X[z]!==void 0?X[z]:null:X}}}function H(I){let J={};if(!I)return J;return I.split(";").forEach((F)=>{var Y;let[R,L]=(Y=F===null||F===void 0?void 0:F.trim())===null||Y===void 0?void 0:Y.split("=");if(R&&L)J[R.trim()]=L.split(" ")[0].trim()}),J}function x(I,J){let G={},F=I.split("/"),[Y]=J.split("?"),R=Y.split("/");if(F.length!==R.length)return null;return F.forEach((L,X)=>{if(L.startsWith(":")){let $=L.slice(1);G[$]=R[X]}}),G}function V(I){return w(this,void 0,void 0,function*(){let J=I.headers.get("Content-Type")||"";if(!J)return{};try{if(J.startsWith("application/json"))return yield I.json();if(J.startsWith("application/x-www-form-urlencoded")){let G=yield I.text();return Object.fromEntries(new URLSearchParams(G))}if(J.startsWith("multipart/form-data")){let G=yield I.formData();return A(G)}return{error:"Unknown request body type"}}catch(G){return{error:"Invalid request body format"}}})}function A(I){let J={};for(let[G,F]of I.entries())J[G]=F;return J}export{O as default};
1
+ function K(F,L,G){let z=new Headers,M={},U=!1,I,Z=null,$,_,Y=200,x={};return{req:F,server:L,url:G,getUser(){return x},setUser(w){if(w)x=w},status(w){return Y=w,this},getIP(){return this.server.requestIP(this.req)},async getBody(){if(!_)_=await W(F);if(_.error)return new Response(JSON.stringify({error:_.error}),{status:400});return _},setHeader(w,E){return z.set(w,E),this},set(w,E){return M[w]=E,this},get(w){return M[w]||null},setAuth(w){return U=w,this},getAuth(){return U},text(w,E){return new Response(w,{status:E??Y,headers:z})},send(w,E){return new Response(w,{status:E??Y,headers:z})},json(w,E){return new Response(JSON.stringify(w),{status:E??Y,headers:z})},html(w,E){return new Response(Bun.file(w),{status:E??Y,headers:z})},file(w,E){return new Response(Bun.file(w),{status:E??Y,headers:z})},redirect(w,E){return z.set("Location",w),new Response(null,{status:E??302,headers:z})},setCookie(w,E,J={}){let X=`${encodeURIComponent(w)}=${encodeURIComponent(E)}`;if(J.maxAge)X+=`; Max-Age=${J.maxAge}`;if(J.expires)X+=`; Expires=${J.expires.toUTCString()}`;if(J.path)X+=`; Path=${J.path}`;if(J.domain)X+=`; Domain=${J.domain}`;if(J.secure)X+="; Secure";if(J.httpOnly)X+="; HttpOnly";if(J.sameSite)X+=`; SameSite=${J.sameSite}`;return z?.append("Set-Cookie",X),this},getParams(w){if(!$&&F?.routePattern)$=R(F?.routePattern,G?.pathname);return w?$[w]||{}:$},getQuery(w){try{if(!I)I=Object.fromEntries(G.searchParams);return w?I[w]||{}:I}catch(E){return{}}},getCookie(w){if(!Z){let E=F.headers.get("cookie");if(E)Z=O(E);else return null}if(!Z)return null;if(w)return Z[w]??null;else return Z}}}function O(F){let L={},G=F?.split(";");for(let z=0;z<G?.length;z++){let[M,...U]=G[z].trim().split("="),I=U?.join("=").trim();if(M)L[M.trim()]=decodeURIComponent(I)}return L}function R(F,L){let G={},z=F.split("/"),[M]=L.split("?"),U=M.split("/");if(z.length!==U.length)return null;for(let I=0;I<z.length;I++)if(z[I].startsWith(":"))G[z[I].slice(1)]=U[I];return G}async function W(F){let L=F.headers.get("Content-Type")||"";if(!L)return{};try{if(L.startsWith("application/json"))return await F.json();if(L.startsWith("application/x-www-form-urlencoded")){let G=await F.text();return Object.fromEntries(new URLSearchParams(G))}if(L.startsWith("multipart/form-data")){let G=await F.formData(),z={};for(let[M,U]of G.entries())z[M]=U;return z}return{error:"Unknown request body type"}}catch(G){return{error:"Invalid request body format"}}}export{K as default};
@@ -1 +1 @@
1
- var Q=function(L,G,E,z){function K(Y){return Y instanceof E?Y:new E(function(U){U(Y)})}return new(E||(E=Promise))(function(Y,U){function Z(I){try{$(z.next(I))}catch(W){U(W)}}function X(I){try{$(z.throw(I))}catch(W){U(W)}}function $(I){I.done?Y(I.value):K(I.value).then(Z,X)}$((z=z.apply(L,G||[])).next())})};function D(L,G,E){let z=new Headers,K={},Y=!1,U,Z=null,X,$,I=200,W={};return{req:L,server:G,url:E,next:()=>{},getUser(){return W},setUser(F){if(F)W=F},status(F){return I=F,this},getIP(){return this.server.requestIP(this.req)},body(){return Q(this,void 0,void 0,function*(){if(!$)$=yield A(L);if($.error)return new Response(JSON.stringify({error:$.error}),{status:400});return $})},setHeader(F,J){return z.set(F,J),this},set(F,J){return K[F]=J,this},get(F){return K[F]||null},setAuth(F){return Y=F,this},getAuth(){return Y},text(F,J){return new Response(F,{status:J!==null&&J!==void 0?J:I,headers:z})},json(F,J){return new Response(JSON.stringify(F),{status:J!==null&&J!==void 0?J:I,headers:z})},html(F,J){return new Response(Bun.file(F),{status:J!==null&&J!==void 0?J:I,headers:z})},file(F,J){return new Response(Bun.file(F),{status:J!==null&&J!==void 0?J:I,headers:z})},redirect(F,J){return z.set("Location",F),new Response(null,{status:J!==null&&J!==void 0?J:302,headers:z})},getParams(F){if(!X)X=B(L===null||L===void 0?void 0:L.routePattern,E===null||E===void 0?void 0:E.pathname);return F?X[F]||{}:X},getQuery(F){try{if(!U)U=Object.fromEntries(E.searchParams);return F?U[F]||{}:U}catch(J){return{}}},cookie(F,J,M={}){let V=`${encodeURIComponent(F)}=${encodeURIComponent(J)}`;if(M.maxAge)V+=`; Max-Age=${M.maxAge}`;if(M.expires)V+=`; Expires=${M.expires.toUTCString()}`;if(M.path)V+=`; Path=${M.path}`;if(M.domain)V+=`; Domain=${M.domain}`;if(M.secure)V+="; Secure";if(M.httpOnly)V+="; HttpOnly";if(M.sameSite)V+=`; SameSite=${M.sameSite}`;return z===null||z===void 0||z.append("Set-Cookie",V),this},getCookie(F){var J;if(!Z||Object.keys(Z).length===0){let M=(J=L.headers)===null||J===void 0?void 0:J.get("cookie");if(M)Z=T(M);else return null}if(!Z)return null;return F?Z[F]!==void 0?Z[F]:null:Z}}}function T(L){let G={};if(!L)return G;return L.split(";").forEach((z)=>{var K;let[Y,U]=(K=z===null||z===void 0?void 0:z.trim())===null||K===void 0?void 0:K.split("=");if(Y&&U)G[Y.trim()]=U.split(" ")[0].trim()}),G}function B(L,G){let E={},z=L.split("/"),[K]=G.split("?"),Y=K.split("/");if(z.length!==Y.length)return null;return z.forEach((U,Z)=>{if(U.startsWith(":")){let X=U.slice(1);E[X]=Y[Z]}}),E}function A(L){return Q(this,void 0,void 0,function*(){let G=L.headers.get("Content-Type")||"";if(!G)return{};try{if(G.startsWith("application/json"))return yield L.json();if(G.startsWith("application/x-www-form-urlencoded")){let E=yield L.text();return Object.fromEntries(new URLSearchParams(E))}if(G.startsWith("multipart/form-data")){let E=yield L.formData();return N(E)}return{error:"Unknown request body type"}}catch(E){return{error:"Invalid request body format"}}})}function N(L){let G={};for(let[E,z]of L.entries())G[E]=z;return G}var O=function(L,G,E,z){function K(Y){return Y instanceof E?Y:new E(function(U){U(Y)})}return new(E||(E=Promise))(function(Y,U){function Z(I){try{$(z.next(I))}catch(W){U(W)}}function X(I){try{$(z.throw(I))}catch(W){U(W)}}function $(I){I.done?Y(I.value):K(I.value).then(Z,X)}$((z=z.apply(L,G||[])).next())})};function R(L,G,E,z){return O(this,void 0,void 0,function*(){var K,Y,U;let Z=z.trie.search(E.pathname,L.method);if(!Z||Z.method!==L.method)return new Response(Z?"Method not allowed":`Route not found for ${E.pathname}`,{status:Z?405:404});if(Z.isDynamic)L.routePattern=Z.path;let X=D(L,G,E);if(z.corsConfig){let I=C(L,X,z.corsConfig);if(I)return I}if(z.hasOnReqHook&&z.hooks.onRequest)z.hooks.onRequest(X,G);if(z.hasFilterEnabled){let I=(K=L.routePattern)!==null&&K!==void 0?K:E.pathname;if(z.filters.includes(I)===!1)if(z.filterFunction)try{let F=yield z.filterFunction(X,G);if(F)return F}catch(F){return console.error("Error in filterFunction:",F),new Response(JSON.stringify({message:"Internal Server Error"}),{status:500})}else return new Response(JSON.stringify({message:"Authentication required"}),{status:400})}if(z.hasMiddleware){for(let W of z.globalMiddlewares){let F=yield W(X,G);if(F)return F}let I=z.middlewares.get(E.pathname)||[];for(let W of I){let F=yield W(X,G);if(F)return F}}if(z.hasPreHandlerHook&&z.hooks.preHandler){let I=yield z.hooks.preHandler(X);if(I)return I}let $=z.hasPreHandlerHook?yield(U=(Y=z.hooks).preHandler)===null||U===void 0?void 0:U.call(Y,X):null;if($)return $;try{let I=yield Z.handler(X);if(z.hasPostHandlerHook&&z.hooks.postHandler)yield z.hooks.postHandler(X);if(z.hasOnSendHook&&z.hooks.onSend){let W=yield z.hooks.onSend(X,I);if(W)return W}return I!==null&&I!==void 0?I:new Response("No response from handler",{status:204})}catch(I){return new Response("Internal Server Error",{status:500})}})}function C(L,G,E={}){var z,K,Y,U,Z;let X=(z=L.headers.get("origin"))!==null&&z!==void 0?z:"*",$=E===null||E===void 0?void 0:E.origin,I=(K=E===null||E===void 0?void 0:E.allowedHeaders)!==null&&K!==void 0?K:["Content-Type","Authorization"],W=(Y=E===null||E===void 0?void 0:E.methods)!==null&&Y!==void 0?Y:["GET","POST","PUT","DELETE","OPTIONS"],F=(U=E===null||E===void 0?void 0:E.credentials)!==null&&U!==void 0?U:!1,J=(Z=E===null||E===void 0?void 0:E.exposedHeaders)!==null&&Z!==void 0?Z:[];if(G.setHeader("Access-Control-Allow-Methods",W),G.setHeader("Access-Control-Allow-Headers",I),G.setHeader("Access-Control-Allow-Credentials",F),J.length)G.setHeader("Access-Control-Expose-Headers",J);if($==="*")G.setHeader("Access-Control-Allow-Origin","*");else if(Array.isArray($))if(X&&$.includes(X))G.setHeader("Access-Control-Allow-Origin",X);else if($.includes("*"))G.setHeader("Access-Control-Allow-Origin","*");else return G.status(403).json({message:"CORS not allowed"});else if(typeof $==="string")if(X===$)G.setHeader("Access-Control-Allow-Origin",X);else return G.status(403).json({message:"CORS not allowed"});else return G.status(403).json({message:"CORS not allowed"});if(G.setHeader("Access-Control-Allow-Origin",X),L.method==="OPTIONS")return G.setHeader("Access-Control-Max-Age","86400"),G.status(204).text("");return null}export{R as default};
1
+ function D(I,F,G){let z=new Headers,J={},L=!1,Z,U=null,Y,_,$=200,A={};return{req:I,server:F,url:G,getUser(){return A},setUser(E){if(E)A=E},status(E){return $=E,this},getIP(){return this.server.requestIP(this.req)},async getBody(){if(!_)_=await j(I);if(_.error)return new Response(JSON.stringify({error:_.error}),{status:400});return _},setHeader(E,X){return z.set(E,X),this},set(E,X){return J[E]=X,this},get(E){return J[E]||null},setAuth(E){return L=E,this},getAuth(){return L},text(E,X){return new Response(E,{status:X??$,headers:z})},send(E,X){return new Response(E,{status:X??$,headers:z})},json(E,X){return new Response(JSON.stringify(E),{status:X??$,headers:z})},html(E,X){return new Response(Bun.file(E),{status:X??$,headers:z})},file(E,X){return new Response(Bun.file(E),{status:X??$,headers:z})},redirect(E,X){return z.set("Location",E),new Response(null,{status:X??302,headers:z})},setCookie(E,X,K={}){let W=`${encodeURIComponent(E)}=${encodeURIComponent(X)}`;if(K.maxAge)W+=`; Max-Age=${K.maxAge}`;if(K.expires)W+=`; Expires=${K.expires.toUTCString()}`;if(K.path)W+=`; Path=${K.path}`;if(K.domain)W+=`; Domain=${K.domain}`;if(K.secure)W+="; Secure";if(K.httpOnly)W+="; HttpOnly";if(K.sameSite)W+=`; SameSite=${K.sameSite}`;return z?.append("Set-Cookie",W),this},getParams(E){if(!Y&&I?.routePattern)Y=V(I?.routePattern,G?.pathname);return E?Y[E]||{}:Y},getQuery(E){try{if(!Z)Z=Object.fromEntries(G.searchParams);return E?Z[E]||{}:Z}catch(X){return{}}},getCookie(E){if(!U){let X=I.headers.get("cookie");if(X)U=T(X);else return null}if(!U)return null;if(E)return U[E]??null;else return U}}}function T(I){let F={},G=I?.split(";");for(let z=0;z<G?.length;z++){let[J,...L]=G[z].trim().split("="),Z=L?.join("=").trim();if(J)F[J.trim()]=decodeURIComponent(Z)}return F}function V(I,F){let G={},z=I.split("/"),[J]=F.split("?"),L=J.split("/");if(z.length!==L.length)return null;for(let Z=0;Z<z.length;Z++)if(z[Z].startsWith(":"))G[z[Z].slice(1)]=L[Z];return G}async function j(I){let F=I.headers.get("Content-Type")||"";if(!F)return{};try{if(F.startsWith("application/json"))return await I.json();if(F.startsWith("application/x-www-form-urlencoded")){let G=await I.text();return Object.fromEntries(new URLSearchParams(G))}if(F.startsWith("multipart/form-data")){let G=await I.formData(),z={};for(let[J,L]of G.entries())z[J]=L;return z}return{error:"Unknown request body type"}}catch(G){return{error:"Invalid request body format"}}}async function M(I,F,G,z){let J=z.trie.search(G.pathname,I.method);if(!J||J.method!==I.method){let U=J?"Method not allowed":`Route not found for ${G.pathname}`,Y=J?405:404;return new Response(JSON.stringify({message:U}),{status:Y})}if(J.isDynamic)I.routePattern=J.path;let L=D(I,F,G);if(z.corsConfig){let U=Q(I,L,z.corsConfig);if(U)return U}if(z.hasOnReqHook&&z.hooks.onRequest)z.hooks.onRequest(I,G,F);if(z.hasFilterEnabled){let U=I.routePattern??G.pathname;if(!z.filters.has(U))if(z.filterFunction)try{let Y=await z.filterFunction(L,F);if(Y)return Y}catch(Y){return console.error("Error in filterFunction:",Y),L.status(500).json({message:"Internal Server Error",error:Y.message})}else return L.status(400).json({message:"Authentication required"})}if(z.hasMiddleware){let U=z.globalMiddlewares;for(let _=0;_<U.length;_++){let $=await U[_](L,F);if($)return $}let Y=z.middlewares.get(G.pathname)||[];for(let _=0;_<Y.length;_++){let $=await Y[_](L,F);if($)return $}}if(z.hasPreHandlerHook&&z.hooks.preHandler){let U=await z.hooks.preHandler(L);if(U)return U}let Z=await J.handler(L);if(z.hasPostHandlerHook&&z.hooks.postHandler)await z.hooks.postHandler(L);if(z.hasOnSendHook&&z.hooks.onSend){let U=await z.hooks.onSend(L,Z);if(U)return U}return Z??L.status(204).json({message:"No response from this handler"})}function Q(I,F,G={}){let z=I.headers.get("origin")??"*",J=G?.origin,L=G?.allowedHeaders??["Content-Type","Authorization"],Z=G?.methods??["GET","POST","PUT","DELETE","OPTIONS"],U=G?.credentials??!1,Y=G?.exposedHeaders??[];if(F.setHeader("Access-Control-Allow-Methods",Z),F.setHeader("Access-Control-Allow-Headers",L),F.setHeader("Access-Control-Allow-Credentials",U),Y.length)F.setHeader("Access-Control-Expose-Headers",Y);if(J==="*")F.setHeader("Access-Control-Allow-Origin","*");else if(Array.isArray(J))if(z&&J.includes(z))F.setHeader("Access-Control-Allow-Origin",z);else if(J.includes("*"))F.setHeader("Access-Control-Allow-Origin","*");else return F.status(403).json({message:"CORS not allowed"});else if(typeof J==="string")if(z===J)F.setHeader("Access-Control-Allow-Origin",z);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",z),I.method==="OPTIONS")return F.setHeader("Access-Control-Max-Age","86400"),F.status(204).text("");return null}export{M as default};
package/dist/main.d.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  import Trie from "./trie.js";
2
- import rateLimit from "./utils.js";
3
- import { corsT, FilterMethods, HookFunction, HookType, middlewareFunc, type handlerFunction, type Hooks, type HttpMethod, type listenCalllBackType } from "./types.js";
2
+ import { corsT, FilterMethods, HookFunction, HookType, middlewareFunc, onError, onRequest, type handlerFunction, type Hooks, type HttpMethod, type listenCalllBackType } from "./types.js";
4
3
  import { Server } from "bun";
5
4
  export default class Diesel {
6
- routes: string[] | undefined;
5
+ tempRoutes: Map<string, any>;
7
6
  globalMiddlewares: middlewareFunc[];
8
7
  middlewares: Map<string, middlewareFunc[]>;
9
8
  trie: Trie;
@@ -12,18 +11,20 @@ export default class Diesel {
12
11
  hasPreHandlerHook: boolean;
13
12
  hasPostHandlerHook: boolean;
14
13
  hasOnSendHook: boolean;
14
+ hasOnError: boolean;
15
15
  hooks: Hooks;
16
16
  corsConfig: corsT;
17
- filters: string[];
17
+ FilterRoutes: string[] | null | undefined;
18
+ filters: Set<string>;
18
19
  filterFunction: middlewareFunc | null;
19
20
  hasFilterEnabled: boolean;
20
- wss: WebSocket | null | undefined;
21
21
  constructor();
22
22
  filter(): FilterMethods;
23
23
  cors(corsConfig: corsT): void;
24
- addHooks(typeOfHook: HookType, fnc: HookFunction): void;
24
+ addHooks(typeOfHook: HookType, fnc: HookFunction | onError | onRequest): void;
25
25
  compile(): void;
26
26
  listen(port: number, callback?: listenCalllBackType, { sslCert, sslKey }?: any): Server | void;
27
+ route(basePath: string, routerInstance: any): void;
27
28
  register(pathPrefix: string, handlerInstance: any): void;
28
29
  addRoute(method: HttpMethod, path: string, handlers: handlerFunction[]): void;
29
30
  use(pathORHandler?: string | middlewareFunc, handler?: middlewareFunc): void;
@@ -33,4 +34,3 @@ export default class Diesel {
33
34
  patch(path: string, ...handlers: handlerFunction[]): this;
34
35
  delete(path: any, ...handlers: handlerFunction[]): this;
35
36
  }
36
- export { rateLimit, };
package/dist/main.js CHANGED
@@ -1 +1 @@
1
- class A{constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class K{constructor(){this.root=new A}insert(G,J){let z=this.root,U=G.split("/").filter(Boolean);if(G==="/"){z.isEndOfWord=!0,z.handler.push(J.handler),z.path=G,z.method.push(J.method);return}for(let Y of U){let Z=!1,X=Y;if(Y.startsWith(":"))Z=!0,X=":";if(!z.children[X])z.children[X]=new A;z=z.children[X],z.isDynamic=Z,z.pattern=Y,z.method.push(J.method),z.handler.push(J.handler),z.path=G}z.isEndOfWord=!0,z.method.push(J.method),z.handler.push(J.handler),z.path=G}search(G,J){let z=this.root,U=G.split("/").filter(Boolean);for(let Z of U){let X=Z;if(!z.children[X])if(z.children[":"])z=z.children[":"];else return null;else z=z.children[X]}let Y=z.method.indexOf(J);if(Y!==-1)return{path:z.path,handler:z.handler[Y],isDynamic:z.isDynamic,pattern:z.pattern,method:z.method[Y]};return{path:z.path,handler:z.handler,isDynamic:z.isDynamic,pattern:z.pattern,method:z.method[Y]}}}var N=function(G,J,z,U){function Y(Z){return Z instanceof z?Z:new z(function(X){X(Z)})}return new(z||(z=Promise))(function(Z,X){function F($){try{V(U.next($))}catch(Q){X(Q)}}function L($){try{V(U.throw($))}catch(Q){X(Q)}}function V($){$.done?Z($.value):Y($.value).then(F,L)}V((U=U.apply(G,J||[])).next())})};function M(G,J,z){let U=new Headers,Y={},Z=!1,X,F=null,L,V,$=200,Q={};return{req:G,server:J,url:z,next:()=>{},getUser(){return Q},setUser(E){if(E)Q=E},status(E){return $=E,this},getIP(){return this.server.requestIP(this.req)},body(){return N(this,void 0,void 0,function*(){if(!V)V=yield O(G);if(V.error)return new Response(JSON.stringify({error:V.error}),{status:400});return V})},setHeader(E,W){return U.set(E,W),this},set(E,W){return Y[E]=W,this},get(E){return Y[E]||null},setAuth(E){return Z=E,this},getAuth(){return Z},text(E,W){return new Response(E,{status:W!==null&&W!==void 0?W:$,headers:U})},json(E,W){return new Response(JSON.stringify(E),{status:W!==null&&W!==void 0?W:$,headers:U})},html(E,W){return new Response(Bun.file(E),{status:W!==null&&W!==void 0?W:$,headers:U})},file(E,W){return new Response(Bun.file(E),{status:W!==null&&W!==void 0?W:$,headers:U})},redirect(E,W){return U.set("Location",E),new Response(null,{status:W!==null&&W!==void 0?W:302,headers:U})},getParams(E){if(!L)L=I(G===null||G===void 0?void 0:G.routePattern,z===null||z===void 0?void 0:z.pathname);return E?L[E]||{}:L},getQuery(E){try{if(!X)X=Object.fromEntries(z.searchParams);return E?X[E]||{}:X}catch(W){return{}}},cookie(E,W,B={}){let D=`${encodeURIComponent(E)}=${encodeURIComponent(W)}`;if(B.maxAge)D+=`; Max-Age=${B.maxAge}`;if(B.expires)D+=`; Expires=${B.expires.toUTCString()}`;if(B.path)D+=`; Path=${B.path}`;if(B.domain)D+=`; Domain=${B.domain}`;if(B.secure)D+="; Secure";if(B.httpOnly)D+="; HttpOnly";if(B.sameSite)D+=`; SameSite=${B.sameSite}`;return U===null||U===void 0||U.append("Set-Cookie",D),this},getCookie(E){var W;if(!F||Object.keys(F).length===0){let B=(W=G.headers)===null||W===void 0?void 0:W.get("cookie");if(B)F=j(B);else return null}if(!F)return null;return E?F[E]!==void 0?F[E]:null:F}}}function j(G){let J={};if(!G)return J;return G.split(";").forEach((U)=>{var Y;let[Z,X]=(Y=U===null||U===void 0?void 0:U.trim())===null||Y===void 0?void 0:Y.split("=");if(Z&&X)J[Z.trim()]=X.split(" ")[0].trim()}),J}function I(G,J){let z={},U=G.split("/"),[Y]=J.split("?"),Z=Y.split("/");if(U.length!==Z.length)return null;return U.forEach((X,F)=>{if(X.startsWith(":")){let L=X.slice(1);z[L]=Z[F]}}),z}function O(G){return N(this,void 0,void 0,function*(){let J=G.headers.get("Content-Type")||"";if(!J)return{};try{if(J.startsWith("application/json"))return yield G.json();if(J.startsWith("application/x-www-form-urlencoded")){let z=yield G.text();return Object.fromEntries(new URLSearchParams(z))}if(J.startsWith("multipart/form-data")){let z=yield G.formData();return S(z)}return{error:"Unknown request body type"}}catch(z){return{error:"Invalid request body format"}}})}function S(G){let J={};for(let[z,U]of G.entries())J[z]=U;return J}var b=function(G,J,z,U){function Y(Z){return Z instanceof z?Z:new z(function(X){X(Z)})}return new(z||(z=Promise))(function(Z,X){function F($){try{V(U.next($))}catch(Q){X(Q)}}function L($){try{V(U.throw($))}catch(Q){X(Q)}}function V($){$.done?Z($.value):Y($.value).then(F,L)}V((U=U.apply(G,J||[])).next())})};function T(G,J,z,U){return b(this,void 0,void 0,function*(){var Y,Z,X;let F=U.trie.search(z.pathname,G.method);if(!F||F.method!==G.method)return new Response(F?"Method not allowed":`Route not found for ${z.pathname}`,{status:F?405:404});if(F.isDynamic)G.routePattern=F.path;let L=M(G,J,z);if(U.corsConfig){let $=w(G,L,U.corsConfig);if($)return $}if(U.hasOnReqHook&&U.hooks.onRequest)U.hooks.onRequest(L,J);if(U.hasFilterEnabled){let $=(Y=G.routePattern)!==null&&Y!==void 0?Y:z.pathname;if(U.filters.includes($)===!1)if(U.filterFunction)try{let E=yield U.filterFunction(L,J);if(E)return E}catch(E){return console.error("Error in filterFunction:",E),new Response(JSON.stringify({message:"Internal Server Error"}),{status:500})}else return new Response(JSON.stringify({message:"Authentication required"}),{status:400})}if(U.hasMiddleware){for(let Q of U.globalMiddlewares){let E=yield Q(L,J);if(E)return E}let $=U.middlewares.get(z.pathname)||[];for(let Q of $){let E=yield Q(L,J);if(E)return E}}if(U.hasPreHandlerHook&&U.hooks.preHandler){let $=yield U.hooks.preHandler(L);if($)return $}let V=U.hasPreHandlerHook?yield(X=(Z=U.hooks).preHandler)===null||X===void 0?void 0:X.call(Z,L):null;if(V)return V;try{let $=yield F.handler(L);if(U.hasPostHandlerHook&&U.hooks.postHandler)yield U.hooks.postHandler(L);if(U.hasOnSendHook&&U.hooks.onSend){let Q=yield U.hooks.onSend(L,$);if(Q)return Q}return $!==null&&$!==void 0?$:new Response("No response from handler",{status:204})}catch($){return new Response("Internal Server Error",{status:500})}})}function w(G,J,z={}){var U,Y,Z,X,F;let L=(U=G.headers.get("origin"))!==null&&U!==void 0?U:"*",V=z===null||z===void 0?void 0:z.origin,$=(Y=z===null||z===void 0?void 0:z.allowedHeaders)!==null&&Y!==void 0?Y:["Content-Type","Authorization"],Q=(Z=z===null||z===void 0?void 0:z.methods)!==null&&Z!==void 0?Z:["GET","POST","PUT","DELETE","OPTIONS"],E=(X=z===null||z===void 0?void 0:z.credentials)!==null&&X!==void 0?X:!1,W=(F=z===null||z===void 0?void 0:z.exposedHeaders)!==null&&F!==void 0?F:[];if(J.setHeader("Access-Control-Allow-Methods",Q),J.setHeader("Access-Control-Allow-Headers",$),J.setHeader("Access-Control-Allow-Credentials",E),W.length)J.setHeader("Access-Control-Expose-Headers",W);if(V==="*")J.setHeader("Access-Control-Allow-Origin","*");else if(Array.isArray(V))if(L&&V.includes(L))J.setHeader("Access-Control-Allow-Origin",L);else if(V.includes("*"))J.setHeader("Access-Control-Allow-Origin","*");else return J.status(403).json({message:"CORS not allowed"});else if(typeof V==="string")if(L===V)J.setHeader("Access-Control-Allow-Origin",L);else return J.status(403).json({message:"CORS not allowed"});else return J.status(403).json({message:"CORS not allowed"});if(J.setHeader("Access-Control-Allow-Origin",L),G.method==="OPTIONS")return J.setHeader("Access-Control-Max-Age","86400"),J.status(204).text("");return null}function C(G){let{time:J=60000,max:z=100,message:U="Rate limit exceeded. Please try again later."}=G,Y=new Map;return(Z)=>{let X=new Date,F=Z.getIP().address;if(!Y.has(F))Y.set(F,{count:0,startTime:X});let L=Y.get(F);if(L)if(X-L.startTime>J)L.count=1,L.startTime=X;else L.count++;if(L&&L.count>z)return Z.status(429).json({error:U});Z.next()}}var H=function(G,J,z,U){function Y(Z){return Z instanceof z?Z:new z(function(X){X(Z)})}return new(z||(z=Promise))(function(Z,X){function F($){try{V(U.next($))}catch(Q){X(Q)}}function L($){try{V(U.throw($))}catch(Q){X(Q)}}function V($){$.done?Z($.value):Y($.value).then(F,L)}V((U=U.apply(G,J||[])).next())})};class R{constructor(){this.routes=[],this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new K,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},this.filters=[],this.filterFunction=null,this.hasFilterEnabled=!1,this.wss=null}filter(){return this.hasFilterEnabled=!0,{routeMatcher:(...G)=>{return this.routes=G.sort(),this.filter()},permitAll:()=>{for(let G of this===null||this===void 0?void 0:this.routes)this.filters.push(G);return this.filter()},require:(G)=>{if(G)this.filterFunction=G}}}cors(G){this.corsConfig=G}addHooks(G,J){if(typeof G!=="string")throw new Error("hookName must be a string");if(typeof J!=="function")throw new Error("callback must be a instance of function");if(this.hooks.hasOwnProperty(G))this.hooks[G]=J;else throw new Error(`Unknown hook type: ${G}`)}compile(){if(this.globalMiddlewares.length>0)this.hasMiddleware=!0;for(let[G,J]of this.middlewares.entries())if(J.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,J,{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();let Y={port:G,fetch:(X,F)=>H(this,void 0,void 0,function*(){let L=new URL(X.url);try{return yield T(X,F,L,this)}catch(V){return new Response("Internal Server Error",{status:500})}}),onClose(){console.log("Server is shutting down...")}};if(z&&U)Y.certFile=z,Y.keyFile=U;let Z=Bun.serve(Y);if(Bun===null||Bun===void 0||Bun.gc(!1),typeof J==="function")return J();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 Z}register(G,J){if(typeof G!=="string")throw new Error("path must be a string");if(typeof J!=="object")throw new Error("handler parameter should be a instance of router object",J);let z=Object.entries(J.trie.root.children);J.trie.root.subMiddlewares.forEach((U,Y)=>{if(!this.middlewares.has(G+Y))this.middlewares.set(G+Y,[]);U===null||U===void 0||U.forEach((Z)=>{var X,F;if(!((X=this.middlewares.get(G+Y))===null||X===void 0?void 0:X.includes(Z)))(F=this.middlewares.get(G+Y))===null||F===void 0||F.push(Z)})});for(let[U,Y]of z){let Z=G+(Y===null||Y===void 0?void 0:Y.path),X=Y.handler[0],F=Y.method[0];this.trie.insert(Z,{handler:X,method:F})}J.trie=new K}addRoute(G,J,z){if(typeof J!=="string")throw new Error("Path must be a string type");if(typeof G!=="string")throw new Error("method must be a string type");let U=z.slice(0,-1),Y=z[z.length-1];if(!this.middlewares.has(J))this.middlewares.set(J,[]);U.forEach((Z)=>{var X,F;if(J==="/"){if(!this.globalMiddlewares.includes(Z))this.globalMiddlewares.push(Z)}else if(!((X=this.middlewares.get(J))===null||X===void 0?void 0:X.includes(Z)))(F=this.middlewares.get(J))===null||F===void 0||F.push(Z)}),this.trie.insert(J,{handler:Y,method:G})}use(G,J){var z,U;if(typeof G==="function"){if(!this.globalMiddlewares.includes(G))this.globalMiddlewares.push(G);return}let Y=G;if(!this.middlewares.has(Y))this.middlewares.set(Y,[]);if(J){if(!((z=this.middlewares.get(Y))===null||z===void 0?void 0:z.includes(J)))(U=this.middlewares.get(Y))===null||U===void 0||U.push(J)}}get(G,...J){return this.addRoute("GET",G,J),this}post(G,...J){return this.addRoute("POST",G,J),this}put(G,...J){return this.addRoute("PUT",G,J),this}patch(G,...J){return this.addRoute("PATCH",G,J),this}delete(G,...J){return this.addRoute("DELETE",G,J),this}}export{C as rateLimit,R as default};
1
+ class B{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 A{root;constructor(){this.root=new B}insert(F,z){let G=this.root,J=F.split("/").filter(Boolean);if(F==="/"){G.isEndOfWord=!0,G.handler=[z.handler],G.path=F,G.method=[z.method];return}for(let L=0;L<J.length;L++){let U=J[L],Z=!1,X=U;if(U.startsWith(":"))Z=!0,X=":";if(!G.children[X])G.children[X]=new B;if(G=G.children[X],G.isDynamic=Z,G.pattern=U,L===J.length-1)G.handler=[z.handler],G.method=[z.method],G.isEndOfWord=!0,G.path=F}}search(F,z){let G=this.root,J=F.split("/").filter(Boolean);for(let U of J){let Z=U;if(!G.children[Z])if(G.children[":"])G=G.children[":"];else return null;else G=G.children[Z]}let L=G.method.indexOf(z);if(G.isEndOfWord&&L!==-1)return{path:G.path,handler:G.handler[L],isDynamic:G.isDynamic,pattern:G.pattern,method:G.method[L]};return null}}function K(F,z,G){let J=new Headers,L={},U=!1,Z,X=null,_,$,E=200,Q={};return{req:F,server:z,url:G,getUser(){return Q},setUser(Y){if(Y)Q=Y},status(Y){return E=Y,this},getIP(){return this.server.requestIP(this.req)},async getBody(){if(!$)$=await N(F);if($.error)return new Response(JSON.stringify({error:$.error}),{status:400});return $},setHeader(Y,W){return J.set(Y,W),this},set(Y,W){return L[Y]=W,this},get(Y){return L[Y]||null},setAuth(Y){return U=Y,this},getAuth(){return U},text(Y,W){return new Response(Y,{status:W??E,headers:J})},send(Y,W){return new Response(Y,{status:W??E,headers:J})},json(Y,W){return new Response(JSON.stringify(Y),{status:W??E,headers:J})},html(Y,W){return new Response(Bun.file(Y),{status:W??E,headers:J})},file(Y,W){return new Response(Bun.file(Y),{status:W??E,headers:J})},redirect(Y,W){return J.set("Location",Y),new Response(null,{status:W??302,headers:J})},setCookie(Y,W,D={}){let V=`${encodeURIComponent(Y)}=${encodeURIComponent(W)}`;if(D.maxAge)V+=`; Max-Age=${D.maxAge}`;if(D.expires)V+=`; Expires=${D.expires.toUTCString()}`;if(D.path)V+=`; Path=${D.path}`;if(D.domain)V+=`; Domain=${D.domain}`;if(D.secure)V+="; Secure";if(D.httpOnly)V+="; HttpOnly";if(D.sameSite)V+=`; SameSite=${D.sameSite}`;return J?.append("Set-Cookie",V),this},getParams(Y){if(!_&&F?.routePattern)_=T(F?.routePattern,G?.pathname);return Y?_[Y]||{}:_},getQuery(Y){try{if(!Z)Z=Object.fromEntries(G.searchParams);return Y?Z[Y]||{}:Z}catch(W){return{}}},getCookie(Y){if(!X){let W=F.headers.get("cookie");if(W)X=I(W);else return null}if(!X)return null;if(Y)return X[Y]??null;else return X}}}function I(F){let z={},G=F?.split(";");for(let J=0;J<G?.length;J++){let[L,...U]=G[J].trim().split("="),Z=U?.join("=").trim();if(L)z[L.trim()]=decodeURIComponent(Z)}return z}function T(F,z){let G={},J=F.split("/"),[L]=z.split("?"),U=L.split("/");if(J.length!==U.length)return null;for(let Z=0;Z<J.length;Z++)if(J[Z].startsWith(":"))G[J[Z].slice(1)]=U[Z];return G}async function N(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(),J={};for(let[L,U]of G.entries())J[L]=U;return J}return{error:"Unknown request body type"}}catch(G){return{error:"Invalid request body format"}}}async function j(F,z,G,J){let L=J.trie.search(G.pathname,F.method);if(!L||L.method!==F.method){let X=L?"Method not allowed":`Route not found for ${G.pathname}`,_=L?405:404;return new Response(JSON.stringify({message:X}),{status:_})}if(L.isDynamic)F.routePattern=L.path;let U=K(F,z,G);if(J.corsConfig){let X=C(F,U,J.corsConfig);if(X)return X}if(J.hasOnReqHook&&J.hooks.onRequest)J.hooks.onRequest(F,G,z);if(J.hasFilterEnabled){let X=F.routePattern??G.pathname;if(!J.filters.has(X))if(J.filterFunction)try{let _=await J.filterFunction(U,z);if(_)return _}catch(_){return console.error("Error in filterFunction:",_),U.status(500).json({message:"Internal Server Error",error:_.message})}else return U.status(400).json({message:"Authentication required"})}if(J.hasMiddleware){let X=J.globalMiddlewares;for(let $=0;$<X.length;$++){let E=await X[$](U,z);if(E)return E}let _=J.middlewares.get(G.pathname)||[];for(let $=0;$<_.length;$++){let E=await _[$](U,z);if(E)return E}}if(J.hasPreHandlerHook&&J.hooks.preHandler){let X=await J.hooks.preHandler(U);if(X)return X}let Z=await L.handler(U);if(J.hasPostHandlerHook&&J.hooks.postHandler)await J.hooks.postHandler(U);if(J.hasOnSendHook&&J.hooks.onSend){let X=await J.hooks.onSend(U,Z);if(X)return X}return Z??U.status(204).json({message:"No response from this handler"})}function C(F,z,G={}){let J=F.headers.get("origin")??"*",L=G?.origin,U=G?.allowedHeaders??["Content-Type","Authorization"],Z=G?.methods??["GET","POST","PUT","DELETE","OPTIONS"],X=G?.credentials??!1,_=G?.exposedHeaders??[];if(z.setHeader("Access-Control-Allow-Methods",Z),z.setHeader("Access-Control-Allow-Headers",U),z.setHeader("Access-Control-Allow-Credentials",X),_.length)z.setHeader("Access-Control-Expose-Headers",_);if(L==="*")z.setHeader("Access-Control-Allow-Origin","*");else if(Array.isArray(L))if(J&&L.includes(J))z.setHeader("Access-Control-Allow-Origin",J);else if(L.includes("*"))z.setHeader("Access-Control-Allow-Origin","*");else return z.status(403).json({message:"CORS not allowed"});else if(typeof L==="string")if(J===L)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}class M{tempRoutes;globalMiddlewares;middlewares;trie;hasOnReqHook;hasMiddleware;hasPreHandlerHook;hasPostHandlerHook;hasOnSendHook;hasOnError;hooks;corsConfig;FilterRoutes;filters;filterFunction;hasFilterEnabled;constructor(){this.tempRoutes=new Map,this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new A,this.corsConfig=null,this.hasMiddleware=!1,this.hasOnReqHook=!1,this.hasPreHandlerHook=!1,this.hasPostHandlerHook=!1,this.hasOnSendHook=!1,this.hasOnError=!1,this.hooks={onRequest:null,preHandler:null,postHandler:null,onSend:null,onError:null,onClose:null},this.FilterRoutes=[],this.filters=new Set,this.filterFunction=null,this.hasFilterEnabled=!1}filter(){return this.hasFilterEnabled=!0,{routeMatcher:(...F)=>{return this.FilterRoutes=F,this.filter()},permitAll:()=>{for(let F of this?.FilterRoutes)this.filters.add(F);return this.FilterRoutes=null,this.filter()},require:(F)=>{if(F)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");switch(F){case"onRequest":this.hooks.onRequest=z,this.hasOnReqHook=!0;break;case"preHandler":this.hooks.preHandler=z,this.hasPreHandlerHook=!0;break;case"postHandler":this.hooks.postHandler=z,this.hasPostHandlerHook=!0;break;case"onSend":this.hooks.onSend=z,this.hasOnSendHook=!0;break;case"onError":this.hooks.onError=z,this.hasOnError=!0;break;case"onClose":this.hooks.onClose=z;break;default: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;if(this.hooks.onError)this.hasOnError=!0;this.tempRoutes=new Map}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 L={port:F,fetch:async(Z,X)=>{let _=new URL(Z.url);try{return await j(Z,X,_,this)}catch($){if(this.hasOnError&&this.hooks.onError){let E=await this.hooks.onError($,Z,_,X);if(E)return E}return new Response(JSON.stringify({message:"Internal Server Error",error:$.message}),{status:500})}}};if(G&&J)L.certFile=G,L.keyFile=J;let U=Bun?.serve(L);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 U}route(F,z){if(!F||typeof F!=="string")throw new Error("Path must be a string");let G=Object.fromEntries(z.tempRoutes),J=Object.entries(G);for(let L=0;L<J.length;L++){let[U,Z]=J[L],X=`${F}${U}`;if(!this.middlewares.has(X))this.middlewares.set(X,[]);Z.handlers.slice(0,-1).forEach((Q)=>{if(!this.middlewares.get(X)?.includes(Q))this.middlewares.get(X)?.push(Q)});let $=Z.handlers[Z.handlers.length-1],E=Z.method;try{this.trie.insert(X,{handler:$,method:E})}catch(Q){console.error(`Error inserting ${X}:`,Q)}}z=null}register(F,z){this.route(F,z)}addRoute(F,z,G){if(typeof z!=="string")throw new Error("Path must be a string");if(typeof F!=="string")throw new Error("Method must be a string");this.tempRoutes.set(z,{method:F,handlers:G});let J=G.slice(0,-1),L=G[G.length-1];if(!this.middlewares.has(z))this.middlewares.set(z,[]);J.forEach((U)=>{if(z==="/")this.globalMiddlewares=[...new Set([...this.globalMiddlewares,...J])];else if(!this.middlewares.get(z)?.includes(U))this.middlewares.get(z)?.push(U)});try{this.trie.insert(z,{handler:L,method:F})}catch(U){console.error(`Error inserting ${z}:`,U)}}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.addRoute("GET",F,z),this}post(F,...z){return this.addRoute("POST",F,z),this}put(F,...z){return this.addRoute("PUT",F,z),this}patch(F,...z){return this.addRoute("PATCH",F,z),this}delete(F,...z){return this.addRoute("DELETE",F,z),this}}export{M as default};
package/dist/trie.d.ts CHANGED
@@ -20,12 +20,6 @@ export default class Trie {
20
20
  isDynamic: boolean;
21
21
  pattern: string;
22
22
  method: string;
23
- } | {
24
- path: string;
25
- handler: handlerFunction[];
26
- isDynamic: boolean;
27
- pattern: string;
28
- method: string;
29
23
  } | null;
30
24
  }
31
25
  export {};
package/dist/trie.js CHANGED
@@ -1 +1 @@
1
- class C{constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class E{constructor(){this.root=new C}insert(w,q){let j=this.root,B=w.split("/").filter(Boolean);if(w==="/"){j.isEndOfWord=!0,j.handler.push(q.handler),j.path=w,j.method.push(q.method);return}for(let v of B){let A=!1,z=v;if(v.startsWith(":"))A=!0,z=":";if(!j.children[z])j.children[z]=new C;j=j.children[z],j.isDynamic=A,j.pattern=v,j.method.push(q.method),j.handler.push(q.handler),j.path=w}j.isEndOfWord=!0,j.method.push(q.method),j.handler.push(q.handler),j.path=w}search(w,q){let j=this.root,B=w.split("/").filter(Boolean);for(let A of B){let z=A;if(!j.children[z])if(j.children[":"])j=j.children[":"];else return null;else j=j.children[z]}let v=j.method.indexOf(q);if(v!==-1)return{path:j.path,handler:j.handler[v],isDynamic:j.isDynamic,pattern:j.pattern,method:j.method[v]};return{path:j.path,handler:j.handler,isDynamic:j.isDynamic,pattern:j.pattern,method:j.method[v]}}}export{E as default};
1
+ class E{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 F{root;constructor(){this.root=new E}insert(q,w){let b=this.root,z=q.split("/").filter(Boolean);if(q==="/"){b.isEndOfWord=!0,b.handler=[w.handler],b.path=q,b.method=[w.method];return}for(let j=0;j<z.length;j++){let A=z[j],B=!1,C=A;if(A.startsWith(":"))B=!0,C=":";if(!b.children[C])b.children[C]=new E;if(b=b.children[C],b.isDynamic=B,b.pattern=A,j===z.length-1)b.handler=[w.handler],b.method=[w.method],b.isEndOfWord=!0,b.path=q}}search(q,w){let b=this.root,z=q.split("/").filter(Boolean);for(let A of z){let B=A;if(!b.children[B])if(b.children[":"])b=b.children[":"];else return null;else b=b.children[B]}let j=b.method.indexOf(w);if(b.isEndOfWord&&j!==-1)return{path:b.path,handler:b.handler[j],isDynamic:b.isDynamic,pattern:b.pattern,method:b.method[j]};return null}}export{F as default};
package/dist/types.d.ts CHANGED
@@ -2,34 +2,32 @@ import { Server } from "bun";
2
2
  export type listenCalllBackType = () => void;
3
3
  export type handlerFunction = (ctx: ContextType, server?: Server) => Response | Promise<Response | null | void>;
4
4
  export type middlewareFunc = (ctx: ContextType, server?: Server | undefined) => null | void | Response | Promise<Response | void | null>;
5
- export type HookFunction = (ctx: ContextType, result?: Response | null | void, server?: Server) => Response | Promise<Response | null | void>;
5
+ export type HookFunction = (ctx: ContextType, result?: Response | null | void, server?: Server) => Response | Promise<Response | null | void> | void;
6
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"
7
+ export type HookType = 'onRequest' | 'preHandler' | 'postHandler' | 'onSend' | 'onError' | 'onClose';
8
+ export interface onError {
9
+ (error: Error, req: Request, url: URL, server: Server): void | null | Response | Promise<Response | null | void>;
10
+ }
11
+ export interface onRequest {
12
+ (req: Request, url: URL, server: Server): void | null | Response | Promise<Response | null | void>;
14
13
  }
15
14
  export interface Hooks {
16
- onRequest: HookFunction | null;
15
+ onRequest: onRequest | null;
17
16
  preHandler: HookFunction | null;
18
17
  postHandler: HookFunction | null;
19
18
  onSend: HookFunction | null;
20
- onError: HookFunction | null;
19
+ onError: onError | null;
21
20
  onClose: HookFunction | null;
22
21
  }
23
22
  export interface ContextType {
24
23
  req: Request;
25
24
  server: Server;
26
25
  url: URL;
27
- next: () => void;
28
26
  setUser: (data?: any) => void;
29
27
  getUser: () => any;
30
28
  status: (status: number) => this;
31
29
  getIP: () => any;
32
- body: () => Promise<any>;
30
+ getBody: () => Promise<any>;
33
31
  setHeader: (key: string, value: any) => this;
34
32
  set: (key: string, value: any) => this;
35
33
  get: (key: string) => any;
@@ -37,12 +35,13 @@ export interface ContextType {
37
35
  getAuth: () => boolean;
38
36
  json: (data: Object, status?: number) => Response;
39
37
  text: (data: string, status?: number) => Response;
38
+ send: (data: string, status?: number) => Response;
40
39
  html: (filePath: string, status?: number) => Response;
41
40
  file: (filePath: string, status?: number) => Response;
42
41
  redirect: (path: string, status?: number) => Response;
43
42
  getParams: (props?: any) => any;
44
43
  getQuery: (props?: any) => any;
45
- cookie: (name: string, value: string, options?: CookieOptions) => this;
44
+ setCookie: (name: string, value: string, options?: CookieOptions) => this;
46
45
  getCookie: (cookieName?: string) => any;
47
46
  }
48
47
  export interface CookieOptions {
@@ -72,12 +71,13 @@ export interface DieselT {
72
71
  hasPostHandlerHook: boolean;
73
72
  hasOnSendHook: boolean;
74
73
  hooks: {
75
- onRequest: ((ctx: ContextType, serer?: Server) => void) | null;
76
- preHandler: ((ctx: ContextType, serer?: Server) => Promise<Response | void | null>) | null;
77
- postHandler: ((ctx: ContextType, serer?: Server) => Promise<Response | void | null>) | null;
78
- onSend: ((ctx?: ContextType, result?: Response | null | void, serer?: Server) => Promise<Response | void | null>) | null;
74
+ onRequest: ((req: Request, url: URL, serer: Server) => void) | null;
75
+ preHandler: ((ctx: ContextType, serer?: Server) => Response | Promise<Response | void | null>) | null;
76
+ postHandler: ((ctx: ContextType, serer?: Server) => Response | Promise<Response | void | null>) | null;
77
+ onSend: ((ctx?: ContextType, result?: Response | null | void, serer?: Server) => Response | Promise<Response | void | null>) | null;
78
+ onError: ((error: Error, req: Request, url: URL, server?: Server) => void | Response | Promise<Response | null | void>) | null;
79
79
  };
80
- filters: string[];
80
+ filters: Set<string>;
81
81
  hasFilterEnabled: boolean;
82
82
  filterFunction: (ctx: ContextType, serer?: Server) => void | Response | Promise<Response | void | null>;
83
83
  corsConfig: corsT | null;
@@ -93,6 +93,7 @@ export interface RouteCache {
93
93
  declare global {
94
94
  interface Request {
95
95
  routePattern?: string;
96
+ [key: string]: any;
96
97
  }
97
98
  }
98
99
  export interface ParseBodyResult {
package/dist/utils.js CHANGED
@@ -1 +1 @@
1
- function H(v){let{time:z=60000,max:A=100,message:C="Rate limit exceeded. Please try again later."}=v,j=new Map;return(D)=>{let E=new Date,F=D.getIP().address;if(!j.has(F))j.set(F,{count:0,startTime:E});let l=j.get(F);if(l)if(E-l.startTime>z)l.count=1,l.startTime=E;else l.count++;if(l&&l.count>A)return D.status(429).json({error:C});D.next()}}var G=(v,z,A,C)=>{if(A>C)return!1;let j=A+(C-A)/2;if(v[j]==z)return!0;if(v[j]>z)return G(v,z,A,j-1);return G(v,z,j+1,C)};export{H as default,G as binaryS};
1
+ function H(v){let{time:z=60000,max:A=100,message:C="Rate limit exceeded. Please try again later."}=v,j=new Map;return(F)=>{let D=new Date,E=F.getIP().address;if(!j.has(E))j.set(E,{count:0,startTime:D});let l=j.get(E);if(l)if(D-l.startTime>z)l.count=1,l.startTime=D;else l.count++;if(l&&l.count>A)return F.status(429).json({error:C})}}var G=(v,z,A,C)=>{if(A>C)return!1;let j=A+(C-A)/2;if(v[j]==z)return!0;if(v[j]>z)return G(v,z,A,j-1);return G(v,z,j+1,C)};export{H as default,G as binaryS};
package/example/main.ts CHANGED
@@ -1,69 +1,74 @@
1
+ import Diesel from "../src/main";
2
+ import jwt from "jsonwebtoken";
3
+ import { ContextType, CookieOptions, HookType, middlewareFunc } from "../src/types";
1
4
  import { Server } from "bun";
2
- import Diesel, { rateLimit } from "../dist/main";
3
- import jwt from 'jsonwebtoken'
4
- import { ContextType, CookieOptions, middlewareFunc } from "../dist/types";
5
5
 
6
6
  const app = new Diesel()
7
- const secret = 'pradeep'
7
+ const secret = "linux";
8
+
8
9
  // app.cors({
9
10
  // origin: ['http://localhost:5173','*'],
10
11
  // methods: 'GET,POST,PUT,DELETE',
11
12
  // allowedHeaders: 'Content-Type,Authorization'
12
13
  // })
13
14
 
14
- async function authJwt(ctx: ContextType, server?: Server): Promise<void | null | Response> {
15
-
15
+ export async function authJwt(ctx: ContextType): Promise<void | null | Response> {
16
+
17
+ const token = ctx.getCookie("accessToken");
18
+ if (!token) {
19
+ return ctx.status(401).json({ message: "Authentication token missing" });
20
+ }
16
21
  try {
17
- const token = ctx?.getCookie("accessToken");
18
-
19
- if (!token) {
20
- return ctx.status(401).json({ message: "Authentication token missing" });
21
- }
22
- // Verify the JWT token using a secret key
23
- const user = jwt.verify(token, secret); // Replace with your JWT secret
24
- // Set the user data in context
25
- ctx.setUser(user)
22
+ const user = await jwt.verify(token, secret); // Replace with your JWT secret
23
+ ctx.setUser(user);
26
24
  } catch (error) {
27
25
  return ctx.status(403).json({ message: "Invalid token" });
28
26
  }
29
27
  }
30
28
 
31
- const limiter = rateLimit({
32
- time: 60000, // Time window in milliseconds (e.g., 1 minute)
33
- max: 10, // Maximum number of requests allowed in the time window
34
- message: "Rate limit exceeded. Please try again later." // Custom error message
35
- });
36
-
37
- // app.use(limiter)
38
-
39
29
  app
40
30
  .filter()
41
- .routeMatcher('/api/user/register', '/api/user/login', '/test/:id', '/cookie')
31
+ .routeMatcher("/cookie",'/api/user/login','api/user/register')
42
32
  .permitAll()
43
- .require(authJwt as middlewareFunc)
33
+ .require(authJwt as middlewareFunc);
34
+
44
35
 
45
- // app.use(authJwt as middlewareFunc)
36
+ app.addHooks('onError', (error: any, req: Request, url: URL, server: Server) => {
37
+ console.error(`Error occurred: ${error.message}`);
38
+ console.error(`Request Method: ${req.method}, Request URL: ${url}`);
39
+ // return new Response('Internal Server Error', { status: 500 }); // You can customize the response as needed
40
+ });
46
41
 
47
- // .require(you can pass jwt auth parser)
48
42
 
49
- app.get("/", async (xl) => {
50
- // // const ip = xl.req
51
- // // // console.log(ip)
52
- // const user = xl.get('user')
53
- const q = xl.getUser()
43
+ app.get("/error", async () => {
44
+ throw new Error("This is a test error to demonstrate error handling");
45
+ });
54
46
 
55
- return xl.status(200).json({ msg: "hello world", q })
47
+ app.get("/", async (xl) => {
48
+ const user = xl.getUser();
49
+ return xl.json({
50
+ user,
51
+ });
56
52
  });
57
53
 
58
- app.get("/test/:id", async (xl) => {
54
+ app.get("/api/user/u",(ctx) => {
55
+ return ctx.text("j")
56
+ })
57
+
58
+ // app.post("/",async (ctx) => {
59
+ // const body = await ctx.getBody()
60
+ // return ctx.json(body)
61
+ // })
62
+
63
+ app.get("/test/:id/:name", async (xl) => {
59
64
  const q = xl.getQuery();
60
- const params = xl.getParams('id');
65
+ const params = xl.getParams();
61
66
  return new Response(JSON.stringify({ msg: "hello world", q, params }));
62
67
  });
63
68
 
64
69
  app.get("/ok", (xl) => {
65
- return xl.status(200).text("kaise ho??")
66
- })
70
+ return xl.status(200).text("kaise ho??");
71
+ });
67
72
 
68
73
  app.get("/cookie", async (xl) => {
69
74
  const user = {
@@ -80,12 +85,18 @@ app.get("/cookie", async (xl) => {
80
85
  sameSite: "Strict", // Prevents CSRF (strict origin policy)
81
86
  path: "/", // Cookie available for all routes
82
87
  };
83
- return xl
84
- .cookie("accessToken", accessToken, options)
85
- .cookie("refreshToken", refreshToken, options)
86
- .json({ msg: "setting cookies" })
88
+
89
+ return (
90
+ xl
91
+ .setCookie("accessToken", accessToken, options)
92
+ .setCookie("refreshToken", refreshToken, options)
93
+ .json({ msg: "setting cookies" })
94
+ );
95
+
87
96
  });
88
97
 
98
+ import {userRoute} from './route'
89
99
 
100
+ app.register("/api/user",userRoute)
90
101
 
91
- app.listen(3000)
102
+ app.listen(3000);
@@ -0,0 +1,40 @@
1
+ import Diesel from "../src/main";
2
+ import Router from "../src/route";
3
+ import { authJwt } from "./main";
4
+
5
+ const userRoute = new Router();
6
+
7
+ const h = () => {
8
+ console.log('object');
9
+ }
10
+
11
+ const s = () =>{
12
+ console.log('s')
13
+ }
14
+
15
+ userRoute.get("/register/:id",(xl) => {
16
+ return xl.text("from register user");
17
+ })
18
+
19
+ userRoute.get("/login",(xl)=>{
20
+ return new Response("hello loin")
21
+ })
22
+
23
+ const newRoute = new Diesel()
24
+
25
+ newRoute.get("/login",(xl)=>{
26
+ return xl.json({message:"from login"})
27
+ })
28
+
29
+ newRoute.get("/tetet",(ctx) =>{
30
+ return ctx.text("from tetet")
31
+ })
32
+
33
+ newRoute.get("/register/:id",(xl) => {
34
+ const param = xl.getParams("id")
35
+ return xl.json({message:"from register",param})
36
+ })
37
+
38
+ export {
39
+ userRoute,newRoute
40
+ }
package/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export * from './dist/types';
2
+
3
+ export { default as Diesel } from './dist/main';
4
+ export { default as Router } from './dist/route';
5
+ export { default as rateLimit } from './dist/utils';