feat: improve rest api middleware

This commit is contained in:
chenos 2021-09-09 12:48:01 +08:00
parent 5847c9eeab
commit edbe1ecb67
2 changed files with 73 additions and 54 deletions

View File

@ -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;

View File

@ -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);
} }
/** /**