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 +12 -0
- package/dist/ctx.js +1 -0
- package/dist/handleRequest.js +1 -0
- package/dist/router.js +1 -0
- package/dist/server.js +1 -0
- package/dist/trie.js +1 -0
- package/package.json +2 -2
- package/src/ctx.js +54 -29
- package/src/server.js +118 -111
package/build.js
ADDED
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
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
|
-
|
|
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
|
|
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:
|
|
81
|
+
status: responseStatus,
|
|
61
82
|
headers: {
|
|
62
83
|
...headers,
|
|
63
84
|
},
|
|
64
85
|
});
|
|
65
86
|
},
|
|
66
|
-
|
|
87
|
+
|
|
88
|
+
file(filePath, status) {
|
|
89
|
+
if (status) {
|
|
90
|
+
responseStatus = status;
|
|
91
|
+
}
|
|
67
92
|
return new Response(Bun.file(filePath), {
|
|
68
|
-
status:
|
|
93
|
+
status: responseStatus,
|
|
69
94
|
headers: {
|
|
70
95
|
...headers,
|
|
71
96
|
},
|
|
72
97
|
});
|
|
73
98
|
},
|
|
74
99
|
|
|
75
|
-
redirect(path, status
|
|
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,
|
|
141
|
-
cookies[cookieName] =
|
|
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
|
|
171
|
+
async function extractDynamicParams(routePattern, path) {
|
|
147
172
|
const object = {};
|
|
148
173
|
const routeSegments = routePattern.split("/");
|
|
149
|
-
const [pathWithoutQuery] = path.split("?");
|
|
150
|
-
const pathSegments = pathWithoutQuery.split("/");
|
|
174
|
+
const [pathWithoutQuery] = path.split("?");
|
|
175
|
+
const pathSegments = pathWithoutQuery.split("/");
|
|
151
176
|
|
|
152
177
|
if (routeSegments.length !== pathSegments.length) {
|
|
153
|
-
return null;
|
|
178
|
+
return null;
|
|
154
179
|
}
|
|
155
180
|
|
|
156
181
|
routeSegments.forEach((segment, index) => {
|
|
157
182
|
if (segment.startsWith(":")) {
|
|
158
|
-
const dynamicKey = segment.slice(1);
|
|
159
|
-
object[dynamicKey] = pathSegments[index];
|
|
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
|
|
2
|
-
import
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
const middlewareHandlers = handlers.slice(0, -1);
|
|
81
|
+
#addRoute(method, path, handlers) {
|
|
82
|
+
const middlewareHandlers = handlers.slice(0, -1);
|
|
72
83
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
|
|
89
|
-
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
|
|
112
|
-
|
|
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
|
-
|
|
116
|
-
|
|
115
|
+
if (!this.middlewares.get(path).includes(handler)) {
|
|
116
|
+
this.middlewares.get(path).push(handler);
|
|
117
117
|
}
|
|
118
|
+
}
|
|
118
119
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
get(path, ...handlers) {
|
|
121
|
+
return this.#addRoute("GET", path, handlers);
|
|
122
|
+
}
|
|
122
123
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
}
|
|
124
|
+
post(path, ...handlers) {
|
|
125
|
+
return this.#addRoute("POST", path, handlers);
|
|
126
|
+
}
|
|
128
127
|
|
|
129
|
-
|
|
130
|
-
|
|
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;
|