From e6846fac0fb1526299a186741e0935cbda4b1263 Mon Sep 17 00:00:00 2001 From: xiaojue Date: Fri, 5 Mar 2021 13:02:36 +0800 Subject: [PATCH] fix: request and response decorators oldFunc call miss arguments --- example/07-plugin/index.ts | 114 +++++++++++++++++++++++++++++++++++++ package.json | 2 +- src/decorators/request.ts | 6 +- src/decorators/response.ts | 8 +-- 4 files changed, 122 insertions(+), 8 deletions(-) create mode 100644 example/07-plugin/index.ts diff --git a/example/07-plugin/index.ts b/example/07-plugin/index.ts new file mode 100644 index 0000000..0519443 --- /dev/null +++ b/example/07-plugin/index.ts @@ -0,0 +1,114 @@ +import { + Constructor, + controller, + Daruk, + DarukContext, + DarukServer, + get, + inject, + plugin, + PluginClass, + provide, + type +} from '../../src'; + +// type +type PromiseVoidFunc = () => Promise; +type PromiseVoidArgsFunc = (...args: any[]) => Promise; +type ClassFunc< + Name extends string | symbol = string | symbol, + Func extends Function = PromiseVoidArgsFunc +> = { [key in Name]: Func }; + +// ReflectList +class ReflectList< + T extends Object = Object, + K = any, + V = any, + P extends string | symbol = string | symbol +> { + public Append(target: T, key: K, value: V, propertyKey?: P) { + const list = this.Get(target, key); + const newList = [value].concat(list); + Reflect.defineMetadata(key, newList, target, propertyKey as string); + } + + public Get(target: T, key: K, propertyKey?: P): V[] { + return Reflect.getMetadata(key, target, propertyKey as string) || []; + } +} + +// ParamPlugin +const ParamReflect = new ReflectList< + any, + string, + { index: number; name: string; type: Constructor }, + 'param' +>(); + +export default function Param(name: string, type: Constructor = String) { + return (target: any, targetKey: string, index: number) => { + ParamReflect.Append(target.constructor, targetKey, { index, name, type }, 'param'); + }; +} + +@plugin() +class ParamPlugin implements PluginClass { + public async initPlugin(daruk: Daruk) { + const controllers: any[] = Reflect.getMetadata('daruk:controller_class', Reflect) || []; + for (const controller of controllers) { + const routeFuncs: string[] = + Reflect.getMetadata('daruk:controller_func_name', controller) || []; + for (const func of routeFuncs) { + const prototype: ClassFunc = controller.prototype; + const params = ParamReflect.Get(controller, func, 'param'); + if (params.length > 0) { + const origin = prototype[func]; + prototype[func] = async function ( + ctx: DarukContext, + next: PromiseVoidFunc, + ...args: any[] + ) { + const params = ParamReflect.Get(controller, func, 'param'); + for (const { index, name, type } of params) { + args[index - 2] = new type(ctx.query[name]); + } + await origin.call(this, ctx, next, ...args); + }; + } + } + } + } +} + +// main +const main = async function () { + try { + const app = DarukServer(); + + @provide('Db') + class Db { + public async FindByName(name: string) { + return { name, address: '127.0.0.1' }; + } + } + + @controller() + class mainController { + @inject('Db') private Db!: Db; + + @get(`find_by_name`) + @type('application/json') // 如果函数`findByName`加上`type`装饰器 无法读取第二个及以后的参数 + public async findByName(ctx: DarukContext, _: any, @Param('name') name: string) { + ctx.body = await this.Db.FindByName(name); + } + } + + await app.binding(); + app.listen(8899); + } catch (error) { + console.log(error); + } +}; + +main(); // http://127.0.0.1:8899/find_by_name?name=ddkk diff --git a/package.json b/package.json index 1826a2a..77e2d97 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "daruk", - "version": "2.3.5", + "version": "2.3.6", "description": "a node.js web framework", "main": "build/index.js", "scripts": { diff --git a/src/decorators/request.ts b/src/decorators/request.ts index 91a685a..eaf0d6f 100644 --- a/src/decorators/request.ts +++ b/src/decorators/request.ts @@ -18,7 +18,7 @@ export function validate(method: method, key: string, validateFunc: validateFunc if (is.string(ret)) ctx.validateError.push(ret); } // tslint:disable-next-line:no-invalid-this - await oldFunc.call(this, ctx, next); + await oldFunc.call(this, ...arguments); await next(); }; }; @@ -53,7 +53,7 @@ export function required(config: { body?: string[]; query?: string[]; params?: s check(query, config.query, 'query') || check(params, config.params, 'params'); // tslint:disable-next-line:no-invalid-this - await oldFunc.call(this, ctx, next); + await oldFunc.call(this, ...arguments); await next(); }; }; @@ -100,7 +100,7 @@ export function typeParse(config: { body?: ParseType; query?: ParseType; params? ctx.parseQuery = parse(config.query, ctx.query); ctx.parseParams = parse(config.params, ctx.params); // tslint:disable-next-line:no-invalid-this - await oldFunc.call(this, ctx, next); + await oldFunc.call(this, ...arguments); await next(); }; }; diff --git a/src/decorators/response.ts b/src/decorators/response.ts index 19391ed..c4f5801 100644 --- a/src/decorators/response.ts +++ b/src/decorators/response.ts @@ -66,7 +66,7 @@ export function json() { descriptor.value = async function jsonWrap(ctx: koa.Context, next: () => Promise) { // tslint:disable-next-line:no-invalid-this - const val = await oldFunc.call(this, ctx); + const val = await oldFunc.call(this, ...arguments); // 确保是Object类型 ctx.body = { ...val }; await next(); @@ -104,7 +104,7 @@ export function type(type: string) { const oldFunc = descriptor.value; descriptor.value = async function typeWrap(ctx: koa.Context, next: () => Promise) { // tslint:disable-next-line:no-invalid-this - await oldFunc.call(this, ctx); + await oldFunc.call(this, ...arguments); ctx.type = type; await next(); }; @@ -137,7 +137,7 @@ export function header(key: string | { [key: string]: string }, value?: string) const oldFunc = descriptor.value; descriptor.value = async function headerWrap(ctx: koa.Context, next: () => Promise) { // tslint:disable-next-line:no-invalid-this - await oldFunc.call(this, ctx); + await oldFunc.call(this, ...arguments); ctx.set(headers); await next(); }; @@ -155,7 +155,7 @@ export function cache(callback: (cacheKey: string, shouldCacheData?: string) => ctx.body = cacheData; } else { // tslint:disable-next-line:no-invalid-this - await oldFunc.call(this, ctx); + await oldFunc.call(this, ...arguments); await callback(cacheKey, ctx.body); } await next();