clear-router 2.0.8 → 2.1.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/README.md +13 -19
- package/dist/Route-BJ9lF-Fj.cjs +53 -0
- package/dist/Route-DS_MAytb.d.cts +122 -0
- package/dist/Route-DcqlC_Bp.mjs +41 -0
- package/dist/Route-DsnulZob.d.mts +122 -0
- package/dist/express/index.cjs +37 -18
- package/dist/express/index.d.cts +4 -30
- package/dist/express/index.d.mts +4 -30
- package/dist/express/index.mjs +38 -18
- package/dist/h3/index.cjs +37 -17
- package/dist/h3/index.d.cts +4 -25
- package/dist/h3/index.d.mts +4 -25
- package/dist/h3/index.mjs +38 -17
- package/dist/src/ClearRequest.d.mts +21 -0
- package/dist/types/basic.d.mts +5 -1
- package/dist/types/express.d.mts +12 -1
- package/dist/types/h3.d.mts +13 -2
- package/package.json +8 -3
- package/dist/basic-BCxhZ1Wd.d.cts +0 -24
- package/dist/basic-POMY6a76.d.mts +0 -24
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Clear Router
|
|
2
2
|
|
|
3
|
-
Laravel-style routing system for Express.js
|
|
3
|
+
Laravel-style routing system for H3 and Express.js, with clean route definitions, middleware support, controller bindings and full TypeScript support.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -19,7 +19,7 @@ pnpm add clear-router h3
|
|
|
19
19
|
|
|
20
20
|
# OR
|
|
21
21
|
|
|
22
|
-
pnpm add clear-router
|
|
22
|
+
pnpm add clear-router express
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
OR
|
|
@@ -39,10 +39,13 @@ yarn add clear-router express
|
|
|
39
39
|
- Middleware stack: per-route and group-level
|
|
40
40
|
- Controller-method pair as route handler
|
|
41
41
|
- Supports HttpContext style handlers: { req, res, next }
|
|
42
|
+
- Function handlers always receive context as first argument
|
|
43
|
+
- Controller handlers receive hydrated `this.body`, `this.query`, `this.params`, and `this.clearRequest`
|
|
44
|
+
- `clearRequest` is passed as second handler argument for controller handlers
|
|
42
45
|
- Auto-binds controller methods
|
|
43
46
|
- Full CommonJS, ESM, and TypeScript support
|
|
44
|
-
- Error handling delegated to Express
|
|
45
|
-
- Route inspection with allRoutes method
|
|
47
|
+
- Error handling delegated to Express | H3
|
|
48
|
+
- Route inspection with the `allRoutes` method
|
|
46
49
|
- Fully Express-compatible
|
|
47
50
|
- Fully H3-compatible
|
|
48
51
|
|
|
@@ -60,20 +63,9 @@ See the [H3 documentation](./docs/H3.md) for details.
|
|
|
60
63
|
|
|
61
64
|
See [API.md](./docs/API.md) for complete API documentation.
|
|
62
65
|
|
|
63
|
-
## Error Handling
|
|
64
|
-
|
|
65
|
-
All errors during route execution are automatically passed to Express error handling middleware using `next(error)`. You can define your error handler:
|
|
66
|
-
|
|
67
|
-
```javascript
|
|
68
|
-
app.use((err, req, res, next) => {
|
|
69
|
-
console.error(err);
|
|
70
|
-
res.status(500).json({ error: err.message });
|
|
71
|
-
});
|
|
72
|
-
```
|
|
73
|
-
|
|
74
66
|
## Middleware Execution Order
|
|
75
67
|
|
|
76
|
-
```
|
|
68
|
+
```txt
|
|
77
69
|
[ Global Middleware ] → [ Group Middleware ] → [ Route Middleware ]
|
|
78
70
|
```
|
|
79
71
|
|
|
@@ -81,6 +73,8 @@ app.use((err, req, res, next) => {
|
|
|
81
73
|
|
|
82
74
|
- If function: executed directly
|
|
83
75
|
- If [Controller, 'method']: auto-instantiated (if needed), method is called
|
|
76
|
+
- First handler arg is always context (`{ req, res, next }` for Express, H3 event for H3)
|
|
77
|
+
- Second handler arg is `clearRequest` for controller handlers
|
|
84
78
|
|
|
85
79
|
## Testing
|
|
86
80
|
|
|
@@ -91,7 +85,7 @@ npm run test:esm # Test ESM
|
|
|
91
85
|
npm run test:ts # Test TypeScript
|
|
92
86
|
```
|
|
93
87
|
|
|
94
|
-
See [TESTING.md](./docs/TESTING.md) for detailed testing guide.
|
|
88
|
+
See [TESTING.md](./docs/TESTING.md) for a detailed testing guide.
|
|
95
89
|
|
|
96
90
|
## Examples
|
|
97
91
|
|
|
@@ -101,7 +95,7 @@ npm run example:esm # ESM example
|
|
|
101
95
|
npm run example:ts # TypeScript example
|
|
102
96
|
```
|
|
103
97
|
|
|
104
|
-
Check `example/` directory for full working demos.
|
|
98
|
+
Check the `example/` directory for full working demos.
|
|
105
99
|
|
|
106
100
|
## Changelog
|
|
107
101
|
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/ClearRequest.ts
|
|
3
|
+
var ClearRequest = class {
|
|
4
|
+
/**
|
|
5
|
+
* @param body - Parsed request body
|
|
6
|
+
*/
|
|
7
|
+
body;
|
|
8
|
+
/**
|
|
9
|
+
* @param query - Parsed query parameters
|
|
10
|
+
*/
|
|
11
|
+
query;
|
|
12
|
+
/**
|
|
13
|
+
* @param params - Parsed route parameters
|
|
14
|
+
*/
|
|
15
|
+
params;
|
|
16
|
+
constructor(init) {
|
|
17
|
+
Object.assign(this, init);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/Route.ts
|
|
23
|
+
var Route = class {
|
|
24
|
+
ctx;
|
|
25
|
+
body = {};
|
|
26
|
+
query = {};
|
|
27
|
+
params = {};
|
|
28
|
+
clearRequest;
|
|
29
|
+
methods;
|
|
30
|
+
path;
|
|
31
|
+
handler;
|
|
32
|
+
middlewares;
|
|
33
|
+
constructor(methods, path, handler, middlewares = []) {
|
|
34
|
+
this.methods = methods;
|
|
35
|
+
this.path = path;
|
|
36
|
+
this.handler = handler;
|
|
37
|
+
this.middlewares = middlewares;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
//#endregion
|
|
42
|
+
Object.defineProperty(exports, 'ClearRequest', {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
get: function () {
|
|
45
|
+
return ClearRequest;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(exports, 'Route', {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () {
|
|
51
|
+
return Route;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { NextFunction, Request, Response as Response$1 } from "express";
|
|
2
|
+
import { H3, H3Event, Middleware, TypedServerRequest } from "h3";
|
|
3
|
+
|
|
4
|
+
//#region types/basic.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Controller method reference
|
|
7
|
+
*/
|
|
8
|
+
type ControllerHandler = [any, string];
|
|
9
|
+
/**
|
|
10
|
+
* HTTP methods supported by the router
|
|
11
|
+
*/
|
|
12
|
+
type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options' | 'head';
|
|
13
|
+
/**
|
|
14
|
+
* Route information object
|
|
15
|
+
*/
|
|
16
|
+
interface RouteInfo {
|
|
17
|
+
methods: HttpMethod[];
|
|
18
|
+
path: string;
|
|
19
|
+
middlewareCount: number;
|
|
20
|
+
handlerType: 'function' | 'controller';
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Common controller action names
|
|
24
|
+
*/
|
|
25
|
+
type ControllerAction = 'index' | 'show' | 'create' | 'update' | 'destroy';
|
|
26
|
+
/**
|
|
27
|
+
* Generic Object type for request data
|
|
28
|
+
*/
|
|
29
|
+
type RequestData = Record<string, any>;
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/ClearRequest.d.ts
|
|
32
|
+
declare class ClearRequest {
|
|
33
|
+
[key: string]: any;
|
|
34
|
+
/**
|
|
35
|
+
* @param body - Parsed request body
|
|
36
|
+
*/
|
|
37
|
+
body: RequestData;
|
|
38
|
+
/**
|
|
39
|
+
* @param query - Parsed query parameters
|
|
40
|
+
*/
|
|
41
|
+
query: RequestData;
|
|
42
|
+
/**
|
|
43
|
+
* @param params - Parsed route parameters
|
|
44
|
+
*/
|
|
45
|
+
params: RequestData;
|
|
46
|
+
constructor(init?: Partial<ClearRequest>);
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region types/express.d.ts
|
|
50
|
+
/**
|
|
51
|
+
* HTTP context passed to route handlers
|
|
52
|
+
*/
|
|
53
|
+
interface HttpContext$1 {
|
|
54
|
+
req: Request;
|
|
55
|
+
res: Response$1;
|
|
56
|
+
next: NextFunction;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Route handler function type
|
|
60
|
+
*/
|
|
61
|
+
type RouteHandler$1 = (
|
|
62
|
+
/**
|
|
63
|
+
* Express context object containing req, res, and next
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
ctx: HttpContext$1,
|
|
67
|
+
/**
|
|
68
|
+
* ClearRequest instance
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
req: ClearRequest) => any | Promise<any>;
|
|
72
|
+
/**
|
|
73
|
+
* Handler can be either a function or controller reference
|
|
74
|
+
*/
|
|
75
|
+
type Handler$1 = RouteHandler$1 | ControllerHandler;
|
|
76
|
+
/**
|
|
77
|
+
* Middleware function type
|
|
78
|
+
*/
|
|
79
|
+
type Middleware$1 = (req: Request, res: Response$1, next: NextFunction) => any | Promise<any>;
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region types/h3.d.ts
|
|
82
|
+
type H3App = Omit<H3['fetch'], 'fetch'> & {
|
|
83
|
+
fetch: (request: TypedServerRequest) => Promise<Response>;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* HTTP context passed to route handlers
|
|
87
|
+
*/
|
|
88
|
+
type HttpContext = H3Event & {};
|
|
89
|
+
/**
|
|
90
|
+
* Route handler function type
|
|
91
|
+
*/
|
|
92
|
+
type RouteHandler = (
|
|
93
|
+
/**
|
|
94
|
+
* H3 event context
|
|
95
|
+
*/
|
|
96
|
+
|
|
97
|
+
ctx: HttpContext,
|
|
98
|
+
/**
|
|
99
|
+
* ClearRequest instance
|
|
100
|
+
*/
|
|
101
|
+
|
|
102
|
+
req: ClearRequest) => any | Promise<any>;
|
|
103
|
+
/**
|
|
104
|
+
* Handler can be either a function or controller reference
|
|
105
|
+
*/
|
|
106
|
+
type Handler = RouteHandler | ControllerHandler;
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region src/Route.d.ts
|
|
109
|
+
declare class Route<X = any, M = Middleware | Middleware$1> {
|
|
110
|
+
ctx: X;
|
|
111
|
+
body: RequestData;
|
|
112
|
+
query: RequestData;
|
|
113
|
+
params: RequestData;
|
|
114
|
+
clearRequest: ClearRequest;
|
|
115
|
+
methods: HttpMethod[];
|
|
116
|
+
path: string;
|
|
117
|
+
handler: Handler;
|
|
118
|
+
middlewares: M[];
|
|
119
|
+
constructor(methods: HttpMethod[], path: string, handler: Handler, middlewares?: M[]);
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
export { Middleware as a, Middleware$1 as c, RouteInfo as d, HttpContext as i, ControllerAction as l, H3App as n, Handler$1 as o, Handler as r, HttpContext$1 as s, Route as t, HttpMethod as u };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region src/ClearRequest.ts
|
|
2
|
+
var ClearRequest = class {
|
|
3
|
+
/**
|
|
4
|
+
* @param body - Parsed request body
|
|
5
|
+
*/
|
|
6
|
+
body;
|
|
7
|
+
/**
|
|
8
|
+
* @param query - Parsed query parameters
|
|
9
|
+
*/
|
|
10
|
+
query;
|
|
11
|
+
/**
|
|
12
|
+
* @param params - Parsed route parameters
|
|
13
|
+
*/
|
|
14
|
+
params;
|
|
15
|
+
constructor(init) {
|
|
16
|
+
Object.assign(this, init);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/Route.ts
|
|
22
|
+
var Route = class {
|
|
23
|
+
ctx;
|
|
24
|
+
body = {};
|
|
25
|
+
query = {};
|
|
26
|
+
params = {};
|
|
27
|
+
clearRequest;
|
|
28
|
+
methods;
|
|
29
|
+
path;
|
|
30
|
+
handler;
|
|
31
|
+
middlewares;
|
|
32
|
+
constructor(methods, path, handler, middlewares = []) {
|
|
33
|
+
this.methods = methods;
|
|
34
|
+
this.path = path;
|
|
35
|
+
this.handler = handler;
|
|
36
|
+
this.middlewares = middlewares;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
export { ClearRequest as n, Route as t };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { H3, H3Event, Middleware, TypedServerRequest } from "h3";
|
|
2
|
+
import { NextFunction, Request, Response as Response$1 } from "express";
|
|
3
|
+
|
|
4
|
+
//#region types/basic.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Controller method reference
|
|
7
|
+
*/
|
|
8
|
+
type ControllerHandler = [any, string];
|
|
9
|
+
/**
|
|
10
|
+
* HTTP methods supported by the router
|
|
11
|
+
*/
|
|
12
|
+
type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options' | 'head';
|
|
13
|
+
/**
|
|
14
|
+
* Route information object
|
|
15
|
+
*/
|
|
16
|
+
interface RouteInfo {
|
|
17
|
+
methods: HttpMethod[];
|
|
18
|
+
path: string;
|
|
19
|
+
middlewareCount: number;
|
|
20
|
+
handlerType: 'function' | 'controller';
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Common controller action names
|
|
24
|
+
*/
|
|
25
|
+
type ControllerAction = 'index' | 'show' | 'create' | 'update' | 'destroy';
|
|
26
|
+
/**
|
|
27
|
+
* Generic Object type for request data
|
|
28
|
+
*/
|
|
29
|
+
type RequestData = Record<string, any>;
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/ClearRequest.d.ts
|
|
32
|
+
declare class ClearRequest {
|
|
33
|
+
[key: string]: any;
|
|
34
|
+
/**
|
|
35
|
+
* @param body - Parsed request body
|
|
36
|
+
*/
|
|
37
|
+
body: RequestData;
|
|
38
|
+
/**
|
|
39
|
+
* @param query - Parsed query parameters
|
|
40
|
+
*/
|
|
41
|
+
query: RequestData;
|
|
42
|
+
/**
|
|
43
|
+
* @param params - Parsed route parameters
|
|
44
|
+
*/
|
|
45
|
+
params: RequestData;
|
|
46
|
+
constructor(init?: Partial<ClearRequest>);
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region types/express.d.ts
|
|
50
|
+
/**
|
|
51
|
+
* HTTP context passed to route handlers
|
|
52
|
+
*/
|
|
53
|
+
interface HttpContext$1 {
|
|
54
|
+
req: Request;
|
|
55
|
+
res: Response$1;
|
|
56
|
+
next: NextFunction;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Route handler function type
|
|
60
|
+
*/
|
|
61
|
+
type RouteHandler$1 = (
|
|
62
|
+
/**
|
|
63
|
+
* Express context object containing req, res, and next
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
ctx: HttpContext$1,
|
|
67
|
+
/**
|
|
68
|
+
* ClearRequest instance
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
req: ClearRequest) => any | Promise<any>;
|
|
72
|
+
/**
|
|
73
|
+
* Handler can be either a function or controller reference
|
|
74
|
+
*/
|
|
75
|
+
type Handler$1 = RouteHandler$1 | ControllerHandler;
|
|
76
|
+
/**
|
|
77
|
+
* Middleware function type
|
|
78
|
+
*/
|
|
79
|
+
type Middleware$1 = (req: Request, res: Response$1, next: NextFunction) => any | Promise<any>;
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region types/h3.d.ts
|
|
82
|
+
type H3App = Omit<H3['fetch'], 'fetch'> & {
|
|
83
|
+
fetch: (request: TypedServerRequest) => Promise<Response>;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* HTTP context passed to route handlers
|
|
87
|
+
*/
|
|
88
|
+
type HttpContext = H3Event & {};
|
|
89
|
+
/**
|
|
90
|
+
* Route handler function type
|
|
91
|
+
*/
|
|
92
|
+
type RouteHandler = (
|
|
93
|
+
/**
|
|
94
|
+
* H3 event context
|
|
95
|
+
*/
|
|
96
|
+
|
|
97
|
+
ctx: HttpContext,
|
|
98
|
+
/**
|
|
99
|
+
* ClearRequest instance
|
|
100
|
+
*/
|
|
101
|
+
|
|
102
|
+
req: ClearRequest) => any | Promise<any>;
|
|
103
|
+
/**
|
|
104
|
+
* Handler can be either a function or controller reference
|
|
105
|
+
*/
|
|
106
|
+
type Handler = RouteHandler | ControllerHandler;
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region src/Route.d.ts
|
|
109
|
+
declare class Route<X = any, M = Middleware | Middleware$1> {
|
|
110
|
+
ctx: X;
|
|
111
|
+
body: RequestData;
|
|
112
|
+
query: RequestData;
|
|
113
|
+
params: RequestData;
|
|
114
|
+
clearRequest: ClearRequest;
|
|
115
|
+
methods: HttpMethod[];
|
|
116
|
+
path: string;
|
|
117
|
+
handler: Handler;
|
|
118
|
+
middlewares: M[];
|
|
119
|
+
constructor(methods: HttpMethod[], path: string, handler: Handler, middlewares?: M[]);
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
export { Middleware as a, Middleware$1 as c, RouteInfo as d, HttpContext as i, ControllerAction as l, H3App as n, Handler$1 as o, Handler as r, HttpContext$1 as s, Route as t, HttpMethod as u };
|
package/dist/express/index.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_Route = require('../Route-BJ9lF-Fj.cjs');
|
|
2
3
|
|
|
3
4
|
//#region src/express/router.ts
|
|
4
5
|
/**
|
|
@@ -8,7 +9,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
8
9
|
* @author 3m1n3nc3
|
|
9
10
|
* @repository https://github.com/toneflix/clear-router
|
|
10
11
|
*/
|
|
11
|
-
var Router = class {
|
|
12
|
+
var Router = class Router {
|
|
12
13
|
/**
|
|
13
14
|
* All registered routes
|
|
14
15
|
*/
|
|
@@ -43,16 +44,11 @@ var Router = class {
|
|
|
43
44
|
static add(methods, path, handler, middlewares) {
|
|
44
45
|
const methodArray = Array.isArray(methods) ? methods : [methods];
|
|
45
46
|
const fullPath = this.normalizePath(`${this.prefix}/${path}`);
|
|
46
|
-
this.routes.push(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
...this.globalMiddlewares,
|
|
52
|
-
...this.groupMiddlewares,
|
|
53
|
-
...middlewares || []
|
|
54
|
-
]
|
|
55
|
-
});
|
|
47
|
+
this.routes.push(new require_Route.Route(methodArray, fullPath, handler, [
|
|
48
|
+
...this.globalMiddlewares,
|
|
49
|
+
...this.groupMiddlewares,
|
|
50
|
+
...middlewares || []
|
|
51
|
+
]));
|
|
56
52
|
}
|
|
57
53
|
/**
|
|
58
54
|
* Register RESTful API resource routes for a controller with optional action filtering
|
|
@@ -200,13 +196,20 @@ var Router = class {
|
|
|
200
196
|
static async apply(router) {
|
|
201
197
|
for (const route of this.routes) {
|
|
202
198
|
let handlerFunction = null;
|
|
199
|
+
let instance = null;
|
|
203
200
|
try {
|
|
204
|
-
if (typeof route.handler === "function")
|
|
201
|
+
if (typeof route.handler === "function")
|
|
202
|
+
/**
|
|
203
|
+
* Since we do not have a controller instance, we will call the handler function directly and the route instance will be the this argument. This allows for both controller-based and function-based handlers to work seamlessly.
|
|
204
|
+
*/
|
|
205
|
+
handlerFunction = route.handler.bind(route);
|
|
205
206
|
else if (Array.isArray(route.handler) && route.handler.length === 2) {
|
|
206
207
|
const [Controller, method] = route.handler;
|
|
207
|
-
if (typeof Controller
|
|
208
|
-
|
|
209
|
-
|
|
208
|
+
if (["function", "object"].includes(typeof Controller) && typeof Controller[method] === "function") {
|
|
209
|
+
instance = Controller;
|
|
210
|
+
handlerFunction = Controller[method].bind(Controller);
|
|
211
|
+
} else if (typeof Controller === "function") {
|
|
212
|
+
instance = new Controller();
|
|
210
213
|
if (typeof instance[method] === "function") handlerFunction = instance[method].bind(instance);
|
|
211
214
|
else throw new Error(`Method "${method}" not found in controller instance "${Controller.name}"`);
|
|
212
215
|
} else throw new Error(`Invalid controller type for route: ${route.path}`);
|
|
@@ -227,16 +230,19 @@ var Router = class {
|
|
|
227
230
|
"head"
|
|
228
231
|
].includes(method)) {
|
|
229
232
|
const error = /* @__PURE__ */ new Error(`Invalid HTTP method: ${method} for route: ${route.path}`);
|
|
230
|
-
console.error(
|
|
233
|
+
console.error("[ROUTES]", error.message);
|
|
231
234
|
throw error;
|
|
232
235
|
}
|
|
233
236
|
router[method](route.path, ...route.middlewares || [], async (req, res, next) => {
|
|
234
237
|
try {
|
|
235
|
-
const
|
|
238
|
+
const ctx = {
|
|
236
239
|
req,
|
|
237
240
|
res,
|
|
238
241
|
next
|
|
239
|
-
}
|
|
242
|
+
};
|
|
243
|
+
const inst = instance ?? route;
|
|
244
|
+
await Router.bindRequestToInstance(ctx, inst);
|
|
245
|
+
const result = handlerFunction(ctx, inst.clearRequest);
|
|
240
246
|
await Promise.resolve(result);
|
|
241
247
|
} catch (error) {
|
|
242
248
|
next(error);
|
|
@@ -245,6 +251,19 @@ var Router = class {
|
|
|
245
251
|
}
|
|
246
252
|
}
|
|
247
253
|
}
|
|
254
|
+
static async bindRequestToInstance(ctx, instance) {
|
|
255
|
+
if (!instance) return;
|
|
256
|
+
instance.ctx = ctx;
|
|
257
|
+
instance.body = ctx.req.body;
|
|
258
|
+
instance.query = ctx.req.query;
|
|
259
|
+
instance.params = ctx.req.params;
|
|
260
|
+
instance.clearRequest = new require_Route.ClearRequest({
|
|
261
|
+
ctx,
|
|
262
|
+
body: instance.body,
|
|
263
|
+
query: instance.query,
|
|
264
|
+
params: instance.params
|
|
265
|
+
});
|
|
266
|
+
}
|
|
248
267
|
};
|
|
249
268
|
|
|
250
269
|
//#endregion
|
package/dist/express/index.d.cts
CHANGED
|
@@ -1,28 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { c as Middleware, d as RouteInfo, l as ControllerAction, o as Handler, s as HttpContext, t as Route, u as HttpMethod } from "../Route-DS_MAytb.cjs";
|
|
2
|
+
import { Router as Router$1 } from "express";
|
|
3
3
|
|
|
4
|
-
//#region types/express.d.ts
|
|
5
|
-
/**
|
|
6
|
-
* HTTP context passed to route handlers
|
|
7
|
-
*/
|
|
8
|
-
interface HttpContext {
|
|
9
|
-
req: Request;
|
|
10
|
-
res: Response;
|
|
11
|
-
next: NextFunction;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Route handler function type
|
|
15
|
-
*/
|
|
16
|
-
type RouteHandler = (ctx: HttpContext) => any | Promise<any>;
|
|
17
|
-
/**
|
|
18
|
-
* Handler can be either a function or controller reference
|
|
19
|
-
*/
|
|
20
|
-
type Handler = RouteHandler | ControllerHandler;
|
|
21
|
-
/**
|
|
22
|
-
* Middleware function type
|
|
23
|
-
*/
|
|
24
|
-
type Middleware = (req: Request, res: Response, next: NextFunction) => any | Promise<any>;
|
|
25
|
-
//#endregion
|
|
26
4
|
//#region src/express/router.d.ts
|
|
27
5
|
/**
|
|
28
6
|
* @class clear-router
|
|
@@ -35,12 +13,7 @@ declare class Router {
|
|
|
35
13
|
/**
|
|
36
14
|
* All registered routes
|
|
37
15
|
*/
|
|
38
|
-
static routes: Array<
|
|
39
|
-
methods: HttpMethod[];
|
|
40
|
-
path: string;
|
|
41
|
-
handler: Handler;
|
|
42
|
-
middlewares: Middleware[];
|
|
43
|
-
}>;
|
|
16
|
+
static routes: Array<Route<HttpContext, Middleware>>;
|
|
44
17
|
/**
|
|
45
18
|
* Current route prefix
|
|
46
19
|
*/
|
|
@@ -154,6 +127,7 @@ declare class Router {
|
|
|
154
127
|
*/
|
|
155
128
|
static apply(router: Router$1): void;
|
|
156
129
|
static apply(router: Router$1): Promise<void>;
|
|
130
|
+
private static bindRequestToInstance;
|
|
157
131
|
}
|
|
158
132
|
//#endregion
|
|
159
133
|
export { Router };
|
package/dist/express/index.d.mts
CHANGED
|
@@ -1,28 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { c as Middleware, d as RouteInfo, l as ControllerAction, o as Handler, s as HttpContext, t as Route, u as HttpMethod } from "../Route-DsnulZob.mjs";
|
|
2
|
+
import { Router as Router$1 } from "express";
|
|
3
3
|
|
|
4
|
-
//#region types/express.d.ts
|
|
5
|
-
/**
|
|
6
|
-
* HTTP context passed to route handlers
|
|
7
|
-
*/
|
|
8
|
-
interface HttpContext {
|
|
9
|
-
req: Request;
|
|
10
|
-
res: Response;
|
|
11
|
-
next: NextFunction;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Route handler function type
|
|
15
|
-
*/
|
|
16
|
-
type RouteHandler = (ctx: HttpContext) => any | Promise<any>;
|
|
17
|
-
/**
|
|
18
|
-
* Handler can be either a function or controller reference
|
|
19
|
-
*/
|
|
20
|
-
type Handler = RouteHandler | ControllerHandler;
|
|
21
|
-
/**
|
|
22
|
-
* Middleware function type
|
|
23
|
-
*/
|
|
24
|
-
type Middleware = (req: Request, res: Response, next: NextFunction) => any | Promise<any>;
|
|
25
|
-
//#endregion
|
|
26
4
|
//#region src/express/router.d.ts
|
|
27
5
|
/**
|
|
28
6
|
* @class clear-router
|
|
@@ -35,12 +13,7 @@ declare class Router {
|
|
|
35
13
|
/**
|
|
36
14
|
* All registered routes
|
|
37
15
|
*/
|
|
38
|
-
static routes: Array<
|
|
39
|
-
methods: HttpMethod[];
|
|
40
|
-
path: string;
|
|
41
|
-
handler: Handler;
|
|
42
|
-
middlewares: Middleware[];
|
|
43
|
-
}>;
|
|
16
|
+
static routes: Array<Route<HttpContext, Middleware>>;
|
|
44
17
|
/**
|
|
45
18
|
* Current route prefix
|
|
46
19
|
*/
|
|
@@ -154,6 +127,7 @@ declare class Router {
|
|
|
154
127
|
*/
|
|
155
128
|
static apply(router: Router$1): void;
|
|
156
129
|
static apply(router: Router$1): Promise<void>;
|
|
130
|
+
private static bindRequestToInstance;
|
|
157
131
|
}
|
|
158
132
|
//#endregion
|
|
159
133
|
export { Router };
|
package/dist/express/index.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { n as ClearRequest, t as Route } from "../Route-DcqlC_Bp.mjs";
|
|
2
|
+
|
|
1
3
|
//#region src/express/router.ts
|
|
2
4
|
/**
|
|
3
5
|
* @class clear-router
|
|
@@ -6,7 +8,7 @@
|
|
|
6
8
|
* @author 3m1n3nc3
|
|
7
9
|
* @repository https://github.com/toneflix/clear-router
|
|
8
10
|
*/
|
|
9
|
-
var Router = class {
|
|
11
|
+
var Router = class Router {
|
|
10
12
|
/**
|
|
11
13
|
* All registered routes
|
|
12
14
|
*/
|
|
@@ -41,16 +43,11 @@ var Router = class {
|
|
|
41
43
|
static add(methods, path, handler, middlewares) {
|
|
42
44
|
const methodArray = Array.isArray(methods) ? methods : [methods];
|
|
43
45
|
const fullPath = this.normalizePath(`${this.prefix}/${path}`);
|
|
44
|
-
this.routes.push(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
...this.globalMiddlewares,
|
|
50
|
-
...this.groupMiddlewares,
|
|
51
|
-
...middlewares || []
|
|
52
|
-
]
|
|
53
|
-
});
|
|
46
|
+
this.routes.push(new Route(methodArray, fullPath, handler, [
|
|
47
|
+
...this.globalMiddlewares,
|
|
48
|
+
...this.groupMiddlewares,
|
|
49
|
+
...middlewares || []
|
|
50
|
+
]));
|
|
54
51
|
}
|
|
55
52
|
/**
|
|
56
53
|
* Register RESTful API resource routes for a controller with optional action filtering
|
|
@@ -198,13 +195,20 @@ var Router = class {
|
|
|
198
195
|
static async apply(router) {
|
|
199
196
|
for (const route of this.routes) {
|
|
200
197
|
let handlerFunction = null;
|
|
198
|
+
let instance = null;
|
|
201
199
|
try {
|
|
202
|
-
if (typeof route.handler === "function")
|
|
200
|
+
if (typeof route.handler === "function")
|
|
201
|
+
/**
|
|
202
|
+
* Since we do not have a controller instance, we will call the handler function directly and the route instance will be the this argument. This allows for both controller-based and function-based handlers to work seamlessly.
|
|
203
|
+
*/
|
|
204
|
+
handlerFunction = route.handler.bind(route);
|
|
203
205
|
else if (Array.isArray(route.handler) && route.handler.length === 2) {
|
|
204
206
|
const [Controller, method] = route.handler;
|
|
205
|
-
if (typeof Controller
|
|
206
|
-
|
|
207
|
-
|
|
207
|
+
if (["function", "object"].includes(typeof Controller) && typeof Controller[method] === "function") {
|
|
208
|
+
instance = Controller;
|
|
209
|
+
handlerFunction = Controller[method].bind(Controller);
|
|
210
|
+
} else if (typeof Controller === "function") {
|
|
211
|
+
instance = new Controller();
|
|
208
212
|
if (typeof instance[method] === "function") handlerFunction = instance[method].bind(instance);
|
|
209
213
|
else throw new Error(`Method "${method}" not found in controller instance "${Controller.name}"`);
|
|
210
214
|
} else throw new Error(`Invalid controller type for route: ${route.path}`);
|
|
@@ -225,16 +229,19 @@ var Router = class {
|
|
|
225
229
|
"head"
|
|
226
230
|
].includes(method)) {
|
|
227
231
|
const error = /* @__PURE__ */ new Error(`Invalid HTTP method: ${method} for route: ${route.path}`);
|
|
228
|
-
console.error(
|
|
232
|
+
console.error("[ROUTES]", error.message);
|
|
229
233
|
throw error;
|
|
230
234
|
}
|
|
231
235
|
router[method](route.path, ...route.middlewares || [], async (req, res, next) => {
|
|
232
236
|
try {
|
|
233
|
-
const
|
|
237
|
+
const ctx = {
|
|
234
238
|
req,
|
|
235
239
|
res,
|
|
236
240
|
next
|
|
237
|
-
}
|
|
241
|
+
};
|
|
242
|
+
const inst = instance ?? route;
|
|
243
|
+
await Router.bindRequestToInstance(ctx, inst);
|
|
244
|
+
const result = handlerFunction(ctx, inst.clearRequest);
|
|
238
245
|
await Promise.resolve(result);
|
|
239
246
|
} catch (error) {
|
|
240
247
|
next(error);
|
|
@@ -243,6 +250,19 @@ var Router = class {
|
|
|
243
250
|
}
|
|
244
251
|
}
|
|
245
252
|
}
|
|
253
|
+
static async bindRequestToInstance(ctx, instance) {
|
|
254
|
+
if (!instance) return;
|
|
255
|
+
instance.ctx = ctx;
|
|
256
|
+
instance.body = ctx.req.body;
|
|
257
|
+
instance.query = ctx.req.query;
|
|
258
|
+
instance.params = ctx.req.params;
|
|
259
|
+
instance.clearRequest = new ClearRequest({
|
|
260
|
+
ctx,
|
|
261
|
+
body: instance.body,
|
|
262
|
+
query: instance.query,
|
|
263
|
+
params: instance.params
|
|
264
|
+
});
|
|
265
|
+
}
|
|
246
266
|
};
|
|
247
267
|
|
|
248
268
|
//#endregion
|
package/dist/h3/index.cjs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_Route = require('../Route-BJ9lF-Fj.cjs');
|
|
3
|
+
let h3 = require("h3");
|
|
2
4
|
|
|
3
5
|
//#region src/h3/router.ts
|
|
4
6
|
/**
|
|
@@ -7,7 +9,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
7
9
|
* @author 3m1n3nc3
|
|
8
10
|
* @repository https://github.com/toneflix/clear-router
|
|
9
11
|
*/
|
|
10
|
-
var Router = class {
|
|
12
|
+
var Router = class Router {
|
|
11
13
|
/**
|
|
12
14
|
* All registered routes
|
|
13
15
|
*/
|
|
@@ -42,16 +44,11 @@ var Router = class {
|
|
|
42
44
|
static add(methods, path, handler, middlewares) {
|
|
43
45
|
const methodArray = Array.isArray(methods) ? methods : [methods];
|
|
44
46
|
const fullPath = this.normalizePath(`${this.prefix}/${path}`);
|
|
45
|
-
this.routes.push(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
...this.globalMiddlewares,
|
|
51
|
-
...this.groupMiddlewares,
|
|
52
|
-
...middlewares || []
|
|
53
|
-
]
|
|
54
|
-
});
|
|
47
|
+
this.routes.push(new require_Route.Route(methodArray, fullPath, handler, [
|
|
48
|
+
...this.globalMiddlewares,
|
|
49
|
+
...this.groupMiddlewares,
|
|
50
|
+
...middlewares || []
|
|
51
|
+
]));
|
|
55
52
|
}
|
|
56
53
|
/**
|
|
57
54
|
* Register RESTful API resource routes for a controller with optional action filtering
|
|
@@ -206,13 +203,20 @@ var Router = class {
|
|
|
206
203
|
static apply(app) {
|
|
207
204
|
for (const route of this.routes) {
|
|
208
205
|
let handlerFunction = null;
|
|
206
|
+
let instance = null;
|
|
209
207
|
try {
|
|
210
|
-
if (typeof route.handler === "function")
|
|
208
|
+
if (typeof route.handler === "function")
|
|
209
|
+
/**
|
|
210
|
+
* Since we do not have a controller instance, we will call the handler function directly and the route instance will be the this argument. This allows for both controller-based and function-based handlers to work seamlessly.
|
|
211
|
+
*/
|
|
212
|
+
handlerFunction = route.handler.bind(route);
|
|
211
213
|
else if (Array.isArray(route.handler) && route.handler.length === 2) {
|
|
212
214
|
const [Controller, method] = route.handler;
|
|
213
|
-
if (typeof Controller
|
|
214
|
-
|
|
215
|
-
|
|
215
|
+
if (["function", "object"].includes(typeof Controller) && typeof Controller[method] === "function") {
|
|
216
|
+
instance = Controller;
|
|
217
|
+
handlerFunction = Controller[method].bind(Controller);
|
|
218
|
+
} else if (typeof Controller === "function") {
|
|
219
|
+
instance = new Controller();
|
|
216
220
|
if (typeof instance[method] === "function") handlerFunction = instance[method].bind(instance);
|
|
217
221
|
else throw new Error(`Method "${method}" not found in controller instance "${Controller.name}"`);
|
|
218
222
|
} else throw new Error(`Invalid controller type for route: ${route.path}`);
|
|
@@ -233,12 +237,15 @@ var Router = class {
|
|
|
233
237
|
"head"
|
|
234
238
|
].includes(method)) {
|
|
235
239
|
const error = /* @__PURE__ */ new Error(`Invalid HTTP method: ${method} for route: ${route.path}`);
|
|
236
|
-
console.error(
|
|
240
|
+
console.error("[ROUTES]", error.message);
|
|
237
241
|
throw error;
|
|
238
242
|
}
|
|
239
243
|
app[method](route.path, async (event) => {
|
|
240
244
|
try {
|
|
241
|
-
const
|
|
245
|
+
const ctx = event;
|
|
246
|
+
const inst = instance ?? route;
|
|
247
|
+
await Router.bindRequestToInstance(ctx, inst);
|
|
248
|
+
const result = handlerFunction(ctx, inst.clearRequest);
|
|
242
249
|
return await Promise.resolve(result);
|
|
243
250
|
} catch (error) {
|
|
244
251
|
return error;
|
|
@@ -248,6 +255,19 @@ var Router = class {
|
|
|
248
255
|
}
|
|
249
256
|
return app;
|
|
250
257
|
}
|
|
258
|
+
static async bindRequestToInstance(ctx, instance) {
|
|
259
|
+
if (!instance) return;
|
|
260
|
+
instance.ctx = ctx;
|
|
261
|
+
instance.body = await (0, h3.readBody)(ctx) ?? {};
|
|
262
|
+
instance.query = (0, h3.getQuery)(ctx);
|
|
263
|
+
instance.params = (0, h3.getRouterParams)(ctx, { decode: true });
|
|
264
|
+
instance.clearRequest = new require_Route.ClearRequest({
|
|
265
|
+
ctx,
|
|
266
|
+
body: instance.body,
|
|
267
|
+
query: instance.query,
|
|
268
|
+
params: instance.params
|
|
269
|
+
});
|
|
270
|
+
}
|
|
251
271
|
};
|
|
252
272
|
|
|
253
273
|
//#endregion
|
package/dist/h3/index.d.cts
CHANGED
|
@@ -1,23 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { H3
|
|
1
|
+
import { a as Middleware, d as RouteInfo, i as HttpContext, l as ControllerAction, n as H3App, r as Handler, t as Route, u as HttpMethod } from "../Route-DS_MAytb.cjs";
|
|
2
|
+
import { H3 } from "h3";
|
|
3
3
|
|
|
4
|
-
//#region types/h3.d.ts
|
|
5
|
-
type H3App = Omit<H3['fetch'], 'fetch'> & {
|
|
6
|
-
fetch: (request: TypedServerRequest) => Promise<Response>;
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* HTTP context passed to route handlers
|
|
10
|
-
*/
|
|
11
|
-
interface HttpContext extends H3Event {}
|
|
12
|
-
/**
|
|
13
|
-
* Route handler function type
|
|
14
|
-
*/
|
|
15
|
-
type RouteHandler = (ctx: HttpContext) => any | Promise<any>;
|
|
16
|
-
/**
|
|
17
|
-
* Handler can be either a function or controller reference
|
|
18
|
-
*/
|
|
19
|
-
type Handler = RouteHandler | ControllerHandler;
|
|
20
|
-
//#endregion
|
|
21
4
|
//#region src/h3/router.d.ts
|
|
22
5
|
/**
|
|
23
6
|
* @class clear-router
|
|
@@ -29,12 +12,7 @@ declare class Router {
|
|
|
29
12
|
/**
|
|
30
13
|
* All registered routes
|
|
31
14
|
*/
|
|
32
|
-
static routes: Array<
|
|
33
|
-
methods: HttpMethod[];
|
|
34
|
-
path: string;
|
|
35
|
-
handler: Handler;
|
|
36
|
-
middlewares: Middleware[];
|
|
37
|
-
}>;
|
|
15
|
+
static routes: Array<Route<HttpContext, Middleware>>;
|
|
38
16
|
/**
|
|
39
17
|
* Current route prefix
|
|
40
18
|
*/
|
|
@@ -147,6 +125,7 @@ declare class Router {
|
|
|
147
125
|
* @param app - H3 app instance
|
|
148
126
|
*/
|
|
149
127
|
static apply(app: H3): H3App;
|
|
128
|
+
private static bindRequestToInstance;
|
|
150
129
|
}
|
|
151
130
|
//#endregion
|
|
152
131
|
export { Router };
|
package/dist/h3/index.d.mts
CHANGED
|
@@ -1,23 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { H3
|
|
1
|
+
import { a as Middleware, d as RouteInfo, i as HttpContext, l as ControllerAction, n as H3App, r as Handler, t as Route, u as HttpMethod } from "../Route-DsnulZob.mjs";
|
|
2
|
+
import { H3 } from "h3";
|
|
3
3
|
|
|
4
|
-
//#region types/h3.d.ts
|
|
5
|
-
type H3App = Omit<H3['fetch'], 'fetch'> & {
|
|
6
|
-
fetch: (request: TypedServerRequest) => Promise<Response>;
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* HTTP context passed to route handlers
|
|
10
|
-
*/
|
|
11
|
-
interface HttpContext extends H3Event {}
|
|
12
|
-
/**
|
|
13
|
-
* Route handler function type
|
|
14
|
-
*/
|
|
15
|
-
type RouteHandler = (ctx: HttpContext) => any | Promise<any>;
|
|
16
|
-
/**
|
|
17
|
-
* Handler can be either a function or controller reference
|
|
18
|
-
*/
|
|
19
|
-
type Handler = RouteHandler | ControllerHandler;
|
|
20
|
-
//#endregion
|
|
21
4
|
//#region src/h3/router.d.ts
|
|
22
5
|
/**
|
|
23
6
|
* @class clear-router
|
|
@@ -29,12 +12,7 @@ declare class Router {
|
|
|
29
12
|
/**
|
|
30
13
|
* All registered routes
|
|
31
14
|
*/
|
|
32
|
-
static routes: Array<
|
|
33
|
-
methods: HttpMethod[];
|
|
34
|
-
path: string;
|
|
35
|
-
handler: Handler;
|
|
36
|
-
middlewares: Middleware[];
|
|
37
|
-
}>;
|
|
15
|
+
static routes: Array<Route<HttpContext, Middleware>>;
|
|
38
16
|
/**
|
|
39
17
|
* Current route prefix
|
|
40
18
|
*/
|
|
@@ -147,6 +125,7 @@ declare class Router {
|
|
|
147
125
|
* @param app - H3 app instance
|
|
148
126
|
*/
|
|
149
127
|
static apply(app: H3): H3App;
|
|
128
|
+
private static bindRequestToInstance;
|
|
150
129
|
}
|
|
151
130
|
//#endregion
|
|
152
131
|
export { Router };
|
package/dist/h3/index.mjs
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { n as ClearRequest, t as Route } from "../Route-DcqlC_Bp.mjs";
|
|
2
|
+
import { getQuery, getRouterParams, readBody } from "h3";
|
|
3
|
+
|
|
1
4
|
//#region src/h3/router.ts
|
|
2
5
|
/**
|
|
3
6
|
* @class clear-router
|
|
@@ -5,7 +8,7 @@
|
|
|
5
8
|
* @author 3m1n3nc3
|
|
6
9
|
* @repository https://github.com/toneflix/clear-router
|
|
7
10
|
*/
|
|
8
|
-
var Router = class {
|
|
11
|
+
var Router = class Router {
|
|
9
12
|
/**
|
|
10
13
|
* All registered routes
|
|
11
14
|
*/
|
|
@@ -40,16 +43,11 @@ var Router = class {
|
|
|
40
43
|
static add(methods, path, handler, middlewares) {
|
|
41
44
|
const methodArray = Array.isArray(methods) ? methods : [methods];
|
|
42
45
|
const fullPath = this.normalizePath(`${this.prefix}/${path}`);
|
|
43
|
-
this.routes.push(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
...this.globalMiddlewares,
|
|
49
|
-
...this.groupMiddlewares,
|
|
50
|
-
...middlewares || []
|
|
51
|
-
]
|
|
52
|
-
});
|
|
46
|
+
this.routes.push(new Route(methodArray, fullPath, handler, [
|
|
47
|
+
...this.globalMiddlewares,
|
|
48
|
+
...this.groupMiddlewares,
|
|
49
|
+
...middlewares || []
|
|
50
|
+
]));
|
|
53
51
|
}
|
|
54
52
|
/**
|
|
55
53
|
* Register RESTful API resource routes for a controller with optional action filtering
|
|
@@ -204,13 +202,20 @@ var Router = class {
|
|
|
204
202
|
static apply(app) {
|
|
205
203
|
for (const route of this.routes) {
|
|
206
204
|
let handlerFunction = null;
|
|
205
|
+
let instance = null;
|
|
207
206
|
try {
|
|
208
|
-
if (typeof route.handler === "function")
|
|
207
|
+
if (typeof route.handler === "function")
|
|
208
|
+
/**
|
|
209
|
+
* Since we do not have a controller instance, we will call the handler function directly and the route instance will be the this argument. This allows for both controller-based and function-based handlers to work seamlessly.
|
|
210
|
+
*/
|
|
211
|
+
handlerFunction = route.handler.bind(route);
|
|
209
212
|
else if (Array.isArray(route.handler) && route.handler.length === 2) {
|
|
210
213
|
const [Controller, method] = route.handler;
|
|
211
|
-
if (typeof Controller
|
|
212
|
-
|
|
213
|
-
|
|
214
|
+
if (["function", "object"].includes(typeof Controller) && typeof Controller[method] === "function") {
|
|
215
|
+
instance = Controller;
|
|
216
|
+
handlerFunction = Controller[method].bind(Controller);
|
|
217
|
+
} else if (typeof Controller === "function") {
|
|
218
|
+
instance = new Controller();
|
|
214
219
|
if (typeof instance[method] === "function") handlerFunction = instance[method].bind(instance);
|
|
215
220
|
else throw new Error(`Method "${method}" not found in controller instance "${Controller.name}"`);
|
|
216
221
|
} else throw new Error(`Invalid controller type for route: ${route.path}`);
|
|
@@ -231,12 +236,15 @@ var Router = class {
|
|
|
231
236
|
"head"
|
|
232
237
|
].includes(method)) {
|
|
233
238
|
const error = /* @__PURE__ */ new Error(`Invalid HTTP method: ${method} for route: ${route.path}`);
|
|
234
|
-
console.error(
|
|
239
|
+
console.error("[ROUTES]", error.message);
|
|
235
240
|
throw error;
|
|
236
241
|
}
|
|
237
242
|
app[method](route.path, async (event) => {
|
|
238
243
|
try {
|
|
239
|
-
const
|
|
244
|
+
const ctx = event;
|
|
245
|
+
const inst = instance ?? route;
|
|
246
|
+
await Router.bindRequestToInstance(ctx, inst);
|
|
247
|
+
const result = handlerFunction(ctx, inst.clearRequest);
|
|
240
248
|
return await Promise.resolve(result);
|
|
241
249
|
} catch (error) {
|
|
242
250
|
return error;
|
|
@@ -246,6 +254,19 @@ var Router = class {
|
|
|
246
254
|
}
|
|
247
255
|
return app;
|
|
248
256
|
}
|
|
257
|
+
static async bindRequestToInstance(ctx, instance) {
|
|
258
|
+
if (!instance) return;
|
|
259
|
+
instance.ctx = ctx;
|
|
260
|
+
instance.body = await readBody(ctx) ?? {};
|
|
261
|
+
instance.query = getQuery(ctx);
|
|
262
|
+
instance.params = getRouterParams(ctx, { decode: true });
|
|
263
|
+
instance.clearRequest = new ClearRequest({
|
|
264
|
+
ctx,
|
|
265
|
+
body: instance.body,
|
|
266
|
+
query: instance.query,
|
|
267
|
+
params: instance.params
|
|
268
|
+
});
|
|
269
|
+
}
|
|
249
270
|
};
|
|
250
271
|
|
|
251
272
|
//#endregion
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { RequestData } from "../types/basic.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/ClearRequest.d.ts
|
|
4
|
+
declare class ClearRequest {
|
|
5
|
+
[key: string]: any;
|
|
6
|
+
/**
|
|
7
|
+
* @param body - Parsed request body
|
|
8
|
+
*/
|
|
9
|
+
body: RequestData;
|
|
10
|
+
/**
|
|
11
|
+
* @param query - Parsed query parameters
|
|
12
|
+
*/
|
|
13
|
+
query: RequestData;
|
|
14
|
+
/**
|
|
15
|
+
* @param params - Parsed route parameters
|
|
16
|
+
*/
|
|
17
|
+
params: RequestData;
|
|
18
|
+
constructor(init?: Partial<ClearRequest>);
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { ClearRequest };
|
package/dist/types/basic.d.mts
CHANGED
|
@@ -20,5 +20,9 @@ interface RouteInfo {
|
|
|
20
20
|
* Common controller action names
|
|
21
21
|
*/
|
|
22
22
|
type ControllerAction = 'index' | 'show' | 'create' | 'update' | 'destroy';
|
|
23
|
+
/**
|
|
24
|
+
* Generic Object type for request data
|
|
25
|
+
*/
|
|
26
|
+
type RequestData = Record<string, any>;
|
|
23
27
|
//#endregion
|
|
24
|
-
export { ControllerAction, ControllerHandler, HttpMethod, RouteInfo };
|
|
28
|
+
export { ControllerAction, ControllerHandler, HttpMethod, RequestData, RouteInfo };
|
package/dist/types/express.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ControllerHandler } from "./basic.mjs";
|
|
2
|
+
import { ClearRequest } from "../src/ClearRequest.mjs";
|
|
2
3
|
import { NextFunction, Request, Response } from "express";
|
|
3
4
|
|
|
4
5
|
//#region types/express.d.ts
|
|
@@ -13,7 +14,17 @@ interface HttpContext {
|
|
|
13
14
|
/**
|
|
14
15
|
* Route handler function type
|
|
15
16
|
*/
|
|
16
|
-
type RouteHandler = (
|
|
17
|
+
type RouteHandler = (
|
|
18
|
+
/**
|
|
19
|
+
* Express context object containing req, res, and next
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
ctx: HttpContext,
|
|
23
|
+
/**
|
|
24
|
+
* ClearRequest instance
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
req: ClearRequest) => any | Promise<any>;
|
|
17
28
|
/**
|
|
18
29
|
* Handler can be either a function or controller reference
|
|
19
30
|
*/
|
package/dist/types/h3.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ControllerHandler } from "./basic.mjs";
|
|
2
|
+
import { ClearRequest } from "../src/ClearRequest.mjs";
|
|
2
3
|
import { H3, H3Event, Middleware, TypedServerRequest } from "h3";
|
|
3
4
|
|
|
4
5
|
//#region types/h3.d.ts
|
|
@@ -9,11 +10,21 @@ type MaybePromise<T = unknown> = T | Promise<T>;
|
|
|
9
10
|
/**
|
|
10
11
|
* HTTP context passed to route handlers
|
|
11
12
|
*/
|
|
12
|
-
|
|
13
|
+
type HttpContext = H3Event & {};
|
|
13
14
|
/**
|
|
14
15
|
* Route handler function type
|
|
15
16
|
*/
|
|
16
|
-
type RouteHandler = (
|
|
17
|
+
type RouteHandler = (
|
|
18
|
+
/**
|
|
19
|
+
* H3 event context
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
ctx: HttpContext,
|
|
23
|
+
/**
|
|
24
|
+
* ClearRequest instance
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
req: ClearRequest) => any | Promise<any>;
|
|
17
28
|
/**
|
|
18
29
|
* Handler can be either a function or controller reference
|
|
19
30
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clear-router",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Laravel-style routing system for Express.js and H3, with CommonJS, ESM, and TypeScript support",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"h3",
|
|
@@ -63,21 +63,26 @@
|
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
+
"@eslint/js": "^10.0.1",
|
|
67
|
+
"@eslint/markdown": "^7.5.1",
|
|
66
68
|
"@types/express": "^4.17.21",
|
|
67
69
|
"@types/node": "^20.10.6",
|
|
68
70
|
"@types/supertest": "^6.0.3",
|
|
71
|
+
"eslint": "^10.0.2",
|
|
69
72
|
"supertest": "^7.1.1",
|
|
70
73
|
"tsdown": "^0.20.3",
|
|
71
74
|
"tsx": "^4.21.0",
|
|
72
75
|
"typescript": "^5.3.3",
|
|
76
|
+
"typescript-eslint": "^8.56.1",
|
|
73
77
|
"vite-tsconfig-paths": "^6.1.1",
|
|
74
78
|
"vitest": "^4.0.18"
|
|
75
79
|
},
|
|
76
80
|
"engines": {
|
|
77
|
-
"node": ">=
|
|
81
|
+
"node": ">=20.0.0"
|
|
78
82
|
},
|
|
79
83
|
"scripts": {
|
|
80
|
-
"test": "
|
|
84
|
+
"test": "vitest",
|
|
85
|
+
"lint": "eslint",
|
|
81
86
|
"test:esm": "vitest tests/esm.test.ts",
|
|
82
87
|
"test:ts": "vitest tests/typescript.test.ts",
|
|
83
88
|
"example": "tsx example/express/index.ts",
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
//#region types/basic.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Controller method reference
|
|
4
|
-
*/
|
|
5
|
-
type ControllerHandler = [any, string];
|
|
6
|
-
/**
|
|
7
|
-
* HTTP methods supported by the router
|
|
8
|
-
*/
|
|
9
|
-
type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options' | 'head';
|
|
10
|
-
/**
|
|
11
|
-
* Route information object
|
|
12
|
-
*/
|
|
13
|
-
interface RouteInfo {
|
|
14
|
-
methods: HttpMethod[];
|
|
15
|
-
path: string;
|
|
16
|
-
middlewareCount: number;
|
|
17
|
-
handlerType: 'function' | 'controller';
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Common controller action names
|
|
21
|
-
*/
|
|
22
|
-
type ControllerAction = 'index' | 'show' | 'create' | 'update' | 'destroy';
|
|
23
|
-
//#endregion
|
|
24
|
-
export { RouteInfo as i, ControllerHandler as n, HttpMethod as r, ControllerAction as t };
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
//#region types/basic.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Controller method reference
|
|
4
|
-
*/
|
|
5
|
-
type ControllerHandler = [any, string];
|
|
6
|
-
/**
|
|
7
|
-
* HTTP methods supported by the router
|
|
8
|
-
*/
|
|
9
|
-
type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options' | 'head';
|
|
10
|
-
/**
|
|
11
|
-
* Route information object
|
|
12
|
-
*/
|
|
13
|
-
interface RouteInfo {
|
|
14
|
-
methods: HttpMethod[];
|
|
15
|
-
path: string;
|
|
16
|
-
middlewareCount: number;
|
|
17
|
-
handlerType: 'function' | 'controller';
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Common controller action names
|
|
21
|
-
*/
|
|
22
|
-
type ControllerAction = 'index' | 'show' | 'create' | 'update' | 'destroy';
|
|
23
|
-
//#endregion
|
|
24
|
-
export { RouteInfo as i, ControllerHandler as n, HttpMethod as r, ControllerAction as t };
|