Skip to content

Commit

Permalink
tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
vcwen committed Mar 9, 2021
1 parent 726f11a commit 1043bee
Show file tree
Hide file tree
Showing 18 changed files with 313 additions and 309 deletions.
5 changes: 4 additions & 1 deletion src/Luren.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import helmet from 'koa-helmet'
import { AppModule } from './lib/AppModule'
import { Router } from './lib/Router'
import { ResponseConverter } from './processors'
import { MiddlewarePack } from './lib/MiddlewarePack'

const debug = Debug('luren')

Expand Down Expand Up @@ -99,7 +100,9 @@ export class Luren<StateT = any, CustomT = any> extends Koa<StateT, CustomT> {
throw TypeError('Invalid middleware type')
}
})
this._appModule.middleware = this._appModule.middleware.concat(middlewareInstances)
this._appModule.middlewarePacks = this._appModule.middlewarePacks.concat(
middlewareInstances.map((m) => new MiddlewarePack(m))
)
return this
}

Expand Down
3 changes: 1 addition & 2 deletions src/constants/MetadataKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ export const MetadataKey = {
AUTHENTICATOR_MOUNT_TYPE: key('AUTHENTICATOR_MOUNT_TYPE'),
CONTROLLER: key('CONTROLLER'),
CONTROLLER_MODULE: key('CONTROLLER_MODULE'),
MIDDLEWARE: key('MIDDLEWARE'),
MIDDLEWARE_FILTER: key('MIDDLEWARE_FILTER'),
MIDDLEWARE_PACKS: key('MIDDLEWARE_PACKS'),
PROCESSORS: key('PROCESSORS'),
ACTION_MODULE: key('ACTION_MODULE'),
ACTION: key('ACTION'),
Expand Down
91 changes: 43 additions & 48 deletions src/decorators/UseMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,22 @@ 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<Middleware>)[]) {
import { Guard } from '../processors'
import { ModuleContext } from '../lib'
import { MiddlewarePack } from '../lib/MiddlewarePack'
export interface IUseMiddlewareOptions {
shouldMount?: (moduleContext: ModuleContext) => boolean
filter?: (middleware: Middleware) => boolean
isPlaceholder?: boolean
}
export function UseMiddleware(
middleware: (Middleware | Constructor<Middleware>) | (Middleware | Constructor<Middleware>)[],
options?: IUseMiddlewareOptions
) {
return (...args: any[]) => {
if (!Array.isArray(middleware)) {
middleware = [middleware]
}
middleware = middleware.map((m) => {
if (typeof m === 'function') {
return getClassInstance(m)
Expand All @@ -19,59 +30,43 @@ export function UseMiddleware(...middleware: (Middleware | Constructor<Middlewar
throw TypeError('Invalid middleware type')
}
})
const newMiddleware = List(middleware)
const middlewarePacks = List(middleware.map((m) => new MiddlewarePack(m as Middleware, options)))
if (args.length === 1) {
const [constructor] = args
const mw: List<any> = Reflect.getOwnMetadata(MetadataKey.MIDDLEWARE, constructor.prototype) || List()
Reflect.defineMetadata(MetadataKey.MIDDLEWARE, newMiddleware.concat(mw), constructor.prototype)
const mwPacks: List<MiddlewarePack> =
Reflect.getOwnMetadata(MetadataKey.MIDDLEWARE_PACKS, constructor.prototype) || List()
Reflect.defineMetadata(MetadataKey.MIDDLEWARE_PACKS, middlewarePacks.concat(mwPacks), constructor.prototype)
} else {
const [target, propertyKey] = args
const mw: List<any> = Reflect.getOwnMetadata(MetadataKey.MIDDLEWARE, target, propertyKey) || List()
Reflect.defineMetadata(MetadataKey.MIDDLEWARE, newMiddleware.concat(mw), target, propertyKey)
const mwPacks: List<MiddlewarePack> =
Reflect.getOwnMetadata(MetadataKey.MIDDLEWARE_PACKS, target, propertyKey) || List()
Reflect.defineMetadata(MetadataKey.MIDDLEWARE_PACKS, middlewarePacks.concat(mwPacks), target, propertyKey)
}
}
}

export function FilterMiddleware<T extends Middleware = Middleware>(options: {
scope?: Constructor<T>
include?: IMiddleFilterOptions<T>
exclude?: IMiddleFilterOptions<T>
}) {
const filter = new MiddlewareFilter(options)
return (...args: any[]) => {
if (args.length === 1) {
const [constructor] = args
const filters: List<MiddlewareFilter> =
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<MiddlewareFilter> =
Reflect.getOwnMetadata(MetadataKey.MIDDLEWARE_FILTER, target, propertyKey) || List()
Reflect.defineMetadata(MetadataKey.MIDDLEWARE_FILTER, filters.concat(filter), target, propertyKey)
}
}
export function UseGuard(
guard: Guard | Constructor<Guard> | (Guard | Constructor<Guard>)[],
options?: IUseMiddlewareOptions
) {
return UseMiddleware(guard, options)
}

export function UseGuards(...guards: (Guard | Constructor<Guard>)[]) {
return UseMiddleware(...guards)
}

export function UseGuard(guard: Guard | Constructor<Guard>) {
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 FilterMiddleware(filter: (m: Middleware) => boolean, type: string)
export function FilterMiddleware(filter: (m: Middleware) => boolean, placeholder?: Middleware)
export function FilterMiddleware(filter: (m: Middleware) => boolean, option: any) {
let m: Middleware
if (typeof option === 'string') {
const type = option
m = new (class extends Middleware {
public type = type
// tslint:disable-next-line: no-empty
public async execute() {}
})()
} else if (option instanceof Middleware) {
m = option
} else {
throw new Error('the option should be a type string or middleware placeholder object')
}
}

export function NoAuthenticator() {
return FilterMiddleware({ scope: Authenticator, exclude: { type: Authenticator } })
return UseMiddleware(m, { filter, isPlaceholder: true })
}
17 changes: 5 additions & 12 deletions src/lib/Action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { List, Map } from 'immutable'
import { Context, Next } from 'koa'
import { HttpMethod, HttpStatusCode, MetadataKey, ParamSource } from '../constants'
import { HttpResponse } from './HttpResponse'
import { Middleware } from './Middleware'
import { ParamInfo } from './ParamInfo'
import { ResponseInfo } from './ResponseInfo'
import { ControllerModule } from '.'
Expand All @@ -17,7 +16,7 @@ import { IncomingFile } from './IncomingFile'
import { GenericType } from './GenericType'
import { normalizeHeaderCase } from './utils'
import mime from 'mime-types'
import { MiddlewareFilter } from './MiddlewareFilter'
import { MiddlewarePack } from './MiddlewarePack'

export class ActionExecutor {
public controller: object
Expand Down Expand Up @@ -348,7 +347,7 @@ export class ActionModule {
public path: string
public pathRegExp: { regExp: RegExp; params: (string | number)[] }
public method: HttpMethod
public middleware: List<Middleware> = List()
public middlewarePacks: List<MiddlewarePack> = List()
public deprecated: boolean = false
public version?: string
public desc?: string
Expand All @@ -375,15 +374,9 @@ export class ActionModule {
this.actionExecutor = new ActionExecutor(this.controllerModule.controller, targetFunction, this.params)
this.responses = getResponseInfos(controllerModule.controller, targetFunction, actionOwner, genericParams)
this.summary = actionMetadata.summary
const middleware: List<Middleware> =
Reflect.getMetadata(MetadataKey.MIDDLEWARE, controllerModule.controller, targetFunction) || List()
const middlewareFilters: List<MiddlewareFilter> =
Reflect.getMetadata(MetadataKey.MIDDLEWARE_FILTER, controllerModule.controller, targetFunction) || List()
const filteredMiddleware = middlewareFilters.reduce(
(mw, filter) => filter.filter(mw),
controllerModule.middleware.concat(middleware).toArray()
)
this.middleware = List(filteredMiddleware)

this.middlewarePacks =
Reflect.getMetadata(MetadataKey.MIDDLEWARE_PACKS, controllerModule.controller, targetFunction) || List()
}
public getFullPath() {
const version = this.version ?? this.controllerModule.version ?? ''
Expand Down
4 changes: 2 additions & 2 deletions src/lib/AppModule.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { List } from 'immutable'
import { Luren } from '../Luren'
import { ControllerModule } from '.'
import { Middleware } from './Middleware'
import { MiddlewarePack } from './MiddlewarePack'

export class AppModule {
public app: Luren
public middleware: List<Middleware> = List()
public middlewarePacks: List<MiddlewarePack> = List()
public controllerModules: List<ControllerModule> = List()
constructor(app: Luren) {
this.app = app
Expand Down
15 changes: 4 additions & 11 deletions src/lib/ControllerModule.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { List } from 'immutable'
import { ActionModule } from './Action'
import { Middleware } from './Middleware'
import { MiddlewarePack } from './MiddlewarePack'
import Path from 'path'
import { CtrlMetadata } from '../decorators'
import { MetadataKey } from '../constants'
import { pathToRegexp } from 'path-to-regexp'
import { MiddlewareFilter } from './MiddlewareFilter'
import { AppModule } from './AppModule'

export class ControllerModule {
appModule: AppModule
public appModule: AppModule
public controller: object
public actionModules: List<ActionModule> = List()
public middleware: List<Middleware> = List()
public middlewarePacks: List<MiddlewarePack> = List()
public name: string
public plural?: string
public prefix: string = ''
Expand All @@ -36,13 +35,7 @@ export class ControllerModule {
end: false
})
this.desc = ctrlMetadata.desc
const middleware: List<Middleware> = Reflect.getMetadata(MetadataKey.MIDDLEWARE, ctrl) || List()
const middlewareFilters: List<MiddlewareFilter> = Reflect.getMetadata(MetadataKey.MIDDLEWARE_FILTER, ctrl) || List()
const filteredMiddleware = middlewareFilters.reduce(
(mw, filter) => filter.filter(mw),
this.appModule.middleware.concat(middleware).toArray()
)
this.middleware = List(filteredMiddleware)
this.middlewarePacks = Reflect.getMetadata(MetadataKey.MIDDLEWARE_PACKS, ctrl) || List()
}
public getFullPath() {
return Path.join(this.prefix, this.version ?? '', this.path)
Expand Down
9 changes: 8 additions & 1 deletion src/lib/Middleware.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
import { Context, Next } from 'koa'
import { v4 as uuid } from 'uuid'

export interface IMiddleware {
execute(ctx: Context, next: Next): Promise<any>
toRawMiddleware(): (ctx: Context, next: Next) => Promise<any>
}

export abstract class Middleware implements IMiddleware {
public id: string
public abstract type: string
constructor() {
this.id = uuid()
}
public abstract async execute(ctx: Context, next: Next): Promise<any>
public toRawMiddleware() {
return async (ctx: Context, next: Next) => {
return this.execute(ctx, next)
}
}
public static fromRawMiddleware(rawMiddleware: (ctx: Context, next: Next) => any) {
public static fromRawMiddleware(type: string, rawMiddleware: (ctx: Context, next: Next) => any) {
// tslint:disable-next-line: max-classes-per-file
return new (class extends Middleware {
public type = type
public execute(ctx: Context, next: Next): Promise<any> {
return rawMiddleware(ctx, next)
}
Expand Down
Loading

0 comments on commit 1043bee

Please sign in to comment.