swagger2ts-gen-cli
Version:
swagger2ts-gen-cli 是一个根据后端服务的 swagger-api 生成客户端代码的 Cli 工具。
2 lines (1 loc) • 6.08 kB
JavaScript
import e from"chalk";import t from"ora";import r from"axios";import n from"js-yaml";import a from"fs-extra";import o from"path";import{rimraf as i}from"rimraf";import s from"adm-zip";const c=async r=>{const n=t("读取参数中... \n").start();if(console.log(`\n ${e.blue("--url:")} ${e.green(r.url)} ${e.red(typeof r.url)} \n\n ${e.blue("--convert:")} ${e.green(r.convert)} ${e.red(typeof r.convert)} \n\n ${e.blue("--client_type:")} ${e.green(r.client_type)} ${e.red(typeof r.client_type)} \n\n ${e.blue("--output_path:")} ${e.green(r.output_dir)} ${e.red(typeof r.output_dir)} \n\n ${e.blue("--clean:")} ${e.green(r.clean)} ${e.red(typeof r.clean)} \n\n `),!(r.url||r.url.includes("swagger-config")||r.url.includes("swagger-resources")||r.url.includes("api-docs")))throw n.fail("读取参数失败 \n"),new Error('请添加 "--url" 参数,并检查是否为后端的 swagger-config 或 swagger-resources 或 api-docs 的路径');return n.succeed("读取参数成功 \n"),process.env.NODE_TLS_REJECT_UNAUTHORIZED="0",r};const p=async e=>{const n=t("读取 api-docs 数据中... \n").start();let a=[];try{n.info("不要担心, 为了发起https请求到“https://generator.swagger.io”,代码中设置了 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'");const t=new URL(e.url).origin,o=[];if(e.url.indexOf("swagger-config")>-1){const n=(await r.get(e.url)).data;n.urls?.forEach((e=>{o.push({name:e.serviceName??e.name,url:`${t}${e.url}`})}))}else if(e.url.indexOf("swagger-resources")>-1){const n=(await r.get(e.url)).data;n?.forEach((e=>{o.push({name:e.name,url:`${t}${e.url}`})}))}else e.url.indexOf("api-docs")>-1&&o.push({name:"generated-api",url:e.url});a=await Promise.all(o.map((e=>new Promise((async t=>{let a;try{a=(await r.get(e.url))?.data}catch(e){}if(!a||500===a.code)return n.warn(e.name+":api-doc数据获取失败"),void t(void 0);const o=function(e){e?.definitions&&Reflect.ownKeys(e?.definitions).forEach((t=>{t.toString().startsWith("Map")&&Reflect.deleteProperty(e.definitions,t),t.toString().startsWith("JSONObject")&&Reflect.deleteProperty(e.definitions,t)}));return e}(a),i=function(e){if(!e)return!1;const t=e.swagger||e.openapi||"2.0";return 3===Number(t.trimStart().split(".")[0])}(o),s=JSON.stringify(o),c=e.name;n.succeed(e.name+":api-doc数据获取成功"),t({name:c,isOAS3:i,originJson:s})})))))}catch(e){throw n.fail("读取 api-docs 数据失败 \n"),a=[],e}return{...e,apiDatas:a}},l=async e=>{const a=t("数据处理中... \n").start();let o=[];try{o=await Promise.all(e.apiDatas.map((t=>new Promise((async a=>{if(!t)return void a(void 0);const o=n.dump(n.load(t.originJson),{lineWidth:-1});let i={},s=t.isOAS3;const c=e.client_type;if(!s&&e.convert){const e=await r.post("https://converter.swagger.io/api/convert",o,{headers:{"Content-Type":"application/yaml",Accept:"application/yaml"}});i=n.load(e.data),s=!0}else i=n.load(o);let p=[];if(p=(await r.get(s?"https://generator3.swagger.io/api/clients":"https://generator.swagger.io/api/gen/clients")).data,-1==p.findIndex((e=>e==c)))throw new Error("client_type 参数有误, 无法生成相应类型的文件");a({...t,isOAS3:s,spec:i,lang:c,type:"CLIENT"})}))))),a.succeed("数据处理成功 \n")}catch(e){throw a.fail("数据处理失败 \n"),o=[],e}return{...e,apiDocs:o}},g=async e=>{const r=t("文件生成中... \n").start();let n=[];try{n=await Promise.all(e.apiDocs.map((t=>new Promise((async n=>{if(!t)return void n(void 0);const s=await u(e,t);if(200!=s?.status)return r.warn(t.name+":文件下载失败,"+s?.data),void n(void 0);i.rimrafSync(`${e.output_dir}/${t.name}`);const c=await((e,t="./")=>new Promise(((r,n)=>{const i=e.headers["content-disposition"]??e.headers["Content-Disposition"],s=i?.split("=")[1]?.replace(/"/g,"")||(new Date).getTime().toString(),c=o.resolve(t,s);a.ensureDirSync(o.dirname(c));const p=a.createWriteStream(c);e.data.pipe(p),p.on("close",(()=>{r(c)})).on("error",(e=>{n(e)}))})))(s,`${e.output_dir}/${t.name}`);await d(c,o.resolve(`${e.output_dir}/${t.name}`),Boolean(e.clean)),r.info(t.name+":文件下载成功"),n(c)})))))}catch(e){throw r.fail("文件生成失败 \n"),n=[],e}return{...e,filePaths:n}},u=async(e,t)=>{if(t.isOAS3)try{return await r.post("https://generator3.swagger.io/api/generate",{lang:t.lang,spec:t.spec,type:t.type},{responseType:"stream"})}catch(e){return{data:e}}else try{const n=await r.post("https://generator.swagger.io/api/gen/clients/"+e.client_type,{spec:t.spec});if(n.data.link){return await r.get(n.data.link,{responseType:"stream"})}}catch(e){return{data:e}}},d=async(e,t,r)=>new Promise(((n,c)=>{try{new s(e).getEntries().forEach((e=>{if(!/\/$/.test(e.entryName)){a.ensureDirSync(o.dirname(`${t}/${e.entryName}`));const r=e.getData();a.writeFileSync(`${t}/${e.entryName}`,r)}})),r&&(i.moveRemoveSync(t+"/.swagger-codegen"),i.moveRemoveSync(t+"/.gitignore"),i.moveRemoveSync(t+"/.npmignore"),i.moveRemoveSync(t+"/package.json"),i.moveRemoveSync(t+"/.swagger-codegen-ignore"),i.moveRemoveSync(t+"/git_push.sh")),n()}catch(e){return void c(e)}})),m=async t=>{(function(...e){if(0===e.length)throw new Error("Expected at least one argument");return async t=>{let r=t;for(const t of e)r=await t(r);return r}})(c,p,l,g)(t).then((()=>{console.log(e.green("Success!"))})).catch((t=>{console.log(e.red("Error!")),console.error(e.red(t))}))},f=e=>{e.command("gen").description("根据后端服务的 swagger-api 生成客户端代码").option("-url, --url <url>","swagger-config 或 swagger-resources 或 api-docs 的路径, 例如: http://xxx.xxx.xxx.xxx:xxxx/v3/api-docs/swagger-config 或 http://xxx.xxx.xxx.xxx:xxxx/swagger-resources 或 http://xxx.xxx.xxx.xxx:xxxx/api/auth/v3/api-docs").option("-c, --convert","是否需要转换为 openApi3.0 标准",!1).option("-ct, --client_type [client_type]","要生成的客户端代码文件类型","typescript-axios").option("-o, --output_dir [output_dir]","生成客户端代码文件后存放的位置","./swagger2ts-gen").option("-clean, --clean","是否清理解压后的无效文件",!1).action((async e=>{m(e)}))};export{m as a,f as g};