@bepalo/router 1.1.12 → 1.2.14

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
 
@@ -107,8 +143,178 @@ Deno.serve(
107
143
  console.log("Server running at http://localhost:3000");
108
144
  ```
109
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
+
110
314
  ### Serve with client address
111
315
 
316
+ #### Bun
317
+
112
318
  ```js
113
319
  // Bun example
114
320
  Bun.serve({
@@ -119,7 +325,11 @@ Bun.serve({
119
325
  },
120
326
  });
121
327
  console.log("Server running at http://localhost:3000");
328
+ ```
329
+
330
+ #### Deno
122
331
 
332
+ ```js
123
333
  // Deno example
124
334
  Deno.serve(
125
335
  {
@@ -136,52 +346,57 @@ Deno.serve(
136
346
  },
137
347
  // router.respond.bind(router),
138
348
  );
349
+ ```
139
350
 
140
- // Nodejs example. very slow
141
- http.createServer(async (req, res) => {
142
- const url = new URL(req.url || "/", `http://${req.headers.host}`);
143
-
144
- // Build fetch request
145
- const headers = new Headers();
146
- Object.entries(req.headers).forEach(
147
- ([k, v]) => v && headers.set(k, v.toString()),
148
- );
149
-
150
- const request = new Request(url, {
151
- method: req.method,
152
- headers,
153
- body: ["GET", "HEAD"].includes(req.method) ? undefined : req,
154
- duplex: "half",
155
- });
156
-
157
- const address = {
158
- family: req.socket.remoteFamily,
159
- address: req.socket.remoteAddress,
160
- port: req.socket.remotePort,
161
- };
162
- try {
163
- const response = await router.respond(request, { address });
351
+ #### Nodejs
164
352
 
165
- res.writeHead(
166
- response.status,
167
- response.statusText,
168
- Object.fromEntries(response.headers.entries()),
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()),
169
363
  );
170
- if (response.body) {
171
- const reader = response.body.getReader();
172
- while (true) {
173
- const { done, value } = await reader.read();
174
- if (done) break;
175
- res.write(value);
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
+ }
176
392
  }
393
+ res.end();
394
+ } catch {
395
+ res.writeHead(500).end();
177
396
  }
178
- res.end();
179
- } catch {
180
- res.writeHead(500).end();
181
- }
182
- }).on("connection", (socket) => socket.setNoDelay(true))
397
+ })
398
+ .on("connection", (socket) => socket.setNoDelay(true))
183
399
  .listen(3000, () => console.log("Server running on port 3000"));
184
-
185
400
  ```
186
401
 
187
402
  ## 📚 Core Concepts
@@ -327,6 +542,8 @@ router.respond(
327
542
  ```ts
328
543
  import {
329
544
  status, // HTTP status response
545
+ redirect, // Redirect response with location header set
546
+ forward, // forward to other path within the router.
330
547
  text, // Plain text response
331
548
  html, // HTML response
332
549
  json, // JSON response
@@ -498,129 +715,40 @@ Routes are matched in this order of priority:
498
715
  ### Router Composition Example
499
716
 
500
717
  ```js
501
- const apiRouter = new Router();
502
-
503
- // API routes
504
- apiRouter.handle("GET /users", () => json({ users: [] }));
505
- apiRouter.handle("POST /users", async (req) => {
506
- const body = await req.json();
507
- return json({ created: true, data: body }, { status: 201 });
508
- });
509
-
510
- // Nested router
511
- const v1Router = new Router();
512
- v1Router.handle("GET /status", () => json({ version: "1.0", status: "ok" }));
513
- apiRouter.append("/v1", v1Router);
514
-
515
- // Mount API router under /api
516
- const mainRouter = new Router();
517
- mainRouter.append("/api", apiRouter);
518
-
519
- // Add some frontend routes
520
- mainRouter.handle("GET /", () => html("<h1>Home</h1>"));
521
- mainRouter.handle("GET /about", () => html("<h1>About</h1>"));
522
- ```
523
-
524
- ### Complete Example with Middleware
525
-
526
- ```js
527
- import {
528
- Router,
529
- text,
530
- json,
531
- cors,
532
- limitRate,
533
- type CTXAddress,
534
- type SocketAddress,
535
- type RouterContext,
536
- } from "@bepalo/router";
537
-
538
- const router = new Router<RouterContext & CTXAddress>({
539
- defaultHeaders: () => [
540
- ["X-Powered-By", "@bepalo/router"],
541
- ["Date", new Date().toUTCString()]
542
- ],
543
- });
544
-
545
- // Global CORS
546
- router.filter("*", [
547
- cors({
548
- origins: ["http://localhost:3000", "https://example.com"],
549
- methods: ["GET", "POST", "PUT", "DELETE"],
550
- allowedHeaders: ["Content-Type", "Authorization"],
551
- credentials: true,
552
- }),
553
- ]);
554
-
555
- // Rate limiting for API
556
- router.filter(
557
- [
558
- "GET /api/.**",
559
- "POST /api/.**",
560
- "PUT /api/.**",
561
- "PATCH /api/.**",
562
- "DELETE /api/.**",
563
- ],
718
+ // User API routes
719
+ const userAPIRouter = new Router();
720
+ userAPIRouter.handle("GET /", () => json({ user: {} }));
721
+ userAPIRouter.handle <
722
+ CTXBody >
723
+ ("POST /",
564
724
  [
565
- limitRate({
566
- key: (req, ctx) => ctx.address.address,
567
- maxTokens: 100,
568
- refillRate: 10, // 10 tokens per second
569
- setXRateLimitHeaders: true,
570
- }),
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
+ },
571
739
  ]);
572
740
 
573
- // Routes
574
- router.handle("GET /", () => text("Welcome to the API"));
575
-
576
- // users API `/api/users` router
577
- {
578
- const usersAPI = new Router();
741
+ // API v1 router
742
+ const v1APIRouter = new Router();
743
+ v1APIRouter.handle("GET /status", () => json({ version: "1.0", status: "ok" }));
579
744
 
580
- usersAPI.handle("POST /", async (req) => {
581
- const body = await req.json();
582
- return json({ id: Date.now(), ...body }, { status: 201 });
583
- });
584
-
585
- usersAPI.handle("GET /", () =>
586
- json({
587
- users: [
588
- { id: 1, name: "Abebe" },
589
- { id: 2, name: "Derartu" },
590
- ],
591
- }),
592
- );
593
-
594
- usersAPI.handle("GET /:id", (req, { params }) =>
595
- json({ user: { id: params.id, name: "User " + params.id } }),
596
- );
597
-
598
- router.append("/api/users", usersAPI);
599
- }
600
-
601
- // Custom Error handling
602
- router.catch("*", (req, ctx) => {
603
- console.error("Error:", ctx.error);
604
- return json({ error: "Internal server error" }, { status: 500 });
605
- });
606
-
607
- // Custom fallback handler
608
- router.fallback("*", () => json({ error: "Not found" }, { status: 404 }));
609
-
610
- // Start server
611
- Bun.serve({
612
- port: 3000,
613
- async fetch(req, server) {
614
- const address = server.requestIP(req) as SocketAddress | null;
615
- if(!address) {
616
- throw new Error("null client address");
617
- }
618
- return await router.respond(req, { address });
619
- },
620
- });
621
-
622
- 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);
623
749
 
750
+ const mainRouter = new Router();
751
+ mainRouter.append("/api/v1", v1APIRouter);
624
752
  ```
625
753
 
626
754
  ## 🎯 Performance
@@ -640,7 +768,7 @@ The router uses a radix tree (trie) data structure for route matching, providing
640
768
  | Feature | @bepalo/router | Express | Hono | Fastify |
641
769
  | ------------------------------- | -------------- | ------- | ---- | ------- |
642
770
  | Radix Tree Routing | ✅ | ❌ | ✅ | ✅ |
643
- | Zero Dependencies | ✅ | ❌ | ❌ | ❌ |
771
+ | Few Dependencies | ✅ | ❌ | ❌ | ❌ |
644
772
  | TypeScript Native | ✅ | ❌ | ✅ | ✅ |
645
773
  | Extended Handler Phases | ✅ | ⚠️ | ⚠️ | ⚠️ |
646
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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"}