feat: improve rest api middleware
This commit is contained in:
		
							parent
							
								
									5847c9eeab
								
							
						
					
					
						commit
						edbe1ecb67
					
				@ -152,32 +152,6 @@ describe('koa middleware', () => {
 | 
				
			|||||||
    expect(response.body.arr).toEqual([3, 4]);
 | 
					    expect(response.body.arr).toEqual([3, 4]);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  it('shound work', async () => {
 | 
					 | 
				
			||||||
    const app = new Koa();
 | 
					 | 
				
			||||||
    const resourcer = new Resourcer();
 | 
					 | 
				
			||||||
    const agent = supertest.agent(app.callback());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    resourcer.define({
 | 
					 | 
				
			||||||
      name: 'tables#fields',
 | 
					 | 
				
			||||||
      actions: {
 | 
					 | 
				
			||||||
        async list(ctx, next) {
 | 
					 | 
				
			||||||
          ctx.body = ctx.body || {};
 | 
					 | 
				
			||||||
          ctx.body.arr = ctx.body.arr || [];
 | 
					 | 
				
			||||||
          ctx.body.arr.push(3);
 | 
					 | 
				
			||||||
          await next();
 | 
					 | 
				
			||||||
          ctx.body.arr.push(4);
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    app.use(resourcer.middleware({
 | 
					 | 
				
			||||||
      nameRule: ({ resourceName, associatedName }) => associatedName ? `${associatedName}#${resourceName}` : resourceName,
 | 
					 | 
				
			||||||
    }));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const response = await agent.get('/tables/demos/fields');
 | 
					 | 
				
			||||||
    expect(response.body.arr).toEqual([3, 4]);
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  describe('action options', () => {
 | 
					  describe('action options', () => {
 | 
				
			||||||
    let resourcer: Resourcer;
 | 
					    let resourcer: Resourcer;
 | 
				
			||||||
    let app: Koa;
 | 
					    let app: Koa;
 | 
				
			||||||
 | 
				
			|||||||
@ -29,11 +29,51 @@ export interface KoaMiddlewareOptions {
 | 
				
			|||||||
  nameRule?: (params: ParsedParams) => string;
 | 
					  nameRule?: (params: ParsedParams) => string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * 上下文中的 key - ctx[paramsKey]
 | 
					   * 自定义 action name
 | 
				
			||||||
   * 
 | 
					   * 
 | 
				
			||||||
   * 可以单独配置 paramsKey,默认为 params
 | 
					   * 默认为
 | 
				
			||||||
 | 
					   * 
 | 
				
			||||||
 | 
					   * - list 查看列表
 | 
				
			||||||
 | 
					   * - create 新增数据
 | 
				
			||||||
 | 
					   * - get 查看数据详情
 | 
				
			||||||
 | 
					   * - update 更新数据
 | 
				
			||||||
 | 
					   * - delete 删除数据
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  paramsKey?: string;
 | 
					  accessors?: {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 查看列表
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    list?: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 新增数据
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    create?: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 查看数据详情
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    get?: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 更新数据
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    update?: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 删除数据
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    delete?: string;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface ResourcerOptions {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 前缀
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  prefix?: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * 自定义 action name
 | 
					   * 自定义 action name
 | 
				
			||||||
@ -127,10 +167,14 @@ export class Resourcer {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  protected middlewareHandlers = new Map<string, any>();
 | 
					  protected middlewareHandlers = new Map<string, any>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  protected paramsKey = 'params';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  protected middlewares = [];
 | 
					  protected middlewares = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public readonly options: ResourcerOptions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constructor(options: ResourcerOptions = {}) {
 | 
				
			||||||
 | 
					    this.options = options;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * 载入指定目录下的 resource 配置(配置的文件驱动)
 | 
					   * 载入指定目录下的 resource 配置(配置的文件驱动)
 | 
				
			||||||
   * 
 | 
					   * 
 | 
				
			||||||
@ -174,6 +218,14 @@ export class Resourcer {
 | 
				
			|||||||
    return this.resources.has(name);
 | 
					    return this.resources.has(name);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  registerAction(name: ActionName, handler: HandlerType) {
 | 
				
			||||||
 | 
					    this.registerActionHandler(name, handler);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  registerActions(handlers: Handlers) {
 | 
				
			||||||
 | 
					    this.registerActionHandlers(handlers);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * 注册全局的 action handlers
 | 
					   * 注册全局的 action handlers
 | 
				
			||||||
   * 
 | 
					   * 
 | 
				
			||||||
@ -212,10 +264,6 @@ export class Resourcer {
 | 
				
			|||||||
    return this.getResource(name).getAction(action);
 | 
					    return this.getResource(name).getAction(action);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getParamsKey() {
 | 
					 | 
				
			||||||
    return this.paramsKey;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  getMiddlewares() {
 | 
					  getMiddlewares() {
 | 
				
			||||||
    return this.middlewares;
 | 
					    return this.middlewares;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -228,48 +276,40 @@ export class Resourcer {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  middleware(options: KoaMiddlewareOptions = {}) {
 | 
					  restApiMiddleware(options: KoaMiddlewareOptions = {}) {
 | 
				
			||||||
    const { prefix, accessors, paramsKey = 'params', nameRule = getNameByParams } = options;
 | 
					    const { prefix, accessors } = options;
 | 
				
			||||||
    return async (ctx: ResourcerContext, next: () => Promise<any>) => {
 | 
					    const restApiMiddleware = async (ctx: ResourcerContext, next: () => Promise<any>) => {
 | 
				
			||||||
      ctx.resourcer = this;
 | 
					      ctx.resourcer = this;
 | 
				
			||||||
      let params = parseRequest({
 | 
					      let params = parseRequest({
 | 
				
			||||||
        path: ctx.request.path,
 | 
					        path: ctx.request.path,
 | 
				
			||||||
        method: ctx.request.method,
 | 
					        method: ctx.request.method,
 | 
				
			||||||
      }, {
 | 
					      }, {
 | 
				
			||||||
        prefix,
 | 
					        prefix: this.options.prefix || prefix,
 | 
				
			||||||
        accessors,
 | 
					        accessors: this.options.accessors || accessors,
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      if (!params) {
 | 
					      if (!params) {
 | 
				
			||||||
        return next();
 | 
					        return next();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      try {
 | 
					      try {
 | 
				
			||||||
        const resource = this.getResource(nameRule(params));
 | 
					        const resource = this.getResource(getNameByParams(params));
 | 
				
			||||||
        // 为关系资源时,暂时需要再执行一遍 parseRequest
 | 
					        // 为关系资源时,暂时需要再执行一遍 parseRequest
 | 
				
			||||||
        if (resource.options.type !== 'single') {
 | 
					        if (resource.options.type && resource.options.type !== 'single') {
 | 
				
			||||||
          params = parseRequest({
 | 
					          params = parseRequest({
 | 
				
			||||||
            path: ctx.request.path,
 | 
					            path: ctx.request.path,
 | 
				
			||||||
            method: ctx.request.method,
 | 
					            method: ctx.request.method,
 | 
				
			||||||
            type: resource.options.type,
 | 
					            type: resource.options.type,
 | 
				
			||||||
          }, {
 | 
					          }, {
 | 
				
			||||||
            prefix,
 | 
					            prefix: this.options.prefix || prefix,
 | 
				
			||||||
            accessors,
 | 
					            accessors: this.options.accessors || accessors,
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
          if (!params) {
 | 
					          if (!params) {
 | 
				
			||||||
            return next();
 | 
					            return next();
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // action 需要 clone 之后再赋给 ctx
 | 
					        // action 需要 clone 之后再赋给 ctx
 | 
				
			||||||
        ctx.action = this.getAction(nameRule(params), params.actionName).clone();
 | 
					        ctx.action = this.getAction(getNameByParams(params), params.actionName).clone();
 | 
				
			||||||
        ctx.action.setContext(ctx);
 | 
					        ctx.action.setContext(ctx);
 | 
				
			||||||
        const query = parseQuery(ctx.request.querystring);
 | 
					        const query = parseQuery(ctx.request.querystring);
 | 
				
			||||||
        // 兼容 ctx.params 的处理,之后的版本里会去掉
 | 
					 | 
				
			||||||
        ctx[paramsKey] = {
 | 
					 | 
				
			||||||
          table: params.resourceName,
 | 
					 | 
				
			||||||
          tableKey: params.resourceKey,
 | 
					 | 
				
			||||||
          relatedTable: params.associatedName,
 | 
					 | 
				
			||||||
          relatedKey: params.resourceKey,
 | 
					 | 
				
			||||||
          action: params.actionName,
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        if (pathToRegexp('/resourcer/{:associatedName.}?:resourceName{\\::actionName}').test(ctx.request.path)) {
 | 
					        if (pathToRegexp('/resourcer/{:associatedName.}?:resourceName{\\::actionName}').test(ctx.request.path)) {
 | 
				
			||||||
          await ctx.action.mergeParams({
 | 
					          await ctx.action.mergeParams({
 | 
				
			||||||
            ...query,
 | 
					            ...query,
 | 
				
			||||||
@ -287,7 +327,12 @@ export class Resourcer {
 | 
				
			|||||||
      } catch (error) {
 | 
					      } catch (error) {
 | 
				
			||||||
        return next();
 | 
					        return next();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					    return restApiMiddleware;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  middleware(options: KoaMiddlewareOptions = {}) {
 | 
				
			||||||
 | 
					    return this.restApiMiddleware(options);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user