@b9g/router 0.1.5 → 0.1.7
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 +130 -73
- package/package.json +13 -10
- package/src/index.d.ts +185 -5
- package/src/index.js +667 -1
- package/src/router.d.ts +0 -167
- package/src/router.js +0 -504
package/README.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# @b9g/router
|
|
2
2
|
|
|
3
|
-
Universal request router
|
|
3
|
+
**Universal request router for ServiceWorker applications. Built on web standards with generator-based middleware.**
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
10
|
-
- **Method Routing**: HTTP method shortcuts (get, post, put, delete, etc.)
|
|
7
|
+
- **ServiceWorker Compatible**: Designed for ServiceWorker `fetch` event handling
|
|
8
|
+
- **Generator Middleware**: Uses `yield` for flow control (no Express-style `next()`)
|
|
9
|
+
- **Web Standards**: Built on URLPattern, Request, and Response APIs
|
|
11
10
|
- **Universal**: Same code runs in browsers, Node.js, Bun, and edge platforms
|
|
11
|
+
- **Simple Context**: Route parameters and middleware-extensible context
|
|
12
12
|
|
|
13
13
|
## Installation
|
|
14
14
|
|
|
@@ -36,49 +36,90 @@ router.get('/posts/:id', (request, context) => {
|
|
|
36
36
|
const response = await router.handler(request);
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
##
|
|
39
|
+
## Middleware
|
|
40
|
+
|
|
41
|
+
The router supports generator-based middleware with `yield` for clean flow control:
|
|
40
42
|
|
|
41
43
|
```javascript
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
// Global middleware using generator pattern
|
|
45
|
+
router.use(async function* (request, context) {
|
|
46
|
+
console.log(`${request.method} ${request.url}`);
|
|
47
|
+
const response = yield request;
|
|
48
|
+
console.log(`${response.status}`);
|
|
49
|
+
return response;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Function middleware (can short-circuit)
|
|
53
|
+
router.use(async (request, context) => {
|
|
54
|
+
if (!request.headers.get('Authorization')) {
|
|
55
|
+
return new Response('Unauthorized', { status: 401 });
|
|
56
|
+
}
|
|
57
|
+
// Return null/undefined to continue to next middleware
|
|
58
|
+
return null;
|
|
59
|
+
});
|
|
60
|
+
```
|
|
44
61
|
|
|
45
|
-
|
|
46
|
-
const caches = new CacheStorage();
|
|
47
|
-
caches.register('posts', () => new MemoryCache('posts'));
|
|
62
|
+
## Caching
|
|
48
63
|
|
|
49
|
-
|
|
64
|
+
The router doesn't provide built-in cache integration. For caching, use the global `caches` API directly in your handlers:
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
router.get('/api/posts/:id', async (request, context) => {
|
|
68
|
+
// Use global caches API
|
|
69
|
+
const cache = await caches.open('api-v1');
|
|
70
|
+
|
|
71
|
+
const cached = await cache.match(request);
|
|
72
|
+
if (cached) return cached;
|
|
50
73
|
|
|
51
|
-
// Route with cache declaration
|
|
52
|
-
router.route({
|
|
53
|
-
pattern: '/api/posts/:id',
|
|
54
|
-
cache: { name: 'posts' }
|
|
55
|
-
}).get(async (request, context) => {
|
|
56
|
-
// context.cache is the opened 'posts' cache
|
|
57
74
|
const post = await db.posts.get(context.params.id);
|
|
58
|
-
|
|
75
|
+
const response = Response.json(post);
|
|
76
|
+
|
|
77
|
+
await cache.put(request, response.clone());
|
|
78
|
+
return response;
|
|
59
79
|
});
|
|
60
80
|
```
|
|
61
81
|
|
|
62
|
-
|
|
82
|
+
Or implement caching as middleware:
|
|
63
83
|
|
|
64
84
|
```javascript
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
85
|
+
// Cache middleware
|
|
86
|
+
async function* cacheMiddleware(request, context) {
|
|
87
|
+
if (request.method !== 'GET') {
|
|
88
|
+
return yield request;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const cache = await caches.open('pages-v1');
|
|
92
|
+
const cached = await cache.match(request);
|
|
93
|
+
if (cached) return cached;
|
|
71
94
|
|
|
72
|
-
|
|
73
|
-
router.route('/admin/*')
|
|
74
|
-
.use(authMiddleware)
|
|
75
|
-
.use(rateLimitMiddleware)
|
|
76
|
-
.get(adminHandler);
|
|
95
|
+
const response = yield request;
|
|
77
96
|
|
|
78
|
-
|
|
79
|
-
|
|
97
|
+
if (response.ok) {
|
|
98
|
+
await cache.put(request, response.clone());
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return response;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
router.use(cacheMiddleware);
|
|
80
105
|
```
|
|
81
106
|
|
|
107
|
+
## Exports
|
|
108
|
+
|
|
109
|
+
### Classes
|
|
110
|
+
|
|
111
|
+
- `Router` - Request router with pattern matching and middleware support
|
|
112
|
+
|
|
113
|
+
### Types
|
|
114
|
+
|
|
115
|
+
- `RouteContext` - Context object passed to handlers with params and middleware-added properties
|
|
116
|
+
- `Handler` - Route handler function type `(request, context) => Response | Promise<Response>`
|
|
117
|
+
- `GeneratorMiddleware` - Generator-based middleware type using `yield`
|
|
118
|
+
- `FunctionMiddleware` - Simple function middleware type
|
|
119
|
+
- `Middleware` - Union of GeneratorMiddleware | FunctionMiddleware
|
|
120
|
+
- `HTTPMethod` - HTTP method string literal type
|
|
121
|
+
- `RouteConfig` - Route configuration object
|
|
122
|
+
|
|
82
123
|
## API Reference
|
|
83
124
|
|
|
84
125
|
### Router
|
|
@@ -86,22 +127,20 @@ router.use('/api/*', corsMiddleware);
|
|
|
86
127
|
#### Constructor
|
|
87
128
|
|
|
88
129
|
```javascript
|
|
89
|
-
new Router(
|
|
130
|
+
new Router()
|
|
90
131
|
```
|
|
91
132
|
|
|
92
|
-
Options:
|
|
93
|
-
- `caches`: CacheStorage instance for cache-aware routing
|
|
94
|
-
|
|
95
133
|
#### Methods
|
|
96
134
|
|
|
97
|
-
##### `route(pattern
|
|
135
|
+
##### `route(pattern)`
|
|
98
136
|
|
|
99
137
|
Create a route builder for the given pattern.
|
|
100
138
|
|
|
101
139
|
```javascript
|
|
102
|
-
router.route('/api/posts/:id'
|
|
103
|
-
.
|
|
104
|
-
.
|
|
140
|
+
router.route('/api/posts/:id')
|
|
141
|
+
.get(handler)
|
|
142
|
+
.post(handler)
|
|
143
|
+
.delete(handler);
|
|
105
144
|
```
|
|
106
145
|
|
|
107
146
|
##### HTTP Method Shortcuts
|
|
@@ -116,14 +155,22 @@ router.head(pattern, handler)
|
|
|
116
155
|
router.options(pattern, handler)
|
|
117
156
|
```
|
|
118
157
|
|
|
119
|
-
##### `use(
|
|
158
|
+
##### `use(middleware)`
|
|
159
|
+
|
|
160
|
+
Add global middleware.
|
|
120
161
|
|
|
121
|
-
|
|
162
|
+
```javascript
|
|
163
|
+
router.use(loggingMiddleware);
|
|
164
|
+
```
|
|
122
165
|
|
|
123
166
|
##### `handler(request): Promise<Response>`
|
|
124
167
|
|
|
125
168
|
Bound handler function for processing requests.
|
|
126
169
|
|
|
170
|
+
```javascript
|
|
171
|
+
const response = await router.handler(request);
|
|
172
|
+
```
|
|
173
|
+
|
|
127
174
|
### Context Object
|
|
128
175
|
|
|
129
176
|
Handler and middleware functions receive a context object:
|
|
@@ -131,12 +178,19 @@ Handler and middleware functions receive a context object:
|
|
|
131
178
|
```javascript
|
|
132
179
|
{
|
|
133
180
|
params: Record<string, string>, // URL parameters
|
|
134
|
-
|
|
135
|
-
caches?: CacheStorage, // All available caches
|
|
136
|
-
// ... additional context
|
|
181
|
+
// Middleware can add arbitrary properties
|
|
137
182
|
}
|
|
138
183
|
```
|
|
139
184
|
|
|
185
|
+
Middleware can extend context with custom properties:
|
|
186
|
+
|
|
187
|
+
```javascript
|
|
188
|
+
router.use(async function* (request, context) {
|
|
189
|
+
context.user = await authenticate(request);
|
|
190
|
+
return yield request;
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
140
194
|
## Examples
|
|
141
195
|
|
|
142
196
|
### Basic API Router
|
|
@@ -144,7 +198,7 @@ Handler and middleware functions receive a context object:
|
|
|
144
198
|
```javascript
|
|
145
199
|
const router = new Router();
|
|
146
200
|
|
|
147
|
-
router.get('/api/health', () =>
|
|
201
|
+
router.get('/api/health', () =>
|
|
148
202
|
Response.json({ status: 'ok' })
|
|
149
203
|
);
|
|
150
204
|
|
|
@@ -160,40 +214,43 @@ router.post('/api/posts', async (request) => {
|
|
|
160
214
|
});
|
|
161
215
|
```
|
|
162
216
|
|
|
163
|
-
###
|
|
217
|
+
### Authentication Middleware
|
|
164
218
|
|
|
165
219
|
```javascript
|
|
166
|
-
|
|
167
|
-
import { CacheStorage, MemoryCache } from '@b9g/cache';
|
|
168
|
-
|
|
169
|
-
const caches = new CacheStorage();
|
|
170
|
-
caches.register('api', () => new MemoryCache('api'));
|
|
171
|
-
|
|
172
|
-
const router = new Router({ caches });
|
|
220
|
+
const router = new Router();
|
|
173
221
|
|
|
174
|
-
//
|
|
175
|
-
router.use(async (request, context
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
222
|
+
// Add user to context
|
|
223
|
+
router.use(async function* (request, context) {
|
|
224
|
+
const token = request.headers.get('Authorization')?.replace('Bearer ', '');
|
|
225
|
+
if (token) {
|
|
226
|
+
context.user = await verifyToken(token);
|
|
179
227
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
228
|
+
return yield request;
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// Protected route
|
|
232
|
+
router.get('/api/profile', async (request, context) => {
|
|
233
|
+
if (!context.user) {
|
|
234
|
+
return new Response('Unauthorized', { status: 401 });
|
|
185
235
|
}
|
|
186
|
-
|
|
187
|
-
return response;
|
|
236
|
+
return Response.json(context.user);
|
|
188
237
|
});
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Subrouter Mounting
|
|
189
241
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
242
|
+
```javascript
|
|
243
|
+
// API subrouter
|
|
244
|
+
const apiRouter = new Router();
|
|
245
|
+
apiRouter.get('/users', getUsersHandler);
|
|
246
|
+
apiRouter.get('/posts', getPostsHandler);
|
|
247
|
+
|
|
248
|
+
// Main router
|
|
249
|
+
const mainRouter = new Router();
|
|
250
|
+
mainRouter.mount('/api/v1', apiRouter);
|
|
251
|
+
// Routes become: /api/v1/users, /api/v1/posts
|
|
195
252
|
```
|
|
196
253
|
|
|
197
254
|
## License
|
|
198
255
|
|
|
199
|
-
MIT
|
|
256
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@b9g/router",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
|
+
"description": "Universal request router for ServiceWorker applications. Built on web standards with cache-aware routing and generator-based middleware.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"router",
|
|
7
|
+
"serviceworker",
|
|
8
|
+
"middleware",
|
|
9
|
+
"cache",
|
|
10
|
+
"universal",
|
|
11
|
+
"web-standards",
|
|
12
|
+
"urlpattern",
|
|
13
|
+
"shovel"
|
|
14
|
+
],
|
|
4
15
|
"dependencies": {
|
|
5
|
-
"@b9g/match-pattern": "^0.1.
|
|
16
|
+
"@b9g/match-pattern": "^0.1.7"
|
|
6
17
|
},
|
|
7
18
|
"devDependencies": {
|
|
8
19
|
"@b9g/libuild": "^0.1.11",
|
|
@@ -24,14 +35,6 @@
|
|
|
24
35
|
"types": "./src/index.d.ts",
|
|
25
36
|
"import": "./src/index.js"
|
|
26
37
|
},
|
|
27
|
-
"./router": {
|
|
28
|
-
"types": "./src/router.d.ts",
|
|
29
|
-
"import": "./src/router.js"
|
|
30
|
-
},
|
|
31
|
-
"./router.js": {
|
|
32
|
-
"types": "./src/router.d.ts",
|
|
33
|
-
"import": "./src/router.js"
|
|
34
|
-
},
|
|
35
38
|
"./package.json": "./package.json"
|
|
36
39
|
}
|
|
37
40
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -3,10 +3,190 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Features:
|
|
5
5
|
* - Pure Request/Response routing (works anywhere)
|
|
6
|
-
* - Middleware chain with next() continuation
|
|
7
6
|
* - Chainable route builder API
|
|
8
|
-
* -
|
|
9
|
-
* -
|
|
7
|
+
* - Generator-based middleware with yield continuation
|
|
8
|
+
* - Integration with URLPattern and MatchPattern for enhanced URL matching
|
|
9
|
+
* - Cache-aware routing
|
|
10
|
+
* TODO:
|
|
11
|
+
* - Portable param matching
|
|
12
|
+
* - Typechecking
|
|
10
13
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Context object passed to handlers and middleware
|
|
16
|
+
* Contains route parameters extracted from URL pattern matching
|
|
17
|
+
*/
|
|
18
|
+
export interface RouteContext {
|
|
19
|
+
/** Route parameters extracted from URL pattern matching */
|
|
20
|
+
params: Record<string, string>;
|
|
21
|
+
/** Middleware can add arbitrary properties for context sharing */
|
|
22
|
+
[key: string]: any;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Handler function signature - terminal response producer
|
|
26
|
+
* Handlers are terminal - must return a Response
|
|
27
|
+
*/
|
|
28
|
+
export type Handler = (request: Request, context: RouteContext) => Response | Promise<Response>;
|
|
29
|
+
/**
|
|
30
|
+
* Generator middleware signature - uses yield for continuation
|
|
31
|
+
* Provides clean syntax and eliminates control flow bugs
|
|
32
|
+
*/
|
|
33
|
+
export type GeneratorMiddleware = (request: Request, context: RouteContext) => Generator<Request, Response | null | undefined, Response> | AsyncGenerator<Request, Response | null | undefined, Response>;
|
|
34
|
+
/**
|
|
35
|
+
* Function middleware signature - supports short-circuiting
|
|
36
|
+
* Can modify request and context, and can return a Response to short-circuit
|
|
37
|
+
* - Return Response: short-circuits, skipping remaining middleware and handler
|
|
38
|
+
* - Return null/undefined: continues to next middleware (fallthrough)
|
|
39
|
+
*/
|
|
40
|
+
export type FunctionMiddleware = (request: Request, context: RouteContext) => Response | null | undefined | Promise<Response | null | undefined>;
|
|
41
|
+
/**
|
|
42
|
+
* Union type for all supported middleware types
|
|
43
|
+
* Framework automatically detects type and executes appropriately
|
|
44
|
+
*/
|
|
45
|
+
export type Middleware = GeneratorMiddleware | FunctionMiddleware;
|
|
46
|
+
/**
|
|
47
|
+
* HTTP methods supported by the router
|
|
48
|
+
*/
|
|
49
|
+
export type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS";
|
|
50
|
+
/**
|
|
51
|
+
* Route configuration options
|
|
52
|
+
*/
|
|
53
|
+
export interface RouteConfig {
|
|
54
|
+
/** URL pattern for the route */
|
|
55
|
+
pattern: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Internal route entry stored by the router
|
|
59
|
+
*/
|
|
60
|
+
interface RouteEntry {
|
|
61
|
+
pattern: import("@b9g/match-pattern").MatchPattern;
|
|
62
|
+
method: string;
|
|
63
|
+
handler: Handler;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Internal middleware entry stored by the router
|
|
67
|
+
*/
|
|
68
|
+
interface MiddlewareEntry {
|
|
69
|
+
middleware: Middleware;
|
|
70
|
+
/** If set, middleware only runs for paths matching this prefix */
|
|
71
|
+
pathPrefix?: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* RouteBuilder provides a chainable API for defining routes with multiple HTTP methods
|
|
75
|
+
*
|
|
76
|
+
* Example:
|
|
77
|
+
* router.route('/api/users/:id')
|
|
78
|
+
* .get(getUserHandler)
|
|
79
|
+
* .put(updateUserHandler)
|
|
80
|
+
* .delete(deleteUserHandler);
|
|
81
|
+
*/
|
|
82
|
+
declare class RouteBuilder {
|
|
83
|
+
#private;
|
|
84
|
+
constructor(router: Router, pattern: string);
|
|
85
|
+
/**
|
|
86
|
+
* Register a GET handler for this route pattern
|
|
87
|
+
*/
|
|
88
|
+
get(handler: Handler): RouteBuilder;
|
|
89
|
+
/**
|
|
90
|
+
* Register a POST handler for this route pattern
|
|
91
|
+
*/
|
|
92
|
+
post(handler: Handler): RouteBuilder;
|
|
93
|
+
/**
|
|
94
|
+
* Register a PUT handler for this route pattern
|
|
95
|
+
*/
|
|
96
|
+
put(handler: Handler): RouteBuilder;
|
|
97
|
+
/**
|
|
98
|
+
* Register a DELETE handler for this route pattern
|
|
99
|
+
*/
|
|
100
|
+
delete(handler: Handler): RouteBuilder;
|
|
101
|
+
/**
|
|
102
|
+
* Register a PATCH handler for this route pattern
|
|
103
|
+
*/
|
|
104
|
+
patch(handler: Handler): RouteBuilder;
|
|
105
|
+
/**
|
|
106
|
+
* Register a HEAD handler for this route pattern
|
|
107
|
+
*/
|
|
108
|
+
head(handler: Handler): RouteBuilder;
|
|
109
|
+
/**
|
|
110
|
+
* Register an OPTIONS handler for this route pattern
|
|
111
|
+
*/
|
|
112
|
+
options(handler: Handler): RouteBuilder;
|
|
113
|
+
/**
|
|
114
|
+
* Register a handler for all HTTP methods on this route pattern
|
|
115
|
+
*/
|
|
116
|
+
all(handler: Handler): RouteBuilder;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Router provides Request/Response routing with middleware support
|
|
120
|
+
* Designed to work universally across all JavaScript runtimes
|
|
121
|
+
*/
|
|
122
|
+
export declare class Router {
|
|
123
|
+
#private;
|
|
124
|
+
constructor();
|
|
125
|
+
/**
|
|
126
|
+
* Register middleware that applies to all routes
|
|
127
|
+
* Middleware executes in the order it was registered
|
|
128
|
+
*/
|
|
129
|
+
use(middleware: Middleware): void;
|
|
130
|
+
/**
|
|
131
|
+
* Register middleware that only applies to routes matching the path prefix
|
|
132
|
+
*/
|
|
133
|
+
use(pathPrefix: string, middleware: Middleware): void;
|
|
134
|
+
/**
|
|
135
|
+
* Create a route builder for the given pattern
|
|
136
|
+
* Returns a chainable interface for registering HTTP method handlers
|
|
137
|
+
*
|
|
138
|
+
* Example:
|
|
139
|
+
* router.route('/api/users/:id')
|
|
140
|
+
* .get(getUserHandler)
|
|
141
|
+
* .put(updateUserHandler);
|
|
142
|
+
*/
|
|
143
|
+
route(pattern: string): RouteBuilder;
|
|
144
|
+
route(config: RouteConfig): RouteBuilder;
|
|
145
|
+
/**
|
|
146
|
+
* Internal method called by RouteBuilder to register routes
|
|
147
|
+
* Public for RouteBuilder access, but not intended for direct use
|
|
148
|
+
*/
|
|
149
|
+
addRoute(method: HTTPMethod, pattern: string, handler: Handler): void;
|
|
150
|
+
/**
|
|
151
|
+
* Handle a request - main entrypoint for ServiceWorker usage
|
|
152
|
+
* Returns a response or throws if no route matches
|
|
153
|
+
*/
|
|
154
|
+
handler: (request: Request) => Promise<Response>;
|
|
155
|
+
/**
|
|
156
|
+
* Match a request against registered routes and execute the handler chain
|
|
157
|
+
* Returns the response from the matched handler, or null if no route matches
|
|
158
|
+
* Note: Global middleware executes even if no route matches
|
|
159
|
+
*/
|
|
160
|
+
match(request: Request): Promise<Response | null>;
|
|
161
|
+
/**
|
|
162
|
+
* Get registered routes for debugging/introspection
|
|
163
|
+
*/
|
|
164
|
+
getRoutes(): RouteEntry[];
|
|
165
|
+
/**
|
|
166
|
+
* Get registered middleware for debugging/introspection
|
|
167
|
+
*/
|
|
168
|
+
getMiddlewares(): MiddlewareEntry[];
|
|
169
|
+
/**
|
|
170
|
+
* Mount a subrouter at a specific path prefix
|
|
171
|
+
* All routes from the subrouter will be prefixed with the mount path
|
|
172
|
+
*
|
|
173
|
+
* Example:
|
|
174
|
+
* const apiRouter = new Router();
|
|
175
|
+
* apiRouter.route('/users').get(getUsersHandler);
|
|
176
|
+
* apiRouter.route('/users/:id').get(getUserHandler);
|
|
177
|
+
*
|
|
178
|
+
* const mainRouter = new Router();
|
|
179
|
+
* mainRouter.mount('/api/v1', apiRouter);
|
|
180
|
+
* // Routes become: /api/v1/users, /api/v1/users/:id
|
|
181
|
+
*/
|
|
182
|
+
mount(mountPath: string, subrouter: Router): void;
|
|
183
|
+
/**
|
|
184
|
+
* Get route statistics
|
|
185
|
+
*/
|
|
186
|
+
getStats(): {
|
|
187
|
+
routeCount: number;
|
|
188
|
+
middlewareCount: number;
|
|
189
|
+
compiled: boolean;
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
export {};
|