barejs 0.1.4 → 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/README.md +96 -49
- package/package.json +1 -1
- package/src/bare.ts +43 -14
- package/src/types.ts +24 -0
package/README.md
CHANGED
|
@@ -1,9 +1,28 @@
|
|
|
1
1
|
# 🚀 BareJS
|
|
2
|
-
|
|
2
|
+
### The Ultra-Low Latency JIT Web Engine for Bun
|
|
3
|
+
|
|
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.
|
|
3
5
|
|
|
4
6
|

|
|
5
7
|
[](https://xarhang.github.io/bareJS/dev/benchmarks/)
|
|
6
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
|
+
---
|
|
7
26
|
|
|
8
27
|
---
|
|
9
28
|
|
|
@@ -26,7 +45,8 @@ Performance comparison between **BareJS**, **Elysia**, and **Hono**.
|
|
|
26
45
|
|
|
27
46
|
---
|
|
28
47
|
|
|
29
|
-
|
|
48
|
+
|
|
49
|
+
### ✨ **Features**
|
|
30
50
|
|
|
31
51
|
* **Ultra Low Latency:** Optimized to minimize processing overhead.
|
|
32
52
|
* **Zero Dependency:** Built natively for security and raw speed.
|
|
@@ -35,50 +55,88 @@ Performance comparison between **BareJS**, **Elysia**, and **Hono**.
|
|
|
35
55
|
|
|
36
56
|
---
|
|
37
57
|
|
|
38
|
-
##
|
|
39
|
-
|
|
40
|
-
### ⚡ The Core Engine
|
|
41
|
-
|
|
42
|
-
BareJS uses a **Static Route Compiler**. When you call `app.listen()`, BareJS transforms your routes into an optimized lookup table. This ensures routing complexity, meaning your app stays fast whether you have 10 routes or 10,000.
|
|
43
|
-
|
|
44
|
-
### 🏗️ Request Context
|
|
45
|
-
|
|
46
|
-
Every handler receives a `Context` object:
|
|
58
|
+
## 📦 Installation
|
|
47
59
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
* `ctx.body`: The validated JSON payload (available when using validators).
|
|
60
|
+
```bash
|
|
61
|
+
bun add barejs
|
|
62
|
+
```
|
|
52
63
|
|
|
53
64
|
---
|
|
54
65
|
|
|
55
|
-
##
|
|
66
|
+
## ⚡ Quick Start
|
|
56
67
|
|
|
57
|
-
|
|
68
|
+
Create an `index.ts` and get your server running in seconds:
|
|
58
69
|
|
|
59
70
|
```typescript
|
|
60
71
|
import { BareJS } from 'barejs';
|
|
61
72
|
|
|
62
73
|
const app = new BareJS();
|
|
63
74
|
|
|
75
|
+
// Simple Route
|
|
64
76
|
app.get('/ping', (ctx) => ctx.json({ message: 'pong' }));
|
|
65
77
|
|
|
78
|
+
// Start Server
|
|
66
79
|
app.listen('0.0.0.0', 3000);
|
|
67
80
|
|
|
68
81
|
```
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 📖 Manual & Documentation
|
|
85
|
+
|
|
86
|
+
### 1. Request Context (`ctx`)
|
|
69
87
|
|
|
70
|
-
|
|
88
|
+
Every handler receives a `Context` object, providing a high-speed interface to the request:
|
|
71
89
|
|
|
72
|
-
|
|
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.
|
|
73
134
|
|
|
74
135
|
```typescript
|
|
75
|
-
import { BareJS } from 'barejs';
|
|
76
136
|
import { typebox, zod, native } from 'barejs/middleware';
|
|
77
137
|
import { Type } from '@sinclair/typebox';
|
|
78
138
|
import { z } from 'zod';
|
|
79
139
|
|
|
80
|
-
const app = new BareJS();
|
|
81
|
-
|
|
82
140
|
// High Performance: TypeBox
|
|
83
141
|
const UserSchema = Type.Object({ name: Type.String() });
|
|
84
142
|
app.post('/tb', typebox(UserSchema), (ctx) => ctx.json(ctx.body));
|
|
@@ -87,41 +145,30 @@ app.post('/tb', typebox(UserSchema), (ctx) => ctx.json(ctx.body));
|
|
|
87
145
|
const ZodSchema = z.object({ age: z.number() });
|
|
88
146
|
app.post('/zod', zod(ZodSchema), (ctx) => ctx.json(ctx.body));
|
|
89
147
|
|
|
90
|
-
//
|
|
148
|
+
// Zero Dependency: Native
|
|
91
149
|
app.post('/native', native({ properties: { id: { type: 'number' } } }), (ctx) => ctx.json(ctx.body));
|
|
92
150
|
|
|
93
151
|
```
|
|
94
152
|
|
|
95
153
|
---
|
|
96
154
|
|
|
97
|
-
##
|
|
98
|
-
|
|
99
|
-
### Prerequisites
|
|
100
|
-
|
|
101
|
-
* **Bun** v1.0.0 or higher
|
|
102
|
-
|
|
103
|
-
### Installation
|
|
104
|
-
|
|
105
|
-
```bash
|
|
106
|
-
bun install barejs
|
|
107
|
-
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### Running Benchmarks Locally
|
|
155
|
+
## 🏗 Roadmap
|
|
111
156
|
|
|
112
|
-
|
|
113
|
-
|
|
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.
|
|
114
163
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
## 🏗 Roadmap
|
|
164
|
+
---
|
|
118
165
|
|
|
119
|
-
|
|
120
|
-
* [x] High-Speed Static Routing ( Lookup Table)
|
|
121
|
-
* [x] Schema Validation Integration
|
|
122
|
-
* [x] Modular Validator Support (TypeBox, Zod, Native)
|
|
123
|
-
* [ ] Full Plugin System
|
|
166
|
+
## 💎 Credits & Dependencies
|
|
124
167
|
|
|
125
|
-
**
|
|
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**.
|
|
126
171
|
|
|
127
|
-
|
|
172
|
+
**Maintained by [xarhang**](https://www.google.com/search?q=https://github.com/xarhang)
|
|
173
|
+
**License: MIT**
|
|
174
|
+
```
|
package/package.json
CHANGED
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
|
+
}
|