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]);
});
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', () => {
let resourcer: Resourcer;
let app: Koa;

View File

@ -29,11 +29,51 @@ export interface KoaMiddlewareOptions {
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
@ -127,10 +167,14 @@ export class Resourcer {
protected middlewareHandlers = new Map<string, any>();
protected paramsKey = 'params';
protected middlewares = [];
public readonly options: ResourcerOptions;
constructor(options: ResourcerOptions = {}) {
this.options = options;
}
/**
* resource
*
@ -174,6 +218,14 @@ export class Resourcer {
return this.resources.has(name);
}
registerAction(name: ActionName, handler: HandlerType) {
this.registerActionHandler(name, handler);
}
registerActions(handlers: Handlers) {
this.registerActionHandlers(handlers);
}
/**
* action handlers
*
@ -212,10 +264,6 @@ export class Resourcer {
return this.getResource(name).getAction(action);
}
getParamsKey() {
return this.paramsKey;
}
getMiddlewares() {
return this.middlewares;
}
@ -228,48 +276,40 @@ export class Resourcer {
}
}
middleware(options: KoaMiddlewareOptions = {}) {
const { prefix, accessors, paramsKey = 'params', nameRule = getNameByParams } = options;
return async (ctx: ResourcerContext, next: () => Promise<any>) => {
restApiMiddleware(options: KoaMiddlewareOptions = {}) {
const { prefix, accessors } = options;
const restApiMiddleware = async (ctx: ResourcerContext, next: () => Promise<any>) => {
ctx.resourcer = this;
let params = parseRequest({
path: ctx.request.path,
method: ctx.request.method,
}, {
prefix,
accessors,
prefix: this.options.prefix || prefix,
accessors: this.options.accessors || accessors,
});
if (!params) {
return next();
}
try {
const resource = this.getResource(nameRule(params));
const resource = this.getResource(getNameByParams(params));
// 为关系资源时,暂时需要再执行一遍 parseRequest
if (resource.options.type !== 'single') {
if (resource.options.type && resource.options.type !== 'single') {
params = parseRequest({
path: ctx.request.path,
method: ctx.request.method,
type: resource.options.type,
}, {
prefix,
accessors,
prefix: this.options.prefix || prefix,
accessors: this.options.accessors || accessors,
});
if (!params) {
return next();
}
}
// 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);
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)) {
await ctx.action.mergeParams({
...query,
@ -287,7 +327,12 @@ export class Resourcer {
} catch (error) {
return next();
}
}
};
return restApiMiddleware;
}
middleware(options: KoaMiddlewareOptions = {}) {
return this.restApiMiddleware(options);
}
/**