clear-router 2.9.0 → 2.9.1
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 +15 -1
- package/dist/core/CoreRouter.cjs +2 -0
- package/dist/core/CoreRouter.mjs +2 -0
- package/dist/core/index.cjs +3 -0
- package/dist/core/index.d.cts +2 -1
- package/dist/core/index.d.mts +2 -1
- package/dist/core/index.mjs +2 -1
- package/dist/decorators/index.cjs +4 -1
- package/dist/decorators/index.d.cts +2 -1
- package/dist/decorators/index.d.mts +2 -1
- package/dist/decorators/index.mjs +2 -1
- package/dist/decorators/middleware.cjs +100 -0
- package/dist/decorators/middleware.d.cts +51 -0
- package/dist/decorators/middleware.d.mts +51 -0
- package/dist/decorators/middleware.mjs +98 -0
- package/dist/decorators/setup.cjs +4 -1
- package/dist/decorators/setup.d.cts +2 -1
- package/dist/decorators/setup.d.mts +2 -1
- package/dist/decorators/setup.mjs +2 -1
- package/dist/index.cjs +3 -0
- package/dist/index.d.cts +2 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.mjs +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -95,7 +95,21 @@ See [API.md](https://arkstack-hq.github.io/clear-router/api) for complete API do
|
|
|
95
95
|
## Middleware Execution Order
|
|
96
96
|
|
|
97
97
|
```txt
|
|
98
|
-
[ Global Middleware ] → [ Group Middleware ] → [ Route Middleware ]
|
|
98
|
+
[ Global Middleware ] → [ Group Middleware ] → [ @middleware (class) ] → [ @middleware (method) ] → [ Route Middleware ]
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Controllers and controller methods can declare middleware with the `@middleware`
|
|
102
|
+
decorator, accepting the same shapes as any other middleware (callbacks,
|
|
103
|
+
middleware classes, or instances exposing a `handle` method):
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
import { middleware } from 'clear-router/decorators';
|
|
107
|
+
|
|
108
|
+
@middleware([auth])
|
|
109
|
+
class AccountController {
|
|
110
|
+
@middleware(GuestMiddleware)
|
|
111
|
+
create() {}
|
|
112
|
+
}
|
|
99
113
|
```
|
|
100
114
|
|
|
101
115
|
## Handler Execution
|
package/dist/core/CoreRouter.cjs
CHANGED
|
@@ -3,6 +3,7 @@ const require_RouteGroup = require('../RouteGroup.cjs');
|
|
|
3
3
|
const require_RouteRegistrar = require('../RouteRegistrar.cjs');
|
|
4
4
|
const require_Request = require('./Request.cjs');
|
|
5
5
|
const require_Response = require('./Response.cjs');
|
|
6
|
+
const require_middleware = require('../decorators/middleware.cjs');
|
|
6
7
|
const require_bindings = require('./bindings.cjs');
|
|
7
8
|
const require_ResourceRoutes = require('../ResourceRoutes.cjs');
|
|
8
9
|
let node_async_hooks = require("node:async_hooks");
|
|
@@ -790,6 +791,7 @@ var CoreRouter = class {
|
|
|
790
791
|
const route = new require_Route.Route(methods.includes("options") ? methods : methods.concat("options"), fullPath, handler, this.resolveMiddlewares([
|
|
791
792
|
...this.globalMiddlewares,
|
|
792
793
|
...activeGroupMiddlewares,
|
|
794
|
+
...require_middleware.getControllerMiddlewares(handler),
|
|
793
795
|
...middlewares || []
|
|
794
796
|
]), {
|
|
795
797
|
registrationPaths,
|
package/dist/core/CoreRouter.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import { RouteGroup } from "../RouteGroup.mjs";
|
|
|
3
3
|
import { RouteRegistrar } from "../RouteRegistrar.mjs";
|
|
4
4
|
import { Request } from "./Request.mjs";
|
|
5
5
|
import { Response } from "./Response.mjs";
|
|
6
|
+
import { getControllerMiddlewares } from "../decorators/middleware.mjs";
|
|
6
7
|
import { Container, getBindingMetadataFromTargets, getDesignParamTypes, getStandardMetadata, isClass } from "./bindings.mjs";
|
|
7
8
|
import { ResourceRoutes } from "../ResourceRoutes.mjs";
|
|
8
9
|
import { createRequire } from "node:module";
|
|
@@ -790,6 +791,7 @@ var CoreRouter = class {
|
|
|
790
791
|
const route = new Route(methods.includes("options") ? methods : methods.concat("options"), fullPath, handler, this.resolveMiddlewares([
|
|
791
792
|
...this.globalMiddlewares,
|
|
792
793
|
...activeGroupMiddlewares,
|
|
794
|
+
...getControllerMiddlewares(handler),
|
|
793
795
|
...middlewares || []
|
|
794
796
|
]), {
|
|
795
797
|
registrationPaths,
|
package/dist/core/index.cjs
CHANGED
|
@@ -4,6 +4,7 @@ const require_RouteGroup = require('../RouteGroup.cjs');
|
|
|
4
4
|
const require_Request = require('./Request.cjs');
|
|
5
5
|
const require_Response = require('./Response.cjs');
|
|
6
6
|
const require_plugins = require('./plugins.cjs');
|
|
7
|
+
const require_middleware = require('../decorators/middleware.cjs');
|
|
7
8
|
const require_CoreRouter = require('./CoreRouter.cjs');
|
|
8
9
|
|
|
9
10
|
exports.CoreRouter = require_CoreRouter.CoreRouter;
|
|
@@ -11,5 +12,7 @@ exports.Request = require_Request.Request;
|
|
|
11
12
|
exports.Response = require_Response.Response;
|
|
12
13
|
exports.RouteGroup = require_RouteGroup.RouteGroup;
|
|
13
14
|
exports.definePlugin = require_plugins.definePlugin;
|
|
15
|
+
exports.getControllerMiddlewares = require_middleware.getControllerMiddlewares;
|
|
14
16
|
exports.importFile = require_helpers.importFile;
|
|
17
|
+
exports.middleware = require_middleware.middleware;
|
|
15
18
|
exports.wrap = require_helpers.wrap;
|
package/dist/core/index.d.cts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Response } from "./Response.cjs";
|
|
2
2
|
import { Request } from "./Request.cjs";
|
|
3
3
|
import { ClearRouterPlugin, ClearRouterPluginArgumentsContext, ClearRouterPluginContext, ClearRouterPluginInput, ClearRouterPluginRequestContext, PluginArgumentsResolver, PluginBind, PluginBindFactory, PluginBindValue, PluginSetupResult, definePlugin } from "./plugins.cjs";
|
|
4
|
+
import { MiddlewareDecorator, MiddlewareInput, getControllerMiddlewares, middleware } from "../decorators/middleware.cjs";
|
|
4
5
|
import { RouteGroup } from "../RouteGroup.cjs";
|
|
5
6
|
import { CoreRouter } from "./CoreRouter.cjs";
|
|
6
7
|
import { importFile, wrap } from "./helpers.cjs";
|
|
7
|
-
export { ClearRouterPlugin, ClearRouterPluginArgumentsContext, ClearRouterPluginContext, ClearRouterPluginInput, ClearRouterPluginRequestContext, CoreRouter, PluginArgumentsResolver, PluginBind, PluginBindFactory, PluginBindValue, PluginSetupResult, Request, Response, RouteGroup, definePlugin, importFile, wrap };
|
|
8
|
+
export { ClearRouterPlugin, ClearRouterPluginArgumentsContext, ClearRouterPluginContext, ClearRouterPluginInput, ClearRouterPluginRequestContext, CoreRouter, MiddlewareDecorator, MiddlewareInput, PluginArgumentsResolver, PluginBind, PluginBindFactory, PluginBindValue, PluginSetupResult, Request, Response, RouteGroup, definePlugin, getControllerMiddlewares, importFile, middleware, wrap };
|
package/dist/core/index.d.mts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Response } from "./Response.mjs";
|
|
2
2
|
import { Request } from "./Request.mjs";
|
|
3
3
|
import { ClearRouterPlugin, ClearRouterPluginArgumentsContext, ClearRouterPluginContext, ClearRouterPluginInput, ClearRouterPluginRequestContext, PluginArgumentsResolver, PluginBind, PluginBindFactory, PluginBindValue, PluginSetupResult, definePlugin } from "./plugins.mjs";
|
|
4
|
+
import { MiddlewareDecorator, MiddlewareInput, getControllerMiddlewares, middleware } from "../decorators/middleware.mjs";
|
|
4
5
|
import { RouteGroup } from "../RouteGroup.mjs";
|
|
5
6
|
import { CoreRouter } from "./CoreRouter.mjs";
|
|
6
7
|
import { importFile, wrap } from "./helpers.mjs";
|
|
7
|
-
export { ClearRouterPlugin, ClearRouterPluginArgumentsContext, ClearRouterPluginContext, ClearRouterPluginInput, ClearRouterPluginRequestContext, CoreRouter, PluginArgumentsResolver, PluginBind, PluginBindFactory, PluginBindValue, PluginSetupResult, Request, Response, RouteGroup, definePlugin, importFile, wrap };
|
|
8
|
+
export { ClearRouterPlugin, ClearRouterPluginArgumentsContext, ClearRouterPluginContext, ClearRouterPluginInput, ClearRouterPluginRequestContext, CoreRouter, MiddlewareDecorator, MiddlewareInput, PluginArgumentsResolver, PluginBind, PluginBindFactory, PluginBindValue, PluginSetupResult, Request, Response, RouteGroup, definePlugin, getControllerMiddlewares, importFile, middleware, wrap };
|
package/dist/core/index.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import { RouteGroup } from "../RouteGroup.mjs";
|
|
|
3
3
|
import { Request } from "./Request.mjs";
|
|
4
4
|
import { Response } from "./Response.mjs";
|
|
5
5
|
import { definePlugin } from "./plugins.mjs";
|
|
6
|
+
import { getControllerMiddlewares, middleware } from "../decorators/middleware.mjs";
|
|
6
7
|
import { CoreRouter } from "./CoreRouter.mjs";
|
|
7
8
|
|
|
8
|
-
export { CoreRouter, Request, Response, RouteGroup, definePlugin, importFile, wrap };
|
|
9
|
+
export { CoreRouter, Request, Response, RouteGroup, definePlugin, getControllerMiddlewares, importFile, middleware, wrap };
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_middleware = require('./middleware.cjs');
|
|
2
3
|
const require_bindings = require('../core/bindings.cjs');
|
|
3
4
|
|
|
4
5
|
exports.Bind = require_bindings.Bind;
|
|
5
|
-
exports.Container = require_bindings.Container;
|
|
6
|
+
exports.Container = require_bindings.Container;
|
|
7
|
+
exports.getControllerMiddlewares = require_middleware.getControllerMiddlewares;
|
|
8
|
+
exports.middleware = require_middleware.middleware;
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import { Bind, BindDecorator, BindFactory, BindToken, BindValue, Container } from "../core/bindings.cjs";
|
|
2
|
-
|
|
2
|
+
import { MiddlewareDecorator, MiddlewareInput, getControllerMiddlewares, middleware } from "./middleware.cjs";
|
|
3
|
+
export { Bind, type BindDecorator, type BindFactory, type BindToken, type BindValue, Container, type MiddlewareDecorator, type MiddlewareInput, getControllerMiddlewares, middleware };
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import { Bind, BindDecorator, BindFactory, BindToken, BindValue, Container } from "../core/bindings.mjs";
|
|
2
|
-
|
|
2
|
+
import { MiddlewareDecorator, MiddlewareInput, getControllerMiddlewares, middleware } from "./middleware.mjs";
|
|
3
|
+
export { Bind, type BindDecorator, type BindFactory, type BindToken, type BindValue, Container, type MiddlewareDecorator, type MiddlewareInput, getControllerMiddlewares, middleware };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/decorators/middleware.ts
|
|
3
|
+
const CLASS_KEY = "__class__";
|
|
4
|
+
const metadataKey = Symbol.for("clear-router:middleware-metadata");
|
|
5
|
+
const store = /* @__PURE__ */ new WeakMap();
|
|
6
|
+
/**
|
|
7
|
+
* Attach one or more middleware to a controller class or a controller method.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* @Middleware([auth])
|
|
12
|
+
* class AccountController {}
|
|
13
|
+
*
|
|
14
|
+
* class LoginController {
|
|
15
|
+
* @Middleware(GuestMiddleware)
|
|
16
|
+
* create () {}
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* Accepts the middleware variadically or as arrays, and every supported
|
|
21
|
+
* middleware shape: callbacks, middleware classes, or instances exposing a
|
|
22
|
+
* `handle` method.
|
|
23
|
+
*
|
|
24
|
+
* @param middlewares
|
|
25
|
+
* @returns
|
|
26
|
+
*/
|
|
27
|
+
function middleware(...middlewares) {
|
|
28
|
+
const flattened = middlewares.flat();
|
|
29
|
+
return ((target, propertyKeyOrContext) => {
|
|
30
|
+
if (isStandardClassContext(propertyKeyOrContext)) {
|
|
31
|
+
setClassMiddlewareMetadata(target, flattened);
|
|
32
|
+
setStandardMetadata(propertyKeyOrContext.metadata, CLASS_KEY, flattened);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (isStandardMethodContext(propertyKeyOrContext)) {
|
|
36
|
+
setStandardMetadata(propertyKeyOrContext.metadata, propertyKeyOrContext.name, flattened);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (typeof propertyKeyOrContext === "undefined") {
|
|
40
|
+
setClassMiddlewareMetadata(target, flattened);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
setMiddlewareMetadata(target, propertyKeyOrContext, flattened);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Collect the decorator-declared middleware for a controller route handler,
|
|
48
|
+
* ordered class-level first then method-level. Returns an empty array for
|
|
49
|
+
* non-controller (callback) handlers or handlers without any decorators.
|
|
50
|
+
*
|
|
51
|
+
* @param handler
|
|
52
|
+
* @returns
|
|
53
|
+
*/
|
|
54
|
+
function getControllerMiddlewares(handler) {
|
|
55
|
+
if (!Array.isArray(handler) || handler.length !== 2) return [];
|
|
56
|
+
const [controller, method] = handler;
|
|
57
|
+
if (!controller) return [];
|
|
58
|
+
const constructor = typeof controller === "function" ? controller : controller.constructor;
|
|
59
|
+
const prototype = typeof controller === "function" ? controller.prototype : Object.getPrototypeOf(controller);
|
|
60
|
+
const standardMetadata = constructor?.[Symbol.metadata];
|
|
61
|
+
const classMiddlewares = getMiddlewareMetadata(constructor, CLASS_KEY) ?? getMiddlewareMetadata(prototype, CLASS_KEY) ?? getStandardMetadata(standardMetadata, CLASS_KEY) ?? [];
|
|
62
|
+
const methodMiddlewares = getMiddlewareMetadata(prototype, method) ?? getMiddlewareMetadata(constructor, method) ?? getStandardMetadata(standardMetadata, method) ?? [];
|
|
63
|
+
return [...classMiddlewares, ...methodMiddlewares];
|
|
64
|
+
}
|
|
65
|
+
function setClassMiddlewareMetadata(target, middlewares) {
|
|
66
|
+
setMiddlewareMetadata(target, CLASS_KEY, middlewares);
|
|
67
|
+
const prototype = target.prototype;
|
|
68
|
+
if (prototype) setMiddlewareMetadata(prototype, CLASS_KEY, middlewares);
|
|
69
|
+
}
|
|
70
|
+
function setMiddlewareMetadata(target, propertyKey, middlewares) {
|
|
71
|
+
const map = store.get(target) ?? /* @__PURE__ */ new Map();
|
|
72
|
+
const existing = map.get(propertyKey);
|
|
73
|
+
map.set(propertyKey, existing ? [...existing, ...middlewares] : middlewares);
|
|
74
|
+
store.set(target, map);
|
|
75
|
+
}
|
|
76
|
+
function getMiddlewareMetadata(target, propertyKey) {
|
|
77
|
+
if (!target) return void 0;
|
|
78
|
+
return store.get(target)?.get(propertyKey);
|
|
79
|
+
}
|
|
80
|
+
function setStandardMetadata(metadata, propertyKey, middlewares) {
|
|
81
|
+
if (!metadata) return;
|
|
82
|
+
const record = metadata;
|
|
83
|
+
record[metadataKey] = record[metadataKey] ?? {};
|
|
84
|
+
const existing = record[metadataKey][propertyKey];
|
|
85
|
+
record[metadataKey][propertyKey] = existing ? [...existing, ...middlewares] : middlewares;
|
|
86
|
+
}
|
|
87
|
+
function getStandardMetadata(metadata, propertyKey) {
|
|
88
|
+
const record = metadata && metadata[metadataKey];
|
|
89
|
+
return record ? record[propertyKey] : void 0;
|
|
90
|
+
}
|
|
91
|
+
function isStandardMethodContext(value) {
|
|
92
|
+
return Boolean(value && typeof value === "object" && value.kind === "method" && typeof value.name !== "undefined");
|
|
93
|
+
}
|
|
94
|
+
function isStandardClassContext(value) {
|
|
95
|
+
return Boolean(value && typeof value === "object" && value.kind === "class" && typeof value.name !== "undefined");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//#endregion
|
|
99
|
+
exports.getControllerMiddlewares = getControllerMiddlewares;
|
|
100
|
+
exports.middleware = middleware;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ClassMiddleware, MiddlewareHandle } from "../types/basic.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/decorators/middleware.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Any value accepted as a middleware by the router: a plain callback, a class
|
|
6
|
+
* exposing a `handle` method, or an already-instantiated object exposing one.
|
|
7
|
+
*/
|
|
8
|
+
type MiddlewareInput = MiddlewareHandle | ClassMiddleware;
|
|
9
|
+
/**
|
|
10
|
+
* Decorator produced by {@link Middleware}. Works both as a class decorator (to
|
|
11
|
+
* apply the middleware to every action of a controller) and as a method
|
|
12
|
+
* decorator (to apply it to a single action). Supports the legacy
|
|
13
|
+
* (`experimentalDecorators`) and TC39 standard decorator signatures.
|
|
14
|
+
*/
|
|
15
|
+
type MiddlewareDecorator = MethodDecorator & ClassDecorator & {
|
|
16
|
+
<This, Value extends (this: This, ...args: any[]) => any>(value: Value, context: ClassMethodDecoratorContext<This, Value>): void | Value;
|
|
17
|
+
<Value extends abstract new (...args: any[]) => any>(value: Value, context: ClassDecoratorContext<Value>): void | Value;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Attach one or more middleware to a controller class or a controller method.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* @Middleware([auth])
|
|
25
|
+
* class AccountController {}
|
|
26
|
+
*
|
|
27
|
+
* class LoginController {
|
|
28
|
+
* @Middleware(GuestMiddleware)
|
|
29
|
+
* create () {}
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* Accepts the middleware variadically or as arrays, and every supported
|
|
34
|
+
* middleware shape: callbacks, middleware classes, or instances exposing a
|
|
35
|
+
* `handle` method.
|
|
36
|
+
*
|
|
37
|
+
* @param middlewares
|
|
38
|
+
* @returns
|
|
39
|
+
*/
|
|
40
|
+
declare function middleware(...middlewares: Array<MiddlewareInput | MiddlewareInput[]>): MiddlewareDecorator;
|
|
41
|
+
/**
|
|
42
|
+
* Collect the decorator-declared middleware for a controller route handler,
|
|
43
|
+
* ordered class-level first then method-level. Returns an empty array for
|
|
44
|
+
* non-controller (callback) handlers or handlers without any decorators.
|
|
45
|
+
*
|
|
46
|
+
* @param handler
|
|
47
|
+
* @returns
|
|
48
|
+
*/
|
|
49
|
+
declare function getControllerMiddlewares(handler: any): MiddlewareInput[];
|
|
50
|
+
//#endregion
|
|
51
|
+
export { MiddlewareDecorator, MiddlewareInput, getControllerMiddlewares, middleware };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ClassMiddleware, MiddlewareHandle } from "../types/basic.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/decorators/middleware.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Any value accepted as a middleware by the router: a plain callback, a class
|
|
6
|
+
* exposing a `handle` method, or an already-instantiated object exposing one.
|
|
7
|
+
*/
|
|
8
|
+
type MiddlewareInput = MiddlewareHandle | ClassMiddleware;
|
|
9
|
+
/**
|
|
10
|
+
* Decorator produced by {@link Middleware}. Works both as a class decorator (to
|
|
11
|
+
* apply the middleware to every action of a controller) and as a method
|
|
12
|
+
* decorator (to apply it to a single action). Supports the legacy
|
|
13
|
+
* (`experimentalDecorators`) and TC39 standard decorator signatures.
|
|
14
|
+
*/
|
|
15
|
+
type MiddlewareDecorator = MethodDecorator & ClassDecorator & {
|
|
16
|
+
<This, Value extends (this: This, ...args: any[]) => any>(value: Value, context: ClassMethodDecoratorContext<This, Value>): void | Value;
|
|
17
|
+
<Value extends abstract new (...args: any[]) => any>(value: Value, context: ClassDecoratorContext<Value>): void | Value;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Attach one or more middleware to a controller class or a controller method.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* @Middleware([auth])
|
|
25
|
+
* class AccountController {}
|
|
26
|
+
*
|
|
27
|
+
* class LoginController {
|
|
28
|
+
* @Middleware(GuestMiddleware)
|
|
29
|
+
* create () {}
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* Accepts the middleware variadically or as arrays, and every supported
|
|
34
|
+
* middleware shape: callbacks, middleware classes, or instances exposing a
|
|
35
|
+
* `handle` method.
|
|
36
|
+
*
|
|
37
|
+
* @param middlewares
|
|
38
|
+
* @returns
|
|
39
|
+
*/
|
|
40
|
+
declare function middleware(...middlewares: Array<MiddlewareInput | MiddlewareInput[]>): MiddlewareDecorator;
|
|
41
|
+
/**
|
|
42
|
+
* Collect the decorator-declared middleware for a controller route handler,
|
|
43
|
+
* ordered class-level first then method-level. Returns an empty array for
|
|
44
|
+
* non-controller (callback) handlers or handlers without any decorators.
|
|
45
|
+
*
|
|
46
|
+
* @param handler
|
|
47
|
+
* @returns
|
|
48
|
+
*/
|
|
49
|
+
declare function getControllerMiddlewares(handler: any): MiddlewareInput[];
|
|
50
|
+
//#endregion
|
|
51
|
+
export { MiddlewareDecorator, MiddlewareInput, getControllerMiddlewares, middleware };
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
//#region src/decorators/middleware.ts
|
|
2
|
+
const CLASS_KEY = "__class__";
|
|
3
|
+
const metadataKey = Symbol.for("clear-router:middleware-metadata");
|
|
4
|
+
const store = /* @__PURE__ */ new WeakMap();
|
|
5
|
+
/**
|
|
6
|
+
* Attach one or more middleware to a controller class or a controller method.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* @Middleware([auth])
|
|
11
|
+
* class AccountController {}
|
|
12
|
+
*
|
|
13
|
+
* class LoginController {
|
|
14
|
+
* @Middleware(GuestMiddleware)
|
|
15
|
+
* create () {}
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* Accepts the middleware variadically or as arrays, and every supported
|
|
20
|
+
* middleware shape: callbacks, middleware classes, or instances exposing a
|
|
21
|
+
* `handle` method.
|
|
22
|
+
*
|
|
23
|
+
* @param middlewares
|
|
24
|
+
* @returns
|
|
25
|
+
*/
|
|
26
|
+
function middleware(...middlewares) {
|
|
27
|
+
const flattened = middlewares.flat();
|
|
28
|
+
return ((target, propertyKeyOrContext) => {
|
|
29
|
+
if (isStandardClassContext(propertyKeyOrContext)) {
|
|
30
|
+
setClassMiddlewareMetadata(target, flattened);
|
|
31
|
+
setStandardMetadata(propertyKeyOrContext.metadata, CLASS_KEY, flattened);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (isStandardMethodContext(propertyKeyOrContext)) {
|
|
35
|
+
setStandardMetadata(propertyKeyOrContext.metadata, propertyKeyOrContext.name, flattened);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (typeof propertyKeyOrContext === "undefined") {
|
|
39
|
+
setClassMiddlewareMetadata(target, flattened);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
setMiddlewareMetadata(target, propertyKeyOrContext, flattened);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Collect the decorator-declared middleware for a controller route handler,
|
|
47
|
+
* ordered class-level first then method-level. Returns an empty array for
|
|
48
|
+
* non-controller (callback) handlers or handlers without any decorators.
|
|
49
|
+
*
|
|
50
|
+
* @param handler
|
|
51
|
+
* @returns
|
|
52
|
+
*/
|
|
53
|
+
function getControllerMiddlewares(handler) {
|
|
54
|
+
if (!Array.isArray(handler) || handler.length !== 2) return [];
|
|
55
|
+
const [controller, method] = handler;
|
|
56
|
+
if (!controller) return [];
|
|
57
|
+
const constructor = typeof controller === "function" ? controller : controller.constructor;
|
|
58
|
+
const prototype = typeof controller === "function" ? controller.prototype : Object.getPrototypeOf(controller);
|
|
59
|
+
const standardMetadata = constructor?.[Symbol.metadata];
|
|
60
|
+
const classMiddlewares = getMiddlewareMetadata(constructor, CLASS_KEY) ?? getMiddlewareMetadata(prototype, CLASS_KEY) ?? getStandardMetadata(standardMetadata, CLASS_KEY) ?? [];
|
|
61
|
+
const methodMiddlewares = getMiddlewareMetadata(prototype, method) ?? getMiddlewareMetadata(constructor, method) ?? getStandardMetadata(standardMetadata, method) ?? [];
|
|
62
|
+
return [...classMiddlewares, ...methodMiddlewares];
|
|
63
|
+
}
|
|
64
|
+
function setClassMiddlewareMetadata(target, middlewares) {
|
|
65
|
+
setMiddlewareMetadata(target, CLASS_KEY, middlewares);
|
|
66
|
+
const prototype = target.prototype;
|
|
67
|
+
if (prototype) setMiddlewareMetadata(prototype, CLASS_KEY, middlewares);
|
|
68
|
+
}
|
|
69
|
+
function setMiddlewareMetadata(target, propertyKey, middlewares) {
|
|
70
|
+
const map = store.get(target) ?? /* @__PURE__ */ new Map();
|
|
71
|
+
const existing = map.get(propertyKey);
|
|
72
|
+
map.set(propertyKey, existing ? [...existing, ...middlewares] : middlewares);
|
|
73
|
+
store.set(target, map);
|
|
74
|
+
}
|
|
75
|
+
function getMiddlewareMetadata(target, propertyKey) {
|
|
76
|
+
if (!target) return void 0;
|
|
77
|
+
return store.get(target)?.get(propertyKey);
|
|
78
|
+
}
|
|
79
|
+
function setStandardMetadata(metadata, propertyKey, middlewares) {
|
|
80
|
+
if (!metadata) return;
|
|
81
|
+
const record = metadata;
|
|
82
|
+
record[metadataKey] = record[metadataKey] ?? {};
|
|
83
|
+
const existing = record[metadataKey][propertyKey];
|
|
84
|
+
record[metadataKey][propertyKey] = existing ? [...existing, ...middlewares] : middlewares;
|
|
85
|
+
}
|
|
86
|
+
function getStandardMetadata(metadata, propertyKey) {
|
|
87
|
+
const record = metadata && metadata[metadataKey];
|
|
88
|
+
return record ? record[propertyKey] : void 0;
|
|
89
|
+
}
|
|
90
|
+
function isStandardMethodContext(value) {
|
|
91
|
+
return Boolean(value && typeof value === "object" && value.kind === "method" && typeof value.name !== "undefined");
|
|
92
|
+
}
|
|
93
|
+
function isStandardClassContext(value) {
|
|
94
|
+
return Boolean(value && typeof value === "object" && value.kind === "class" && typeof value.name !== "undefined");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
//#endregion
|
|
98
|
+
export { getControllerMiddlewares, middleware };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_middleware = require('./middleware.cjs');
|
|
2
3
|
const require_bindings = require('../core/bindings.cjs');
|
|
3
4
|
const require_CoreRouter = require('../core/CoreRouter.cjs');
|
|
4
5
|
require('./index.cjs');
|
|
@@ -12,4 +13,6 @@ require_CoreRouter.CoreRouter.configureDefaults({ container: {
|
|
|
12
13
|
|
|
13
14
|
//#endregion
|
|
14
15
|
exports.Bind = require_bindings.Bind;
|
|
15
|
-
exports.Container = require_bindings.Container;
|
|
16
|
+
exports.Container = require_bindings.Container;
|
|
17
|
+
exports.getControllerMiddlewares = require_middleware.getControllerMiddlewares;
|
|
18
|
+
exports.middleware = require_middleware.middleware;
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import { Bind, BindDecorator, BindFactory, BindToken, BindValue, Container } from "../core/bindings.cjs";
|
|
2
|
-
|
|
2
|
+
import { MiddlewareDecorator, MiddlewareInput, getControllerMiddlewares, middleware } from "./middleware.cjs";
|
|
3
|
+
export { Bind, BindDecorator, BindFactory, BindToken, BindValue, Container, MiddlewareDecorator, MiddlewareInput, getControllerMiddlewares, middleware };
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import { Bind, BindDecorator, BindFactory, BindToken, BindValue, Container } from "../core/bindings.mjs";
|
|
2
|
-
|
|
2
|
+
import { MiddlewareDecorator, MiddlewareInput, getControllerMiddlewares, middleware } from "./middleware.mjs";
|
|
3
|
+
export { Bind, BindDecorator, BindFactory, BindToken, BindValue, Container, MiddlewareDecorator, MiddlewareInput, getControllerMiddlewares, middleware };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getControllerMiddlewares, middleware } from "./middleware.mjs";
|
|
1
2
|
import { Bind, Container } from "../core/bindings.mjs";
|
|
2
3
|
import { CoreRouter } from "../core/CoreRouter.mjs";
|
|
3
4
|
import "./index.mjs";
|
|
@@ -10,4 +11,4 @@ CoreRouter.configureDefaults({ container: {
|
|
|
10
11
|
} });
|
|
11
12
|
|
|
12
13
|
//#endregion
|
|
13
|
-
export { Bind, Container };
|
|
14
|
+
export { Bind, Container, getControllerMiddlewares, middleware };
|
package/dist/index.cjs
CHANGED
|
@@ -8,6 +8,7 @@ const require_RouteRegistrar = require('./RouteRegistrar.cjs');
|
|
|
8
8
|
const require_Request = require('./core/Request.cjs');
|
|
9
9
|
const require_Response = require('./core/Response.cjs');
|
|
10
10
|
const require_plugins = require('./core/plugins.cjs');
|
|
11
|
+
const require_middleware = require('./decorators/middleware.cjs');
|
|
11
12
|
const require_CoreRouter = require('./core/CoreRouter.cjs');
|
|
12
13
|
require('./core/index.cjs');
|
|
13
14
|
|
|
@@ -20,6 +21,8 @@ exports.Route = require_Route.Route;
|
|
|
20
21
|
exports.RouteGroup = require_RouteGroup.RouteGroup;
|
|
21
22
|
exports.RouteRegistrar = require_RouteRegistrar.RouteRegistrar;
|
|
22
23
|
exports.definePlugin = require_plugins.definePlugin;
|
|
24
|
+
exports.getControllerMiddlewares = require_middleware.getControllerMiddlewares;
|
|
23
25
|
exports.importFile = require_helpers.importFile;
|
|
26
|
+
exports.middleware = require_middleware.middleware;
|
|
24
27
|
exports.parseDomainParameters = require_Route.parseDomainParameters;
|
|
25
28
|
exports.wrap = require_helpers.wrap;
|
package/dist/index.d.cts
CHANGED
|
@@ -4,9 +4,10 @@ import { ClearRequest } from "./ClearRequest.cjs";
|
|
|
4
4
|
import { Route, parseDomainParameters } from "./Route.cjs";
|
|
5
5
|
import { Request } from "./core/Request.cjs";
|
|
6
6
|
import { ClearRouterPlugin, ClearRouterPluginArgumentsContext, ClearRouterPluginContext, ClearRouterPluginInput, ClearRouterPluginRequestContext, PluginArgumentsResolver, PluginBind, PluginBindFactory, PluginBindValue, PluginSetupResult, definePlugin } from "./core/plugins.cjs";
|
|
7
|
+
import { MiddlewareDecorator, MiddlewareInput, getControllerMiddlewares, middleware } from "./decorators/middleware.cjs";
|
|
7
8
|
import { Controller } from "./Controller.cjs";
|
|
8
9
|
import { RouteGroup } from "./RouteGroup.cjs";
|
|
9
10
|
import { RouteRegistrar, RouteRegistrarGroupFactory } from "./RouteRegistrar.cjs";
|
|
10
11
|
import { CoreRouter } from "./core/CoreRouter.cjs";
|
|
11
12
|
import { importFile, wrap } from "./core/helpers.cjs";
|
|
12
|
-
export { ClearHttpContext, ClearRequest, ClearRouterPlugin, ClearRouterPluginArgumentsContext, ClearRouterPluginContext, ClearRouterPluginInput, ClearRouterPluginRequestContext, Controller, CoreRouter, PluginArgumentsResolver, PluginBind, PluginBindFactory, PluginBindValue, PluginSetupResult, Request, Response, Route, RouteGroup, RouteParameter, RouteRegistrar, RouteRegistrarGroupFactory, definePlugin, importFile, parseDomainParameters, wrap };
|
|
13
|
+
export { ClearHttpContext, ClearRequest, ClearRouterPlugin, ClearRouterPluginArgumentsContext, ClearRouterPluginContext, ClearRouterPluginInput, ClearRouterPluginRequestContext, Controller, CoreRouter, MiddlewareDecorator, MiddlewareInput, PluginArgumentsResolver, PluginBind, PluginBindFactory, PluginBindValue, PluginSetupResult, Request, Response, Route, RouteGroup, RouteParameter, RouteRegistrar, RouteRegistrarGroupFactory, definePlugin, getControllerMiddlewares, importFile, middleware, parseDomainParameters, wrap };
|
package/dist/index.d.mts
CHANGED
|
@@ -4,9 +4,10 @@ import { ClearRequest } from "./ClearRequest.mjs";
|
|
|
4
4
|
import { Route, parseDomainParameters } from "./Route.mjs";
|
|
5
5
|
import { Request } from "./core/Request.mjs";
|
|
6
6
|
import { ClearRouterPlugin, ClearRouterPluginArgumentsContext, ClearRouterPluginContext, ClearRouterPluginInput, ClearRouterPluginRequestContext, PluginArgumentsResolver, PluginBind, PluginBindFactory, PluginBindValue, PluginSetupResult, definePlugin } from "./core/plugins.mjs";
|
|
7
|
+
import { MiddlewareDecorator, MiddlewareInput, getControllerMiddlewares, middleware } from "./decorators/middleware.mjs";
|
|
7
8
|
import { Controller } from "./Controller.mjs";
|
|
8
9
|
import { RouteGroup } from "./RouteGroup.mjs";
|
|
9
10
|
import { RouteRegistrar, RouteRegistrarGroupFactory } from "./RouteRegistrar.mjs";
|
|
10
11
|
import { CoreRouter } from "./core/CoreRouter.mjs";
|
|
11
12
|
import { importFile, wrap } from "./core/helpers.mjs";
|
|
12
|
-
export { ClearHttpContext, ClearRequest, ClearRouterPlugin, ClearRouterPluginArgumentsContext, ClearRouterPluginContext, ClearRouterPluginInput, ClearRouterPluginRequestContext, Controller, CoreRouter, PluginArgumentsResolver, PluginBind, PluginBindFactory, PluginBindValue, PluginSetupResult, Request, Response, Route, RouteGroup, RouteParameter, RouteRegistrar, RouteRegistrarGroupFactory, definePlugin, importFile, parseDomainParameters, wrap };
|
|
13
|
+
export { ClearHttpContext, ClearRequest, ClearRouterPlugin, ClearRouterPluginArgumentsContext, ClearRouterPluginContext, ClearRouterPluginInput, ClearRouterPluginRequestContext, Controller, CoreRouter, MiddlewareDecorator, MiddlewareInput, PluginArgumentsResolver, PluginBind, PluginBindFactory, PluginBindValue, PluginSetupResult, Request, Response, Route, RouteGroup, RouteParameter, RouteRegistrar, RouteRegistrarGroupFactory, definePlugin, getControllerMiddlewares, importFile, middleware, parseDomainParameters, wrap };
|
package/dist/index.mjs
CHANGED
|
@@ -7,7 +7,8 @@ import { RouteRegistrar } from "./RouteRegistrar.mjs";
|
|
|
7
7
|
import { Request } from "./core/Request.mjs";
|
|
8
8
|
import { Response } from "./core/Response.mjs";
|
|
9
9
|
import { definePlugin } from "./core/plugins.mjs";
|
|
10
|
+
import { getControllerMiddlewares, middleware } from "./decorators/middleware.mjs";
|
|
10
11
|
import { CoreRouter } from "./core/CoreRouter.mjs";
|
|
11
12
|
import "./core/index.mjs";
|
|
12
13
|
|
|
13
|
-
export { ClearRequest, Controller, CoreRouter, Request, Response, Route, RouteGroup, RouteRegistrar, definePlugin, importFile, parseDomainParameters, wrap };
|
|
14
|
+
export { ClearRequest, Controller, CoreRouter, Request, Response, Route, RouteGroup, RouteRegistrar, definePlugin, getControllerMiddlewares, importFile, middleware, parseDomainParameters, wrap };
|
package/package.json
CHANGED