bun-router 0.5.8 → 0.6.0
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/examples/basic.ts +3 -3
- package/examples/cookies.ts +15 -0
- package/examples/dynamic.ts +6 -6
- package/examples/logger.ts +2 -2
- package/examples/sqlite.ts +2 -2
- package/examples/todo.ts +3 -3
- package/lib/http/generic-methods.ts +10 -11
- package/lib/router/router.d.ts +10 -5
- package/lib/router/router.ts +20 -5
- package/package.json +1 -1
package/examples/basic.ts
CHANGED
|
@@ -2,17 +2,17 @@ import { router, http } from '..';
|
|
|
2
2
|
|
|
3
3
|
const r = router();
|
|
4
4
|
|
|
5
|
-
r.add('/', 'GET', () => http.json('ok'));
|
|
5
|
+
r.add('/', 'GET', () => http.json(200, 'ok'));
|
|
6
6
|
|
|
7
7
|
r.add('/user/:name', 'GET', (ctx) => {
|
|
8
8
|
const name = ctx.params.get('name');
|
|
9
|
-
return http.json(name);
|
|
9
|
+
return http.json(200, name);
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
r.add('/user/:name/:id', 'GET', (ctx) => {
|
|
13
13
|
const name = ctx.params.get('name');
|
|
14
14
|
const id = ctx.params.get('id');
|
|
15
|
-
return http.json({name: name, id: id});
|
|
15
|
+
return http.json(200, {name: name, id: id});
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
r.serve();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { router } from '..';
|
|
2
|
+
|
|
3
|
+
const r = router();
|
|
4
|
+
|
|
5
|
+
r.add('/set-cookie', 'GET', ctx => {
|
|
6
|
+
ctx.cookies.set('domain', 'localhost');
|
|
7
|
+
ctx.cookies.set('path', '/set-cookie');
|
|
8
|
+
|
|
9
|
+
ctx.logger.message(ctx.token ?? 'no token provided');
|
|
10
|
+
|
|
11
|
+
return ctx.json( 200, {message: 'cookie stored'});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
r.serve();
|
package/examples/dynamic.ts
CHANGED
|
@@ -3,20 +3,20 @@ import { Context } from '../lib/router/router.d';
|
|
|
3
3
|
|
|
4
4
|
const handler = (ctx: Context) => {
|
|
5
5
|
const name = ctx.params.get('name');
|
|
6
|
-
if (typeof name === 'undefined' || name === '') return http.html('<h6 style="color: red">User Undefined</h6>');
|
|
7
|
-
return http.html(`<h4>Hello, ${name}!</h4>`);
|
|
6
|
+
if (typeof name === 'undefined' || name === '') return http.html(500, '<h6 style="color: red">User Undefined</h6>');
|
|
7
|
+
return http.html(200, `<h4>Hello, ${name}!</h4>`);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
const space = (ctx: Context) => {
|
|
11
11
|
const name = ctx.params.get('name');
|
|
12
|
-
if (typeof name === 'undefined' || name === '') return http.html(`<h6 style="color: red">Space [${name}] Not Found</h6>`);
|
|
13
|
-
return http.html(`<h4>Welcome to ${name}!`)
|
|
12
|
+
if (typeof name === 'undefined' || name === '') return http.html(404, `<h6 style="color: red">Space [${name}] Not Found</h6>`);
|
|
13
|
+
return http.html(200, `<h4>Welcome to ${name}!`)
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
const handleSettings = (ctx: Context) => {
|
|
17
17
|
const name = ctx.params.get('name');
|
|
18
|
-
if (typeof name === 'undefined' || name === '') return http.html(`<h6 style="color: red">User Not Found</h6>`);
|
|
19
|
-
return http.html(`<h4>Settings for ${name}</h4>`)
|
|
18
|
+
if (typeof name === 'undefined' || name === '') return http.html(404, `<h6 style="color: red">User Not Found</h6>`);
|
|
19
|
+
return http.html(200, `<h4>Settings for ${name}</h4>`)
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
const r = router();
|
package/examples/logger.ts
CHANGED
|
@@ -8,9 +8,9 @@ r.add('/:foo', 'GET', (ctx) => {
|
|
|
8
8
|
const foo = ctx.params.get('foo');
|
|
9
9
|
if (!foo) {
|
|
10
10
|
log.error(500, url.pathname, ctx.request.method, new Error('undefined'));
|
|
11
|
-
return http.json(
|
|
11
|
+
return http.json(500,{text: 'Foo is undefined'});
|
|
12
12
|
}
|
|
13
|
-
return http.html(`<h4 style='font-family: sans-serif;'>Oh hello, ${foo}</h4>`)
|
|
13
|
+
return http.html(200, `<h4 style='font-family: sans-serif;'>Oh hello, ${foo}</h4>`)
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
r.serve();
|
package/examples/sqlite.ts
CHANGED
|
@@ -8,7 +8,7 @@ r.add('/u/new/:name', 'GET', (ctx) => {
|
|
|
8
8
|
|
|
9
9
|
ctx.db.run(`INSERT INTO test VALUES(${rando}, "${name}")`);
|
|
10
10
|
|
|
11
|
-
return http.json({message: 'ok'});
|
|
11
|
+
return http.json(200, {message: 'ok'});
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
r.add('/u/:name', 'GET', (ctx) => {
|
|
@@ -16,7 +16,7 @@ r.add('/u/:name', 'GET', (ctx) => {
|
|
|
16
16
|
const data = ctx.db.query(`SELECT * FROM test WHERE name = "${name}";`).get();
|
|
17
17
|
const d = data as {id: number, name: string};
|
|
18
18
|
|
|
19
|
-
return d ? http.json(d) : new Response('not found', {status: 404});
|
|
19
|
+
return d ? http.json(200, d) : new Response('not found', {status: 404});
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
r.serve();
|
package/examples/todo.ts
CHANGED
|
@@ -26,7 +26,7 @@ r.add('/api/new', 'POST', ctx => {
|
|
|
26
26
|
ctx.logger.message(`Adding ${key} with ${content}`);
|
|
27
27
|
todo.add(key, content);
|
|
28
28
|
|
|
29
|
-
return ctx.json({ message: 'ok' });
|
|
29
|
+
return ctx.json(200, { message: 'ok' });
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
r.add('/api/todo/:key', 'GET', ctx => {
|
|
@@ -36,11 +36,11 @@ r.add('/api/todo/:key', 'GET', ctx => {
|
|
|
36
36
|
const content = todo.get(key);
|
|
37
37
|
if (!content) return http.notFound();
|
|
38
38
|
|
|
39
|
-
return ctx.json({key: key, content: content});
|
|
39
|
+
return ctx.json(200, {key: key, content: content});
|
|
40
40
|
});
|
|
41
41
|
|
|
42
42
|
r.add('/api/get/all', 'GET', ctx => {
|
|
43
|
-
return ctx.json(todo.export());
|
|
43
|
+
return ctx.json(200, todo.export());
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
r.serve();
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { httpStatusCodes } from "./status";
|
|
2
2
|
|
|
3
3
|
const http = {
|
|
4
|
-
json: async (data: any): Promise<Response> => {
|
|
4
|
+
json: async (statusCode: number, data: any): Promise<Response> => {
|
|
5
5
|
const jsonString = JSON.stringify(data);
|
|
6
6
|
return Promise.resolve(new Response(jsonString, {
|
|
7
|
-
status:
|
|
8
|
-
statusText: httpStatusCodes[
|
|
7
|
+
status: statusCode,
|
|
8
|
+
statusText: httpStatusCodes[statusCode],
|
|
9
9
|
headers: {'Content-Type': 'application/json'},
|
|
10
10
|
}));
|
|
11
11
|
},
|
|
12
|
-
html: async (content: string): Promise<Response> => {
|
|
12
|
+
html: async (statusCode: number, content: string): Promise<Response> => {
|
|
13
13
|
content = Bun.escapeHTML(content);
|
|
14
14
|
return Promise.resolve(new Response(Bun.escapeHTML(content), {
|
|
15
|
-
status:
|
|
16
|
-
statusText: httpStatusCodes[
|
|
15
|
+
status: statusCode,
|
|
16
|
+
statusText: httpStatusCodes[statusCode],
|
|
17
17
|
headers: {'Content-Type': 'text/html; charset=utf-8'}
|
|
18
18
|
}));
|
|
19
19
|
},
|
|
20
|
-
file: async (fp: string): Promise<Response> => {
|
|
20
|
+
file: async (statusCode: number, fp: string): Promise<Response> => {
|
|
21
21
|
const file = Bun.file(fp);
|
|
22
22
|
const exists = await file.exists();
|
|
23
23
|
|
|
@@ -32,8 +32,8 @@ const http = {
|
|
|
32
32
|
contentType = file.type + '; charset=utf-8';
|
|
33
33
|
|
|
34
34
|
return Promise.resolve(new Response(content, {
|
|
35
|
-
status:
|
|
36
|
-
statusText: httpStatusCodes[
|
|
35
|
+
status: statusCode,
|
|
36
|
+
statusText: httpStatusCodes[statusCode],
|
|
37
37
|
headers: { 'Content-Type': contentType}
|
|
38
38
|
}));
|
|
39
39
|
},
|
|
@@ -57,8 +57,7 @@ const http = {
|
|
|
57
57
|
headers: {'Content-Type': 'text/html; charset-utf-8'},
|
|
58
58
|
});
|
|
59
59
|
return Promise.resolve(response)
|
|
60
|
-
}
|
|
61
|
-
|
|
60
|
+
},
|
|
62
61
|
}
|
|
63
62
|
|
|
64
63
|
export { http }
|
package/lib/router/router.d.ts
CHANGED
|
@@ -4,14 +4,18 @@ import { Database } from 'bun:sqlite';
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
type Context = {
|
|
7
|
+
cookies: Map<string, string>,
|
|
8
|
+
db: Database,
|
|
9
|
+
formData: FormData | Promise<FormData> | undefined,
|
|
10
|
+
json: (statusCode: number, data: any) => Response | Promise<Response>,
|
|
11
|
+
logger: Logger,
|
|
12
|
+
params: Map<string, string>,
|
|
13
|
+
query: URLSearchParams,
|
|
7
14
|
request: Request,
|
|
8
15
|
route: Route,
|
|
9
|
-
params: Map<string, string>,
|
|
10
16
|
token?: string,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
json: (data: any) => Response | Promise<Response>,
|
|
14
|
-
}
|
|
17
|
+
};
|
|
18
|
+
|
|
15
19
|
|
|
16
20
|
type Route = {
|
|
17
21
|
pattern: string,
|
|
@@ -39,4 +43,5 @@ type Router = (port?: number | string, options?: RouterOptions) => {
|
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
|
|
46
|
+
|
|
42
47
|
export { Context , Route, Router, RouterOptions, Options }
|
package/lib/router/router.ts
CHANGED
|
@@ -48,20 +48,24 @@ const match = (route: Route, ctx: Context): boolean => {
|
|
|
48
48
|
|
|
49
49
|
// set the context for the reuest
|
|
50
50
|
const setContext = (req: Request, lgr: Logger, opts: Options, route: Route): Context => {
|
|
51
|
+
const token = req.headers.get('Authorization');
|
|
51
52
|
return {
|
|
53
|
+
token: token ?? '',
|
|
54
|
+
cookies: new Map(),
|
|
55
|
+
formData: req.formData(),
|
|
52
56
|
request: req,
|
|
53
57
|
params: new Map(),
|
|
58
|
+
query: new URL(req.url).searchParams,
|
|
54
59
|
db: new Database(opts.db ?? ':memory:'),
|
|
55
60
|
logger: lgr,
|
|
56
61
|
route: route,
|
|
57
|
-
json: (data: any) => http.json(data),
|
|
62
|
+
json: (statusCode: number, data: any) => http.json(statusCode, data),
|
|
58
63
|
}
|
|
59
64
|
}
|
|
60
65
|
|
|
61
66
|
const router: Router = (port?: number | string, options?: RouterOptions<Options>) => {
|
|
62
67
|
const routes: Array<Route> = new Array();
|
|
63
68
|
const lgr = logger();
|
|
64
|
-
let dbConn = '';
|
|
65
69
|
|
|
66
70
|
return {
|
|
67
71
|
// add a new route
|
|
@@ -105,7 +109,7 @@ const router: Router = (port?: number | string, options?: RouterOptions<Options>
|
|
|
105
109
|
const route: Route = {
|
|
106
110
|
pattern: patternPath,
|
|
107
111
|
method: 'GET',
|
|
108
|
-
callback: async () => await http.file(pure),
|
|
112
|
+
callback: async () => await http.file(200, pure),
|
|
109
113
|
};
|
|
110
114
|
|
|
111
115
|
routes.push(route);
|
|
@@ -135,18 +139,29 @@ const router: Router = (port?: number | string, options?: RouterOptions<Options>
|
|
|
135
139
|
if (match(route, ctx) || route.pattern === url.pathname) {
|
|
136
140
|
if (route.method === ctx.request.method) {
|
|
137
141
|
const res = await route.callback(ctx);
|
|
142
|
+
|
|
143
|
+
let cookieValue: string[] = [];
|
|
144
|
+
if (ctx.cookies.size !== 0) {
|
|
145
|
+
for (const [key, value] of ctx.cookies) {
|
|
146
|
+
cookieValue.push(`${key}=${value}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
res.headers.set('Set-Cookie', cookieValue.join('; '));
|
|
151
|
+
|
|
138
152
|
statusCode = res.status;
|
|
153
|
+
|
|
139
154
|
lgr.info(res.status, route.pattern, req.method, httpStatusCodes[res.status]);
|
|
140
155
|
return Promise.resolve(res);
|
|
141
156
|
} else {
|
|
142
157
|
const res = new Response(httpStatusCodes[405], {
|
|
143
158
|
status: 405,
|
|
144
|
-
statusText: httpStatusCodes[
|
|
159
|
+
statusText: httpStatusCodes[405]
|
|
145
160
|
});
|
|
146
161
|
lgr.info(405, route.pattern, req.method, httpStatusCodes[405])
|
|
147
162
|
return Promise.resolve(res);
|
|
148
163
|
}
|
|
149
|
-
}
|
|
164
|
+
}
|
|
150
165
|
}
|
|
151
166
|
|
|
152
167
|
lgr.info(statusCode, url.pathname, req.method, httpStatusCodes[statusCode]);
|
package/package.json
CHANGED