barejs 0.1.3 → 0.1.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/LICENSE +21 -0
- package/README.md +129 -20
- package/package.json +3 -2
- package/src/bare.ts +43 -14
- package/src/types.ts +24 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 xarhang
|
|
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
CHANGED
|
@@ -1,10 +1,28 @@
|
|
|
1
1
|
# 🚀 BareJS
|
|
2
|
+
### The Ultra-Low Latency JIT Web Engine for Bun
|
|
2
3
|
|
|
3
|
-
BareJS is
|
|
4
|
+
BareJS is a minimalist, high-performance web engine architected for the **Bun** ecosystem. By utilizing a **Just-In-Time (JIT) Route Compilation** strategy and an asynchronous **Onion-Model** pipeline, BareJS achieves near-native throughput, outperforming traditional frameworks by eliminating runtime routing overhead.
|
|
4
5
|
|
|
5
6
|

|
|
6
7
|
[](https://xarhang.github.io/bareJS/dev/benchmarks/)
|
|
7
8
|
[](https://bun.sh)
|
|
9
|
+
[](https://www.npmjs.com/package/barejs)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 🏛 Architectural Engineering
|
|
14
|
+
|
|
15
|
+
Unlike traditional frameworks that iterate through arrays or regex patterns on every request, BareJS utilizes a **Static Compilation Phase**.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### The JIT Lifecycle
|
|
20
|
+
When `app.listen()` is invoked, the engine:
|
|
21
|
+
1. **Analyzes** the complete route tree and global middleware stack.
|
|
22
|
+
2. **Serializes** the execution logic into a flat, optimized JavaScript function.
|
|
23
|
+
3. **Binds** the function using `new Function()`, allowing the **JavaScriptCore (JSC)** engine to perform aggressive inline caching and speculative optimizations.
|
|
24
|
+
|
|
25
|
+
---
|
|
8
26
|
|
|
9
27
|
---
|
|
10
28
|
|
|
@@ -18,7 +36,7 @@ Performance comparison between **BareJS**, **Elysia**, and **Hono**.
|
|
|
18
36
|
<!-- MARKER: PERFORMANCE_TABLE_START -->
|
|
19
37
|
| Framework | Latency (Avg) | Speed Ratio |
|
|
20
38
|
| :--- | :--- | :--- |
|
|
21
|
-
| **BareJS
|
|
39
|
+
| **BareJS** | **-- ns/iter** | **Baseline (1.0x)** |
|
|
22
40
|
| Elysia | -- ns/iter | --x slower |
|
|
23
41
|
| Hono | -- ns/iter | --x slower |
|
|
24
42
|
<!-- MARKER: PERFORMANCE_TABLE_END -->
|
|
@@ -27,27 +45,108 @@ Performance comparison between **BareJS**, **Elysia**, and **Hono**.
|
|
|
27
45
|
|
|
28
46
|
---
|
|
29
47
|
|
|
30
|
-
## ✨ Features
|
|
31
48
|
|
|
32
|
-
|
|
33
|
-
- **Zero Dependency:** Built natively for security and raw speed.
|
|
34
|
-
- **Optimized for Bun:** Leverages native Bun APIs for maximum performance.
|
|
35
|
-
- **Memory Efficient:** Minimal heap usage and clean garbage collection.
|
|
49
|
+
### ✨ **Features**
|
|
36
50
|
|
|
37
|
-
|
|
51
|
+
* **Ultra Low Latency:** Optimized to minimize processing overhead.
|
|
52
|
+
* **Zero Dependency:** Built natively for security and raw speed.
|
|
53
|
+
* **Optimized for Bun:** Leverages native Bun APIs for maximum performance.
|
|
54
|
+
* **Memory Efficient:** Minimal heap usage and clean garbage collection.
|
|
38
55
|
|
|
39
|
-
|
|
40
|
-
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 📦 Installation
|
|
41
59
|
|
|
42
|
-
### Installation
|
|
43
60
|
```bash
|
|
44
|
-
bun
|
|
61
|
+
bun add barejs
|
|
45
62
|
```
|
|
46
63
|
|
|
47
|
-
|
|
64
|
+
---
|
|
48
65
|
|
|
49
|
-
|
|
50
|
-
|
|
66
|
+
## ⚡ Quick Start
|
|
67
|
+
|
|
68
|
+
Create an `index.ts` and get your server running in seconds:
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import { BareJS } from 'barejs';
|
|
72
|
+
|
|
73
|
+
const app = new BareJS();
|
|
74
|
+
|
|
75
|
+
// Simple Route
|
|
76
|
+
app.get('/ping', (ctx) => ctx.json({ message: 'pong' }));
|
|
77
|
+
|
|
78
|
+
// Start Server
|
|
79
|
+
app.listen('0.0.0.0', 3000);
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 📖 Manual & Documentation
|
|
85
|
+
|
|
86
|
+
### 1. Request Context (`ctx`)
|
|
87
|
+
|
|
88
|
+
Every handler receives a `Context` object, providing a high-speed interface to the request:
|
|
89
|
+
|
|
90
|
+
* `ctx.req`: The [Native Bun Request](https://www.google.com/search?q=https://bun.sh/docs/api/http%23request).
|
|
91
|
+
* `ctx.json(data)`: Optimized JSON response helper with pre-defined headers.
|
|
92
|
+
* `ctx.body`: The validated JSON payload (available when using validators).
|
|
93
|
+
* `ctx.params`: Route parameters (e.g., `/user/:id`).
|
|
94
|
+
|
|
95
|
+
### 2. Middleware (The Onion Model)
|
|
96
|
+
|
|
97
|
+
BareJS supports an asynchronous recursive pipeline, allowing you to wrap logic before and after the handler.
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
app.use(async (ctx, next) => {
|
|
101
|
+
const start = performance.now();
|
|
102
|
+
const response = await next(); // Proceed to next middleware or handler
|
|
103
|
+
console.log(`Latency: ${(performance.now() - start).toFixed(2)}ms`);
|
|
104
|
+
return response;
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 3. Full Plugin System
|
|
110
|
+
|
|
111
|
+
Encapsulate complex logic into reusable modules that plug directly into the engine lifecycle.
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
const databasePlugin = {
|
|
115
|
+
name: 'barejs-db',
|
|
116
|
+
version: '1.0.0',
|
|
117
|
+
install: (app: BareJS) => {
|
|
118
|
+
app.use(async (ctx, next) => {
|
|
119
|
+
ctx.db = "CONNECTED";
|
|
120
|
+
return await next();
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
app.use(databasePlugin);
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 🛡️ Schema Validation
|
|
132
|
+
|
|
133
|
+
BareJS allows you to use different validators for different routes, focusing on high-speed schema checks.
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { typebox, zod, native } from 'barejs/middleware';
|
|
137
|
+
import { Type } from '@sinclair/typebox';
|
|
138
|
+
import { z } from 'zod';
|
|
139
|
+
|
|
140
|
+
// High Performance: TypeBox
|
|
141
|
+
const UserSchema = Type.Object({ name: Type.String() });
|
|
142
|
+
app.post('/tb', typebox(UserSchema), (ctx) => ctx.json(ctx.body));
|
|
143
|
+
|
|
144
|
+
// Popular Choice: Zod
|
|
145
|
+
const ZodSchema = z.object({ age: z.number() });
|
|
146
|
+
app.post('/zod', zod(ZodSchema), (ctx) => ctx.json(ctx.body));
|
|
147
|
+
|
|
148
|
+
// Zero Dependency: Native
|
|
149
|
+
app.post('/native', native({ properties: { id: { type: 'number' } } }), (ctx) => ctx.json(ctx.body));
|
|
51
150
|
|
|
52
151
|
```
|
|
53
152
|
|
|
@@ -55,11 +154,21 @@ bun run benchmarks/index.ts
|
|
|
55
154
|
|
|
56
155
|
## 🏗 Roadmap
|
|
57
156
|
|
|
58
|
-
* [x] Middleware
|
|
59
|
-
* [x]
|
|
60
|
-
* [x]
|
|
61
|
-
* [
|
|
157
|
+
* [x] **Middleware Support**: Async/Await "Onion" execution chain.
|
|
158
|
+
* [x] **JIT Static Routing**: lookup via compiled static maps.
|
|
159
|
+
* [x] **Validation Integration**: Support for TypeBox, Zod, and Native JSON.
|
|
160
|
+
* [x] **Full Plugin System**: Modular extensibility with zero overhead.
|
|
161
|
+
* [ ] **Dynamic Path JIT**: Compiled Regex for parameterized routes (e.g., `/user/:id`).
|
|
162
|
+
* [ ] **Native WebSocket Support**: High-speed binary streaming.
|
|
62
163
|
|
|
63
164
|
---
|
|
64
165
|
|
|
65
|
-
|
|
166
|
+
## 💎 Credits & Dependencies
|
|
167
|
+
|
|
168
|
+
* **[Bun](https://bun.sh/)**: The foundational runtime for BareJS.
|
|
169
|
+
* **[TypeBox](https://github.com/sinclairzx81/typebox)** & **[Zod](https://zod.dev/)**: For high-speed type safety.
|
|
170
|
+
* **Inspiration**: Architectural patterns from **Koa** and **ElysiaJS**.
|
|
171
|
+
|
|
172
|
+
**Maintained by [xarhang**](https://www.google.com/search?q=https://github.com/xarhang)
|
|
173
|
+
**License: MIT**
|
|
174
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "barejs",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"author": "xarhang",
|
|
5
5
|
"description": "High-performance JIT-specialized web framework for Bun",
|
|
6
6
|
"main": "src/bare.ts",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"files": [
|
|
38
38
|
"src",
|
|
39
|
-
"README.md"
|
|
39
|
+
"README.md",
|
|
40
|
+
"LICENSE"
|
|
40
41
|
]
|
|
41
42
|
}
|
package/src/bare.ts
CHANGED
|
@@ -2,7 +2,7 @@ export interface Context {
|
|
|
2
2
|
req: Request;
|
|
3
3
|
params: Record<string, string>;
|
|
4
4
|
json: (data: any) => Response;
|
|
5
|
-
body?: any;
|
|
5
|
+
body?: any;
|
|
6
6
|
[key: string]: any;
|
|
7
7
|
}
|
|
8
8
|
|
|
@@ -10,65 +10,94 @@ export type Next = () => Promise<any> | any;
|
|
|
10
10
|
export type Middleware = (ctx: Context, next: Next) => any;
|
|
11
11
|
export type Handler = (ctx: Context) => any;
|
|
12
12
|
|
|
13
|
+
export interface BarePlugin {
|
|
14
|
+
name: string;
|
|
15
|
+
version: string;
|
|
16
|
+
install: (app: BareJS) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
export class BareJS {
|
|
14
20
|
private routes: { method: string; path: string; handlers: (Middleware | Handler)[] }[] = [];
|
|
15
21
|
private globalMiddlewares: Middleware[] = [];
|
|
16
|
-
private compiledFetch?: (req: Request) => Promise<Response
|
|
22
|
+
private compiledFetch?: (req: Request) => Promise<Response> | Response;
|
|
17
23
|
private staticMap: Record<string, any> = {};
|
|
18
24
|
|
|
25
|
+
// --- Routing Methods ---
|
|
26
|
+
public get = (path: string, ...h: (Middleware | Handler)[]) => { this.routes.push({ method: "GET", path, handlers: h }); return this; };
|
|
19
27
|
public post = (path: string, ...h: (Middleware | Handler)[]) => { this.routes.push({ method: "POST", path, handlers: h }); return this; };
|
|
20
28
|
public put = (path: string, ...h: (Middleware | Handler)[]) => { this.routes.push({ method: "PUT", path, handlers: h }); return this; };
|
|
21
29
|
public patch = (path: string, ...h: (Middleware | Handler)[]) => { this.routes.push({ method: "PATCH", path, handlers: h }); return this; };
|
|
22
30
|
public delete = (path: string, ...h: (Middleware | Handler)[]) => { this.routes.push({ method: "DELETE", path, handlers: h }); return this; };
|
|
23
|
-
public get = (path: string, ...h: (Middleware | Handler)[]) => { this.routes.push({ method: "GET", path, handlers: h }); return this; };
|
|
24
|
-
public use = (...m: Middleware[]) => { this.globalMiddlewares.push(...m); return this; };
|
|
25
31
|
|
|
32
|
+
// --- Plugin & Middleware System ---
|
|
33
|
+
public use = (arg: Middleware | BarePlugin) => {
|
|
34
|
+
if (typeof arg === 'object' && 'install' in arg) {
|
|
35
|
+
arg.install(this);
|
|
36
|
+
} else {
|
|
37
|
+
this.globalMiddlewares.push(arg as Middleware);
|
|
38
|
+
}
|
|
39
|
+
return this;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// --- Core Engine ---
|
|
26
43
|
public fetch = (req: Request): Promise<Response> | Response => {
|
|
27
44
|
if (!this.compiledFetch) this.compile();
|
|
28
45
|
return this.compiledFetch!(req);
|
|
29
|
-
}
|
|
46
|
+
};
|
|
30
47
|
|
|
31
48
|
private compile() {
|
|
32
49
|
this.routes.forEach((route) => {
|
|
33
|
-
|
|
50
|
+
// Middleware Onion Runner
|
|
51
|
+
const chain = async (ctx: Context) => {
|
|
34
52
|
let idx = 0;
|
|
35
53
|
const middlewares = [...this.globalMiddlewares, ...route.handlers];
|
|
36
|
-
const next = (): any => {
|
|
54
|
+
const next = async (): Promise<any> => {
|
|
37
55
|
const handler = middlewares[idx++];
|
|
38
56
|
if (!handler) return;
|
|
39
|
-
|
|
57
|
+
// Support both async and sync handlers
|
|
58
|
+
return await (handler.length > 1
|
|
59
|
+
? (handler as Middleware)(ctx, next)
|
|
60
|
+
: (handler as Handler)(ctx));
|
|
40
61
|
};
|
|
41
|
-
return next();
|
|
62
|
+
return await next();
|
|
42
63
|
};
|
|
43
64
|
this.staticMap[`${route.method}:${route.path}`] = chain;
|
|
44
65
|
});
|
|
45
66
|
|
|
67
|
+
// JIT Optimized Fetch Function
|
|
46
68
|
const fnBody = `
|
|
47
69
|
const staticMap = this.staticMap;
|
|
48
70
|
const EMPTY_PARAMS = Object.freeze({});
|
|
49
71
|
const jsonHeader = { "content-type": "application/json" };
|
|
50
|
-
|
|
72
|
+
|
|
73
|
+
return async (req) => {
|
|
51
74
|
const url = req.url;
|
|
52
75
|
const pathStart = url.indexOf('/', 8);
|
|
53
76
|
const path = pathStart === -1 ? '/' : url.substring(pathStart);
|
|
54
77
|
const key = req.method + ":" + path;
|
|
78
|
+
|
|
55
79
|
const runner = staticMap[key];
|
|
56
80
|
if (runner) {
|
|
57
|
-
const ctx = {
|
|
58
|
-
|
|
81
|
+
const ctx = {
|
|
82
|
+
req,
|
|
83
|
+
params: EMPTY_PARAMS,
|
|
84
|
+
json: (d) => new Response(JSON.stringify(d), { headers: jsonHeader })
|
|
85
|
+
};
|
|
86
|
+
return await runner(ctx);
|
|
59
87
|
}
|
|
60
88
|
return new Response('404 Not Found', { status: 404 });
|
|
61
89
|
};`;
|
|
90
|
+
|
|
62
91
|
this.compiledFetch = new Function(fnBody).bind(this)();
|
|
63
92
|
}
|
|
64
93
|
|
|
65
|
-
listen(ip: string = '0.0.0.0', port: number = 3000) {
|
|
94
|
+
public listen(ip: string = '0.0.0.0', port: number = 3000) {
|
|
66
95
|
this.compile();
|
|
67
96
|
console.log(`🚀 BareJS running at http://${ip}:${port}`);
|
|
68
97
|
return Bun.serve({
|
|
69
98
|
hostname: ip,
|
|
70
99
|
port,
|
|
71
|
-
fetch: (req) => this.
|
|
100
|
+
fetch: (req) => this.fetch(req),
|
|
72
101
|
});
|
|
73
102
|
}
|
|
74
103
|
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// src/context.ts
|
|
2
|
+
export class Context {
|
|
3
|
+
public res: Response;
|
|
4
|
+
|
|
5
|
+
constructor(public req: Request) {
|
|
6
|
+
this.res = new Response("Not Found", { status: 404 });
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
json(data: any) {
|
|
10
|
+
this.res = new Response(JSON.stringify(data), {
|
|
11
|
+
headers: { "Content-Type": "application/json" },
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
setResHeader(key: string, value: string) {
|
|
17
|
+
const newHeaders = new Headers(this.res.headers);
|
|
18
|
+
newHeaders.set(key, value);
|
|
19
|
+
this.res = new Response(this.res.body, {
|
|
20
|
+
status: this.res.status,
|
|
21
|
+
headers: newHeaders,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|