barejs 0.1.4 → 0.1.6

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 CHANGED
@@ -1,9 +1,28 @@
1
1
  # 🚀 BareJS
2
- BareJS is an ultra-high-performance web engine built on the Bun runtime, designed for minimalism and the lowest possible latency.
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
  ![Benchmark Status](https://github.com/xarhang/bareJS/actions/workflows/bench.yml/badge.svg)
5
7
  [![Performance Dashboard](https://img.shields.io/badge/Performance-Dashboard-blueviolet?style=flat-square&logo=speedtest)](https://xarhang.github.io/bareJS/dev/benchmarks/)
6
8
  [![Bun Version](https://img.shields.io/badge/Bun-%3E%3D1.0.0-black?style=flat-square&logo=bun)](https://bun.sh)
9
+ [![NPM Version](https://img.shields.io/npm/v/barejs.svg?style=flat-square)](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
- ✨ **Features**
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
- ## 📖 Documentation
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
- * `ctx.req`: The native Bun `Request`.
49
- * `ctx.params`: Route parameters (e.g., `/user/:id`).
50
- * `ctx.json(data)`: High-speed JSON response helper.
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
- ## 🛠 Usage Examples
66
+ ## Quick Start
56
67
 
57
- ### 1. Basic Server
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
- ### 2. Validation (Choose Your Weapon)
88
+ Every handler receives a `Context` object, providing a high-speed interface to the request:
71
89
 
72
- BareJS allows you to use different validators for different routes.
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
- // No Dependencies: Native
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
- ## 🛠 Getting Started
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
- ```bash
113
- bun run bench
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
- * [x] Middleware Pattern Support (Chain Execution)
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
- **Maintained by xarhang**
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
@@ -1,11 +1,16 @@
1
1
  {
2
2
  "name": "barejs",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "author": "xarhang",
5
5
  "description": "High-performance JIT-specialized web framework for Bun",
6
- "main": "src/bare.ts",
7
- "types": "src/bare.ts",
6
+ "main": "./src/bare.ts",
7
+ "types": "./src/bare.ts",
8
8
  "type": "module",
9
+ "exports": {
10
+ ".": "./src/bare.ts",
11
+ "./middleware": "./src/middleware/index.ts"
12
+ },
13
+ "sideEffects": false,
9
14
  "repository": {
10
15
  "type": "git",
11
16
  "url": "git+https://github.com/xarhang/barejs.git"
@@ -13,7 +18,9 @@
13
18
  "scripts": {
14
19
  "test": "echo \"Error: no test specified\" && exit 1",
15
20
  "bench": "bun run benchmarks/index.ts",
16
- "dev": "bun --watch src/bare.ts"
21
+ "dev": "bun --watch src/bare.ts",
22
+ "build": "bun ./scripts/build.ts",
23
+ "release": "bun run build && npm version patch && npm publish --access public"
17
24
  },
18
25
  "keywords": [
19
26
  "bun",
@@ -24,19 +31,31 @@
24
31
  "zod"
25
32
  ],
26
33
  "license": "MIT",
27
- "dependencies": {
34
+ "peerDependencies": {
28
35
  "@sinclair/typebox": "^0.34.46",
29
- "zod": "^4.3.5"
36
+ "zod": "^3.0.0"
37
+ },
38
+ "peerDependenciesMeta": {
39
+ "@sinclair/typebox": {
40
+ "optional": true
41
+ },
42
+ "zod": {
43
+ "optional": true
44
+ }
30
45
  },
31
46
  "devDependencies": {
47
+ "@sinclair/typebox": "^0.34.46",
48
+ "zod": "^3.23.8",
32
49
  "@types/bun": "latest",
33
50
  "elysia": "^1.4.21",
34
51
  "hono": "^4.11.3",
35
- "mitata": "^1.0.34"
52
+ "mitata": "^1.0.34",
53
+ "typescript": "latest"
36
54
  },
37
55
  "files": [
38
56
  "src",
57
+ "dist",
39
58
  "README.md",
40
59
  "LICENSE"
41
60
  ]
42
- }
61
+ }
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,119 @@ 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
- const chain = (ctx: Context) => {
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
- return handler(ctx, next);
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
- return (req) => {
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 = { req, params: EMPTY_PARAMS, json: (d) => new Response(JSON.stringify(d), { headers: jsonHeader }) };
58
- return runner(ctx);
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
- console.log(`🚀 BareJS running at http://${ip}:${port}`);
96
+
97
+
98
+
99
+
100
+ const reset = "\x1b[0m";
101
+ const cyan = "\x1b[36m";
102
+ const yellow = "\x1b[33m";
103
+ const gray = "\x1b[90m";
104
+ const bold = "\x1b[1m";
105
+ if (process.env.NODE_ENV !== 'production' && process.env.BARE_SILENT !== 'true') {
106
+ console.log(`
107
+ ${cyan}${bold} ____ _ ____
108
+ | __ ) __ _ _ __ ___ | / ___|
109
+ | _ \\ / _\` | '__/ _ \\ _ | \\___ \\
110
+ | |_) | (_| | | | __/| |_| |___) |
111
+ |____/ \\__,_|_| \\___| \\___/|____/
112
+ ${reset}
113
+ ${yellow}BareJS${reset} ${gray}${reset}
114
+ ${gray}-----------------------------------${reset}
115
+ 🚀 Running at: ${cyan}http://${ip}:${port}${reset}
116
+ ${gray}Ready to build everything awesome!${reset}
117
+ `);
118
+ } else {
119
+
120
+ console.log(`🚀 BareJS running at http://${ip}:${port}`);
121
+ }
68
122
  return Bun.serve({
69
123
  hostname: ip,
70
124
  port,
71
- fetch: (req) => this.compiledFetch!(req),
125
+ fetch: (req) => this.fetch(req),
72
126
  });
73
127
  }
74
128
  }
package/src/index.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { BareJS, type Context } from './bare';
2
+ import { typebox, native } from './middleware/validators';
3
+ import * as TB from '@sinclair/typebox';
4
+
5
+ const app = new BareJS();
6
+
7
+ // Create Schema with TypeBox
8
+ const UserSchema = TB.Type.Object({
9
+ name: TB.Type.String(),
10
+ age: TB.Type.Number()
11
+ });
12
+
13
+ // ✅ Route 1: Using TypeBox Validator (Fastest for Bun)
14
+ app.post('/users-tb', typebox(UserSchema), (ctx: Context) => {
15
+ return ctx.json({ message: "Saved via TypeBox", user: ctx.body });
16
+ });
17
+
18
+ // ✅ Route 2: Using Native Validator (Safe alternative if TypeBox has issues)
19
+ app.post('/users-native', native(UserSchema), (ctx: Context) => {
20
+ return ctx.json({ message: "Saved via Native", user: ctx.body });
21
+ });
22
+
23
+ // ✅ Route 3: No Validator (Pure speed, 0 ns overhead)
24
+ app.get('/ping', (ctx: Context) => ctx.json({ message: "pong" }));
25
+
26
+ app.listen('0.0.0.0', 3000);
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
+ }