diesel-core 0.0.8 → 0.0.11
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/dist/ctx.d.ts +2 -0
- package/dist/ctx.js +1 -1
- package/dist/handleRequest.d.ts +2 -0
- package/dist/handleRequest.js +1 -1
- package/dist/main.d.ts +27 -0
- package/dist/main.js +1 -1
- package/dist/router.d.ts +12 -0
- package/dist/router.js +1 -1
- package/dist/trie.d.ts +31 -0
- package/dist/trie.js +1 -1
- package/dist/types.d.ts +96 -0
- package/example/tester.js +2 -2
- package/package.json +4 -3
- package/src/ctx.ts +17 -19
- package/src/handleRequest.ts +6 -6
- package/src/main.ts +9 -1
- package/src/types.ts +6 -6
- package/test/README.md +15 -0
- package/test/bun.lockb +0 -0
- package/test/index.ts +1 -0
- package/test/package.json +11 -0
- package/test/tsconfig.json +27 -0
- package/tsconfig.json +4 -2
- package/dist/server.js +0 -1
package/dist/ctx.d.ts
ADDED
package/dist/ctx.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
async function $(G){const F={};if(!G)return F;return G.split(";").forEach((L)=>{const[R,J]=L?.trim()?.split("=");if(R&&J)F[R.trim()]=J.split(" ")[0].trim()}),F}function K(G,F){const z={},L=G.split("/"),[R]=F.split("?"),J=R.split("/");if(L.length!==J.length)return null;return L.forEach((U,Y)=>{if(U.startsWith(":")){const X=U.slice(1);z[X]=J[Y]}}),z}async function W(G){const F=G.headers.get("Content-Type")||"";if(!F)return{};try{if(F.startsWith("application/json"))return await G.json();if(F.startsWith("application/x-www-form-urlencoded")){const z=await G.text();return Object.fromEntries(new URLSearchParams(z))}if(F.startsWith("multipart/form-data")){const z=await G.formData();return O(z)}return{error:"Unknown request body type"}}catch(z){return{error:"Invalid request body format"}}}function O(G){const F={};for(let[z,L]of G.entries())F[z]=L;return F}function _(G,F){let z=new Headers,L={},R=!1,J=null,U=null,Y=null,X,Z=200;return{req:G,url:F,next:()=>{},status(w){return Z=w,this},async body(){if(!X)X=await W(G);if(X.error)return new Response(JSON.stringify({error:X.error}),{status:400});return X},setHeader(w,E){return z.set(w,E),this},set(w,E){return L[w]=E,this},get(w){return L[w]||null},setAuth(w){return R=w,this},getAuth(){return R},text(w,E){return new Response(w,{status:E??Z,headers:z})},json(w,E){return new Response(JSON.stringify(w),{status:E??Z,headers:z})},html(w,E){return new Response(Bun.file(w),{status:E??Z,headers:z})},file(w,E){return new Response(Bun.file(w),{status:E??Z,headers:z})},redirect(w,E){return z.set("Location",w),new Response(null,{status:E??302,headers:z})},getParams(w){if(!Y)Y=K(G?.routePattern,F?.pathname);return w?Y[w]||null:Y},getQuery(w){if(!J)J=Object.fromEntries(F.searchParams);return w?J[w]||null:J},async cookie(w,E,I={}){let M=`${encodeURIComponent(w)}=${encodeURIComponent(E)}`;if(I.maxAge)M+=`; Max-Age=${I.maxAge}`;if(I.expires)M+=`; Expires=${I.expires.toUTCString()}`;if(I.path)M+=`; Path=${I.path}`;if(I.domain)M+=`; Domain=${I.domain}`;if(I.secure)M+="; Secure";if(I.httpOnly)M+="; HttpOnly";if(I.sameSite)M+=`; SameSite=${I.sameSite}`;return z?.append("Set-Cookie",M),this},async getCookie(w){if(!U){const E=G.headers.get("cookie");if(E)U=await $(E)}return w?U[w]||null:U}}}export{_ as default};
|
package/dist/handleRequest.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
async function O(G){const F={};if(!G)return F;return G.split(";").forEach((I)=>{const[U,J]=I?.trim()?.split("=");if(U&&J)F[U.trim()]=J.split(" ")[0].trim()}),F}function A(G,F){const z={},I=G.split("/"),[U]=F.split("?"),J=U.split("/");if(I.length!==J.length)return null;return I.forEach((X,$)=>{if(X.startsWith(":")){const _=X.slice(1);z[_]=J[$]}}),z}async function V(G){const F=G.headers.get("Content-Type")||"";if(!F)return{};try{if(F.startsWith("application/json"))return await G.json();if(F.startsWith("application/x-www-form-urlencoded")){const z=await G.text();return Object.fromEntries(new URLSearchParams(z))}if(F.startsWith("multipart/form-data")){const z=await G.formData();return j(z)}return{error:"Unknown request body type"}}catch(z){return{error:"Invalid request body format"}}}function j(G){const F={};for(let[z,I]of G.entries())F[z]=I;return F}function M(G,F){let z=new Headers,I={},U=!1,J=null,X=null,$=null,_,K=200;return{req:G,url:F,next:()=>{},status(E){return K=E,this},async body(){if(!_)_=await V(G);if(_.error)return new Response(JSON.stringify({error:_.error}),{status:400});return _},setHeader(E,L){return z.set(E,L),this},set(E,L){return I[E]=L,this},get(E){return I[E]||null},setAuth(E){return U=E,this},getAuth(){return U},text(E,L){return new Response(E,{status:L??K,headers:z})},json(E,L){return new Response(JSON.stringify(E),{status:L??K,headers:z})},html(E,L){return new Response(Bun.file(E),{status:L??K,headers:z})},file(E,L){return new Response(Bun.file(E),{status:L??K,headers:z})},redirect(E,L){return z.set("Location",E),new Response(null,{status:L??302,headers:z})},getParams(E){if(!$)$=A(G?.routePattern,F?.pathname);return E?$[E]||null:$},getQuery(E){if(!J)J=Object.fromEntries(F.searchParams);return E?J[E]||null:J},async cookie(E,L,Y={}){let Z=`${encodeURIComponent(E)}=${encodeURIComponent(L)}`;if(Y.maxAge)Z+=`; Max-Age=${Y.maxAge}`;if(Y.expires)Z+=`; Expires=${Y.expires.toUTCString()}`;if(Y.path)Z+=`; Path=${Y.path}`;if(Y.domain)Z+=`; Domain=${Y.domain}`;if(Y.secure)Z+="; Secure";if(Y.httpOnly)Z+="; HttpOnly";if(Y.sameSite)Z+=`; SameSite=${Y.sameSite}`;return z?.append("Set-Cookie",Z),this},async getCookie(E){if(!X){const L=G.headers.get("cookie");if(L)X=await O(L)}return E?X[E]||null:X}}}async function Q(G,F){for(let z of G){const I=await z(F);if(I)return I}}var W={};async function D(G,F,z){const I=M(G,F);if(z.hasOnReqHook&&z.hooks.onRequest)await z.hooks.onRequest(I);if(z.hasMiddleware){const J=[...z.globalMiddlewares,...z.middlewares.get(F.pathname)||[]],X=await Q(J,I);if(X)return X}let U;if(W[F.pathname+G.method])U=W[F.pathname+G.method];else U=z.trie.search(F.pathname,G.method),W[F.pathname+G.method]=U;if(!U||!U.handler)return new Response(`Route not found for ${F.pathname}`,{status:404});if(U.method!==G.method)return new Response("Method not allowed",{status:405});if(U.isDynamic)G.routePattern=U.path;if(z.hasPreHandlerHook&&z.hooks.preHandler){const J=await z.hooks.preHandler(I);if(J)return J}try{const J=await U.handler(I);if(z.hasPostHandlerHook&&z.hooks.postHandler)await z.hooks.postHandler(I);if(z.hasOnSendHook&&z.hooks.onSend){const X=await z.hooks.onSend(I,J);if(X)return X}return J??new Response("No response from handler",{status:204})}catch(J){return new Response("Internal Server Error",{status:500})}}export{D as default};
|
package/dist/main.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import Trie from "./trie.js";
|
|
2
|
+
import { HookType, type handlerFunction, type Hooks, type listenCalllBackType } from "./types.js";
|
|
3
|
+
declare class Diesel {
|
|
4
|
+
#private;
|
|
5
|
+
routes: Map<String, any>;
|
|
6
|
+
globalMiddlewares: handlerFunction[];
|
|
7
|
+
middlewares: Map<string, handlerFunction[]>;
|
|
8
|
+
trie: Trie;
|
|
9
|
+
hasOnReqHook: boolean;
|
|
10
|
+
hasMiddleware: boolean;
|
|
11
|
+
hasPreHandlerHook: boolean;
|
|
12
|
+
hasPostHandlerHook: boolean;
|
|
13
|
+
hasOnSendHook: boolean;
|
|
14
|
+
hooks: Hooks;
|
|
15
|
+
constructor();
|
|
16
|
+
addHooks(typeOfHook: HookType, fnc: handlerFunction): void;
|
|
17
|
+
compile(): void;
|
|
18
|
+
listen(port: number, callback?: listenCalllBackType, { sslCert, sslKey }?: any): void | import("bun").Server;
|
|
19
|
+
register(pathPrefix: string, handlerInstance: any): void;
|
|
20
|
+
use(pathORHandler: string | handlerFunction, handler: handlerFunction): number | undefined;
|
|
21
|
+
get(path: string, ...handlers: handlerFunction[]): this;
|
|
22
|
+
post(path: string, ...handlers: handlerFunction[]): this;
|
|
23
|
+
put(path: string, ...handlers: handlerFunction[]): this;
|
|
24
|
+
patch(path: string, ...handlers: handlerFunction[]): this;
|
|
25
|
+
delete(path: any, ...handlers: handlerFunction[]): this;
|
|
26
|
+
}
|
|
27
|
+
export default Diesel;
|
package/dist/main.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var C=(J,L)=>()=>(L||J((L={exports:{}}).exports,L),L.exports);var S=C((D)=>{Object.defineProperty(D,"__esModule",{value:!0});class O{constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class j{constructor(){this.root=new O}insert(J,L){let z=this.root;const U=J.split("/").filter(Boolean);if(J==="/"){z.isEndOfWord=!0,z.handler.push(L.handler),z.path=J,z.method.push(L.method);return}for(let X of U){let Y=!1,Z=X;if(X.startsWith(":"))Y=!0,Z=":";if(!z.children[Z])z.children[Z]=new O;z=z.children[Z],z.isDynamic=Y,z.pattern=X}z.isEndOfWord=!0,z.method.push(L.method),z.handler.push(L.handler),z.path=J}search(J,L){let z=this.root;const U=J.split("/").filter(Boolean);for(let Y of U){let Z=Y;if(!z.children[Z])if(z.children[":"])z=z.children[":"];else return null;else z=z.children[Z]}let X=z.method.indexOf(L);if(X!==-1)return{path:z.path,handler:z.handler[X],isDynamic:z.isDynamic,pattern:z.pattern,method:z.method[X]};return{path:z.path,handler:z.handler,isDynamic:z.isDynamic,pattern:z.pattern,method:z.method[X]}}}D.default=j});var H=C((I)=>{function k(J,L){let z={},U={},X=!1,Y=null,Z=null,W=null,G,V=200;return{req:J,url:L,next:()=>{},status($){return V=$,this},body(){return T(this,void 0,void 0,function*(){if(!G)G=yield c(J);if(G.error)return new Response(JSON.stringify({error:G.error}),{status:400,headers:{"Content-Type":"application/json"}});return G})},setHeader($,E){return z[$]=E,this},set($,E){return U[$]=E,this},get($){return U[$]||null},setAuth($){return X=$,this},getAuth(){return X},text($,E){if(E)V=E;return new Response($,{status:V,headers:z})},json($,E){if(E)V=E;return new Response(JSON.stringify($),{status:V,headers:Object.assign({"Content-Type":"application/json"},z)})},html($,E){if(E)V=E;return new Response(Bun.file($),{status:V,headers:Object.assign({},z)})},file($,E){if(E)V=E;return new Response(Bun.file($),{status:V,headers:Object.assign({},z)})},redirect($,E){if(E)V=E;return new Response(null,{status:V,headers:Object.assign({Location:$},z)})},getParams($){if(!W)W=m(J===null||J===void 0?void 0:J.routePattern,L===null||L===void 0?void 0:L.pathname);return $?W[$]||null:W},getQuery($){if(!Y)Y=Object.fromEntries(L.searchParams);return $?Y[$]||null:Y},cookie($,E){return T(this,arguments,void 0,function*(f,v,Q={}){let F=`${encodeURIComponent(f)}=${encodeURIComponent(v)}`;if(Q.maxAge)F+=`; Max-Age=${Q.maxAge}`;if(Q.expires)F+=`; Expires=${Q.expires.toUTCString()}`;if(Q.path)F+=`; Path=${Q.path}`;if(Q.domain)F+=`; Domain=${Q.domain}`;if(Q.secure)F+="; Secure";if(Q.httpOnly)F+="; HttpOnly";if(Q.sameSite)F+=`; SameSite=${Q.sameSite}`;if(z["Set-Cookie"]){const R=Array.isArray(z["Set-Cookie"])?z["Set-Cookie"]:[z["Set-Cookie"]];R.push(F),z["Set-Cookie"]=R}else z["Set-Cookie"]=F;return this})},getCookie($){return T(this,void 0,void 0,function*(){if(!Z){const E=J.headers.get("cookie");if(E)Z=yield _(E)}return $?Z[$]||null:Z})}}}function _(J){return T(this,void 0,void 0,function*(){const L={};if(!J)return L;return J.split(";").forEach((U)=>{var X;const[Y,Z]=(X=U===null||U===void 0?void 0:U.trim())===null||X===void 0?void 0:X.split("=");if(Y&&Z)L[Y.trim()]=Z.split(" ")[0].trim()}),L})}function m(J,L){const z={},U=J.split("/"),[X]=L.split("?"),Y=X.split("/");if(U.length!==Y.length)return null;return U.forEach((Z,W)=>{if(Z.startsWith(":")){const G=Z.slice(1);z[G]=Y[W]}}),z}function c(J){return T(this,void 0,void 0,function*(){const L=J.headers.get("Content-Type")||"";if(!L)return{};try{if(L.startsWith("application/json"))return yield J.json();if(L.startsWith("application/x-www-form-urlencoded")){const z=yield J.text();return Object.fromEntries(new URLSearchParams(z))}if(L.startsWith("multipart/form-data")){const z=yield J.formData();return h(z)}return{error:"Unknown request body type"}}catch(z){return{error:"Invalid request body format"}}})}function h(J){const L={};for(let[z,U]of J.entries())L[z]=U;return L}var T=I&&I.__awaiter||function(J,L,z,U){function X(Y){return Y instanceof z?Y:new z(function(Z){Z(Y)})}return new(z||(z=Promise))(function(Y,Z){function W($){try{V(U.next($))}catch(E){Z(E)}}function G($){try{V(U.throw($))}catch(E){Z(E)}}function V($){$.done?Y($.value):X($.value).then(W,G)}V((U=U.apply(J,L||[])).next())})};Object.defineProperty(I,"__esModule",{value:!0});I.default=k});var q=C((B)=>{function i(J,L,z){return w(this,void 0,void 0,function*(){const U=p.default(J,L);if(z.hasOnReqHook)yield z.hooks.onRequest(U);if(z.hasMiddleware){const Y=[...z.globalMiddlewares,...z.middlewares.get(L.pathname)||[]],Z=yield n(Y,U);if(Z)return Z}let X;if(b[L.pathname+J.method])X=b[L.pathname+J.method];else X=z.trie.search(L.pathname,J.method),b[L.pathname+J.method]=X;if(!X||!X.handler)return new Response(`Route not found for ${L.pathname}`,{status:404});if(X.method!==J.method)return new Response("Method not allowed",{status:405});if(X.isDynamic)J.routePattern=X.path;if(z.hasPreHandlerHook){const Y=yield z.hooks.preHandler(U);if(Y)return Y}try{const Y=yield X.handler(U);if(z.hasPostHandlerHook)yield z.hooks.postHandler(U);if(z.hasOnSendHook){const Z=yield z.hooks.onSend(Y,U);if(Z)return Z}return Y!==null&&Y!==void 0?Y:new Response("No response from handler",{status:204})}catch(Y){return new Response("Internal Server Error",{status:500})}})}function n(J,L){return w(this,void 0,void 0,function*(){for(let z of J){const U=yield z(L);if(U)return U}})}var w=B&&B.__awaiter||function(J,L,z,U){function X(Y){return Y instanceof z?Y:new z(function(Z){Z(Y)})}return new(z||(z=Promise))(function(Y,Z){function W($){try{V(U.next($))}catch(E){Z(E)}}function G($){try{V(U.throw($))}catch(E){Z(E)}}function V($){$.done?Y($.value):X($.value).then(W,G)}V((U=U.apply(J,L||[])).next())})},u=B&&B.__importDefault||function(J){return J&&J.__esModule?J:{default:J}};Object.defineProperty(B,"__esModule",{value:!0});B.default=i;var p=u(H()),b={}});var o=C((M)=>{var l=M&&M.__awaiter||function(J,L,z,U){function X(Y){return Y instanceof z?Y:new z(function(Z){Z(Y)})}return new(z||(z=Promise))(function(Y,Z){function W($){try{V(U.next($))}catch(E){Z(E)}}function G($){try{V(U.throw($))}catch(E){Z(E)}}function V($){$.done?Y($.value):X($.value).then(W,G)}V((U=U.apply(J,L||[])).next())})},N=M&&M.__classPrivateFieldGet||function(J,L,z,U){if(z==="a"&&!U)throw new TypeError("Private accessor was defined without a getter");if(typeof L==="function"?J!==L||!U:!L.has(J))throw new TypeError("Cannot read private member from an object whose class did not declare it");return z==="m"?U:z==="a"?U.call(J):U?U.value:L.get(J)},P=M&&M.__importDefault||function(J){return J&&J.__esModule?J:{default:J}},K,A;Object.defineProperty(M,"__esModule",{value:!0});var y=P(S()),d=P(q());class x{constructor(){K.add(this),this.routes=new Map,this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new y.default,this.hasMiddleware=!1,this.hasOnReqHook=!1,this.hasPreHandlerHook=!1,this.hasPostHandlerHook=!1,this.hasOnSendHook=!1,this.hooks={onRequest:null,preHandler:null,postHandler:null,onSend:null,onError:null,onClose:null}}addHooks(J,L){if(typeof J!=="string")throw new Error("hookName must be a string");if(typeof L!=="function")throw new Error("callback must be a instance of function");if(this.hooks.hasOwnProperty(J))this.hooks[J]=L;else throw new Error(`Unknown hook type: ${J}`)}compile(){if(this.globalMiddlewares.length>0)this.hasMiddleware=!0;for(let[J,L]of this.middlewares.entries())if(L.length>0){this.hasMiddleware=!0;break}if(this.hooks.onRequest)this.hasOnReqHook=!0;if(this.hooks.preHandler)this.hasPreHandlerHook=!0;if(this.hooks.postHandler)this.hasPostHandlerHook=!0;if(this.hooks.onSend)this.hasOnSendHook=!0}listen(J,L,{sslCert:z=null,sslKey:U=null}={}){if(typeof Bun==="undefined")throw new Error(".listen() is designed to run on Bun only...");if(typeof J!=="number")throw new Error("Port must be a numeric value");this.compile();const X={port:J,fetch:(Z)=>l(this,void 0,void 0,function*(){const W=new URL(Z.url);try{return yield d.default(Z,W,this)}catch(G){return new Response("Internal Server Error",{status:500})}}),onClose(){console.log("Server is shutting down...")}};if(z&&U)X.certFile=z,X.keyFile=U;const Y=Bun.serve(X);if(typeof L==="function")return L();if(z&&U)console.log(`HTTPS server is running on https://localhost:${J}`);else console.log(`HTTP server is running on http://localhost:${J}`);return Y}register(J,L){if(typeof J!=="string")throw new Error("path must be a string");if(typeof L!=="object")throw new Error("handler parameter should be a instance of router object",L);const z=Object.entries(L.trie.root.children);L.trie.root.subMiddlewares.forEach((U,X)=>{if(!this.middlewares.has(J+X))this.middlewares.set(J+X,[]);U===null||U===void 0||U.forEach((Y)=>{var Z,W;if(!((Z=this.middlewares.get(J+X))===null||Z===void 0?void 0:Z.includes(Y)))(W=this.middlewares.get(J+X))===null||W===void 0||W.push(Y)})});for(let[U,X]of z){const Y=J+(X===null||X===void 0?void 0:X.path),Z=X.handler[0],W=X.method[0];this.trie.insert(Y,{handler:Z,method:W})}L.trie=new y.default}use(J,L){var z,U;if(typeof J==="function"){if(!this.globalMiddlewares.includes(J))return this.globalMiddlewares.push(J)}const X=J;if(!this.middlewares.has(X))this.middlewares.set(X,[]);if(!((z=this.middlewares.get(X))===null||z===void 0?void 0:z.includes(L)))(U=this.middlewares.get(X))===null||U===void 0||U.push(L)}get(J,...L){return N(this,K,"m",A).call(this,"GET",J,L),this}post(J,...L){return N(this,K,"m",A).call(this,"POST",J,L),this}put(J,...L){return N(this,K,"m",A).call(this,"PUT",J,L),this}patch(J,...L){return N(this,K,"m",A).call(this,"PATCH",J,L),this}delete(J,...L){return N(this,K,"m",A).call(this,"DELETE",J,L),this}}K=new WeakSet,A=function J(L,z,U){if(typeof z!=="string")throw new Error("Path must be a string type");if(typeof L!=="string")throw new Error("method must be a string type");const X=U.slice(0,-1),Y=U[U.length-1];if(!this.middlewares.has(z))this.middlewares.set(z,[]);X.forEach((Z)=>{var W,G;if(z==="/"){if(!this.globalMiddlewares.includes(Z))this.globalMiddlewares.push(Z)}else if(!((W=this.middlewares.get(z))===null||W===void 0?void 0:W.includes(Z)))(G=this.middlewares.get(z))===null||G===void 0||G.push(Z)}),this.trie.insert(z,{handler:Y,method:L})};M.default=x});export default o();
|
|
1
|
+
class Q{children;isEndOfWord;handler;isDynamic;pattern;path;method;subMiddlewares;constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class V{root;constructor(){this.root=new Q}insert(F,G){let z=this.root;const U=F.split("/").filter(Boolean);if(F==="/"){z.isEndOfWord=!0,z.handler.push(G.handler),z.path=F,z.method.push(G.method);return}for(let J of U){let L=!1,Y=J;if(J.startsWith(":"))L=!0,Y=":";if(!z.children[Y])z.children[Y]=new Q;z=z.children[Y],z.isDynamic=L,z.pattern=J}z.isEndOfWord=!0,z.method.push(G.method),z.handler.push(G.handler),z.path=F}search(F,G){let z=this.root;const U=F.split("/").filter(Boolean);for(let L of U){let Y=L;if(!z.children[Y])if(z.children[":"])z=z.children[":"];else return null;else z=z.children[Y]}let J=z.method.indexOf(G);if(J!==-1)return{path:z.path,handler:z.handler[J],isDynamic:z.isDynamic,pattern:z.pattern,method:z.method[J]};return{path:z.path,handler:z.handler,isDynamic:z.isDynamic,pattern:z.pattern,method:z.method[J]}}}async function D(F){const G={};if(!F)return G;return F.split(";").forEach((U)=>{const[J,L]=U?.trim()?.split("=");if(J&&L)G[J.trim()]=L.split(" ")[0].trim()}),G}function v(F,G){const z={},U=F.split("/"),[J]=G.split("?"),L=J.split("/");if(U.length!==L.length)return null;return U.forEach((Y,$)=>{if(Y.startsWith(":")){const E=Y.slice(1);z[E]=L[$]}}),z}async function b(F){const G=F.headers.get("Content-Type")||"";if(!G)return{};try{if(G.startsWith("application/json"))return await F.json();if(G.startsWith("application/x-www-form-urlencoded")){const z=await F.text();return Object.fromEntries(new URLSearchParams(z))}if(G.startsWith("multipart/form-data")){const z=await F.formData();return T(z)}return{error:"Unknown request body type"}}catch(z){return{error:"Invalid request body format"}}}function T(F){const G={};for(let[z,U]of F.entries())G[z]=U;return G}function M(F,G){let z=new Headers,U={},J=!1,L=null,Y=null,$=null,E,A=200;return{req:F,url:G,next:()=>{},status(X){return A=X,this},async body(){if(!E)E=await b(F);if(E.error)return new Response(JSON.stringify({error:E.error}),{status:400});return E},setHeader(X,Z){return z.set(X,Z),this},set(X,Z){return U[X]=Z,this},get(X){return U[X]||null},setAuth(X){return J=X,this},getAuth(){return J},text(X,Z){return new Response(X,{status:Z??A,headers:z})},json(X,Z){return new Response(JSON.stringify(X),{status:Z??A,headers:z})},html(X,Z){return new Response(Bun.file(X),{status:Z??A,headers:z})},file(X,Z){return new Response(Bun.file(X),{status:Z??A,headers:z})},redirect(X,Z){return z.set("Location",X),new Response(null,{status:Z??302,headers:z})},getParams(X){if(!$)$=v(F?.routePattern,G?.pathname);return X?$[X]||null:$},getQuery(X){if(!L)L=Object.fromEntries(G.searchParams);return X?L[X]||null:L},async cookie(X,Z,_={}){let W=`${encodeURIComponent(X)}=${encodeURIComponent(Z)}`;if(_.maxAge)W+=`; Max-Age=${_.maxAge}`;if(_.expires)W+=`; Expires=${_.expires.toUTCString()}`;if(_.path)W+=`; Path=${_.path}`;if(_.domain)W+=`; Domain=${_.domain}`;if(_.secure)W+="; Secure";if(_.httpOnly)W+="; HttpOnly";if(_.sameSite)W+=`; SameSite=${_.sameSite}`;return z?.append("Set-Cookie",W),this},async getCookie(X){if(!Y){const Z=F.headers.get("cookie");if(Z)Y=await D(Z)}return X?Y[X]||null:Y}}}async function N(F,G){for(let z of F){const U=await z(G);if(U)return U}}var B={};async function K(F,G,z){const U=M(F,G);if(z.hasOnReqHook&&z.hooks.onRequest)await z.hooks.onRequest(U);if(z.hasMiddleware){const L=[...z.globalMiddlewares,...z.middlewares.get(G.pathname)||[]],Y=await N(L,U);if(Y)return Y}let J;if(B[G.pathname+F.method])J=B[G.pathname+F.method];else J=z.trie.search(G.pathname,F.method),B[G.pathname+F.method]=J;if(!J||!J.handler)return new Response(`Route not found for ${G.pathname}`,{status:404});if(J.method!==F.method)return new Response("Method not allowed",{status:405});if(J.isDynamic)F.routePattern=J.path;if(z.hasPreHandlerHook&&z.hooks.preHandler){const L=await z.hooks.preHandler(U);if(L)return L}try{const L=await J.handler(U);if(z.hasPostHandlerHook&&z.hooks.postHandler)await z.hooks.postHandler(U);if(z.hasOnSendHook&&z.hooks.onSend){const Y=await z.hooks.onSend(U,L);if(Y)return Y}return L??new Response("No response from handler",{status:204})}catch(L){return new Response("Internal Server Error",{status:500})}}class j{routes;globalMiddlewares;middlewares;trie;hasOnReqHook;hasMiddleware;hasPreHandlerHook;hasPostHandlerHook;hasOnSendHook;hooks;constructor(){this.routes=new Map,this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new V,this.hasMiddleware=!1,this.hasOnReqHook=!1,this.hasPreHandlerHook=!1,this.hasPostHandlerHook=!1,this.hasOnSendHook=!1,this.hooks={onRequest:null,preHandler:null,postHandler:null,onSend:null,onError:null,onClose:null}}addHooks(F,G){if(typeof F!=="string")throw new Error("hookName must be a string");if(typeof G!=="function")throw new Error("callback must be a instance of function");if(this.hooks.hasOwnProperty(F))this.hooks[F]=G;else throw new Error(`Unknown hook type: ${F}`)}compile(){if(this.globalMiddlewares.length>0)this.hasMiddleware=!0;for(let[F,G]of this.middlewares.entries())if(G.length>0){this.hasMiddleware=!0;break}if(this.hooks.onRequest)this.hasOnReqHook=!0;if(this.hooks.preHandler)this.hasPreHandlerHook=!0;if(this.hooks.postHandler)this.hasPostHandlerHook=!0;if(this.hooks.onSend)this.hasOnSendHook=!0}listen(F,G,{sslCert:z=null,sslKey:U=null}={}){if(typeof Bun==="undefined")throw new Error(".listen() is designed to run on Bun only...");if(typeof F!=="number")throw new Error("Port must be a numeric value");this.compile();const J=this,L={port:F,fetch:async($)=>{const E=new URL($.url);try{return await K($,E,this)}catch(A){return new Response("Internal Server Error",{status:500})}},onClose(){console.log("Server is shutting down...")}};if(z&&U)L.certFile=z,L.keyFile=U;const Y=Bun.serve(L);if(typeof G==="function")return G();if(z&&U)console.log(`HTTPS server is running on https://localhost:${F}`);else console.log(`HTTP server is running on http://localhost:${F}`);return Y}register(F,G){if(typeof F!=="string")throw new Error("path must be a string");if(typeof G!=="object")throw new Error("handler parameter should be a instance of router object",G);const z=Object.entries(G.trie.root.children);G.trie.root.subMiddlewares.forEach((U,J)=>{if(!this.middlewares.has(F+J))this.middlewares.set(F+J,[]);U?.forEach((L)=>{if(!this.middlewares.get(F+J)?.includes(L))this.middlewares.get(F+J)?.push(L)})});for(let[U,J]of z){const L=F+J?.path,Y=J.handler[0],$=J.method[0];this.trie.insert(L,{handler:Y,method:$})}G.trie=new V}#z(F,G,z){if(typeof G!=="string")throw new Error("Path must be a string type");if(typeof F!=="string")throw new Error("method must be a string type");const U=z.slice(0,-1),J=z[z.length-1];if(!this.middlewares.has(G))this.middlewares.set(G,[]);U.forEach((L)=>{if(G==="/"){if(!this.globalMiddlewares.includes(L))this.globalMiddlewares.push(L)}else if(!this.middlewares.get(G)?.includes(L))this.middlewares.get(G)?.push(L)}),this.trie.insert(G,{handler:J,method:F})}use(F,G){if(typeof F==="function"){if(!this.globalMiddlewares.includes(F))return this.globalMiddlewares.push(F)}const z=F;if(!this.middlewares.has(z))this.middlewares.set(z,[]);if(!this.middlewares.get(z)?.includes(G))this.middlewares.get(z)?.push(G)}get(F,...G){return this.#z("GET",F,G),this}post(F,...G){return this.#z("POST",F,G),this}put(F,...G){return this.#z("PUT",F,G),this}patch(F,...G){return this.#z("PATCH",F,G),this}delete(F,...G){return this.#z("DELETE",F,G),this}}var g=j;export{g as default};
|
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import diesel from "./main";
|
|
2
|
+
import type { handlerFunction } from "./types";
|
|
3
|
+
declare class Router extends diesel {
|
|
4
|
+
#private;
|
|
5
|
+
constructor();
|
|
6
|
+
get(path: string, ...handlers: handlerFunction[]): this;
|
|
7
|
+
post(path: string, ...handlers: handlerFunction[]): this;
|
|
8
|
+
put(path: string, ...handlers: handlerFunction[]): this;
|
|
9
|
+
patch(path: string, ...handlers: handlerFunction[]): this;
|
|
10
|
+
delete(path: string, ...handlers: handlerFunction[]): this;
|
|
11
|
+
}
|
|
12
|
+
export default Router;
|
package/dist/router.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var C=(J,L)=>()=>(L||J((L={exports:{}}).exports,L),L.exports);var y=C((R)=>{Object.defineProperty(R,"__esModule",{value:!0});class S{constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class w{constructor(){this.root=new S}insert(J,L){let z=this.root;const U=J.split("/").filter(Boolean);if(J==="/"){z.isEndOfWord=!0,z.handler.push(L.handler),z.path=J,z.method.push(L.method);return}for(let Y of U){let X=!1,Z=Y;if(Y.startsWith(":"))X=!0,Z=":";if(!z.children[Z])z.children[Z]=new S;z=z.children[Z],z.isDynamic=X,z.pattern=Y}z.isEndOfWord=!0,z.method.push(L.method),z.handler.push(L.handler),z.path=J}search(J,L){let z=this.root;const U=J.split("/").filter(Boolean);for(let X of U){let Z=X;if(!z.children[Z])if(z.children[":"])z=z.children[":"];else return null;else z=z.children[Z]}let Y=z.method.indexOf(L);if(Y!==-1)return{path:z.path,handler:z.handler[Y],isDynamic:z.isDynamic,pattern:z.pattern,method:z.method[Y]};return{path:z.path,handler:z.handler,isDynamic:z.isDynamic,pattern:z.pattern,method:z.method[Y]}}}R.default=w});var P=C((b)=>{function p(J,L){let z={},U={},Y=!1,X=null,Z=null,W=null,Q,V=200;return{req:J,url:L,next:()=>{},status($){return V=$,this},body(){return O(this,void 0,void 0,function*(){if(!Q)Q=yield l(J);if(Q.error)return new Response(JSON.stringify({error:Q.error}),{status:400,headers:{"Content-Type":"application/json"}});return Q})},setHeader($,E){return z[$]=E,this},set($,E){return U[$]=E,this},get($){return U[$]||null},setAuth($){return Y=$,this},getAuth(){return Y},text($,E){if(E)V=E;return new Response($,{status:V,headers:z})},json($,E){if(E)V=E;return new Response(JSON.stringify($),{status:V,headers:Object.assign({"Content-Type":"application/json"},z)})},html($,E){if(E)V=E;return new Response(Bun.file($),{status:V,headers:Object.assign({},z)})},file($,E){if(E)V=E;return new Response(Bun.file($),{status:V,headers:Object.assign({},z)})},redirect($,E){if(E)V=E;return new Response(null,{status:V,headers:Object.assign({Location:$},z)})},getParams($){if(!W)W=n(J===null||J===void 0?void 0:J.routePattern,L===null||L===void 0?void 0:L.pathname);return $?W[$]||null:W},getQuery($){if(!X)X=Object.fromEntries(L.searchParams);return $?X[$]||null:X},cookie($,E){return O(this,arguments,void 0,function*(c,h,B={}){let K=`${encodeURIComponent(c)}=${encodeURIComponent(h)}`;if(B.maxAge)K+=`; Max-Age=${B.maxAge}`;if(B.expires)K+=`; Expires=${B.expires.toUTCString()}`;if(B.path)K+=`; Path=${B.path}`;if(B.domain)K+=`; Domain=${B.domain}`;if(B.secure)K+="; Secure";if(B.httpOnly)K+="; HttpOnly";if(B.sameSite)K+=`; SameSite=${B.sameSite}`;if(z["Set-Cookie"]){const q=Array.isArray(z["Set-Cookie"])?z["Set-Cookie"]:[z["Set-Cookie"]];q.push(K),z["Set-Cookie"]=q}else z["Set-Cookie"]=K;return this})},getCookie($){return O(this,void 0,void 0,function*(){if(!Z){const E=J.headers.get("cookie");if(E)Z=yield i(E)}return $?Z[$]||null:Z})}}}function i(J){return O(this,void 0,void 0,function*(){const L={};if(!J)return L;return J.split(";").forEach((U)=>{var Y;const[X,Z]=(Y=U===null||U===void 0?void 0:U.trim())===null||Y===void 0?void 0:Y.split("=");if(X&&Z)L[X.trim()]=Z.split(" ")[0].trim()}),L})}function n(J,L){const z={},U=J.split("/"),[Y]=L.split("?"),X=Y.split("/");if(U.length!==X.length)return null;return U.forEach((Z,W)=>{if(Z.startsWith(":")){const Q=Z.slice(1);z[Q]=X[W]}}),z}function l(J){return O(this,void 0,void 0,function*(){const L=J.headers.get("Content-Type")||"";if(!L)return{};try{if(L.startsWith("application/json"))return yield J.json();if(L.startsWith("application/x-www-form-urlencoded")){const z=yield J.text();return Object.fromEntries(new URLSearchParams(z))}if(L.startsWith("multipart/form-data")){const z=yield J.formData();return d(z)}return{error:"Unknown request body type"}}catch(z){return{error:"Invalid request body format"}}})}function d(J){const L={};for(let[z,U]of J.entries())L[z]=U;return L}var O=b&&b.__awaiter||function(J,L,z,U){function Y(X){return X instanceof z?X:new z(function(Z){Z(X)})}return new(z||(z=Promise))(function(X,Z){function W($){try{V(U.next($))}catch(E){Z(E)}}function Q($){try{V(U.throw($))}catch(E){Z(E)}}function V($){$.done?X($.value):Y($.value).then(W,Q)}V((U=U.apply(J,L||[])).next())})};Object.defineProperty(b,"__esModule",{value:!0});b.default=p});var g=C((G)=>{function a(J,L,z){return x(this,void 0,void 0,function*(){const U=s.default(J,L);if(z.hasOnReqHook)yield z.hooks.onRequest(U);if(z.hasMiddleware){const X=[...z.globalMiddlewares,...z.middlewares.get(L.pathname)||[]],Z=yield r(X,U);if(Z)return Z}let Y;if(H[L.pathname+J.method])Y=H[L.pathname+J.method];else Y=z.trie.search(L.pathname,J.method),H[L.pathname+J.method]=Y;if(!Y||!Y.handler)return new Response(`Route not found for ${L.pathname}`,{status:404});if(Y.method!==J.method)return new Response("Method not allowed",{status:405});if(Y.isDynamic)J.routePattern=Y.path;if(z.hasPreHandlerHook){const X=yield z.hooks.preHandler(U);if(X)return X}try{const X=yield Y.handler(U);if(z.hasPostHandlerHook)yield z.hooks.postHandler(U);if(z.hasOnSendHook){const Z=yield z.hooks.onSend(X,U);if(Z)return Z}return X!==null&&X!==void 0?X:new Response("No response from handler",{status:204})}catch(X){return new Response("Internal Server Error",{status:500})}})}function r(J,L){return x(this,void 0,void 0,function*(){for(let z of J){const U=yield z(L);if(U)return U}})}var x=G&&G.__awaiter||function(J,L,z,U){function Y(X){return X instanceof z?X:new z(function(Z){Z(X)})}return new(z||(z=Promise))(function(X,Z){function W($){try{V(U.next($))}catch(E){Z(E)}}function Q($){try{V(U.throw($))}catch(E){Z(E)}}function V($){$.done?X($.value):Y($.value).then(W,Q)}V((U=U.apply(J,L||[])).next())})},o=G&&G.__importDefault||function(J){return J&&J.__esModule?J:{default:J}};Object.defineProperty(G,"__esModule",{value:!0});G.default=a;var s=o(P()),H={}});var m=C((A)=>{var t=A&&A.__awaiter||function(J,L,z,U){function Y(X){return X instanceof z?X:new z(function(Z){Z(X)})}return new(z||(z=Promise))(function(X,Z){function W($){try{V(U.next($))}catch(E){Z(E)}}function Q($){try{V(U.throw($))}catch(E){Z(E)}}function V($){$.done?X($.value):Y($.value).then(W,Q)}V((U=U.apply(J,L||[])).next())})},j=A&&A.__classPrivateFieldGet||function(J,L,z,U){if(z==="a"&&!U)throw new TypeError("Private accessor was defined without a getter");if(typeof L==="function"?J!==L||!U:!L.has(J))throw new TypeError("Cannot read private member from an object whose class did not declare it");return z==="m"?U:z==="a"?U.call(J):U?U.value:L.get(J)},v=A&&A.__importDefault||function(J){return J&&J.__esModule?J:{default:J}},F,I;Object.defineProperty(A,"__esModule",{value:!0});var f=v(y()),e=v(g());class k{constructor(){F.add(this),this.routes=new Map,this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new f.default,this.hasMiddleware=!1,this.hasOnReqHook=!1,this.hasPreHandlerHook=!1,this.hasPostHandlerHook=!1,this.hasOnSendHook=!1,this.hooks={onRequest:null,preHandler:null,postHandler:null,onSend:null,onError:null,onClose:null}}addHooks(J,L){if(typeof J!=="string")throw new Error("hookName must be a string");if(typeof L!=="function")throw new Error("callback must be a instance of function");if(this.hooks.hasOwnProperty(J))this.hooks[J]=L;else throw new Error(`Unknown hook type: ${J}`)}compile(){if(this.globalMiddlewares.length>0)this.hasMiddleware=!0;for(let[J,L]of this.middlewares.entries())if(L.length>0){this.hasMiddleware=!0;break}if(this.hooks.onRequest)this.hasOnReqHook=!0;if(this.hooks.preHandler)this.hasPreHandlerHook=!0;if(this.hooks.postHandler)this.hasPostHandlerHook=!0;if(this.hooks.onSend)this.hasOnSendHook=!0}listen(J,L,{sslCert:z=null,sslKey:U=null}={}){if(typeof Bun==="undefined")throw new Error(".listen() is designed to run on Bun only...");if(typeof J!=="number")throw new Error("Port must be a numeric value");this.compile();const Y={port:J,fetch:(Z)=>t(this,void 0,void 0,function*(){const W=new URL(Z.url);try{return yield e.default(Z,W,this)}catch(Q){return new Response("Internal Server Error",{status:500})}}),onClose(){console.log("Server is shutting down...")}};if(z&&U)Y.certFile=z,Y.keyFile=U;const X=Bun.serve(Y);if(typeof L==="function")return L();if(z&&U)console.log(`HTTPS server is running on https://localhost:${J}`);else console.log(`HTTP server is running on http://localhost:${J}`);return X}register(J,L){if(typeof J!=="string")throw new Error("path must be a string");if(typeof L!=="object")throw new Error("handler parameter should be a instance of router object",L);const z=Object.entries(L.trie.root.children);L.trie.root.subMiddlewares.forEach((U,Y)=>{if(!this.middlewares.has(J+Y))this.middlewares.set(J+Y,[]);U===null||U===void 0||U.forEach((X)=>{var Z,W;if(!((Z=this.middlewares.get(J+Y))===null||Z===void 0?void 0:Z.includes(X)))(W=this.middlewares.get(J+Y))===null||W===void 0||W.push(X)})});for(let[U,Y]of z){const X=J+(Y===null||Y===void 0?void 0:Y.path),Z=Y.handler[0],W=Y.method[0];this.trie.insert(X,{handler:Z,method:W})}L.trie=new f.default}use(J,L){var z,U;if(typeof J==="function"){if(!this.globalMiddlewares.includes(J))return this.globalMiddlewares.push(J)}const Y=J;if(!this.middlewares.has(Y))this.middlewares.set(Y,[]);if(!((z=this.middlewares.get(Y))===null||z===void 0?void 0:z.includes(L)))(U=this.middlewares.get(Y))===null||U===void 0||U.push(L)}get(J,...L){return j(this,F,"m",I).call(this,"GET",J,L),this}post(J,...L){return j(this,F,"m",I).call(this,"POST",J,L),this}put(J,...L){return j(this,F,"m",I).call(this,"PUT",J,L),this}patch(J,...L){return j(this,F,"m",I).call(this,"PATCH",J,L),this}delete(J,...L){return j(this,F,"m",I).call(this,"DELETE",J,L),this}}F=new WeakSet,I=function J(L,z,U){if(typeof z!=="string")throw new Error("Path must be a string type");if(typeof L!=="string")throw new Error("method must be a string type");const Y=U.slice(0,-1),X=U[U.length-1];if(!this.middlewares.has(z))this.middlewares.set(z,[]);Y.forEach((Z)=>{var W,Q;if(z==="/"){if(!this.globalMiddlewares.includes(Z))this.globalMiddlewares.push(Z)}else if(!((W=this.middlewares.get(z))===null||W===void 0?void 0:W.includes(Z)))(Q=this.middlewares.get(z))===null||Q===void 0||Q.push(Z)}),this.trie.insert(z,{handler:X,method:L})};A.default=k});var Lz=C((M)=>{var D=M&&M.__classPrivateFieldGet||function(J,L,z,U){if(z==="a"&&!U)throw new TypeError("Private accessor was defined without a getter");if(typeof L==="function"?J!==L||!U:!L.has(J))throw new TypeError("Cannot read private member from an object whose class did not declare it");return z==="m"?U:z==="a"?U.call(J):U?U.value:L.get(J)},zz=M&&M.__importDefault||function(J){return J&&J.__esModule?J:{default:J}},T,N;Object.defineProperty(M,"__esModule",{value:!0});var Jz=zz(m());class _ extends Jz.default{constructor(){super();T.add(this)}get(J,...L){return D(this,T,"m",N).call(this,"GET",J,L),this}post(J,...L){return D(this,T,"m",N).call(this,"POST",J,L),this}put(J,...L){return D(this,T,"m",N).call(this,"PUT",J,L),this}patch(J,...L){return D(this,T,"m",N).call(this,"PATCH",J,L),this}delete(J,...L){return D(this,T,"m",N).call(this,"DELETE",J,L),this}}T=new WeakSet,N=function J(L,z,U){if(!this.trie.root.subMiddlewares.has(z))this.trie.root.subMiddlewares.set(z,[]);const Y=U.slice(0,-1),X=this.trie.root.subMiddlewares.get(z);Y.forEach((W)=>{if(!(X===null||X===void 0?void 0:X.includes(W)))X===null||X===void 0||X.push(W)});const Z=U[U.length-1];this.trie.insert(z,{handler:Z,method:L})};M.default=_});export default Lz();
|
|
1
|
+
class Q{children;isEndOfWord;handler;isDynamic;pattern;path;method;subMiddlewares;constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class V{root;constructor(){this.root=new Q}insert(G,F){let z=this.root;const U=G.split("/").filter(Boolean);if(G==="/"){z.isEndOfWord=!0,z.handler.push(F.handler),z.path=G,z.method.push(F.method);return}for(let J of U){let L=!1,Y=J;if(J.startsWith(":"))L=!0,Y=":";if(!z.children[Y])z.children[Y]=new Q;z=z.children[Y],z.isDynamic=L,z.pattern=J}z.isEndOfWord=!0,z.method.push(F.method),z.handler.push(F.handler),z.path=G}search(G,F){let z=this.root;const U=G.split("/").filter(Boolean);for(let L of U){let Y=L;if(!z.children[Y])if(z.children[":"])z=z.children[":"];else return null;else z=z.children[Y]}let J=z.method.indexOf(F);if(J!==-1)return{path:z.path,handler:z.handler[J],isDynamic:z.isDynamic,pattern:z.pattern,method:z.method[J]};return{path:z.path,handler:z.handler,isDynamic:z.isDynamic,pattern:z.pattern,method:z.method[J]}}}async function T(G){const F={};if(!G)return F;return G.split(";").forEach((U)=>{const[J,L]=U?.trim()?.split("=");if(J&&L)F[J.trim()]=L.split(" ")[0].trim()}),F}function b(G,F){const z={},U=G.split("/"),[J]=F.split("?"),L=J.split("/");if(U.length!==L.length)return null;return U.forEach((Y,$)=>{if(Y.startsWith(":")){const E=Y.slice(1);z[E]=L[$]}}),z}async function N(G){const F=G.headers.get("Content-Type")||"";if(!F)return{};try{if(F.startsWith("application/json"))return await G.json();if(F.startsWith("application/x-www-form-urlencoded")){const z=await G.text();return Object.fromEntries(new URLSearchParams(z))}if(F.startsWith("multipart/form-data")){const z=await G.formData();return I(z)}return{error:"Unknown request body type"}}catch(z){return{error:"Invalid request body format"}}}function I(G){const F={};for(let[z,U]of G.entries())F[z]=U;return F}function B(G,F){let z=new Headers,U={},J=!1,L=null,Y=null,$=null,E,A=200;return{req:G,url:F,next:()=>{},status(X){return A=X,this},async body(){if(!E)E=await N(G);if(E.error)return new Response(JSON.stringify({error:E.error}),{status:400});return E},setHeader(X,Z){return z.set(X,Z),this},set(X,Z){return U[X]=Z,this},get(X){return U[X]||null},setAuth(X){return J=X,this},getAuth(){return J},text(X,Z){return new Response(X,{status:Z??A,headers:z})},json(X,Z){return new Response(JSON.stringify(X),{status:Z??A,headers:z})},html(X,Z){return new Response(Bun.file(X),{status:Z??A,headers:z})},file(X,Z){return new Response(Bun.file(X),{status:Z??A,headers:z})},redirect(X,Z){return z.set("Location",X),new Response(null,{status:Z??302,headers:z})},getParams(X){if(!$)$=b(G?.routePattern,F?.pathname);return X?$[X]||null:$},getQuery(X){if(!L)L=Object.fromEntries(F.searchParams);return X?L[X]||null:L},async cookie(X,Z,_={}){let W=`${encodeURIComponent(X)}=${encodeURIComponent(Z)}`;if(_.maxAge)W+=`; Max-Age=${_.maxAge}`;if(_.expires)W+=`; Expires=${_.expires.toUTCString()}`;if(_.path)W+=`; Path=${_.path}`;if(_.domain)W+=`; Domain=${_.domain}`;if(_.secure)W+="; Secure";if(_.httpOnly)W+="; HttpOnly";if(_.sameSite)W+=`; SameSite=${_.sameSite}`;return z?.append("Set-Cookie",W),this},async getCookie(X){if(!Y){const Z=G.headers.get("cookie");if(Z)Y=await T(Z)}return X?Y[X]||null:Y}}}async function C(G,F){for(let z of G){const U=await z(F);if(U)return U}}var K={};async function j(G,F,z){const U=B(G,F);if(z.hasOnReqHook&&z.hooks.onRequest)await z.hooks.onRequest(U);if(z.hasMiddleware){const L=[...z.globalMiddlewares,...z.middlewares.get(F.pathname)||[]],Y=await C(L,U);if(Y)return Y}let J;if(K[F.pathname+G.method])J=K[F.pathname+G.method];else J=z.trie.search(F.pathname,G.method),K[F.pathname+G.method]=J;if(!J||!J.handler)return new Response(`Route not found for ${F.pathname}`,{status:404});if(J.method!==G.method)return new Response("Method not allowed",{status:405});if(J.isDynamic)G.routePattern=J.path;if(z.hasPreHandlerHook&&z.hooks.preHandler){const L=await z.hooks.preHandler(U);if(L)return L}try{const L=await J.handler(U);if(z.hasPostHandlerHook&&z.hooks.postHandler)await z.hooks.postHandler(U);if(z.hasOnSendHook&&z.hooks.onSend){const Y=await z.hooks.onSend(U,L);if(Y)return Y}return L??new Response("No response from handler",{status:204})}catch(L){return new Response("Internal Server Error",{status:500})}}class D{routes;globalMiddlewares;middlewares;trie;hasOnReqHook;hasMiddleware;hasPreHandlerHook;hasPostHandlerHook;hasOnSendHook;hooks;constructor(){this.routes=new Map,this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new V,this.hasMiddleware=!1,this.hasOnReqHook=!1,this.hasPreHandlerHook=!1,this.hasPostHandlerHook=!1,this.hasOnSendHook=!1,this.hooks={onRequest:null,preHandler:null,postHandler:null,onSend:null,onError:null,onClose:null}}addHooks(G,F){if(typeof G!=="string")throw new Error("hookName must be a string");if(typeof F!=="function")throw new Error("callback must be a instance of function");if(this.hooks.hasOwnProperty(G))this.hooks[G]=F;else throw new Error(`Unknown hook type: ${G}`)}compile(){if(this.globalMiddlewares.length>0)this.hasMiddleware=!0;for(let[G,F]of this.middlewares.entries())if(F.length>0){this.hasMiddleware=!0;break}if(this.hooks.onRequest)this.hasOnReqHook=!0;if(this.hooks.preHandler)this.hasPreHandlerHook=!0;if(this.hooks.postHandler)this.hasPostHandlerHook=!0;if(this.hooks.onSend)this.hasOnSendHook=!0}listen(G,F,{sslCert:z=null,sslKey:U=null}={}){if(typeof Bun==="undefined")throw new Error(".listen() is designed to run on Bun only...");if(typeof G!=="number")throw new Error("Port must be a numeric value");this.compile();const J=this,L={port:G,fetch:async($)=>{const E=new URL($.url);try{return await j($,E,this)}catch(A){return new Response("Internal Server Error",{status:500})}},onClose(){console.log("Server is shutting down...")}};if(z&&U)L.certFile=z,L.keyFile=U;const Y=Bun.serve(L);if(typeof F==="function")return F();if(z&&U)console.log(`HTTPS server is running on https://localhost:${G}`);else console.log(`HTTP server is running on http://localhost:${G}`);return Y}register(G,F){if(typeof G!=="string")throw new Error("path must be a string");if(typeof F!=="object")throw new Error("handler parameter should be a instance of router object",F);const z=Object.entries(F.trie.root.children);F.trie.root.subMiddlewares.forEach((U,J)=>{if(!this.middlewares.has(G+J))this.middlewares.set(G+J,[]);U?.forEach((L)=>{if(!this.middlewares.get(G+J)?.includes(L))this.middlewares.get(G+J)?.push(L)})});for(let[U,J]of z){const L=G+J?.path,Y=J.handler[0],$=J.method[0];this.trie.insert(L,{handler:Y,method:$})}F.trie=new V}#z(G,F,z){if(typeof F!=="string")throw new Error("Path must be a string type");if(typeof G!=="string")throw new Error("method must be a string type");const U=z.slice(0,-1),J=z[z.length-1];if(!this.middlewares.has(F))this.middlewares.set(F,[]);U.forEach((L)=>{if(F==="/"){if(!this.globalMiddlewares.includes(L))this.globalMiddlewares.push(L)}else if(!this.middlewares.get(F)?.includes(L))this.middlewares.get(F)?.push(L)}),this.trie.insert(F,{handler:J,method:G})}use(G,F){if(typeof G==="function"){if(!this.globalMiddlewares.includes(G))return this.globalMiddlewares.push(G)}const z=G;if(!this.middlewares.has(z))this.middlewares.set(z,[]);if(!this.middlewares.get(z)?.includes(F))this.middlewares.get(z)?.push(F)}get(G,...F){return this.#z("GET",G,F),this}post(G,...F){return this.#z("POST",G,F),this}put(G,...F){return this.#z("PUT",G,F),this}patch(G,...F){return this.#z("PATCH",G,F),this}delete(G,...F){return this.#z("DELETE",G,F),this}}var M=D;class v extends M{constructor(){super()}#z(G,F,z){if(!this.trie.root.subMiddlewares.has(F))this.trie.root.subMiddlewares.set(F,[]);const U=z.slice(0,-1),J=this.trie.root.subMiddlewares.get(F);U.forEach((Y)=>{if(!J?.includes(Y))J?.push(Y)});const L=z[z.length-1];this.trie.insert(F,{handler:L,method:G})}get(G,...F){return this.#z("GET",G,F),this}post(G,...F){return this.#z("POST",G,F),this}put(G,...F){return this.#z("PUT",G,F),this}patch(G,...F){return this.#z("PATCH",G,F),this}delete(G,...F){return this.#z("DELETE",G,F),this}}var f=v;export{f as default};
|
package/dist/trie.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { handlerFunction, HttpMethod, RouteT } from "./types";
|
|
2
|
+
declare class TrieNode {
|
|
3
|
+
children: Record<string, TrieNode>;
|
|
4
|
+
isEndOfWord: boolean;
|
|
5
|
+
handler: handlerFunction[];
|
|
6
|
+
isDynamic: boolean;
|
|
7
|
+
pattern: string;
|
|
8
|
+
path: string;
|
|
9
|
+
method: string[];
|
|
10
|
+
subMiddlewares: Map<string, handlerFunction[]>;
|
|
11
|
+
constructor();
|
|
12
|
+
}
|
|
13
|
+
export default class Trie {
|
|
14
|
+
root: TrieNode;
|
|
15
|
+
constructor();
|
|
16
|
+
insert(path: string, route: RouteT): void;
|
|
17
|
+
search(path: string, method: HttpMethod): {
|
|
18
|
+
path: string;
|
|
19
|
+
handler: handlerFunction;
|
|
20
|
+
isDynamic: boolean;
|
|
21
|
+
pattern: string;
|
|
22
|
+
method: string;
|
|
23
|
+
} | {
|
|
24
|
+
path: string;
|
|
25
|
+
handler: handlerFunction[];
|
|
26
|
+
isDynamic: boolean;
|
|
27
|
+
pattern: string;
|
|
28
|
+
method: string;
|
|
29
|
+
} | null;
|
|
30
|
+
}
|
|
31
|
+
export {};
|
package/dist/trie.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
class C{children;isEndOfWord;handler;isDynamic;pattern;path;method;subMiddlewares;constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class E{root;constructor(){this.root=new C}insert(w,z){let b=this.root;const B=w.split("/").filter(Boolean);if(w==="/"){b.isEndOfWord=!0,b.handler.push(z.handler),b.path=w,b.method.push(z.method);return}for(let j of B){let A=!1,q=j;if(j.startsWith(":"))A=!0,q=":";if(!b.children[q])b.children[q]=new C;b=b.children[q],b.isDynamic=A,b.pattern=j}b.isEndOfWord=!0,b.method.push(z.method),b.handler.push(z.handler),b.path=w}search(w,z){let b=this.root;const B=w.split("/").filter(Boolean);for(let A of B){let q=A;if(!b.children[q])if(b.children[":"])b=b.children[":"];else return null;else b=b.children[q]}let j=b.method.indexOf(z);if(j!==-1)return{path:b.path,handler:b.handler[j],isDynamic:b.isDynamic,pattern:b.pattern,method:b.method[j]};return{path:b.path,handler:b.handler,isDynamic:b.isDynamic,pattern:b.pattern,method:b.method[j]}}}export{E as default};
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
export type listenCalllBackType = () => void;
|
|
2
|
+
export type handlerFunction = (ctx: ContextType) => Promise<Response | null | void>;
|
|
3
|
+
export type HookFunction = (ctx: ContextType, result?: Response | null | void) => Promise<Response | null | void>;
|
|
4
|
+
export type onSendHookFunc = (result?: Response | null | void, ctx?: ContextType) => Promise<Response | null | void>;
|
|
5
|
+
export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD";
|
|
6
|
+
export declare enum HookType {
|
|
7
|
+
onRequest = "onRequest",
|
|
8
|
+
preHandler = "preHandler",
|
|
9
|
+
postHandler = "postHandler",
|
|
10
|
+
onSend = "onSend",
|
|
11
|
+
onError = "onError",
|
|
12
|
+
onClose = "onClose"
|
|
13
|
+
}
|
|
14
|
+
export interface Hooks {
|
|
15
|
+
onRequest: HookFunction | null;
|
|
16
|
+
preHandler: HookFunction | null;
|
|
17
|
+
postHandler: HookFunction | null;
|
|
18
|
+
onSend: HookFunction | null;
|
|
19
|
+
onError: HookFunction | null;
|
|
20
|
+
onClose: HookFunction | null;
|
|
21
|
+
}
|
|
22
|
+
export interface ContextType {
|
|
23
|
+
req: Request;
|
|
24
|
+
url: URL;
|
|
25
|
+
next: () => void;
|
|
26
|
+
status: (status: number) => this;
|
|
27
|
+
body: () => Promise<any>;
|
|
28
|
+
setHeader: (key: string, value: any) => this;
|
|
29
|
+
set: (key: string, value: any) => this;
|
|
30
|
+
get: (key: string) => any;
|
|
31
|
+
setAuth: (authStatus: boolean) => this;
|
|
32
|
+
getAuth: () => boolean;
|
|
33
|
+
json: (data: Object, status?: number) => Response;
|
|
34
|
+
text: (data: string, status?: number) => Response;
|
|
35
|
+
html: (filePath: string, status?: number) => Response;
|
|
36
|
+
file: (filePath: string, status?: number) => Response;
|
|
37
|
+
redirect: (path: string, status?: number) => Response;
|
|
38
|
+
getParams: (props?: any) => any;
|
|
39
|
+
getQuery: (props?: any) => any;
|
|
40
|
+
cookie: (name: string, value: string, options?: CookieOptions) => Promise<this>;
|
|
41
|
+
getCookie: (cookieName?: string) => Promise<any>;
|
|
42
|
+
}
|
|
43
|
+
export interface CookieOptions {
|
|
44
|
+
maxAge?: number;
|
|
45
|
+
expires?: Date;
|
|
46
|
+
path?: string;
|
|
47
|
+
domain?: string;
|
|
48
|
+
secure?: boolean;
|
|
49
|
+
httpOnly?: boolean;
|
|
50
|
+
sameSite?: "Strict" | "Lax" | "None";
|
|
51
|
+
}
|
|
52
|
+
export interface RouteNodeType {
|
|
53
|
+
path: string;
|
|
54
|
+
handler: Function[];
|
|
55
|
+
method: string[];
|
|
56
|
+
}
|
|
57
|
+
export interface RouteHandlerT {
|
|
58
|
+
method: string;
|
|
59
|
+
handler: (ctx: ContextType) => Promise<Response | null | void>;
|
|
60
|
+
isDynamic?: boolean;
|
|
61
|
+
path?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface DieselT {
|
|
64
|
+
hasOnReqHook: boolean;
|
|
65
|
+
hasMiddleware: boolean;
|
|
66
|
+
hasPreHandlerHook: boolean;
|
|
67
|
+
hasPostHandlerHook: boolean;
|
|
68
|
+
hasOnSendHook: boolean;
|
|
69
|
+
hooks: {
|
|
70
|
+
onRequest: ((ctx: ContextType) => void) | null;
|
|
71
|
+
preHandler: ((ctx: ContextType) => Promise<Response | void | null>) | null;
|
|
72
|
+
postHandler: ((ctx: ContextType) => Promise<Response | void | null>) | null;
|
|
73
|
+
onSend: ((ctx?: ContextType, result?: Response | null | void) => Promise<Response | void | null>) | null;
|
|
74
|
+
};
|
|
75
|
+
globalMiddlewares: Array<(ctx: ContextType) => Promise<Response | null | void>>;
|
|
76
|
+
middlewares: Map<string, Array<(ctx: ContextType) => Promise<Response | null | void>>>;
|
|
77
|
+
trie: {
|
|
78
|
+
search: (pathname: string, method: string) => RouteHandlerT | undefined;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
export interface RouteCache {
|
|
82
|
+
[key: string]: RouteHandlerT | undefined;
|
|
83
|
+
}
|
|
84
|
+
declare global {
|
|
85
|
+
interface Request {
|
|
86
|
+
routePattern?: string;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export interface ParseBodyResult {
|
|
90
|
+
error?: string;
|
|
91
|
+
data?: any;
|
|
92
|
+
}
|
|
93
|
+
export interface RouteT {
|
|
94
|
+
method: string;
|
|
95
|
+
handler: handlerFunction;
|
|
96
|
+
}
|
package/example/tester.js
CHANGED
|
@@ -36,7 +36,7 @@ app.get("/r", (xl) => {
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
app.get("/", async (xl) => {
|
|
39
|
-
return
|
|
39
|
+
return xl.status(200).text("hello d")
|
|
40
40
|
})
|
|
41
41
|
|
|
42
42
|
app.post("/", async (xl) => {
|
|
@@ -63,7 +63,7 @@ app.get("/c", async(xl) => {
|
|
|
63
63
|
await xl.cookie("refreshToken", refreshToken, options)
|
|
64
64
|
// xl.cookie("refreshToken", refreshToken, options);
|
|
65
65
|
await xl.getCookie()
|
|
66
|
-
return xl.
|
|
66
|
+
return xl.json({msg:"setting cookies"})
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
// For "/test", middlewares h, s will run before the handler
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "diesel-core",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"main": "dist/
|
|
3
|
+
"version": "0.0.11",
|
|
4
|
+
"main": "dist/main.js",
|
|
5
|
+
"types": "dist/main.d.ts",
|
|
5
6
|
"scripts": {
|
|
6
|
-
"
|
|
7
|
+
"build": "bun run build.js"
|
|
7
8
|
},
|
|
8
9
|
"keywords": [],
|
|
9
10
|
"author": "",
|
package/src/ctx.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import type { ContextType, CookieOptions, ParseBodyResult } from "./types";
|
|
2
2
|
|
|
3
3
|
export default function createCtx(req: Request, url: URL): ContextType {
|
|
4
|
-
let headers
|
|
4
|
+
let headers: Headers = new Headers()
|
|
5
5
|
let settedValue: Record<string, string> = {};
|
|
6
|
-
let isAuthenticated = false;
|
|
6
|
+
let isAuthenticated: boolean = false;
|
|
7
7
|
let parsedQuery: any = null;
|
|
8
8
|
let parsedCookie: any = null
|
|
9
9
|
let parsedParams: any = null;
|
|
10
10
|
let parsedBody: ParseBodyResult | null;
|
|
11
|
-
let responseStatus = 200;
|
|
11
|
+
let responseStatus: number = 200;
|
|
12
12
|
|
|
13
13
|
return {
|
|
14
14
|
req,
|
|
@@ -16,7 +16,7 @@ export default function createCtx(req: Request, url: URL): ContextType {
|
|
|
16
16
|
next: () => { },
|
|
17
17
|
|
|
18
18
|
// Set response status for chaining
|
|
19
|
-
status(status: number) {
|
|
19
|
+
status(status: number): ContextType {
|
|
20
20
|
responseStatus = status;
|
|
21
21
|
return this;
|
|
22
22
|
},
|
|
@@ -33,26 +33,26 @@ export default function createCtx(req: Request, url: URL): ContextType {
|
|
|
33
33
|
return parsedBody;
|
|
34
34
|
},
|
|
35
35
|
|
|
36
|
-
setHeader(key: string, value: any) {
|
|
37
|
-
headers.set(key,value)
|
|
36
|
+
setHeader(key: string, value: any): ContextType {
|
|
37
|
+
headers.set(key, value)
|
|
38
38
|
return this;
|
|
39
39
|
},
|
|
40
40
|
|
|
41
|
-
set(key: string, value: any) {
|
|
41
|
+
set(key: string, value: any): ContextType {
|
|
42
42
|
settedValue[key] = value;
|
|
43
43
|
return this;
|
|
44
44
|
},
|
|
45
45
|
|
|
46
|
-
get(key: string) {
|
|
46
|
+
get(key: string): any | null {
|
|
47
47
|
return settedValue[key] || null;
|
|
48
48
|
},
|
|
49
49
|
|
|
50
|
-
setAuth(authStatus: boolean) {
|
|
50
|
+
setAuth(authStatus: boolean): ContextType {
|
|
51
51
|
isAuthenticated = authStatus;
|
|
52
52
|
return this;
|
|
53
53
|
},
|
|
54
54
|
|
|
55
|
-
getAuth() {
|
|
55
|
+
getAuth(): boolean {
|
|
56
56
|
return isAuthenticated;
|
|
57
57
|
},
|
|
58
58
|
|
|
@@ -64,28 +64,28 @@ export default function createCtx(req: Request, url: URL): ContextType {
|
|
|
64
64
|
});
|
|
65
65
|
},
|
|
66
66
|
|
|
67
|
-
json(data: any, status?: number) {
|
|
67
|
+
json(data: any, status?: number): Response {
|
|
68
68
|
return new Response(JSON.stringify(data), {
|
|
69
69
|
status: status ?? responseStatus,
|
|
70
70
|
headers
|
|
71
71
|
});
|
|
72
72
|
},
|
|
73
73
|
|
|
74
|
-
html(filepath: string, status?: number) {
|
|
74
|
+
html(filepath: string, status?: number): Response {
|
|
75
75
|
return new Response(Bun.file(filepath), {
|
|
76
76
|
status: status ?? responseStatus,
|
|
77
77
|
headers
|
|
78
78
|
});
|
|
79
79
|
},
|
|
80
80
|
|
|
81
|
-
file(filePath: string, status?: number) {
|
|
81
|
+
file(filePath: string, status?: number): Response {
|
|
82
82
|
return new Response(Bun.file(filePath), {
|
|
83
83
|
status: status ?? responseStatus,
|
|
84
84
|
headers
|
|
85
85
|
});
|
|
86
86
|
},
|
|
87
87
|
|
|
88
|
-
redirect(path: string, status?: number) {
|
|
88
|
+
redirect(path: string, status?: number): Response {
|
|
89
89
|
headers.set('Location', path);
|
|
90
90
|
return new Response(null, {
|
|
91
91
|
status: status ?? 302,
|
|
@@ -109,7 +109,7 @@ export default function createCtx(req: Request, url: URL): ContextType {
|
|
|
109
109
|
return props ? parsedQuery[props] || null : parsedQuery;
|
|
110
110
|
},
|
|
111
111
|
|
|
112
|
-
async cookie(name: string, value: string, options: CookieOptions = {}) {
|
|
112
|
+
async cookie(name: string, value: string, options: CookieOptions = {}): Promise<ContextType> {
|
|
113
113
|
let cookieString = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
|
|
114
114
|
|
|
115
115
|
// Add options to cookie string (e.g., expiration, path, HttpOnly, etc.)
|
|
@@ -120,11 +120,9 @@ export default function createCtx(req: Request, url: URL): ContextType {
|
|
|
120
120
|
if (options.secure) cookieString += `; Secure`;
|
|
121
121
|
if (options.httpOnly) cookieString += `; HttpOnly`;
|
|
122
122
|
if (options.sameSite) cookieString += `; SameSite=${options.sameSite}`;
|
|
123
|
-
|
|
124
|
-
headers?.append('Set-Cookie',cookieString)
|
|
125
|
-
// console.log(headers)
|
|
126
|
-
// console.log(Object.fromEntries(headers))
|
|
127
123
|
|
|
124
|
+
headers?.append('Set-Cookie', cookieString)
|
|
125
|
+
|
|
128
126
|
return this;
|
|
129
127
|
},
|
|
130
128
|
|
package/src/handleRequest.ts
CHANGED
|
@@ -8,7 +8,7 @@ export default async function handleRequest(req:Request, url:URL, diesel:DieselT
|
|
|
8
8
|
const ctx:ContextType = createCtx(req, url);
|
|
9
9
|
|
|
10
10
|
// OnReq hook 1
|
|
11
|
-
if (diesel.hasOnReqHook) {
|
|
11
|
+
if (diesel.hasOnReqHook && diesel.hooks.onRequest) {
|
|
12
12
|
await diesel.hooks.onRequest(ctx)
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -47,7 +47,7 @@ export default async function handleRequest(req:Request, url:URL, diesel:DieselT
|
|
|
47
47
|
if (routeHandler.isDynamic) req.routePattern = routeHandler.path;
|
|
48
48
|
|
|
49
49
|
// Run preHandler hooks 2
|
|
50
|
-
if (diesel.hasPreHandlerHook) {
|
|
50
|
+
if (diesel.hasPreHandlerHook && diesel.hooks.preHandler) {
|
|
51
51
|
const Hookresult = await diesel.hooks.preHandler(ctx);
|
|
52
52
|
if(Hookresult) return Hookresult;
|
|
53
53
|
}
|
|
@@ -58,13 +58,13 @@ export default async function handleRequest(req:Request, url:URL, diesel:DieselT
|
|
|
58
58
|
const result = await routeHandler.handler(ctx) as Response | null | void ;
|
|
59
59
|
|
|
60
60
|
// 3. run the postHandler hooks
|
|
61
|
-
if (diesel.hasPostHandlerHook) {
|
|
62
|
-
await diesel.hooks.postHandler(ctx)
|
|
61
|
+
if (diesel.hasPostHandlerHook && diesel.hooks.postHandler) {
|
|
62
|
+
await diesel.hooks.postHandler(ctx)
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// 4. Run onSend hooks before sending the response
|
|
66
|
-
if (diesel.hasOnSendHook) {
|
|
67
|
-
const hookResponse = await diesel.hooks.onSend(result
|
|
66
|
+
if (diesel.hasOnSendHook && diesel.hooks.onSend) {
|
|
67
|
+
const hookResponse = await diesel.hooks.onSend(ctx,result);
|
|
68
68
|
if(hookResponse) return hookResponse
|
|
69
69
|
}
|
|
70
70
|
|
package/src/main.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import Trie from "./trie.js";
|
|
2
2
|
import handleRequest from "./handleRequest.js";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
HookType,
|
|
5
|
+
type handlerFunction,
|
|
6
|
+
type Hooks,
|
|
7
|
+
type HttpMethod,
|
|
8
|
+
type listenCalllBackType,
|
|
9
|
+
type RouteNodeType
|
|
10
|
+
} from "./types.js";
|
|
4
11
|
|
|
5
12
|
class Diesel {
|
|
6
13
|
routes : Map<String,any>;
|
|
@@ -78,6 +85,7 @@ class Diesel {
|
|
|
78
85
|
}
|
|
79
86
|
|
|
80
87
|
this.compile();
|
|
88
|
+
const dieselInstance = this as Diesel
|
|
81
89
|
const options:any = {
|
|
82
90
|
port,
|
|
83
91
|
fetch: async (req:Request) => {
|
package/src/types.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export type listenCalllBackType = () => void;
|
|
3
3
|
export type handlerFunction = (ctx:ContextType) => Promise<Response | null | void> ;
|
|
4
4
|
export type HookFunction = (ctx:ContextType ,result?: Response | null | void,) => Promise<Response | null | void>
|
|
5
|
-
|
|
5
|
+
export type onSendHookFunc = (result?: Response | null | void, ctx?:ContextType) => Promise<Response | null | void>
|
|
6
6
|
export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD";
|
|
7
7
|
|
|
8
8
|
export enum HookType {
|
|
@@ -77,13 +77,13 @@ export interface DieselT {
|
|
|
77
77
|
hasPostHandlerHook: boolean;
|
|
78
78
|
hasOnSendHook: boolean;
|
|
79
79
|
hooks:{
|
|
80
|
-
onRequest: (ctx:ContextType) =>
|
|
81
|
-
preHandler: (ctx:ContextType) => Promise<Response | void | null>
|
|
82
|
-
postHandler: (ctx:ContextType) => Promise< void >
|
|
83
|
-
onSend: (result
|
|
80
|
+
onRequest: ((ctx:ContextType) =>void) | null
|
|
81
|
+
preHandler:( (ctx:ContextType) => Promise<Response | void | null>) | null
|
|
82
|
+
postHandler: ((ctx: ContextType) => Promise<Response | void | null>) | null; // Updated to include Response | null
|
|
83
|
+
onSend: ((ctx?: ContextType, result?: Response | null | void) => Promise<Response | void | null>) | null;
|
|
84
84
|
};
|
|
85
85
|
globalMiddlewares: Array<(ctx:ContextType) => Promise<Response | null | void >>
|
|
86
|
-
middlewares: Map< string , Array<() => Promise<Response | null | void >>>
|
|
86
|
+
middlewares: Map< string , Array<(ctx:ContextType) => Promise<Response | null | void >>>
|
|
87
87
|
trie: {
|
|
88
88
|
search: (pathname: string, method: string) => RouteHandlerT | undefined;
|
|
89
89
|
};
|
package/test/README.md
ADDED
package/test/bun.lockb
ADDED
|
Binary file
|
package/test/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log("Hello via Bun!");
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Enable latest features
|
|
4
|
+
"lib": ["ESNext", "DOM"],
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
|
|
11
|
+
// Bundler mode
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"verbatimModuleSyntax": true,
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
|
|
17
|
+
// Best practices
|
|
18
|
+
"strict": true,
|
|
19
|
+
"skipLibCheck": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
|
21
|
+
|
|
22
|
+
// Some stricter flags (disabled by default)
|
|
23
|
+
"noUnusedLocals": false,
|
|
24
|
+
"noUnusedParameters": false,
|
|
25
|
+
"noPropertyAccessFromIndexSignature": false
|
|
26
|
+
}
|
|
27
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"target": "ES6", // Specify ECMAScript target version
|
|
4
4
|
"module": "commonjs", // Specify module code generation
|
|
5
|
-
"outDir": "./
|
|
6
|
-
"rootDir": "./src",
|
|
5
|
+
"outDir": "./dist", // Redirect output structure to the 'dist' directory
|
|
6
|
+
"rootDir": "./src",
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"emitDeclarationOnly": true, // Specify the root directory of input files
|
|
7
9
|
"strict": true, // Enable all strict type-checking options
|
|
8
10
|
"esModuleInterop": true, // Enables emit interoperability between CommonJS and ES Modules
|
|
9
11
|
"skipLibCheck": true, // Skip type checking of declaration files
|
package/dist/server.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
class B{constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class V{constructor(){this.root=new B}insert(F,G){let z=this.root;const L=F.split("/").filter(Boolean);if(F==="/"){z.isEndOfWord=!0,z.handler.push(G.handler),z.path=F,z.method.push(G.method);return}for(let J of L){let U=!1,Y=J;if(J.startsWith(":"))U=!0,Y=":";if(!z.children[Y])z.children[Y]=new B;z=z.children[Y],z.isDynamic=U,z.pattern=J}z.isEndOfWord=!0,z.method.push(G.method),z.handler.push(G.handler),z.path=F}insertMidl(F){if(!this.root.subMiddlewares.has(F))this.root.subMiddlewares.set(F)}search(F,G){let z=this.root;const L=F.split("/").filter(Boolean);for(let U of L){let Y=U;if(!z.children[Y])if(z.children[":"])z=z.children[":"];else return null;else z=z.children[Y]}let J=z.method.indexOf(G);if(J!==-1)return{path:z.path,handler:z.handler[J],isDynamic:z.isDynamic,pattern:z.pattern,method:z.method[J]};return{path:z.path,handler:z.handler,isDynamic:z.isDynamic,pattern:z.pattern,method:z.method[J]}}getAllRoutes(){const F=[],G=(z,L)=>{if(z.isEndOfWord)F.push({path:L,handler:z.handler,isImportant:z.isImportant,isDynamic:z.isDynamic,pattern:z.pattern});for(let J in z.children){const U=z.children[J],Y=L+(J===":"?"/:"+U.pattern:"/"+J);G(U,Y)}};return G(this.root,""),F}}async function b(F){const G={};if(!F)return G;return F.split(";").forEach((L)=>{const[J,U]=L.trim().split("=");G[J]=U.split(" ")[0]}),G}function v(F,G){const z={},L=F.split("/"),[J]=G.split("?"),U=J.split("/");if(L.length!==U.length)return null;return L.forEach((Y,E)=>{if(Y.startsWith(":")){const A=Y.slice(1);z[A]=U[E]}}),z}async function T(F){const G=F.headers.get("Content-Type")||"";if(!G)return{};try{if(G.startsWith("application/json"))return await F.json();if(G.startsWith("application/x-www-form-urlencoded")){const z=await F.text();return Object.fromEntries(new URLSearchParams(z))}if(G.startsWith("multipart/form-data")){const z=await F.formData();return N(z)}return new Response({error:"Unknown request body type"})}catch(z){return new Response({error:"Invalid request body format"})}}function N(F){const G={};for(let[z,L]of F.entries())G[z]=L;return G}function Q(F,G){let z={},L={},J=!1,U=null,Y=null,E=null,A=null,$=200;return{req:F,url:G,next:()=>{},status(X){return $=X,this},async body(){if(!A)A=await T(F);return A},setHeader(X,Z){return z[X]=Z,this},set(X,Z){return L[X]=Z,this},get(X){return L[X]},setAuth(X){return J=X,this},getAuth(){return J},text(X,Z){if(Z)$=Z;return new Response(X,{status:$,headers:z})},json(X,Z){if(Z)$=Z;return new Response(JSON.stringify(X),{status:$,headers:{"Content-Type":"application/json",...z}})},html(X,Z){if(Z)$=Z;return new Response(Bun.file(X),{status:$,headers:{...z}})},file(X,Z){if(Z)$=Z;return new Response(Bun.file(X),{status:$,headers:{...z}})},redirect(X,Z){if(Z)$=Z;return new Response(null,{status:$,headers:{Location:X,...z}})},getParams(X){if(!E)E=v(F.routePattern,G.pathname);return X?E[X]:E},getQuery(X){if(!U)U=Object.fromEntries(G.searchParams);return X?U[X]:U},async cookie(X,Z,_={}){let W=`${encodeURIComponent(X)}=${encodeURIComponent(Z)}`;if(_.maxAge)W+=`; Max-Age=${_.maxAge}`;if(_.expires)W+=`; Expires=${_.expires.toUTCString()}`;if(_.path)W+=`; Path=${_.path}`;if(_.domain)W+=`; Domain=${_.domain}`;if(_.secure)W+="; Secure";if(_.httpOnly)W+="; HttpOnly";if(_.sameSite)W+=`; SameSite=${_.sameSite}`;if(z["Set-Cookie"]){const K=Array.isArray(z["Set-Cookie"])?z["Set-Cookie"]:[z["Set-Cookie"]];K.push(W),z["Set-Cookie"]=K}else z["Set-Cookie"]=W;return this},async getCookie(X){if(!Y)Y=await b(F.headers.get("cookie"));return X?Y[X]:Y}}}async function I(F,G){for(let z of F){const L=await z(G);if(L)return L}}var M={};async function j(F,G,z){const L=Q(F,G);if(z.hasOnReqHook)await z.hooks.onRequest(L);if(z.hasMiddleware){const U=[...z.globalMiddlewares,...z.middlewares.get(G.pathname)||[]],Y=await I(U,L);if(Y)return Y}let J;if(M[G.pathname+F.method])J=M[G.pathname+F.method];else J=z.trie.search(G.pathname,F.method),M[G.pathname+F.method]=J;if(!J||!J.handler)return new Response(`Route not found for ${G.pathname}`,{status:404});if(J.method!==F.method)return new Response("Method not allowed",{status:405});if(J.isDynamic)F.routePattern=J.path;if(z.hasPreHandlerHook){const U=await z.hooks.preHandler(L);if(U)return U}try{const U=await J.handler(L);if(z.hasPostHandlerHook)await z.hooks.postHandler(L);if(z.hasOnSendHook){const Y=await z.hooks.onSend(U,L);if(Y)return Y}return U??new Response("No response from handler",{status:204})}catch(U){return new Response("Internal Server Error",{status:500})}}class D{constructor(){this.routes=new Map,this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new V,this.hasMiddleware=!1,this.hasOnReqHook=!1,this.hasPreHandlerHook=!1,this.hasPostHandlerHook=!1,this.hasOnSendHook=!1,this.hooks={onRequest:null,preHandler:null,postHandler:null,onSend:null,onError:null,onClose:null}}addHooks(F,G){if(typeof F!=="string")throw new Error("hookName must be a string");if(typeof G!=="function")throw new Error("callback must be a instance of function");if(this.hooks.hasOwnProperty(F))this.hooks[F]=G;else throw new Error(`Unknown hook type: ${F}`)}compile(){if(this.globalMiddlewares.length>0)this.hasMiddleware=!0;for(let[F,G]of this.middlewares.entries())if(G.length>0){this.hasMiddleware=!0;break}if(this.hooks.onRequest)this.hasOnReqHook=!0;if(this.hooks.preHandler)this.hasPreHandlerHook=!0;if(this.hooks.postHandler)this.hasPostHandlerHook=!0;if(this.hooks.onSend)this.hasOnSendHook=!0}listen(F,G,{sslCert:z=null,sslKey:L=null}={}){if(typeof Bun==="undefined")throw new Error(".listen() is designed to run on Bun only...");if(typeof F!=="number")throw new Error("Port must be a numeric value");this.compile();const J={port:F,fetch:async(Y)=>{const E=new URL(Y.url);try{return await j(Y,E,this)}catch(A){return new Response("Internal Server Error",{status:500})}},onClose(){console.log("Server is shutting down...")}};if(z&&L)J.certFile=z,J.keyFile=L;const U=Bun.serve(J);if(typeof G==="function")return G();if(z&&L)console.log(`HTTPS server is running on https://localhost:${F}`);else console.log(`HTTP server is running on http://localhost:${F}`);return U}register(F,G){if(typeof F!=="string")throw new Error("path must be a string");if(typeof G!=="object")throw new Error("handler parameter should be a instance of router object",G);const z=Object.entries(G.trie.root.children);G.trie.root.subMiddlewares.forEach((L,J)=>{if(!this.middlewares.has(F+J))this.middlewares.set(F+J,[]);if(!this.middlewares.get(F+J).includes(...L))this.middlewares.get(F+J).push(...L)});for(let[L,J]of z){const U=F+J?.path,Y=J.handler[0],E=J.method[0];this.trie.insert(U,{handler:Y,method:E})}G.trie=new V}#z(F,G,z){if(typeof G!=="string")throw new Error("Path must be a string type");if(typeof F!=="string")throw new Error("method must be a string type");const L=z.slice(0,-1);if(!this.middlewares.has(G))this.middlewares.set(G,[]);if(G==="/")L.forEach((U)=>{if(!this.globalMiddlewares.includes(U))this.globalMiddlewares.push(U)});else if(!this.middlewares.get(G).includes(...L))this.middlewares.get(G).push(...L);const J=z[z.length-1];this.trie.insert(G,{handler:J,method:F})}use(F,G){if(typeof F==="function"){if(!this.globalMiddlewares.includes(F))return this.globalMiddlewares.push(F)}const z=F;if(!this.middlewares.has(z))this.middlewares.set(z,[]);if(!this.middlewares.get(z).includes(G))this.middlewares.get(z).push(G)}get(F,...G){return this.#z("GET",F,G),this}post(F,...G){return this.#z("POST",F,G),this}put(F,...G){return this.#z("PUT",F,G),this}patch(F,...G){return this.#z("PATCH",F,G),this}delete(F,...G){return this.#z("DELETE",F,G),this}}var H=D;export{H as default};
|