diesel-core 0.0.3 → 0.0.5

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/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(F){const G={};if(!F)return G;return F.split(";").forEach((L)=>{const[X,M]=L.trim().split("=");G[X]=M.split(" ")[0]}),G}async function K(F,G){const z={},L=F.split("/"),[X]=G.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(F){const G=F.headers.get("Content-Type");if(G.includes("application/json"))try{return await F.json()}catch(z){return new Response({error:"Invalid JSON format"})}else if(G.startsWith("application/x-www-form-urlencoded")){const z=await F.text();return Object.fromEntries(new URLSearchParams(z))}else if(G.startsWith("multipart/form-data")){const z=await F.formData();return O(z)}else return new Response({error:"unknown request body"})}function O(F){const G={};for(let[z,L]of F.entries())G[z]=L;return G}function $(F,G){let z={},L={},X=!1,M=null,U=null,Y=null,Z=null,J=200;return{req:F,url:G,next:()=>{},status(w){return J=w,this},async body(){if(!Z)Z=await W(F);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}})},async getParams(w){if(!Y)Y=await K(F.routePattern,G.pathname);return w?Y[w]:Y},getQuery(w){if(!M)M=Object.fromEntries(G.searchParams.entries());return w?M[w]:M},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(F.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[E,Y]=X.trim().split("=");L[E]=Y.split(" ")[0]}),L}async function R(J,L){const G={},X=J.split("/"),[E]=L.split("?"),Y=E.split("/");if(X.length!==Y.length)return null;return X.forEach(($,z)=>{if($.startsWith(":")){const K=$.slice(1);G[K]=Y[z]}}),G}async function V(J){const L=J.headers.get("Content-Type");if(L.includes("application/json"))try{return await J.json()}catch(G){return new Response({error:"Invalid JSON format"})}else if(L.startsWith("application/x-www-form-urlencoded")){const G=await J.text();return Object.fromEntries(new URLSearchParams(G))}else if(L.startsWith("multipart/form-data")){const G=await J.formData();return A(G)}else return new Response({error:"unknown request body"})}function A(J){const L={};for(let[G,X]of J.entries())L[G]=X;return L}function W(J,L){let G={},X={},E=!1,Y=null,$=null,z=null,K=null,_=200;return{req:J,url:L,next:()=>{},status(I){return _=I,this},async body(){if(!K)K=await V(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 E=I,this},getAuth(){return E},text(I,U){if(U)_=U;return new Response(I,{status:_,headers:G})},json(I,U){if(U)_=U;return new Response(JSON.stringify(I),{status:_,headers:{"Content-Type":"application/json",...G}})},html(I,U){if(U)_=U;return new Response(Bun.file(I),{status:_,headers:{...G}})},file(I,U){if(U)_=U;return new Response(Bun.file(I),{status:_,headers:{...G}})},redirect(I,U){if(U)_=U;return new Response(null,{status:_,headers:{Location:I,...G}})},async getParams(I){if(!z)z=await R(J.routePattern,L.pathname);return I?z[I]:z},getQuery(I){if(!Y)Y=Object.fromEntries(L.searchParams.entries());return I?Y[I]:Y},cookie(I,U,Z={}){let F=`${encodeURIComponent(I)}=${encodeURIComponent(U)}`;if(Z.maxAge)F+=`; Max-Age=${Z.maxAge}`;if(Z.expires)F+=`; Expires=${Z.expires.toUTCString()}`;if(Z.path)F+=`; Path=${Z.path}`;if(Z.domain)F+=`; Domain=${Z.domain}`;if(Z.secure)F+="; Secure";if(Z.httpOnly)F+="; HttpOnly";if(Z.sameSite)F+=`; SameSite=${Z.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(!$)$=await O(J.headers.get("cookie"));return I?$[I]:$}}}async function T(J,L){for(let G of J){const X=await G(L);if(X)return X}}function j(J){return new Response(`Route not found for ${J}`,{status:404})}function D(){return new Response("Method not allowed",{status:405})}function Q(){return new Response("No response from handler",{status:204})}function b(){return new Response("Internal Server Error",{status:500})}async function B(J,L,G){const{pathname:X}=L,{method:E}=J,Y=G.trie.search(X,E);if(!Y||!Y.handler)return j(X);if(Y.method!==E)return D();if(Y.isDynamic)J.routePattern=Y.path;const $=W(J,L);if(G.hasMiddleware){const z=[...G.globalMiddlewares,...G.middlewares.get(X)||[]],K=await T(z,$);if(K)return K}try{return await Y.handler($)??Q()}catch(z){return b()}}export{B as default};
package/dist/router.js ADDED
@@ -0,0 +1 @@
1
+ class M{constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isImportant=!1,this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class A{constructor(){this.root=new M}insert(L,G){let E=this.root;const U=L.split("/").filter(Boolean);if(L==="/"){E.isEndOfWord=!0,E.handler.push(G.handler),E.isImportant=G.isImportant,E.path=L,E.method.push(G.method);return}for(let J of U){let X=!1,Z=J;if(J.startsWith(":"))X=!0,Z=":";if(!E.children[Z])E.children[Z]=new M;E=E.children[Z],E.isDynamic=X,E.pattern=J}E.isEndOfWord=!0,E.method.push(G.method),E.handler.push(G.handler),E.isImportant=G.isImportant,E.path=L}insertMidl(L){if(!this.root.subMiddlewares.has(L))this.root.subMiddlewares.set(L)}search(L,G){let E=this.root;const U=L.split("/").filter(Boolean);for(let X of U){let Z=X;if(!E.children[Z])if(E.children[":"])E=E.children[":"];else return null;else E=E.children[Z]}let J=E.method.indexOf(G);if(J!==-1)return{path:E.path,handler:E.handler[J],isDynamic:E.isDynamic,pattern:E.pattern,method:E.method[J]};return{path:E.path,handler:E.handler,isDynamic:E.isDynamic,pattern:E.pattern,method:E.method[J]}}getAllRoutes(){const L=[],G=(E,U)=>{if(E.isEndOfWord)L.push({path:U,handler:E.handler,isImportant:E.isImportant,isDynamic:E.isDynamic,pattern:E.pattern});for(let J in E.children){const X=E.children[J],Z=U+(J===":"?"/:"+X.pattern:"/"+J);G(X,Z)}};return G(this.root,""),L}}async function j(L){const G={};if(!L)return G;return L.split(";").forEach((U)=>{const[J,X]=U.trim().split("=");G[J]=X.split(" ")[0]}),G}async function C(L,G){const E={},U=L.split("/"),[J]=G.split("?"),X=J.split("/");if(U.length!==X.length)return null;return U.forEach((Z,$)=>{if(Z.startsWith(":")){const W=Z.slice(1);E[W]=X[$]}}),E}async function O(L){const G=L.headers.get("Content-Type");if(G.includes("application/json"))try{return await L.json()}catch(E){return new Response({error:"Invalid JSON format"})}else if(G.startsWith("application/x-www-form-urlencoded")){const E=await L.text();return Object.fromEntries(new URLSearchParams(E))}else if(G.startsWith("multipart/form-data")){const E=await L.formData();return I(E)}else return new Response({error:"unknown request body"})}function I(L){const G={};for(let[E,U]of L.entries())G[E]=U;return G}function V(L,G){let E={},U={},J=!1,X=null,Z=null,$=null,W=null,F=200;return{req:L,url:G,next:()=>{},status(Y){return F=Y,this},async body(){if(!W)W=await O(L);return W},setHeader(Y,_){return E[Y]=_,this},set(Y,_){return U[Y]=_,this},get(Y){return U[Y]},setAuth(Y){return J=Y,this},getAuth(){return J},text(Y,_){if(_)F=_;return new Response(Y,{status:F,headers:E})},json(Y,_){if(_)F=_;return new Response(JSON.stringify(Y),{status:F,headers:{"Content-Type":"application/json",...E}})},html(Y,_){if(_)F=_;return new Response(Bun.file(Y),{status:F,headers:{...E}})},file(Y,_){if(_)F=_;return new Response(Bun.file(Y),{status:F,headers:{...E}})},redirect(Y,_){if(_)F=_;return new Response(null,{status:F,headers:{Location:Y,...E}})},async getParams(Y){if(!$)$=await C(L.routePattern,G.pathname);return Y?$[Y]:$},getQuery(Y){if(!X)X=Object.fromEntries(G.searchParams.entries());return Y?X[Y]:X},cookie(Y,_,z={}){let K=`${encodeURIComponent(Y)}=${encodeURIComponent(_)}`;if(z.maxAge)K+=`; Max-Age=${z.maxAge}`;if(z.expires)K+=`; Expires=${z.expires.toUTCString()}`;if(z.path)K+=`; Path=${z.path}`;if(z.domain)K+=`; Domain=${z.domain}`;if(z.secure)K+="; Secure";if(z.httpOnly)K+="; HttpOnly";if(z.sameSite)K+=`; SameSite=${z.sameSite}`;if(E["Set-Cookie"]){const Q=Array.isArray(E["Set-Cookie"])?E["Set-Cookie"]:[E["Set-Cookie"]];Q.push(K),E["Set-Cookie"]=Q}else E["Set-Cookie"]=K;return this},async getCookie(Y){if(!Z)Z=await j(L.headers.get("cookie"));return Y?Z[Y]:Z}}}async function v(L,G){for(let E of L){const U=await E(G);if(U)return U}}function N(L){return new Response(`Route not found for ${L}`,{status:404})}function f(){return new Response("Method not allowed",{status:405})}function w(){return new Response("No response from handler",{status:204})}function R(){return new Response("Internal Server Error",{status:500})}async function B(L,G,E){const{pathname:U}=G,{method:J}=L,X=E.trie.search(U,J);if(!X||!X.handler)return N(U);if(X.method!==J)return f();if(X.isDynamic)L.routePattern=X.path;const Z=V(L,G);if(E.hasMiddleware){const $=[...E.globalMiddlewares,...E.middlewares.get(U)||[]],W=await v($,Z);if(W)return W}try{return await X.handler(Z)??w()}catch($){return R()}}class T{constructor(){this.routes=new Map,this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new A,this.hasMiddleware=!1}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}}listen(L,G){this.compile();const E=Bun.serve({port:L,fetch:async(U)=>{const J=new URL(U.url);try{return await B(U,J,this)}catch(X){return new Response("Internal Server Error",{status:500})}},onClose(){console.log("Server is shutting down...")}});if(typeof G==="function")return G();return console.log(`Server is running on http://localhost:${L}`),E}register(L,G){const E=Object.entries(G.trie.root.children);G.trie.root.subMiddlewares.forEach((U,J)=>{if(!this.middlewares.has(L+J))this.middlewares.set(L+J,[]);if(!this.middlewares.get(L+J).includes(...U))this.middlewares.get(L+J).push(...U)});for(let[U,J]of E){const X=L+J?.path,Z=J.handler[0],$=J.method[0];this.trie.insert(X,{handler:Z,method:$})}G.trie=new A}#E(L,G,E){const U=E.slice(0,-1);if(!this.middlewares.has(G))this.middlewares.set(G,[]);if(G==="/")U.forEach((X)=>{if(!this.globalMiddlewares.includes(X))this.globalMiddlewares.push(X)});else if(!this.middlewares.get(G).includes(...U))this.middlewares.get(G).push(...U);const J=E[E.length-1];this.trie.insert(G,{handler:J,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 D=T;class b extends D{constructor(){super()}#E(L,G,E){if(!this.trie.root.subMiddlewares.has(G))this.trie.root.subMiddlewares.set(G,[]);const U=E.slice(0,-1);if(!this.trie.root.subMiddlewares.get(G).includes(...U))this.trie.root.subMiddlewares.get(G).push(...U);const J=E[E.length-1];this.trie.insert(G,{handler:J,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 m=b;export{m as default};
package/dist/server.js ADDED
@@ -0,0 +1 @@
1
+ class A{constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isImportant=!1,this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class V{constructor(){this.root=new A}insert(J,L){let G=this.root;const X=J.split("/").filter(Boolean);if(J==="/"){G.isEndOfWord=!0,G.handler.push(L.handler),G.isImportant=L.isImportant,G.path=J,G.method.push(L.method);return}for(let U of X){let Y=!1,_=U;if(U.startsWith(":"))Y=!0,_=":";if(!G.children[_])G.children[_]=new A;G=G.children[_],G.isDynamic=Y,G.pattern=U}G.isEndOfWord=!0,G.method.push(L.method),G.handler.push(L.handler),G.isImportant=L.isImportant,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 _=Y;if(!G.children[_])if(G.children[":"])G=G.children[":"];else return null;else G=G.children[_]}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],_=X+(U===":"?"/:"+Y.pattern:"/"+U);L(Y,_)}};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}async function C(J,L){const G={},X=J.split("/"),[U]=L.split("?"),Y=U.split("/");if(X.length!==Y.length)return null;return X.forEach((_,z)=>{if(_.startsWith(":")){const E=_.slice(1);G[E]=Y[z]}}),G}async function O(J){const L=J.headers.get("Content-Type");if(L.includes("application/json"))try{return await J.json()}catch(G){return new Response({error:"Invalid JSON format"})}else if(L.startsWith("application/x-www-form-urlencoded")){const G=await J.text();return Object.fromEntries(new URLSearchParams(G))}else if(L.startsWith("multipart/form-data")){const G=await J.formData();return T(G)}else return new Response({error:"unknown request body"})}function T(J){const L={};for(let[G,X]of J.entries())L[G]=X;return L}function B(J,L){let G={},X={},U=!1,Y=null,_=null,z=null,E=null,K=200;return{req:J,url:L,next:()=>{},status(Z){return K=Z,this},async body(){if(!E)E=await O(J);return E},setHeader(Z,$){return G[Z]=$,this},set(Z,$){return X[Z]=$,this},get(Z){return X[Z]},setAuth(Z){return U=Z,this},getAuth(){return U},text(Z,$){if($)K=$;return new Response(Z,{status:K,headers:G})},json(Z,$){if($)K=$;return new Response(JSON.stringify(Z),{status:K,headers:{"Content-Type":"application/json",...G}})},html(Z,$){if($)K=$;return new Response(Bun.file(Z),{status:K,headers:{...G}})},file(Z,$){if($)K=$;return new Response(Bun.file(Z),{status:K,headers:{...G}})},redirect(Z,$){if($)K=$;return new Response(null,{status:K,headers:{Location:Z,...G}})},async getParams(Z){if(!z)z=await C(J.routePattern,L.pathname);return Z?z[Z]:z},getQuery(Z){if(!Y)Y=Object.fromEntries(L.searchParams.entries());return Z?Y[Z]:Y},cookie(Z,$,F={}){let W=`${encodeURIComponent(Z)}=${encodeURIComponent($)}`;if(F.maxAge)W+=`; Max-Age=${F.maxAge}`;if(F.expires)W+=`; Expires=${F.expires.toUTCString()}`;if(F.path)W+=`; Path=${F.path}`;if(F.domain)W+=`; Domain=${F.domain}`;if(F.secure)W+="; Secure";if(F.httpOnly)W+="; HttpOnly";if(F.sameSite)W+=`; SameSite=${F.sameSite}`;if(G["Set-Cookie"]){const j=Array.isArray(G["Set-Cookie"])?G["Set-Cookie"]:[G["Set-Cookie"]];j.push(W),G["Set-Cookie"]=j}else G["Set-Cookie"]=W;return this},async getCookie(Z){if(!_)_=await M(J.headers.get("cookie"));return Z?_[Z]:_}}}async function b(J,L){for(let G of J){const X=await G(L);if(X)return X}}function I(J){return new Response(`Route not found for ${J}`,{status:404})}function v(){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 Q(J,L,G){const{pathname:X}=L,{method:U}=J,Y=G.trie.search(X,U);if(!Y||!Y.handler)return I(X);if(Y.method!==U)return v();if(Y.isDynamic)J.routePattern=Y.path;const _=B(J,L);if(G.hasMiddleware){const z=[...G.globalMiddlewares,...G.middlewares.get(X)||[]],E=await b(z,_);if(E)return E}try{return await Y.handler(_)??N()}catch(z){return R()}}class D{constructor(){this.routes=new Map,this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new V,this.hasMiddleware=!1}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}}listen(J,L){this.compile();const G=Bun.serve({port:J,fetch:async(X)=>{const U=new URL(X.url);try{return await Q(X,U,this)}catch(Y){return new Response("Internal Server Error",{status:500})}},onClose(){console.log("Server is shutting down...")}});if(typeof L==="function")return L();return console.log(`Server is running on http://localhost:${J}`),G}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,_=U.handler[0],z=U.method[0];this.trie.insert(Y,{handler:_,method:z})}L.trie=new V}#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 S=D;export{S as default};
package/dist/trie.js ADDED
@@ -0,0 +1 @@
1
+ class E{constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isImportant=!1,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.isImportant=z.isImportant,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.isImportant=z.isImportant,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.3",
4
- "main": "src/server.js",
3
+ "version": "0.0.5",
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,26 +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)
18
- return parsedBody;
24
+ parsedBody = await parseBody(req);
19
25
  }
20
26
  return parsedBody;
21
27
  },
28
+
22
29
  setHeader(key, value) {
23
30
  headers[key] = value;
31
+ return this;
24
32
  },
25
33
 
26
34
  set(key, value) {
27
35
  settedValue[key] = value;
36
+ return this;
28
37
  },
29
38
 
30
39
  get(key) {
@@ -33,22 +42,30 @@ export default function createCtx(req, url) {
33
42
 
34
43
  setAuth(authStatus) {
35
44
  isAuthenticated = authStatus;
45
+ return this;
36
46
  },
37
47
 
38
48
  getAuth() {
39
49
  return isAuthenticated;
40
50
  },
41
51
 
42
- text(data, status = 200) {
52
+ // Response methods with optional status
53
+ text(data, status) {
54
+ if (status) {
55
+ responseStatus = status;
56
+ }
43
57
  return new Response(data, {
44
- status,
58
+ status: responseStatus,
45
59
  headers: headers,
46
60
  });
47
61
  },
48
62
 
49
- json(data, status = 200) {
63
+ json(data, status) {
64
+ if (status) {
65
+ responseStatus = status;
66
+ }
50
67
  return new Response(JSON.stringify(data), {
51
- status,
68
+ status: responseStatus,
52
69
  headers: {
53
70
  "Content-Type": "application/json",
54
71
  ...headers,
@@ -56,26 +73,36 @@ export default function createCtx(req, url) {
56
73
  });
57
74
  },
58
75
 
59
- html(filepath) {
76
+ html(filepath, status) {
77
+ if (status) {
78
+ responseStatus = status;
79
+ }
60
80
  return new Response(Bun.file(filepath), {
61
- status: 200,
81
+ status: responseStatus,
62
82
  headers: {
63
83
  ...headers,
64
84
  },
65
85
  });
66
86
  },
67
- file(filePath) {
87
+
88
+ file(filePath, status) {
89
+ if (status) {
90
+ responseStatus = status;
91
+ }
68
92
  return new Response(Bun.file(filePath), {
69
- status: 200,
93
+ status: responseStatus,
70
94
  headers: {
71
95
  ...headers,
72
96
  },
73
97
  });
74
98
  },
75
99
 
76
- redirect(path, status = 302) {
100
+ redirect(path, status) {
101
+ if (status) {
102
+ responseStatus = status;
103
+ }
77
104
  return new Response(null, {
78
- status,
105
+ status: responseStatus,
79
106
  headers: {
80
107
  Location: path,
81
108
  ...headers,
@@ -83,9 +110,9 @@ export default function createCtx(req, url) {
83
110
  });
84
111
  },
85
112
 
86
- getParams(props) {
113
+ async getParams(props) {
87
114
  if (!parsedParams) {
88
- parsedParams = extractDynamicParams(req.routePattern, url.pathname);
115
+ parsedParams = await extractDynamicParams(req.routePattern, url.pathname);
89
116
  }
90
117
  return props ? parsedParams[props] : parsedParams;
91
118
  },
@@ -97,7 +124,7 @@ export default function createCtx(req, url) {
97
124
  return props ? parsedQuery[props] : parsedQuery;
98
125
  },
99
126
 
100
- cookie(name, value, options = {}) {
127
+ async cookie(name, value, options = {}) {
101
128
  let cookieString = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
102
129
 
103
130
  // Add options to cookie string (e.g., expiration, path, HttpOnly, etc.)
@@ -110,59 +137,56 @@ export default function createCtx(req, url) {
110
137
  if (options.sameSite) cookieString += `; SameSite=${options.sameSite}`;
111
138
 
112
139
  if (headers["Set-Cookie"]) {
113
- // If it's already an array, push the new cookie, otherwise convert to array
114
140
  const existingCookies = Array.isArray(headers["Set-Cookie"]) ? headers["Set-Cookie"] : [headers["Set-Cookie"]];
115
-
116
- // Add the new cookie string to the array
117
141
  existingCookies.push(cookieString);
118
-
119
- // Update Set-Cookie header
120
142
  headers["Set-Cookie"] = existingCookies;
121
143
  } else {
122
- // If no cookies exist, initialize the header
123
144
  headers["Set-Cookie"] = cookieString;
124
145
  }
146
+ return this;
125
147
  },
126
- getCookie(cookieName) {
148
+
149
+ async getCookie(cookieName) {
127
150
  if (!parsedCookie) {
128
- parsedCookie = parseCookie(req.headers.get("cookie"));
151
+ parsedCookie = await parseCookie(req.headers.get("cookie"));
129
152
  }
130
153
  return cookieName ? parsedCookie[cookieName] : parsedCookie;
131
154
  },
132
155
  };
133
156
  }
134
157
 
135
- function parseCookie(header) {
158
+
159
+ async function parseCookie(header) {
136
160
  const cookies = {};
137
161
  if (!header) return cookies;
138
162
 
139
163
  const cookieArray = header.split(";");
140
164
  cookieArray.forEach((cookie) => {
141
- const [cookieName, cookievalue] = cookie.trim().split("=");
142
- cookies[cookieName] = cookievalue.split(" ")[0];
165
+ const [cookieName, cookieValue] = cookie.trim().split("=");
166
+ cookies[cookieName] = cookieValue.split(" ")[0];
143
167
  });
144
168
  return cookies;
145
169
  }
146
170
 
147
- const extractDynamicParams = (routePattern, path) => {
171
+ async function extractDynamicParams(routePattern, path) {
148
172
  const object = {};
149
173
  const routeSegments = routePattern.split("/");
150
- const [pathWithoutQuery] = path.split("?"); // Ignore the query string in the path
151
- const pathSegments = pathWithoutQuery.split("/"); // Re-split after removing query
174
+ const [pathWithoutQuery] = path.split("?");
175
+ const pathSegments = pathWithoutQuery.split("/");
152
176
 
153
177
  if (routeSegments.length !== pathSegments.length) {
154
- return null; // Path doesn't match the pattern
178
+ return null;
155
179
  }
156
180
 
157
181
  routeSegments.forEach((segment, index) => {
158
182
  if (segment.startsWith(":")) {
159
- const dynamicKey = segment.slice(1); // Remove ':' to get the key name
160
- object[dynamicKey] = pathSegments[index]; // Map the path segment to the key
183
+ const dynamicKey = segment.slice(1);
184
+ object[dynamicKey] = pathSegments[index];
161
185
  }
162
186
  });
163
187
 
164
188
  return object;
165
- };
189
+ }
166
190
 
167
191
  async function parseBody(req) {
168
192
  const contentType = req.headers.get("Content-Type");
@@ -10,7 +10,6 @@ export default async function handleRequest(req, url, diesel) {
10
10
  // Early return if route or method is not found
11
11
  if (!routeHandler || !routeHandler.handler) return responseNotFound(pathname);
12
12
  if (routeHandler.method !== method) return responseMethodNotAllowed();
13
-
14
13
  // If the route is dynamic, we only set routePattern if necessary
15
14
  if (routeHandler.isDynamic) req.routePattern = routeHandler.path;
16
15
 
@@ -19,7 +18,7 @@ export default async function handleRequest(req, url, diesel) {
19
18
  if (diesel.hasMiddleware) {
20
19
  const middlewares = [
21
20
  ...diesel.globalMiddlewares,
22
- ...(diesel.middlewares.get(pathname) || [])
21
+ ...diesel.middlewares.get(pathname) || []
23
22
  ];
24
23
 
25
24
  const middlewareResult = await executeMiddleware(middlewares, ctx);
package/src/server.js CHANGED
@@ -1,132 +1,143 @@
1
- import {serve} from 'bun'
2
- import Trie from './trie.js';
3
- import handleRequest from './handleRequest.js'
1
+ import Trie from "./trie.js";
2
+ import handleRequest from "./handleRequest.js";
4
3
 
5
4
  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;
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
+ }
12
+
13
+ compile() {
14
+ if (this.globalMiddlewares.length > 0) {
15
+ this.hasMiddleware = true;
12
16
  }
13
-
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
- }
17
+ for (const [path, middlewares] of this.middlewares.entries()) {
18
+ if (middlewares.length > 0) {
19
+ this.hasMiddleware = true;
20
+ break;
21
+ }
22
+ }
23
+ }
24
+
25
+ listen(port, { sslCert = null, sslKey = null } = {}, callback) {
26
+ this.compile();
27
+ const options = {
28
+ port,
29
+ fetch: async (req) => {
30
+ const url = new URL(req.url);
31
+ try {
32
+ return await handleRequest(req, url, this);
33
+ } catch (error) {
34
+ return new Response("Internal Server Error", { status: 500 });
23
35
  }
36
+ },
37
+ onClose() {
38
+ console.log("Server is shutting down...");
39
+ },
40
+ };
41
+
42
+ if (sslCert && sslKey) {
43
+ options.certFile = sslCert;
44
+ options.keyFile = sslKey;
45
+ }
46
+ const server = Bun.serve(options);
47
+
48
+ if (typeof callback === "function") {
49
+ return callback();
24
50
  }
25
-
26
- listen(port,callback){
27
- this.compile()
28
- const server = serve({
29
- port,
30
- fetch: (req) => {
31
- const url = new URL(req.url)
32
- return handleRequest(req,url,this)
33
- },
34
- onClose() {
35
- console.log("Server is shutting down...");
36
- }
37
- });
38
- if (typeof callback === 'function') {
39
- return callback();
40
- }
41
- console.log(`Server is running on http://localhost:${port}`);
42
- return server;
51
+
52
+ if (sslCert && sslKey) {
53
+ console.log(`HTTPS server is running on https://localhost:${port}`);
54
+ } else {
55
+ console.log(`HTTP server is running on http://localhost:${port}`);
43
56
  }
44
57
 
45
- register(pathPrefix,handlerInstance){
46
- const routeEntries = Object.entries(handlerInstance.trie.root.children);
47
- // console.log(handlerInstance.trie.root);
48
- handlerInstance.trie.root.subMiddlewares.forEach((middleware,path)=>{
49
- if (!this.middlewares.has(pathPrefix+path)) {
50
- this.middlewares.set(pathPrefix+path, []);
51
- }
52
- if (!this.middlewares.get(pathPrefix+path).includes(...middleware)) {
53
- this.middlewares.get(pathPrefix+path).push(...middleware);
54
- }
55
- })
56
- for (const [routeKey, routeNode] of routeEntries) {
57
- const fullpath = pathPrefix + routeNode?.path;
58
- const routeHandler = routeNode.handler[0];
59
- const httpMethod = routeNode.method[0];
60
- this.trie.insert(fullpath, { handler: routeHandler, method: httpMethod });
61
- }
62
- handlerInstance.trie = new Trie();
58
+ return server;
59
+ }
60
+
61
+ register(pathPrefix, handlerInstance) {
62
+ const routeEntries = Object.entries(handlerInstance.trie.root.children);
63
+ // console.log(handlerInstance.trie.root);
64
+ handlerInstance.trie.root.subMiddlewares.forEach((middleware, path) => {
65
+ if (!this.middlewares.has(pathPrefix + path)) {
66
+ this.middlewares.set(pathPrefix + path, []);
67
+ }
68
+ if (!this.middlewares.get(pathPrefix + path).includes(...middleware)) {
69
+ this.middlewares.get(pathPrefix + path).push(...middleware);
70
+ }
71
+ });
72
+ for (const [routeKey, routeNode] of routeEntries) {
73
+ const fullpath = pathPrefix + routeNode?.path;
74
+ const routeHandler = routeNode.handler[0];
75
+ const httpMethod = routeNode.method[0];
76
+ this.trie.insert(fullpath, { handler: routeHandler, method: httpMethod });
63
77
  }
78
+ handlerInstance.trie = new Trie();
79
+ }
64
80
 
65
- #addRoute(method,path,handlers){
66
-
67
- const middlewareHandlers = handlers.slice(0, -1);
81
+ #addRoute(method, path, handlers) {
82
+ const middlewareHandlers = handlers.slice(0, -1);
68
83
 
69
- if (!this.middlewares.has(path)) {
70
- this.middlewares.set(path,[])
71
- }
72
- if (path === '/') {
73
- middlewareHandlers.forEach(midlleware => {
74
- if(!this.globalMiddlewares.includes(midlleware)){
75
- this.globalMiddlewares.push(midlleware)
76
- }
77
- })
78
- } else {
79
- if (!this.middlewares.get(path).includes(...middlewareHandlers)) {
80
- this.middlewares.get(path).push(...middlewareHandlers);
81
- }
84
+ if (!this.middlewares.has(path)) {
85
+ this.middlewares.set(path, []);
86
+ }
87
+ if (path === "/") {
88
+ middlewareHandlers.forEach((midlleware) => {
89
+ if (!this.globalMiddlewares.includes(midlleware)) {
90
+ this.globalMiddlewares.push(midlleware);
82
91
  }
83
-
84
- const handler = handlers[handlers.length-1]
85
- this.trie.insert(path,{handler,method})
86
-
92
+ });
93
+ } else {
94
+ if (!this.middlewares.get(path).includes(...middlewareHandlers)) {
95
+ this.middlewares.get(path).push(...middlewareHandlers);
96
+ }
87
97
  }
88
98
 
99
+ const handler = handlers[handlers.length - 1];
100
+ this.trie.insert(path, { handler, method });
101
+ }
89
102
 
90
- use(pathORHandler,handler){
91
- if (typeof pathORHandler === 'function') {
92
- if (!this.globalMiddlewares.includes(pathORHandler)) {
93
- return this.globalMiddlewares.push(pathORHandler)
94
- }
95
- }
96
- // now it means it is path midl
97
- const path = pathORHandler
98
- if (!this.middlewares.has(path)) {
99
- this.middlewares.set(path,[])
100
- }
101
-
102
- if(!this.middlewares.get(path).includes(handler)){
103
- this.middlewares.get(path).push(handler)
104
- }
103
+ use(pathORHandler, handler) {
104
+ if (typeof pathORHandler === "function") {
105
+ if (!this.globalMiddlewares.includes(pathORHandler)) {
106
+ return this.globalMiddlewares.push(pathORHandler);
107
+ }
105
108
  }
106
-
107
- get(path,...handlers){
108
- return this.#addRoute("GET",path,handlers)
109
+ // now it means it is path midl
110
+ const path = pathORHandler;
111
+ if (!this.middlewares.has(path)) {
112
+ this.middlewares.set(path, []);
109
113
  }
110
114
 
111
- post(path,...handlers){
112
- return this.#addRoute("POST",path,handlers)
115
+ if (!this.middlewares.get(path).includes(handler)) {
116
+ this.middlewares.get(path).push(handler);
113
117
  }
118
+ }
114
119
 
115
- put(path,...handlers){
116
- return this.#addRoute("PUT",path,handlers)
117
- }
120
+ get(path, ...handlers) {
121
+ return this.#addRoute("GET", path, handlers);
122
+ }
118
123
 
119
- patch(path,...handlers){
120
- if (handlers.length>0) {
121
- return this.#addRoute("PATCH",path,handlers)
122
- }
123
- }
124
+ post(path, ...handlers) {
125
+ return this.#addRoute("POST", path, handlers);
126
+ }
124
127
 
125
- delete(path,...handlers){
126
- return this.#addRoute("DELETE",path,handlers)
128
+ put(path, ...handlers) {
129
+ return this.#addRoute("PUT", path, handlers);
130
+ }
131
+
132
+ patch(path, ...handlers) {
133
+ if (handlers.length > 0) {
134
+ return this.#addRoute("PATCH", path, handlers);
127
135
  }
136
+ }
128
137
 
138
+ delete(path, ...handlers) {
139
+ return this.#addRoute("DELETE", path, handlers);
140
+ }
129
141
  }
130
142
 
131
-
132
- export default diesel;
143
+ export default diesel;
package/src/trie.js CHANGED
@@ -98,7 +98,13 @@ class TrieNode {
98
98
  }
99
99
 
100
100
  // Fallback if method is not found
101
- return null;
101
+ return {
102
+ path: node.path,
103
+ handler: node.handler,
104
+ isDynamic: node.isDynamic,
105
+ pattern: node.pattern,
106
+ method: node.method[routeMethodIndex]
107
+ };
102
108
  }
103
109
 
104
110