@b9g/router 0.2.1 → 0.2.2

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
@@ -279,7 +279,10 @@ type TrailingSlashMode = "strip" | "add"
279
279
  Standard middleware is available from `@b9g/router/middleware`:
280
280
 
281
281
  ```typescript
282
- import {cors, trailingSlash} from '@b9g/router/middleware';
282
+ import {cors, logger, trailingSlash} from '@b9g/router/middleware';
283
+
284
+ // Request logging
285
+ router.use(logger());
283
286
 
284
287
  // CORS middleware
285
288
  router.use(cors({
@@ -293,6 +296,21 @@ router.use(trailingSlash("strip")); // /path/ → /path
293
296
 
294
297
  ### Available Middleware
295
298
 
299
+ #### `logger(options?: LoggerOptions)`
300
+
301
+ Logs incoming requests and outgoing responses with timing information via [LogTape](https://github.com/dahlia/logtape).
302
+
303
+ ```
304
+ → GET /
305
+ ← 200 GET / (3ms)
306
+ ```
307
+
308
+ ```typescript
309
+ interface LoggerOptions {
310
+ category?: string[]; // Default: ["app", "router"]
311
+ }
312
+ ```
313
+
296
314
  #### `cors(options?: CORSOptions)`
297
315
 
298
316
  Handles Cross-Origin Resource Sharing headers and preflight requests.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b9g/router",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Universal request router built on web standards with generator-based middleware.",
5
5
  "keywords": [
6
6
  "router",
@@ -19,7 +19,8 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "@b9g/http-errors": "^0.2.1",
22
- "@b9g/match-pattern": "^0.2.1"
22
+ "@b9g/match-pattern": "^0.2.1",
23
+ "@logtape/logtape": "^1.2.0"
23
24
  },
24
25
  "devDependencies": {
25
26
  "@b9g/libuild": "^0.1.18"
@@ -98,4 +98,39 @@ export interface CORSOptions {
98
98
  * }));
99
99
  * ```
100
100
  */
101
+ /**
102
+ * Logger configuration options
103
+ */
104
+ export interface LoggerOptions {
105
+ /**
106
+ * LogTape category for the logger
107
+ * @default ["app", "router"]
108
+ */
109
+ category?: string[];
110
+ }
111
+ /**
112
+ * Request logging middleware
113
+ *
114
+ * Logs incoming requests and outgoing responses with timing information.
115
+ * Uses LogTape via the specified category (default: ["app", "router"]).
116
+ *
117
+ * Output format:
118
+ * ```
119
+ * → GET /
120
+ * ← 200 GET / (3ms)
121
+ * ```
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * import {Router} from "@b9g/router";
126
+ * import {logger} from "@b9g/router/middleware";
127
+ *
128
+ * const router = new Router();
129
+ * router.use(logger());
130
+ *
131
+ * // Custom category
132
+ * router.use(logger({ category: ["app", "http"] }));
133
+ * ```
134
+ */
135
+ export declare function logger(options?: LoggerOptions): (request: Request) => AsyncGenerator<Request, Response | undefined, Response>;
101
136
  export declare function cors(options?: CORSOptions): (request: Request, _context: any) => AsyncGenerator<Request, Response | undefined, Response>;
package/src/middleware.js CHANGED
@@ -1,5 +1,6 @@
1
1
  /// <reference types="./middleware.d.ts" />
2
2
  // src/middleware.ts
3
+ import { getLogger } from "@logtape/logtape";
3
4
  function trailingSlash(mode) {
4
5
  return (req) => {
5
6
  const url = new URL(req.url);
@@ -39,6 +40,21 @@ function getAllowedOrigin(config, requestOrigin) {
39
40
  }
40
41
  return null;
41
42
  }
43
+ function logger(options = {}) {
44
+ const { category = ["app", "router"] } = options;
45
+ const log = getLogger(category);
46
+ return async function* (request) {
47
+ const url = new URL(request.url);
48
+ const method = request.method;
49
+ const pathname = url.pathname;
50
+ log.info`→ ${method} ${pathname}`;
51
+ const start = Date.now();
52
+ const response = yield request;
53
+ const duration = Date.now() - start;
54
+ log.info`← ${response.status} ${method} ${pathname} (${duration}ms)`;
55
+ return response;
56
+ };
57
+ }
42
58
  function cors(options = {}) {
43
59
  const {
44
60
  origin = "*",
@@ -104,5 +120,6 @@ function cors(options = {}) {
104
120
  }
105
121
  export {
106
122
  cors,
123
+ logger,
107
124
  trailingSlash
108
125
  };