deco-express 0.1.6 → 0.2.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/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { Express, RequestHandler } from 'express';
1
+ import { RequestHandler, Express } from 'express';
2
2
  import Joi from 'joi';
3
3
 
4
4
  /**
@@ -34,19 +34,24 @@ declare function Route(method: keyof Express, path?: string, ...middleware: Requ
34
34
  * and is prepended to every route path registered by {@link Route} decorators
35
35
  * on the class's methods.
36
36
  *
37
+ * Controller-level middleware is stored under the `"controllerMiddleware"` key
38
+ * and is prepended to every route handler in the controller.
39
+ *
37
40
  * @param baseRoute - The base path prefix for all routes in the controller
38
41
  * (e.g. `"/users"`). Defaults to `""` (no prefix).
42
+ * @param middleware - Zero or more Express middleware functions that are
43
+ * executed **before** every route handler in the controller.
39
44
  *
40
45
  * @example
41
46
  * ```ts
42
- * \@Controller('/users')
47
+ * \@Controller('/users', authMiddleware)
43
48
  * class UserController {
44
49
  * \@Route('get', '/:id')
45
50
  * getUser(req: Request, res: Response) { ... }
46
51
  * }
47
52
  * ```
48
53
  */
49
- declare function Controller(baseRoute?: string): (target: object) => void;
54
+ declare function Controller(baseRoute?: string, ...middleware: RequestHandler[]): (target: object) => void;
50
55
 
51
56
  /**
52
57
  * Method decorator that validates `req.body` against a Joi schema before the
@@ -91,8 +96,10 @@ type Constructor<T = object> = new (...args: unknown[]) => T;
91
96
  * For each controller the function:
92
97
  * 1. Instantiates the class with `new`.
93
98
  * 2. Reads the `"baseRoute"` metadata set by {@link Controller}.
94
- * 3. Reads the `"routeHandlers"` metadata set by {@link Route}.
95
- * 4. Mounts each handler at the resolved full path on the Express app.
99
+ * 3. Reads the `"controllerMiddleware"` metadata set by {@link Controller}.
100
+ * 4. Reads the `"routeHandlers"` metadata set by {@link Route}.
101
+ * 5. Mounts each handler at the resolved full path on the Express app,
102
+ * with controller-level middleware prepended to each route's handlers.
96
103
  *
97
104
  * The full path is built as:
98
105
  * ```
@@ -105,6 +112,8 @@ type Constructor<T = object> = new (...args: unknown[]) => T;
105
112
  * @param version - API version number. When `addApi` is `true` and `version`
106
113
  * is non-zero, a `/v{version}` segment is inserted after `/api`.
107
114
  * Defaults to `1`.
115
+ * @param log - When `true`, prints each registered route to the console.
116
+ * Defaults to `false`.
108
117
  *
109
118
  * @example
110
119
  * ```ts
@@ -113,11 +122,11 @@ type Constructor<T = object> = new (...args: unknown[]) => T;
113
122
  * import { UserController } from './controllers/user';
114
123
  *
115
124
  * const app = express();
116
- * defineRoutes([UserController], app);
117
- * // Routes are now available at /api/v1/...
125
+ * defineRoutes([UserController], app, true, 1, true);
126
+ * // [deco-express] GET /api/v1/users/:id
118
127
  * ```
119
128
  */
120
- declare function defineRoutes(controllers: Constructor[], application: Express, addApi?: boolean, version?: number): void;
129
+ declare function defineRoutes(controllers: Constructor[], application: Express, addApi?: boolean, version?: number, log?: boolean): void;
121
130
 
122
131
  /**
123
132
  * A nested map that stores route handlers organised by HTTP method and path.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Express, RequestHandler } from 'express';
1
+ import { RequestHandler, Express } from 'express';
2
2
  import Joi from 'joi';
3
3
 
4
4
  /**
@@ -34,19 +34,24 @@ declare function Route(method: keyof Express, path?: string, ...middleware: Requ
34
34
  * and is prepended to every route path registered by {@link Route} decorators
35
35
  * on the class's methods.
36
36
  *
37
+ * Controller-level middleware is stored under the `"controllerMiddleware"` key
38
+ * and is prepended to every route handler in the controller.
39
+ *
37
40
  * @param baseRoute - The base path prefix for all routes in the controller
38
41
  * (e.g. `"/users"`). Defaults to `""` (no prefix).
42
+ * @param middleware - Zero or more Express middleware functions that are
43
+ * executed **before** every route handler in the controller.
39
44
  *
40
45
  * @example
41
46
  * ```ts
42
- * \@Controller('/users')
47
+ * \@Controller('/users', authMiddleware)
43
48
  * class UserController {
44
49
  * \@Route('get', '/:id')
45
50
  * getUser(req: Request, res: Response) { ... }
46
51
  * }
47
52
  * ```
48
53
  */
49
- declare function Controller(baseRoute?: string): (target: object) => void;
54
+ declare function Controller(baseRoute?: string, ...middleware: RequestHandler[]): (target: object) => void;
50
55
 
51
56
  /**
52
57
  * Method decorator that validates `req.body` against a Joi schema before the
@@ -91,8 +96,10 @@ type Constructor<T = object> = new (...args: unknown[]) => T;
91
96
  * For each controller the function:
92
97
  * 1. Instantiates the class with `new`.
93
98
  * 2. Reads the `"baseRoute"` metadata set by {@link Controller}.
94
- * 3. Reads the `"routeHandlers"` metadata set by {@link Route}.
95
- * 4. Mounts each handler at the resolved full path on the Express app.
99
+ * 3. Reads the `"controllerMiddleware"` metadata set by {@link Controller}.
100
+ * 4. Reads the `"routeHandlers"` metadata set by {@link Route}.
101
+ * 5. Mounts each handler at the resolved full path on the Express app,
102
+ * with controller-level middleware prepended to each route's handlers.
96
103
  *
97
104
  * The full path is built as:
98
105
  * ```
@@ -105,6 +112,8 @@ type Constructor<T = object> = new (...args: unknown[]) => T;
105
112
  * @param version - API version number. When `addApi` is `true` and `version`
106
113
  * is non-zero, a `/v{version}` segment is inserted after `/api`.
107
114
  * Defaults to `1`.
115
+ * @param log - When `true`, prints each registered route to the console.
116
+ * Defaults to `false`.
108
117
  *
109
118
  * @example
110
119
  * ```ts
@@ -113,11 +122,11 @@ type Constructor<T = object> = new (...args: unknown[]) => T;
113
122
  * import { UserController } from './controllers/user';
114
123
  *
115
124
  * const app = express();
116
- * defineRoutes([UserController], app);
117
- * // Routes are now available at /api/v1/...
125
+ * defineRoutes([UserController], app, true, 1, true);
126
+ * // [deco-express] GET /api/v1/users/:id
118
127
  * ```
119
128
  */
120
- declare function defineRoutes(controllers: Constructor[], application: Express, addApi?: boolean, version?: number): void;
129
+ declare function defineRoutes(controllers: Constructor[], application: Express, addApi?: boolean, version?: number, log?: boolean): void;
121
130
 
122
131
  /**
123
132
  * A nested map that stores route handlers organised by HTTP method and path.
package/dist/index.js CHANGED
@@ -41,9 +41,10 @@ function Route(method, path = "", ...middleware) {
41
41
  };
42
42
  }
43
43
  __name(Route, "Route");
44
- function Controller(baseRoute = "") {
44
+ function Controller(baseRoute = "", ...middleware) {
45
45
  return (target) => {
46
46
  Reflect.defineMetadata("baseRoute", baseRoute, target);
47
+ Reflect.defineMetadata("controllerMiddleware", middleware, target);
47
48
  };
48
49
  }
49
50
  __name(Controller, "Controller");
@@ -66,7 +67,7 @@ function Validate(schema) {
66
67
  __name(Validate, "Validate");
67
68
 
68
69
  // src/functions/routes.ts
69
- function defineRoutes(controllers, application, addApi = true, version = 1) {
70
+ function defineRoutes(controllers, application, addApi = true, version = 1, log = false) {
70
71
  for (const ControllerClass of controllers) {
71
72
  const controller = new ControllerClass();
72
73
  const routeHandlers = Reflect.getMetadata(
@@ -74,12 +75,14 @@ function defineRoutes(controllers, application, addApi = true, version = 1) {
74
75
  controller
75
76
  );
76
77
  const controllerPath = Reflect.getMetadata("baseRoute", controller.constructor) ?? "";
78
+ const controllerMiddleware = Reflect.getMetadata("controllerMiddleware", controller.constructor) ?? [];
77
79
  if (!routeHandlers) continue;
78
80
  for (const [method, routes] of routeHandlers) {
79
81
  for (const [routePath, handlers] of routes) {
80
82
  const versionSegment = addApi && version ? `/v${version}` : "";
81
83
  const fullPath = `${addApi ? "/api" : ""}${versionSegment}${controllerPath}${routePath}`;
82
- application[method](fullPath, handlers);
84
+ application[method](fullPath, [...controllerMiddleware, ...handlers]);
85
+ if (log) console.log(`[deco-express] ${method.toUpperCase()} ${fullPath}`);
83
86
  }
84
87
  }
85
88
  }
package/dist/index.mjs CHANGED
@@ -16,9 +16,10 @@ function Route(method, path = "", ...middleware) {
16
16
  };
17
17
  }
18
18
  __name(Route, "Route");
19
- function Controller(baseRoute = "") {
19
+ function Controller(baseRoute = "", ...middleware) {
20
20
  return (target) => {
21
21
  Reflect.defineMetadata("baseRoute", baseRoute, target);
22
+ Reflect.defineMetadata("controllerMiddleware", middleware, target);
22
23
  };
23
24
  }
24
25
  __name(Controller, "Controller");
@@ -41,7 +42,7 @@ function Validate(schema) {
41
42
  __name(Validate, "Validate");
42
43
 
43
44
  // src/functions/routes.ts
44
- function defineRoutes(controllers, application, addApi = true, version = 1) {
45
+ function defineRoutes(controllers, application, addApi = true, version = 1, log = false) {
45
46
  for (const ControllerClass of controllers) {
46
47
  const controller = new ControllerClass();
47
48
  const routeHandlers = Reflect.getMetadata(
@@ -49,12 +50,14 @@ function defineRoutes(controllers, application, addApi = true, version = 1) {
49
50
  controller
50
51
  );
51
52
  const controllerPath = Reflect.getMetadata("baseRoute", controller.constructor) ?? "";
53
+ const controllerMiddleware = Reflect.getMetadata("controllerMiddleware", controller.constructor) ?? [];
52
54
  if (!routeHandlers) continue;
53
55
  for (const [method, routes] of routeHandlers) {
54
56
  for (const [routePath, handlers] of routes) {
55
57
  const versionSegment = addApi && version ? `/v${version}` : "";
56
58
  const fullPath = `${addApi ? "/api" : ""}${versionSegment}${controllerPath}${routePath}`;
57
- application[method](fullPath, handlers);
59
+ application[method](fullPath, [...controllerMiddleware, ...handlers]);
60
+ if (log) console.log(`[deco-express] ${method.toUpperCase()} ${fullPath}`);
58
61
  }
59
62
  }
60
63
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deco-express",
3
- "version": "0.1.6",
3
+ "version": "0.2.0",
4
4
  "author": "ndrolp",
5
5
  "description": "Decorator-based utilities for building Express.js REST APIs in TypeScript",
6
6
  "main": "./dist/index.js",