princejs 1.9.6 โ 2.0.0
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 +109 -10
- package/dist/adapters/node.d.ts +47 -0
- package/dist/adapters/node.d.ts.map +1 -0
- package/dist/prince.d.ts +12 -0
- package/dist/prince.d.ts.map +1 -1
- package/dist/prince.js +39 -3
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
<img src="./src/images/og.png" alt="PrinceJS"/>
|
|
4
|
-
|
|
5
3
|
# ๐ PrinceJS
|
|
6
4
|
|
|
7
5
|
**Ultra-clean, modern & minimal Bun web framework.**
|
|
@@ -36,9 +34,9 @@ Benchmarked with `oha -c 100 -z 30s` on Windows 10:
|
|
|
36
34
|
## ๐ Quick Start
|
|
37
35
|
|
|
38
36
|
```bash
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
npm install princejs
|
|
38
|
+
bun add princejs
|
|
39
|
+
yarn add princejs
|
|
42
40
|
```
|
|
43
41
|
|
|
44
42
|
```ts
|
|
@@ -77,7 +75,8 @@ app.listen(3000);
|
|
|
77
75
|
| SQLite Database | `princejs/db` |
|
|
78
76
|
| Plugin System | `princejs` |
|
|
79
77
|
| End-to-End Type Safety | `princejs/client` |
|
|
80
|
-
| Deploy Adapters | `princejs/vercel` ยท `princejs/cloudflare` ยท `princejs/deno` |
|
|
78
|
+
| Deploy Adapters | `princejs/vercel` ยท `princejs/cloudflare` ยท `princejs/deno` ยท `princejs/node` |
|
|
79
|
+
| Lifecycle Hooks | `princejs` |
|
|
81
80
|
|
|
82
81
|
---
|
|
83
82
|
|
|
@@ -160,6 +159,57 @@ app.plugin(usersPlugin, { prefix: "/api" });
|
|
|
160
159
|
|
|
161
160
|
---
|
|
162
161
|
|
|
162
|
+
## ๐ฃ Lifecycle Hooks
|
|
163
|
+
|
|
164
|
+
React to key moments in request processing with lifecycle hooks:
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
import { prince } from "princejs";
|
|
168
|
+
|
|
169
|
+
const app = prince();
|
|
170
|
+
|
|
171
|
+
// Called for every incoming request
|
|
172
|
+
app.onRequest((req) => {
|
|
173
|
+
console.log(`๐ฅ Request received: ${req.method} ${req.url}`);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Called before handler execution
|
|
177
|
+
app.onBeforeHandle((req, path, method) => {
|
|
178
|
+
console.log(`๐ About to handle: ${method} ${path}`);
|
|
179
|
+
(req as any).startTime = Date.now();
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Called after successful handler execution
|
|
183
|
+
app.onAfterHandle((req, res, path, method) => {
|
|
184
|
+
const duration = Date.now() - (req as any).startTime;
|
|
185
|
+
console.log(`โ
Response: ${method} ${path} ${res.status} (${duration}ms)`);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Called when handler throws an error
|
|
189
|
+
app.onError((err, req, path, method) => {
|
|
190
|
+
console.error(`โ Error in ${method} ${path}:`, err.message);
|
|
191
|
+
// Send alert, log to monitoring service, etc.
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
app.get("/users", () => ({ users: [] }));
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Hook execution order:**
|
|
198
|
+
1. `onRequest` โ early for request-wide setup
|
|
199
|
+
2. `onBeforeHandle` โ just before route handler runs
|
|
200
|
+
3. Handler executes
|
|
201
|
+
4. `onAfterHandle` โ after success (on error, skipped)
|
|
202
|
+
5. `onError` โ only if handler throws (skips onAfterHandle)
|
|
203
|
+
|
|
204
|
+
**Use cases:**
|
|
205
|
+
- ๐ Metrics & observability
|
|
206
|
+
- ๐ Request inspection & debugging
|
|
207
|
+
- โฑ๏ธ Timing & performance monitoring
|
|
208
|
+
- ๐จ Error tracking & alerting
|
|
209
|
+
- ๐ Security audits & compliance logging
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
163
213
|
## ๐ End-to-End Type Safety
|
|
164
214
|
|
|
165
215
|
Define a contract once โ your client gets full TypeScript autocompletion automatically:
|
|
@@ -206,6 +256,25 @@ import { toDeno } from "princejs/deno";
|
|
|
206
256
|
Deno.serve(toDeno(app));
|
|
207
257
|
```
|
|
208
258
|
|
|
259
|
+
**Node Adapter** - `server.ts`
|
|
260
|
+
```ts
|
|
261
|
+
import { createServer } from "http";
|
|
262
|
+
import { toNode, toExpress } from "princejs/node";
|
|
263
|
+
|
|
264
|
+
const app = prince();
|
|
265
|
+
app.get("/", () => ({ message: "Hello from Node!" }));
|
|
266
|
+
|
|
267
|
+
// Native Node.js http
|
|
268
|
+
const server = createServer(toNode(app));
|
|
269
|
+
server.listen(3000);
|
|
270
|
+
|
|
271
|
+
// Or with Express
|
|
272
|
+
import express from "express";
|
|
273
|
+
const expressApp = express();
|
|
274
|
+
expressApp.all("*", toExpress(app));
|
|
275
|
+
expressApp.listen(3000);
|
|
276
|
+
```
|
|
277
|
+
|
|
209
278
|
---
|
|
210
279
|
|
|
211
280
|
## ๐ฏ Full Example
|
|
@@ -222,7 +291,29 @@ import { z } from "zod";
|
|
|
222
291
|
|
|
223
292
|
const app = prince(true);
|
|
224
293
|
|
|
225
|
-
//
|
|
294
|
+
// ==========================================
|
|
295
|
+
// LIFECYCLE HOOKS - Timing & Observability
|
|
296
|
+
// ==========================================
|
|
297
|
+
app.onRequest((req) => {
|
|
298
|
+
(req as any).startTime = Date.now();
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
app.onBeforeHandle((req, path, method) => {
|
|
302
|
+
console.log(`๐ Handling: ${method} ${path}`);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
app.onAfterHandle((req, res, path, method) => {
|
|
306
|
+
const duration = Date.now() - (req as any).startTime;
|
|
307
|
+
console.log(`โ
${method} ${path} โ ${res.status} (${duration}ms)`);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
app.onError((err, req, path, method) => {
|
|
311
|
+
console.error(`โ ${method} ${path} failed:`, err.message);
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
// ==========================================
|
|
315
|
+
// GLOBAL MIDDLEWARE
|
|
316
|
+
// ==========================================
|
|
226
317
|
app.use(cors());
|
|
227
318
|
app.use(logger());
|
|
228
319
|
app.use(rateLimit({ max: 100, window: 60 }));
|
|
@@ -231,6 +322,10 @@ app.use(jwt(key));
|
|
|
231
322
|
app.use(session({ secret: "key" }));
|
|
232
323
|
app.use(compress());
|
|
233
324
|
|
|
325
|
+
// ==========================================
|
|
326
|
+
// ROUTES
|
|
327
|
+
// ==========================================
|
|
328
|
+
|
|
234
329
|
// JSX
|
|
235
330
|
const Page = () => Html(Head("Test Page"), Body(H1("Hello World"), P("This is a test")));
|
|
236
331
|
app.get("/jsx", () => render(Page()));
|
|
@@ -247,7 +342,7 @@ app.ws("/chat", {
|
|
|
247
342
|
|
|
248
343
|
// Auth
|
|
249
344
|
app.get("/protected", auth(), (req) => ({ user: req.user }));
|
|
250
|
-
app.get("/api", apiKey({ keys: ["key_123"] }),
|
|
345
|
+
app.get("/api", apiKey({ keys: ["key_123"] }), (req) => ({ ok: true }));
|
|
251
346
|
|
|
252
347
|
// Helpers
|
|
253
348
|
app.get("/data", cache(60)(() => ({ time: Date.now() })));
|
|
@@ -256,10 +351,14 @@ app.get("/events", sse(), (req) => {
|
|
|
256
351
|
setInterval(() => req.sseSend({ time: Date.now() }), 1000);
|
|
257
352
|
});
|
|
258
353
|
|
|
259
|
-
//
|
|
354
|
+
// ==========================================
|
|
355
|
+
// CRON JOBS
|
|
356
|
+
// ==========================================
|
|
260
357
|
cron("*/1 * * * *", () => console.log("PrinceJS heartbeat"));
|
|
261
358
|
|
|
262
|
-
//
|
|
359
|
+
// ==========================================
|
|
360
|
+
// OPENAPI + SCALAR DOCS
|
|
361
|
+
// ==========================================
|
|
263
362
|
const api = app.openapi({ title: "PrinceJS App", version: "1.0.0" }, "/docs");
|
|
264
363
|
api.route("GET", "/items", {
|
|
265
364
|
summary: "List items",
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Official Node.js deploy adapter for PrinceJS
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* // server.ts
|
|
6
|
+
* import { createServer } from "http";
|
|
7
|
+
* import { prince } from "princejs";
|
|
8
|
+
* import { toNode } from "princejs/node";
|
|
9
|
+
*
|
|
10
|
+
* const app = prince();
|
|
11
|
+
* app.get("/", () => ({ message: "Hello from Node.js!" }));
|
|
12
|
+
*
|
|
13
|
+
* const server = createServer(toNode(app));
|
|
14
|
+
* server.listen(3000, () => {
|
|
15
|
+
* console.log("Listening on http://localhost:3000");
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // With Express.js
|
|
20
|
+
* import express from "express";
|
|
21
|
+
* import { prince } from "princejs";
|
|
22
|
+
* import { toExpress } from "princejs/node";
|
|
23
|
+
*
|
|
24
|
+
* const app = express();
|
|
25
|
+
* const princeApp = prince();
|
|
26
|
+
* princeApp.get("/", () => ({ message: "Hello!" }));
|
|
27
|
+
*
|
|
28
|
+
* app.all("*", toExpress(princeApp));
|
|
29
|
+
* app.listen(3000);
|
|
30
|
+
*/
|
|
31
|
+
export type PrinceApp = {
|
|
32
|
+
fetch(request: Request): Promise<Response>;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Converts a Prince app to a Node.js http.createServer() handler
|
|
36
|
+
* @example
|
|
37
|
+
* const server = createServer(toNode(app));
|
|
38
|
+
* server.listen(3000);
|
|
39
|
+
*/
|
|
40
|
+
export declare function toNode(app: PrinceApp): (req: any, res: any) => Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Converts a Prince app to an Express.js middleware handler
|
|
43
|
+
* @example
|
|
44
|
+
* app.all("*", toExpress(princeApp));
|
|
45
|
+
*/
|
|
46
|
+
export declare function toExpress(app: PrinceApp): (req: any, res: any, next?: any) => Promise<void>;
|
|
47
|
+
//# sourceMappingURL=node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/adapters/node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,MAAM,MAAM,SAAS,GAAG;IAAE,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CAAE,CAAC;AAEvE;;;;;GAKG;AACH,wBAAgB,MAAM,CACpB,GAAG,EAAE,SAAS,GACb,CACD,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,KACL,OAAO,CAAC,IAAI,CAAC,CAuCjB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,SAAS,GACb,CACD,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,EACR,IAAI,CAAC,EAAE,GAAG,KACP,OAAO,CAAC,IAAI,CAAC,CAoCjB"}
|
package/dist/prince.d.ts
CHANGED
|
@@ -14,6 +14,10 @@ export interface PrinceRequest extends Request {
|
|
|
14
14
|
sseSend?: (data: any, event?: string, id?: string) => void;
|
|
15
15
|
[key: string]: any;
|
|
16
16
|
}
|
|
17
|
+
export type OnRequest = (req: PrinceRequest) => void | Promise<void>;
|
|
18
|
+
export type OnBeforeHandle = (req: PrinceRequest, path: string, method: string) => void | Promise<void>;
|
|
19
|
+
export type OnAfterHandle = (req: PrinceRequest, res: Response, path: string, method: string) => void | Promise<void>;
|
|
20
|
+
export type OnError = (err: any, req: PrinceRequest, path: string, method: string) => void | Promise<void>;
|
|
17
21
|
interface WebSocketHandler {
|
|
18
22
|
open?: (ws: any) => void;
|
|
19
23
|
message?: (ws: any, msg: string | Buffer) => void;
|
|
@@ -62,6 +66,10 @@ export declare class Prince {
|
|
|
62
66
|
private staticRoutes;
|
|
63
67
|
private staticMiddlewares;
|
|
64
68
|
private routeCache;
|
|
69
|
+
private onRequestHooks;
|
|
70
|
+
private onBeforeHandleHooks;
|
|
71
|
+
private onAfterHandleHooks;
|
|
72
|
+
private onErrorHooks;
|
|
65
73
|
constructor(devMode?: boolean);
|
|
66
74
|
use(mw: Middleware): this;
|
|
67
75
|
/**
|
|
@@ -77,6 +85,10 @@ export declare class Prince {
|
|
|
77
85
|
*/
|
|
78
86
|
plugin<TOptions = any>(plugin: PrincePlugin<TOptions>, options?: TOptions): this;
|
|
79
87
|
error(fn: (err: any, req: PrinceRequest) => Response): this;
|
|
88
|
+
onRequest(hook: OnRequest): this;
|
|
89
|
+
onBeforeHandle(hook: OnBeforeHandle): this;
|
|
90
|
+
onAfterHandle(hook: OnAfterHandle): this;
|
|
91
|
+
onError(hook: OnError): this;
|
|
80
92
|
json(data: any, status?: number): Response;
|
|
81
93
|
response(): ResponseBuilder;
|
|
82
94
|
get(path: string, ...args: (RouteHandler | Middleware)[]): this;
|
package/dist/prince.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prince.d.ts","sourceRoot":"","sources":["../src/prince.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAe,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE9E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,KAAK,IAAI,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;AACpC,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,GAAG,QAAQ,GAAG,SAAS,CAAC;AAC3G,KAAK,aAAa,GAAG,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,GAAG,UAAU,CAAC;AAE1E,MAAM,WAAW,aAAc,SAAQ,OAAO;IAC5C,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC7B,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"prince.d.ts","sourceRoot":"","sources":["../src/prince.ts"],"names":[],"mappings":"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"}
|
package/dist/prince.js
CHANGED
|
@@ -310,6 +310,10 @@ class Prince {
|
|
|
310
310
|
staticRoutes = new Map;
|
|
311
311
|
staticMiddlewares = new Map;
|
|
312
312
|
routeCache = new Map;
|
|
313
|
+
onRequestHooks = [];
|
|
314
|
+
onBeforeHandleHooks = [];
|
|
315
|
+
onAfterHandleHooks = [];
|
|
316
|
+
onErrorHooks = [];
|
|
313
317
|
constructor(devMode = false) {
|
|
314
318
|
this.devMode = devMode;
|
|
315
319
|
}
|
|
@@ -325,6 +329,22 @@ class Prince {
|
|
|
325
329
|
this.errorHandler = fn;
|
|
326
330
|
return this;
|
|
327
331
|
}
|
|
332
|
+
onRequest(hook) {
|
|
333
|
+
this.onRequestHooks.push(hook);
|
|
334
|
+
return this;
|
|
335
|
+
}
|
|
336
|
+
onBeforeHandle(hook) {
|
|
337
|
+
this.onBeforeHandleHooks.push(hook);
|
|
338
|
+
return this;
|
|
339
|
+
}
|
|
340
|
+
onAfterHandle(hook) {
|
|
341
|
+
this.onAfterHandleHooks.push(hook);
|
|
342
|
+
return this;
|
|
343
|
+
}
|
|
344
|
+
onError(hook) {
|
|
345
|
+
this.onErrorHooks.push(hook);
|
|
346
|
+
return this;
|
|
347
|
+
}
|
|
328
348
|
json(data, status = 200) {
|
|
329
349
|
return new Response(JSON.stringify(data), {
|
|
330
350
|
status,
|
|
@@ -572,7 +592,7 @@ class Prince {
|
|
|
572
592
|
}
|
|
573
593
|
return null;
|
|
574
594
|
}
|
|
575
|
-
async executeHandler(req, handler, params, query, routeMiddlewares) {
|
|
595
|
+
async executeHandler(req, handler, params, query, routeMiddlewares, method, pathname) {
|
|
576
596
|
Object.defineProperty(req, "params", { value: params, writable: true, configurable: true });
|
|
577
597
|
Object.defineProperty(req, "query", { value: query, writable: true, configurable: true });
|
|
578
598
|
if (["POST", "PUT", "PATCH"].includes(req.method) && !req.parsedBody) {
|
|
@@ -593,6 +613,9 @@ class Prince {
|
|
|
593
613
|
},
|
|
594
614
|
configurable: true
|
|
595
615
|
});
|
|
616
|
+
for (const hook of this.onBeforeHandleHooks) {
|
|
617
|
+
await hook(req, pathname, method);
|
|
618
|
+
}
|
|
596
619
|
const allMiddlewares = routeMiddlewares.length > 0 ? [...this.middlewares, ...routeMiddlewares] : this.middlewares;
|
|
597
620
|
let i = 0;
|
|
598
621
|
const next = async () => {
|
|
@@ -610,13 +633,20 @@ class Prince {
|
|
|
610
633
|
return new Response(res);
|
|
611
634
|
return this.json(res);
|
|
612
635
|
};
|
|
613
|
-
|
|
636
|
+
const response = await next();
|
|
637
|
+
for (const hook of this.onAfterHandleHooks) {
|
|
638
|
+
await hook(req, response.clone(), pathname, method);
|
|
639
|
+
}
|
|
640
|
+
return response;
|
|
614
641
|
}
|
|
615
642
|
async handleFetch(req) {
|
|
616
643
|
const url = new URL(req.url);
|
|
617
644
|
const r = req;
|
|
618
645
|
const method = req.method;
|
|
619
646
|
const pathname = url.pathname;
|
|
647
|
+
for (const hook of this.onRequestHooks) {
|
|
648
|
+
await hook(r);
|
|
649
|
+
}
|
|
620
650
|
const routeMatch = this.findRoute(method, pathname);
|
|
621
651
|
if (!routeMatch) {
|
|
622
652
|
return this.json({ error: "Not Found" }, 404);
|
|
@@ -630,12 +660,18 @@ class Prince {
|
|
|
630
660
|
}
|
|
631
661
|
});
|
|
632
662
|
}
|
|
633
|
-
return this.executeHandler(r, routeMatch.handler, routeMatch.params, url.searchParams, routeMatch.middlewares);
|
|
663
|
+
return this.executeHandler(r, routeMatch.handler, routeMatch.params, url.searchParams, routeMatch.middlewares, method, pathname);
|
|
634
664
|
}
|
|
635
665
|
async fetch(req) {
|
|
666
|
+
const url = new URL(req.url);
|
|
667
|
+
const pathname = url.pathname;
|
|
668
|
+
const method = req.method;
|
|
636
669
|
try {
|
|
637
670
|
return await this.handleFetch(req);
|
|
638
671
|
} catch (err) {
|
|
672
|
+
for (const hook of this.onErrorHooks) {
|
|
673
|
+
await hook(err, req, pathname, method);
|
|
674
|
+
}
|
|
639
675
|
if (this.errorHandler)
|
|
640
676
|
return this.errorHandler(err, req);
|
|
641
677
|
if (this.devMode) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "princejs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
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",
|
|
@@ -45,6 +45,10 @@
|
|
|
45
45
|
"import": "./dist/adapters/deno.js",
|
|
46
46
|
"types": "./dist/adapters/deno.d.ts"
|
|
47
47
|
},
|
|
48
|
+
"./node": {
|
|
49
|
+
"import": "./dist/adapters/node.js",
|
|
50
|
+
"types": "./dist/adapters/node.d.ts"
|
|
51
|
+
},
|
|
48
52
|
"./client": {
|
|
49
53
|
"import": "./dist/client.js",
|
|
50
54
|
"types": "./dist/client.d.ts"
|