<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      利用ast和jscodeshift統(tǒng)計(jì)項(xiàng)目文件中接口重復(fù)使用率

      第一階段:
      由于有的接口最多只有兩層 /xx/xx,所以查找出所有接口截取最后兩層進(jìn)行統(tǒng)計(jì)
      grep -Er 'ur[il]\s*\=|url:|action\=' ./src | awk -F "[\'\`]" '{print $2}'|  grep -Eo "(\/[^\/]+){2}$" |sort | uniq -c | sort -r
      這樣的話有幾個(gè)問(wèn)題:
      1、yy/xx/xx 和 xx/xx/xx會(huì)被統(tǒng)計(jì)成一個(gè)
      2、/xx/xx的GET請(qǐng)求 和 /xx/xx的POST或者其他請(qǐng)求也會(huì)統(tǒng)計(jì)成一個(gè)

      第二階段:
      為了獲得更準(zhǔn)確一點(diǎn)的統(tǒng)計(jì),先通過(guò)jscodeshift對(duì)項(xiàng)目里各種寫(xiě)法的請(qǐng)求進(jìn)行規(guī)整組成完整url
      判斷了項(xiàng)目中的各種請(qǐng)求寫(xiě)法
      jscodeshift庫(kù): https://github.com/facebook/jscodeshift
      ast語(yǔ)法樹(shù)在線解析:https://astexplorer.net/

          const glob = require("glob");
          const fs = require('fs');
          const j = require('jscodeshift');
          const util = require('util');
          const fetch = require('node-fetch');
          const execFile = util.promisify(require('child_process').execFile);
      
          // 解析環(huán)境變量url
          const getSystemEnvs = (fileSource) => {
              const source = j(fileSource);
              let envsObj = {};
              source.find(j.Property, { key: { name: 'defineInProcessEnv' } }).find(j.Property).forEach(f => {
                  let key = f.node.key.name;
                  let value = '';
                  let valueMatch = f.node.value.arguments[0];
                  if (valueMatch.type === 'LogicalExpression') {
                      value = valueMatch.right.value;
                  } else if (valueMatch.type === 'Literal') {
                      value = valueMatch.value;
                  } else {
                      value = '';
                  }
                  envsObj = Object.assign({}, envsObj, { [key]: value });
              })
              return envsObj;
          }
          // 規(guī)整url接口
          const transformApis = (fileSource, envsMap) => {
              const source = j(fileSource);
              let globalBaseUrl = ''; // 全局的前綴
              // 獲取頁(yè)面里定義的全局baseUrl或baseUri前綴變量
              const parseGlobalBaseUrl = source.find(j.VariableDeclaration).find(j.VariableDeclarator, {
                  id: {
                      type: 'Identifier',
                  },
                  init: {
                      type: 'Literal'
                  }
              }).filter((f) => /baseUrl|baseUri|hostStart/i.test(f.node.id.name));
              if (parseGlobalBaseUrl.length) {
                  globalBaseUrl = parseGlobalBaseUrl.get().node.init.value;
              }
              // 判斷是否有方法封裝的
              // const baseUrl = '/wms/internal/xxx/';
              // const sendPostRequestApi = (argObj) => sendPostRequest(argObj, baseUrl);
              const hasFnReWrite = source.find(j.VariableDeclaration).find(j.VariableDeclarator, (f) => f.id.name === 'sendPostRequestApi' && f.init?.body?.callee?.name === 'sendPostRequest' && f.init?.body?.arguments[1]?.name === 'baseUrl').length;
              source.find(j.VariableDeclaration).find(j.VariableDeclarator, {
                  init: {
                      type: 'ArrowFunctionExpression'
                  }
              })
                .forEach((b) => {
                    let method = ''; // 請(qǐng)求方法
                    let preUrl = ''; // 原來(lái)的url地址
                    let prefix = ''; // url前綴
                    // 如果是調(diào)用表達(dá)式類型
                    if (b.node?.init?.body?.type === 'CallExpression') {
                        // 解析請(qǐng)求調(diào)用方法類型 排除tms的
                        const parseMethod = b.node?.init?.body?.callee?.name?.match(/Internal|Post|Get(?=Request)|Put|sendRequest/ig);
                        if (parseMethod) {
                            method = parseMethod[0];
                            // 如果是sendInternalPostRequest internalSendPostRequest 取全局baseUrl|baseUri 前綴是/wms/internal/front
                            if (parseMethod[0] === 'Internal') {
                                prefix = globalBaseUrl || '/wms/internal/front';
                                method = 'POST';
                            } else if (parseMethod[0] === 'sendRequest') {
                                // 如果是sendRequest類型 前綴都是wms/qc
                                prefix = '/wms/qc';
                                method = 'POST';
                            }
                        } else {
                            return false;
                        }
                        // 解析環(huán)境變量 有可能process.env.WWS_XXX、''、/wms/xxx/xxx、baseUrl、baseUri、或者沒(méi)有
                        // 判斷請(qǐng)求方法調(diào)用的第二個(gè)參數(shù)類型 有可能沒(méi)有傳參
                        // console.info('--', b.node.init.body.arguments[1])
                        const secondArgumentsType = b.node.init.body.arguments[1] ? b.node.init.body.arguments[1].type : '';
                        if (secondArgumentsType) {
                            if (secondArgumentsType === 'MemberExpression' || secondArgumentsType === 'ConditionalExpression') {
                                // process.env.XXX_XXX或者M(jìn)OCK_SWITCH ? MOCK_URL + MOCK_HOST +process.env.XXX_XXX : process.env.XXX_XXX類型
                                const parseEnvs = j(b).find(j.MemberExpression, (d) => d.property.name !== 'env');
                                prefix = parseEnvs.length ? `${parseEnvs.get().node.property.name}` : '';
                                prefix = envsMap[prefix];
                            } else if (secondArgumentsType === 'Literal') {
                                // 字符串類型 ''、/wms/xxx/xxx
                                prefix = b.node.init.body.arguments[1].value;
                            } else if (secondArgumentsType === 'Identifier') {
                                // 變量類型 param、baseUrl、baseUri hostStart
                                const varName = b.node.init.body.arguments[1].name;
                                if (/baseUrl|baseUri|hostStart/i.test(varName)) {
                                    prefix = globalBaseUrl;
                                } else if (varName === 'param') {
                                    // 這種寫(xiě)法的經(jīng)查詢都是Internal類型的前綴
                                    prefix = '/wms/internal/front';
                                }
                            }
                        } else {
                            // 沒(méi)有傳路徑變量的 默認(rèn)是/wms/front 如果有方法封裝的話則為全局的url前綴
                            prefix = (hasFnReWrite ? globalBaseUrl : prefix) || '/wms/front';
                        }
                        // 獲取原url和參數(shù)里baseUrl
                        const firstArgumentsType = b.node.init.body.arguments[0] ? b.node.init.body.arguments[0].type : '';
                        if (firstArgumentsType === 'ObjectExpression') {
                            j(b).find(j.Property, { value: { type: 'Literal' } }).forEach((c) => {
                                if (c.node.key.name === 'url') {
                                    preUrl = c.node.value.value;
                                } else if (c.node.key.name === 'baseUrl') {
                                    prefix = c.node.value.value;
                                }
                            });
                            j(b).find(j.Property, { key: { name: 'url' } }).forEach((e) => {
                                e.node.value.value = `${prefix}${preUrl}_${method.toUpperCase()}`;
                            });
                        } else if (firstArgumentsType === 'Literal') {
                            // 這種寫(xiě)法的經(jīng)查詢都是Internal類型的前綴
                            preUrl = b.node.init.body.arguments[0].value || '';
                            // 構(gòu)造成一個(gè){url:'xxx'}對(duì)象節(jié)點(diǎn)后面好匹配
                            j(b).find('Literal').replaceWith(j.objectExpression([
                                j.property(
                                  'init',
                                  j.identifier('url'),
                                  j.literal(`${prefix}${preUrl}_${method.toUpperCase()}`),
                                ),
                            ]));
                        }
                    } else if (b.node?.init?.body?.type === 'BlockStatement') {
                        // 如果是個(gè)代碼塊
                        const findHasUrlOrUri = j(b).find(j.VariableDeclarator, (j) => /url|uri/i.test(j.id.name));
                        findHasUrlOrUri.find(j.TemplateLiteral).forEach((f) => {
                            // 如果url uri是一個(gè)模板字符串說(shuō)明路徑可能含有環(huán)境變量或者其他路徑變量
                            const parseEnvs = j(f).find(j.MemberExpression, (d) => d.property.name !== 'env')
                            // 沒(méi)有環(huán)境變量的尾部路徑
                            let urlTail;
                            const parseUrlTail = j(f).find(j.TemplateElement, (k) => {
                                urlTail = k.value.cooked;
                                return urlTail !== '';
                            });
                            if (parseEnvs.length) {
                                if (urlTail) {
                                    findHasUrlOrUri.find(j.TemplateLiteral).replaceWith(j.identifier(`'${envsMap[parseEnvs.get().node.property.name]}${urlTail}_POST'`));
                                }
                            }
                            j(f).find(j.Identifier, ((m) => {
                                if (/baseUrl|baseUri/i.test(m.name) && urlTail) {
                                    findHasUrlOrUri.find(j.TemplateLiteral).replaceWith(j.identifier(`'${globalBaseUrl}${urlTail}_POST'`));
                                }
                            }));
                            // 如果沒(méi)有變量只是因?yàn)橛昧朔匆?hào)
                            findHasUrlOrUri.find(j.TemplateLiteral).replaceWith(j.identifier(`'${urlTail}_POST'`));
                        });
                        // 如果方法塊里的url|uri是字符串只是在后面加個(gè)請(qǐng)求類型
                        findHasUrlOrUri.find(j.Literal).forEach((f) => {
                            f.node.value = `${f.node.value}_POST`;
                        });
                    }
                });
              // 操作記錄的url規(guī)整
              source.find(j.JSXAttribute, {name: {name: 'url'}}).forEach(f => {
                  if (f.node.value.type === 'Literal') {
                      f.node.value.value = `${f.node.value.value}_POST`
                  }
              })
              // upload請(qǐng)求url規(guī)整
              source.find(j.JSXAttribute, {name: {name: 'action'}}).forEach(f => {
                  if (f.node?.value?.type === 'Literal') {
                      j(f.node).find(j.Literal).replaceWith(j.literal(`${f.node.value.value}_POST`))
                  }
                  if (f.node?.value?.type === 'JSXExpressionContainer') {
                      const jsxExpressionContainer = j(f).find(j.JSXExpressionContainer)
                      if (f.node?.value?.expression?.name === 'uploadUrl') {
                          jsxExpressionContainer && jsxExpressionContainer.replaceWith(j.literal(`${globalBaseUrl}_POST`))
                      }
                      if (j(f).find(j.TemplateElement).length > 1) {
                          const parseEnvs = j(f).find(j.MemberExpression, (d) => d.property.name !== 'env')
                          let prefix = '';
                          let urlTail = '';
                          if (parseEnvs.length) {
                              prefix = parseEnvs.get().node.property.name
                              prefix = envsMap[prefix];
                          }
                          const parseUrlTail = j(f).find(j.TemplateElement, (k) => {
                              urlTail = k.value.cooked
                              return urlTail !== '';
                          })
                          jsxExpressionContainer && jsxExpressionContainer.replaceWith(j.literal(`${prefix}${urlTail}_POST`))
                      }
                  }
              })
              return source.toSource({
                  quote: 'single',
              });
          };
          const projectDir = process.argv.slice(2)[0];
          const project = projectDir.match(/\/([^\/]+)$/)[1];
          const legorcSource = fs.readFileSync(`${projectDir}/.legorc.ts`);
          const envsMap = getSystemEnvs(legorcSource.toString()) || {};
          // 遍歷文件規(guī)整url接口
          glob(`${projectDir}/src/**/*.js{,x}`, function (er, files) {
              for (let i = 0; i < files.length; i += 1) {
                  const uri = files[i];
                  const fileSource = fs.readFileSync(uri);
                  const newData = transformApis(fileSource.toString(), envsMap);
                  if (newData) {
                      fs.writeFileSync(uri, newData);
                  }
              }
              // 規(guī)整完成調(diào)用shell進(jìn)行統(tǒng)計(jì)和群消息通知
              execFile('bash', ['./api_analyse.sh', `${projectDir}/src`], (error, stdout, stderr) => {
                  if (error) {
                      return console.error(error);
                  }
                  const content = `# ${project}項(xiàng)目中接口重復(fù)使用>=5次的統(tǒng)計(jì)
      * 時(shí)間:${new Date().toLocaleString()}
      * ${stdout}`;
                  // console.info(content)
                  
              })
          })
      
      
      

      通過(guò)下面的sh會(huì)調(diào)用上面的js進(jìn)行url規(guī)整,當(dāng)上面的js運(yùn)行完畢會(huì)調(diào)用下面的sh進(jìn)行統(tǒng)計(jì)

      #! /bin/bash
      sys_arr=('/tmp/xxx' '/tmp/yyy');
      if [ -z $1 ]
        then
          for s in "${sys_arr[@]}"; do
           if [ -d $s ];then
             cd $s;
             git reset --hard;
             git checkout master;
             git pull;
             cd /www;
             node 'api_analyse.js' $s;
           fi;
          done;
        else
          grep -Er 'ur[il]\s*\=|url:|action\=' "$1" | awk -F [\'\`\"] '{print $2}' | grep -E '.+_(POST|GET|PUT)' |sort | uniq -c | sort -r | awk '$1>=5{print $0}'
      fi;
      

        

      結(jié)果預(yù)覽:

       

      posted @ 2022-07-01 21:50  韭菜茄子  閱讀(118)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 摸丰满大乳奶水www免费| 亚洲欧洲色图片网站| 无码人妻斩一区二区三区| 精品国产一区二区三区av性色| 国产精品免费久久久免费| 美女一级毛片无遮挡内谢| 人妻少妇精品系列一区二区| 亚洲欧美自偷自拍视频图片| 亚洲女同精品久久女同| 在线观看热码亚洲av每日更新| 四虎国产精品久久免费地址| 久久国产精品成人影院| 欧美老少配性行为| 天堂…中文在线最新版在线| 国产精品亚洲二区在线看| 国产在线午夜不卡精品影院| 秋霞鲁丝片成人无码| 美欧日韩一区二区三区视频| 亚洲第一区二区快射影院| 久久精品女人天堂av免费观看| 青海省| 国产精品美女久久久久久麻豆| 国产成人高清亚洲综合| 亚洲AV无码成H人动漫无遮挡| 久久人人97超碰精品| 好姑娘6电影在线观看| 永久不封国产av毛片| 丰满熟妇人妻中文字幕| 熟女蜜臀av麻豆一区二区| 性男女做视频观看网站| 国产成人精彩在线视频| 午夜福利激情一区二区三区| 精品国产成人国产在线视| 欧美人与动牲交a免费| 长丰县| 亚洲精品香蕉一区二区| 中文字幕日韩精品亚洲一区| 在线中文字幕第一页| 激情综合网激情五月我去也| 亚洲人成网站在线在线观看| 国产精品永久免费成人av|