diesel-core 0.0.4 → 0.0.6

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/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ Diesel Bunjs License
2
+ Copyright (c) 2024 Pradeep Sahu
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5
+
6
+ 1. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7
+
8
+ 2. The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the authors or copyright holders be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the Software or the use or other dealings in the Software.
package/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # DieselJS
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.
4
+
5
+
6
+ ## Installation
7
+
8
+ Install diesel-core via bun, npm , yarn , pnpm :
9
+
10
+ ```bash
11
+ npm install diesel-core
12
+
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);
21
+
22
+
23
+ app.get("/", async (xl) => {
24
+ return xl.status(200).text("Hello world...!")
25
+ OR
26
+ return xl.text("Hello world!")
27
+ OR
28
+ return new Response("Hello world")
29
+ });
30
+
31
+ // Render a HTML page
32
+ app.get("/render",async (xl) => {
33
+ return xl.html(`${import.meta.dir}/index.html`);
34
+ });
35
+
36
+ app.get("/async-test",async (xl) => {
37
+ await new Promise((resolve) => setTimeout(resolve, 1000));
38
+ return xl.json({ message: "Async operation completed" },200);
39
+ });
40
+
41
+
42
+ app.get("/redirect",(xl) => {
43
+ return xl.redirect("/");
44
+ });
45
+
46
+ app.get("/hello/:id",(xl) => {
47
+ const id = xl.getParams("id")
48
+ return xl.json({ msg: "Hello", id });
49
+ });
50
+
51
+
52
+ // Start the server
53
+ app.listen(port, () => {
54
+ console.log(`diesel is running on port ${port}`);
55
+ });
56
+
package/build.js ADDED
@@ -0,0 +1,12 @@
1
+ // build.js
2
+ await Bun.build({
3
+ entrypoints: [
4
+ './src/server.js',
5
+ './src/ctx.js',
6
+ './src/handleRequest.js',
7
+ './src/trie.js',
8
+ './src/router.js'
9
+ ],
10
+ outdir: './dist',
11
+ minify: true, // Enable minification
12
+ });
package/dist/ctx.js ADDED
@@ -0,0 +1 @@
1
+ async function H(G){const F={};if(!G)return F;return G.split(";").forEach((L)=>{const[X,M]=L.trim().split("=");F[X]=M.split(" ")[0]}),F}function K(G,F){const z={},L=G.split("/"),[X]=F.split("?"),M=X.split("/");if(L.length!==M.length)return null;return L.forEach((U,Y)=>{if(U.startsWith(":")){const Z=U.slice(1);z[Z]=M[Y]}}),z}async function W(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 O(z)}return new Response({error:"Unknown request body type"})}catch(z){return new Response({error:"Invalid request body format"})}}function O(G){const F={};for(let[z,L]of G.entries())F[z]=L;return F}function $(G,F){let z={},L={},X=!1,M=null,U=null,Y=null,Z=null,J=200;return{req:G,url:F,next:()=>{},status(w){return J=w,this},async body(){if(!Z)Z=await W(G);return Z},setHeader(w,E){return z[w]=E,this},set(w,E){return L[w]=E,this},get(w){return L[w]},setAuth(w){return X=w,this},getAuth(){return X},text(w,E){if(E)J=E;return new Response(w,{status:J,headers:z})},json(w,E){if(E)J=E;return new Response(JSON.stringify(w),{status:J,headers:{"Content-Type":"application/json",...z}})},html(w,E){if(E)J=E;return new Response(Bun.file(w),{status:J,headers:{...z}})},file(w,E){if(E)J=E;return new Response(Bun.file(w),{status:J,headers:{...z}})},redirect(w,E){if(E)J=E;return new Response(null,{status:J,headers:{Location:w,...z}})},getParams(w){if(!Y)Y=K(G.routePattern,F.pathname);return w?Y[w]:Y},getQuery(w){if(!M)M=Object.fromEntries(F.searchParams);return w?M[w]:M},async cookie(w,E,I={}){let R=`${encodeURIComponent(w)}=${encodeURIComponent(E)}`;if(I.maxAge)R+=`; Max-Age=${I.maxAge}`;if(I.expires)R+=`; Expires=${I.expires.toUTCString()}`;if(I.path)R+=`; Path=${I.path}`;if(I.domain)R+=`; Domain=${I.domain}`;if(I.secure)R+="; Secure";if(I.httpOnly)R+="; HttpOnly";if(I.sameSite)R+=`; SameSite=${I.sameSite}`;if(z["Set-Cookie"]){const _=Array.isArray(z["Set-Cookie"])?z["Set-Cookie"]:[z["Set-Cookie"]];_.push(R),z["Set-Cookie"]=_}else z["Set-Cookie"]=R;return this},async getCookie(w){if(!U)U=await H(G.headers.get("cookie"));return w?U[w]:U}}}export{$ as default};
@@ -0,0 +1 @@
1
+ async function O(J){const L={};if(!J)return L;return J.split(";").forEach((X)=>{const[_,Y]=X.trim().split("=");L[_]=Y.split(" ")[0]}),L}function V(J,L){const G={},X=J.split("/"),[_]=L.split("?"),Y=_.split("/");if(X.length!==Y.length)return null;return X.forEach((Z,E)=>{if(Z.startsWith(":")){const K=Z.slice(1);G[K]=Y[E]}}),G}async function A(J){const L=J.headers.get("Content-Type")||"";if(!L)return{};try{if(L.startsWith("application/json"))return await J.json();if(L.startsWith("application/x-www-form-urlencoded")){const G=await J.text();return Object.fromEntries(new URLSearchParams(G))}if(L.startsWith("multipart/form-data")){const G=await J.formData();return B(G)}return new Response({error:"Unknown request body type"})}catch(G){return new Response({error:"Invalid request body format"})}}function B(J){const L={};for(let[G,X]of J.entries())L[G]=X;return L}function W(J,L){let G={},X={},_=!1,Y=null,Z=null,E=null,K=null,z=200;return{req:J,url:L,next:()=>{},status(I){return z=I,this},async body(){if(!K)K=await A(J);return K},setHeader(I,U){return G[I]=U,this},set(I,U){return X[I]=U,this},get(I){return X[I]},setAuth(I){return _=I,this},getAuth(){return _},text(I,U){if(U)z=U;return new Response(I,{status:z,headers:G})},json(I,U){if(U)z=U;return new Response(JSON.stringify(I),{status:z,headers:{"Content-Type":"application/json",...G}})},html(I,U){if(U)z=U;return new Response(Bun.file(I),{status:z,headers:{...G}})},file(I,U){if(U)z=U;return new Response(Bun.file(I),{status:z,headers:{...G}})},redirect(I,U){if(U)z=U;return new Response(null,{status:z,headers:{Location:I,...G}})},getParams(I){if(!E)E=V(J.routePattern,L.pathname);return I?E[I]:E},getQuery(I){if(!Y)Y=Object.fromEntries(L.searchParams);return I?Y[I]:Y},async cookie(I,U,$={}){let F=`${encodeURIComponent(I)}=${encodeURIComponent(U)}`;if($.maxAge)F+=`; Max-Age=${$.maxAge}`;if($.expires)F+=`; Expires=${$.expires.toUTCString()}`;if($.path)F+=`; Path=${$.path}`;if($.domain)F+=`; Domain=${$.domain}`;if($.secure)F+="; Secure";if($.httpOnly)F+="; HttpOnly";if($.sameSite)F+=`; SameSite=${$.sameSite}`;if(G["Set-Cookie"]){const M=Array.isArray(G["Set-Cookie"])?G["Set-Cookie"]:[G["Set-Cookie"]];M.push(F),G["Set-Cookie"]=M}else G["Set-Cookie"]=F;return this},async getCookie(I){if(!Z)Z=await O(J.headers.get("cookie"));return I?Z[I]:Z}}}async function D(J,L){for(let G of J){const X=await G(L);if(X)return X}}function Q(J){return new Response(`Route not found for ${J}`,{status:404})}function R(){return new Response("Method not allowed",{status:405})}function T(){return new Response("No response from handler",{status:204})}function b(){return new Response("Internal Server Error",{status:500})}async function j(J,L,G){const X=W(J,L);if(G.hasOnReqHook)for(let Y of G.hooks.onRequest)await Y(X);if(G.hasMiddleware){const Y=[...G.globalMiddlewares,...G.middlewares.get(L.pathname)||[]],Z=await D(Y,X);if(Z)return Z}const _=G.trie.search(L.pathname,J.method);if(!_||!_.handler)return Q(L.pathname);if(_.method!==J.method)return R();if(_.isDynamic)J.routePattern=_.path;if(G.hasPreHandlerHook)for(let Y of G.hooks.preHandler){const Z=await Y(X);if(Z)return Z}try{const Y=await _.handler(X);if(G.hasPostHandlerHook)for(let Z of G.hooks.postHandler)await Z(X);if(G.hasOnSendHook)for(let Z of G.hooks.onSend){const E=await Z(Y,X);if(E)return E}return Y??T()}catch(Y){return b()}}export{j as default};
package/dist/router.js ADDED
@@ -0,0 +1 @@
1
+ class V{constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class M{constructor(){this.root=new V}insert(L,G){let E=this.root;const J=L.split("/").filter(Boolean);if(L==="/"){E.isEndOfWord=!0,E.handler.push(G.handler),E.path=L,E.method.push(G.method);return}for(let U of J){let X=!1,Y=U;if(U.startsWith(":"))X=!0,Y=":";if(!E.children[Y])E.children[Y]=new V;E=E.children[Y],E.isDynamic=X,E.pattern=U}E.isEndOfWord=!0,E.method.push(G.method),E.handler.push(G.handler),E.path=L}insertMidl(L){if(!this.root.subMiddlewares.has(L))this.root.subMiddlewares.set(L)}search(L,G){let E=this.root;const J=L.split("/").filter(Boolean);for(let X of J){let Y=X;if(!E.children[Y])if(E.children[":"])E=E.children[":"];else return null;else E=E.children[Y]}let U=E.method.indexOf(G);if(U!==-1)return{path:E.path,handler:E.handler[U],isDynamic:E.isDynamic,pattern:E.pattern,method:E.method[U]};return{path:E.path,handler:E.handler,isDynamic:E.isDynamic,pattern:E.pattern,method:E.method[U]}}getAllRoutes(){const L=[],G=(E,J)=>{if(E.isEndOfWord)L.push({path:J,handler:E.handler,isImportant:E.isImportant,isDynamic:E.isDynamic,pattern:E.pattern});for(let U in E.children){const X=E.children[U],Y=J+(U===":"?"/:"+X.pattern:"/"+U);G(X,Y)}};return G(this.root,""),L}}async function K(L){const G={};if(!L)return G;return L.split(";").forEach((J)=>{const[U,X]=J.trim().split("=");G[U]=X.split(" ")[0]}),G}function I(L,G){const E={},J=L.split("/"),[U]=G.split("?"),X=U.split("/");if(J.length!==X.length)return null;return J.forEach((Y,$)=>{if(Y.startsWith(":")){const A=Y.slice(1);E[A]=X[$]}}),E}async function v(L){const G=L.headers.get("Content-Type")||"";if(!G)return{};try{if(G.startsWith("application/json"))return await L.json();if(G.startsWith("application/x-www-form-urlencoded")){const E=await L.text();return Object.fromEntries(new URLSearchParams(E))}if(G.startsWith("multipart/form-data")){const E=await L.formData();return C(E)}return new Response({error:"Unknown request body type"})}catch(E){return new Response({error:"Invalid request body format"})}}function C(L){const G={};for(let[E,J]of L.entries())G[E]=J;return G}function B(L,G){let E={},J={},U=!1,X=null,Y=null,$=null,A=null,F=200;return{req:L,url:G,next:()=>{},status(Z){return F=Z,this},async body(){if(!A)A=await v(L);return A},setHeader(Z,_){return E[Z]=_,this},set(Z,_){return J[Z]=_,this},get(Z){return J[Z]},setAuth(Z){return U=Z,this},getAuth(){return U},text(Z,_){if(_)F=_;return new Response(Z,{status:F,headers:E})},json(Z,_){if(_)F=_;return new Response(JSON.stringify(Z),{status:F,headers:{"Content-Type":"application/json",...E}})},html(Z,_){if(_)F=_;return new Response(Bun.file(Z),{status:F,headers:{...E}})},file(Z,_){if(_)F=_;return new Response(Bun.file(Z),{status:F,headers:{...E}})},redirect(Z,_){if(_)F=_;return new Response(null,{status:F,headers:{Location:Z,...E}})},getParams(Z){if(!$)$=I(L.routePattern,G.pathname);return Z?$[Z]:$},getQuery(Z){if(!X)X=Object.fromEntries(G.searchParams);return Z?X[Z]:X},async cookie(Z,_,z={}){let W=`${encodeURIComponent(Z)}=${encodeURIComponent(_)}`;if(z.maxAge)W+=`; Max-Age=${z.maxAge}`;if(z.expires)W+=`; Expires=${z.expires.toUTCString()}`;if(z.path)W+=`; Path=${z.path}`;if(z.domain)W+=`; Domain=${z.domain}`;if(z.secure)W+="; Secure";if(z.httpOnly)W+="; HttpOnly";if(z.sameSite)W+=`; SameSite=${z.sameSite}`;if(E["Set-Cookie"]){const D=Array.isArray(E["Set-Cookie"])?E["Set-Cookie"]:[E["Set-Cookie"]];D.push(W),E["Set-Cookie"]=D}else E["Set-Cookie"]=W;return this},async getCookie(Z){if(!Y)Y=await K(L.headers.get("cookie"));return Z?Y[Z]:Y}}}async function O(L,G){for(let E of L){const J=await E(G);if(J)return J}}function N(L){return new Response(`Route not found for ${L}`,{status:404})}function w(){return new Response("Method not allowed",{status:405})}function R(){return new Response("No response from handler",{status:204})}function P(){return new Response("Internal Server Error",{status:500})}async function Q(L,G,E){const J=B(L,G);if(E.hasOnReqHook)for(let X of E.hooks.onRequest)await X(J);if(E.hasMiddleware){const X=[...E.globalMiddlewares,...E.middlewares.get(G.pathname)||[]],Y=await O(X,J);if(Y)return Y}const U=E.trie.search(G.pathname,L.method);if(!U||!U.handler)return N(G.pathname);if(U.method!==L.method)return w();if(U.isDynamic)L.routePattern=U.path;if(E.hasPreHandlerHook)for(let X of E.hooks.preHandler){const Y=await X(J);if(Y)return Y}try{const X=await U.handler(J);if(E.hasPostHandlerHook)for(let Y of E.hooks.postHandler)await Y(J);if(E.hasOnSendHook)for(let Y of E.hooks.onSend){const $=await Y(X,J);if($)return $}return X??R()}catch(X){return P()}}class T{constructor(){this.routes=new Map,this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new M,this.hasMiddleware=!1,this.hasOnReqHook=!1,this.hasPreHandlerHook=!1,this.hasPostHandlerHook=!1,this.hasOnSendHook=!1,this.hooks={onRequest:[],preHandler:[],postHandler:[],onSend:[],onError:[],onClose:[]}}addHooks(L,G){if(this.hooks[L])this.hooks[L].push(G);else throw new Error(`Unknown hook type: ${type}`)}compile(){if(this.globalMiddlewares.length>0)this.hasMiddleware=!0;for(let[L,G]of this.middlewares.entries())if(G.length>0){this.hasMiddleware=!0;break}if(this.hooks.onRequest.length>0)this.hasOnReqHook=!0;if(this.hooks.preHandler.length>0)this.hasPreHandlerHook=!0;if(this.hooks.postHandler.length>0)this.hasPostHandlerHook=!0;if(this.hooks.onSend.length>0)this.hasOnSendHook=!0}listen(L,{sslCert:G=null,sslKey:E=null}={},J){this.compile();const U={port:L,fetch:async(Y)=>{const $=new URL(Y.url);try{return await Q(Y,$,this)}catch(A){return new Response("Internal Server Error",{status:500})}},onClose(){console.log("Server is shutting down...")}};if(G&&E)U.certFile=G,U.keyFile=E;const X=Bun.serve(U);if(typeof J==="function")return J();if(G&&E)console.log(`HTTPS server is running on https://localhost:${L}`);else console.log(`HTTP server is running on http://localhost:${L}`);return X}register(L,G){const E=Object.entries(G.trie.root.children);G.trie.root.subMiddlewares.forEach((J,U)=>{if(!this.middlewares.has(L+U))this.middlewares.set(L+U,[]);if(!this.middlewares.get(L+U).includes(...J))this.middlewares.get(L+U).push(...J)});for(let[J,U]of E){const X=L+U?.path,Y=U.handler[0],$=U.method[0];this.trie.insert(X,{handler:Y,method:$})}G.trie=new M}#E(L,G,E){const J=E.slice(0,-1);if(!this.middlewares.has(G))this.middlewares.set(G,[]);if(G==="/")J.forEach((X)=>{if(!this.globalMiddlewares.includes(X))this.globalMiddlewares.push(X)});else if(!this.middlewares.get(G).includes(...J))this.middlewares.get(G).push(...J);const U=E[E.length-1];this.trie.insert(G,{handler:U,method:L})}use(L,G){if(typeof L==="function"){if(!this.globalMiddlewares.includes(L))return this.globalMiddlewares.push(L)}const E=L;if(!this.middlewares.has(E))this.middlewares.set(E,[]);if(!this.middlewares.get(E).includes(G))this.middlewares.get(E).push(G)}get(L,...G){return this.#E("GET",L,G)}post(L,...G){return this.#E("POST",L,G)}put(L,...G){return this.#E("PUT",L,G)}patch(L,...G){if(G.length>0)return this.#E("PATCH",L,G)}delete(L,...G){return this.#E("DELETE",L,G)}}var b=T;class j extends b{constructor(){super()}#E(L,G,E){if(!this.trie.root.subMiddlewares.has(G))this.trie.root.subMiddlewares.set(G,[]);const J=E.slice(0,-1);if(!this.trie.root.subMiddlewares.get(G).includes(...J))this.trie.root.subMiddlewares.get(G).push(...J);const U=E[E.length-1];this.trie.insert(G,{handler:U,method:L})}get(L,...G){return this.#E("GET",L,G)}post(L,...G){return this.#E("POST",L,G)}put(L,...G){return this.#E("PUT",L,G)}patch(L,...G){if(G.length>0)return this.#E("PATCH",L,G)}delete(L,...G){return this.#E("DELETE",L,G)}}var c=j;export{c as default};
package/dist/server.js ADDED
@@ -0,0 +1 @@
1
+ class B{constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class A{constructor(){this.root=new B}insert(J,L){let G=this.root;const X=J.split("/").filter(Boolean);if(J==="/"){G.isEndOfWord=!0,G.handler.push(L.handler),G.path=J,G.method.push(L.method);return}for(let U of X){let Y=!1,Z=U;if(U.startsWith(":"))Y=!0,Z=":";if(!G.children[Z])G.children[Z]=new B;G=G.children[Z],G.isDynamic=Y,G.pattern=U}G.isEndOfWord=!0,G.method.push(L.method),G.handler.push(L.handler),G.path=J}insertMidl(J){if(!this.root.subMiddlewares.has(J))this.root.subMiddlewares.set(J)}search(J,L){let G=this.root;const X=J.split("/").filter(Boolean);for(let Y of X){let Z=Y;if(!G.children[Z])if(G.children[":"])G=G.children[":"];else return null;else G=G.children[Z]}let U=G.method.indexOf(L);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]}}getAllRoutes(){const J=[],L=(G,X)=>{if(G.isEndOfWord)J.push({path:X,handler:G.handler,isImportant:G.isImportant,isDynamic:G.isDynamic,pattern:G.pattern});for(let U in G.children){const Y=G.children[U],Z=X+(U===":"?"/:"+Y.pattern:"/"+U);L(Y,Z)}};return L(this.root,""),J}}async function M(J){const L={};if(!J)return L;return J.split(";").forEach((X)=>{const[U,Y]=X.trim().split("=");L[U]=Y.split(" ")[0]}),L}function b(J,L){const G={},X=J.split("/"),[U]=L.split("?"),Y=U.split("/");if(X.length!==Y.length)return null;return X.forEach((Z,z)=>{if(Z.startsWith(":")){const V=Z.slice(1);G[V]=Y[z]}}),G}async function I(J){const L=J.headers.get("Content-Type")||"";if(!L)return{};try{if(L.startsWith("application/json"))return await J.json();if(L.startsWith("application/x-www-form-urlencoded")){const G=await J.text();return Object.fromEntries(new URLSearchParams(G))}if(L.startsWith("multipart/form-data")){const G=await J.formData();return T(G)}return new Response({error:"Unknown request body type"})}catch(G){return new Response({error:"Invalid request body format"})}}function T(J){const L={};for(let[G,X]of J.entries())L[G]=X;return L}function Q(J,L){let G={},X={},U=!1,Y=null,Z=null,z=null,V=null,W=200;return{req:J,url:L,next:()=>{},status(_){return W=_,this},async body(){if(!V)V=await I(J);return V},setHeader(_,$){return G[_]=$,this},set(_,$){return X[_]=$,this},get(_){return X[_]},setAuth(_){return U=_,this},getAuth(){return U},text(_,$){if($)W=$;return new Response(_,{status:W,headers:G})},json(_,$){if($)W=$;return new Response(JSON.stringify(_),{status:W,headers:{"Content-Type":"application/json",...G}})},html(_,$){if($)W=$;return new Response(Bun.file(_),{status:W,headers:{...G}})},file(_,$){if($)W=$;return new Response(Bun.file(_),{status:W,headers:{...G}})},redirect(_,$){if($)W=$;return new Response(null,{status:W,headers:{Location:_,...G}})},getParams(_){if(!z)z=b(J.routePattern,L.pathname);return _?z[_]:z},getQuery(_){if(!Y)Y=Object.fromEntries(L.searchParams);return _?Y[_]:Y},async cookie(_,$,F={}){let E=`${encodeURIComponent(_)}=${encodeURIComponent($)}`;if(F.maxAge)E+=`; Max-Age=${F.maxAge}`;if(F.expires)E+=`; Expires=${F.expires.toUTCString()}`;if(F.path)E+=`; Path=${F.path}`;if(F.domain)E+=`; Domain=${F.domain}`;if(F.secure)E+="; Secure";if(F.httpOnly)E+="; HttpOnly";if(F.sameSite)E+=`; SameSite=${F.sameSite}`;if(G["Set-Cookie"]){const D=Array.isArray(G["Set-Cookie"])?G["Set-Cookie"]:[G["Set-Cookie"]];D.push(E),G["Set-Cookie"]=D}else G["Set-Cookie"]=E;return this},async getCookie(_){if(!Z)Z=await M(J.headers.get("cookie"));return _?Z[_]:Z}}}async function v(J,L){for(let G of J){const X=await G(L);if(X)return X}}function C(J){return new Response(`Route not found for ${J}`,{status:404})}function O(){return new Response("Method not allowed",{status:405})}function N(){return new Response("No response from handler",{status:204})}function R(){return new Response("Internal Server Error",{status:500})}async function j(J,L,G){const X=Q(J,L);if(G.hasOnReqHook)for(let Y of G.hooks.onRequest)await Y(X);if(G.hasMiddleware){const Y=[...G.globalMiddlewares,...G.middlewares.get(L.pathname)||[]],Z=await v(Y,X);if(Z)return Z}const U=G.trie.search(L.pathname,J.method);if(!U||!U.handler)return C(L.pathname);if(U.method!==J.method)return O();if(U.isDynamic)J.routePattern=U.path;if(G.hasPreHandlerHook)for(let Y of G.hooks.preHandler){const Z=await Y(X);if(Z)return Z}try{const Y=await U.handler(X);if(G.hasPostHandlerHook)for(let Z of G.hooks.postHandler)await Z(X);if(G.hasOnSendHook)for(let Z of G.hooks.onSend){const z=await Z(Y,X);if(z)return z}return Y??N()}catch(Y){return R()}}class K{constructor(){this.routes=new Map,this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new A,this.hasMiddleware=!1,this.hasOnReqHook=!1,this.hasPreHandlerHook=!1,this.hasPostHandlerHook=!1,this.hasOnSendHook=!1,this.hooks={onRequest:[],preHandler:[],postHandler:[],onSend:[],onError:[],onClose:[]}}addHooks(J,L){if(this.hooks[J])this.hooks[J].push(L);else throw new Error(`Unknown hook type: ${type}`)}compile(){if(this.globalMiddlewares.length>0)this.hasMiddleware=!0;for(let[J,L]of this.middlewares.entries())if(L.length>0){this.hasMiddleware=!0;break}if(this.hooks.onRequest.length>0)this.hasOnReqHook=!0;if(this.hooks.preHandler.length>0)this.hasPreHandlerHook=!0;if(this.hooks.postHandler.length>0)this.hasPostHandlerHook=!0;if(this.hooks.onSend.length>0)this.hasOnSendHook=!0}listen(J,{sslCert:L=null,sslKey:G=null}={},X){this.compile();const U={port:J,fetch:async(Z)=>{const z=new URL(Z.url);try{return await j(Z,z,this)}catch(V){return new Response("Internal Server Error",{status:500})}},onClose(){console.log("Server is shutting down...")}};if(L&&G)U.certFile=L,U.keyFile=G;const Y=Bun.serve(U);if(typeof X==="function")return X();if(L&&G)console.log(`HTTPS server is running on https://localhost:${J}`);else console.log(`HTTP server is running on http://localhost:${J}`);return Y}register(J,L){const G=Object.entries(L.trie.root.children);L.trie.root.subMiddlewares.forEach((X,U)=>{if(!this.middlewares.has(J+U))this.middlewares.set(J+U,[]);if(!this.middlewares.get(J+U).includes(...X))this.middlewares.get(J+U).push(...X)});for(let[X,U]of G){const Y=J+U?.path,Z=U.handler[0],z=U.method[0];this.trie.insert(Y,{handler:Z,method:z})}L.trie=new A}#G(J,L,G){const X=G.slice(0,-1);if(!this.middlewares.has(L))this.middlewares.set(L,[]);if(L==="/")X.forEach((Y)=>{if(!this.globalMiddlewares.includes(Y))this.globalMiddlewares.push(Y)});else if(!this.middlewares.get(L).includes(...X))this.middlewares.get(L).push(...X);const U=G[G.length-1];this.trie.insert(L,{handler:U,method:J})}use(J,L){if(typeof J==="function"){if(!this.globalMiddlewares.includes(J))return this.globalMiddlewares.push(J)}const G=J;if(!this.middlewares.has(G))this.middlewares.set(G,[]);if(!this.middlewares.get(G).includes(L))this.middlewares.get(G).push(L)}get(J,...L){return this.#G("GET",J,L)}post(J,...L){return this.#G("POST",J,L)}put(J,...L){return this.#G("PUT",J,L)}patch(J,...L){if(L.length>0)return this.#G("PATCH",J,L)}delete(J,...L){return this.#G("DELETE",J,L)}}var x=K;export{x as default};
package/dist/trie.js ADDED
@@ -0,0 +1 @@
1
+ class E{constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class F{constructor(){this.root=new E}insert(j,z){let b=this.root;const C=j.split("/").filter(Boolean);if(j==="/"){b.isEndOfWord=!0,b.handler.push(z.handler),b.path=j,b.method.push(z.method);return}for(let q of C){let B=!1,A=q;if(q.startsWith(":"))B=!0,A=":";if(!b.children[A])b.children[A]=new E;b=b.children[A],b.isDynamic=B,b.pattern=q}b.isEndOfWord=!0,b.method.push(z.method),b.handler.push(z.handler),b.path=j}insertMidl(j){if(!this.root.subMiddlewares.has(j))this.root.subMiddlewares.set(j)}search(j,z){let b=this.root;const C=j.split("/").filter(Boolean);for(let B of C){let A=B;if(!b.children[A])if(b.children[":"])b=b.children[":"];else return null;else b=b.children[A]}let q=b.method.indexOf(z);if(q!==-1)return{path:b.path,handler:b.handler[q],isDynamic:b.isDynamic,pattern:b.pattern,method:b.method[q]};return{path:b.path,handler:b.handler,isDynamic:b.isDynamic,pattern:b.pattern,method:b.method[q]}}getAllRoutes(){const j=[],z=(b,C)=>{if(b.isEndOfWord)j.push({path:C,handler:b.handler,isImportant:b.isImportant,isDynamic:b.isDynamic,pattern:b.pattern});for(let q in b.children){const B=b.children[q],A=C+(q===":"?"/:"+B.pattern:"/"+q);z(B,A)}};return z(this.root,""),j}}export{F as default};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "diesel-core",
3
- "version": "0.0.4",
4
- "main": "src/server.js",
3
+ "version": "0.0.6",
4
+ "main": "dist/server.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
7
7
  },
package/src/ctx.js CHANGED
@@ -5,25 +5,35 @@ export default function createCtx(req, url) {
5
5
  let parsedQuery = null;
6
6
  let parsedCookie = null;
7
7
  let parsedParams = null;
8
- let parsedBody= null
8
+ let parsedBody = null;
9
+ let responseStatus = 200; // Default status
9
10
 
10
11
  return {
11
12
  req,
12
13
  url,
13
14
  next: () => {},
14
- ///////
15
+
16
+ // Set response status for chaining
17
+ status(status) {
18
+ responseStatus = status;
19
+ return this;
20
+ },
21
+
15
22
  async body() {
16
23
  if (!parsedBody) {
17
- parsedBody = await parseBody(req)
24
+ parsedBody = await parseBody(req);
18
25
  }
19
26
  return parsedBody;
20
27
  },
28
+
21
29
  setHeader(key, value) {
22
30
  headers[key] = value;
31
+ return this;
23
32
  },
24
33
 
25
34
  set(key, value) {
26
35
  settedValue[key] = value;
36
+ return this;
27
37
  },
28
38
 
29
39
  get(key) {
@@ -32,22 +42,30 @@ export default function createCtx(req, url) {
32
42
 
33
43
  setAuth(authStatus) {
34
44
  isAuthenticated = authStatus;
45
+ return this;
35
46
  },
36
47
 
37
48
  getAuth() {
38
49
  return isAuthenticated;
39
50
  },
40
51
 
41
- text(data, status = 200) {
52
+ // Response methods with optional status
53
+ text(data, status) {
54
+ if (status) {
55
+ responseStatus = status;
56
+ }
42
57
  return new Response(data, {
43
- status,
58
+ status: responseStatus,
44
59
  headers: headers,
45
60
  });
46
61
  },
47
62
 
48
- json(data, status = 200) {
63
+ json(data, status) {
64
+ if (status) {
65
+ responseStatus = status;
66
+ }
49
67
  return new Response(JSON.stringify(data), {
50
- status,
68
+ status: responseStatus,
51
69
  headers: {
52
70
  "Content-Type": "application/json",
53
71
  ...headers,
@@ -55,26 +73,36 @@ export default function createCtx(req, url) {
55
73
  });
56
74
  },
57
75
 
58
- html(filepath) {
76
+ html(filepath, status) {
77
+ if (status) {
78
+ responseStatus = status;
79
+ }
59
80
  return new Response(Bun.file(filepath), {
60
- status: 200,
81
+ status: responseStatus,
61
82
  headers: {
62
83
  ...headers,
63
84
  },
64
85
  });
65
86
  },
66
- file(filePath) {
87
+
88
+ file(filePath, status) {
89
+ if (status) {
90
+ responseStatus = status;
91
+ }
67
92
  return new Response(Bun.file(filePath), {
68
- status: 200,
93
+ status: responseStatus,
69
94
  headers: {
70
95
  ...headers,
71
96
  },
72
97
  });
73
98
  },
74
99
 
75
- redirect(path, status = 302) {
100
+ redirect(path, status) {
101
+ if (status) {
102
+ responseStatus = status;
103
+ }
76
104
  return new Response(null, {
77
- status,
105
+ status: responseStatus,
78
106
  headers: {
79
107
  Location: path,
80
108
  ...headers,
@@ -82,21 +110,21 @@ export default function createCtx(req, url) {
82
110
  });
83
111
  },
84
112
 
85
- async getParams(props) {
113
+ getParams(props) {
86
114
  if (!parsedParams) {
87
- parsedParams = await extractDynamicParams(req.routePattern, url.pathname);
115
+ parsedParams = extractDynamicParams(req.routePattern, url.pathname);
88
116
  }
89
117
  return props ? parsedParams[props] : parsedParams;
90
118
  },
91
119
 
92
120
  getQuery(props) {
93
121
  if (!parsedQuery) {
94
- parsedQuery = Object.fromEntries(url.searchParams.entries());
122
+ parsedQuery = Object.fromEntries(url.searchParams);
95
123
  }
96
124
  return props ? parsedQuery[props] : parsedQuery;
97
125
  },
98
126
 
99
- cookie(name, value, options = {}) {
127
+ async cookie(name, value, options = {}) {
100
128
  let cookieString = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
101
129
 
102
130
  // Add options to cookie string (e.g., expiration, path, HttpOnly, etc.)
@@ -109,19 +137,15 @@ export default function createCtx(req, url) {
109
137
  if (options.sameSite) cookieString += `; SameSite=${options.sameSite}`;
110
138
 
111
139
  if (headers["Set-Cookie"]) {
112
- // If it's already an array, push the new cookie, otherwise convert to array
113
140
  const existingCookies = Array.isArray(headers["Set-Cookie"]) ? headers["Set-Cookie"] : [headers["Set-Cookie"]];
114
-
115
- // Add the new cookie string to the array
116
141
  existingCookies.push(cookieString);
117
-
118
- // Update Set-Cookie header
119
142
  headers["Set-Cookie"] = existingCookies;
120
143
  } else {
121
- // If no cookies exist, initialize the header
122
144
  headers["Set-Cookie"] = cookieString;
123
145
  }
146
+ return this;
124
147
  },
148
+
125
149
  async getCookie(cookieName) {
126
150
  if (!parsedCookie) {
127
151
  parsedCookie = await parseCookie(req.headers.get("cookie"));
@@ -131,57 +155,66 @@ export default function createCtx(req, url) {
131
155
  };
132
156
  }
133
157
 
158
+
134
159
  async function parseCookie(header) {
135
160
  const cookies = {};
136
161
  if (!header) return cookies;
137
162
 
138
163
  const cookieArray = header.split(";");
139
164
  cookieArray.forEach((cookie) => {
140
- const [cookieName, cookievalue] = cookie.trim().split("=");
141
- cookies[cookieName] = cookievalue.split(" ")[0];
165
+ const [cookieName, cookieValue] = cookie.trim().split("=");
166
+ cookies[cookieName] = cookieValue.split(" ")[0];
142
167
  });
143
168
  return cookies;
144
169
  }
145
170
 
146
- async function extractDynamicParams (routePattern, path) {
171
+ function extractDynamicParams(routePattern, path) {
147
172
  const object = {};
148
173
  const routeSegments = routePattern.split("/");
149
- const [pathWithoutQuery] = path.split("?"); // Ignore the query string in the path
150
- const pathSegments = pathWithoutQuery.split("/"); // Re-split after removing query
174
+ const [pathWithoutQuery] = path.split("?");
175
+ const pathSegments = pathWithoutQuery.split("/");
151
176
 
152
177
  if (routeSegments.length !== pathSegments.length) {
153
- return null; // Path doesn't match the pattern
178
+ return null;
154
179
  }
155
180
 
156
181
  routeSegments.forEach((segment, index) => {
157
182
  if (segment.startsWith(":")) {
158
- const dynamicKey = segment.slice(1); // Remove ':' to get the key name
159
- object[dynamicKey] = pathSegments[index]; // Map the path segment to the key
183
+ const dynamicKey = segment.slice(1);
184
+ object[dynamicKey] = pathSegments[index];
160
185
  }
161
186
  });
162
187
 
163
188
  return object;
164
- };
189
+ }
165
190
 
166
191
  async function parseBody(req) {
167
- const contentType = req.headers.get("Content-Type");
168
- if (contentType.includes("application/json")) {
169
- try {
192
+ const contentType = req.headers.get("Content-Type") || "";
193
+
194
+ if (!contentType) return {};
195
+
196
+ try {
197
+ if (contentType.startsWith("application/json")) {
170
198
  return await req.json();
171
- } catch (error) {
172
- return new Response({ error: "Invalid JSON format" });
173
199
  }
174
- } else if (contentType.startsWith("application/x-www-form-urlencoded")) {
175
- const body = await req.text();
176
- return Object.fromEntries(new URLSearchParams(body));
177
- } else if (contentType.startsWith("multipart/form-data")) {
178
- const formData = await req.formData();
179
- return formDataToObject(formData);
180
- } else {
181
- return new Response({ error: "unknown request body" });
200
+
201
+ if (contentType.startsWith("application/x-www-form-urlencoded")) {
202
+ const body = await req.text();
203
+ return Object.fromEntries(new URLSearchParams(body));
204
+ }
205
+
206
+ if (contentType.startsWith("multipart/form-data")) {
207
+ const formData = await req.formData();
208
+ return formDataToObject(formData);
209
+ }
210
+
211
+ return new Response({ error: "Unknown request body type" });
212
+ } catch (error) {
213
+ return new Response({ error: "Invalid request body format" });
182
214
  }
183
215
  }
184
216
 
217
+
185
218
  function formDataToObject(formData) {
186
219
  const obj = {};
187
220
  for (const [key, value] of formData.entries()) {
@@ -1,46 +1,68 @@
1
1
  import createCtx from "./ctx";
2
2
 
3
3
  export default async function handleRequest(req, url, diesel) {
4
- const { pathname } = url;
5
- const { method } = req;
4
+
5
+ const ctx = createCtx(req, url);
6
+
7
+ // OnReq hook 1
8
+ if (diesel.hasOnReqHook) {
9
+ await diesel.hooks.onRequest(ctx)
10
+ }
11
+
12
+ // middleware execution
13
+ if (diesel.hasMiddleware) {
14
+ const middlewares = [
15
+ ...diesel.globalMiddlewares,
16
+ ...diesel.middlewares.get(url.pathname) || []
17
+ ];
18
+
19
+ const middlewareResult = await executeMiddleware(middlewares, ctx);
20
+ if (middlewareResult) return middlewareResult;
21
+ }
6
22
 
7
23
  // Try to find the route handler in the trie
8
- const routeHandler = diesel.trie.search(pathname, method);
9
-
24
+ const routeHandler = diesel.trie.search(url.pathname, req.method);
25
+
10
26
  // Early return if route or method is not found
11
- if (!routeHandler || !routeHandler.handler) return responseNotFound(pathname);
12
- if (routeHandler.method !== method) return responseMethodNotAllowed();
27
+ if (!routeHandler || !routeHandler.handler) return responseNotFound(url.pathname);
28
+ if (routeHandler.method !== req.method) return responseMethodNotAllowed();
29
+
13
30
  // If the route is dynamic, we only set routePattern if necessary
14
31
  if (routeHandler.isDynamic) req.routePattern = routeHandler.path;
15
32
 
16
- const ctx = createCtx(req, url);
17
-
18
- if (diesel.hasMiddleware) {
19
- const middlewares = [
20
- ...diesel.globalMiddlewares,
21
- ...diesel.middlewares.get(pathname) || []
22
- ];
23
-
24
- const middlewareResult = await executeMiddleware(middlewares, ctx);
25
- if (middlewareResult) return middlewareResult;
33
+ // Run preHandler hooks 2
34
+ if (diesel.hasPreHandlerHook) {
35
+ const Hookresult = await diesel.hooks.preHandler(ctx);
36
+ if(Hookresult) return Hookresult;
37
+ }
26
38
 
27
- }
28
-
29
39
 
30
40
  // Finally, execute the route handler and return its result
31
41
  try {
32
42
  const result = await routeHandler.handler(ctx);
43
+
44
+ // 3. run the postHandler hooks
45
+ if (diesel.hasPostHandlerHook) {
46
+ await diesel.hooks.postHandler(ctx)
47
+ }
48
+
49
+ // 4. Run onSend hooks before sending the response
50
+ if (diesel.hasOnSendHook) {
51
+ const hookResponse = await diesel.hooks.onSend(result, ctx);
52
+ if(hookResponse) return hookResponse
53
+ }
54
+
33
55
  return result ?? responseNoHandler();
34
56
  } catch (error) {
35
57
  return responseServerError();
36
58
  }
37
59
  }
38
60
 
39
- // Optimized middleware execution: stops as soon as a middleware returns a response
61
+ // middleware execution
40
62
  async function executeMiddleware(middlewares, ctx) {
41
63
  for (const middleware of middlewares) {
42
64
  const result = await middleware(ctx);
43
- if (result) return result; // Early exit if middleware returns a result
65
+ if (result) return result;
44
66
  }
45
67
  }
46
68
 
package/src/server.js CHANGED
@@ -1,136 +1,194 @@
1
- import {serve} from 'bun'
2
- import Trie from './trie.js';
3
- import handleRequest from './handleRequest.js'
4
-
5
- class diesel {
6
- constructor(){
7
- this.routes = new Map()
8
- this.globalMiddlewares = [];
9
- this.middlewares = new Map()
10
- this.trie = new Trie()
11
- this.hasMiddleware = false;
1
+ import Trie from "./trie.js";
2
+ import handleRequest from "./handleRequest.js";
3
+
4
+ class Diesel {
5
+ constructor() {
6
+ this.routes = new Map();
7
+ this.globalMiddlewares = [];
8
+ this.middlewares = new Map();
9
+ this.trie = new Trie();
10
+ this.hasMiddleware = false;
11
+ this.hasOnReqHook=false;
12
+ this.hasPreHandlerHook=false;
13
+ this.hasPostHandlerHook=false;
14
+ this.hasOnSendHook=false;
15
+ this.hooks = {
16
+ onRequest: null,
17
+ preHandler: null,
18
+ postHandler: null,
19
+ onSend: null,
20
+ onError: null,
21
+ onClose: null
12
22
  }
23
+ }
13
24
 
14
- compile (){
15
- if (this.globalMiddlewares.length > 0) {
16
- this.hasMiddleware = true;
17
- }
18
- for (const [path, middlewares] of this.middlewares.entries()) {
19
- if (middlewares.length > 0) {
20
- this.hasMiddleware = true;
21
- break;
22
- }
23
- }
25
+ addHooks(typeOfHook,fnc){
26
+ if (this.hooks.hasOwnProperty(typeOfHook)) {
27
+ this.hooks[typeOfHook] = fnc; // Overwrite or set the hook
28
+ } else {
29
+ throw new Error(`Unknown hook type: ${typeOfHook}`); // Throw an error for invalid hook types
24
30
  }
31
+ }
25
32
 
26
- listen(port,callback){
27
- this.compile()
28
- const server = serve({
29
- port,
30
- fetch: async (req) => {
31
- const url = new URL(req.url)
32
- try {
33
- return await handleRequest(req,url,this)
34
- } catch (error) {
35
- return new Response('Internal Server Error', { status: 500 });
36
- }
37
- },
38
- onClose() {
39
- console.log("Server is shutting down...");
40
- }
41
- });
42
- if (typeof callback === 'function') {
43
- return callback();
44
- }
45
- console.log(`Server is running on http://localhost:${port}`);
46
- return server;
33
+ compile() {
34
+ if (this.globalMiddlewares.length > 0) {
35
+ this.hasMiddleware = true;
47
36
  }
48
-
49
- register(pathPrefix,handlerInstance){
50
- const routeEntries = Object.entries(handlerInstance.trie.root.children);
51
- // console.log(handlerInstance.trie.root);
52
- handlerInstance.trie.root.subMiddlewares.forEach((middleware,path)=>{
53
- if (!this.middlewares.has(pathPrefix+path)) {
54
- this.middlewares.set(pathPrefix+path, []);
55
- }
56
- if (!this.middlewares.get(pathPrefix+path).includes(...middleware)) {
57
- this.middlewares.get(pathPrefix+path).push(...middleware);
58
- }
59
- })
60
- for (const [routeKey, routeNode] of routeEntries) {
61
- const fullpath = pathPrefix + routeNode?.path;
62
- const routeHandler = routeNode.handler[0];
63
- const httpMethod = routeNode.method[0];
64
- this.trie.insert(fullpath, { handler: routeHandler, method: httpMethod });
65
- }
66
- handlerInstance.trie = new Trie();
37
+ for (const [path, middlewares] of this.middlewares.entries()) {
38
+ if (middlewares.length > 0) {
39
+ this.hasMiddleware = true;
40
+ break;
41
+ }
42
+ }
43
+
44
+ // check if hook is present or not
45
+ if (this.hooks.onRequest) this.hasOnReqHook=true;
46
+ if(this.hooks.preHandler) this.hasPreHandlerHook=true;
47
+ if(this.hooks.postHandler) this.hasPostHandlerHook=true;
48
+ if(this.hooks.onSend) this.hasOnSendHook=true;
49
+
50
+ }
51
+
52
+ listen(port, { sslCert = null, sslKey = null } = {}, callback) {
53
+ if (typeof Bun === 'undefined')
54
+ throw new Error(
55
+ '.listen() is designed to run on Bun only...'
56
+ )
57
+
58
+ if (typeof port !== "number") {
59
+ throw new Error('Port must be a numeric value')
67
60
  }
68
61
 
69
- #addRoute(method,path,handlers){
70
-
71
- const middlewareHandlers = handlers.slice(0, -1);
62
+ this.compile();
72
63
 
73
- if (!this.middlewares.has(path)) {
74
- this.middlewares.set(path,[])
64
+ const options = {
65
+ port,
66
+ fetch: async (req) => {
67
+ const url = new URL(req.url);
68
+ try {
69
+ return await handleRequest(req, url, this);
70
+ } catch (error) {
71
+ return new Response("Internal Server Error", { status: 500 });
75
72
  }
76
- if (path === '/') {
77
- middlewareHandlers.forEach(midlleware => {
78
- if(!this.globalMiddlewares.includes(midlleware)){
79
- this.globalMiddlewares.push(midlleware)
80
- }
81
- })
82
- } else {
83
- if (!this.middlewares.get(path).includes(...middlewareHandlers)) {
84
- this.middlewares.get(path).push(...middlewareHandlers);
85
- }
86
- }
87
-
88
- const handler = handlers[handlers.length-1]
89
- this.trie.insert(path,{handler,method})
90
-
73
+ },
74
+ onClose() {
75
+ console.log("Server is shutting down...");
76
+ },
77
+ };
78
+
79
+ if (sslCert && sslKey) {
80
+ options.certFile = sslCert;
81
+ options.keyFile = sslKey;
82
+ }
83
+ const server = Bun.serve(options);
84
+
85
+ Bun?.gc(false)
86
+
87
+ if (typeof callback === "function") {
88
+ return callback();
91
89
  }
92
-
93
-
94
- use(pathORHandler,handler){
95
- if (typeof pathORHandler === 'function') {
96
- if (!this.globalMiddlewares.includes(pathORHandler)) {
97
- return this.globalMiddlewares.push(pathORHandler)
98
- }
99
- }
100
- // now it means it is path midl
101
- const path = pathORHandler
102
- if (!this.middlewares.has(path)) {
103
- this.middlewares.set(path,[])
104
- }
105
-
106
- if(!this.middlewares.get(path).includes(handler)){
107
- this.middlewares.get(path).push(handler)
108
- }
90
+
91
+ if (sslCert && sslKey) {
92
+ console.log(`HTTPS server is running on https://localhost:${port}`);
93
+ } else {
94
+ console.log(`HTTP server is running on http://localhost:${port}`);
109
95
  }
110
96
 
111
- get(path,...handlers){
112
- return this.#addRoute("GET",path,handlers)
97
+ return server;
98
+ }
99
+
100
+ register(pathPrefix, handlerInstance) {
101
+ const routeEntries = Object.entries(handlerInstance.trie.root.children);
102
+ // console.log(handlerInstance.trie.root);
103
+ handlerInstance.trie.root.subMiddlewares.forEach((middleware, path) => {
104
+ if (!this.middlewares.has(pathPrefix + path)) {
105
+ this.middlewares.set(pathPrefix + path, []);
106
+ }
107
+ if (!this.middlewares.get(pathPrefix + path).includes(...middleware)) {
108
+ this.middlewares.get(pathPrefix + path).push(...middleware);
109
+ }
110
+ });
111
+ for (const [routeKey, routeNode] of routeEntries) {
112
+ const fullpath = pathPrefix + routeNode?.path;
113
+ const routeHandler = routeNode.handler[0];
114
+ const httpMethod = routeNode.method[0];
115
+ this.trie.insert(fullpath, { handler: routeHandler, method: httpMethod });
113
116
  }
117
+ handlerInstance.trie = new Trie();
118
+ }
114
119
 
115
- post(path,...handlers){
116
- return this.#addRoute("POST",path,handlers)
120
+ #addRoute(method, path, handlers) {
121
+ if(typeof path !== "string"){
122
+ throw new Error("Path must be a string type");
117
123
  }
118
-
119
- put(path,...handlers){
120
- return this.#addRoute("PUT",path,handlers)
124
+ if(typeof method !== "string"){
125
+ throw new Error("method must be a string type");
121
126
  }
127
+ const middlewareHandlers = handlers.slice(0, -1);
122
128
 
123
- patch(path,...handlers){
124
- if (handlers.length>0) {
125
- return this.#addRoute("PATCH",path,handlers)
129
+ if (!this.middlewares.has(path)) {
130
+ this.middlewares.set(path, []);
131
+ }
132
+ if (path === "/") {
133
+ middlewareHandlers.forEach((midlleware) => {
134
+ if (!this.globalMiddlewares.includes(midlleware)) {
135
+ this.globalMiddlewares.push(midlleware);
126
136
  }
137
+ });
138
+ } else {
139
+ if (!this.middlewares.get(path).includes(...middlewareHandlers)) {
140
+ this.middlewares.get(path).push(...middlewareHandlers);
141
+ }
127
142
  }
128
143
 
129
- delete(path,...handlers){
130
- return this.#addRoute("DELETE",path,handlers)
144
+ const handler = handlers[handlers.length - 1];
145
+ this.trie.insert(path, { handler, method });
146
+ }
147
+
148
+ use(pathORHandler, handler) {
149
+ if (typeof pathORHandler === "function") {
150
+ if (!this.globalMiddlewares.includes(pathORHandler)) {
151
+ return this.globalMiddlewares.push(pathORHandler);
152
+ }
153
+ }
154
+ // now it means it is path midl
155
+ const path = pathORHandler;
156
+ if (!this.middlewares.has(path)) {
157
+ this.middlewares.set(path, []);
131
158
  }
132
159
 
160
+ if (!this.middlewares.get(path).includes(handler)) {
161
+ this.middlewares.get(path).push(handler);
162
+ }
163
+ }
164
+
165
+ get(path, ...handlers) {
166
+ this.#addRoute("GET", path, handlers);
167
+ return this
168
+ }
169
+
170
+ post(path, ...handlers) {
171
+ this.#addRoute("POST", path, handlers);
172
+ return this
173
+ }
174
+
175
+ put(path, ...handlers) {
176
+ this.#addRoute("PUT", path, handlers);
177
+ return this
178
+ }
179
+
180
+ patch(path, ...handlers) {
181
+ if(typeof path !== "string"){
182
+ throw new Error("Path must be a string type");
183
+ }
184
+ this.#addRoute("PATCH", path, handlers);
185
+ return this
186
+ }
187
+
188
+ delete(path, ...handlers) {
189
+ this.#addRoute("DELETE", path, handlers);
190
+ return this;
191
+ }
133
192
  }
134
193
 
135
-
136
- export default diesel;
194
+ export default Diesel
package/src/trie.js CHANGED
@@ -3,7 +3,6 @@ class TrieNode {
3
3
  this.children = {};
4
4
  this.isEndOfWord = false;
5
5
  this.handler = [];
6
- this.isImportant = false;
7
6
  this.isDynamic = false;
8
7
  this.pattern = '';
9
8
  this.path = "";
@@ -25,7 +24,6 @@ class TrieNode {
25
24
  if (path === '/') {
26
25
  node.isEndOfWord = true;
27
26
  node.handler.push(route.handler)
28
- node.isImportant = route.isImportant;
29
27
  node.path = path;
30
28
  node.method.push(route.method)
31
29
  return;
@@ -54,7 +52,6 @@ class TrieNode {
54
52
  node.isEndOfWord = true;
55
53
  node.method.push(route.method);
56
54
  node.handler.push(route.handler)
57
- node.isImportant = route.isImportant;
58
55
  node.path = path; // Store the original path
59
56
  }
60
57