koa-swagger-decorator 源碼簡(jiǎn)單闡述(草稿)

核心文件
wrapper.ts

  1. 用于依據(jù) decorator 函數(shù)執(zhí)行后得到的數(shù)據(jù)進(jìn)行 router 的自動(dòng)化構(gòu)建,同時(shí)根據(jù) middlewares 函數(shù)的結(jié)果在 router 構(gòu)建時(shí)添加相對(duì)應(yīng)的中間件。
  2. 基于 swaggerObject 構(gòu)建 swagger 文檔

swaggerObject.ts
swagger 文檔可以使用 json 描述, swaggerObject 暴露出一個(gè) SwaggerObject 的實(shí)例,提供添加對(duì)應(yīng)的 swagger 字段的方法供 decorator 使用,并且暴露出 data 字段表示整個(gè) swagger 對(duì)象,用于構(gòu)建 swagger json 文檔

decorators.ts
定義使用的 decorator,如 @request,@summary 等。由于 swagger 文檔的構(gòu)建中,對(duì)個(gè)字段會(huì)有相似的結(jié)構(gòu),如 summary 與 description 的格式相同,所以為了使得 decorator 函數(shù)更加簡(jiǎn)潔,使用curry化的方式優(yōu)化代碼結(jié)構(gòu)。如下

const _desc = (type: string, text: string | any[]) => (target: any, name: string, descriptor: PropertyDescriptor) => {
  descriptor.value[type] = text;
  swaggerObject.add(target, name, { [type]: text });
  return descriptor;
};
const desc = _.curry(_desc);
const description = desc('description');
const summary = desc('summary');
const tags = desc('tags');

這些 decorator 會(huì)需要處理兩件事,一是對(duì)于 swaggerObject 要添加相關(guān)字段內(nèi)容,二是對(duì)于 router 構(gòu)建要添加相關(guān)字段內(nèi)容,如 @request 需要添加 path,method 兩個(gè)字段到綁定的方法中,使得 wapper.js 中可以根據(jù)這些信息構(gòu)建 router

validate/index.ts
validate/check.ts
這兩個(gè)文件用于對(duì) decorator 定義的參數(shù)進(jìn)行校驗(yàn)。關(guān)鍵難點(diǎn)在于對(duì)于 swagger 中 array 和 object 嵌套結(jié)構(gòu)的校驗(yàn),利用遞歸的方式實(shí)現(xiàn)。參考代碼如下,在 cObject 中調(diào)用 check 校驗(yàn)嵌套數(shù)據(jù)。

const check = (input: any, expect: Expect) => {
  const cond = _.cond([
    [_.equals('string'), () => cString(input, expect)],
    [_.equals('boolean'), () => cBool(input, expect)],
    [_.equals('number'), () => cNum(input, expect)],
    [_.equals('object'), () => cObject(input, expect)],
    [_.equals('array'), () => cArray(input, expect)],
    [_.T, () => ({ is: true, val: input })] // 其他類型不做校驗(yàn),直接返回原數(shù)據(jù)
  ]);

  return cond(expect.type);
};


// /**
//  * 對(duì) Object 做檢驗(yàn), 支持嵌套數(shù)據(jù)
// {
//   aaaa: 'hh',
//   bbbb: 'qq',
// }
// { // expect:
//   type: 'object',
//   properties: {
//     aaaa: { type: 'string', example: 'http://www.baidu.com', required: true },
//     bbbb: { type: 'string', example: 'Bob' }
//     c: { type: 'object', properties: {ii: {type: 'string'}, jj: {type: 'number'}} }

//   }
// }
//  */
const cObject = (input: any, expect: Expect = {}) => {
  if (!cRequired(input, expect).is) return { is: false };

  const res = { is: true, val: input };
  if (!is.object(input)) return { is: false };
  if (!expect.properties) return res;

  for (const key of Object.keys(expect.properties)) {
    // ignore empty key if not required
    if (!expect.properties[key].required && input[key] === undefined) {
      continue; // eslint-disable-line
    }
    const { is, val } = check(input[key], expect.properties[key]);
    if (!is) {
      console.log('error object properties:', key); // TODO need to update error debug info
      res.is = false;
      break;
    }
    input[key] = is ? val : input[key];
  }
  return res;
};
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容