import { List } from 'immutable' import _ from 'lodash' import 'reflect-metadata' import { MetadataKey } from '../constants/MetadataKey' import { Middleware } from '../lib/Middleware' import { getClassInstance } from '../lib/utils' import { Constructor } from '../types/Constructor' import { Authenticator, Guard } from '../processors' import { IMiddleFilterOptions, MiddlewareFilter } from '../lib/MiddlewareFilter' export function UseMiddleware(...middleware: (Middleware | Constructor)[]) { return (...args: any[]) => { middleware = middleware.map((m) => { if (typeof m === 'function') { return getClassInstance(m) } else if (m instanceof Middleware) { return m } else { throw TypeError('Invalid middleware type') } }) const newMiddleware = List(middleware) if (args.length === 1) { const [constructor] = args const mw: List = Reflect.getOwnMetadata(MetadataKey.MIDDLEWARE, constructor.prototype) || List() Reflect.defineMetadata(MetadataKey.MIDDLEWARE, newMiddleware.concat(mw), constructor.prototype) } else { const [target, propertyKey] = args const mw: List = Reflect.getOwnMetadata(MetadataKey.MIDDLEWARE, target, propertyKey) || List() Reflect.defineMetadata(MetadataKey.MIDDLEWARE, newMiddleware.concat(mw), target, propertyKey) } } } export function FilterMiddleware(options: { scope?: Constructor include?: IMiddleFilterOptions exclude?: IMiddleFilterOptions }) { const filter = new MiddlewareFilter(options) return (...args: any[]) => { if (args.length === 1) { const [constructor] = args const filters: List = Reflect.getOwnMetadata(MetadataKey.MIDDLEWARE_FILTER, constructor.prototype) || List() Reflect.defineMetadata(MetadataKey.MIDDLEWARE_FILTER, filters.concat(filter), constructor.prototype) } else { const [target, propertyKey] = args const filters: List = Reflect.getOwnMetadata(MetadataKey.MIDDLEWARE_FILTER, target, propertyKey) || List() Reflect.defineMetadata(MetadataKey.MIDDLEWARE_FILTER, filters.concat(filter), target, propertyKey) } } } export function UseGuards(...guards: (Guard | Constructor)[]) { return UseMiddleware(...guards) } export function UseGuard(guard: Guard | Constructor) { return UseMiddleware(guard) } export function UseAuthenticator(authenticator: Authenticator) { return UseMiddleware(authenticator) } export function OnlyAuthenticator(authenticator: Authenticator) { return (...args: any[]) => { UseMiddleware(authenticator)(...args) FilterMiddleware({ scope: Authenticator, include: { middleware: [authenticator] } })(...args) } } export function NoAuthenticator() { return FilterMiddleware({ scope: Authenticator, exclude: { type: Authenticator } }) }