diesel-core 0.0.24 → 1.0.1

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.
@@ -0,0 +1,49 @@
1
+ name: Ci of Diesel-project
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - main
7
+
8
+ jobs:
9
+ build:
10
+ name: Build our Diesel-core
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - name: Checkout code
15
+ uses: actions/checkout@v2
16
+
17
+ # Cache Bun installation
18
+ - name: Cache Bun
19
+ id: cache-bun
20
+ uses: actions/cache@v3
21
+ with:
22
+ path: ~/.bun
23
+ key: ${{ runner.os }}-bun-${{ hashFiles('**/bunfig.toml') }}
24
+ restore-keys: |
25
+ ${{ runner.os }}-bun-
26
+
27
+ # Install Bun if it's not cached
28
+ - name: Install Bun
29
+ run: |
30
+ if [ ! -d "$HOME/.bun" ]; then
31
+ curl -fsSL https://bun.sh/install | bash
32
+ fi
33
+ echo "$HOME/.bun/bin" >> $GITHUB_PATH
34
+ continue-on-error: true # Allows the workflow to continue even if Bun is already installed
35
+
36
+ - name: Install dependencies
37
+ run: bun install
38
+
39
+ - name: Run TypeScript Compiler
40
+ run: tsc
41
+
42
+ - name: Minify our code
43
+ run: bun run build
44
+
45
+ - name: Run server and Test Application
46
+ env:
47
+ PORT: 3001
48
+ run: bun test
49
+
package/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ ### [Read the docs](https://diesel-core.vercel.app/)
2
+
1
3
  # DieselJS
2
4
 
3
5
  **made only for bun***
@@ -34,6 +36,28 @@ app.listen(port, () => {
34
36
  console.log(`diesel is running on port ${port}`)
35
37
  })
36
38
  ```
39
+ # HttpMethods
40
+ **In Diesel there are almost all http methods that you can use**
41
+
42
+ ```javascript
43
+ app.get()
44
+
45
+ app.post()
46
+
47
+ app.put()
48
+
49
+ app.patch()
50
+
51
+ app.delete()
52
+
53
+ app.any() // used for all http methods such as GET,POST,PUT..
54
+
55
+ app.head()
56
+
57
+ app.options()
58
+
59
+ ```
60
+
37
61
 
38
62
  # CORS
39
63
 
@@ -83,9 +107,9 @@ async function authJwt (ctx:ContextType, server?:Server): Promise<void | Respons
83
107
  // Define routes and apply filter
84
108
  app
85
109
  .filter()
86
- .routeMatcher('/api/user/register', '/api/user/login', '/test/:id', '/cookie') // Define public routes
87
- .permitAll() // Mark these routes as public (no auth required)
88
- .require(authJwt); // Apply the authJwt middleware to all other routes
110
+ .routeMatcher('/api/user/register', '/api/user/login', '/test/:id', '/cookie')
111
+ .permitAll()
112
+ .authenticate([authJwt]);
89
113
 
90
114
  // Example public route (no auth required)
91
115
  app.get("/api/user/register", async (ctx:ContextType) => {
@@ -120,11 +144,13 @@ app.listen(port, () => {
120
144
  ```javascript
121
145
  .permitAll()
122
146
  ```
123
- 1. **require(fnc?: middlewareFunc)** :Means that defined routes in ***routeMatcher*** is public & All endpoints needs authentication.
147
+ 1. **authenticate([fnc?: middlewareFunc])** :Means that defined routes in ***routeMatcher*** is public & All endpoints needs authentication.
124
148
 
125
- *Note* : If you don't pass a middleware function to require(), DieselJS will throw an "Unauthorized" error by default. Ensure that you implement and pass a valid authentication function
149
+ *Note* : If you don't pass a middleware function to authenticate(), DieselJS will throw an "Unauthorized" error by default. Ensure that you implement and pass a valid authentication function
126
150
  ```javascript
127
- .require(authJwt)
151
+ .authenticate([authJwt])
152
+
153
+ .authenticate([authJwt, ....]) // you can can add many auth midlleware to authenticate
128
154
  ```
129
155
  ## Use Case
130
156
  * **Public Routes** : Some routes ***(like /api/user/register or /api/user/login)*** are often open to all users without authentication. These routes can be specified with permitAll().
@@ -0,0 +1,3 @@
1
+ import { Server } from "bun";
2
+ import { DieselT } from "./types";
3
+ export declare const pipelineHandler: (req: Request, server: Server, url: URL, diesel: DieselT) => Promise<Response | undefined>;
package/dist/ctx.js CHANGED
@@ -1 +1 @@
1
- function x(F,L,G){let z=new Headers,M={},U=!1,I,Y=null,_,Z,$={};return{req:F,server:L,url:G,getUser(){return $},setUser(w){if(w)$=w},getIP(){return this.server.requestIP(this.req)},async getBody(){if(!Z)Z=await R(F);if(Z.error)return new Response(JSON.stringify({error:Z.error}),{status:400});return Z},setHeader(w,E){return z.set(w,E),this},set(w,E){if(typeof w!=="string")throw new Error("Key must be string type!");if(!E)throw new Error("value paramter is missing pls pass value after key");return M[w]=E,this},get(w){return w?M[w]:null},setAuth(w){return U=w,this},getAuth(){return U},text(w,E){return new Response(w,{status:E,headers:z})},json(w,E){return new Response(JSON.stringify(w),{status:E,headers:z})},file(w,E){return new Response(Bun.file(w),{status:E,headers:z})},redirect(w,E){return z.set("Location",w),new Response(null,{status:E??302,headers:z})},setCookie(w,E,J={}){let X=`${encodeURIComponent(w)}=${encodeURIComponent(E)}`;if(J.maxAge)X+=`; Max-Age=${J.maxAge}`;if(J.expires)X+=`; Expires=${J.expires.toUTCString()}`;if(J.path)X+=`; Path=${J.path}`;if(J.domain)X+=`; Domain=${J.domain}`;if(J.secure)X+="; Secure";if(J.httpOnly)X+="; HttpOnly";if(J.sameSite)X+=`; SameSite=${J.sameSite}`;return z?.append("Set-Cookie",X),this},getParams(w){if(!_&&F?.routePattern)_=O(F?.routePattern,G?.pathname);if(w)return _[w]??{};return w},getQuery(w){try{if(!I)I=Object.fromEntries(G.searchParams);return w?I[w]||{}:I}catch(E){return{}}},getCookie(w){if(!Y){let E=F.headers.get("cookie");if(E)Y=K(E);else return null}if(!Y)return null;if(w)return Y[w]??null;else return Y}}}function K(F){let L={},G=F?.split(";");for(let z=0;z<G?.length;z++){let[M,...U]=G[z].trim().split("="),I=U?.join("=").trim();if(M)L[M.trim()]=decodeURIComponent(I)}return L}function O(F,L){let G={},z=F.split("/"),[M]=L.split("?"),U=M.split("/");if(z.length!==U.length)return null;for(let I=0;I<z.length;I++)if(z[I].startsWith(":"))G[z[I].slice(1)]=U[I];return G}async function R(F){let L=F.headers.get("Content-Type");if(!L)return{};try{if(L.startsWith("application/json"))return await F.json();if(L.startsWith("application/x-www-form-urlencoded")){let G=await F.text();return Object.fromEntries(new URLSearchParams(G))}if(L.startsWith("multipart/form-data")){let G=await F.formData(),z={};for(let[M,U]of G.entries())z[M]=U;return z}return{error:"Unknown request body type"}}catch(G){return{error:"Invalid request body format"}}}export{x as default};
1
+ function D(G){switch(G.split(".").pop()?.toLowerCase()){case"js":return"application/javascript";case"css":return"text/css";case"html":return"text/html";case"json":return"application/json";case"png":return"image/png";case"jpg":case"jpeg":return"image/jpeg";case"svg":return"image/svg+xml";case"gif":return"image/gif";case"woff":return"font/woff";case"woff2":return"font/woff2";default:return"application/octet-stream"}}function _(G,U,J){let E=new Headers({"X-Powered-By":"DieselJS","Cache-Control":"no-cache"});E.set("X-Powered-By","DieselJS");let Z={},$=!1,X,K=null,O,R,w={};return{req:G,server:U,url:J,setHeader(z,F){return E.set(z,F),this},getUser(){return w},setUser(z){if(z)w=z},getIP(){return this.server.requestIP(this.req)},async getBody(){if(!R)R=await V(G);if(R.error)return new Response(JSON.stringify({error:R.error}),{status:400});return R},set(z,F){if(typeof z!=="string")throw new Error("Key must be string type!");if(!F)throw new Error("value paramter is missing pls pass value after key");return Z[z]=F,this},get(z){return z?Z[z]:null},setAuth(z){return $=z,this},getAuth(){return $},text(z,F){if(!E.has("Content-Type"))E.set("Content-Type","text/plain; charset=utf-8");return new Response(z,{status:F,headers:E})},send(z,F){if(typeof z==="string"){if(!E.has("Content-Type"))E.set("Content-Type","text/plain; charset=utf-8")}else if(typeof z==="object"){if(!E.has("Content-Type"))E.set("Content-Type","application/json; charset=utf-8");z=JSON.stringify(z)}else if(z instanceof Uint8Array||z instanceof ArrayBuffer){if(!E.has("Content-Type"))E.set("Content-Type","application/octet-stream")}return new Response(z,{status:F,headers:E})},json(z,F){if(!E.has("Content-Type"))E.set("Content-Type","application/json; charset=utf-8");return new Response(JSON.stringify(z),{status:F,headers:E})},file(z,F=200,L){let Y=D(z),M=Bun.file(z),W=new Headers;if(!W.has("Content-Type"))W.set("Content-Type",L??Y);return new Response(M,{status:F,headers:W})},redirect(z,F){return E.set("Location",z),new Response(null,{status:F??302,headers:E})},setCookie(z,F,L={}){let Y=`${encodeURIComponent(z)}=${encodeURIComponent(F)}`;if(L.maxAge)Y+=`; Max-Age=${L.maxAge}`;if(L.expires)Y+=`; Expires=${L.expires.toUTCString()}`;if(L.path)Y+=`; Path=${L.path}`;if(L.domain)Y+=`; Domain=${L.domain}`;if(L.secure)Y+="; Secure";if(L.httpOnly)Y+="; HttpOnly";if(L.sameSite)Y+=`; SameSite=${L.sameSite}`;return E?.append("Set-Cookie",Y),this},getParams(z){if(!O&&G?.routePattern)O=H(G?.routePattern,J?.pathname);if(z)if(O)return O[z];else return;if(O)return z;else return},getQuery(z){try{if(!X)X=Object.fromEntries(J.searchParams);if(z)return X[z]??void 0;return X}catch(F){return}},getCookie(z){if(!K){let F=G.headers.get("cookie");if(F)K=A(F);else return}if(!K)return;if(z)return K[z]??void 0;else return K}}}function A(G){let U={},J=G?.split(";");for(let E=0;E<J?.length;E++){let[Z,...$]=J[E].trim().split("="),X=$?.join("=").trim();if(Z)U[Z.trim()]=decodeURIComponent(X)}return U}function H(G,U){let J={},E=G.split("/"),[Z]=U.split("?"),$=Z.split("/");if(E.length!==$.length)return null;for(let X=0;X<E.length;X++)if(E[X].startsWith(":"))J[E[X].slice(1)]=$[X];return J}async function V(G){let U=G.headers.get("Content-Type");if(!U)return{};try{if(U.startsWith("application/json"))return await G.json();if(U.startsWith("application/x-www-form-urlencoded")){let J=await G.text();return Object.fromEntries(new URLSearchParams(J))}if(U.startsWith("multipart/form-data")){let J=await G.formData(),E={};for(let[Z,$]of J.entries())E[Z]=$;return E}return{error:"Unknown request body type"}}catch(J){return{error:"Invalid request body format"}}}export{_ as default};
@@ -1,3 +1,7 @@
1
1
  import { Server } from "bun";
2
- import type { DieselT } from "./types";
2
+ import type { ContextType, corsT, DieselT } from "./types";
3
3
  export default function handleRequest(req: Request, server: Server, url: URL, diesel: DieselT): Promise<Response>;
4
+ export declare function applyCors(req: Request, ctx: ContextType, config?: corsT): Response | null;
5
+ export declare function handleFilterRequest(diesel: DieselT, path: string, ctx: ContextType, server: Server): Promise<Response | undefined>;
6
+ export declare function generateErrorResponse(status: number, message: string): Response;
7
+ export declare function handleStaticFiles(diesel: DieselT, pathname: string, ctx: ContextType): Promise<Response | null>;
@@ -1 +1 @@
1
- function D(I,E,G){let z=new Headers,J={},L=!1,Y,U=null,Z,_,K={};return{req:I,server:E,url:G,getUser(){return K},setUser(F){if(F)K=F},getIP(){return this.server.requestIP(this.req)},async getBody(){if(!_)_=await j(I);if(_.error)return new Response(JSON.stringify({error:_.error}),{status:400});return _},setHeader(F,X){return z.set(F,X),this},set(F,X){if(typeof F!=="string")throw new Error("Key must be string type!");if(!X)throw new Error("value paramter is missing pls pass value after key");return J[F]=X,this},get(F){return F?J[F]:null},setAuth(F){return L=F,this},getAuth(){return L},text(F,X){return new Response(F,{status:X,headers:z})},json(F,X){return new Response(JSON.stringify(F),{status:X,headers:z})},file(F,X){return new Response(Bun.file(F),{status:X,headers:z})},redirect(F,X){return z.set("Location",F),new Response(null,{status:X??302,headers:z})},setCookie(F,X,$={}){let W=`${encodeURIComponent(F)}=${encodeURIComponent(X)}`;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},getParams(F){if(!Z&&I?.routePattern)Z=T(I?.routePattern,G?.pathname);if(F)return Z[F]??{};return F},getQuery(F){try{if(!Y)Y=Object.fromEntries(G.searchParams);return F?Y[F]||{}:Y}catch(X){return{}}},getCookie(F){if(!U){let X=I.headers.get("cookie");if(X)U=A(X);else return null}if(!U)return null;if(F)return U[F]??null;else return U}}}function A(I){let E={},G=I?.split(";");for(let z=0;z<G?.length;z++){let[J,...L]=G[z].trim().split("="),Y=L?.join("=").trim();if(J)E[J.trim()]=decodeURIComponent(Y)}return E}function T(I,E){let G={},z=I.split("/"),[J]=E.split("?"),L=J.split("/");if(z.length!==L.length)return null;for(let Y=0;Y<z.length;Y++)if(z[Y].startsWith(":"))G[z[Y].slice(1)]=L[Y];return G}async function j(I){let E=I.headers.get("Content-Type");if(!E)return{};try{if(E.startsWith("application/json"))return await I.json();if(E.startsWith("application/x-www-form-urlencoded")){let G=await I.text();return Object.fromEntries(new URLSearchParams(G))}if(E.startsWith("multipart/form-data")){let G=await I.formData(),z={};for(let[J,L]of G.entries())z[J]=L;return z}return{error:"Unknown request body type"}}catch(G){return{error:"Invalid request body format"}}}async function M(I,E,G,z){let J=z.trie.search(G.pathname,I.method);if(J?.isDynamic)I.routePattern=J.path;let L=D(I,E,G);if(z.corsConfig){let U=Q(I,L,z.corsConfig);if(U)return U}if(z.hasOnReqHook&&z.hooks.onRequest)z.hooks.onRequest(I,G,E);if(z.hasFilterEnabled){let U=I.routePattern??G.pathname;if(!z.filters.has(U))if(z.filterFunction)try{let Z=await z.filterFunction(L,E);if(Z)return Z}catch(Z){return console.error("Error in filterFunction:",Z),L.json({message:"Internal Server Error",error:Z.message},500)}else return L.json({message:"Authentication required"},400)}if(z.hasMiddleware){let U=z.globalMiddlewares;for(let _=0;_<U.length;_++){let K=await U[_](L,E);if(K)return K}let Z=z.middlewares.get(G.pathname)||[];for(let _=0;_<Z.length;_++){let K=await Z[_](L,E);if(K)return K}}if(!J||J.method!==I.method){let U=J?"Method not allowed":`Route not found for ${G.pathname}`,Z=J?405:404;return new Response(JSON.stringify({message:U}),{status:Z})}if(z.hasPreHandlerHook&&z.hooks.preHandler){let U=await z.hooks.preHandler(L);if(U)return U}let Y=await J.handler(L);if(z.hasPostHandlerHook&&z.hooks.postHandler)await z.hooks.postHandler(L);if(z.hasOnSendHook&&z.hooks.onSend){let U=await z.hooks.onSend(L,Y);if(U)return U}return Y??L.json({message:"No response from this handler"},204)}function Q(I,E,G={}){let z=I.headers.get("origin")??"*",J=G?.origin,L=G?.allowedHeaders??["Content-Type","Authorization"],Y=G?.methods??["GET","POST","PUT","DELETE","OPTIONS"],U=G?.credentials??!1,Z=G?.exposedHeaders??[];if(E.setHeader("Access-Control-Allow-Methods",Y),E.setHeader("Access-Control-Allow-Headers",L),E.setHeader("Access-Control-Allow-Credentials",U),Z.length)E.setHeader("Access-Control-Expose-Headers",Z);if(J==="*")E.setHeader("Access-Control-Allow-Origin","*");else if(Array.isArray(J))if(z&&J.includes(z))E.setHeader("Access-Control-Allow-Origin",z);else if(J.includes("*"))E.setHeader("Access-Control-Allow-Origin","*");else return E.json({message:"CORS not allowed"},403);else if(typeof J==="string")if(z===J)E.setHeader("Access-Control-Allow-Origin",z);else return E.json({message:"CORS not allowed"},403);else return E.json({message:"CORS not allowed"},403);if(E.setHeader("Access-Control-Allow-Origin",z),I.method==="OPTIONS")return E.setHeader("Access-Control-Max-Age","86400"),E.text("",204);return null}export{M as default};
1
+ function A(L){switch(L.split(".").pop()?.toLowerCase()){case"js":return"application/javascript";case"css":return"text/css";case"html":return"text/html";case"json":return"application/json";case"png":return"image/png";case"jpg":case"jpeg":return"image/jpeg";case"svg":return"image/svg+xml";case"gif":return"image/gif";case"woff":return"font/woff";case"woff2":return"font/woff2";default:return"application/octet-stream"}}function Q(L,J,U){let z=new Headers({"X-Powered-By":"DieselJS","Cache-Control":"no-cache"});z.set("X-Powered-By","DieselJS");let X={},Y=!1,K,Z=null,W,E,F={};return{req:L,server:J,url:U,setHeader(G,$){return z.set(G,$),this},getUser(){return F},setUser(G){if(G)F=G},getIP(){return this.server.requestIP(this.req)},async getBody(){if(!E)E=await M(L);if(E.error)return new Response(JSON.stringify({error:E.error}),{status:400});return E},set(G,$){if(typeof G!=="string")throw new Error("Key must be string type!");if(!$)throw new Error("value paramter is missing pls pass value after key");return X[G]=$,this},get(G){return G?X[G]:null},setAuth(G){return Y=G,this},getAuth(){return Y},text(G,$){if(!z.has("Content-Type"))z.set("Content-Type","text/plain; charset=utf-8");return new Response(G,{status:$,headers:z})},send(G,$){if(typeof G==="string"){if(!z.has("Content-Type"))z.set("Content-Type","text/plain; charset=utf-8")}else if(typeof G==="object"){if(!z.has("Content-Type"))z.set("Content-Type","application/json; charset=utf-8");G=JSON.stringify(G)}else if(G instanceof Uint8Array||G instanceof ArrayBuffer){if(!z.has("Content-Type"))z.set("Content-Type","application/octet-stream")}return new Response(G,{status:$,headers:z})},json(G,$){if(!z.has("Content-Type"))z.set("Content-Type","application/json; charset=utf-8");return new Response(JSON.stringify(G),{status:$,headers:z})},file(G,$=200,_){let D=A(G),N=Bun.file(G),j=new Headers;if(!j.has("Content-Type"))j.set("Content-Type",_??D);return new Response(N,{status:$,headers:j})},redirect(G,$){return z.set("Location",G),new Response(null,{status:$??302,headers:z})},setCookie(G,$,_={}){let D=`${encodeURIComponent(G)}=${encodeURIComponent($)}`;if(_.maxAge)D+=`; Max-Age=${_.maxAge}`;if(_.expires)D+=`; Expires=${_.expires.toUTCString()}`;if(_.path)D+=`; Path=${_.path}`;if(_.domain)D+=`; Domain=${_.domain}`;if(_.secure)D+="; Secure";if(_.httpOnly)D+="; HttpOnly";if(_.sameSite)D+=`; SameSite=${_.sameSite}`;return z?.append("Set-Cookie",D),this},getParams(G){if(!W&&L?.routePattern)W=O(L?.routePattern,U?.pathname);if(G)if(W)return W[G];else return;if(W)return G;else return},getQuery(G){try{if(!K)K=Object.fromEntries(U.searchParams);if(G)return K[G]??void 0;return K}catch($){return}},getCookie(G){if(!Z){let $=L.headers.get("cookie");if($)Z=B($);else return}if(!Z)return;if(G)return Z[G]??void 0;else return Z}}}function B(L){let J={},U=L?.split(";");for(let z=0;z<U?.length;z++){let[X,...Y]=U[z].trim().split("="),K=Y?.join("=").trim();if(X)J[X.trim()]=decodeURIComponent(K)}return J}function O(L,J){let U={},z=L.split("/"),[X]=J.split("?"),Y=X.split("/");if(z.length!==Y.length)return null;for(let K=0;K<z.length;K++)if(z[K].startsWith(":"))U[z[K].slice(1)]=Y[K];return U}async function M(L){let J=L.headers.get("Content-Type");if(!J)return{};try{if(J.startsWith("application/json"))return await L.json();if(J.startsWith("application/x-www-form-urlencoded")){let U=await L.text();return Object.fromEntries(new URLSearchParams(U))}if(J.startsWith("multipart/form-data")){let U=await L.formData(),z={};for(let[X,Y]of U.entries())z[X]=Y;return z}return{error:"Unknown request body type"}}catch(U){return{error:"Invalid request body format"}}}async function I(L,J,U,z){let X=z.trie.search(U.pathname,L.method);if(X?.isDynamic)L.routePattern=X.path;let Y=Q(L,J,U);if(z.corsConfig){let Z=C(L,Y,z.corsConfig);if(Z)return Z}if(z.hooks.onRequest)z.hooks.onRequest(L,U,J);if(z.hasFilterEnabled){let Z=L.routePattern??U.pathname,W=await b(z,Z,Y,J);if(W)return W}if(z.hasMiddleware){let Z=z.globalMiddlewares;for(let E=0;E<Z.length;E++){let F=await Z[E](Y,J);if(F)return F}let W=z.middlewares.get(U.pathname)||[];for(let E=0;E<W.length;E++){let F=await W[E](Y,J);if(F)return F}}if(!X||X.method!==L.method){let Z=z.trie.search("*",L.method);if(Z){let W=await T(z,U.pathname,Y);if(W)return W;return await Z.handler(Y)}return V(X?405:404,X?"Method not allowed":`Route not found for ${U.pathname}`)}if(z.hooks.preHandler){let Z=await z.hooks.preHandler(Y);if(Z)return Z}let K=await X.handler(Y);if(z.hooks.postHandler)await z.hooks.postHandler(Y);if(z.hooks.onSend){let Z=await z.hooks.onSend(Y,K);if(Z)return Z}return K??V(204,"No response from this handler")}function C(L,J,U={}){let z=L.headers.get("origin")??"*",X=U?.origin,Y=U?.allowedHeaders??["Content-Type","Authorization"],K=U?.methods??["GET","POST","PUT","DELETE","OPTIONS"],Z=U?.credentials??!1,W=U?.exposedHeaders??[];if(J.setHeader("Access-Control-Allow-Methods",K),J.setHeader("Access-Control-Allow-Headers",Y),J.setHeader("Access-Control-Allow-Credentials",Z),W.length)J.setHeader("Access-Control-Expose-Headers",W);if(X==="*"||z==="*")J.setHeader("Access-Control-Allow-Origin","*");else if(Array.isArray(X))if(z&&X.includes(z))J.setHeader("Access-Control-Allow-Origin",z);else if(X.includes("*"))J.setHeader("Access-Control-Allow-Origin","*");else return J.json({message:"CORS not allowed"},403);else if(typeof X==="string")if(z===X)J.setHeader("Access-Control-Allow-Origin",z);else return J.json({message:"CORS not allowed"},403);else return J.json({message:"CORS not allowed"},403);if(J.setHeader("Access-Control-Allow-Origin",z),L.method==="OPTIONS")return J.setHeader("Access-Control-Max-Age","86400"),J.text("",204);return null}async function b(L,J,U,z){if(!L.filters.has(J)){if(L.filterFunction.length)for(let X of L.filterFunction){let Y=await X(U,z);if(Y)return Y}return U.json({error:!0,message:"Protected route, authentication required",status:401},401)}}function V(L,J){return new Response(JSON.stringify({error:!0,message:J,status:L}),{status:L,headers:{"Content-Type":"application/json"}})}async function T(L,J,U){if(!L.UseStaticFiles)throw new Error("Static files directory is not configured.");let z=`${L.UseStaticFiles}${J}`;if(/\.(js|css|html)$/.test(J)){let X=A(z);return U.file(z,200,X)}return null}export{T as handleStaticFiles,b as handleFilterRequest,V as generateErrorResponse,I as default,C as applyCors};
package/dist/main.d.ts CHANGED
@@ -2,7 +2,7 @@ import Trie from "./trie.js";
2
2
  import { corsT, FilterMethods, HookFunction, HookType, listenArgsT, middlewareFunc, onError, onRequest, type handlerFunction, type Hooks } from "./types.js";
3
3
  import { Server } from "bun";
4
4
  export default class Diesel {
5
- tempRoutes: Map<string, any>;
5
+ private tempRoutes;
6
6
  globalMiddlewares: middlewareFunc[];
7
7
  middlewares: Map<string, middlewareFunc[]>;
8
8
  trie: Trie;
@@ -16,14 +16,20 @@ export default class Diesel {
16
16
  corsConfig: corsT;
17
17
  FilterRoutes: string[] | null | undefined;
18
18
  filters: Set<string>;
19
- filterFunction: middlewareFunc | null;
19
+ filterFunction: middlewareFunc[];
20
20
  hasFilterEnabled: boolean;
21
+ private serverInstance;
22
+ UseStaticFiles: any;
23
+ staticFiles: any;
21
24
  constructor();
22
- filter(): FilterMethods;
25
+ setupFilter(): FilterMethods;
23
26
  cors(corsConfig: corsT): this;
27
+ UseStatic(filePath: string): void;
28
+ static(route: string | string[], filePath: string | string[]): this;
24
29
  addHooks(typeOfHook: HookType, fnc: HookFunction | onError | onRequest): this;
25
30
  private compile;
26
31
  listen(port?: number, ...args: listenArgsT[]): Server | void;
32
+ close(callback?: () => void): void;
27
33
  /**
28
34
  * Registers a router instance for subrouting.
29
35
  * Allows defining subroutes like:
@@ -58,5 +64,9 @@ export default class Diesel {
58
64
  post(path: string, ...handlers: handlerFunction[]): this;
59
65
  put(path: string, ...handlers: handlerFunction[]): this;
60
66
  patch(path: string, ...handlers: handlerFunction[]): this;
61
- delete(path: any, ...handlers: handlerFunction[]): this;
67
+ delete(path: string, ...handlers: handlerFunction[]): this;
68
+ any(path: string, ...handlers: handlerFunction[]): this;
69
+ head(path: string, ...handlers: handlerFunction[]): this;
70
+ options(path: string, ...handlers: handlerFunction[]): this;
71
+ propfind(path: string, ...handlers: handlerFunction[]): this;
62
72
  }
package/dist/main.js CHANGED
@@ -1 +1 @@
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 D{root;constructor(){this.root=new Q}insert(G,z){let L=this.root,J=G.split("/").filter(Boolean);if(G==="/"){L.isEndOfWord=!0,L.handler=[z.handler],L.path=G,L.method=[z.method];return}for(let U=0;U<J.length;U++){let X=J[U],_=!1,Y=X;if(X.startsWith(":"))_=!0,Y=":";if(!L.children[Y])L.children[Y]=new Q;if(L=L.children[Y],L.isDynamic=_,L.pattern=X,U===J.length-1)L.handler=[z.handler],L.method=[z.method],L.isEndOfWord=!0,L.path=G}}search(G,z){let L=this.root,J=G.split("/").filter(Boolean);for(let X of J){let _=X;if(!L.children[_])if(L.children[":"])L=L.children[":"];else return null;else L=L.children[_]}let U=L.method.indexOf(z);if(L.isEndOfWord&&U!==-1)return{path:L.path,handler:L.handler[U],isDynamic:L.isDynamic,pattern:L.pattern,method:L.method[U]};return null}}function V(G,z,L){let J=new Headers,U={},X=!1,_,Y=null,$,F,W={};return{req:G,server:z,url:L,getUser(){return W},setUser(Z){if(Z)W=Z},getIP(){return this.server.requestIP(this.req)},async getBody(){if(!F)F=await T(G);if(F.error)return new Response(JSON.stringify({error:F.error}),{status:400});return F},setHeader(Z,K){return J.set(Z,K),this},set(Z,K){if(typeof Z!=="string")throw new Error("Key must be string type!");if(!K)throw new Error("value paramter is missing pls pass value after key");return U[Z]=K,this},get(Z){return Z?U[Z]:null},setAuth(Z){return X=Z,this},getAuth(){return X},text(Z,K){return new Response(Z,{status:K,headers:J})},json(Z,K){return new Response(JSON.stringify(Z),{status:K,headers:J})},file(Z,K){return new Response(Bun.file(Z),{status:K,headers:J})},redirect(Z,K){return J.set("Location",Z),new Response(null,{status:K??302,headers:J})},setCookie(Z,K,E={}){let A=`${encodeURIComponent(Z)}=${encodeURIComponent(K)}`;if(E.maxAge)A+=`; Max-Age=${E.maxAge}`;if(E.expires)A+=`; Expires=${E.expires.toUTCString()}`;if(E.path)A+=`; Path=${E.path}`;if(E.domain)A+=`; Domain=${E.domain}`;if(E.secure)A+="; Secure";if(E.httpOnly)A+="; HttpOnly";if(E.sameSite)A+=`; SameSite=${E.sameSite}`;return J?.append("Set-Cookie",A),this},getParams(Z){if(!$&&G?.routePattern)$=I(G?.routePattern,L?.pathname);if(Z)return $[Z]??{};return Z},getQuery(Z){try{if(!_)_=Object.fromEntries(L.searchParams);return Z?_[Z]||{}:_}catch(K){return{}}},getCookie(Z){if(!Y){let K=G.headers.get("cookie");if(K)Y=M(K);else return null}if(!Y)return null;if(Z)return Y[Z]??null;else return Y}}}function M(G){let z={},L=G?.split(";");for(let J=0;J<L?.length;J++){let[U,...X]=L[J].trim().split("="),_=X?.join("=").trim();if(U)z[U.trim()]=decodeURIComponent(_)}return z}function I(G,z){let L={},J=G.split("/"),[U]=z.split("?"),X=U.split("/");if(J.length!==X.length)return null;for(let _=0;_<J.length;_++)if(J[_].startsWith(":"))L[J[_].slice(1)]=X[_];return L}async function T(G){let z=G.headers.get("Content-Type");if(!z)return{};try{if(z.startsWith("application/json"))return await G.json();if(z.startsWith("application/x-www-form-urlencoded")){let L=await G.text();return Object.fromEntries(new URLSearchParams(L))}if(z.startsWith("multipart/form-data")){let L=await G.formData(),J={};for(let[U,X]of L.entries())J[U]=X;return J}return{error:"Unknown request body type"}}catch(L){return{error:"Invalid request body format"}}}async function B(G,z,L,J){let U=J.trie.search(L.pathname,G.method);if(U?.isDynamic)G.routePattern=U.path;let X=V(G,z,L);if(J.corsConfig){let Y=N(G,X,J.corsConfig);if(Y)return Y}if(J.hasOnReqHook&&J.hooks.onRequest)J.hooks.onRequest(G,L,z);if(J.hasFilterEnabled){let Y=G.routePattern??L.pathname;if(!J.filters.has(Y))if(J.filterFunction)try{let $=await J.filterFunction(X,z);if($)return $}catch($){return console.error("Error in filterFunction:",$),X.json({message:"Internal Server Error",error:$.message},500)}else return X.json({message:"Authentication required"},400)}if(J.hasMiddleware){let Y=J.globalMiddlewares;for(let F=0;F<Y.length;F++){let W=await Y[F](X,z);if(W)return W}let $=J.middlewares.get(L.pathname)||[];for(let F=0;F<$.length;F++){let W=await $[F](X,z);if(W)return W}}if(!U||U.method!==G.method){let Y=U?"Method not allowed":`Route not found for ${L.pathname}`,$=U?405:404;return new Response(JSON.stringify({message:Y}),{status:$})}if(J.hasPreHandlerHook&&J.hooks.preHandler){let Y=await J.hooks.preHandler(X);if(Y)return Y}let _=await U.handler(X);if(J.hasPostHandlerHook&&J.hooks.postHandler)await J.hooks.postHandler(X);if(J.hasOnSendHook&&J.hooks.onSend){let Y=await J.hooks.onSend(X,_);if(Y)return Y}return _??X.json({message:"No response from this handler"},204)}function N(G,z,L={}){let J=G.headers.get("origin")??"*",U=L?.origin,X=L?.allowedHeaders??["Content-Type","Authorization"],_=L?.methods??["GET","POST","PUT","DELETE","OPTIONS"],Y=L?.credentials??!1,$=L?.exposedHeaders??[];if(z.setHeader("Access-Control-Allow-Methods",_),z.setHeader("Access-Control-Allow-Headers",X),z.setHeader("Access-Control-Allow-Credentials",Y),$.length)z.setHeader("Access-Control-Expose-Headers",$);if(U==="*")z.setHeader("Access-Control-Allow-Origin","*");else if(Array.isArray(U))if(J&&U.includes(J))z.setHeader("Access-Control-Allow-Origin",J);else if(U.includes("*"))z.setHeader("Access-Control-Allow-Origin","*");else return z.json({message:"CORS not allowed"},403);else if(typeof U==="string")if(J===U)z.setHeader("Access-Control-Allow-Origin",J);else return z.json({message:"CORS not allowed"},403);else return z.json({message:"CORS not allowed"},403);if(z.setHeader("Access-Control-Allow-Origin",J),G.method==="OPTIONS")return z.setHeader("Access-Control-Max-Age","86400"),z.text("",204);return null}class j{tempRoutes;globalMiddlewares;middlewares;trie;hasOnReqHook;hasMiddleware;hasPreHandlerHook;hasPostHandlerHook;hasOnSendHook;hasOnError;hooks;corsConfig;FilterRoutes;filters;filterFunction;hasFilterEnabled;constructor(){this.tempRoutes=new Map,this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new D,this.corsConfig=null,this.hasMiddleware=!1,this.hasOnReqHook=!1,this.hasPreHandlerHook=!1,this.hasPostHandlerHook=!1,this.hasOnSendHook=!1,this.hasOnError=!1,this.hooks={onRequest:null,preHandler:null,postHandler:null,onSend:null,onError:null,onClose:null},this.FilterRoutes=[],this.filters=new Set,this.filterFunction=null,this.hasFilterEnabled=!1}filter(){return this.hasFilterEnabled=!0,{routeMatcher:(...G)=>{return this.FilterRoutes=G,this.filter()},permitAll:()=>{for(let G of this?.FilterRoutes)this.filters.add(G);return this.FilterRoutes=null,this.filter()},require:(G)=>{if(G)this.filterFunction=G}}}cors(G){return this.corsConfig=G,this}addHooks(G,z){if(typeof G!=="string")throw new Error("hookName must be a string");if(typeof z!=="function")throw new Error("callback must be a instance of function");switch(G){case"onRequest":this.hooks.onRequest=z,this.hasOnReqHook=!0;break;case"preHandler":this.hooks.preHandler=z,this.hasPreHandlerHook=!0;break;case"postHandler":this.hooks.postHandler=z,this.hasPostHandlerHook=!0;break;case"onSend":this.hooks.onSend=z,this.hasOnSendHook=!0;break;case"onError":this.hooks.onError=z,this.hasOnError=!0;break;case"onClose":this.hooks.onClose=z;break;default:throw new Error(`Unknown hook type: ${G}`)}return this}compile(){if(this.globalMiddlewares.length>0)this.hasMiddleware=!0;for(let[G,z]of this.middlewares.entries())if(z.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;if(this.hooks.onError)this.hasOnError=!0;this.tempRoutes=new Map}listen(G=3000,...z){if(typeof Bun==="undefined")throw new Error(".listen() is designed to run on Bun only...");if(!G||typeof G!=="number")throw new Error("port is required and should be a number type");let L="0.0.0.0",J=void 0,U={};for(let Y of z)if(typeof Y==="string")L=Y;else if(typeof Y==="function")J=Y;else if(typeof Y==="object"&&Y!==null)U=Y;let X={port:G,hostname:L,fetch:async(Y,$)=>{let F=new URL(Y.url);try{return await B(Y,$,F,this)}catch(W){if(this.hasOnError&&this.hooks.onError){let Z=await this.hooks.onError(W,Y,F,$);if(Z)return Z}return new Response(JSON.stringify({message:"Internal Server Error",error:W.message}),{status:500})}}};if(U.sslCert&&U.sslKey)X.certFile=U.sslCert,X.keyFile=U.sslKey;this.compile();let _=Bun?.serve(X);if(J)return J();if(U.sslCert&&U.sslKey)console.log(`HTTPS server is running on https://localhost:${G}`);else console.log(`HTTP server is running on http://localhost:${G}`);return _}route(G,z){if(!G||typeof G!=="string")throw new Error("Path must be a string");let L=Object.fromEntries(z.tempRoutes);return Object.entries(L).forEach(([U,X])=>{let _=`${G}${U}`;if(!this.middlewares.has(_))this.middlewares.set(_,[]);X.handlers.slice(0,-1).forEach((W)=>{if(!this.middlewares.get(_)?.includes(W))this.middlewares.get(_)?.push(W)});let $=X.handlers[X.handlers.length-1],F=X.method;try{this.trie.insert(_,{handler:$,method:F})}catch(W){console.error(`Error inserting ${_}:`,W)}}),z=null,this}register(G,z){return this.route(G,z)}addRoute(G,z,L){if(typeof z!=="string")throw new Error(`Error in ${L[L.length-1]}: Path must be a string. Received: ${typeof z}`);if(typeof G!=="string")throw new Error(`Error in addRoute: Method must be a string. Received: ${typeof G}`);this.tempRoutes.set(z,{method:G,handlers:L});let J=L.slice(0,-1),U=L[L.length-1];if(!this.middlewares.has(z))this.middlewares.set(z,[]);J.forEach((X)=>{if(z==="/")this.globalMiddlewares=[...new Set([...this.globalMiddlewares,...J])];else if(!this.middlewares.get(z)?.includes(X))this.middlewares.get(z)?.push(X)});try{this.trie.insert(z,{handler:U,method:G})}catch(X){console.error(`Error inserting ${z}:`,X)}}use(G,z){if(Array.isArray(G))G.forEach((J)=>{if(typeof J==="function")this.globalMiddlewares.push(J)});if(typeof G==="function"){if(this.globalMiddlewares.push(G),Array.isArray(z))z.forEach((J)=>{this.globalMiddlewares.push(J)});return}return(Array.isArray(G)?G.filter((J)=>typeof J==="string"):[G].filter((J)=>typeof J==="string")).forEach((J)=>{if(!this.middlewares.has(J))this.middlewares.set(J,[]);if(z)(Array.isArray(z)?z:[z]).forEach((X)=>{this.middlewares.get(J)?.push(X)})}),this}get(G,...z){return this.addRoute("GET",G,z),this}post(G,...z){return this.addRoute("POST",G,z),this}put(G,...z){return this.addRoute("PUT",G,z),this}patch(G,...z){return this.addRoute("PATCH",G,z),this}delete(G,...z){return this.addRoute("DELETE",G,z),this}}export{j as default};
1
+ class B{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 D{root;constructor(){this.root=new B}insert(z,G){let J=this.root,L=z.split("/").filter(Boolean);if(z==="/"){J.isEndOfWord=!0,J.handler.push(G.handler),J.path=z,J.method.push(G.method);return}for(let U of L){let X=!1,Y=U;if(U.startsWith(":"))X=!0,Y=":";if(!J.children[Y])J.children[Y]=new B;J=J.children[Y],J.isDynamic=X,J.pattern=U,J.method.push(G.method),J.handler.push(G.handler),J.path=z}J.isEndOfWord=!0,J.method.push(G.method),J.handler.push(G.handler),J.path=z}search(z,G){let J=this.root,L=z.split("/").filter(Boolean),U=L.length;for(let $ of L){let K=$;if(!J.children[K])if(J.children[":"])J=J.children[":"];else return null;else J=J.children[K]}let X=J.path.split("/").filter(Boolean);if(U!==X.length)return null;let Y=J.method.indexOf(G);if(Y!==-1)return{path:J.path,handler:J.handler[Y],isDynamic:J.isDynamic,pattern:J.pattern,method:J.method[Y]};return{path:J.path,handler:J.handler,isDynamic:J.isDynamic,pattern:J.pattern,method:J.method[Y]}}}function Q(z){switch(z.split(".").pop()?.toLowerCase()){case"js":return"application/javascript";case"css":return"text/css";case"html":return"text/html";case"json":return"application/json";case"png":return"image/png";case"jpg":case"jpeg":return"image/jpeg";case"svg":return"image/svg+xml";case"gif":return"image/gif";case"woff":return"font/woff";case"woff2":return"font/woff2";default:return"application/octet-stream"}}function j(z,G,J){let L=new Headers({"X-Powered-By":"DieselJS","Cache-Control":"no-cache"});L.set("X-Powered-By","DieselJS");let U={},X=!1,Y,$=null,K,E,A={};return{req:z,server:G,url:J,setHeader(Z,W){return L.set(Z,W),this},getUser(){return A},setUser(Z){if(Z)A=Z},getIP(){return this.server.requestIP(this.req)},async getBody(){if(!E)E=await w(z);if(E.error)return new Response(JSON.stringify({error:E.error}),{status:400});return E},set(Z,W){if(typeof Z!=="string")throw new Error("Key must be string type!");if(!W)throw new Error("value paramter is missing pls pass value after key");return U[Z]=W,this},get(Z){return Z?U[Z]:null},setAuth(Z){return X=Z,this},getAuth(){return X},text(Z,W){if(!L.has("Content-Type"))L.set("Content-Type","text/plain; charset=utf-8");return new Response(Z,{status:W,headers:L})},send(Z,W){if(typeof Z==="string"){if(!L.has("Content-Type"))L.set("Content-Type","text/plain; charset=utf-8")}else if(typeof Z==="object"){if(!L.has("Content-Type"))L.set("Content-Type","application/json; charset=utf-8");Z=JSON.stringify(Z)}else if(Z instanceof Uint8Array||Z instanceof ArrayBuffer){if(!L.has("Content-Type"))L.set("Content-Type","application/octet-stream")}return new Response(Z,{status:W,headers:L})},json(Z,W){if(!L.has("Content-Type"))L.set("Content-Type","application/json; charset=utf-8");return new Response(JSON.stringify(Z),{status:W,headers:L})},file(Z,W=200,_){let F=Q(Z),T=Bun.file(Z),V=new Headers;if(!V.has("Content-Type"))V.set("Content-Type",_??F);return new Response(T,{status:W,headers:V})},redirect(Z,W){return L.set("Location",Z),new Response(null,{status:W??302,headers:L})},setCookie(Z,W,_={}){let F=`${encodeURIComponent(Z)}=${encodeURIComponent(W)}`;if(_.maxAge)F+=`; Max-Age=${_.maxAge}`;if(_.expires)F+=`; Expires=${_.expires.toUTCString()}`;if(_.path)F+=`; Path=${_.path}`;if(_.domain)F+=`; Domain=${_.domain}`;if(_.secure)F+="; Secure";if(_.httpOnly)F+="; HttpOnly";if(_.sameSite)F+=`; SameSite=${_.sameSite}`;return L?.append("Set-Cookie",F),this},getParams(Z){if(!K&&z?.routePattern)K=S(z?.routePattern,J?.pathname);if(Z)if(K)return K[Z];else return;if(K)return Z;else return},getQuery(Z){try{if(!Y)Y=Object.fromEntries(J.searchParams);if(Z)return Y[Z]??void 0;return Y}catch(W){return}},getCookie(Z){if(!$){let W=z.headers.get("cookie");if(W)$=I(W);else return}if(!$)return;if(Z)return $[Z]??void 0;else return $}}}function I(z){let G={},J=z?.split(";");for(let L=0;L<J?.length;L++){let[U,...X]=J[L].trim().split("="),Y=X?.join("=").trim();if(U)G[U.trim()]=decodeURIComponent(Y)}return G}function S(z,G){let J={},L=z.split("/"),[U]=G.split("?"),X=U.split("/");if(L.length!==X.length)return null;for(let Y=0;Y<L.length;Y++)if(L[Y].startsWith(":"))J[L[Y].slice(1)]=X[Y];return J}async function w(z){let G=z.headers.get("Content-Type");if(!G)return{};try{if(G.startsWith("application/json"))return await z.json();if(G.startsWith("application/x-www-form-urlencoded")){let J=await z.text();return Object.fromEntries(new URLSearchParams(J))}if(G.startsWith("multipart/form-data")){let J=await z.formData(),L={};for(let[U,X]of J.entries())L[U]=X;return L}return{error:"Unknown request body type"}}catch(J){return{error:"Invalid request body format"}}}async function N(z,G,J,L){let U=L.trie.search(J.pathname,z.method);if(U?.isDynamic)z.routePattern=U.path;let X=j(z,G,J);if(L.corsConfig){let $=b(z,X,L.corsConfig);if($)return $}if(L.hooks.onRequest)L.hooks.onRequest(z,J,G);if(L.hasFilterEnabled){let $=z.routePattern??J.pathname,K=await v(L,$,X,G);if(K)return K}if(L.hasMiddleware){let $=L.globalMiddlewares;for(let E=0;E<$.length;E++){let A=await $[E](X,G);if(A)return A}let K=L.middlewares.get(J.pathname)||[];for(let E=0;E<K.length;E++){let A=await K[E](X,G);if(A)return A}}if(!U||U.method!==z.method){let $=L.trie.search("*",z.method);if($){let K=await O(L,J.pathname,X);if(K)return K;return await $.handler(X)}return C(U?405:404,U?"Method not allowed":`Route not found for ${J.pathname}`)}if(L.hooks.preHandler){let $=await L.hooks.preHandler(X);if($)return $}let Y=await U.handler(X);if(L.hooks.postHandler)await L.hooks.postHandler(X);if(L.hooks.onSend){let $=await L.hooks.onSend(X,Y);if($)return $}return Y??C(204,"No response from this handler")}function b(z,G,J={}){let L=z.headers.get("origin")??"*",U=J?.origin,X=J?.allowedHeaders??["Content-Type","Authorization"],Y=J?.methods??["GET","POST","PUT","DELETE","OPTIONS"],$=J?.credentials??!1,K=J?.exposedHeaders??[];if(G.setHeader("Access-Control-Allow-Methods",Y),G.setHeader("Access-Control-Allow-Headers",X),G.setHeader("Access-Control-Allow-Credentials",$),K.length)G.setHeader("Access-Control-Expose-Headers",K);if(U==="*"||L==="*")G.setHeader("Access-Control-Allow-Origin","*");else if(Array.isArray(U))if(L&&U.includes(L))G.setHeader("Access-Control-Allow-Origin",L);else if(U.includes("*"))G.setHeader("Access-Control-Allow-Origin","*");else return G.json({message:"CORS not allowed"},403);else if(typeof U==="string")if(L===U)G.setHeader("Access-Control-Allow-Origin",L);else return G.json({message:"CORS not allowed"},403);else return G.json({message:"CORS not allowed"},403);if(G.setHeader("Access-Control-Allow-Origin",L),z.method==="OPTIONS")return G.setHeader("Access-Control-Max-Age","86400"),G.text("",204);return null}async function v(z,G,J,L){if(!z.filters.has(G)){if(z.filterFunction.length)for(let U of z.filterFunction){let X=await U(J,L);if(X)return X}return J.json({error:!0,message:"Protected route, authentication required",status:401},401)}}function C(z,G){return new Response(JSON.stringify({error:!0,message:G,status:z}),{status:z,headers:{"Content-Type":"application/json"}})}async function O(z,G,J){if(!z.UseStaticFiles)throw new Error("Static files directory is not configured.");let L=`${z.UseStaticFiles}${G}`;if(/\.(js|css|html)$/.test(G)){let U=Q(L);return J.file(L,200,U)}return null}class M{tempRoutes;globalMiddlewares;middlewares;trie;hasOnReqHook;hasMiddleware;hasPreHandlerHook;hasPostHandlerHook;hasOnSendHook;hasOnError;hooks;corsConfig;FilterRoutes;filters;filterFunction;hasFilterEnabled;serverInstance;UseStaticFiles;staticFiles;constructor(){this.tempRoutes=new Map,this.globalMiddlewares=[],this.middlewares=new Map,this.trie=new D,this.corsConfig=null,this.hasMiddleware=!1,this.hasOnReqHook=!1,this.hasPreHandlerHook=!1,this.hasPostHandlerHook=!1,this.hasOnSendHook=!1,this.hasOnError=!1,this.hooks={onRequest:null,preHandler:null,postHandler:null,onSend:null,onError:null,onClose:null},this.FilterRoutes=[],this.filters=new Set,this.filterFunction=[],this.hasFilterEnabled=!1,this.serverInstance=null,this.UseStaticFiles=null,this.staticFiles={}}setupFilter(){return this.hasFilterEnabled=!0,{routeMatcher:(...z)=>{return this.FilterRoutes=z,this.setupFilter()},permitAll:()=>{for(let z of this?.FilterRoutes)this.filters.add(z);return this.FilterRoutes=null,this.setupFilter()},authenticate:(z)=>{if(z?.length)for(let G of z)this.filterFunction.push(G)}}}cors(z){return this.corsConfig=z,this}UseStatic(z){this.UseStaticFiles=z}static(z,G){if(!Array.isArray(z)&&!Array.isArray(G))this.staticFiles[z]=G;else for(let J=0;J<z.length;J++)this.staticFiles[z[J]]=G[J];return this}addHooks(z,G){if(typeof z!=="string")throw new Error("hookName must be a string");if(typeof G!=="function")throw new Error("callback must be a instance of function");switch(z){case"onRequest":this.hooks.onRequest=G;break;case"preHandler":this.hooks.preHandler=G;break;case"postHandler":this.hooks.postHandler=G;break;case"onSend":this.hooks.onSend=G;break;case"onError":this.hooks.onError=G;break;case"onClose":this.hooks.onClose=G;break;default:throw new Error(`Unknown hook type: ${z}`)}return this}compile(){if(this.globalMiddlewares.length>0)this.hasMiddleware=!0;for(let[z,G]of this.middlewares.entries())if(G.length>0){this.hasMiddleware=!0;break}this.tempRoutes=new Map}listen(z=3000,...G){if(typeof Bun==="undefined")throw new Error(".listen() is designed to run on Bun only...");if(!z||typeof z!=="number")throw new Error("port is required and should be a number type");let J="0.0.0.0",L=void 0,U={};for(let Y of G)if(typeof Y==="string")J=Y;else if(typeof Y==="function")L=Y;else if(typeof Y==="object"&&Y!==null)U=Y;let X={port:z,hostname:J,fetch:async(Y,$)=>{let K=new URL(Y.url);try{return await N(Y,$,K,this)}catch(E){return this.hasOnError&&this.hooks.onError?this.hooks.onError(E,Y,K,$):new Response(JSON.stringify({message:"Internal Server Error",error:E.message,status:500}),{status:500})}},static:this.staticFiles,development:!0};if(U.sslCert&&U.sslKey)X.certFile=U.sslCert,X.keyFile=U.sslKey;if(this.compile(),this.serverInstance=Bun?.serve(X),L)return L();if(U.sslCert&&U.sslKey)console.log(`HTTPS server is running on https://localhost:${z}`);else console.log(`HTTP server is running on http://localhost:${z}`);return this.serverInstance}close(z){if(this.serverInstance)this.serverInstance.stop(!0),this.serverInstance=null,z?z():console.log("Server has been stopped");else console.warn("Server is not running.")}route(z,G){if(!z||typeof z!=="string")throw new Error("Path must be a string");let J=Object.fromEntries(G.tempRoutes);return Object.entries(J).forEach(([U,X])=>{let Y=`${z}${U}`;if(!this.middlewares.has(Y))this.middlewares.set(Y,[]);X.handlers.slice(0,-1).forEach((A)=>{if(!this.middlewares.get(Y)?.includes(A))this.middlewares.get(Y)?.push(A)});let K=X.handlers[X.handlers.length-1],E=X.method;try{this.trie.insert(Y,{handler:K,method:E})}catch(A){console.error(`Error inserting ${Y}:`,A)}}),G=null,this}register(z,G){return this.route(z,G)}addRoute(z,G,J){if(typeof G!=="string")throw new Error(`Error in ${J[J.length-1]}: Path must be a string. Received: ${typeof G}`);if(typeof z!=="string")throw new Error(`Error in addRoute: Method must be a string. Received: ${typeof z}`);this.tempRoutes.set(G,{method:z,handlers:J});let L=J.slice(0,-1),U=J[J.length-1];if(!this.middlewares.has(G))this.middlewares.set(G,[]);L.forEach((X)=>{if(G==="/")this.globalMiddlewares=[...new Set([...this.globalMiddlewares,...L])];else if(!this.middlewares.get(G)?.includes(X))this.middlewares.get(G)?.push(X)});try{if(z==="ANY"){let X=["GET","POST","PUT","DELETE","PATCH","OPTIONS","HEAD","PROPFIND"];for(let Y of X)this.trie.insert(G,{handler:U,method:Y})}this.trie.insert(G,{handler:U,method:z})}catch(X){console.error(`Error inserting ${G}:`,X)}}use(z,G){if(Array.isArray(z))z.forEach((L)=>{if(typeof L==="function")this.globalMiddlewares.push(L)});if(typeof z==="function"){if(this.globalMiddlewares.push(z),Array.isArray(G))G.forEach((L)=>{this.globalMiddlewares.push(L)});return}return(Array.isArray(z)?z.filter((L)=>typeof L==="string"):[z].filter((L)=>typeof L==="string")).forEach((L)=>{if(!this.middlewares.has(L))this.middlewares.set(L,[]);if(G)(Array.isArray(G)?G:[G]).forEach((X)=>{this.middlewares.get(L)?.push(X)})}),this}get(z,...G){return this.addRoute("GET",z,G),this}post(z,...G){return this.addRoute("POST",z,G),this}put(z,...G){return this.addRoute("PUT",z,G),this}patch(z,...G){return this.addRoute("PATCH",z,G),this}delete(z,...G){return this.addRoute("DELETE",z,G),this}any(z,...G){return this.addRoute("ANY",z,G),this}head(z,...G){return this.addRoute("HEAD",z,G),this}options(z,...G){return this.addRoute("OPTIONS",z,G),this}propfind(z,...G){return this.addRoute("PROPFIND",z,G),this}}export{M as default};
package/dist/trie.d.ts CHANGED
@@ -20,6 +20,12 @@ export default class Trie {
20
20
  isDynamic: boolean;
21
21
  pattern: string;
22
22
  method: string;
23
+ } | {
24
+ path: string;
25
+ handler: handlerFunction[];
26
+ isDynamic: boolean;
27
+ pattern: string;
28
+ method: string;
23
29
  } | null;
24
30
  }
25
31
  export {};
package/dist/trie.js CHANGED
@@ -1 +1 @@
1
- class E{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 F{root;constructor(){this.root=new E}insert(q,w){let b=this.root,z=q.split("/").filter(Boolean);if(q==="/"){b.isEndOfWord=!0,b.handler=[w.handler],b.path=q,b.method=[w.method];return}for(let j=0;j<z.length;j++){let A=z[j],B=!1,C=A;if(A.startsWith(":"))B=!0,C=":";if(!b.children[C])b.children[C]=new E;if(b=b.children[C],b.isDynamic=B,b.pattern=A,j===z.length-1)b.handler=[w.handler],b.method=[w.method],b.isEndOfWord=!0,b.path=q}}search(q,w){let b=this.root,z=q.split("/").filter(Boolean);for(let A of z){let B=A;if(!b.children[B])if(b.children[":"])b=b.children[":"];else return null;else b=b.children[B]}let j=b.method.indexOf(w);if(b.isEndOfWord&&j!==-1)return{path:b.path,handler:b.handler[j],isDynamic:b.isDynamic,pattern:b.pattern,method:b.method[j]};return null}}export{F as default};
1
+ class E{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 G{root;constructor(){this.root=new E}insert(w,v){let j=this.root,A=w.split("/").filter(Boolean);if(w==="/"){j.isEndOfWord=!0,j.handler.push(v.handler),j.path=w,j.method.push(v.method);return}for(let z of A){let B=!1,q=z;if(z.startsWith(":"))B=!0,q=":";if(!j.children[q])j.children[q]=new E;j=j.children[q],j.isDynamic=B,j.pattern=z,j.method.push(v.method),j.handler.push(v.handler),j.path=w}j.isEndOfWord=!0,j.method.push(v.method),j.handler.push(v.handler),j.path=w}search(w,v){let j=this.root,A=w.split("/").filter(Boolean),z=A.length;for(let H of A){let F=H;if(!j.children[F])if(j.children[":"])j=j.children[":"];else return null;else j=j.children[F]}let B=j.path.split("/").filter(Boolean);if(z!==B.length)return null;let q=j.method.indexOf(v);if(q!==-1)return{path:j.path,handler:j.handler[q],isDynamic:j.isDynamic,pattern:j.pattern,method:j.method[q]};return{path:j.path,handler:j.handler,isDynamic:j.isDynamic,pattern:j.pattern,method:j.method[q]}}}export{G as default};
package/dist/types.d.ts CHANGED
@@ -3,7 +3,7 @@ export type listenCalllBackType = () => void;
3
3
  export type handlerFunction = (ctx: ContextType, server?: Server) => Response | Promise<Response | null | void>;
4
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> | void;
6
- export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD";
6
+ export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD" | "ANY" | "PROPFIND";
7
7
  export type HookType = 'onRequest' | 'preHandler' | 'postHandler' | 'onSend' | 'onError' | 'onClose';
8
8
  export interface onError {
9
9
  (error: Error, req: Request, url: URL, server: Server): void | null | Response | Promise<Response | null | void>;
@@ -34,7 +34,8 @@ export interface ContextType {
34
34
  getAuth: () => boolean;
35
35
  json: (data: Object, status?: number) => Response;
36
36
  text: (data: string, status?: number) => Response;
37
- file: (filePath: string, status?: number) => Response;
37
+ send: (data: string, status?: number) => Response;
38
+ file: (filePath: string, status?: number, mimeType?: string) => Response;
38
39
  redirect: (path: string, status?: number) => Response;
39
40
  getParams: (props?: any) => any;
40
41
  getQuery: (props?: any) => any;
@@ -76,13 +77,14 @@ export interface DieselT {
76
77
  };
77
78
  filters: Set<string>;
78
79
  hasFilterEnabled: boolean;
79
- filterFunction: (ctx: ContextType, serer?: Server) => void | Response | Promise<Response | void | null>;
80
+ filterFunction: Array<(ctx: ContextType, serer?: Server) => void | Response | Promise<Response | void | null>>;
80
81
  corsConfig: corsT | null;
81
82
  globalMiddlewares: Array<(ctx: ContextType, serer?: Server) => void | Promise<Response | null | void>>;
82
83
  middlewares: Map<string, Array<(ctx: ContextType, serer?: Server) => void | Promise<Response | null | void>>>;
83
84
  trie: {
84
85
  search: (pathname: string, method: string) => RouteHandlerT | undefined;
85
86
  };
87
+ UseStaticFiles: string | null;
86
88
  }
87
89
  export interface RouteCache {
88
90
  [key: string]: RouteHandlerT | undefined;
@@ -114,7 +116,7 @@ export type corsT = {
114
116
  export interface FilterMethods {
115
117
  routeMatcher: (...routes: string[]) => FilterMethods;
116
118
  permitAll: () => FilterMethods;
117
- require: (fnc?: middlewareFunc) => Response | void;
119
+ authenticate: (fnc?: middlewareFunc[]) => Response | Promise<Response | null> | void;
118
120
  }
119
121
  export type listenArgsT = string | (() => void) | {
120
122
  sslCert?: string;
package/dist/utils.d.ts CHANGED
@@ -4,4 +4,5 @@ export default function rateLimit(props: {
4
4
  max?: number;
5
5
  message?: string;
6
6
  }): (ctx: ContextType) => void | Response;
7
+ export declare function getMimeType(filePath: string): string;
7
8
  export declare const binaryS: (arr: string[], target: string, start: number, end: number) => boolean;
package/dist/utils.js CHANGED
@@ -1 +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(F)=>{let D=new Date,E=F.getIP().address;if(!j.has(E))j.set(E,{count:0,startTime:D});let l=j.get(E);if(l)if(D-l.startTime>z)l.count=1,l.startTime=D;else l.count++;if(l&&l.count>A)return F.json({error:C},429)}}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};
1
+ function J(j){let{time:z=60000,max:C=100,message:D="Rate limit exceeded. Please try again later."}=j,v=new Map;return(G)=>{let E=new Date,F=G.getIP().address;if(!v.has(F))v.set(F,{count:0,startTime:E});let A=v.get(F);if(A)if(E-A.startTime>z)A.count=1,A.startTime=E;else A.count++;if(A&&A.count>C)return G.json({error:D},429)}}function K(j){switch(j.split(".").pop()?.toLowerCase()){case"js":return"application/javascript";case"css":return"text/css";case"html":return"text/html";case"json":return"application/json";case"png":return"image/png";case"jpg":case"jpeg":return"image/jpeg";case"svg":return"image/svg+xml";case"gif":return"image/gif";case"woff":return"font/woff";case"woff2":return"font/woff2";default:return"application/octet-stream"}}var H=(j,z,C,D)=>{if(C>D)return!1;let v=C+(D-C)/2;if(j[v]==z)return!0;if(j[v]>z)return H(j,z,C,v-1);return H(j,z,v+1,D)};export{K as getMimeType,J as default,H as binaryS};
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "diesel-core",
3
- "version": "0.0.24",
3
+ "version": "1.0.1",
4
4
  "main": "index.js",
5
5
  "types": "index.d.ts",
6
6
  "scripts": {
7
- "build": "bun run build.js"
7
+ "build": "bun run build.js",
8
+ "test": "bun run test/index.test.ts"
8
9
  },
9
10
  "keywords": [],
10
11
  "author": "",
@@ -15,8 +16,5 @@
15
16
  },
16
17
  "peerDependencies": {
17
18
  "typescript": "^5.0.0"
18
- },
19
- "dependencies": {
20
- "cookie": "^1.0.1"
21
19
  }
22
20
  }
package/route.ts ADDED
@@ -0,0 +1,35 @@
1
+ // import Diesel from "./main";
2
+ // import type { handlerFunction, HttpMethod } from "./types";
3
+
4
+ // class Router extends Diesel {
5
+ // constructor() {
6
+ // super();
7
+ // }
8
+
9
+ // get(path:string, ...handlers:handlerFunction[]) {
10
+ // this.addRoute("GET", path, handlers);
11
+ // return this
12
+ // }
13
+
14
+ // post(path:string, ...handlers:handlerFunction[]) {
15
+ // this.addRoute("POST", path, handlers);
16
+ // return this;
17
+ // }
18
+
19
+ // put(path:string, ...handlers:handlerFunction[]) {
20
+ // this.addRoute("PUT", path, handlers);
21
+ // return this
22
+ // }
23
+
24
+ // patch(path:string, ...handlers:handlerFunction[]) {
25
+ // this.addRoute("PATCH", path, handlers);
26
+ // return this
27
+ // }
28
+
29
+ // delete(path:string, ...handlers:handlerFunction[]) {
30
+ // this.addRoute("DELETE", path, handlers);
31
+ // return this;
32
+ // }
33
+ // }
34
+
35
+ // export default Router;
@@ -0,0 +1,73 @@
1
+ import { Server } from "bun";
2
+ import { ContextType, DieselT } from "./types";
3
+ import createCtx from "./ctx";
4
+ import { applyCors, generateErrorResponse, handleFilterRequest, handleStaticFiles } from "./handleRequest";
5
+
6
+ export const pipelineHandler = async (req: Request, server: Server, url: URL, diesel: DieselT) => {
7
+
8
+ const ctx: ContextType = createCtx(req, server, url);
9
+
10
+ const pipeline = [
11
+
12
+ () => applyCors(req, ctx, diesel.corsConfig),
13
+
14
+ () => diesel.hasOnReqHook && diesel.hooks.onRequest?.(req, url, server),
15
+
16
+ async () => diesel.hasFilterEnabled && await handleFilterRequest(diesel, req.routePattern ?? url.pathname, ctx, server),
17
+
18
+ async () => {
19
+ if (diesel.hasMiddleware) {
20
+ const globalMiddleware = diesel.globalMiddlewares;
21
+ for (let i = 0; i < globalMiddleware.length; i++) {
22
+ const result = await globalMiddleware[i](ctx, server);
23
+ if (result) return result;
24
+ }
25
+
26
+ const pathMiddlewares = diesel.middlewares.get(url.pathname) || [];
27
+ for (let i = 0; i < pathMiddlewares.length; i++) {
28
+ const result = await pathMiddlewares[i](ctx, server);
29
+ if (result) return result;
30
+ }
31
+ }
32
+ },
33
+
34
+ async () => {
35
+ const routeHandler = diesel.trie.search(url.pathname, req.method);
36
+ if (!routeHandler || routeHandler.method !== req.method) {
37
+ const wildCard = diesel.trie.search("*", req.method)
38
+ if (wildCard) {
39
+ const staticResponse = await handleStaticFiles(diesel, url.pathname, ctx);
40
+ if (staticResponse) return staticResponse;
41
+
42
+ const result = await wildCard.handler(ctx);
43
+ return result as Response
44
+ }
45
+
46
+ return generateErrorResponse(routeHandler ? 405 : 404, routeHandler ? "Method not allowed" : `Route not found for ${url.pathname}`);
47
+ }
48
+ if (routeHandler?.isDynamic) req.routePattern = routeHandler.path;
49
+
50
+ if (diesel.hasPreHandlerHook) {
51
+ const preHookResponse = await diesel.hooks.preHandler?.(ctx);
52
+ if (preHookResponse) return preHookResponse;
53
+ }
54
+
55
+ const result = await routeHandler.handler(ctx);
56
+
57
+ if (diesel.hasPostHandlerHook && diesel.hooks.postHandler) {
58
+ await diesel.hooks.postHandler(ctx);
59
+ }
60
+ if (diesel.hasOnSendHook && diesel.hooks.onSend) {
61
+ const hookResponse = await diesel.hooks.onSend(ctx, result);
62
+ if (hookResponse) return hookResponse;
63
+ }
64
+ return result ?? generateErrorResponse(204, "No response from this handler");
65
+ }
66
+
67
+ ]
68
+
69
+ for (let i = 0; i < pipeline.length; i++) {
70
+ const result = await pipeline[i]();
71
+ if (result) return result;
72
+ }
73
+ }