diesel-core 0.0.16 → 0.0.17
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/CONTRIBUTING.md +3 -1
- package/README.md +20 -3
- package/build.js +23 -13
- package/dist/ctx.js +1 -0
- package/dist/handleRequest.js +1 -0
- package/dist/main.js +1 -0
- package/dist/trie.js +1 -0
- package/dist/types.d.ts +2 -2
- package/dist/utils.js +1 -0
- package/example/bun.lockb +0 -0
- package/example/main.ts +47 -50
- package/example/package.json +3 -0
- package/package.json +2 -2
- package/src/ctx.ts +13 -7
- package/src/handleRequest.ts +14 -12
- package/src/main.ts +1 -0
- package/src/types.ts +10 -2
- package/tsconfig.json +1 -1
package/CONTRIBUTING.md
CHANGED
package/README.md
CHANGED
|
@@ -169,11 +169,28 @@ app.addHooks('onSend',async (xl, result) => {
|
|
|
169
169
|
|
|
170
170
|
# Middleware example
|
|
171
171
|
|
|
172
|
+
**No Need to call NonSense *next()* in Middleware**
|
|
173
|
+
|
|
174
|
+
**just dont return , if evrything goes right**
|
|
175
|
+
|
|
172
176
|
```javascript
|
|
173
|
-
function
|
|
174
|
-
|
|
177
|
+
async function authJwt (ctx:ContextType, server?:Server): Promise<void | Response> {
|
|
178
|
+
|
|
179
|
+
try {
|
|
180
|
+
const token = ctx?.getCookie("accessToken");
|
|
181
|
+
if (!token) {
|
|
182
|
+
return ctx.status(401).json({ message: "Authentication token missing" });
|
|
183
|
+
}
|
|
184
|
+
// Verify the JWT token using a secret key
|
|
185
|
+
const user = jwt.verify(token, secret);
|
|
186
|
+
ctx.set('user',user);
|
|
187
|
+
} catch (error) {
|
|
188
|
+
return ctx.status(403).json({ message: "Invalid token" });
|
|
189
|
+
}
|
|
175
190
|
}
|
|
176
|
-
|
|
191
|
+
|
|
192
|
+
// this is a global middleware
|
|
193
|
+
app.use(authJwt)
|
|
177
194
|
|
|
178
195
|
// path middleware example
|
|
179
196
|
app.use("/user",authJWT)
|
package/build.js
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
outdir: './dist',
|
|
11
|
-
minify: true, // Enable minification
|
|
12
|
-
})
|
|
1
|
+
import path from 'path';
|
|
2
|
+
const entryPoints = [
|
|
3
|
+
'./main/main.js',
|
|
4
|
+
'./main/ctx.js',
|
|
5
|
+
'./main/handleRequest.js',
|
|
6
|
+
'./main/trie.js',
|
|
7
|
+
'./main/router.js',
|
|
8
|
+
'./main/utils.js'
|
|
9
|
+
];
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
entryPoints.forEach(entry => {
|
|
12
|
+
console.log(`Building: ${entry}`);
|
|
13
|
+
try {
|
|
14
|
+
Bun.build({
|
|
15
|
+
entrypoints: [path.resolve(entry)],
|
|
16
|
+
outdir: './dist',
|
|
17
|
+
minify: true,
|
|
18
|
+
});
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.error(`Failed to build ${entry}:`, error);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Bun.spawn(['rm','-rf','./main'])
|
package/dist/ctx.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var w=function(I,J,G,F){function Y(R){return R instanceof G?R:new G(function(L){L(R)})}return new(G||(G=Promise))(function(R,L){function X(U){try{Z(F.next(U))}catch(W){L(W)}}function $(U){try{Z(F.throw(U))}catch(W){L(W)}}function Z(U){U.done?R(U.value):Y(U.value).then(X,$)}Z((F=F.apply(I,J||[])).next())})};function O(I,J,G){let F=new Headers,Y={},R=!1,L,X=null,$,Z,U=200,W={};return{req:I,server:J,url:G,next:()=>{},getUser(){return W},setUser(z){if(z)W=z},status(z){return U=z,this},getIP(){return this.server.requestIP(this.req)},body(){return w(this,void 0,void 0,function*(){if(!Z)Z=yield V(I);if(Z.error)return new Response(JSON.stringify({error:Z.error}),{status:400});return Z})},setHeader(z,E){return F.set(z,E),this},set(z,E){return Y[z]=E,this},get(z){return Y[z]||null},setAuth(z){return R=z,this},getAuth(){return R},text(z,E){return new Response(z,{status:E!==null&&E!==void 0?E:U,headers:F})},json(z,E){return new Response(JSON.stringify(z),{status:E!==null&&E!==void 0?E:U,headers:F})},html(z,E){return new Response(Bun.file(z),{status:E!==null&&E!==void 0?E:U,headers:F})},file(z,E){return new Response(Bun.file(z),{status:E!==null&&E!==void 0?E:U,headers:F})},redirect(z,E){return F.set("Location",z),new Response(null,{status:E!==null&&E!==void 0?E:302,headers:F})},getParams(z){if(!$)$=x(I===null||I===void 0?void 0:I.routePattern,G===null||G===void 0?void 0:G.pathname);return z?$[z]||{}:$},getQuery(z){try{if(!L)L=Object.fromEntries(G.searchParams);return z?L[z]||{}:L}catch(E){return{}}},cookie(z,E,M={}){let K=`${encodeURIComponent(z)}=${encodeURIComponent(E)}`;if(M.maxAge)K+=`; Max-Age=${M.maxAge}`;if(M.expires)K+=`; Expires=${M.expires.toUTCString()}`;if(M.path)K+=`; Path=${M.path}`;if(M.domain)K+=`; Domain=${M.domain}`;if(M.secure)K+="; Secure";if(M.httpOnly)K+="; HttpOnly";if(M.sameSite)K+=`; SameSite=${M.sameSite}`;return F===null||F===void 0||F.append("Set-Cookie",K),this},getCookie(z){var E;if(!X||Object.keys(X).length===0){let M=(E=I.headers)===null||E===void 0?void 0:E.get("cookie");if(M)X=H(M);else return null}if(!X)return null;return z?X[z]!==void 0?X[z]:null:X}}}function H(I){let J={};if(!I)return J;return I.split(";").forEach((F)=>{var Y;let[R,L]=(Y=F===null||F===void 0?void 0:F.trim())===null||Y===void 0?void 0:Y.split("=");if(R&&L)J[R.trim()]=L.split(" ")[0].trim()}),J}function x(I,J){let G={},F=I.split("/"),[Y]=J.split("?"),R=Y.split("/");if(F.length!==R.length)return null;return F.forEach((L,X)=>{if(L.startsWith(":")){let $=L.slice(1);G[$]=R[X]}}),G}function V(I){return w(this,void 0,void 0,function*(){let J=I.headers.get("Content-Type")||"";if(!J)return{};try{if(J.startsWith("application/json"))return yield I.json();if(J.startsWith("application/x-www-form-urlencoded")){let G=yield I.text();return Object.fromEntries(new URLSearchParams(G))}if(J.startsWith("multipart/form-data")){let G=yield I.formData();return A(G)}return{error:"Unknown request body type"}}catch(G){return{error:"Invalid request body format"}}})}function A(I){let J={};for(let[G,F]of I.entries())J[G]=F;return J}export{O as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var Q=function(L,G,E,z){function K(Y){return Y instanceof E?Y:new E(function(U){U(Y)})}return new(E||(E=Promise))(function(Y,U){function Z(I){try{$(z.next(I))}catch(W){U(W)}}function X(I){try{$(z.throw(I))}catch(W){U(W)}}function $(I){I.done?Y(I.value):K(I.value).then(Z,X)}$((z=z.apply(L,G||[])).next())})};function D(L,G,E){let z=new Headers,K={},Y=!1,U,Z=null,X,$,I=200,W={};return{req:L,server:G,url:E,next:()=>{},getUser(){return W},setUser(F){if(F)W=F},status(F){return I=F,this},getIP(){return this.server.requestIP(this.req)},body(){return Q(this,void 0,void 0,function*(){if(!$)$=yield A(L);if($.error)return new Response(JSON.stringify({error:$.error}),{status:400});return $})},setHeader(F,J){return z.set(F,J),this},set(F,J){return K[F]=J,this},get(F){return K[F]||null},setAuth(F){return Y=F,this},getAuth(){return Y},text(F,J){return new Response(F,{status:J!==null&&J!==void 0?J:I,headers:z})},json(F,J){return new Response(JSON.stringify(F),{status:J!==null&&J!==void 0?J:I,headers:z})},html(F,J){return new Response(Bun.file(F),{status:J!==null&&J!==void 0?J:I,headers:z})},file(F,J){return new Response(Bun.file(F),{status:J!==null&&J!==void 0?J:I,headers:z})},redirect(F,J){return z.set("Location",F),new Response(null,{status:J!==null&&J!==void 0?J:302,headers:z})},getParams(F){if(!X)X=B(L===null||L===void 0?void 0:L.routePattern,E===null||E===void 0?void 0:E.pathname);return F?X[F]||{}:X},getQuery(F){try{if(!U)U=Object.fromEntries(E.searchParams);return F?U[F]||{}:U}catch(J){return{}}},cookie(F,J,M={}){let V=`${encodeURIComponent(F)}=${encodeURIComponent(J)}`;if(M.maxAge)V+=`; Max-Age=${M.maxAge}`;if(M.expires)V+=`; Expires=${M.expires.toUTCString()}`;if(M.path)V+=`; Path=${M.path}`;if(M.domain)V+=`; Domain=${M.domain}`;if(M.secure)V+="; Secure";if(M.httpOnly)V+="; HttpOnly";if(M.sameSite)V+=`; SameSite=${M.sameSite}`;return z===null||z===void 0||z.append("Set-Cookie",V),this},getCookie(F){var J;if(!Z||Object.keys(Z).length===0){let M=(J=L.headers)===null||J===void 0?void 0:J.get("cookie");if(M)Z=T(M);else return null}if(!Z)return null;return F?Z[F]!==void 0?Z[F]:null:Z}}}function T(L){let G={};if(!L)return G;return L.split(";").forEach((z)=>{var K;let[Y,U]=(K=z===null||z===void 0?void 0:z.trim())===null||K===void 0?void 0:K.split("=");if(Y&&U)G[Y.trim()]=U.split(" ")[0].trim()}),G}function B(L,G){let E={},z=L.split("/"),[K]=G.split("?"),Y=K.split("/");if(z.length!==Y.length)return null;return z.forEach((U,Z)=>{if(U.startsWith(":")){let X=U.slice(1);E[X]=Y[Z]}}),E}function A(L){return Q(this,void 0,void 0,function*(){let G=L.headers.get("Content-Type")||"";if(!G)return{};try{if(G.startsWith("application/json"))return yield L.json();if(G.startsWith("application/x-www-form-urlencoded")){let E=yield L.text();return Object.fromEntries(new URLSearchParams(E))}if(G.startsWith("multipart/form-data")){let E=yield L.formData();return N(E)}return{error:"Unknown request body type"}}catch(E){return{error:"Invalid request body format"}}})}function N(L){let G={};for(let[E,z]of L.entries())G[E]=z;return G}var O=function(L,G,E,z){function K(Y){return Y instanceof E?Y:new E(function(U){U(Y)})}return new(E||(E=Promise))(function(Y,U){function Z(I){try{$(z.next(I))}catch(W){U(W)}}function X(I){try{$(z.throw(I))}catch(W){U(W)}}function $(I){I.done?Y(I.value):K(I.value).then(Z,X)}$((z=z.apply(L,G||[])).next())})};function R(L,G,E,z){return O(this,void 0,void 0,function*(){var K,Y,U;let Z=z.trie.search(E.pathname,L.method);if(!Z||Z.method!==L.method)return new Response(Z?"Method not allowed":`Route not found for ${E.pathname}`,{status:Z?405:404});if(Z.isDynamic)L.routePattern=Z.path;let X=D(L,G,E);if(z.corsConfig){let I=C(L,X,z.corsConfig);if(I)return I}if(z.hasOnReqHook&&z.hooks.onRequest)z.hooks.onRequest(X,G);if(z.hasFilterEnabled){let I=(K=L.routePattern)!==null&&K!==void 0?K:E.pathname;if(z.filters.includes(I)===!1)if(z.filterFunction)try{let F=yield z.filterFunction(X,G);if(F)return F}catch(F){return console.error("Error in filterFunction:",F),new Response(JSON.stringify({message:"Internal Server Error"}),{status:500})}else return new Response(JSON.stringify({message:"Authentication required"}),{status:400})}if(z.hasMiddleware){for(let W of z.globalMiddlewares){let F=yield W(X,G);if(F)return F}let I=z.middlewares.get(E.pathname)||[];for(let W of I){let F=yield W(X,G);if(F)return F}}if(z.hasPreHandlerHook&&z.hooks.preHandler){let I=yield z.hooks.preHandler(X);if(I)return I}let $=z.hasPreHandlerHook?yield(U=(Y=z.hooks).preHandler)===null||U===void 0?void 0:U.call(Y,X):null;if($)return $;try{let I=yield Z.handler(X);if(z.hasPostHandlerHook&&z.hooks.postHandler)yield z.hooks.postHandler(X);if(z.hasOnSendHook&&z.hooks.onSend){let W=yield z.hooks.onSend(X,I);if(W)return W}return I!==null&&I!==void 0?I:new Response("No response from handler",{status:204})}catch(I){return new Response("Internal Server Error",{status:500})}})}function C(L,G,E={}){var z,K,Y,U,Z;let X=(z=L.headers.get("origin"))!==null&&z!==void 0?z:"*",$=E===null||E===void 0?void 0:E.origin,I=(K=E===null||E===void 0?void 0:E.allowedHeaders)!==null&&K!==void 0?K:["Content-Type","Authorization"],W=(Y=E===null||E===void 0?void 0:E.methods)!==null&&Y!==void 0?Y:["GET","POST","PUT","DELETE","OPTIONS"],F=(U=E===null||E===void 0?void 0:E.credentials)!==null&&U!==void 0?U:!1,J=(Z=E===null||E===void 0?void 0:E.exposedHeaders)!==null&&Z!==void 0?Z:[];if(G.setHeader("Access-Control-Allow-Methods",W),G.setHeader("Access-Control-Allow-Headers",I),G.setHeader("Access-Control-Allow-Credentials",F),J.length)G.setHeader("Access-Control-Expose-Headers",J);if($==="*")G.setHeader("Access-Control-Allow-Origin","*");else if(Array.isArray($))if(X&&$.includes(X))G.setHeader("Access-Control-Allow-Origin",X);else if($.includes("*"))G.setHeader("Access-Control-Allow-Origin","*");else return G.status(403).json({message:"CORS not allowed"});else if(typeof $==="string")if(X===$)G.setHeader("Access-Control-Allow-Origin",X);else return G.status(403).json({message:"CORS not allowed"});else return G.status(403).json({message:"CORS not allowed"});if(G.setHeader("Access-Control-Allow-Origin",X),L.method==="OPTIONS")return G.setHeader("Access-Control-Max-Age","86400"),G.status(204).text("");return null}export{R as default};
|
package/dist/main.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class A{constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class K{constructor(){this.root=new A}insert(G,J){let z=this.root,U=G.split("/").filter(Boolean);if(G==="/"){z.isEndOfWord=!0,z.handler.push(J.handler),z.path=G,z.method.push(J.method);return}for(let Y of U){let Z=!1,X=Y;if(Y.startsWith(":"))Z=!0,X=":";if(!z.children[X])z.children[X]=new A;z=z.children[X],z.isDynamic=Z,z.pattern=Y,z.method.push(J.method),z.handler.push(J.handler),z.path=G}z.isEndOfWord=!0,z.method.push(J.method),z.handler.push(J.handler),z.path=G}search(G,J){let z=this.root,U=G.split("/").filter(Boolean);for(let Z of U){let X=Z;if(!z.children[X])if(z.children[":"])z=z.children[":"];else return null;else z=z.children[X]}let Y=z.method.indexOf(J);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]}}}var N=function(G,J,z,U){function Y(Z){return Z instanceof z?Z:new z(function(X){X(Z)})}return new(z||(z=Promise))(function(Z,X){function F($){try{V(U.next($))}catch(Q){X(Q)}}function L($){try{V(U.throw($))}catch(Q){X(Q)}}function V($){$.done?Z($.value):Y($.value).then(F,L)}V((U=U.apply(G,J||[])).next())})};function M(G,J,z){let U=new Headers,Y={},Z=!1,X,F=null,L,V,$=200,Q={};return{req:G,server:J,url:z,next:()=>{},getUser(){return Q},setUser(E){if(E)Q=E},status(E){return $=E,this},getIP(){return this.server.requestIP(this.req)},body(){return N(this,void 0,void 0,function*(){if(!V)V=yield O(G);if(V.error)return new Response(JSON.stringify({error:V.error}),{status:400});return V})},setHeader(E,W){return U.set(E,W),this},set(E,W){return Y[E]=W,this},get(E){return Y[E]||null},setAuth(E){return Z=E,this},getAuth(){return Z},text(E,W){return new Response(E,{status:W!==null&&W!==void 0?W:$,headers:U})},json(E,W){return new Response(JSON.stringify(E),{status:W!==null&&W!==void 0?W:$,headers:U})},html(E,W){return new Response(Bun.file(E),{status:W!==null&&W!==void 0?W:$,headers:U})},file(E,W){return new Response(Bun.file(E),{status:W!==null&&W!==void 0?W:$,headers:U})},redirect(E,W){return U.set("Location",E),new Response(null,{status:W!==null&&W!==void 0?W:302,headers:U})},getParams(E){if(!L)L=I(G===null||G===void 0?void 0:G.routePattern,z===null||z===void 0?void 0:z.pathname);return E?L[E]||{}:L},getQuery(E){try{if(!X)X=Object.fromEntries(z.searchParams);return E?X[E]||{}:X}catch(W){return{}}},cookie(E,W,B={}){let D=`${encodeURIComponent(E)}=${encodeURIComponent(W)}`;if(B.maxAge)D+=`; Max-Age=${B.maxAge}`;if(B.expires)D+=`; Expires=${B.expires.toUTCString()}`;if(B.path)D+=`; Path=${B.path}`;if(B.domain)D+=`; Domain=${B.domain}`;if(B.secure)D+="; Secure";if(B.httpOnly)D+="; HttpOnly";if(B.sameSite)D+=`; SameSite=${B.sameSite}`;return U===null||U===void 0||U.append("Set-Cookie",D),this},getCookie(E){var W;if(!F||Object.keys(F).length===0){let B=(W=G.headers)===null||W===void 0?void 0:W.get("cookie");if(B)F=j(B);else return null}if(!F)return null;return E?F[E]!==void 0?F[E]:null:F}}}function j(G){let J={};if(!G)return J;return G.split(";").forEach((U)=>{var Y;let[Z,X]=(Y=U===null||U===void 0?void 0:U.trim())===null||Y===void 0?void 0:Y.split("=");if(Z&&X)J[Z.trim()]=X.split(" ")[0].trim()}),J}function I(G,J){let z={},U=G.split("/"),[Y]=J.split("?"),Z=Y.split("/");if(U.length!==Z.length)return null;return U.forEach((X,F)=>{if(X.startsWith(":")){let L=X.slice(1);z[L]=Z[F]}}),z}function O(G){return N(this,void 0,void 0,function*(){let J=G.headers.get("Content-Type")||"";if(!J)return{};try{if(J.startsWith("application/json"))return yield G.json();if(J.startsWith("application/x-www-form-urlencoded")){let z=yield G.text();return Object.fromEntries(new URLSearchParams(z))}if(J.startsWith("multipart/form-data")){let z=yield G.formData();return S(z)}return{error:"Unknown request body type"}}catch(z){return{error:"Invalid request body format"}}})}function S(G){let J={};for(let[z,U]of G.entries())J[z]=U;return J}var b=function(G,J,z,U){function Y(Z){return Z instanceof z?Z:new z(function(X){X(Z)})}return new(z||(z=Promise))(function(Z,X){function F($){try{V(U.next($))}catch(Q){X(Q)}}function L($){try{V(U.throw($))}catch(Q){X(Q)}}function V($){$.done?Z($.value):Y($.value).then(F,L)}V((U=U.apply(G,J||[])).next())})};function T(G,J,z,U){return b(this,void 0,void 0,function*(){var Y,Z,X;let F=U.trie.search(z.pathname,G.method);if(!F||F.method!==G.method)return new Response(F?"Method not allowed":`Route not found for ${z.pathname}`,{status:F?405:404});if(F.isDynamic)G.routePattern=F.path;let L=M(G,J,z);if(U.corsConfig){let $=w(G,L,U.corsConfig);if($)return $}if(U.hasOnReqHook&&U.hooks.onRequest)U.hooks.onRequest(L,J);if(U.hasFilterEnabled){let $=(Y=G.routePattern)!==null&&Y!==void 0?Y:z.pathname;if(U.filters.includes($)===!1)if(U.filterFunction)try{let E=yield U.filterFunction(L,J);if(E)return E}catch(E){return console.error("Error in filterFunction:",E),new Response(JSON.stringify({message:"Internal Server Error"}),{status:500})}else return new Response(JSON.stringify({message:"Authentication required"}),{status:400})}if(U.hasMiddleware){for(let Q of U.globalMiddlewares){let E=yield Q(L,J);if(E)return E}let $=U.middlewares.get(z.pathname)||[];for(let Q of $){let E=yield Q(L,J);if(E)return E}}if(U.hasPreHandlerHook&&U.hooks.preHandler){let $=yield U.hooks.preHandler(L);if($)return $}let V=U.hasPreHandlerHook?yield(X=(Z=U.hooks).preHandler)===null||X===void 0?void 0:X.call(Z,L):null;if(V)return V;try{let $=yield F.handler(L);if(U.hasPostHandlerHook&&U.hooks.postHandler)yield U.hooks.postHandler(L);if(U.hasOnSendHook&&U.hooks.onSend){let Q=yield U.hooks.onSend(L,$);if(Q)return Q}return $!==null&&$!==void 0?$:new Response("No response from handler",{status:204})}catch($){return new Response("Internal Server Error",{status:500})}})}function w(G,J,z={}){var U,Y,Z,X,F;let L=(U=G.headers.get("origin"))!==null&&U!==void 0?U:"*",V=z===null||z===void 0?void 0:z.origin,$=(Y=z===null||z===void 0?void 0:z.allowedHeaders)!==null&&Y!==void 0?Y:["Content-Type","Authorization"],Q=(Z=z===null||z===void 0?void 0:z.methods)!==null&&Z!==void 0?Z:["GET","POST","PUT","DELETE","OPTIONS"],E=(X=z===null||z===void 0?void 0:z.credentials)!==null&&X!==void 0?X:!1,W=(F=z===null||z===void 0?void 0:z.exposedHeaders)!==null&&F!==void 0?F:[];if(J.setHeader("Access-Control-Allow-Methods",Q),J.setHeader("Access-Control-Allow-Headers",$),J.setHeader("Access-Control-Allow-Credentials",E),W.length)J.setHeader("Access-Control-Expose-Headers",W);if(V==="*")J.setHeader("Access-Control-Allow-Origin","*");else if(Array.isArray(V))if(L&&V.includes(L))J.setHeader("Access-Control-Allow-Origin",L);else if(V.includes("*"))J.setHeader("Access-Control-Allow-Origin","*");else return J.status(403).json({message:"CORS not allowed"});else if(typeof V==="string")if(L===V)J.setHeader("Access-Control-Allow-Origin",L);else return J.status(403).json({message:"CORS not allowed"});else return J.status(403).json({message:"CORS not allowed"});if(J.setHeader("Access-Control-Allow-Origin",L),G.method==="OPTIONS")return J.setHeader("Access-Control-Max-Age","86400"),J.status(204).text("");return null}function C(G){let{time:J=60000,max:z=100,message:U="Rate limit exceeded. Please try again later."}=G,Y=new Map;return(Z)=>{let X=new Date,F=Z.getIP().address;if(!Y.has(F))Y.set(F,{count:0,startTime:X});let L=Y.get(F);if(L)if(X-L.startTime>J)L.count=1,L.startTime=X;else L.count++;if(L&&L.count>z)return Z.status(429).json({error:U});Z.next()}}var H=function(G,J,z,U){function Y(Z){return Z instanceof z?Z:new z(function(X){X(Z)})}return new(z||(z=Promise))(function(Z,X){function F($){try{V(U.next($))}catch(Q){X(Q)}}function L($){try{V(U.throw($))}catch(Q){X(Q)}}function V($){$.done?Z($.value):Y($.value).then(F,L)}V((U=U.apply(G,J||[])).next())})};class R{constructor(){this.routes=[],this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new K,this.corsConfig=null,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},this.filters=[],this.filterFunction=null,this.hasFilterEnabled=!1,this.wss=null}filter(){return this.hasFilterEnabled=!0,{routeMatcher:(...G)=>{return this.routes=G.sort(),this.filter()},permitAll:()=>{for(let G of this===null||this===void 0?void 0:this.routes)this.filters.push(G);return this.filter()},require:(G)=>{if(G)this.filterFunction=G}}}cors(G){this.corsConfig=G}addHooks(G,J){if(typeof G!=="string")throw new Error("hookName must be a string");if(typeof J!=="function")throw new Error("callback must be a instance of function");if(this.hooks.hasOwnProperty(G))this.hooks[G]=J;else throw new Error(`Unknown hook type: ${G}`)}compile(){if(this.globalMiddlewares.length>0)this.hasMiddleware=!0;for(let[G,J]of this.middlewares.entries())if(J.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,J,{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();let Y={port:G,fetch:(X,F)=>H(this,void 0,void 0,function*(){let L=new URL(X.url);try{return yield T(X,F,L,this)}catch(V){return new Response("Internal Server Error",{status:500})}}),onClose(){console.log("Server is shutting down...")}};if(z&&U)Y.certFile=z,Y.keyFile=U;let Z=Bun.serve(Y);if(Bun===null||Bun===void 0||Bun.gc(!1),typeof J==="function")return J();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 Z}register(G,J){if(typeof G!=="string")throw new Error("path must be a string");if(typeof J!=="object")throw new Error("handler parameter should be a instance of router object",J);let z=Object.entries(J.trie.root.children);J.trie.root.subMiddlewares.forEach((U,Y)=>{if(!this.middlewares.has(G+Y))this.middlewares.set(G+Y,[]);U===null||U===void 0||U.forEach((Z)=>{var X,F;if(!((X=this.middlewares.get(G+Y))===null||X===void 0?void 0:X.includes(Z)))(F=this.middlewares.get(G+Y))===null||F===void 0||F.push(Z)})});for(let[U,Y]of z){let Z=G+(Y===null||Y===void 0?void 0:Y.path),X=Y.handler[0],F=Y.method[0];this.trie.insert(Z,{handler:X,method:F})}J.trie=new K}addRoute(G,J,z){if(typeof J!=="string")throw new Error("Path must be a string type");if(typeof G!=="string")throw new Error("method must be a string type");let U=z.slice(0,-1),Y=z[z.length-1];if(!this.middlewares.has(J))this.middlewares.set(J,[]);U.forEach((Z)=>{var X,F;if(J==="/"){if(!this.globalMiddlewares.includes(Z))this.globalMiddlewares.push(Z)}else if(!((X=this.middlewares.get(J))===null||X===void 0?void 0:X.includes(Z)))(F=this.middlewares.get(J))===null||F===void 0||F.push(Z)}),this.trie.insert(J,{handler:Y,method:G})}use(G,J){var z,U;if(typeof G==="function"){if(!this.globalMiddlewares.includes(G))this.globalMiddlewares.push(G);return}let Y=G;if(!this.middlewares.has(Y))this.middlewares.set(Y,[]);if(J){if(!((z=this.middlewares.get(Y))===null||z===void 0?void 0:z.includes(J)))(U=this.middlewares.get(Y))===null||U===void 0||U.push(J)}}get(G,...J){return this.addRoute("GET",G,J),this}post(G,...J){return this.addRoute("POST",G,J),this}put(G,...J){return this.addRoute("PUT",G,J),this}patch(G,...J){return this.addRoute("PATCH",G,J),this}delete(G,...J){return this.addRoute("DELETE",G,J),this}}export{C as rateLimit,R as default};
|
package/dist/trie.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class C{constructor(){this.children={},this.isEndOfWord=!1,this.handler=[],this.isDynamic=!1,this.pattern="",this.path="",this.method=[],this.subMiddlewares=new Map}}class E{constructor(){this.root=new C}insert(w,q){let j=this.root,B=w.split("/").filter(Boolean);if(w==="/"){j.isEndOfWord=!0,j.handler.push(q.handler),j.path=w,j.method.push(q.method);return}for(let v of B){let A=!1,z=v;if(v.startsWith(":"))A=!0,z=":";if(!j.children[z])j.children[z]=new C;j=j.children[z],j.isDynamic=A,j.pattern=v,j.method.push(q.method),j.handler.push(q.handler),j.path=w}j.isEndOfWord=!0,j.method.push(q.method),j.handler.push(q.handler),j.path=w}search(w,q){let j=this.root,B=w.split("/").filter(Boolean);for(let A of B){let z=A;if(!j.children[z])if(j.children[":"])j=j.children[":"];else return null;else j=j.children[z]}let v=j.method.indexOf(q);if(v!==-1)return{path:j.path,handler:j.handler[v],isDynamic:j.isDynamic,pattern:j.pattern,method:j.method[v]};return{path:j.path,handler:j.handler,isDynamic:j.isDynamic,pattern:j.pattern,method:j.method[v]}}}export{E as default};
|
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Server } from "bun";
|
|
2
2
|
export type listenCalllBackType = () => void;
|
|
3
3
|
export type handlerFunction = (ctx: ContextType, server?: Server) => Response | Promise<Response | null | void>;
|
|
4
|
-
export type middlewareFunc = (ctx: ContextType, server?: Server | undefined) => void | Response | Promise<Response>;
|
|
4
|
+
export type middlewareFunc = (ctx: ContextType, server?: Server | undefined) => null | void | Response | Promise<Response | void | null>;
|
|
5
5
|
export type HookFunction = (ctx: ContextType, result?: Response | null | void, server?: Server) => Response | Promise<Response | null | void>;
|
|
6
6
|
export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD";
|
|
7
7
|
export declare enum HookType {
|
|
@@ -79,7 +79,7 @@ export interface DieselT {
|
|
|
79
79
|
};
|
|
80
80
|
filters: string[];
|
|
81
81
|
hasFilterEnabled: boolean;
|
|
82
|
-
filterFunction: (ctx: ContextType, serer?: Server) => void | Response | Promise<Response | void>;
|
|
82
|
+
filterFunction: (ctx: ContextType, serer?: Server) => void | Response | Promise<Response | void | null>;
|
|
83
83
|
corsConfig: corsT | null;
|
|
84
84
|
globalMiddlewares: Array<(ctx: ContextType, serer?: Server) => void | Promise<Response | null | void>>;
|
|
85
85
|
middlewares: Map<string, Array<(ctx: ContextType, serer?: Server) => void | Promise<Response | null | void>>>;
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function H(v){let{time:z=60000,max:A=100,message:C="Rate limit exceeded. Please try again later."}=v,j=new Map;return(D)=>{let E=new Date,F=D.getIP().address;if(!j.has(F))j.set(F,{count:0,startTime:E});let l=j.get(F);if(l)if(E-l.startTime>z)l.count=1,l.startTime=E;else l.count++;if(l&&l.count>A)return D.status(429).json({error:C});D.next()}}var G=(v,z,A,C)=>{if(A>C)return!1;let j=A+(C-A)/2;if(v[j]==z)return!0;if(v[j]>z)return G(v,z,A,j-1);return G(v,z,j+1,C)};export{H as default,G as binaryS};
|
package/example/bun.lockb
CHANGED
|
Binary file
|
package/example/main.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Server } from "bun";
|
|
2
|
-
import Diesel
|
|
2
|
+
import Diesel, { rateLimit } from "../dist/main";
|
|
3
3
|
import jwt from 'jsonwebtoken'
|
|
4
|
-
import { ContextType, CookieOptions, middlewareFunc } from "../
|
|
4
|
+
import { ContextType, CookieOptions, middlewareFunc } from "../dist/types";
|
|
5
5
|
|
|
6
6
|
const app = new Diesel()
|
|
7
7
|
const secret = 'pradeep'
|
|
@@ -11,21 +11,18 @@ const secret = 'pradeep'
|
|
|
11
11
|
// allowedHeaders: 'Content-Type,Authorization'
|
|
12
12
|
// })
|
|
13
13
|
|
|
14
|
-
async function authJwt
|
|
15
|
-
|
|
16
|
-
const token = ctx?.getCookie("accessToken");
|
|
17
|
-
if (!token) {
|
|
18
|
-
return ctx.status(401).json({ message: "Authentication token missing" });
|
|
19
|
-
}
|
|
14
|
+
async function authJwt(ctx: ContextType, server?: Server): Promise<void | null | Response> {
|
|
15
|
+
|
|
20
16
|
try {
|
|
21
|
-
|
|
17
|
+
const token = ctx?.getCookie("accessToken");
|
|
18
|
+
|
|
19
|
+
if (!token) {
|
|
20
|
+
return ctx.status(401).json({ message: "Authentication token missing" });
|
|
21
|
+
}
|
|
22
22
|
// Verify the JWT token using a secret key
|
|
23
23
|
const user = jwt.verify(token, secret); // Replace with your JWT secret
|
|
24
24
|
// Set the user data in context
|
|
25
|
-
ctx.
|
|
26
|
-
|
|
27
|
-
// Proceed to the next middleware/route handler
|
|
28
|
-
return ctx.next();
|
|
25
|
+
ctx.setUser(user)
|
|
29
26
|
} catch (error) {
|
|
30
27
|
return ctx.status(403).json({ message: "Invalid token" });
|
|
31
28
|
}
|
|
@@ -36,58 +33,58 @@ const limiter = rateLimit({
|
|
|
36
33
|
max: 10, // Maximum number of requests allowed in the time window
|
|
37
34
|
message: "Rate limit exceeded. Please try again later." // Custom error message
|
|
38
35
|
});
|
|
39
|
-
|
|
36
|
+
|
|
40
37
|
// app.use(limiter)
|
|
41
38
|
|
|
42
39
|
app
|
|
43
|
-
.filter()
|
|
44
|
-
.routeMatcher('/api/user/register','/api/user/login','/test/:id','/cookie')
|
|
45
|
-
.permitAll()
|
|
46
|
-
.require(authJwt as middlewareFunc)
|
|
40
|
+
.filter()
|
|
41
|
+
.routeMatcher('/api/user/register', '/api/user/login', '/test/:id', '/cookie')
|
|
42
|
+
.permitAll()
|
|
43
|
+
.require(authJwt as middlewareFunc)
|
|
47
44
|
|
|
48
|
-
// app.use(authJwt)
|
|
45
|
+
// app.use(authJwt as middlewareFunc)
|
|
49
46
|
|
|
50
47
|
// .require(you can pass jwt auth parser)
|
|
51
48
|
|
|
52
|
-
app.get("/", async(xl) => {
|
|
49
|
+
app.get("/", async (xl) => {
|
|
53
50
|
// // const ip = xl.req
|
|
54
51
|
// // // console.log(ip)
|
|
55
52
|
// const user = xl.get('user')
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return xl.status(200).json({msg:"hello world",q})
|
|
53
|
+
const q = xl.getUser()
|
|
54
|
+
|
|
55
|
+
return xl.status(200).json({ msg: "hello world", q })
|
|
59
56
|
});
|
|
60
57
|
|
|
61
58
|
app.get("/test/:id", async (xl) => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
59
|
+
const q = xl.getQuery();
|
|
60
|
+
const params = xl.getParams('id');
|
|
61
|
+
return new Response(JSON.stringify({ msg: "hello world", q, params }));
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
app.get("/ok", (xl) => {
|
|
65
|
+
return xl.status(200).text("kaise ho??")
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
app.get("/cookie", async (xl) => {
|
|
69
|
+
const user = {
|
|
70
|
+
name: "pk",
|
|
71
|
+
age: 22,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const accessToken = jwt.sign(user, secret, { expiresIn: "1d" });
|
|
75
|
+
const refreshToken = jwt.sign(user, secret, { expiresIn: "10d" });
|
|
76
|
+
const options: CookieOptions = {
|
|
77
|
+
httpOnly: true, // Makes cookie accessible only by the web server (not JS)
|
|
78
|
+
secure: true, // Ensures the cookie is sent over HTTPS
|
|
79
|
+
maxAge: 24 * 60 * 60 * 1000, // 1 day in milliseconds
|
|
80
|
+
sameSite: "Strict", // Prevents CSRF (strict origin policy)
|
|
81
|
+
path: "/", // Cookie available for all routes
|
|
82
|
+
};
|
|
83
|
+
return xl
|
|
87
84
|
.cookie("accessToken", accessToken, options)
|
|
88
85
|
.cookie("refreshToken", refreshToken, options)
|
|
89
|
-
.json({msg:"setting cookies"})
|
|
90
|
-
|
|
86
|
+
.json({ msg: "setting cookies" })
|
|
87
|
+
});
|
|
91
88
|
|
|
92
89
|
|
|
93
90
|
|
package/example/package.json
CHANGED
package/package.json
CHANGED
package/src/ctx.ts
CHANGED
|
@@ -5,9 +5,9 @@ export default function createCtx(req: Request, server:Server ,url: URL): Contex
|
|
|
5
5
|
let headers: Headers = new Headers()
|
|
6
6
|
let settedValue: Record<string, string> = {};
|
|
7
7
|
let isAuthenticated: boolean = false;
|
|
8
|
-
let parsedQuery: any
|
|
9
|
-
let parsedCookie: any =
|
|
10
|
-
let parsedParams: any
|
|
8
|
+
let parsedQuery: any
|
|
9
|
+
let parsedCookie: any = null
|
|
10
|
+
let parsedParams: any
|
|
11
11
|
let parsedBody: ParseBodyResult | null;
|
|
12
12
|
let responseStatus: number = 200;
|
|
13
13
|
let user : any = {}
|
|
@@ -120,10 +120,14 @@ export default function createCtx(req: Request, server:Server ,url: URL): Contex
|
|
|
120
120
|
|
|
121
121
|
getQuery(props?: any)
|
|
122
122
|
: string | Record<string, string> | {} {
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
try {
|
|
124
|
+
if (!parsedQuery) {
|
|
125
|
+
parsedQuery = Object.fromEntries(url.searchParams);
|
|
126
|
+
}
|
|
127
|
+
return props ? parsedQuery[props] || {} : parsedQuery;
|
|
128
|
+
} catch (error) {
|
|
129
|
+
return {}
|
|
125
130
|
}
|
|
126
|
-
return props ? parsedQuery[props] || {} : parsedQuery;
|
|
127
131
|
},
|
|
128
132
|
|
|
129
133
|
cookie(name: string, value: string, options: CookieOptions = {}) {
|
|
@@ -144,10 +148,12 @@ export default function createCtx(req: Request, server:Server ,url: URL): Contex
|
|
|
144
148
|
},
|
|
145
149
|
|
|
146
150
|
getCookie(cookieName?: string){
|
|
147
|
-
if (!parsedCookie) {
|
|
151
|
+
if (!parsedCookie || Object.keys(parsedCookie).length === 0) {
|
|
148
152
|
const cookieHeader = req.headers?.get("cookie")
|
|
149
153
|
if (cookieHeader) {
|
|
150
154
|
parsedCookie = parseCookie(cookieHeader);
|
|
155
|
+
} else {
|
|
156
|
+
return null
|
|
151
157
|
}
|
|
152
158
|
}
|
|
153
159
|
if (!parsedCookie) {
|
package/src/handleRequest.ts
CHANGED
|
@@ -4,11 +4,9 @@ import type { ContextType, corsT, DieselT, middlewareFunc, RouteHandlerT } from
|
|
|
4
4
|
|
|
5
5
|
export default async function handleRequest(req: Request, server: Server, url: URL, diesel: DieselT): Promise<Response> {
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
7
|
// Try to find the route handler in the trie
|
|
10
8
|
const routeHandler: RouteHandlerT | undefined = diesel.trie.search(url.pathname, req.method);
|
|
11
|
-
|
|
9
|
+
|
|
12
10
|
// Early return if route or method is not found
|
|
13
11
|
if (!routeHandler || routeHandler.method !== req.method) {
|
|
14
12
|
return new Response(routeHandler ? "Method not allowed" : `Route not found for ${url.pathname}`, {
|
|
@@ -24,7 +22,7 @@ export default async function handleRequest(req: Request, server: Server, url: U
|
|
|
24
22
|
|
|
25
23
|
// cors execution
|
|
26
24
|
if (diesel.corsConfig) {
|
|
27
|
-
const corsResult =
|
|
25
|
+
const corsResult = applyCors(req, ctx, diesel.corsConfig)
|
|
28
26
|
if (corsResult) return corsResult;
|
|
29
27
|
}
|
|
30
28
|
|
|
@@ -33,9 +31,10 @@ export default async function handleRequest(req: Request, server: Server, url: U
|
|
|
33
31
|
|
|
34
32
|
// filter applying
|
|
35
33
|
if (diesel.hasFilterEnabled) {
|
|
36
|
-
|
|
34
|
+
|
|
37
35
|
const path = req.routePattern ?? url.pathname
|
|
38
36
|
const hasRoute = diesel.filters.includes(path)
|
|
37
|
+
|
|
39
38
|
if (hasRoute === false) {
|
|
40
39
|
if (diesel.filterFunction) {
|
|
41
40
|
try {
|
|
@@ -57,13 +56,16 @@ export default async function handleRequest(req: Request, server: Server, url: U
|
|
|
57
56
|
|
|
58
57
|
// middleware execution
|
|
59
58
|
if (diesel.hasMiddleware) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
// first run global midl
|
|
60
|
+
for (const globalMiddleware of diesel.globalMiddlewares) {
|
|
61
|
+
const result = await globalMiddleware(ctx, server);
|
|
62
|
+
if (result) return result;
|
|
63
|
+
}
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
// then path specific midl
|
|
66
|
+
const pathMiddlewares = diesel.middlewares.get(url.pathname) || [];
|
|
67
|
+
for (const pathMiddleware of pathMiddlewares) {
|
|
68
|
+
const result = await pathMiddleware(ctx, server);
|
|
67
69
|
if (result) return result;
|
|
68
70
|
}
|
|
69
71
|
|
|
@@ -100,7 +102,7 @@ export default async function handleRequest(req: Request, server: Server, url: U
|
|
|
100
102
|
}
|
|
101
103
|
|
|
102
104
|
|
|
103
|
-
|
|
105
|
+
function applyCors(req: Request, ctx: ContextType, config: corsT = {}): Response | null {
|
|
104
106
|
const origin = req.headers.get('origin') ?? '*'
|
|
105
107
|
const allowedOrigins = config?.origin
|
|
106
108
|
const allowedHeaders = config?.allowedHeaders ?? ["Content-Type", "Authorization"]
|
package/src/main.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Server } from "bun";
|
|
|
2
2
|
|
|
3
3
|
export type listenCalllBackType = () => void;
|
|
4
4
|
export type handlerFunction = (ctx: ContextType, server?: Server) => Response | Promise<Response | null | void>;
|
|
5
|
-
export type middlewareFunc = (ctx:ContextType,server?:Server | undefined) => void | Response | Promise<Response>
|
|
5
|
+
export type middlewareFunc = (ctx:ContextType,server?:Server | undefined) => null | void | Response | Promise<Response | void | null>
|
|
6
6
|
export type HookFunction = (ctx: ContextType, result?: Response | null | void, server?: Server) => Response | Promise<Response | null | void>
|
|
7
7
|
// export type onSendHookFunc = (result?: Response | null | void, ctx?:ContextType) => Response | Promise<Response | null | void>
|
|
8
8
|
export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD";
|
|
@@ -89,7 +89,7 @@ export interface DieselT {
|
|
|
89
89
|
};
|
|
90
90
|
filters: string[]
|
|
91
91
|
hasFilterEnabled:boolean
|
|
92
|
-
filterFunction: (ctx:ContextType,serer?:Server) => void | Response | Promise<Response|void>
|
|
92
|
+
filterFunction: (ctx:ContextType,serer?:Server) => void | Response | Promise<Response | void | null>
|
|
93
93
|
corsConfig: corsT | null
|
|
94
94
|
globalMiddlewares: Array<(ctx: ContextType, serer?: Server) => void | Promise<Response | null | void>>
|
|
95
95
|
middlewares: Map<string, Array<(ctx: ContextType, serer?: Server) => void | Promise<Response | null | void>>>
|
|
@@ -98,6 +98,14 @@ export interface DieselT {
|
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
// export interface routerT {
|
|
102
|
+
// get : (path: string, ...handlers: handlerFunction[]) => this,
|
|
103
|
+
// post: (path: string, ...handlers: handlerFunction[]) => this
|
|
104
|
+
// put: (path: string, ...handlers: handlerFunction[]) => this
|
|
105
|
+
// delete: (path: string, ...handlers: handlerFunction[]) => this
|
|
106
|
+
// patch: (path: string, ...handlers: handlerFunction[]) => this
|
|
107
|
+
// }
|
|
108
|
+
|
|
101
109
|
export interface RouteCache {
|
|
102
110
|
[key: string]: RouteHandlerT | undefined;
|
|
103
111
|
}
|
package/tsconfig.json
CHANGED