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 +0 -2
- package/examples/logger.ts +16 -0
- package/httplocalhost3001vader.jpg +0 -0
- package/index.ts +2 -1
- package/lib/logger/color.ts +36 -0
- package/lib/logger/logger.d.ts +8 -0
- package/lib/logger/logger.ts +80 -0
- package/lib/router/router.ts +21 -7
- package/package.json +1 -1
- package/tests/router.test.ts +3 -1
- package/tests/static.test.sh +4 -1
package/README.md
CHANGED
|
@@ -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
|
@@ -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 }
|
package/lib/router/router.ts
CHANGED
|
@@ -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
|
-
|
|
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 (
|
|
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
package/tests/router.test.ts
CHANGED
|
@@ -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
|
+
});
|