|
1 |
| -import type { ArgumentMetadata, ArgumentsHost, CanActivate, ExceptionFilter, ExecutionContext, PipeTransform } from '@nestjs/common' |
2 |
| -import type { IArgument, IPluginContext } from '@unioc/core' |
| 1 | +import type { ArgumentMetadata, ArgumentsHost, CanActivate, ExceptionFilter, ExecutionContext, NestMiddleware, NestModule, PipeTransform } from '@nestjs/common' |
| 2 | +import type { IArgument, IClassWrapper, IPluginContext } from '@unioc/core' |
3 | 3 | import type { IClass } from '@unioc/shared'
|
4 | 4 | import type { IHttpParam, IRestfulConnect, IRestfulScanner } from '@unioc/web'
|
| 5 | +import type { IMiddlewareApplyData, MiddlewareType } from '../middleware/middleware-customer' |
5 | 6 | import type { NestJSMethodOperator } from './method-operator'
|
| 7 | +import type { NestJSMethodWrapper } from './method-wrapper' |
6 | 8 | import { CONTROLLER_WATERMARK, FILTER_CATCH_EXCEPTIONS } from '@nestjs/common/constants.js'
|
| 9 | +import { isClass } from '@unioc/shared' |
7 | 10 | import { RestfulScanner } from '@unioc/web'
|
| 11 | +import { MiddlewareCustomerBuilder } from '../middleware/middleware-customer' |
8 | 12 | import { NestJSControllerWrapper } from './controller-wrapper'
|
9 | 13 | import { NestJSRestfulHandler } from './restful-handler'
|
10 | 14 |
|
11 | 15 | export interface INestJSPipeArgument extends IArgument, ArgumentMetadata, Partial<Record<IHttpParam, unknown>> {}
|
12 | 16 | export type INestJSFilterCatchType = 'done' | 'no-match'
|
13 | 17 |
|
14 | 18 | export class NestJSRestfulScanner extends RestfulScanner implements IRestfulScanner {
|
| 19 | + constructor(pluginContext: IPluginContext, private readonly _modules: IClassWrapper[]) { |
| 20 | + super(pluginContext) |
| 21 | + } |
| 22 | + |
15 | 23 | override getPluginContext(): IPluginContext {
|
16 | 24 | return super.getPluginContext()
|
17 | 25 | }
|
@@ -134,6 +142,74 @@ export class NestJSRestfulScanner extends RestfulScanner implements IRestfulScan
|
134 | 142 | return true
|
135 | 143 | }
|
136 | 144 |
|
| 145 | + private _middlewareCustomerMap: Map<MiddlewareType, IMiddlewareApplyData> = new Map<MiddlewareType, IMiddlewareApplyData>() |
| 146 | + |
| 147 | + async resolveMiddlewares(): Promise<void> { |
| 148 | + for (const moduleWrapper of this._modules) { |
| 149 | + const resolveInstance: NestModule = await moduleWrapper.resolve() |
| 150 | + if (!('configure' in resolveInstance) || typeof resolveInstance.configure !== 'function') |
| 151 | + continue |
| 152 | + |
| 153 | + const middlewareCustomer = new MiddlewareCustomerBuilder(this.getPluginContext()) |
| 154 | + await resolveInstance.configure(middlewareCustomer) |
| 155 | + this._middlewareCustomerMap = middlewareCustomer.merge(this._middlewareCustomerMap) |
| 156 | + } |
| 157 | + } |
| 158 | + |
| 159 | + async executeMiddlewares(methodWrapper: NestJSMethodWrapper, ctx: IRestfulConnect.WebContext): Promise<void> { |
| 160 | + const fullPaths = methodWrapper.findAll().map(o => o.getFullPath()) |
| 161 | + const classTarget = methodWrapper.getControllerOperator().getControllerWrapper().getClassWrapper().getTarget() |
| 162 | + const matchedMiddlewares: MiddlewareType[] = [] |
| 163 | + |
| 164 | + for (const [middleware, data] of this._middlewareCustomerMap.entries()) { |
| 165 | + for (const route of data.includedRoutes) { |
| 166 | + if (isClass(route)) { |
| 167 | + if (classTarget === route) { |
| 168 | + matchedMiddlewares.push(middleware) |
| 169 | + } |
| 170 | + } |
| 171 | + else if (typeof route === 'string') { |
| 172 | + if (fullPaths.includes(route)) { |
| 173 | + matchedMiddlewares.push(middleware) |
| 174 | + } |
| 175 | + } |
| 176 | + else { |
| 177 | + if (fullPaths.includes(route.path)) { |
| 178 | + matchedMiddlewares.push(middleware) |
| 179 | + } |
| 180 | + } |
| 181 | + } |
| 182 | + |
| 183 | + for (const route of data.excludedRoutes) { |
| 184 | + if (isClass(route)) { |
| 185 | + if (classTarget === route) { |
| 186 | + matchedMiddlewares.splice(matchedMiddlewares.indexOf(middleware), 1) |
| 187 | + } |
| 188 | + } |
| 189 | + else if (typeof route === 'string') { |
| 190 | + if (fullPaths.includes(route)) { |
| 191 | + matchedMiddlewares.splice(matchedMiddlewares.indexOf(middleware), 1) |
| 192 | + } |
| 193 | + } |
| 194 | + else { |
| 195 | + if (fullPaths.includes(route.path)) { |
| 196 | + matchedMiddlewares.splice(matchedMiddlewares.indexOf(middleware), 1) |
| 197 | + } |
| 198 | + } |
| 199 | + } |
| 200 | + } |
| 201 | + |
| 202 | + for (const middleware of matchedMiddlewares) { |
| 203 | + if (isClass(middleware)) { |
| 204 | + const middlewareInstance = await this.getPluginContext().createClass<IClass<NestMiddleware>>(middleware).resolve() |
| 205 | + await middlewareInstance.use(ctx.request, ctx.response, ctx.next) |
| 206 | + } |
| 207 | + else { |
| 208 | + await middleware(ctx.request, ctx.response, ctx.next) |
| 209 | + } |
| 210 | + } |
| 211 | + } |
| 212 | + |
137 | 213 | resolveConnectHandler(): IRestfulConnect.Handler {
|
138 | 214 | return new NestJSRestfulHandler(this)
|
139 | 215 | }
|
|
0 commit comments