princejs 1.5.2 → 1.5.4
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 +164 -33
- package/dist/prince.js +11 -10
- package/dist/validation.js +5 -1
- package/package.json +2 -2
package/Readme.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
#
|
|
1
|
+
# PrinceJS — The Fastest Bun Framework in History
|
|
2
2
|
|
|
3
|
-
**2.8 kB gzipped** •
|
|
3
|
+
**2.8 kB gzipped** • **19,200 req/s** • **Built by a 13yo Nigerian**
|
|
4
4
|
|
|
5
|
-
> *"I didn
|
|
5
|
+
> *"I didn't beat Elysia. I destroyed it."* — @Lil_Prince_1218
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## 🏆 World Record: Fastest Framework Under 3 kB
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
12
|
# Create a new PrinceJS app
|
|
@@ -20,74 +20,205 @@ bun dev
|
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
```ts
|
|
23
|
-
import {
|
|
24
|
-
import { cors } from "princejs/middleware";
|
|
23
|
+
import { prince } from "princejs";
|
|
24
|
+
import { cors, logger } from "princejs/middleware";
|
|
25
25
|
|
|
26
|
-
const app =
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
const app = prince();
|
|
27
|
+
|
|
28
|
+
app.use(cors());
|
|
29
|
+
app.use(logger());
|
|
30
|
+
|
|
31
|
+
app.get("/", () => ({ message: "Hello PrinceJS!" }));
|
|
32
|
+
app.get("/users/:id", (req) => ({ id: req.params.id }));
|
|
30
33
|
|
|
31
|
-
app.listen(
|
|
34
|
+
app.listen(3000);
|
|
32
35
|
```
|
|
33
36
|
|
|
34
37
|
---
|
|
35
38
|
|
|
36
39
|
## ⚔️ Size War (Gzipped — Real World)
|
|
37
40
|
|
|
38
|
-
| Framework | Gzipped | Minified | vs
|
|
41
|
+
| Framework | Gzipped | Minified | vs PrinceJS |
|
|
39
42
|
| ------------ | ---------- | ---------- | ----------- |
|
|
40
|
-
| **
|
|
43
|
+
| **PrinceJS** | **2.8 kB** | **7.8 kB** | — |
|
|
41
44
|
| **Hono** | 7.3 kB | 18.7 kB | 2.6× bigger |
|
|
42
45
|
| **Elysia** | 62.5 kB | 245 kB | 22× bigger |
|
|
43
46
|
|
|
44
|
-
>
|
|
47
|
+
> PrinceJS fits in a tweet. Elysia needs a ZIP file.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## ⚡ Benchmarks (autocannon -c 100 -d 30)
|
|
52
|
+
|
|
53
|
+
**Windows 11 • November 15, 2025 • 100 connections • 30 seconds**
|
|
54
|
+
|
|
55
|
+
### Route: `GET /users/:id`
|
|
56
|
+
|
|
57
|
+
| Rank | Framework | Req/s | Requests (30s) | Throughput |
|
|
58
|
+
| ---- | ------------ | ---------- | -------------- | ----------- |
|
|
59
|
+
| 🥇 | **PrinceJS** | **19,200** | **576k** | **2.34 MB/s** |
|
|
60
|
+
| 🥈 | Hono | 16,212 | 486k | 1.98 MB/s |
|
|
61
|
+
| 🥉 | Elysia | 15,862 | 476k | 1.94 MB/s |
|
|
62
|
+
| 4️⃣ | Express | 9,325 | 280k | 1.84 MB/s |
|
|
63
|
+
|
|
64
|
+
### Summary
|
|
65
|
+
|
|
66
|
+
- **PrinceJS beats Elysia by 21%** (3,338 more req/s)
|
|
67
|
+
- **PrinceJS beats Hono by 18%** (2,988 more req/s)
|
|
68
|
+
- **PrinceJS beats Express by 106%** (2× faster)
|
|
69
|
+
|
|
70
|
+
> **PrinceJS is the FASTEST framework under 10 kB. Period.**
|
|
45
71
|
|
|
46
72
|
---
|
|
47
73
|
|
|
48
|
-
##
|
|
74
|
+
## 🔥 Why PrinceJS Wins
|
|
49
75
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
| **princejs** | **599k** | **19,966** | 🥈 2nd fastest |
|
|
53
|
-
| **Elysia** | 602k | 20,071 | 🥇 0.5% faster |
|
|
54
|
-
| **Hono** | 578k | 19,254 | 🥉 Slower |
|
|
76
|
+
### 1. **Trie-Based Router** (Cached)
|
|
77
|
+
Most frameworks rebuild routes on every request. PrinceJS builds once and caches.
|
|
55
78
|
|
|
56
|
-
|
|
79
|
+
### 2. **Zero Overhead Middleware**
|
|
80
|
+
Middleware tracking prevents duplicate execution. No wasted cycles.
|
|
81
|
+
|
|
82
|
+
### 3. **Optimized for Bun**
|
|
83
|
+
Native Bun.serve() with WebSocket support. No abstraction layers.
|
|
84
|
+
|
|
85
|
+
### 4. **Smart Body Parsing**
|
|
86
|
+
Only parses body when needed (POST/PUT/PATCH). GET requests skip parsing entirely.
|
|
57
87
|
|
|
58
88
|
---
|
|
59
89
|
|
|
60
|
-
##
|
|
90
|
+
## 🧰 Features
|
|
61
91
|
|
|
62
92
|
```ts
|
|
63
|
-
|
|
64
|
-
|
|
93
|
+
import { cors, logger, rateLimit, serve } from "princejs/middleware";
|
|
94
|
+
import { validate } from "princejs/validation";
|
|
95
|
+
import { z } from "zod";
|
|
96
|
+
|
|
97
|
+
app
|
|
98
|
+
.use(cors())
|
|
99
|
+
.use(logger({ format: "dev" }))
|
|
100
|
+
.use(rateLimit({ max: 100, window: 60 }))
|
|
101
|
+
.use(serve({ root: "./public" }))
|
|
102
|
+
.use(validate(z.object({
|
|
103
|
+
name: z.string(),
|
|
104
|
+
age: z.number()
|
|
105
|
+
})));
|
|
65
106
|
```
|
|
66
107
|
|
|
67
|
-
✅
|
|
68
|
-
✅
|
|
69
|
-
✅
|
|
108
|
+
✅ **Middleware:** CORS, Logger, Rate Limiting, Static Files
|
|
109
|
+
✅ **Validation:** Zod schema validation
|
|
110
|
+
✅ **WebSocket:** Full WebSocket support
|
|
111
|
+
✅ **File Upload:** Multipart form data handling
|
|
112
|
+
✅ **Response Builder:** Fluent API for responses
|
|
113
|
+
✅ **OpenAPI:** Auto-generate API docs
|
|
70
114
|
|
|
71
115
|
---
|
|
72
116
|
|
|
73
|
-
## 📦
|
|
117
|
+
## 📦 Installation
|
|
74
118
|
|
|
75
119
|
```bash
|
|
76
|
-
npm
|
|
120
|
+
npm install princejs
|
|
77
121
|
# or
|
|
78
122
|
bun add princejs
|
|
123
|
+
# or
|
|
124
|
+
yarn add princejs
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 🎯 Full Example
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import { prince } from "princejs";
|
|
133
|
+
import { cors, logger, rateLimit } from "princejs/middleware";
|
|
134
|
+
import { validate } from "princejs/validation";
|
|
135
|
+
import { z } from "zod";
|
|
136
|
+
|
|
137
|
+
const app = prince(true); // dev mode
|
|
138
|
+
|
|
139
|
+
// Middleware
|
|
140
|
+
app.use(cors());
|
|
141
|
+
app.use(logger());
|
|
142
|
+
app.use(rateLimit({ max: 100, window: 60 }));
|
|
143
|
+
|
|
144
|
+
// Routes
|
|
145
|
+
app.get("/", () => ({
|
|
146
|
+
message: "Welcome to PrinceJS",
|
|
147
|
+
version: "1.5.2"
|
|
148
|
+
}));
|
|
149
|
+
|
|
150
|
+
app.get("/users/:id", (req) => ({
|
|
151
|
+
id: req.params.id,
|
|
152
|
+
name: "John Doe"
|
|
153
|
+
}));
|
|
154
|
+
|
|
155
|
+
// File upload
|
|
156
|
+
app.post("/upload", (req) => ({
|
|
157
|
+
files: Object.keys(req.files || {}),
|
|
158
|
+
body: req.body
|
|
159
|
+
}));
|
|
160
|
+
|
|
161
|
+
// WebSocket
|
|
162
|
+
app.ws("/chat", {
|
|
163
|
+
open: (ws) => ws.send("Welcome!"),
|
|
164
|
+
message: (ws, msg) => ws.send(`Echo: ${msg}`),
|
|
165
|
+
close: (ws) => console.log("Disconnected")
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
app.listen(3000);
|
|
79
169
|
```
|
|
80
170
|
|
|
81
171
|
---
|
|
82
172
|
|
|
83
|
-
## 📚
|
|
173
|
+
## 📚 Documentation
|
|
84
174
|
|
|
85
|
-
|
|
175
|
+
Check: [princejs](https://princejs.vercel.app)
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## 🤝 Contributing
|
|
180
|
+
|
|
181
|
+
Issues and PRs welcome! This is a learning project but we take quality seriously.
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
git clone https://github.com/MatthewTheCoder1218/princejs
|
|
185
|
+
cd princejs
|
|
186
|
+
bun install
|
|
187
|
+
bun test
|
|
188
|
+
```
|
|
86
189
|
|
|
87
190
|
---
|
|
88
191
|
|
|
89
192
|
## 🇳🇬 Built in Nigeria
|
|
90
193
|
|
|
91
|
-
|
|
194
|
+
**Made by @Lil_Prince_1218 — Age 13**
|
|
195
|
+
|
|
196
|
+
> *"2.8 kB. 19,200 req/s. The fastest framework under 10 kB."*
|
|
197
|
+
|
|
198
|
+
Inspired by the greats (Express, Hono, Elysia) but built to win.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 📄 License
|
|
203
|
+
|
|
204
|
+
MIT © 2025 Matthew Michael
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## ⭐ Star This Repo
|
|
209
|
+
|
|
210
|
+
If PrinceJS helped you, give it a star! It helps other developers discover it.
|
|
211
|
+
|
|
212
|
+
**GitHub:** [github.com/MatthewTheCoder1218/princejs](https://github.com/MatthewTheCoder1218/princejs)
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## 🔗 Links
|
|
217
|
+
|
|
218
|
+
- [npm](https://www.npmjs.com/package/princejs)
|
|
219
|
+
- [GitHub](https://github.com/MatthewTheCoder1218/princejs)
|
|
220
|
+
- [Twitter](https://twitter.com/Lil_Prince_1218)
|
|
221
|
+
|
|
222
|
+
---
|
|
92
223
|
|
|
93
|
-
|
|
224
|
+
**PrinceJS: Small in size. Giant in speed. 🚀**
|
package/dist/prince.js
CHANGED
|
@@ -188,19 +188,20 @@ class Prince {
|
|
|
188
188
|
return async (req, params, query) => {
|
|
189
189
|
Object.defineProperty(req, "params", { value: params, writable: true, configurable: true });
|
|
190
190
|
Object.defineProperty(req, "query", { value: query, writable: true, configurable: true });
|
|
191
|
+
if (["POST", "PUT", "PATCH"].includes(req.method)) {
|
|
192
|
+
const parsed = await this.parseBody(req);
|
|
193
|
+
if (parsed && typeof parsed === "object" && "files" in parsed && "fields" in parsed) {
|
|
194
|
+
Object.defineProperty(req, "body", { value: parsed.fields, writable: true, configurable: true });
|
|
195
|
+
Object.defineProperty(req, "files", { value: parsed.files, writable: true, configurable: true });
|
|
196
|
+
} else {
|
|
197
|
+
Object.defineProperty(req, "body", { value: parsed, writable: true, configurable: true });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
191
200
|
let i = 0;
|
|
192
201
|
const next = async () => {
|
|
193
202
|
if (i < this.middlewares.length) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
if (["POST", "PUT", "PATCH"].includes(req.method)) {
|
|
197
|
-
const parsed = await this.parseBody(req);
|
|
198
|
-
if (parsed && typeof parsed === "object" && "files" in parsed && "fields" in parsed) {
|
|
199
|
-
Object.defineProperty(req, "body", { value: parsed.fields, writable: true, configurable: true });
|
|
200
|
-
Object.defineProperty(req, "files", { value: parsed.files, writable: true, configurable: true });
|
|
201
|
-
} else {
|
|
202
|
-
Object.defineProperty(req, "body", { value: parsed, writable: true, configurable: true });
|
|
203
|
-
}
|
|
203
|
+
const result = await this.middlewares[i++](req, next);
|
|
204
|
+
return result ?? new Response("");
|
|
204
205
|
}
|
|
205
206
|
const res = await handler(req);
|
|
206
207
|
if (res instanceof Response)
|
package/dist/validation.js
CHANGED
|
@@ -6,7 +6,11 @@ var validate = (schema, source = "body") => {
|
|
|
6
6
|
const data = source === "body" ? req.body : source === "query" ? req.query : req.params;
|
|
7
7
|
const validated = schema.parse(data);
|
|
8
8
|
req[`validated${source.charAt(0).toUpperCase() + source.slice(1)}`] = validated;
|
|
9
|
-
|
|
9
|
+
if (next) {
|
|
10
|
+
const result = await next();
|
|
11
|
+
return result;
|
|
12
|
+
}
|
|
13
|
+
return;
|
|
10
14
|
} catch (err) {
|
|
11
15
|
return new Response(JSON.stringify({
|
|
12
16
|
error: "Validation failed",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "princejs",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.4",
|
|
4
4
|
"description": "An easy and fast backend framework — by a 13yo developer, for developers.",
|
|
5
5
|
"main": "dist/prince.js",
|
|
6
6
|
"types": "dist/prince.d.ts",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"typescript": "^5.9.3"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
|
-
"zod": "^
|
|
62
|
+
"zod": "^4.0.0"
|
|
63
63
|
},
|
|
64
64
|
"peerDependenciesMeta": {
|
|
65
65
|
"zod": {
|