@mxweb/core 1.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.
- package/LICENSE +21 -0
- package/README.md +61 -0
- package/dist/application.d.ts +402 -0
- package/dist/application.js +1 -0
- package/dist/application.mjs +1 -0
- package/dist/common.d.ts +323 -0
- package/dist/common.js +1 -0
- package/dist/common.mjs +1 -0
- package/dist/config.d.ts +258 -0
- package/dist/config.js +1 -0
- package/dist/config.mjs +1 -0
- package/dist/context.d.ts +48 -0
- package/dist/context.js +1 -0
- package/dist/context.mjs +1 -0
- package/dist/controller.d.ts +238 -0
- package/dist/controller.js +1 -0
- package/dist/controller.mjs +1 -0
- package/dist/decorator.d.ts +349 -0
- package/dist/decorator.js +1 -0
- package/dist/decorator.mjs +1 -0
- package/dist/error.d.ts +301 -0
- package/dist/error.js +1 -0
- package/dist/error.mjs +1 -0
- package/dist/execute.d.ts +469 -0
- package/dist/execute.js +1 -0
- package/dist/execute.mjs +1 -0
- package/dist/feature.d.ts +239 -0
- package/dist/feature.js +1 -0
- package/dist/feature.mjs +1 -0
- package/dist/hooks.d.ts +251 -0
- package/dist/hooks.js +1 -0
- package/dist/hooks.mjs +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- package/dist/logger.d.ts +360 -0
- package/dist/logger.js +1 -0
- package/dist/logger.mjs +1 -0
- package/dist/response.d.ts +665 -0
- package/dist/response.js +1 -0
- package/dist/response.mjs +1 -0
- package/dist/route.d.ts +298 -0
- package/dist/route.js +1 -0
- package/dist/route.mjs +1 -0
- package/dist/router.d.ts +205 -0
- package/dist/router.js +1 -0
- package/dist/router.mjs +1 -0
- package/dist/service.d.ts +261 -0
- package/dist/service.js +1 -0
- package/dist/service.mjs +1 -0
- package/package.json +168 -0
package/dist/route.d.ts
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Route definition for mapping HTTP methods and paths to handlers.
|
|
3
|
+
*
|
|
4
|
+
* This module provides the `Route` class which represents a single route definition
|
|
5
|
+
* in the application. Routes are created using static factory methods and can include:
|
|
6
|
+
* - HTTP method (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)
|
|
7
|
+
* - Path pattern with dynamic segments (e.g., "/users/:id")
|
|
8
|
+
* - Handler (controller method name or function)
|
|
9
|
+
* - Decorators (guards, filters, interceptors, pipes)
|
|
10
|
+
* - Middlewares
|
|
11
|
+
*
|
|
12
|
+
* @module route
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { Route, applyDecorators, UseGuards } from "@mxweb/core";
|
|
17
|
+
*
|
|
18
|
+
* // Simple routes
|
|
19
|
+
* Route.get("/users", "findAll")
|
|
20
|
+
* Route.post("/users", "create")
|
|
21
|
+
* Route.get("/users/:id", "findOne")
|
|
22
|
+
*
|
|
23
|
+
* // Route with decorators
|
|
24
|
+
* Route.delete(
|
|
25
|
+
* "/users/:id",
|
|
26
|
+
* "remove",
|
|
27
|
+
* applyDecorators(UseGuards(AuthGuard, AdminGuard))
|
|
28
|
+
* )
|
|
29
|
+
*
|
|
30
|
+
* // Route with inline handler
|
|
31
|
+
* Route.get("/health", async (ctx) => {
|
|
32
|
+
* return ctx.response.success({ status: "ok" });
|
|
33
|
+
* })
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
import { RouteMethod } from "./common";
|
|
37
|
+
import { DecoratorResult } from "./decorator";
|
|
38
|
+
import { Reflect, RouteHandler, RouteMiddleware } from "./execute";
|
|
39
|
+
/**
|
|
40
|
+
* Represents a single route definition in the application.
|
|
41
|
+
*
|
|
42
|
+
* A Route encapsulates all information needed to match and handle an HTTP request:
|
|
43
|
+
* - The HTTP method (GET, POST, etc.)
|
|
44
|
+
* - The URL path pattern
|
|
45
|
+
* - The handler (controller method name or function)
|
|
46
|
+
* - Route-level guards, filters, interceptors, and pipes
|
|
47
|
+
* - Custom middlewares
|
|
48
|
+
*
|
|
49
|
+
* Routes are created using static factory methods (`get`, `post`, etc.)
|
|
50
|
+
* and are typically grouped together in a Router.
|
|
51
|
+
*
|
|
52
|
+
* @remarks
|
|
53
|
+
* The constructor is private - always use static factory methods to create routes.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* // Creating routes for a product feature
|
|
58
|
+
* const routes = [
|
|
59
|
+
* Route.get("/", "findAll"),
|
|
60
|
+
* Route.get("/:id", "findOne"),
|
|
61
|
+
* Route.post("/", "create", applyDecorators(UseGuards(AuthGuard))),
|
|
62
|
+
* Route.put("/:id", "update", applyDecorators(UseGuards(AuthGuard))),
|
|
63
|
+
* Route.delete("/:id", "remove", applyDecorators(UseGuards(AuthGuard, AdminGuard))),
|
|
64
|
+
* ];
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare class Route {
|
|
68
|
+
private readonly method;
|
|
69
|
+
private readonly path;
|
|
70
|
+
private readonly action;
|
|
71
|
+
private readonly reflect;
|
|
72
|
+
private readonly middlewares;
|
|
73
|
+
/**
|
|
74
|
+
* Private constructor to enforce factory method usage.
|
|
75
|
+
*
|
|
76
|
+
* @param method - The HTTP method for this route
|
|
77
|
+
* @param path - The URL path pattern (can include dynamic segments like :id)
|
|
78
|
+
* @param action - Controller method name or inline handler function
|
|
79
|
+
* @param reflect - Reflect instance containing guards, filters, interceptors, pipes
|
|
80
|
+
* @param middlewares - Array of middleware functions for this route
|
|
81
|
+
*/
|
|
82
|
+
private constructor();
|
|
83
|
+
/**
|
|
84
|
+
* Gets the HTTP method for this route.
|
|
85
|
+
*
|
|
86
|
+
* @returns The RouteMethod enum value
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* const route = Route.get("/users", "findAll");
|
|
91
|
+
* console.log(route.getMethod()); // RouteMethod.GET
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
getMethod(): RouteMethod;
|
|
95
|
+
/**
|
|
96
|
+
* Gets the URL path pattern for this route.
|
|
97
|
+
*
|
|
98
|
+
* @returns The path string (e.g., "/users/:id")
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```ts
|
|
102
|
+
* const route = Route.get("/users/:id", "findOne");
|
|
103
|
+
* console.log(route.getPath()); // "/users/:id"
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
getPath(): string;
|
|
107
|
+
/**
|
|
108
|
+
* Gets the action (handler) for this route.
|
|
109
|
+
*
|
|
110
|
+
* @returns The controller method name (string) or handler function
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```ts
|
|
114
|
+
* const route = Route.get("/users", "findAll");
|
|
115
|
+
* console.log(route.getAction()); // "findAll"
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
getAction(): string | RouteHandler;
|
|
119
|
+
/**
|
|
120
|
+
* Gets the Reflect instance containing route-level decorators.
|
|
121
|
+
*
|
|
122
|
+
* @returns The Reflect instance with guards, filters, interceptors, pipes, and metadata
|
|
123
|
+
*/
|
|
124
|
+
getReflect(): Reflect;
|
|
125
|
+
/**
|
|
126
|
+
* Gets the middleware functions for this route.
|
|
127
|
+
*
|
|
128
|
+
* @returns Array of middleware functions
|
|
129
|
+
*/
|
|
130
|
+
getMiddlewares(): RouteMiddleware[];
|
|
131
|
+
/**
|
|
132
|
+
* Normalizes decorator/middleware arguments into a consistent format.
|
|
133
|
+
*
|
|
134
|
+
* This method handles the flexible API where the third parameter can be either
|
|
135
|
+
* a DecoratorResult (from applyDecorators) or a middleware function.
|
|
136
|
+
*
|
|
137
|
+
* @param decoratorsOrMiddleware - Either a DecoratorResult or a middleware function
|
|
138
|
+
* @param middlewares - Additional middleware functions
|
|
139
|
+
* @returns Tuple of [Reflect instance, middlewares array]
|
|
140
|
+
* @internal
|
|
141
|
+
*/
|
|
142
|
+
private static normalize;
|
|
143
|
+
/**
|
|
144
|
+
* Creates a route with the specified HTTP method.
|
|
145
|
+
*
|
|
146
|
+
* This is the base factory method used by all HTTP method shortcuts.
|
|
147
|
+
*
|
|
148
|
+
* @param method - The HTTP method
|
|
149
|
+
* @param path - The URL path pattern
|
|
150
|
+
* @param action - Controller method name or handler function
|
|
151
|
+
* @param decoratorsOrMiddleware - Optional decorators or first middleware
|
|
152
|
+
* @param middlewares - Additional middlewares
|
|
153
|
+
* @returns A new Route instance
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```ts
|
|
157
|
+
* Route.route(RouteMethod.GET, "/custom", "handler")
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
static route(method: RouteMethod, path: string, action: string | RouteHandler, decoratorsOrMiddleware?: DecoratorResult | RouteMiddleware, middlewares?: RouteMiddleware[]): Route;
|
|
161
|
+
/**
|
|
162
|
+
* Creates a GET route.
|
|
163
|
+
*
|
|
164
|
+
* Used for retrieving resources without side effects.
|
|
165
|
+
*
|
|
166
|
+
* @param path - The URL path pattern
|
|
167
|
+
* @param handle - Controller method name or handler function
|
|
168
|
+
* @param decoratorsOrMiddleware - Optional decorators or first middleware
|
|
169
|
+
* @param middlewares - Additional middlewares
|
|
170
|
+
* @returns A new Route instance for GET requests
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```ts
|
|
174
|
+
* // Simple GET route
|
|
175
|
+
* Route.get("/users", "findAll")
|
|
176
|
+
*
|
|
177
|
+
* // GET with path parameter
|
|
178
|
+
* Route.get("/users/:id", "findOne")
|
|
179
|
+
*
|
|
180
|
+
* // GET with guards
|
|
181
|
+
* Route.get("/profile", "getProfile", applyDecorators(UseGuards(AuthGuard)))
|
|
182
|
+
*
|
|
183
|
+
* // GET with inline handler
|
|
184
|
+
* Route.get("/ping", async () => ({ pong: true }))
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
static get(path: string, handle: string | RouteHandler, decoratorsOrMiddleware?: DecoratorResult | RouteMiddleware, ...middlewares: RouteMiddleware[]): Route;
|
|
188
|
+
/**
|
|
189
|
+
* Creates a POST route.
|
|
190
|
+
*
|
|
191
|
+
* Used for creating new resources.
|
|
192
|
+
*
|
|
193
|
+
* @param path - The URL path pattern
|
|
194
|
+
* @param handle - Controller method name or handler function
|
|
195
|
+
* @param decoratorsOrMiddleware - Optional decorators or first middleware
|
|
196
|
+
* @param middlewares - Additional middlewares
|
|
197
|
+
* @returns A new Route instance for POST requests
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```ts
|
|
201
|
+
* // Create resource
|
|
202
|
+
* Route.post("/users", "create")
|
|
203
|
+
*
|
|
204
|
+
* // With validation pipe
|
|
205
|
+
* Route.post("/users", "create", applyDecorators(UsePipes(ValidationPipe)))
|
|
206
|
+
* ```
|
|
207
|
+
*/
|
|
208
|
+
static post(path: string, handle: string | RouteHandler, decoratorsOrMiddleware?: DecoratorResult | RouteMiddleware, ...middlewares: RouteMiddleware[]): Route;
|
|
209
|
+
/**
|
|
210
|
+
* Creates a PUT route.
|
|
211
|
+
*
|
|
212
|
+
* Used for replacing an entire resource.
|
|
213
|
+
*
|
|
214
|
+
* @param path - The URL path pattern
|
|
215
|
+
* @param handle - Controller method name or handler function
|
|
216
|
+
* @param decoratorsOrMiddleware - Optional decorators or first middleware
|
|
217
|
+
* @param middlewares - Additional middlewares
|
|
218
|
+
* @returns A new Route instance for PUT requests
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```ts
|
|
222
|
+
* // Replace entire resource
|
|
223
|
+
* Route.put("/users/:id", "replace")
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
static put(path: string, handle: string | RouteHandler, decoratorsOrMiddleware?: DecoratorResult | RouteMiddleware, ...middlewares: RouteMiddleware[]): Route;
|
|
227
|
+
/**
|
|
228
|
+
* Creates a PATCH route.
|
|
229
|
+
*
|
|
230
|
+
* Used for partial updates to a resource.
|
|
231
|
+
*
|
|
232
|
+
* @param path - The URL path pattern
|
|
233
|
+
* @param handle - Controller method name or handler function
|
|
234
|
+
* @param decoratorsOrMiddleware - Optional decorators or first middleware
|
|
235
|
+
* @param middlewares - Additional middlewares
|
|
236
|
+
* @returns A new Route instance for PATCH requests
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ```ts
|
|
240
|
+
* // Partial update
|
|
241
|
+
* Route.patch("/users/:id", "update")
|
|
242
|
+
* ```
|
|
243
|
+
*/
|
|
244
|
+
static patch(path: string, handle: string | RouteHandler, decoratorsOrMiddleware?: DecoratorResult | RouteMiddleware, ...middlewares: RouteMiddleware[]): Route;
|
|
245
|
+
/**
|
|
246
|
+
* Creates a DELETE route.
|
|
247
|
+
*
|
|
248
|
+
* Used for removing resources.
|
|
249
|
+
*
|
|
250
|
+
* @param path - The URL path pattern
|
|
251
|
+
* @param handle - Controller method name or handler function
|
|
252
|
+
* @param decoratorsOrMiddleware - Optional decorators or first middleware
|
|
253
|
+
* @param middlewares - Additional middlewares
|
|
254
|
+
* @returns A new Route instance for DELETE requests
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* ```ts
|
|
258
|
+
* // Delete resource (usually requires auth)
|
|
259
|
+
* Route.delete("/users/:id", "remove", applyDecorators(UseGuards(AuthGuard)))
|
|
260
|
+
* ```
|
|
261
|
+
*/
|
|
262
|
+
static delete(path: string, handle: string | RouteHandler, decoratorsOrMiddleware?: DecoratorResult | RouteMiddleware, ...middlewares: RouteMiddleware[]): Route;
|
|
263
|
+
/**
|
|
264
|
+
* Creates a HEAD route.
|
|
265
|
+
*
|
|
266
|
+
* Used for retrieving headers without body (like GET but without response body).
|
|
267
|
+
*
|
|
268
|
+
* @param path - The URL path pattern
|
|
269
|
+
* @param handle - Controller method name or handler function
|
|
270
|
+
* @param decoratorsOrMiddleware - Optional decorators or first middleware
|
|
271
|
+
* @param middlewares - Additional middlewares
|
|
272
|
+
* @returns A new Route instance for HEAD requests
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* ```ts
|
|
276
|
+
* Route.head("/users/:id", "checkExists")
|
|
277
|
+
* ```
|
|
278
|
+
*/
|
|
279
|
+
static head(path: string, handle: string | RouteHandler, decoratorsOrMiddleware?: DecoratorResult | RouteMiddleware, ...middlewares: RouteMiddleware[]): Route;
|
|
280
|
+
/**
|
|
281
|
+
* Creates an OPTIONS route.
|
|
282
|
+
*
|
|
283
|
+
* Used for describing available communication options for a resource.
|
|
284
|
+
* Typically handled automatically by CORS middleware.
|
|
285
|
+
*
|
|
286
|
+
* @param path - The URL path pattern
|
|
287
|
+
* @param handle - Controller method name or handler function
|
|
288
|
+
* @param decoratorsOrMiddleware - Optional decorators or first middleware
|
|
289
|
+
* @param middlewares - Additional middlewares
|
|
290
|
+
* @returns A new Route instance for OPTIONS requests
|
|
291
|
+
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```ts
|
|
294
|
+
* Route.options("/users", "corsOptions")
|
|
295
|
+
* ```
|
|
296
|
+
*/
|
|
297
|
+
static options(path: string, handle: string | RouteHandler, decoratorsOrMiddleware?: DecoratorResult | RouteMiddleware, ...middlewares: RouteMiddleware[]): Route;
|
|
298
|
+
}
|
package/dist/route.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var t=require("./common.js"),e=require("./execute.js");class r{constructor(t,e,r,s,i=[]){this.method=t,this.path=e,this.action=r,this.reflect=s,this.middlewares=i}getMethod(){return this.method}getPath(){return this.path}getAction(){return this.action}getReflect(){return this.reflect}getMiddlewares(){return this.middlewares}static normalize(t,r){let s={guards:new Set,filters:new Set,interceptors:new Set,pipes:new Set,metadata:new Map};"function"==typeof t?r.unshift(t):t&&(s=t);return[new e.Reflect(s.metadata,s.guards,s.filters,s.interceptors,s.pipes),r]}static route(t,e,s,i,o=[]){return new r(t,e,s,...this.normalize(i,o))}static get(e,r,s,...i){return this.route(t.RouteMethod.GET,e,r,s,i)}static post(e,r,s,...i){return this.route(t.RouteMethod.POST,e,r,s,i)}static put(e,r,s,...i){return this.route(t.RouteMethod.PUT,e,r,s,i)}static patch(e,r,s,...i){return this.route(t.RouteMethod.PATCH,e,r,s,i)}static delete(e,r,s,...i){return this.route(t.RouteMethod.DELETE,e,r,s,i)}static head(e,r,s,...i){return this.route(t.RouteMethod.HEAD,e,r,s,i)}static options(e,r,s,...i){return this.route(t.RouteMethod.OPTIONS,e,r,s,i)}}exports.Route=r;
|
package/dist/route.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{RouteMethod as t}from"./common.mjs";import{Reflect as e}from"./execute.mjs";class r{constructor(t,e,r,i,s=[]){this.method=t,this.path=e,this.action=r,this.reflect=i,this.middlewares=s}getMethod(){return this.method}getPath(){return this.path}getAction(){return this.action}getReflect(){return this.reflect}getMiddlewares(){return this.middlewares}static normalize(t,r){let i={guards:new Set,filters:new Set,interceptors:new Set,pipes:new Set,metadata:new Map};"function"==typeof t?r.unshift(t):t&&(i=t);return[new e(i.metadata,i.guards,i.filters,i.interceptors,i.pipes),r]}static route(t,e,i,s,n=[]){return new r(t,e,i,...this.normalize(s,n))}static get(e,r,i,...s){return this.route(t.GET,e,r,i,s)}static post(e,r,i,...s){return this.route(t.POST,e,r,i,s)}static put(e,r,i,...s){return this.route(t.PUT,e,r,i,s)}static patch(e,r,i,...s){return this.route(t.PATCH,e,r,i,s)}static delete(e,r,i,...s){return this.route(t.DELETE,e,r,i,s)}static head(e,r,i,...s){return this.route(t.HEAD,e,r,i,s)}static options(e,r,i,...s){return this.route(t.OPTIONS,e,r,i,s)}}export{r as Route};
|
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Router for registering routes and matching incoming requests.
|
|
3
|
+
*
|
|
4
|
+
* This module provides the `Router` class which manages a collection of routes
|
|
5
|
+
* and matches incoming requests to the appropriate route handler. Features:
|
|
6
|
+
* - Path parameter extraction (e.g., `/users/:id` → `{ id: "123" }`)
|
|
7
|
+
* - Optional parameters (e.g., `/posts/:id?`)
|
|
8
|
+
* - Wildcard patterns (e.g., `/files/*` captures remaining path segments)
|
|
9
|
+
* - HTTP method matching
|
|
10
|
+
*
|
|
11
|
+
* @module router
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { Router, Route } from "@mxweb/core";
|
|
16
|
+
*
|
|
17
|
+
* // Create a router with routes
|
|
18
|
+
* const router = Router.register(
|
|
19
|
+
* Route.get("/", "index"),
|
|
20
|
+
* Route.get("/:id", "findOne"),
|
|
21
|
+
* Route.post("/", "create"),
|
|
22
|
+
* Route.put("/:id", "update"),
|
|
23
|
+
* Route.delete("/:id", "remove"),
|
|
24
|
+
* );
|
|
25
|
+
*
|
|
26
|
+
* // Match a request
|
|
27
|
+
* const matched = router.match(RouteMethod.GET, "/123");
|
|
28
|
+
* // matched = { route: ..., params: { id: "123" }, wildcards: [] }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
import { RouteMethod } from "./common";
|
|
32
|
+
import { Route } from "./route";
|
|
33
|
+
/**
|
|
34
|
+
* Result of a successful route match.
|
|
35
|
+
*
|
|
36
|
+
* Contains the matched route, extracted path parameters, and any
|
|
37
|
+
* wildcard segments captured from the URL.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* // For pattern "/users/:id" and path "/users/123"
|
|
42
|
+
* const matched: RouteMatched = {
|
|
43
|
+
* route: Route.get("/users/:id", "findOne"),
|
|
44
|
+
* params: { id: "123" },
|
|
45
|
+
* wildcards: []
|
|
46
|
+
* };
|
|
47
|
+
*
|
|
48
|
+
* // For pattern "/files/*" and path "/files/images/photo.jpg"
|
|
49
|
+
* const matched: RouteMatched = {
|
|
50
|
+
* route: Route.get("/files/*", "serveFile"),
|
|
51
|
+
* params: {},
|
|
52
|
+
* wildcards: ["images", "photo.jpg"]
|
|
53
|
+
* };
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export interface RouteMatched {
|
|
57
|
+
/** The matched Route instance */
|
|
58
|
+
route: Route;
|
|
59
|
+
/** Extracted path parameters (e.g., { id: "123" }) */
|
|
60
|
+
params: Record<string, string>;
|
|
61
|
+
/** Wildcard segments captured after a `*` pattern */
|
|
62
|
+
wildcards: string[];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Internal structure for registered routes.
|
|
66
|
+
*
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
69
|
+
export interface RouteRegister {
|
|
70
|
+
/** The HTTP method for this route */
|
|
71
|
+
method: RouteMethod;
|
|
72
|
+
/** The Route instance */
|
|
73
|
+
route: Route;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Router for managing and matching HTTP routes.
|
|
77
|
+
*
|
|
78
|
+
* The Router class provides route registration and URL matching capabilities.
|
|
79
|
+
* It supports:
|
|
80
|
+
* - **Path parameters**: `/users/:id` extracts `id` from the URL
|
|
81
|
+
* - **Optional parameters**: `/posts/:id?` makes `id` optional
|
|
82
|
+
* - **Wildcards**: `/files/*` captures all remaining segments
|
|
83
|
+
* - **Literal segments**: `/api/v1/users` matches exactly
|
|
84
|
+
*
|
|
85
|
+
* @remarks
|
|
86
|
+
* The constructor is private - use `Router.register()` to create instances.
|
|
87
|
+
* Each Feature typically has one Router that groups related routes.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* // Product feature router
|
|
92
|
+
* export const productRouter = Router.register(
|
|
93
|
+
* Route.get("/", "findAll"),
|
|
94
|
+
* Route.get("/:id", "findOne"),
|
|
95
|
+
* Route.post("/", "create", applyDecorators(UseGuards(AuthGuard))),
|
|
96
|
+
* Route.patch("/:id", "update", applyDecorators(UseGuards(AuthGuard))),
|
|
97
|
+
* Route.delete("/:id", "remove", applyDecorators(UseGuards(AuthGuard, AdminGuard))),
|
|
98
|
+
* );
|
|
99
|
+
*
|
|
100
|
+
* // Feature with router
|
|
101
|
+
* export const productFeature = Feature.create({
|
|
102
|
+
* path: "/products",
|
|
103
|
+
* controller: ProductController,
|
|
104
|
+
* router: productRouter,
|
|
105
|
+
* });
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export declare class Router {
|
|
109
|
+
private readonly registered;
|
|
110
|
+
/**
|
|
111
|
+
* Private constructor to enforce factory method usage.
|
|
112
|
+
*
|
|
113
|
+
* @param registered - Set of registered routes
|
|
114
|
+
*/
|
|
115
|
+
private constructor();
|
|
116
|
+
/**
|
|
117
|
+
* Creates a new Router with the specified routes.
|
|
118
|
+
*
|
|
119
|
+
* This is the primary way to create a Router instance. Routes are
|
|
120
|
+
* registered in order and will be matched in that order.
|
|
121
|
+
*
|
|
122
|
+
* @param routes - One or more Route instances to register
|
|
123
|
+
* @returns A new Router instance
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```ts
|
|
127
|
+
* const router = Router.register(
|
|
128
|
+
* Route.get("/", "index"),
|
|
129
|
+
* Route.get("/search", "search"),
|
|
130
|
+
* Route.get("/:id", "findOne"),
|
|
131
|
+
* Route.post("/", "create"),
|
|
132
|
+
* );
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
static register(...routes: Route[]): Router;
|
|
136
|
+
/**
|
|
137
|
+
* Matches an incoming request to a registered route.
|
|
138
|
+
*
|
|
139
|
+
* Iterates through registered routes in order and returns the first
|
|
140
|
+
* match. If no route matches, returns `null`.
|
|
141
|
+
*
|
|
142
|
+
* @param method - The HTTP method of the request
|
|
143
|
+
* @param path - The URL path to match (e.g., "/users/123")
|
|
144
|
+
* @returns RouteMatched object if found, null otherwise
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* const router = Router.register(
|
|
149
|
+
* Route.get("/:id", "findOne"),
|
|
150
|
+
* );
|
|
151
|
+
*
|
|
152
|
+
* const matched = router.match(RouteMethod.GET, "/456");
|
|
153
|
+
* if (matched) {
|
|
154
|
+
* console.log(matched.params.id); // "456"
|
|
155
|
+
* console.log(matched.route.getAction()); // "findOne"
|
|
156
|
+
* }
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
match(method: RouteMethod, path: string): {
|
|
160
|
+
route: Route;
|
|
161
|
+
params: Record<string, string>;
|
|
162
|
+
wildcards: string[];
|
|
163
|
+
} | null;
|
|
164
|
+
/**
|
|
165
|
+
* Matches a URL path against a route pattern.
|
|
166
|
+
*
|
|
167
|
+
* This static method performs the actual pattern matching logic.
|
|
168
|
+
* It supports:
|
|
169
|
+
* - **Literal segments**: Must match exactly
|
|
170
|
+
* - **Path parameters**: `:param` captures a single segment
|
|
171
|
+
* - **Optional parameters**: `:param?` matches zero or one segment
|
|
172
|
+
* - **Wildcards**: `*` at the end captures all remaining segments
|
|
173
|
+
*
|
|
174
|
+
* @param pattern - The route pattern (e.g., "/users/:id")
|
|
175
|
+
* @param target - The actual URL path (e.g., "/users/123")
|
|
176
|
+
* @returns Object with params and wildcards if matched, null otherwise
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```ts
|
|
180
|
+
* // Basic parameter
|
|
181
|
+
* Router.match("/users/:id", "/users/123");
|
|
182
|
+
* // { params: { id: "123" }, wildcards: [] }
|
|
183
|
+
*
|
|
184
|
+
* // Optional parameter (present)
|
|
185
|
+
* Router.match("/posts/:id?", "/posts/456");
|
|
186
|
+
* // { params: { id: "456" }, wildcards: [] }
|
|
187
|
+
*
|
|
188
|
+
* // Optional parameter (absent)
|
|
189
|
+
* Router.match("/posts/:id?", "/posts");
|
|
190
|
+
* // { params: { id: "" }, wildcards: [] }
|
|
191
|
+
*
|
|
192
|
+
* // Wildcard
|
|
193
|
+
* Router.match("/files/*", "/files/docs/readme.md");
|
|
194
|
+
* // { params: {}, wildcards: ["docs", "readme.md"] }
|
|
195
|
+
*
|
|
196
|
+
* // No match
|
|
197
|
+
* Router.match("/users/:id", "/products/123");
|
|
198
|
+
* // null
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
201
|
+
static match(pattern: string, target: string): {
|
|
202
|
+
params: Record<string, string>;
|
|
203
|
+
wildcards: string[];
|
|
204
|
+
} | null;
|
|
205
|
+
}
|
package/dist/router.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";class t{constructor(t){this.registered=t}static register(...e){return new t(new Set(e.map(t=>({method:t.getMethod(),route:t}))))}match(e,r){const s=this.registered;for(const n of s){if(n.method!==e)continue;const s=t.match(n.route.getPath(),r);if(s)return{route:n.route,params:s.params,wildcards:s.wildcards}}return null}static match(t,e){const r=t.trim().replace(/^\/+/,"").replace(/\/+$/,""),s=e.trim().replace(/^\/+/,"").replace(/\/+$/,""),n=r.split("/"),i=s.split("/"),l={},c=[],o="*"===n[n.length-1],h=o?n.slice(0,-1):n;let a=0;for(const t of h)t.startsWith(":")&&t.endsWith("?")||a++;if(o){if(i.length<a)return null}else if(i.length<a||i.length>n.length)return null;let u=0;for(let t=0;t<h.length;t++){const e=h[t],r=i[u];if(e.startsWith(":")){let s=e.substring(1);const n=s.endsWith("?");if(n&&(s=s.slice(0,-1)),void 0!==r){if(n&&t+1<h.length){const e=h[t+1];if(!e.startsWith(":")&&e===r){l[s]="";continue}if(e.startsWith(":")){const e=i.length-u;let r=0;for(let e=t;e<h.length;e++){const t=h[e];t.startsWith(":")&&t.endsWith("?")||r++}if(e===r){l[s]="";continue}}}l[s]=r,u++}else{if(!n)return null;l[s]=""}}else{if(e!==r)return null;u++}}return o&&c.push(...i.slice(h.length)),{params:l,wildcards:c}}}exports.Router=t;
|
package/dist/router.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class t{constructor(t){this.registered=t}static register(...e){return new t(new Set(e.map(t=>({method:t.getMethod(),route:t}))))}match(e,r){const s=this.registered;for(const n of s){if(n.method!==e)continue;const s=t.match(n.route.getPath(),r);if(s)return{route:n.route,params:s.params,wildcards:s.wildcards}}return null}static match(t,e){const r=t.trim().replace(/^\/+/,"").replace(/\/+$/,""),s=e.trim().replace(/^\/+/,"").replace(/\/+$/,""),n=r.split("/"),i=s.split("/"),l={},c=[],o="*"===n[n.length-1],h=o?n.slice(0,-1):n;let a=0;for(const t of h)t.startsWith(":")&&t.endsWith("?")||a++;if(o){if(i.length<a)return null}else if(i.length<a||i.length>n.length)return null;let u=0;for(let t=0;t<h.length;t++){const e=h[t],r=i[u];if(e.startsWith(":")){let s=e.substring(1);const n=s.endsWith("?");if(n&&(s=s.slice(0,-1)),void 0!==r){if(n&&t+1<h.length){const e=h[t+1];if(!e.startsWith(":")&&e===r){l[s]="";continue}if(e.startsWith(":")){const e=i.length-u;let r=0;for(let e=t;e<h.length;e++){const t=h[e];t.startsWith(":")&&t.endsWith("?")||r++}if(e===r){l[s]="";continue}}}l[s]=r,u++}else{if(!n)return null;l[s]=""}}else{if(e!==r)return null;u++}}return o&&c.push(...i.slice(h.length)),{params:l,wildcards:c}}}export{t as Router};
|