princejs 1.9.4 โ†’ 1.9.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.
Files changed (2) hide show
  1. package/Readme.md +126 -208
  2. package/package.json +1 -1
package/Readme.md CHANGED
@@ -1,17 +1,40 @@
1
- # ๐Ÿ‘‘ **PrinceJS**
1
+ <div align="center">
2
2
 
3
- ![PrinceJS Image](./src/images/og.png)
3
+ <img src="./src/images/og.png" alt="PrinceJS" width="120" />
4
4
 
5
- ### โšก Ultra-clean, modern & minimal Bun web framework built by a 13 year old. Among the top three in performance.
5
+ # ๐Ÿ‘‘ PrinceJS
6
6
 
7
- ![npm](https://img.shields.io/npm/v/princejs)
8
- ![stars](https://img.shields.io/github/stars/MatthewTheCoder1218/princejs)
9
- ![downloads](https://img.shields.io/npm/dt/princejs)
10
- ![license](https://img.shields.io/github/license/MatthewTheCoder1218/princejs)
7
+ **Ultra-clean, modern & minimal Bun web framework.**
8
+ Built by a 13-year-old Nigerian developer. Among the top three in performance.
9
+
10
+ [![npm version](https://img.shields.io/npm/v/princejs?style=flat-square)](https://www.npmjs.com/package/princejs)
11
+ [![GitHub stars](https://img.shields.io/github/stars/MatthewTheCoder1218/princejs?style=flat-square)](https://github.com/MatthewTheCoder1218/princejs)
12
+ [![npm downloads](https://img.shields.io/npm/dt/princejs?style=flat-square)](https://www.npmjs.com/package/princejs)
13
+ [![license](https://img.shields.io/github/license/MatthewTheCoder1218/princejs?style=flat-square)](https://github.com/MatthewTheCoder1218/princejs/blob/main/LICENSE)
14
+
15
+ [**Website**](https://princejs.vercel.app) ยท [**npm**](https://www.npmjs.com/package/princejs) ยท [**GitHub**](https://github.com/MatthewTheCoder1218/princejs) ยท [**Twitter**](https://twitter.com/princejs_bun)
16
+
17
+ </div>
18
+
19
+ ---
20
+
21
+ ## โšก Performance
22
+
23
+ Benchmarked with `oha -c 100 -z 30s` on Windows 10:
24
+
25
+ | Framework | Req/s | Total |
26
+ |-----------|------:|------:|
27
+ | Elysia | 25,312 | 759k |
28
+ | Hono | 22,124 | 664k |
29
+ | **PrinceJS** | **21,748** | **653k** |
30
+ | Express | 9,325 | 280k |
31
+
32
+ > PrinceJS is **2.3ร— faster than Express** and sits comfortably in the top 3 โ€” at just **4.4kB gzipped**.
11
33
 
12
34
  ---
13
35
 
14
36
  ## ๐Ÿš€ Quick Start
37
+
15
38
  ```bash
16
39
  bun create princejs my-app
17
40
  cd my-app
@@ -37,77 +60,30 @@ app.listen(3000);
37
60
 
38
61
  ## ๐Ÿงฐ Features
39
62
 
40
- ```ts
41
- import { cors, logger, rateLimit, serve } from "princejs/middleware";
42
- import { validate } from "princejs/validation";
43
- import { z } from "zod";
44
-
45
- app
46
- .use(cors())
47
- .use(logger())
48
- .use(rateLimit({ max: 100, window: 60 }))
49
- .use(serve({ root: "./public" }))
50
- .use(validate(z.object({
51
- name: z.string(),
52
- age: z.number()
53
- })));
54
- ```
55
-
56
- ### Middleware
57
-
58
- * CORS
59
- * Logger
60
- * Rate Limiting
61
- * Static Files
63
+ | Feature | Import |
64
+ |---------|--------|
65
+ | Routing | `princejs` |
66
+ | Middleware (CORS, Logger, Rate Limit, Auth, JWT) | `princejs/middleware` |
67
+ | Zod Validation | `princejs/middleware` |
68
+ | File Uploads | `princejs/helpers` |
69
+ | WebSockets | `princejs` |
70
+ | Server-Sent Events | `princejs/helpers` |
71
+ | Sessions | `princejs/middleware` |
72
+ | Response Compression | `princejs/middleware` |
73
+ | In-memory Cache | `princejs/helpers` |
74
+ | Cron Scheduler | `princejs/scheduler` |
75
+ | **OpenAPI + Scalar Docs** | `princejs` |
76
+ | JSX / SSR | `princejs/jsx` |
77
+ | SQLite Database | `princejs/db` |
78
+ | Plugin System | `princejs` |
79
+ | End-to-End Type Safety | `princejs/client` |
80
+ | Deploy Adapters | `princejs/vercel` ยท `princejs/cloudflare` ยท `princejs/deno` |
62
81
 
63
- ### Validation (Zod)
64
-
65
- ### File Uploads
66
-
67
- ### Response Builder
68
-
69
- ### WebSocket Support
70
-
71
- ### Auth & API Keys
72
-
73
- ### Server-Sent Events
74
-
75
- ### Sessions
76
-
77
- ### Response Compression
78
-
79
- ### Route-level Middleware
80
-
81
- ### Plugin System
82
-
83
- You can share bundles of routes and middleware as plugins.
84
-
85
- ```ts
86
- import { prince, type PrincePlugin } from "princejs";
87
-
88
- const usersPlugin: PrincePlugin<{ prefix?: string }> = (app, opts) => {
89
- const base = opts?.prefix ?? "";
90
-
91
- // plugin-wide middleware
92
- app.use((req, next) => {
93
- (req as any).fromPlugin = true;
94
- return next();
95
- });
96
-
97
- // plugin routes
98
- app.get(`${base}/users`, (req) => ({
99
- ok: true,
100
- fromPlugin: (req as any).fromPlugin,
101
- }));
102
- };
103
-
104
- const app = prince();
105
- app.plugin(usersPlugin, { prefix: "/api" });
106
- ```
82
+ ---
107
83
 
108
- ### OpenAPI + Scalar Docs
84
+ ## ๐Ÿ“– OpenAPI + Scalar Docs โœจ
109
85
 
110
- Auto-generate an OpenAPI 3.0 spec and serve a beautiful [Scalar](https://scalar.com) API reference UI โ€” all from a single `app.openapi()` call. Routes, validation, and docs stay in sync automatically.
86
+ Auto-generate an OpenAPI 3.0 spec and serve a beautiful [Scalar](https://scalar.com) UI โ€” all from a single `app.openapi()` call. Routes, validation, and docs stay in sync automatically.
111
87
 
112
88
  ```ts
113
89
  import { prince } from "princejs";
@@ -139,112 +115,99 @@ app.listen(3000);
139
115
  // โ†’ GET /docs.json Raw OpenAPI JSON
140
116
  ```
141
117
 
142
- **`api.route()` does three things at once:**
143
- - Registers the route on PrinceJS (same as `app.get()` / `app.post()`)
144
- - Auto-wires `validate(schema.body)` middleware โ€” no separate import needed
145
- - Writes the full OpenAPI spec entry including path params, request body, query params, and response schema
118
+ `api.route()` does three things at once:
146
119
 
147
- | `schema` key | Runtime effect | Scalar docs |
120
+ - โœ… Registers the route on PrinceJS
121
+ - โœ… Auto-wires `validate(schema.body)` โ€” no separate import needed
122
+ - โœ… Writes the full OpenAPI spec entry
123
+
124
+ | `schema` key | Runtime | Scalar Docs |
148
125
  |---|---|---|
149
- | `body` | โœ… Validates & strips via `validate()` | โœ… requestBody model |
150
- | `query` | โŒ docs only | โœ… typed query params |
151
- | `response` | โŒ docs only | โœ… 200 response model |
126
+ | `body` | โœ… Validates request | โœ… requestBody model |
127
+ | `query` | โ€” | โœ… Typed query params |
128
+ | `response` | โ€” | โœ… 200 response model |
129
+
130
+ > Routes on `app.get()` / `app.post()` stay private โ€” never appear in docs.
152
131
 
153
- Routes registered with `app.get()` / `app.post()` directly never appear in the docs โ€” useful for internal health checks, webhooks, and admin endpoints.
132
+ **Themes:** `default` ยท `moon` ยท `purple` ยท `solarized` ยท `bluePlanet` ยท `deepSpace` ยท `saturn` ยท `kepler` ยท `mars`
154
133
 
155
- **Available themes:** `default` ยท `moon` ยท `purple` ยท `solarized` ยท `bluePlanet` ยท `deepSpace` ยท `saturn` ยท `kepler` ยท `mars`
134
+ ---
156
135
 
157
- ### Database (SQLite)
136
+ ## ๐Ÿ”Œ Plugin System
158
137
 
159
- ### End to End Type-Safety
138
+ Share bundles of routes and middleware as reusable plugins:
160
139
 
161
- PrinceJS supports contract-based type safety to sync your frontend and backend seamlessly. By defining an API contract, your client receives full TypeScript autocompletion and type-checking for routes, parameters, and responses.
140
+ ```ts
141
+ import { prince, type PrincePlugin } from "princejs";
162
142
 
143
+ const usersPlugin: PrincePlugin<{ prefix?: string }> = (app, opts) => {
144
+ const base = opts?.prefix ?? "";
163
145
 
164
- **Define Your Contract**
146
+ app.use((req, next) => {
147
+ (req as any).fromPlugin = true;
148
+ return next();
149
+ });
150
+
151
+ app.get(`${base}/users`, (req) => ({
152
+ ok: true,
153
+ fromPlugin: (req as any).fromPlugin,
154
+ }));
155
+ };
156
+
157
+ const app = prince();
158
+ app.plugin(usersPlugin, { prefix: "/api" });
159
+ ```
160
+
161
+ ---
162
+
163
+ ## ๐Ÿ”’ End-to-End Type Safety
164
+
165
+ Define a contract once โ€” your client gets full TypeScript autocompletion automatically:
165
166
 
166
167
  ```ts
167
168
  type ApiContract = {
168
- "GET /users/:id": {
169
- params: { id: string };
170
- response: { id: string; name: string };
169
+ "GET /users/:id": {
170
+ params: { id: string };
171
+ response: { id: string; name: string };
171
172
  };
172
- "POST /users": {
173
- body: { name: string };
174
- response: { id: string; ok: boolean };
173
+ "POST /users": {
174
+ body: { name: string };
175
+ response: { id: string; ok: boolean };
175
176
  };
176
177
  };
177
- ```
178
178
 
179
- **Initialize The Client**
180
-
181
- ```ts
182
179
  import { createClient } from "princejs/client";
183
180
 
184
181
  const client = createClient<ApiContract>("http://localhost:3000");
185
182
 
186
- // Fully typed request and response
187
183
  const user = await client.get("/users/:id", { params: { id: "42" } });
188
- console.log(user.name); // Typed as string
184
+ console.log(user.name); // typed as string โœ…
189
185
  ```
190
186
 
191
187
  ---
192
188
 
193
- ## Deploy (Vercel, Workers, Deno)
194
-
195
- Official adapters let you run the same Prince app on Vercel Edge, Cloudflare Workers, and Deno Deploy.
196
-
197
- **Vercel (Edge)** โ€” `api/[[...route]].ts`:
189
+ ## ๐ŸŒ Deploy Adapters
198
190
 
191
+ **Vercel Edge** โ€” `api/[[...route]].ts`
199
192
  ```ts
200
- import { prince } from "princejs";
201
193
  import { toVercel } from "princejs/vercel";
202
-
203
- const app = prince();
204
- app.get("/", () => ({ message: "Hello from Vercel!" }));
205
-
206
194
  export default toVercel(app);
207
195
  ```
208
196
 
209
- **Cloudflare Workers** โ€” `src/index.ts`:
210
-
197
+ **Cloudflare Workers** โ€” `src/index.ts`
211
198
  ```ts
212
- import { prince } from "princejs";
213
199
  import { toWorkers } from "princejs/cloudflare";
214
-
215
- const app = prince();
216
- app.get("/", () => ({ message: "Hello from Workers!" }));
217
-
218
200
  export default toWorkers(app);
219
201
  ```
220
202
 
221
- **Deno Deploy** โ€” `main.ts`:
222
-
203
+ **Deno Deploy** โ€” `main.ts`
223
204
  ```ts
224
- import { prince } from "princejs";
225
205
  import { toDeno } from "princejs/deno";
226
-
227
- const app = prince();
228
- app.get("/", () => ({ message: "Hello from Deno!" }));
229
-
230
206
  Deno.serve(toDeno(app));
231
207
  ```
232
208
 
233
209
  ---
234
210
 
235
- ## Performance With Oha (oha -c 100 -z 30s)
236
-
237
- | Framework | Req/s | Total |
238
- |-----------|----------------|--------|
239
- | Elysia | 25,312 req/s | 759k |
240
- | Hono | 22,124 req/s | 664k |
241
- | PrinceJS | 21,748 req/s | 653k |
242
- | Express | 9,325 req/s | 280k |
243
-
244
- ### Among the top three
245
-
246
- ---
247
-
248
211
  ## ๐ŸŽฏ Full Example
249
212
 
250
213
  ```ts
@@ -252,89 +215,51 @@ import { prince } from "princejs";
252
215
  import { cors, logger, rateLimit, auth, apiKey, jwt, session, compress, serve } from "princejs/middleware";
253
216
  import { validate } from "princejs/validation";
254
217
  import { cache, upload, sse } from "princejs/helpers";
255
- import { cron, openapi } from "princejs/scheduler";
256
- import { Html, Head, Body, H1, P, render } from "princejs/jsx"
218
+ import { cron } from "princejs/scheduler";
219
+ import { Html, Head, Body, H1, P, render } from "princejs/jsx";
257
220
  import { db } from "princejs/db";
258
221
  import { z } from "zod";
259
222
 
260
223
  const app = prince(true);
261
224
 
225
+ // Global middleware
262
226
  app.use(cors());
263
227
  app.use(logger());
264
228
  app.use(rateLimit({ max: 100, window: 60 }));
265
-
266
229
  app.use(serve({ root: "./public" }));
267
-
268
- app.use(validate(z.object({ name: z.string() })));
269
-
270
230
  app.use(jwt(key));
271
231
  app.use(session({ secret: "key" }));
272
232
  app.use(compress());
273
233
 
274
- const Page = () => Html(
275
- Head("Test Page"),
276
- Body(
277
- H1("Hello World"),
278
- P("This is a test")
279
- )
280
- );
281
-
282
- // With props (optional)
283
- const Card = (props: any) => Div(
284
- { className: "card", style: "padding: 1rem;" },
285
- H1(props.title),
286
- P(props.content)
287
- );
288
-
289
- // Without props
290
- const Simple = () => Div(
291
- H1("No Props Needed"),
292
- P("Just pure content")
293
- );
294
-
295
- const requireAuth = async (req: any, next: any) => {
296
- const token = req.headers.get("Authorization");
297
- if (!token) return new Response("Unauthorized", { status: 401 });
298
- req.user = { id: 1, name: "Alice" };
299
- return next();
300
- };
301
-
302
- app.get("/protected", requireAuth, async (req) => {
303
- return { user: req.user };
304
- });
234
+ // JSX
235
+ const Page = () => Html(Head("Test Page"), Body(H1("Hello World"), P("This is a test")));
236
+ app.get("/jsx", () => render(Page()));
305
237
 
238
+ // Database
306
239
  const users = db.sqlite("./db.sqlite", "CREATE TABLE users...");
240
+ app.get("/users", () => users.query("SELECT * FROM users"));
307
241
 
242
+ // WebSockets
308
243
  app.ws("/chat", {
309
244
  open: (ws) => ws.send("Welcome!"),
310
- message: (ws, msg) => ws.send(`Echo: ${msg}`)
245
+ message: (ws, msg) => ws.send(`Echo: ${msg}`),
311
246
  });
312
247
 
313
-
248
+ // Auth
314
249
  app.get("/protected", auth(), (req) => ({ user: req.user }));
315
250
  app.get("/api", apiKey({ keys: ["key_123"] }), handler);
316
251
 
317
- app.get("/", () => ({ message: "Welcome to PrinceJS" }));
318
-
319
- app.get("/users/:id", (req) => ({ id: req.params.id }));
320
-
321
- app.get("/jsx", () => render(Page()));
322
-
252
+ // Helpers
323
253
  app.get("/data", cache(60)(() => ({ time: Date.now() })));
324
-
325
254
  app.post("/upload", upload(), (req) => ({ files: Object.keys(req.files || {}) }));
326
-
327
255
  app.get("/events", sse(), (req) => {
328
256
  setInterval(() => req.sseSend({ time: Date.now() }), 1000);
329
257
  });
330
258
 
331
- app.get("/count", (req) => ({ visits: req.session.visits++ || 1 }));
332
-
333
- app.get("/users", () => users.query("SELECT * FROM users"));
334
-
259
+ // Cron
335
260
  cron("*/1 * * * *", () => console.log("PrinceJS heartbeat"));
336
261
 
337
- // OpenAPI + Scalar
262
+ // OpenAPI + Scalar docs
338
263
  const api = app.openapi({ title: "PrinceJS App", version: "1.0.0" }, "/docs");
339
264
  api.route("GET", "/items", {
340
265
  summary: "List items",
@@ -353,21 +278,15 @@ app.listen(3000);
353
278
  ## ๐Ÿ“ฆ Installation
354
279
 
355
280
  ```bash
356
- npm install princejs
357
- # or
358
281
  bun add princejs
359
282
  # or
283
+ npm install princejs
284
+ # or
360
285
  yarn add princejs
361
286
  ```
362
287
 
363
288
  ---
364
289
 
365
- ## ๐Ÿ“š Documentation
366
-
367
- Visit: **princejs.vercel.app**
368
-
369
- ---
370
-
371
290
  ## ๐Ÿค Contributing
372
291
 
373
292
  ```bash
@@ -379,20 +298,19 @@ bun test
379
298
 
380
299
  ---
381
300
 
382
- ## โญ Star This Repo
383
-
384
- If PrinceJS helped you, star the repo!
301
+ ## ๐Ÿ”— Links
385
302
 
386
- GitHub: [https://github.com/MatthewTheCoder1218/princejs](https://github.com/MatthewTheCoder1218/princejs)
303
+ - ๐ŸŒ Website: [princejs.vercel.app](https://princejs.vercel.app)
304
+ - ๐Ÿ“ฆ npm: [npmjs.com/package/princejs](https://www.npmjs.com/package/princejs)
305
+ - ๐Ÿ’ป GitHub: [github.com/MatthewTheCoder1218/princejs](https://github.com/MatthewTheCoder1218/princejs)
306
+ - ๐Ÿฆ Twitter: [@princejs_bun](https://twitter.com/princejs_bun)
387
307
 
388
308
  ---
389
309
 
390
- ## ๐Ÿ”— Links
310
+ <div align="center">
391
311
 
392
- * npm: [https://www.npmjs.com/package/princejs](https://www.npmjs.com/package/princejs)
393
- * GitHub: [https://github.com/MatthewTheCoder1218/princejs](https://github.com/MatthewTheCoder1218/princejs)
394
- * Twitter: [https://twitter.com/Lil_Prince_1218](https://twitter.com/Lil_Prince_1218)
312
+ **PrinceJS: Small in size. Giant in capability. ๐Ÿ‘‘**
395
313
 
396
- ---
314
+ *Built with โค๏ธ in Nigeria*
397
315
 
398
- **PrinceJS: Small in size. Giant in capability. ๐Ÿš€**
316
+ </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "princejs",
3
- "version": "1.9.4",
3
+ "version": "1.9.5",
4
4
  "description": "An easy and fast backend framework that is among the top three โ€” by a 13yo developer, for developers.",
5
5
  "main": "dist/prince.js",
6
6
  "types": "dist/prince.d.ts",