princejs 2.1.6 → 2.2.1
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 +192 -4
- package/dist/helpers.d.ts +3 -0
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +56 -0
- package/dist/middleware.d.ts +22 -0
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +3149 -347
- package/dist/prince.d.ts +28 -0
- package/dist/prince.d.ts.map +1 -1
- package/dist/prince.js +38 -0
- package/package.json +1 -1
package/Readme.md
CHANGED
|
@@ -61,9 +61,9 @@ app.listen(3000);
|
|
|
61
61
|
|
|
62
62
|
| Feature | Import |
|
|
63
63
|
|---------|--------|
|
|
64
|
-
| Routing, WebSockets, OpenAPI, Plugins, Lifecycle Hooks, Cookies, IP | `princejs` |
|
|
65
|
-
| CORS, Logger, JWT, Auth, Rate Limit, Validate, Compress, Session, API Key | `princejs/middleware` |
|
|
66
|
-
| File Uploads, SSE, In-memory Cache | `princejs/helpers` |
|
|
64
|
+
| Routing, Route Grouping, WebSockets, OpenAPI, Plugins, Lifecycle Hooks, Cookies, IP | `princejs` |
|
|
65
|
+
| CORS, Logger, JWT, JWKS, Auth, Rate Limit, Validate, Compress, Session, API Key, Secure Headers, Timeout, Request ID, IP Restriction, Static Files | `princejs/middleware` |
|
|
66
|
+
| File Uploads, SSE, Streaming, In-memory Cache | `princejs/helpers` |
|
|
67
67
|
| Cron Scheduler | `princejs/scheduler` |
|
|
68
68
|
| JSX / SSR | `princejs/jsx` |
|
|
69
69
|
| SQLite Database | `princejs/db` |
|
|
@@ -155,6 +155,188 @@ app.post("/admin", (req) => {
|
|
|
155
155
|
|
|
156
156
|
---
|
|
157
157
|
|
|
158
|
+
|
|
159
|
+
## 🗂️ Route Grouping
|
|
160
|
+
|
|
161
|
+
Group routes under a shared prefix with optional shared middleware. Zero overhead at request time — purely a registration convenience.
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
import { prince } from "princejs";
|
|
165
|
+
|
|
166
|
+
const app = prince();
|
|
167
|
+
|
|
168
|
+
// Basic grouping
|
|
169
|
+
app.group("/api", (r) => {
|
|
170
|
+
r.get("/users", () => ({ users: [] }));
|
|
171
|
+
r.post("/users", (req) => ({ created: req.parsedBody }));
|
|
172
|
+
r.get("/users/:id", (req) => ({ id: req.params?.id }));
|
|
173
|
+
});
|
|
174
|
+
// → GET /api/users
|
|
175
|
+
// → POST /api/users
|
|
176
|
+
// → GET /api/users/:id
|
|
177
|
+
|
|
178
|
+
// With shared middleware — applies to every route in the group
|
|
179
|
+
import { auth } from "princejs/middleware";
|
|
180
|
+
|
|
181
|
+
app.group("/admin", auth(), (r) => {
|
|
182
|
+
r.get("/stats", () => ({ stats: {} }));
|
|
183
|
+
r.delete("/users/:id", (req) => ({ deleted: req.params?.id }));
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Chainable
|
|
187
|
+
app
|
|
188
|
+
.group("/v1", (r) => { r.get("/ping", () => ({ v: 1 })); })
|
|
189
|
+
.group("/v2", (r) => { r.get("/ping", () => ({ v: 2 })); });
|
|
190
|
+
|
|
191
|
+
app.listen(3000);
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 🛡️ Secure Headers
|
|
197
|
+
|
|
198
|
+
One call sets all the security headers your production app needs:
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
import { secureHeaders } from "princejs/middleware";
|
|
202
|
+
|
|
203
|
+
app.use(secureHeaders());
|
|
204
|
+
// Sets: X-Frame-Options, X-Content-Type-Options, X-XSS-Protection,
|
|
205
|
+
// Strict-Transport-Security, Referrer-Policy
|
|
206
|
+
|
|
207
|
+
// Custom options
|
|
208
|
+
app.use(secureHeaders({
|
|
209
|
+
xFrameOptions: "DENY",
|
|
210
|
+
contentSecurityPolicy: "default-src 'self'",
|
|
211
|
+
permissionsPolicy: "camera=(), microphone=()",
|
|
212
|
+
strictTransportSecurity: "max-age=63072000; includeSubDomains; preload",
|
|
213
|
+
}));
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## ⏱️ Request Timeout
|
|
219
|
+
|
|
220
|
+
Kill hanging requests before they pile up:
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
import { timeout } from "princejs/middleware";
|
|
224
|
+
|
|
225
|
+
app.use(timeout(5000)); // 5 second global timeout → 408
|
|
226
|
+
app.use(timeout(3000, "Slow!")); // custom message
|
|
227
|
+
|
|
228
|
+
// Per-route timeout
|
|
229
|
+
app.get("/heavy", timeout(10000), (req) => heavyOperation());
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## 🏷️ Request ID
|
|
235
|
+
|
|
236
|
+
Attach a unique ID to every request for distributed tracing and log correlation:
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
import { requestId } from "princejs/middleware";
|
|
240
|
+
|
|
241
|
+
app.use(requestId());
|
|
242
|
+
// → sets req.id and X-Request-ID response header
|
|
243
|
+
|
|
244
|
+
// Custom header name
|
|
245
|
+
app.use(requestId({ header: "X-Trace-ID" }));
|
|
246
|
+
|
|
247
|
+
// Custom generator
|
|
248
|
+
app.use(requestId({ generator: () => `req-${Date.now()}` }));
|
|
249
|
+
|
|
250
|
+
app.get("/", (req) => ({ requestId: req.id }));
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## 🚫 IP Restriction
|
|
256
|
+
|
|
257
|
+
Allow or block specific IPs:
|
|
258
|
+
|
|
259
|
+
```ts
|
|
260
|
+
import { ipRestriction } from "princejs/middleware";
|
|
261
|
+
|
|
262
|
+
// Only allow these IPs
|
|
263
|
+
app.use(ipRestriction({ allowList: ["192.168.1.1", "10.0.0.1"] }));
|
|
264
|
+
|
|
265
|
+
// Block these IPs
|
|
266
|
+
app.use(ipRestriction({ denyList: ["1.2.3.4"] }));
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## 📁 Static Files
|
|
272
|
+
|
|
273
|
+
Serve a directory of static files. Falls through to your routes if the file doesn't exist:
|
|
274
|
+
|
|
275
|
+
```ts
|
|
276
|
+
import { serveStatic } from "princejs/middleware";
|
|
277
|
+
|
|
278
|
+
app.use(serveStatic("./public"));
|
|
279
|
+
// → GET /logo.png serves ./public/logo.png
|
|
280
|
+
// → GET / serves ./public/index.html
|
|
281
|
+
// → GET /api/users falls through to your route handler
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## 🌊 Streaming
|
|
287
|
+
|
|
288
|
+
Stream chunked responses for AI/LLM output, large payloads, or anything that generates data over time:
|
|
289
|
+
|
|
290
|
+
```ts
|
|
291
|
+
import { stream } from "princejs/helpers";
|
|
292
|
+
|
|
293
|
+
// Async generator — cleanest for AI token streaming
|
|
294
|
+
app.get("/ai", stream(async function*(req) {
|
|
295
|
+
yield "Hello ";
|
|
296
|
+
await delay(100);
|
|
297
|
+
yield "from ";
|
|
298
|
+
yield "PrinceJS!";
|
|
299
|
+
}));
|
|
300
|
+
|
|
301
|
+
// Async callback
|
|
302
|
+
app.get("/data", stream(async (req) => {
|
|
303
|
+
req.streamSend("chunk 1");
|
|
304
|
+
await fetchMoreData();
|
|
305
|
+
req.streamSend("chunk 2");
|
|
306
|
+
}));
|
|
307
|
+
|
|
308
|
+
// Custom content type for binary or JSON streams
|
|
309
|
+
app.get("/events", stream(async function*(req) {
|
|
310
|
+
for (const item of items) {
|
|
311
|
+
yield JSON.stringify(item) + "\n";
|
|
312
|
+
}
|
|
313
|
+
}, { contentType: "application/x-ndjson" }));
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## 🔑 JWKS / Third-Party Auth
|
|
319
|
+
|
|
320
|
+
Verify JWTs from Auth0, Clerk, Supabase, or any JWKS endpoint — no symmetric key needed:
|
|
321
|
+
|
|
322
|
+
```ts
|
|
323
|
+
import { jwks } from "princejs/middleware";
|
|
324
|
+
|
|
325
|
+
// Auth0
|
|
326
|
+
app.use(jwks("https://your-domain.auth0.com/.well-known/jwks.json"));
|
|
327
|
+
|
|
328
|
+
// Clerk
|
|
329
|
+
app.use(jwks("https://your-clerk-domain.clerk.accounts.dev/.well-known/jwks.json"));
|
|
330
|
+
|
|
331
|
+
// Supabase
|
|
332
|
+
app.use(jwks("https://your-project.supabase.co/auth/v1/.well-known/jwks.json"));
|
|
333
|
+
|
|
334
|
+
// req.user is set after verification, same as jwt()
|
|
335
|
+
app.get("/protected", auth(), (req) => ({ user: req.user }));
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
158
340
|
## 📖 OpenAPI + Scalar Docs ✨
|
|
159
341
|
|
|
160
342
|
Auto-generate an OpenAPI 3.0 spec and serve a beautiful [Scalar](https://scalar.com) UI — all from a single `app.openapi()` call.
|
|
@@ -352,8 +534,11 @@ import {
|
|
|
352
534
|
session,
|
|
353
535
|
compress,
|
|
354
536
|
validate,
|
|
537
|
+
secureHeaders,
|
|
538
|
+
timeout,
|
|
539
|
+
requestId,
|
|
355
540
|
} from "princejs/middleware";
|
|
356
|
-
import { cache, upload, sse } from "princejs/helpers";
|
|
541
|
+
import { cache, upload, sse, stream } from "princejs/helpers";
|
|
357
542
|
import { cron } from "princejs/scheduler";
|
|
358
543
|
import { Html, Head, Body, H1, P, render } from "princejs/jsx";
|
|
359
544
|
import { db } from "princejs/db";
|
|
@@ -372,6 +557,9 @@ app.onError((err, req, path, method) => {
|
|
|
372
557
|
});
|
|
373
558
|
|
|
374
559
|
// ── Global middleware ─────────────────────────────────────
|
|
560
|
+
app.use(secureHeaders());
|
|
561
|
+
app.use(requestId());
|
|
562
|
+
app.use(timeout(10000));
|
|
375
563
|
app.use(cors());
|
|
376
564
|
app.use(logger());
|
|
377
565
|
app.use(rateLimit(100, 60));
|
package/dist/helpers.d.ts
CHANGED
|
@@ -3,4 +3,7 @@ export declare const cache: (ttl: number) => (handler: any) => (req: PrinceReque
|
|
|
3
3
|
export declare const email: (to: string, subject: string, html: string) => Promise<void>;
|
|
4
4
|
export declare const upload: () => (req: PrinceRequest) => Promise<Response>;
|
|
5
5
|
export declare const sse: () => (req: PrinceRequest) => Response;
|
|
6
|
+
export declare const stream: (handler: (req: PrinceRequest) => AsyncGenerator<string | Uint8Array, void, unknown> | void | Promise<void>, options?: {
|
|
7
|
+
contentType?: string;
|
|
8
|
+
}) => (req: PrinceRequest) => Response;
|
|
6
9
|
//# sourceMappingURL=helpers.d.ts.map
|
package/dist/helpers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,eAAO,MAAM,KAAK,GAAI,KAAK,MAAM,MAEvB,SAAS,GAAG,MAAY,KAAK,aAAa,iBASnD,CAAC;AAGF,eAAO,MAAM,KAAK,GAAU,IAAI,MAAM,EAAE,SAAS,MAAM,EAAE,MAAM,MAAM,kBAMpE,CAAC;AAGF,eAAO,MAAM,MAAM,SACH,KAAK,aAAa,sBA4CjC,CAAC;AAGF,eAAO,MAAM,GAAG,SACN,KAAK,aAAa,aA0B3B,CAAC"}
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,eAAO,MAAM,KAAK,GAAI,KAAK,MAAM,MAEvB,SAAS,GAAG,MAAY,KAAK,aAAa,iBASnD,CAAC;AAGF,eAAO,MAAM,KAAK,GAAU,IAAI,MAAM,EAAE,SAAS,MAAM,EAAE,MAAM,MAAM,kBAMpE,CAAC;AAGF,eAAO,MAAM,MAAM,SACH,KAAK,aAAa,sBA4CjC,CAAC;AAGF,eAAO,MAAM,GAAG,SACN,KAAK,aAAa,aA0B3B,CAAC;AAgBF,eAAO,MAAM,MAAM,GACjB,SAAS,CAAC,GAAG,EAAE,aAAa,KAAK,cAAc,CAAC,MAAM,GAAG,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAC1G,UAAU;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,MAK1B,KAAK,aAAa,aAmD3B,CAAC"}
|
package/dist/helpers.js
CHANGED
|
@@ -81,8 +81,64 @@ var sse = () => {
|
|
|
81
81
|
});
|
|
82
82
|
};
|
|
83
83
|
};
|
|
84
|
+
var stream = (handler, options) => {
|
|
85
|
+
const contentType = options?.contentType ?? "text/plain; charset=utf-8";
|
|
86
|
+
const enc = new TextEncoder;
|
|
87
|
+
return (req) => {
|
|
88
|
+
let resolveController;
|
|
89
|
+
const controllerReady = new Promise((res) => {
|
|
90
|
+
resolveController = res;
|
|
91
|
+
});
|
|
92
|
+
const readable = new ReadableStream({
|
|
93
|
+
start(c) {
|
|
94
|
+
resolveController(c);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
controllerReady.then((controller) => {
|
|
98
|
+
const enqueue = (chunk) => controller.enqueue(typeof chunk === "string" ? enc.encode(chunk) : chunk);
|
|
99
|
+
req.streamSend = enqueue;
|
|
100
|
+
req.streamClose = () => controller.close();
|
|
101
|
+
req.streamError = (e) => controller.error(e);
|
|
102
|
+
const result = handler(req);
|
|
103
|
+
if (result && typeof result[Symbol.asyncIterator] === "function") {
|
|
104
|
+
(async () => {
|
|
105
|
+
try {
|
|
106
|
+
for await (const chunk of result) {
|
|
107
|
+
enqueue(chunk);
|
|
108
|
+
}
|
|
109
|
+
controller.close();
|
|
110
|
+
} catch (e) {
|
|
111
|
+
controller.error(e);
|
|
112
|
+
}
|
|
113
|
+
})();
|
|
114
|
+
} else if (result instanceof Promise) {
|
|
115
|
+
result.then(() => {
|
|
116
|
+
try {
|
|
117
|
+
controller.close();
|
|
118
|
+
} catch {}
|
|
119
|
+
}).catch((e) => {
|
|
120
|
+
try {
|
|
121
|
+
controller.error(e);
|
|
122
|
+
} catch {}
|
|
123
|
+
});
|
|
124
|
+
} else {
|
|
125
|
+
try {
|
|
126
|
+
controller.close();
|
|
127
|
+
} catch {}
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
return new Response(readable, {
|
|
131
|
+
headers: {
|
|
132
|
+
"Content-Type": contentType,
|
|
133
|
+
"Transfer-Encoding": "chunked",
|
|
134
|
+
"X-Content-Type-Options": "nosniff"
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
};
|
|
84
139
|
export {
|
|
85
140
|
upload,
|
|
141
|
+
stream,
|
|
86
142
|
sse,
|
|
87
143
|
email,
|
|
88
144
|
cache
|
package/dist/middleware.d.ts
CHANGED
|
@@ -35,5 +35,27 @@ export declare const session: (options: {
|
|
|
35
35
|
maxAge?: number;
|
|
36
36
|
name?: string;
|
|
37
37
|
}) => (req: PrinceRequest, next: Next) => Promise<Response | undefined>;
|
|
38
|
+
export declare const secureHeaders: (options?: {
|
|
39
|
+
xFrameOptions?: string;
|
|
40
|
+
xContentTypeOptions?: boolean;
|
|
41
|
+
xXssProtection?: string;
|
|
42
|
+
strictTransportSecurity?: string;
|
|
43
|
+
referrerPolicy?: string;
|
|
44
|
+
permissionsPolicy?: string;
|
|
45
|
+
contentSecurityPolicy?: string;
|
|
46
|
+
}) => (req: PrinceRequest, next: Next) => Promise<Response | undefined>;
|
|
47
|
+
export declare const timeout: (ms: number, message?: string) => (req: PrinceRequest, next: Next) => Promise<Response | undefined>;
|
|
48
|
+
export declare const requestId: (options?: {
|
|
49
|
+
header?: string;
|
|
50
|
+
generator?: () => string;
|
|
51
|
+
}) => (req: PrinceRequest, next: Next) => Promise<Response | undefined>;
|
|
52
|
+
export declare const ipRestriction: (options: {
|
|
53
|
+
allowList?: string[];
|
|
54
|
+
denyList?: string[];
|
|
55
|
+
}) => (req: PrinceRequest, next: Next) => Promise<Response | undefined>;
|
|
56
|
+
export declare const serveStatic: (root: string) => (req: PrinceRequest, next: Next) => Promise<Response | undefined>;
|
|
57
|
+
export declare const jwks: (jwksUrl: string, options?: {
|
|
58
|
+
algorithms?: string[];
|
|
59
|
+
}) => (req: PrinceRequest, next: Next) => Promise<Response | undefined>;
|
|
38
60
|
export {};
|
|
39
61
|
//# sourceMappingURL=middleware.d.ts.map
|
package/dist/middleware.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,KAAK,IAAI,GAAG,MAAM,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;AAGhD,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;QACjB,GAAG,EAAE,aAAa,CAAC;QACnB,GAAG,CAAC,EAAE,QAAQ,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,GAAG,CAAC;KACb,KAAK,IAAI,CAAC;CACZ;AAED,eAAO,MAAM,MAAM,GAAI,UAAS,aAAkB,MASlC,KAAK,aAAa,EAAE,MAAM,IAAI,kCAqD7C,CAAC;AAGF,eAAO,MAAM,IAAI,GAAI,SAAQ,MAAY,MACzB,KAAK,GAAG,EAAE,MAAM,QAAQ,iBA+BvC,CAAC;AAGF,eAAO,MAAM,OAAO,GAAU,SAAS,GAAG,EAAE,QAAQ,UAAU,EAAE,WAAW,MAAM,oBAQhF,CAAC;AAEF,eAAO,MAAM,GAAG,GAAI,KAAK,UAAU,MACnB,KAAK,aAAa,EAAE,MAAM,IAAI,kCAuB7C,CAAC;AAGF,eAAO,MAAM,SAAS,GAAI,KAAK,MAAM,EAAE,eAAW,MAGlC,KAAK,aAAa,EAAE,MAAM,IAAI,kCAqC7C,CAAC;AAGF,eAAO,MAAM,QAAQ,GAAI,QAAQ,CAAC,CAAC,SAAS,MAC5B,KAAK,GAAG,EAAE,MAAM,QAAQ,iBAyEvC,CAAC;AAGF,eAAO,MAAM,IAAI,GAAI,UAAU;IAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,MACnC,KAAK,aAAa,EAAE,MAAM,IAAI,kCAwB7C,CAAC;AAGF,eAAO,MAAM,MAAM,GAAI,SAAS;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,MAInD,KAAK,aAAa,EAAE,MAAM,IAAI,kCAa7C,CAAC;AAGF,eAAO,MAAM,QAAQ,GAAI,UAAU;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC;CAC1C,MAIe,KAAK,aAAa,EAAE,MAAM,IAAI,kCAqC7C,CAAC;AAGF,eAAO,MAAM,OAAO,GAAI,SAAS;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,MAce,KAAK,aAAa,EAAE,MAAM,IAAI,kCA+C7C,CAAC"}
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
|