本周关于自动将后台接口文档(OpenAPI 文档)翻译成 JS 代码的工作进行了第一个迭代的开发,完成了基于 axios 的初步版本,同时,使用百家饭上面的公开 API(浙里办SSO API)生成了示例代码,模板和示例已经上传到了 gitee 的开源仓库,详情点击查看
生成逻辑说明
主要的生成逻辑如下:
入口脚本
index.js 存储了类库的入口代码,示例生成内容如下:
const axios = require("axios");
const config = require("./config.js");
const instance = axios.create(config);
const sso_servlet_organduser = require("./api-sso_servlet_organduser.js");
sso_servlet_organduser.injure(instance);
module.exports = instance;
复制代码
主要内容就是生成 axios 的 instance,并将 instance 传给每个 path 的生成代码,进行函数的注入,最后作为统一的对象 export,这样,使用方就可以直接 require 这个库,进行使用,使用示例如下:
const axios = require("./axios");
axios.getSsoServletOrganduser().then(res=>{
console.log(res);
}).catch(err=>{
console.log(err);
})
复制代码
全局配置脚本
config.js 存储全局的配置信息,包括服务器选择和参数设置,示例生成内容如下:
module.exports = {
// 认证服务
baseURL: 'https://puser.zjzwfw.gov.cn/',
// 打开下一行,修改请求超时时间,当前例子为10s
// timeout: 10 * 1000
}
复制代码
在考虑代码生成的同时,在生成接口地址的地方,同时使用 API 文档中的地址描述信息生成了对应地址的描述,作为注释加到了地址的前方,方便用户在后期开发中进行选择和修改。
接口脚本
针对接口中定义的每一个接口,会自动生成对应的一个接口 js 文件,以 api-xxx 命名,示例内容如下:
const { verify, timestr,md5 } = require("./functions.js");
const injure = (instance)=>{
var config = {params:{}};
// 路径:sso/servlet/organduser, 调用方法GET
//params要求传输以下属性,没有标注'有默认值'的参数由调用方传输
//-method(有默认值):调用方法
//-servicecode:接入资源在SSO注册成功后的业务代码,由【SSO管理员】提供。
//-time(有默认值):时间戳,当前时间 年月日时分秒 例:2009年10月10日 12时12分12秒格式为20091010121212
//-sign(有默认值):MD5(servicecode+servicepwd+time),将业务代码、业务密钥、发送时间按顺序连接并进行md5加密。注:1、参数servicepwd由【SSO管理员】提供;2、MD5算法是标准算法,可使用java内部实现;3、MD5后的值为32位并且小写。
//-userid:用户在SSO的身份唯一标示
//-datatype(有默认值):数据格式 xml json。默认xml
//-servicepwd:分配的密码,注意,该参数仅用于sign计算
instance.getSsoServletOrganduser = (params = {}) => {
var verify_err = null ||
verify(params.servicecode,"servicecode",{"required":true}) ||
verify(params.userid,"userid",{"required":true}) ||
verify(params.servicepwd,"servicepwd",{"required":true});
if ( verify_err !=null){
return verify_err;
}
var defaultParam = {
datatype: "json",
method: "getUserInfoById",
};
params = Object.assign(defaultParam,params);
if (params.time == undefined){
params.time= timestr("YYYYMMDDHHmmss");
}
if (params.sign == undefined){
params.sign= md5(params.servicecode+params.servicepwd+params.time);
}
return instance.get("sso/servlet/organduser",{params});
}
}
module.exports = {
injure
}
复制代码
如果接口定义了 get 方法,则文件会在传入的 axios instance 中注入 getXxx 的方法,如果是 post 则为 postXxx,其他方法类推。
该方法包括以下部分:
入参校验,对接口定义中定义为必传,但是不包含默认值的参数进行判断,如果检查有问题,直接返回 reject 的 Promise。
默认值填充,对接口定义中包含了默认值,且默认值不是可计算属性的参数,构建一个默认参数对象,与传入参数进行合并。
对没有传入数值,但是参数定义中,定义为计算属性(就是默认值以‘=’开头的属性,例如timestr("YYYYMMDDHHmmss")
),将计算表达式翻译成实际 js 代码。
调用 axios 的原始函数,如 get,post 等。
辅助函数
生成结果中另包含辅助的支撑计算属性的函数,目前包括 md5 和 timestr 两个函数,以及校验参数使用的 verify 函数。
const dayjs = require("dayjs");
const md5 = require("md5");
module.exports = {
timestr: (fmt) => {
return dayjs().format(fmt);
},
md5: (str) => {
return md5(str);
},
verify: (par, name, option) =>{
if (option.required && par == undefined){
return Promise.reject("参数"+name+"要求必传,但未传入");
}
}
}
复制代码
进展说明
综合本周的情况,初步的 js 调用生成有了一个雏形,如果有希望试用的同学注意以下没有实现或者没有测试的部分:
1)post 请求的调用生成
2)对 openapi 定义的正则表达式等输入验证方式没有实现
欢迎试用,提供您宝贵的意见
API 各式各样,完全的覆盖各类需求,需要一个逐步完善的过程,我们希望获得您的建议、吐槽,以及各种需求,可以在csdn社区里发帖或者在gitee.com里提交 issue,多谢,该部分功能将在周边完善后开放试用,敬请期待。
评论