bun-router 0.5.4 → 0.5.5

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 CHANGED
@@ -1,18 +1,18 @@
1
- import { router, html, json } from '..';
1
+ import { router, http } from '..';
2
2
 
3
3
  const r = router();
4
4
 
5
- r.add('/', 'GET', () => json('ok'));
5
+ r.add('/', 'GET', () => http.json('ok'));
6
6
 
7
7
  r.add('/user/:name', 'GET', (ctx) => {
8
8
  const name = ctx.params.get('name');
9
- return json(name);
9
+ return http.json(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 json({name: name, id: id});
15
+ return http.json({name: name, id: id});
16
16
  });
17
17
 
18
18
  r.serve();
@@ -1,22 +1,22 @@
1
- import { router, html } from '..';
1
+ import { router, http } from '..';
2
2
  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 html('<h6 style="color: red">User Undefined</h6>');
7
- return html(`<h4>Hello, ${name}!</h4>`);
6
+ if (typeof name === 'undefined' || name === '') return http.html('<h6 style="color: red">User Undefined</h6>');
7
+ return http.html(`<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 html(`<h6 style="color: red">Space [${name}] Not Found</h6>`);
13
- return html(`<h4>Welcome to ${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}!`)
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 html(`<h6 style="color: red">User Not Found</h6>`);
19
- return html(`<h4>Settings for ${name}</h4>`)
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>`)
20
20
  }
21
21
 
22
22
  const r = router();
@@ -1,4 +1,4 @@
1
- import { router, logger, json, html } from '..';
1
+ import { router, logger, http } from '..';
2
2
 
3
3
  const r = router();
4
4
  const log = logger();
@@ -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 json({status: 500, text: 'Foo is undefined'});
11
+ return http.json({status: 500, text: 'Foo is undefined'});
12
12
  }
13
- return html(`<h4 style='font-family: sans-serif;'>Oh hello, ${foo}</h4>`)
13
+ return http.html(`<h4 style='font-family: sans-serif;'>Oh hello, ${foo}</h4>`)
14
14
  });
15
15
 
16
16
  r.serve();
@@ -1,4 +1,4 @@
1
- import { router, json } from '..';
1
+ import { router, http } from '..';
2
2
 
3
3
  const r = router(3000, {db: './examples/dbs/test.db'});
4
4
 
@@ -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 json({message: 'ok'});
11
+ return http.json({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 ? json(d) : new Response('not found', {status: 404});
19
+ return d ? http.json(d) : new Response('not found', {status: 404});
20
20
  });
21
21
 
22
22
  r.serve();
@@ -0,0 +1,64 @@
1
+ import { httpStatusCodes } from "./status";
2
+
3
+ const http = {
4
+ json: async (data: any): Promise<Response> => {
5
+ const jsonString = JSON.stringify(data);
6
+ return Promise.resolve(new Response(jsonString, {
7
+ status: 200,
8
+ statusText: httpStatusCodes[200],
9
+ headers: {'Content-Type': 'application/json'},
10
+ }));
11
+ },
12
+ html: async (content: string): Promise<Response> => {
13
+ content = Bun.escapeHTML(content);
14
+ return Promise.resolve(new Response(Bun.escapeHTML(content), {
15
+ status: 200,
16
+ statusText: httpStatusCodes[200],
17
+ headers: {'Content-Type': 'text/html; charset=utf-8'}
18
+ }));
19
+ },
20
+ file: async (fp: string): Promise<Response> => {
21
+ const file = Bun.file(fp);
22
+ const exists = await file.exists();
23
+
24
+ if (!exists) return http.notFound(`File not found: ${fp}`);
25
+
26
+ const content = await file.arrayBuffer();
27
+ if (!content) return http.noContent();
28
+
29
+ let contentType = 'text/html; charset=utf-9';
30
+
31
+ if (file.type.includes('image'))
32
+ contentType = file.type + '; charset=utf-8';
33
+
34
+ return Promise.resolve(new Response(content, {
35
+ status: 200,
36
+ statusText: httpStatusCodes[200],
37
+ headers: { 'Content-Type': contentType}
38
+ }));
39
+ },
40
+ noContent: async (): Promise<Response> => Promise.resolve(new Response('no content', {
41
+ status: 204,
42
+ statusText: 'no content',
43
+ })),
44
+ notFound: async(msg?: string): Promise<Response> => {
45
+ const response = new Response(msg ?? 'not found', {
46
+ status: 404,
47
+ statusText: httpStatusCodes[404],
48
+ headers: {'Content-Type': 'text/html'},
49
+ });
50
+
51
+ return Promise.resolve(response);
52
+ },
53
+ message: async (status: number, msg?: string): Promise<Response> => {
54
+ const response = new Response(msg ?? '?', {
55
+ status: status,
56
+ statusText: httpStatusCodes[status],
57
+ headers: {'Content-Type': 'text/html; charset-utf-8'},
58
+ });
59
+ return Promise.resolve(response)
60
+ }
61
+
62
+ }
63
+
64
+ export { http }
@@ -5,100 +5,7 @@ import { readDir } from '../fs/fsys';
5
5
  import { logger } from '../logger/logger';
6
6
  import path from 'path';
7
7
  import { Logger } from '../logger/logger.d';
8
-
9
- // create a generic HTTP response
10
- const httpMessage = async (status: number, msg?: string): Promise<Response> => {
11
- const response = new Response(msg ?? '?', {
12
- status: status,
13
- statusText: msg ?? '?',
14
- headers: { 'Content-Type': 'text/html; charset-uft-8' }
15
- });
16
- return new Promise((resolve) => {
17
- resolve(response);
18
- });
19
- };
20
-
21
- // a generic 'not found' HTTP response
22
- const notFound = async (msg?: string): Promise<Response> => {
23
- const response = new Response(msg ?? 'not found', {
24
- status: 404,
25
- statusText: 'not found',
26
- headers: { 'Content-Type': 'text/html' },
27
- });
28
-
29
- return new Promise((resolve) => {
30
- resolve(response);
31
- });
32
- }
33
-
34
- // a generic 'no content' HTTP response
35
- const noContent = async (): Promise<Response> => {
36
- const response = new Response('no content', {
37
- status: 204,
38
- statusText: 'no content',
39
- });
40
-
41
- return new Promise((resolve) => {
42
- resolve(response);
43
- });
44
- }
45
-
46
- // IO handling
47
- const file = async (filepath: string): Promise<Response> => {
48
- const file = Bun.file(filepath);
49
- const exists = await file.exists();
50
-
51
- // check if the file exists, return 'not found' if it doesn't.
52
- if (!exists)
53
- return notFound(`File not found: ${filepath}`);
54
-
55
- // get the content of the file as an ArrayBuffer
56
- const content = await file.arrayBuffer();
57
- if (!content)
58
- return noContent();
59
-
60
- // default Content-Type + encoding
61
- let contentType = 'text/html; charset=utf-8';
62
-
63
- // change the Content-Type if the file type is an image.
64
- // file.type provides the necessary Content-Type
65
- if (file.type.includes('image')) {
66
- contentType = file.type + '; charset=utf-8';
67
- }
68
-
69
- // create a new response with the necessary criteria
70
- const response = new Response(content, {
71
- status: 200,
72
- statusText: 'ok',
73
- headers: { 'Content-Type': contentType },
74
- });
75
-
76
- return Promise.resolve(response);
77
- }
78
-
79
- // handle strings as HTML
80
- const html = async (content: string): Promise<Response> => {
81
- const response = new Response(content, {
82
- status: 200,
83
- statusText: 'ok',
84
- headers: { 'Content-Type': 'text/html; charset=utf-8' },
85
- });
86
-
87
- // escape the HTML
88
- content = Bun.escapeHTML(content);
89
-
90
- return Promise.resolve(response);
91
- }
92
-
93
- // create a JSON response
94
- const json = (data: any): Response => {
95
- const jsonString = JSON.stringify(data);
96
-
97
- const res = new Response(jsonString);
98
- res.headers.set('Content-Type', 'application/json');
99
-
100
- return res
101
- }
8
+ import { http } from '../http/generic-methods';
102
9
 
103
10
  // extract dynamic URL parameters
104
11
  // if the route pattern is /:foo and the request URL is /bar: {foo: 'bar'}
@@ -139,6 +46,7 @@ const match = (route: Route, ctx: Context): boolean => {
139
46
  return false;
140
47
  }
141
48
 
49
+ // set the context for the reuest
142
50
  const setContext = (req: Request, lgr: Logger, opts: Options): Context => {
143
51
  return {
144
52
  request: req,
@@ -197,7 +105,7 @@ const router: Router = (port?: number | string, options?: RouterOptions<Options>
197
105
  const route: Route = {
198
106
  pattern: patternPath,
199
107
  method: 'GET',
200
- callback: async () => await file(pure),
108
+ callback: async () => await http.file(pure),
201
109
  };
202
110
  routes.push(route);
203
111
  });
@@ -218,13 +126,13 @@ const router: Router = (port?: number | string, options?: RouterOptions<Options>
218
126
  opts.db = o.db;
219
127
  }
220
128
 
221
- let statusCode = 404; // Default status code for route not found
129
+ let statusCode = 404;
222
130
 
223
131
  for (const route of routes) {
224
132
  const ctx = setContext(req, lgr, opts);
225
133
 
226
134
  if (url.pathname === '/favicon.ico') {
227
- return noContent();
135
+ return http.noContent();
228
136
  }
229
137
 
230
138
  if (route.method !== req.method) {
@@ -247,11 +155,11 @@ const router: Router = (port?: number | string, options?: RouterOptions<Options>
247
155
 
248
156
  if (statusCode === 405) {
249
157
  lgr.info(statusCode, url.pathname, req.method, httpStatusCodes[statusCode]);
250
- return httpMessage(statusCode, httpStatusCodes[statusCode]);
158
+ return http.message(statusCode, httpStatusCodes[statusCode]);
251
159
  }
252
160
 
253
161
  lgr.info(statusCode, url.pathname, req.method, httpStatusCodes[statusCode]);
254
- return httpMessage(statusCode, httpStatusCodes[statusCode]);
162
+ return http.message(statusCode, httpStatusCodes[statusCode]);
255
163
 
256
164
  }
257
165
  });
@@ -260,4 +168,4 @@ const router: Router = (port?: number | string, options?: RouterOptions<Options>
260
168
  }
261
169
 
262
170
 
263
- export { router, json, file, extract, html }
171
+ export { router, extract, http }
package/package.json CHANGED
@@ -8,5 +8,5 @@
8
8
  "peerDependencies": {
9
9
  "typescript": "^5.0.0"
10
10
  },
11
- "version": "0.5.4"
11
+ "version": "0.5.5"
12
12
  }