0http-bun 0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 BackendStack21.js
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # Introduction
2
+ Experimental, bun-based HTTP framework inspired by 0http!
3
+
4
+ ## Usage
5
+ ```js
6
+ const http = require('0http-bun')
7
+
8
+ const { router } = http({})
9
+ router.use((req, next) => {
10
+ req.ctx = {
11
+ engine: 'bun'
12
+ }
13
+
14
+ return next()
15
+ })
16
+ router.get('/:id', async (req) => {
17
+ return Response.json(req.params)
18
+ })
19
+ router.post('/', async (req) => {
20
+ return new Response('POST')
21
+ })
22
+ router.delete('/:id', async (req) => {
23
+ return Response.json(req.params, {
24
+ status: 200
25
+ })
26
+ })
27
+
28
+ module.exports = {
29
+ port: 3000,
30
+ fetch: (request) => router.lookup(request)
31
+ }
32
+ ```
33
+
34
+ # Support / Donate 💚
35
+ You can support the maintenance of this project:
36
+ - PayPal: https://www.paypal.me/kyberneees
package/demos/basic.js ADDED
@@ -0,0 +1,27 @@
1
+ /* global Response */
2
+ const http = require('../index')
3
+
4
+ const { router } = http({})
5
+ router.use((req, next) => {
6
+ req.ctx = {
7
+ engine: 'bun'
8
+ }
9
+
10
+ return next()
11
+ })
12
+ router.get('/:id', async (req) => {
13
+ return Response.json(req.params)
14
+ })
15
+ router.post('/', async (req) => {
16
+ return new Response('POST')
17
+ })
18
+ router.delete('/:id', async (req) => {
19
+ return Response.json(req.params, {
20
+ status: 200
21
+ })
22
+ })
23
+
24
+ module.exports = {
25
+ port: 3000,
26
+ fetch: (request) => router.lookup(request)
27
+ }
package/index.js ADDED
@@ -0,0 +1,7 @@
1
+ module.exports = (config = {}) => {
2
+ const router = config.router || require('./lib/router/sequential')(config)
3
+
4
+ return {
5
+ router
6
+ }
7
+ }
package/lib/next.js ADDED
@@ -0,0 +1,35 @@
1
+ module.exports = function next (middlewares, req, index, routers = {}, defaultRoute, errorHandler) {
2
+ const middleware = middlewares[index]
3
+ if (!middleware) {
4
+ return defaultRoute(req)
5
+ }
6
+
7
+ function step (err) {
8
+ if (err) {
9
+ return errorHandler(err, req)
10
+ } else {
11
+ return next(middlewares, req, index + 1, routers, defaultRoute, errorHandler)
12
+ }
13
+ }
14
+
15
+ try {
16
+ if (middleware.id) {
17
+ // nested routes support
18
+ const pattern = routers[middleware.id]
19
+ if (pattern) {
20
+ req.preRouterPath = req.path
21
+
22
+ req.path = req.path.replace(pattern, '')
23
+ if (!req.path.startsWith('/')) {
24
+ req.path = '/' + req.path
25
+ }
26
+ }
27
+
28
+ return middleware.lookup(req, step)
29
+ } else {
30
+ return middleware(req, step)
31
+ }
32
+ } catch (err) {
33
+ return errorHandler(err, req)
34
+ }
35
+ }
@@ -0,0 +1,104 @@
1
+ /* global Response */
2
+
3
+ const Trouter = require('trouter')
4
+ const next = require('./../next')
5
+ const LRU = require('lru-cache')
6
+ const { parse } = require('regexparam')
7
+
8
+ module.exports = (config = {}) => {
9
+ if (config.defaultRoute === undefined) {
10
+ config.defaultRoute = (req) => {
11
+ const res = new Response(null, {
12
+ status: 404
13
+ })
14
+
15
+ return res
16
+ }
17
+ }
18
+ if (config.errorHandler === undefined) {
19
+ config.errorHandler = (err, req) => {
20
+ const res = new Response(err.message, {
21
+ status: 500
22
+ })
23
+
24
+ return res
25
+ }
26
+ }
27
+ if (config.cacheSize === undefined) {
28
+ config.cacheSize = 1000
29
+ }
30
+ if (config.id === undefined) {
31
+ config.id = (Date.now().toString(36) + Math.random().toString(36).substring(2, 5)).toUpperCase()
32
+ }
33
+
34
+ const routers = {}
35
+ const isCacheEnabled = config.cacheSize > 0
36
+ const cache = isCacheEnabled ? new LRU({ max: config.cacheSize }) : null
37
+ const router = new Trouter()
38
+ router.id = config.id
39
+
40
+ const _use = router.use
41
+
42
+ router.use = (prefix, ...middlewares) => {
43
+ if (typeof prefix === 'function') {
44
+ middlewares = [prefix, ...middlewares]
45
+ prefix = '/'
46
+ }
47
+ _use.call(router, prefix, middlewares)
48
+
49
+ if (middlewares[0].id) {
50
+ // caching router -> pattern relation for urls pattern replacement
51
+ const { pattern } = parse(prefix, true)
52
+ routers[middlewares[0].id] = pattern
53
+ }
54
+
55
+ return this
56
+ }
57
+
58
+ router.lookup = async (req, step) => {
59
+ const url = new URL(req.url)
60
+ req.path = url.pathname || '/'
61
+ req.query = url.queryparams
62
+ req.search = url.search
63
+ req.hostname = url.hostname
64
+
65
+ let match
66
+ if (isCacheEnabled) {
67
+ const reqCacheKey = req.method + req.path
68
+ match = cache.get(reqCacheKey)
69
+ if (!match) {
70
+ match = router.find(req.method, req.path)
71
+ cache.set(reqCacheKey, match)
72
+ }
73
+ } else {
74
+ match = router.find(req.method, req.path)
75
+ }
76
+
77
+ if (match.handlers.length !== 0) {
78
+ const middlewares = [...match.handlers]
79
+ if (step !== undefined) {
80
+ // router is being used as a nested router
81
+ middlewares.push((req, next) => {
82
+ req.path = req.preRouterPath
83
+
84
+ delete req.preRouterPath
85
+
86
+ return step()
87
+ })
88
+ }
89
+
90
+ if (!req.params) {
91
+ req.params = {}
92
+ }
93
+ Object.assign(req.params, match.params)
94
+
95
+ return next(middlewares, req, 0, routers, config.defaultRoute, config.errorHandler)
96
+ } else {
97
+ return config.defaultRoute(req)
98
+ }
99
+ }
100
+
101
+ router.on = (method, pattern, ...handlers) => router.add(method, pattern, handlers)
102
+
103
+ return router
104
+ }
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "0http-bun",
3
+ "version": "0.0.1",
4
+ "description": "0http alternative for Bun",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "dependencies": {
10
+ "lru-cache": "^7.10.1",
11
+ "regexparam": "^2.0.0",
12
+ "trouter": "^3.2.0"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/BackendStack21/0http-bun.git"
17
+ },
18
+ "keywords": [
19
+ "http",
20
+ "server",
21
+ "rest",
22
+ "api",
23
+ "web",
24
+ "bun"
25
+ ],
26
+ "author": "Rolando Santamaria Maso <kyberneees@gmail.com>",
27
+ "license": "MIT",
28
+ "bugs": {
29
+ "url": "https://github.com/BackendStack21/0http-bun/issues"
30
+ },
31
+ "homepage": "https://github.com/BackendStack21/0http-bun#readme"
32
+ }