@nextrush/router 3.0.0

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.
@@ -0,0 +1,301 @@
1
+ import { RouterOptions, RouteHandler, HttpMethod, Middleware, RouteMatch, Context } from '@nextrush/types';
2
+ export { HttpMethod, Middleware, Route, RouteHandler, RouteMatch, Router as RouterInterface, RouterOptions } from '@nextrush/types';
3
+
4
+ /**
5
+ * @nextrush/router - Router Implementation
6
+ *
7
+ * High-performance router using a segment trie for route matching.
8
+ * Routes are keyed by full path segments (e.g. "users", ":id"), not by
9
+ * individual characters — this is a segment-based trie, not a compressed
10
+ * radix tree. Supports parameters, wildcards, and method-based routing.
11
+ *
12
+ * @packageDocumentation
13
+ */
14
+
15
+ /**
16
+ * Router class — high-performance segment trie router
17
+ *
18
+ * Routes are indexed by path segment, giving O(d) lookup where d is the
19
+ * number of segments. Static routes are additionally stored in a hash map
20
+ * for O(1) fast-path lookup.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const router = createRouter();
25
+ *
26
+ * router.get('/users', listUsers);
27
+ * router.get('/users/:id', getUser);
28
+ * router.post('/users', createUser);
29
+ *
30
+ * app.use(router.routes());
31
+ * ```
32
+ */
33
+ declare class Router {
34
+ private readonly root;
35
+ private readonly opts;
36
+ private readonly routerMiddleware;
37
+ /**
38
+ * Static route hash map for O(1) lookup.
39
+ * Key: "METHOD path" (e.g. "GET /users"), Value: HandlerEntry
40
+ */
41
+ private readonly staticRoutes;
42
+ /** Whether any routes have params or wildcards (disables static-only fast path) */
43
+ private hasParamRoutes;
44
+ constructor(options?: RouterOptions);
45
+ /**
46
+ * Normalize path based on router options
47
+ */
48
+ private normalizePath;
49
+ /**
50
+ * Add a route to the radix tree
51
+ */
52
+ private addRoute;
53
+ get(path: string, ...handlers: RouteHandler[]): this;
54
+ post(path: string, ...handlers: RouteHandler[]): this;
55
+ put(path: string, ...handlers: RouteHandler[]): this;
56
+ delete(path: string, ...handlers: RouteHandler[]): this;
57
+ patch(path: string, ...handlers: RouteHandler[]): this;
58
+ head(path: string, ...handlers: RouteHandler[]): this;
59
+ options(path: string, ...handlers: RouteHandler[]): this;
60
+ all(path: string, ...handlers: RouteHandler[]): this;
61
+ route(method: HttpMethod, path: string, ...handlers: RouteHandler[]): this;
62
+ /**
63
+ * Register a redirect route from one path to another
64
+ *
65
+ * @param from - Source path to redirect from
66
+ * @param to - Target path or URL to redirect to
67
+ * @param status - HTTP status code (default: 301 permanent redirect)
68
+ * @returns this for chaining
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * // Permanent redirect (301)
73
+ * router.redirect('/old-page', '/new-page');
74
+ *
75
+ * // Temporary redirect (302)
76
+ * router.redirect('/temp', '/destination', 302);
77
+ *
78
+ * // Redirect to external URL
79
+ * router.redirect('/docs', 'https://docs.example.com');
80
+ *
81
+ * // With parameters - redirects /users/:id to /profiles/:id
82
+ * router.redirect('/users/:id', '/profiles/:id');
83
+ * ```
84
+ */
85
+ redirect(from: string, to: string, status?: 301 | 302 | 303 | 307 | 308): this;
86
+ use(pathOrMiddleware: string | Middleware | Router, routerOrUndefined?: Router): this;
87
+ /**
88
+ * Mount a sub-router at a path prefix (Hono-style)
89
+ *
90
+ * This is the explicit API for mounting sub-routers.
91
+ * Equivalent to `router.use(path, subRouter)` but more semantic.
92
+ *
93
+ * @param path - Path prefix for the sub-router
94
+ * @param router - Router instance to mount
95
+ * @returns this for chaining
96
+ *
97
+ * @example
98
+ * ```typescript
99
+ * // Create modular routers
100
+ * const users = createRouter();
101
+ * users.get('/', listUsers);
102
+ * users.get('/:id', getUser);
103
+ *
104
+ * const posts = createRouter();
105
+ * posts.get('/', listPosts);
106
+ *
107
+ * // Mount sub-routers
108
+ * const api = createRouter();
109
+ * api.mount('/users', users);
110
+ * api.mount('/posts', posts);
111
+ *
112
+ * // Or use on main router
113
+ * const router = createRouter();
114
+ * router.mount('/api', api);
115
+ *
116
+ * app.use(router.routes());
117
+ * ```
118
+ */
119
+ mount(path: string, router: Router): this;
120
+ /**
121
+ * Mount a sub-router (internal)
122
+ *
123
+ * Carries the sub-router's own `routerMiddleware` forward so that
124
+ * `subrouter.use(mw)` middleware applies to every copied route.
125
+ */
126
+ private mountRouter;
127
+ /**
128
+ * Recursively copy routes from another router
129
+ */
130
+ private copyRoutes;
131
+ /**
132
+ * Match a route and return handler + params
133
+ */
134
+ match(method: HttpMethod, path: string): RouteMatch | null;
135
+ /**
136
+ * Extract the next segment from path at given position without allocating arrays.
137
+ * Returns [segment, nextIndex] where nextIndex is position after the trailing '/'.
138
+ */
139
+ private extractSegment;
140
+ /**
141
+ * Index-based recursive node matching (avoids array allocation)
142
+ */
143
+ private matchNodeIndexed;
144
+ /**
145
+ * Get routes middleware function
146
+ * Mount this on the application
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * app.use(router.routes());
151
+ * ```
152
+ */
153
+ routes(): Middleware;
154
+ /**
155
+ * Re-compile all route executors to include router-level middleware.
156
+ * Called once when routes() is invoked, not per-request.
157
+ */
158
+ private sealRouterMiddleware;
159
+ /**
160
+ * Generate allowed methods middleware
161
+ * Responds to OPTIONS and sets Allow header
162
+ */
163
+ allowedMethods(): Middleware;
164
+ /**
165
+ * Find all HTTP methods registered for a given path via single tree walk
166
+ * @internal
167
+ */
168
+ private findAllowedMethods;
169
+ /**
170
+ * Walk the tree to find the node matching a path (ignoring HTTP method)
171
+ * @internal
172
+ */
173
+ private findNode;
174
+ /**
175
+ * Create a route group with shared prefix and middleware
176
+ *
177
+ * @param prefix - Path prefix for all routes in the group
178
+ * @param middlewareOrCallback - Middleware array or callback function
179
+ * @param callback - Callback function if middleware is provided
180
+ * @returns this for chaining
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * // Simple group with prefix
185
+ * router.group('/api', (r) => {
186
+ * r.get('/users', listUsers);
187
+ * r.get('/posts', listPosts);
188
+ * });
189
+ *
190
+ * // Group with middleware
191
+ * router.group('/admin', [authMiddleware], (r) => {
192
+ * r.get('/dashboard', dashboard);
193
+ * r.post('/settings', updateSettings);
194
+ * });
195
+ *
196
+ * // Nested groups
197
+ * router.group('/api/v1', (r) => {
198
+ * r.group('/users', [rateLimit], (ur) => {
199
+ * ur.get('/', listUsers);
200
+ * ur.get('/:id', getUser);
201
+ * });
202
+ * });
203
+ * ```
204
+ */
205
+ group(prefix: string, middlewareOrCallback: Middleware[] | ((router: Router) => void), callback?: (router: Router) => void): this;
206
+ /**
207
+ * Remove all registered routes and middleware, resetting the router to its initial state.
208
+ * Useful for plugin `destroy()` to cleanly un-register routes.
209
+ */
210
+ reset(): void;
211
+ /**
212
+ * Internal method to add route with group context
213
+ * @internal
214
+ */
215
+ _addGroupRoute(method: HttpMethod, path: string, handlers: RouteHandler[], groupMiddleware: Middleware[]): void;
216
+ }
217
+ /**
218
+ * Create a new Router instance
219
+ *
220
+ * @param options - Router options
221
+ * @returns New Router instance
222
+ *
223
+ * @example
224
+ * ```typescript
225
+ * const router = createRouter();
226
+ * const apiRouter = createRouter({ prefix: '/api/v1' });
227
+ * ```
228
+ */
229
+ declare function createRouter(options?: RouterOptions): Router;
230
+
231
+ /**
232
+ * @nextrush/router - Segment Trie Node
233
+ *
234
+ * Internal segment trie implementation for high-performance route matching.
235
+ * Uses a compressed trie structure for O(k) lookups where k is path length.
236
+ *
237
+ * @packageDocumentation
238
+ * @internal
239
+ */
240
+
241
+ /**
242
+ * Node type enumeration
243
+ */
244
+ declare const enum NodeType {
245
+ /** Static path segment: /users */
246
+ STATIC = 0,
247
+ /** Named parameter: /:id */
248
+ PARAM = 1,
249
+ /** Wildcard: /* */
250
+ WILDCARD = 2
251
+ }
252
+ /**
253
+ * Radix tree node
254
+ */
255
+ interface RadixNode {
256
+ /** Path segment for this node */
257
+ segment: string;
258
+ /** Node type */
259
+ type: NodeType;
260
+ /** Children nodes keyed by first character */
261
+ children: Map<string, RadixNode>;
262
+ /** Parameter name if this is a param node */
263
+ paramName?: string;
264
+ /** Handlers keyed by HTTP method */
265
+ handlers: Map<HttpMethod, HandlerEntry>;
266
+ /** Wildcard child if any */
267
+ wildcardChild?: RadixNode;
268
+ /** Parameter child if any */
269
+ paramChild?: RadixNode;
270
+ }
271
+ /**
272
+ * Handler entry with middleware and pre-compiled executor
273
+ */
274
+ interface HandlerEntry {
275
+ handler: RouteHandler;
276
+ middleware: Middleware[];
277
+ /** Pre-compiled executor for fast dispatch (no closure per request) */
278
+ executor?: (ctx: Context) => Promise<void>;
279
+ }
280
+ /**
281
+ * Create a new radix node
282
+ */
283
+ declare function createNode(segment: string, type?: NodeType): RadixNode;
284
+ /**
285
+ * Parse path segments
286
+ * Splits path into segments and identifies param/wildcard types
287
+ *
288
+ * @param path - Route path to parse
289
+ * @param caseSensitive - If false, lowercase static segments for case-insensitive matching
290
+ */
291
+ declare function parseSegments(path: string, caseSensitive?: boolean): ParsedSegment[];
292
+ /**
293
+ * Parsed segment structure
294
+ */
295
+ interface ParsedSegment {
296
+ segment: string;
297
+ type: NodeType;
298
+ paramName?: string;
299
+ }
300
+
301
+ export { type HandlerEntry, NodeType, type ParsedSegment, type RadixNode, Router, createNode, createRouter, parseSegments };