@bepalo/router 1.1.11 → 1.2.13

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
@@ -8,7 +8,43 @@
8
8
 
9
9
  [![Vitest](https://img.shields.io/badge/vitest-6E9F18?style=for-the-badge&logo=vitest&logoColor=white)](test-result.md)
10
10
 
11
- **A fast, feature-rich HTTP router for modern JavaScript runtimes.**
11
+ **A fast, feature-rich HTTP router for modern JavaScript runtimes.** [jump to example](#example)
12
+
13
+ ## 📑 Table of Contents
14
+
15
+ 1. [🏆 @bepalo/router](#-bepalorouter)
16
+ 2. [✨ Features](#-features)
17
+ 3. [🚀 Get Started](#-get-started)
18
+ - [📥 Installation](#-installation)
19
+ - [📦 Basic Usage](#-basic-usage)
20
+ - [Example](#example)
21
+ - [Serve with client address](#serve-with-client-address)
22
+ - [Bun](#bun)
23
+ - [Deno](#deno)
24
+ - [Nodejs](#nodejs)
25
+ 4. [📚 Core Concepts](#-core-concepts)
26
+ - [Handler Types & Execution Order](#handler-types--execution-order)
27
+ - [Router Context](#router-context)
28
+ 5. [📖 API Reference](#-api-reference)
29
+ - [Router Class](#router-class)
30
+ - [Constructor](#constructor)
31
+ - [Configuration Options](#configuration-options)
32
+ - [Handler Registration Methods](#handler-registration-methods)
33
+ - [Handler Options](#handler-options)
34
+ - [Router Composition](#router-composition)
35
+ - [Request Processing](#request-processing)
36
+ - [Helper Functions](#helper-functions)
37
+ - [Provided Middleware](#provided-middleware)
38
+ - [🔧 Advanced Usage](#-advanced-usage)
39
+ - [Pipeline (Multiple Handlers)](#pipeline-multiple-handlers)
40
+ - [Path Patterns](#path-patterns)
41
+ - [Route Priority](#route-priority)
42
+ - [Router Composition Example](#router-composition-example)
43
+ 6. [🎯 Performance](#-performance)
44
+ - [Comparison with Other Routers](#comparison-with-other-routers)
45
+ 7. [📄 License](#-license)
46
+ 8. [🕊️ Thanks and Enjoy](#-thanks-and-enjoy)
47
+ 9. [💖 Be a Sponsor](#-be-a-sponsor)
12
48
 
13
49
  ## ✨ Features
14
50
 
@@ -63,6 +99,7 @@ import {
63
99
  type CTXUpload,
64
100
  parseUploadStreaming,
65
101
  } from "@bepalo/router";
102
+ // } from "jsr:@bepalo/router"; // for deno
66
103
 
67
104
  // Create a router instance
68
105
  const router = new Router();
@@ -94,9 +131,274 @@ Bun.serve({
94
131
  fetch: (req) => router.respond(req),
95
132
  });
96
133
 
134
+ // Start server (Deno example)
135
+ Deno.serve(
136
+ {
137
+ port: 3000,
138
+ onListen: () => console.log("Server listening on http://localhost:3000"),
139
+ },
140
+ router.respond.bind(router),
141
+ );
142
+
143
+ console.log("Server running at http://localhost:3000");
144
+ ```
145
+
146
+ ### Example
147
+
148
+ ```js
149
+ import {
150
+ Router,
151
+ status,
152
+ html,
153
+ json,
154
+ cors,
155
+ limitRate,
156
+ parseBody,
157
+ type CTXBody,
158
+ type CTXAddress,
159
+ type SocketAddress,
160
+ } from "@bepalo/router";
161
+ import { z } from "zod";
162
+
163
+ const router = new Router<CTXAddress>({
164
+ // Default headers can accept static headers or dynamic headers
165
+ // as a function like this
166
+ defaultHeaders: () => [
167
+ ["X-Powered-By", "@bepalo/router"],
168
+ ["Date", new Date().toUTCString()],
169
+ ],
170
+ // Errors are caught by defualt but not logged
171
+ defaultCatcher: (req, ctx) => {
172
+ console.error("Error:", ctx.error);
173
+ return json({ error: "Something went wrong" }, { status: 500 });
174
+ },
175
+ // For crude optimizations
176
+ enable: {
177
+ hooks: false,
178
+ afters: false,
179
+ filters: true,
180
+ fallbacks: true,
181
+ catchers: true,
182
+ },
183
+ ///...
184
+ });
185
+
186
+ // Global CORS
187
+ router.filter("GET /.**", [
188
+ limitRate({
189
+ key: (req, ctx) => ctx.address.address, // used to identify client
190
+ maxTokens: 30,
191
+ refillRate: 3, // 3 tokens every second
192
+ setXRateLimitHeaders: true,
193
+ }),
194
+ cors({
195
+ origins: "*",
196
+ methods: ["GET"],
197
+ }),
198
+ ]);
199
+
200
+ // Rate limiting for API
201
+ router.filter(
202
+ [
203
+ "GET /api/.**",
204
+ "POST /api/.**",
205
+ "PUT /api/.**",
206
+ "PATCH /api/.**",
207
+ "DELETE /api/.**",
208
+ ],
209
+ [
210
+ limitRate({
211
+ key: (req, ctx) => ctx.address.address, // used to identify client
212
+ maxTokens: 100,
213
+ refillInterval: 30_000, // every 30 seconds
214
+ refillRate: 50, // 50 tokens every refillInterval
215
+ setXRateLimitHeaders: true,
216
+ }),
217
+ cors({
218
+ origins: ["http://localhost:3000", "https://example.com"],
219
+ methods: ["GET", "POST", "PUT", "DELETE"],
220
+ allowedHeaders: ["Content-Type", "Authorization"],
221
+ credentials: true,
222
+ endHere: true,
223
+ }),
224
+ ],
225
+ );
226
+
227
+ // Main route
228
+ router.handle("GET /", () =>
229
+ html("<h1>Welcome! Enjoy using @beplao/router</h1>"),
230
+ );
231
+ router.handle("GET /status", () => status(200));
232
+
233
+ // Sample sub-route `/api/user`
234
+ ////////////////////////////////////////
235
+ // eg. inside routes/api/user.ts
236
+ const userRepo = new Map();
237
+ const userAPI = new Router();
238
+ let topId = 1000;
239
+
240
+ const postUserBodySchema = z.object({
241
+ name: z.string(),
242
+ password: z.string().min(4),
243
+ });
244
+
245
+ userAPI.filter<CTXBody>("POST /", [
246
+ parseBody(),
247
+ (req, { body }) => {
248
+ const { success, error } = postUserBodySchema.safeParse(body);
249
+ const errors = error?.issues ?? [];
250
+ if (!success) return json({ errors }, { status: 400 });
251
+ },
252
+ ]);
253
+ userAPI.handle<CTXBody>("POST /", [
254
+ (req, { body }) => {
255
+ const id = topId++;
256
+ const { name, password } = body;
257
+ const user = { id, name, password };
258
+ userRepo.set(id, user);
259
+ return json({ success: true, id }, { status: 201 });
260
+ },
261
+ ]);
262
+
263
+ userAPI.handle("GET /", () =>
264
+ json({ users: Object.fromEntries(userRepo.entries()) }),
265
+ );
266
+
267
+ userAPI.handle("GET /:userId", (req, { params }) => {
268
+ const { userId } = params;
269
+ const user = userRepo.get(parseInt(userId));
270
+ if (!user) return json({ error: "User not found" }, { status: 404 });
271
+ return json({ user });
272
+ });
273
+
274
+ ////////////////////////////////////////
275
+
276
+ router.append("/api/user", userAPI);
277
+
278
+ // fallback handling
279
+ router.fallback("GET /api/.**", () =>
280
+ json({ error: "Not found" }, { status: 404 }),
281
+ );
282
+
283
+ // Error handling
284
+ router.catch(
285
+ [
286
+ "GET /api/.**",
287
+ "POST /api/.**",
288
+ "PUT /api/.**",
289
+ "PATCH /api/.**",
290
+ "DELETE /api/.**",
291
+ ],
292
+ [
293
+ (req, ctx) => {
294
+ console.error("APIError:", ctx.error);
295
+ return json({ error: "Something went wrong" }, { status: 500 });
296
+ },
297
+ ],
298
+ );
299
+
300
+ // Start server
301
+ Bun.serve({
302
+ port: 3000,
303
+ async fetch(req, server) {
304
+ const address = server.requestIP(req) as SocketAddress | null;
305
+ if (!address) throw new Error("null client address");
306
+ /// best to log request and response here...
307
+ return await router.respond(req, { address });
308
+ },
309
+ });
310
+
311
+ console.log("Server listening on http://localhost:3000");
312
+ ```
313
+
314
+ ### Serve with client address
315
+
316
+ #### Bun
317
+
318
+ ```js
319
+ // Bun example
320
+ Bun.serve({
321
+ port: 3000,
322
+ async fetch(req, server) {
323
+ const address = server.requestIP(req) as SocketAddress;
324
+ return await router.respond(req, { address });
325
+ },
326
+ });
97
327
  console.log("Server running at http://localhost:3000");
98
328
  ```
99
329
 
330
+ #### Deno
331
+
332
+ ```js
333
+ // Deno example
334
+ Deno.serve(
335
+ {
336
+ port: 3000,
337
+ onListen: () => console.log("Server listening on http://localhost:3000"),
338
+ },
339
+ async (req, { remoteAddr }) => {
340
+ const address = {
341
+ family: remoteAddr.transport,
342
+ address: remoteAddr.hostname,
343
+ port: remoteAddr.port,
344
+ } as SocketAddress;
345
+ return router.respond(req, { address });
346
+ },
347
+ // router.respond.bind(router),
348
+ );
349
+ ```
350
+
351
+ #### Nodejs
352
+
353
+ ```js
354
+ // Nodejs example. very slow
355
+ http
356
+ .createServer(async (req, res) => {
357
+ const url = new URL(req.url || "/", `http://${req.headers.host}`);
358
+
359
+ // Build fetch request
360
+ const headers = new Headers();
361
+ Object.entries(req.headers).forEach(
362
+ ([k, v]) => v && headers.set(k, v.toString()),
363
+ );
364
+
365
+ const request = new Request(url, {
366
+ method: req.method,
367
+ headers,
368
+ body: ["GET", "HEAD"].includes(req.method) ? undefined : req,
369
+ duplex: "half",
370
+ });
371
+
372
+ const address = {
373
+ family: req.socket.remoteFamily,
374
+ address: req.socket.remoteAddress,
375
+ port: req.socket.remotePort,
376
+ };
377
+ try {
378
+ const response = await router.respond(request, { address });
379
+
380
+ res.writeHead(
381
+ response.status,
382
+ response.statusText,
383
+ Object.fromEntries(response.headers.entries()),
384
+ );
385
+ if (response.body) {
386
+ const reader = response.body.getReader();
387
+ while (true) {
388
+ const { done, value } = await reader.read();
389
+ if (done) break;
390
+ res.write(value);
391
+ }
392
+ }
393
+ res.end();
394
+ } catch {
395
+ res.writeHead(500).end();
396
+ }
397
+ })
398
+ .on("connection", (socket) => socket.setNoDelay(true))
399
+ .listen(3000, () => console.log("Server running on port 3000"));
400
+ ```
401
+
100
402
  ## 📚 Core Concepts
101
403
 
102
404
  ### Handler Types & Execution Order
@@ -240,6 +542,8 @@ router.respond(
240
542
  ```ts
241
543
  import {
242
544
  status, // HTTP status response
545
+ redirect, // Redirect response with location header set
546
+ forward, // forward to other path within the router.
243
547
  text, // Plain text response
244
548
  html, // HTML response
245
549
  json, // JSON response
@@ -411,129 +715,40 @@ Routes are matched in this order of priority:
411
715
  ### Router Composition Example
412
716
 
413
717
  ```js
414
- const apiRouter = new Router();
415
-
416
- // API routes
417
- apiRouter.handle("GET /users", () => json({ users: [] }));
418
- apiRouter.handle("POST /users", async (req) => {
419
- const body = await req.json();
420
- return json({ created: true, data: body }, { status: 201 });
421
- });
422
-
423
- // Nested router
424
- const v1Router = new Router();
425
- v1Router.handle("GET /status", () => json({ version: "1.0", status: "ok" }));
426
- apiRouter.append("/v1", v1Router);
427
-
428
- // Mount API router under /api
429
- const mainRouter = new Router();
430
- mainRouter.append("/api", apiRouter);
431
-
432
- // Add some frontend routes
433
- mainRouter.handle("GET /", () => html("<h1>Home</h1>"));
434
- mainRouter.handle("GET /about", () => html("<h1>About</h1>"));
435
- ```
436
-
437
- ### Complete Example with Middleware
438
-
439
- ```js
440
- import {
441
- Router,
442
- text,
443
- json,
444
- cors,
445
- limitRate,
446
- type CTXAddress,
447
- type SocketAddress,
448
- type RouterContext,
449
- } from "@bepalo/router";
450
-
451
- const router = new Router<RouterContext & CTXAddress>({
452
- defaultHeaders: () => [
453
- ["X-Powered-By", "@bepalo/router"],
454
- ["Date", new Date().toUTCString()]
455
- ],
456
- });
457
-
458
- // Global CORS
459
- router.filter("*", [
460
- cors({
461
- origins: ["http://localhost:3000", "https://example.com"],
462
- methods: ["GET", "POST", "PUT", "DELETE"],
463
- allowedHeaders: ["Content-Type", "Authorization"],
464
- credentials: true,
465
- }),
466
- ]);
467
-
468
- // Rate limiting for API
469
- router.filter(
718
+ // User API routes
719
+ const userAPIRouter = new Router();
720
+ userAPIRouter.handle("GET /", () => json({ user: {} }));
721
+ userAPIRouter.handle <
722
+ CTXBody >
723
+ ("POST /",
470
724
  [
471
- "GET /api/.**",
472
- "POST /api/.**",
473
- "PUT /api/.**",
474
- "PATCH /api/.**",
475
- "DELETE /api/.**",
476
- ],
477
- [
478
- limitRate({
479
- key: (req, ctx) => ctx.address.address,
480
- maxTokens: 100,
481
- refillRate: 10, // 10 tokens per second
482
- setXRateLimitHeaders: true,
483
- }),
725
+ parseBody(),
726
+ async (req, { body }) => {
727
+ return json({ success: true, data: body }, { status: 201 });
728
+ },
729
+ ]);
730
+
731
+ // Session API routes
732
+ const sessionAPIRouter = new Router();
733
+ sessionAPIRouter.handle("GET /", () => json({ session: {} }));
734
+ sessionAPIRouter.handle("POST /", [
735
+ parseBody(),
736
+ async (req, { body }) => {
737
+ return json({ success: true, data: body }, { status: 201 });
738
+ },
484
739
  ]);
485
740
 
486
- // Routes
487
- router.handle("GET /", () => text("Welcome to the API"));
741
+ // API v1 router
742
+ const v1APIRouter = new Router();
743
+ v1APIRouter.handle("GET /status", () => json({ version: "1.0", status: "ok" }));
488
744
 
489
- // users API `/api/users` router
490
- {
491
- const usersAPI = new Router();
492
-
493
- usersAPI.handle("POST /", async (req) => {
494
- const body = await req.json();
495
- return json({ id: Date.now(), ...body }, { status: 201 });
496
- });
497
-
498
- usersAPI.handle("GET /", () =>
499
- json({
500
- users: [
501
- { id: 1, name: "Abebe" },
502
- { id: 2, name: "Derartu" },
503
- ],
504
- }),
505
- );
506
-
507
- usersAPI.handle("GET /:id", (req, { params }) =>
508
- json({ user: { id: params.id, name: "User " + params.id } }),
509
- );
510
-
511
- router.append("/api/users", usersAPI);
512
- }
513
-
514
- // Custom Error handling
515
- router.catch("*", (req, ctx) => {
516
- console.error("Error:", ctx.error);
517
- return json({ error: "Internal server error" }, { status: 500 });
518
- });
519
-
520
- // Custom fallback handler
521
- router.fallback("*", () => json({ error: "Not found" }, { status: 404 }));
522
-
523
- // Start server
524
- Bun.serve({
525
- port: 3000,
526
- async fetch(req, server) {
527
- const address = server.requestIP(req) as SocketAddress | null;
528
- if(!address) {
529
- throw new Error("null client address");
530
- }
531
- return await router.respond(req, { address });
532
- },
533
- });
534
-
535
- console.log("Server listening on http://localhost:3000");
745
+ // Composition is useful for defining routes in multiple files
746
+ // and appending them in other routes.
747
+ v1APIRouter.append("/user", userAPIRouter);
748
+ v1APIRouter.append("/session", sessionAPIRouter);
536
749
 
750
+ const mainRouter = new Router();
751
+ mainRouter.append("/api/v1", v1APIRouter);
537
752
  ```
538
753
 
539
754
  ## 🎯 Performance
@@ -553,7 +768,7 @@ The router uses a radix tree (trie) data structure for route matching, providing
553
768
  | Feature | @bepalo/router | Express | Hono | Fastify |
554
769
  | ------------------------------- | -------------- | ------- | ---- | ------- |
555
770
  | Radix Tree Routing | ✅ | ❌ | ✅ | ✅ |
556
- | Zero Dependencies | ✅ | ❌ | ❌ | ❌ |
771
+ | Few Dependencies | ✅ | ❌ | ❌ | ❌ |
557
772
  | TypeScript Native | ✅ | ❌ | ✅ | ✅ |
558
773
  | Extended Handler Phases | ✅ | ⚠️ | ⚠️ | ⚠️ |
559
774
  | Built-in Middleware | ✅ | ❌ | ✅ | ✅ |
@@ -1,12 +1,14 @@
1
+ import { RouterContext } from "./router";
1
2
  import { Handler } from "./types";
2
3
  export * from "./upload-stream";
3
- type SURecord = Record<string, unknown>;
4
- type SSRecord = Record<string, string>;
5
4
  export interface SocketAddress {
6
5
  address: string;
7
6
  family: string;
8
7
  port: number;
9
8
  }
9
+ export type CTXError = {
10
+ error: Error;
11
+ };
10
12
  export type CTXAddress = {
11
13
  address: SocketAddress;
12
14
  };
@@ -24,6 +26,24 @@ export declare function getHttpStatusText(code: number): string;
24
26
  * status(204, null); // No content response
25
27
  */
26
28
  export declare const status: (status: number, content?: string | null, init?: ResponseInit) => Response;
29
+ /**
30
+ * Creates a redirect Response.
31
+ * Defaults to 302 Found unless another status is provided.
32
+ * @param {string} location - The URL to redirect to
33
+ * @param {number} [code=302] - The HTTP status code (301, 302, 303, 307, 308)
34
+ * @param {ResponseInit} [init] - Additional response initialization options
35
+ * @returns {Response} A Response object with Location header
36
+ */
37
+ export declare const redirect: (location: string, init?: ResponseInit) => Response;
38
+ /**
39
+ * Forwards the request to another handler internally.
40
+ * Does not change the URL or send a redirect to the client.
41
+ * @param {string} path - The new path to forward to
42
+ * @returns {Response} A Response object with the forwarded request's response
43
+ */
44
+ export declare const forward: <XContext = {}>(path: string, options?: {
45
+ method: string;
46
+ }) => Handler<RouterContext<XContext>>;
27
47
  /**
28
48
  * Creates a text/plain Response.
29
49
  * Defaults to status 200 and text/plain content-type if not specified.
@@ -177,10 +197,10 @@ export declare const parseCookieFromRequest: <Expected extends Record<string, st
177
197
  /**
178
198
  * Context object containing parsed cookies.
179
199
  * @typedef {Object} CTXCookie
180
- * @property {SSRecord} cookie - Parsed cookies from the request
200
+ * @property {Record<string, string>} cookie - Parsed cookies from the request
181
201
  */
182
202
  export type CTXCookie = {
183
- cookie: SSRecord;
203
+ cookie: Record<string, string>;
184
204
  };
185
205
  /**
186
206
  * Creates middleware that parses cookies from the request and adds them to the context.
@@ -193,10 +213,10 @@ export declare const parseCookie: <Context extends CTXCookie>() => Handler<Conte
193
213
  /**
194
214
  * Context object containing parsed request body.
195
215
  * @typedef {Object} CTXBody
196
- * @property {SURecord} body - Parsed request body data
216
+ * @property {Record<string, unknown>} body - Parsed request body data
197
217
  */
198
218
  export type CTXBody = {
199
- body: SURecord;
219
+ body: Record<string, unknown>;
200
220
  };
201
221
  /**
202
222
  * Supported media types for request body parsing.
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"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"}