diesel-core 0.0.4 → 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.4",
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,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,
@@ -96,7 +124,7 @@ export default function createCtx(req, url) {
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,37 +155,38 @@ 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
+ async 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
192
  const contentType = req.headers.get("Content-Type");
package/src/server.js CHANGED
@@ -1,136 +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: 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;
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}`);
47
56
  }
48
57
 
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();
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 });
67
77
  }
78
+ handlerInstance.trie = new Trie();
79
+ }
68
80
 
69
- #addRoute(method,path,handlers){
70
-
71
- const middlewareHandlers = handlers.slice(0, -1);
81
+ #addRoute(method, path, handlers) {
82
+ const middlewareHandlers = handlers.slice(0, -1);
72
83
 
73
- if (!this.middlewares.has(path)) {
74
- this.middlewares.set(path,[])
75
- }
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
- }
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);
86
91
  }
87
-
88
- const handler = handlers[handlers.length-1]
89
- this.trie.insert(path,{handler,method})
90
-
92
+ });
93
+ } else {
94
+ if (!this.middlewares.get(path).includes(...middlewareHandlers)) {
95
+ this.middlewares.get(path).push(...middlewareHandlers);
96
+ }
91
97
  }
92
98
 
99
+ const handler = handlers[handlers.length - 1];
100
+ this.trie.insert(path, { handler, method });
101
+ }
93
102
 
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
- }
103
+ use(pathORHandler, handler) {
104
+ if (typeof pathORHandler === "function") {
105
+ if (!this.globalMiddlewares.includes(pathORHandler)) {
106
+ return this.globalMiddlewares.push(pathORHandler);
107
+ }
109
108
  }
110
-
111
- get(path,...handlers){
112
- 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, []);
113
113
  }
114
114
 
115
- post(path,...handlers){
116
- return this.#addRoute("POST",path,handlers)
115
+ if (!this.middlewares.get(path).includes(handler)) {
116
+ this.middlewares.get(path).push(handler);
117
117
  }
118
+ }
118
119
 
119
- put(path,...handlers){
120
- return this.#addRoute("PUT",path,handlers)
121
- }
120
+ get(path, ...handlers) {
121
+ return this.#addRoute("GET", path, handlers);
122
+ }
122
123
 
123
- patch(path,...handlers){
124
- if (handlers.length>0) {
125
- return this.#addRoute("PATCH",path,handlers)
126
- }
127
- }
124
+ post(path, ...handlers) {
125
+ return this.#addRoute("POST", path, handlers);
126
+ }
128
127
 
129
- delete(path,...handlers){
130
- 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);
131
135
  }
136
+ }
132
137
 
138
+ delete(path, ...handlers) {
139
+ return this.#addRoute("DELETE", path, handlers);
140
+ }
133
141
  }
134
142
 
135
-
136
- export default diesel;
143
+ export default diesel;