bun-router 0.3.0 → 0.3.4

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/README.md CHANGED
@@ -29,8 +29,6 @@ import {router, html, json } from 'bun-router';
29
29
 
30
30
  const r = router(3001);
31
31
 
32
- r.static('/assets', './assets');
33
-
34
32
  r.add('/', (ctx) => html('<h1>Hello World</h1>'));
35
33
 
36
34
  r.add('/greeting/:name', 'GET', (ctx) => {
@@ -0,0 +1,16 @@
1
+ import { router, logger, json, html } from '..';
2
+
3
+ const r = router();
4
+ const log = logger();
5
+
6
+ r.add('/:foo', 'GET', (ctx) => {
7
+ const url = new URL(ctx.request.url);
8
+ const foo = ctx.params.get('foo');
9
+ if (!foo) {
10
+ log.error(500, url.pathname, ctx.request.method, new Error('undefined'));
11
+ return json({status: 500, text: 'Foo is undefined'});
12
+ }
13
+ return html(`<h4 style='font-family: sans-serif;'>Oh hello, ${foo}</h4>`)
14
+ });
15
+
16
+ r.serve();
Binary file
package/index.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './lib/router/router';
2
- export * from './lib/fs/fsys';
2
+ export * from './lib/fs/fsys';
3
+ export * from './lib/logger/logger';
@@ -0,0 +1,36 @@
1
+ const Colors: Record<string,string> = {
2
+ reset: "\x1b[0m",
3
+
4
+ // foreground
5
+ black: "\x1b[30m",
6
+ red: "\x1b[31m",
7
+ green: "\x1b[32m",
8
+ yellow: "\x1b[33m",
9
+ blue: "\x1b[34m",
10
+ magenta: "\x1b[35m",
11
+ cyan: "\x1b[36m",
12
+ white: "\x1b[37m",
13
+
14
+ // background
15
+ bgBlack: "\x1b[40m",
16
+ bgRed: "\x1b[41m",
17
+ bgGreen: "\x1b[42m",
18
+ bgYellow: "\x1b[43m",
19
+ bgBlue: "\x1b[44m",
20
+ bgMagenta: "\x1b[45m",
21
+ bgCyan: "\x1b[46m",
22
+ bgWhite: "\x1b[47m",
23
+ };
24
+
25
+
26
+ const color = (c: string, bkg: string, msg: string) => {
27
+ const foreground = Colors[c];
28
+ const background = Colors[bkg];
29
+ const reset = Colors.reset;
30
+
31
+ return `${foreground}${background}${msg}${reset}`;
32
+ };
33
+
34
+
35
+
36
+ export { color }
@@ -0,0 +1,8 @@
1
+ type Logger = {
2
+ start: (port: number | string) => void,
3
+ info: (statusCode: number, routePath: string, method: string, message?: string) => void,
4
+ error: (statusCode: number, routePath: string, method: string, error: Error) => void,
5
+ warn: (msg: string) => void,
6
+ }
7
+
8
+ export { Logger }
@@ -0,0 +1,80 @@
1
+ import { color } from './color';
2
+ import {Logger} from './logger.d';
3
+
4
+ const pad = (n: number) => String(n).padStart(2, '0');
5
+
6
+ const timestamp = (date: Date) => {
7
+ const month = pad(date.getMonth());
8
+ const day = pad(date.getDate());
9
+ const hour = pad(date.getHours());
10
+ const minute = pad(date.getMinutes());
11
+ const seconds = pad(date.getSeconds());
12
+ const stamp = `${hour}:${minute}:${seconds}`;
13
+
14
+ return {month, day, hour, minute, stamp};
15
+ }
16
+
17
+ const colorCode = (n: number, text?:string): string => {
18
+ const s = ` [${String(n)}${text ?? ''}] `;
19
+ if (n < 100) return color('black', 'bgYellow', s);
20
+ else if (n >= 100 && n < 200) return color('black', 'bgCyan', s);
21
+ else if (n >= 200 && n < 300) return color('black', 'bgGreen', s);
22
+ else if (n >= 300 && n < 400) return color('black', 'bgRed', s);
23
+ else if (n >= 400 && n < 500) return color('black', 'bgRed', s);
24
+ else if (n >= 500) return color('white', 'bgRed', s);
25
+ return color('white', 'bgBlack', `[${s}]`).trim();
26
+ }
27
+
28
+ const clean = (s: string) => s.replace(/\x1B\[\d{1,2}(;\d{1,2}){0,2}m/g, '');
29
+
30
+ const format = (statusCode: number, routePath: string, method: string, message?: string): string => {
31
+ const { stamp } = timestamp((new Date(Date.now())));
32
+ const source = color('green', 'bgBlack', `[bun-router ${stamp}]`);
33
+ const rp = color('white', 'bgBlack', routePath);
34
+
35
+ return `${source} : ${colorCode(statusCode)} : ${rp} ${(method === 'GET') ? '->' : '<-'} ${method}\n`
36
+ }
37
+
38
+ const logger = (): Logger => {
39
+ const messages: string[] = [];
40
+ const errors: string[] = [];
41
+ return {
42
+ start: async (port: number | string) => {
43
+ const { stamp } = timestamp((new Date(Date.now())));
44
+ const source = color('green', 'bgBlack', `[bun-router ${stamp}]`)
45
+ const portColor = color('green', 'bgBlack', String(port));
46
+ const msg = `${source}: Starting Server on :${portColor}\n`;
47
+
48
+ await Bun.write(Bun.stdout, msg);
49
+ },
50
+ info: async (statusCode: number, routePath: string, method: string, message?: string) => {
51
+ const { stamp } = timestamp((new Date(Date.now())));
52
+ const source = color('green', 'bgBlack', `[bun-router ${stamp}]`);
53
+ const rp = color('white', 'bgBlack', routePath);
54
+ const msg = `${source}: ${colorCode(statusCode)}: ${rp} ${(method === 'GET') ? '->' : '<-'} ${method}\n`
55
+
56
+ await Bun.write(Bun.stdout, msg);
57
+
58
+ messages.push(clean(msg));
59
+ },
60
+ error: async (statusCode: number, routePath: string, method: string, error: Error) => {
61
+ const { stamp } = timestamp((new Date(Date.now())));
62
+ const source = color('black', 'bgRed', `[error ${stamp}]`);
63
+ const rp = color('white', 'bgBlack', routePath);
64
+ const msg = `${source}: ${colorCode(statusCode)}: ${rp} ${(method === 'GET') ? '->' : '<-'} ${error.message}\n`;
65
+
66
+ await Bun.write(Bun.stdout, msg);
67
+
68
+ errors.push(clean(msg));
69
+ },
70
+ warn: async (msg: string) => {
71
+ const { stamp } = timestamp((new Date(Date.now())));
72
+ const source = color('black', 'bgYellow', `[warning ${stamp}]`);
73
+ const msgColor = color('yellow', 'bgBlack', msg);
74
+ msg = `${source} : ${msgColor}\n`;
75
+ await Bun.write(Bun.stdout, msg);
76
+ }
77
+ }
78
+ }
79
+
80
+ export { logger }
@@ -1,5 +1,6 @@
1
1
  import { Route, Router, Context, Options } from './router.d';
2
2
  import { readDir } from '../fs/fsys';
3
+ import { logger } from '../logger/logger';
3
4
  import path from 'path';
4
5
 
5
6
  const notFound = async (): Promise<Response> => {
@@ -14,6 +15,17 @@ const notFound = async (): Promise<Response> => {
14
15
  });
15
16
  }
16
17
 
18
+ const noContent = async (): Promise<Response> => {
19
+ const response = new Response('no content', {
20
+ status: 204,
21
+ statusText: 'no content',
22
+ });
23
+
24
+ return new Promise((resolve) => {
25
+ resolve(response);
26
+ });
27
+ }
28
+
17
29
  const file = async (filepath: string): Promise<Response> => {
18
30
  const file = Bun.file(filepath);
19
31
  const exists = await file.exists();
@@ -93,6 +105,7 @@ const match = (route: Route, ctx: Context): boolean => {
93
105
  const router: Router = (port?: number | string, options?: Options) => {
94
106
  const routes: Array<Route> = new Array();
95
107
  const paths: { [key: string]: string } = {};
108
+ const lgr = logger();
96
109
 
97
110
  return {
98
111
  add: (pattern: string, method: string, callback: (ctx: Context) => Response | Promise<Response>) => {
@@ -114,15 +127,12 @@ const router: Router = (port?: number | string, options?: Options) => {
114
127
 
115
128
  }
116
129
 
117
- console.log((pattern[0] != '/'))
118
130
  if (pattern[0] !== '/') pattern = '/' + pattern;
119
131
 
120
132
  let patternPath = pattern + base;
121
133
 
122
134
  if (base === 'index') patternPath = pattern;
123
135
 
124
- console.log(patternPath);
125
-
126
136
  const route: Route = {
127
137
  pattern: patternPath,
128
138
  method: 'GET',
@@ -130,15 +140,14 @@ const router: Router = (port?: number | string, options?: Options) => {
130
140
  };
131
141
  routes.push(route);
132
142
  });
133
- console.log(routes.length);
134
-
135
143
  },
136
144
  serve: () => {
137
- console.log(`[bun-router]: Listening on port -> :${port ?? 3000}`)
145
+ lgr.start(port ?? 3000);
138
146
  Bun.serve({
139
147
  port: port ?? 3000,
140
148
  ...options,
141
149
  fetch(req) {
150
+ const url = new URL(req.url);
142
151
  for (const route of routes) {
143
152
  const ctx: Context = {
144
153
  request: req,
@@ -150,9 +159,14 @@ const router: Router = (port?: number | string, options?: Options) => {
150
159
 
151
160
  extractor?.params();
152
161
 
153
- if (match(route, ctx))
162
+ if (url.pathname === '/favicon.ico') return noContent();
163
+
164
+ if (match(route, ctx)) {
165
+ lgr.info(200, route.pattern, route.method)
154
166
  return route.callback(ctx);
167
+ }
155
168
  }
169
+ lgr.info(404, url.pathname, req.method, 'not found');
156
170
  return new Response('not found');
157
171
  }
158
172
  });
package/package.json CHANGED
@@ -8,5 +8,5 @@
8
8
  "peerDependencies": {
9
9
  "typescript": "^5.0.0"
10
10
  },
11
- "version": "0.3.0"
11
+ "version": "0.3.4"
12
12
  }
@@ -1,6 +1,8 @@
1
1
  import { describe, test, expect } from 'bun:test';
2
2
  import { router, extract } from '..';
3
3
  import { Context, Route } from '../lib/router/router.d';
4
+ import { logger } from '../lib/logger/logger';
5
+ import { color } from '../lib/logger/color';
4
6
 
5
7
  describe('URL Params', () => {
6
8
  test('/user/:name', () => {
@@ -98,4 +100,4 @@ describe('Router', () => {
98
100
 
99
101
  proc.kill(0);
100
102
  });
101
- });
103
+ });
@@ -46,7 +46,10 @@ function run_test() {
46
46
  echo "Failed: $url returned $actual | expected: $expected"
47
47
  fi
48
48
 
49
- rm "$name"
49
+ if does_exist "$name"; then
50
+ rm "$name"
51
+ fi
52
+
50
53
  }
51
54
 
52
55
  for expected in "${!test_cases[@]}"; do