这里是引用
cli.js
javascript">#!/usr/bin/env node
const path = require('path');
const fs = require('fs');
const chalk = require("chalk");
const figlet = require("figlet");
const { program } = require('commander');
const swagger = require('./swagger.js');
let config = {};
// 配置文件如果存在则读取
if (fs.existsSync(path.resolve('DevSpeed.config.js'))) {
config = require(path.resolve('DevSpeed.config.js'));
} else {
fs.writeFileSync(path.resolve('DevSpeed.config.js'), `module.exports = {
"swaggerPath": ""
}`, function (error) {
console.log(error);
})
}
console.log(
chalk.yellow(
figlet.textSync("DevSpeed", {
font: "Slant",
horizontalLayout: "default",
verticalLayout: "default"
})
)
);
program.version('1.0.0', '-v, --version')
program
.command('swagger')
.description('拉取 Swagger 地址')
.action(function (module) {
swagger(config, module)
});
program.parse(process.argv);
swagger.js
javascript">const inquirer = require("inquirer");
const chalk = require("chalk");
const figlet = require("figlet");
const shell = require("shelljs");
const request = require('request')
const path = require('path');
const fs = require('fs');
const format = require('./format')
const js_beautify = require('js-beautify').js; // also available under "js" export
const css_beautify = require('js-beautify').css;
const html_beautify = require('js-beautify').html;
const CLI = require('clui');
const Spinner = CLI.Spinner;
/**
* cli 模块选择事件
*
* @param {*} list
* @return {*}
*/
const askQuestions = (list) => {
list.unshift('全部');
const questions = [{
type: "list",
name: "_index",
message: "请选择需要更新的模块",
choices: list,
filter: function (val) {
var _index = list.indexOf(val);
return _index;
}
}];
return inquirer.prompt(questions);
};
/**
* GET 接口请求
*
* @param {*} url
* @return {*}
*/
const _$request = function (url) {
var countdown = new Spinner('请稍等...', ['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷']);
countdown.start();
return new Promise((resolve, rejected) => {
request({
url: url
}, function (error, response, body) {
countdown.stop();
if (!error && response.statusCode == 200) {
try {
var _json = JSON.parse(body);
resolve(_json)
} catch (error) {
resolve(body)
}
} else {
console.log(chalk.red('服务器链接失败\n'), chalk.red(error));
}
});
});
};
const getDoc = async (url) => {
let reg = /configObject\s+=\s+JSON\.parse\((.+?)\)/;
let IP = url.split('/')[2];
// this.IP = 'http://' + IP;
const body = await _$request(url);
let configObject;
body.replace(reg, function ($i) {
eval($i);
});
let requireArray = [];
for (let i = 0; i < configObject.urls.length; i++) {
const element = configObject.urls[i];
element.url = 'http://' + IP + element.url;
var _name = element.url.split('/')[5];
if (_name) {
// console.log(_name);
_name = path.extname(_name).replace('.', '').replace('Controller', '')
}
element.key = _name;
requireArray.push(element);
// requireArray.push(axios.get(this.IP + element.url).then(res => res.data));
}
return requireArray
};
/**
* 格式化树形结构
*
* @param {*} ele
* @return {*}
*/
const SingleObjectFormat = function (ele) {
var folder = {};
// folder.id = this.guid();
folder.title = ele.info.title;
// console.log(folder.title);
folder.children = [];
folder.models = {};
folder.Schemas = {};
var _models = ele.components.schemas;
for (const key in _models) {
const element = _models[key];
folder.Schemas[key] = element;
folder.models['#/components/schemas/' + key] = format.Models(element, key);
};
for (const url in ele.paths) {
const method = ele.paths[url];
for (const type in method) {
const _file = method[type];
var file = {};
// file.id = this.guid();
file.title = _file.summary;
file.url = url;
file.type = type;
file.key = _file.tags[0];
file.query = _file.parameters;
_file.requestBody && (() => {
file.body = {};
for (const key in _file.requestBody.content) {
const element = _file.requestBody.content[key];
if (key != 'application/*+json' && key != 'text/json' && key != 'application/json-patch+json') {
file.body[key] = format.Models(element.schema, key);
}
}
})();
// file.parent = folder.id;
_file.responses && (function () {
if (!_file.responses) {
return;
}
if (!_file.responses['200']) {
return;
}
if (!_file.responses['200'].content) {
return;
}
if (!_file.responses['200'].content['application/json']) {
return;
}
if (!_file.responses['200'].content['application/json'].schema) {
return;
}
file.responses = format.Models(_file.responses['200'].content['application/json'].schema, '200');
})();
folder.children.push(file);
};
};
return folder;
};
const looks_like_html = (source) => {
var trimmed = source.replace(/^[ \t\n\r]+/, '');
return trimmed && (trimmed.substring(0, 1) === '<');
};
const beautify = (source) => {
var output, opts = {};
opts.indent_char = ' ';
opts.preserve_newlines = "-1";
if (looks_like_html(source)) {
output = html_beautify(source, opts);
} else {
output = js_beautify(source, opts);
};
return output;
};
const renderSingleFile = (folder, config) => {
var key = '';
var folderStrArray = [];
var _nameKeys = [];
folder.children.forEach(child => {
var $name = child.url.split('/')[3];
key = child.key;
if (_nameKeys.includes($name)) {
$name += '_' + child.type;
};
if (child.responses) {
try {
var _String = format.String(child.responses, folder.models);
var _responses = '* // 返回值数据模型 \n' + 'var responsesData = ' + beautify(_String) + '\n';
} catch (error) {
var _responses = '';
}
};
var _bodyStr = '';
for (const key in child.body) {
const element = child.body[key];
var _String = format.String(element, folder.models);
_bodyStr += '* // Body参数 -- 类型 : ' + key + '\n';
_bodyStr += 'var bodyData = ' + beautify(_String);
}
const renderAnnotation = item => ' // ' + item.annotate + ' (' + item.type + ') ' + (item.checked ? '必填' : '') + '\n';
var _queryString = '';
var _queryArray = [];
if (child.query) {
child.query.forEach(ele => {
var _data = {};
_data.key = ele.name;
_data.type = ele.schema.type;
_data.annotate = ele.description || '';
_data.checked = !ele.nullable;
_queryArray.push(_data);
});
if (_queryArray.length) {
_queryString = '{'
for (let i = 0; i < _queryArray.length; i++) {
var item = _queryArray[i];
if (item.type == 'object') {
_queryString += (item.key + ': {},' + renderAnnotation(item));
} else {
_queryString += ((item.key ? item.key : '\'\'') + ':' + '\'\',' + renderAnnotation(item));
}
};
_queryString += '}'
_queryString = beautify(_queryString);
_queryString = '* // url 参数 \n' + 'var query =' + _queryString;
}
}
// console.log(_queryString.replace(/\n/g, '\n \t* '));
var str = `
/**
* ${child.title || child.url}
*
${_queryString ? '* @param {Object} parmas Url参数' : ''}
${_bodyStr ? '* @param {Object} options Body参数' : ''}
* @return {Promise} 接口异步传输对象
* @example
${_queryString && _queryString.replace(/\n/g, '\n\t* ')}
${_bodyStr && _bodyStr.replace(/\n/g, '\n\t* ')}
${_responses && _responses.replace(/\n/g, '\n\t* ')}
*/
'${$name}': function (${_queryString ? 'parmas' : ''}${_bodyStr ? (_queryString ? ', options' : 'options') : ''}) {
return request.${child.type}('${child.url}', ${_queryString ? 'parmas, ' : '{}, '}${_bodyStr ? 'options, ' : '{}, '}'pro')
},
`;
folderStrArray.push(str);
});
var _str = config.formatModuleString || `import request from './request.js'\n`;
_str += `\n\n// ${folder.title}\n`;
_str += `export default {\n`;
folderStrArray.forEach(ele => {
_str += '\t' + ele;
})
_str += '};';
return {
key: key,
str: _str,
}
};
const askFileExist = (fileName) => {
const questions = [{
type: "list",
name: "isHave",
message: fileName + "文件已经存在,是否覆盖?",
choices: ['是', '否'],
filter: function (val) {
return val == '是';
}
}];
return inquirer.prompt(questions);
};
const writeFile = function (filePath, content) {
fs.writeFile(path.resolve(filePath), content, 'utf8', function (err) {
if (err) {
console.log(chalk.red(err));
} else {
console.log(chalk.greenBright(filePath + ' : 输出成功!'));
}
});
};
const exportsFile = async function (options, config, ignore) {
var folder = SingleObjectFormat(options);
var fileObject = renderSingleFile(folder, config);
var filePath = config.apiPath + '/' + fileObject.key + '.js';
// var stat = fs.existsSync(path.resolve(filePath));
writeFile(filePath, fileObject.str);
// if (!stat || ignore) {
// } else {
// var ans = await askFileExist(fileObject.key + '.js');
// if (ans.isHave) {
// writeFile(filePath, fileObject.str);
// } else {
// console.log(chalk.red(filePath + '.js : 已经跳过'));
// };
// }
};
/**
* 初始化 Swagger 文档接口
*
* @param {配置文件地址} config
* @param {*} module
* @return {*}
*/
const initSwagger = async (config) => {
console.log(chalk.greenBright('\nSwagger 接口工具\n'));
if (!config.swaggerPath) {
console.log(chalk.red('请配置 swagger文档地址 : DevSpeed.config.js => swaggerPath'));
return;
};
if (!config.apiPath) {
console.log(chalk.red('请配置 api文件夹位置 : DevSpeed.config.js => apiPath'));
return;
};
var stat = fs.existsSync(path.resolve(config.apiPath));
if (!stat) {
console.log(chalk.red('请检查 api 文件夹位置 : DevSpeed.config.js => apiPath'));
return;
}
let DocPath = config.swaggerPath;
const Doclist = await getDoc(DocPath);
var QuestionsList = [];
Doclist.forEach(ele => {
QuestionsList.push(ele.name + '(' + chalk.yellow(ele.key) + ')');
})
const answers = await askQuestions(QuestionsList);
if (answers._index == 0) {
var requestList = [];
Doclist.forEach(ele => {
requestList.push(_$request(ele.url));
})
var allDoc = await Promise.all(requestList);
// console.log(allDoc);
allDoc.forEach(ele => {
exportsFile(ele, config);
})
} else {
var selectDoc = Doclist[answers._index - 1];
var wrihteDoc = await _$request(selectDoc.url);
exportsFile(wrihteDoc, config);
};
};
module.exports = initSwagger
format.js
javascript">const formatModelsObject = function (properties, $ref) {
if (!properties && $ref) {
return $ref;
}
var itemArray = [];
for (const key in properties) {
const keyItem = properties[key];
var _obj = formatBase(keyItem, key);
if (_obj.type == 'array') {
_obj.type = 'array';
_obj.itemArray = formatModelsArray(keyItem.items);
};
if (_obj.type == 'object') {
_obj.type = 'object';
if (keyItem.additionalProperties) {
_obj.itemArray = [formatDict(keyItem.additionalProperties)];
} else {
_obj.itemArray = formatModelsObject(keyItem.properties, keyItem.$ref);
};
};
itemArray.push(_obj);
};
return itemArray;
};
const formatDict = function (additionalProperties) {
var model = formatBase(additionalProperties, '\'<*>\'');
if (additionalProperties.type == 'object' || !additionalProperties.type) {
model.itemArray = formatModelsObject(additionalProperties.properties, additionalProperties.$ref);
} else if (additionalProperties.type == 'array') {
model.itemArray = formatModelsArray(additionalProperties.items)
}
return model;
}
const formatModelsArray = function (ModelsArray) {
if (ModelsArray.type == 'object') {
return formatModelsObject(ModelsArray.properties, ModelsArray.$ref);
} else if (ModelsArray.type == 'array') {
return formatModelsArray(ModelsArray.items)
} else if (ModelsArray.$ref) {
return ModelsArray.$ref;
} else {
return formatBase(ModelsArray);
}
};
const formatBase = function (ModelsSchemas, key) {
var model = {};
model.name = ModelsSchemas.description || model.key;
model.key = key;
model.type = ModelsSchemas.type || 'object';
model.checked = !ModelsSchemas.nullable;
model.itemArray = [];
ModelsSchemas.enum && (model.enum = ModelsSchemas.enum);
ModelsSchemas.format && (model.format = ModelsSchemas.format);
ModelsSchemas.readOnly && (model.readOnly = ModelsSchemas.readOnly);
ModelsSchemas.default && (model.default = ModelsSchemas.default);
ModelsSchemas.writeOnly && (model.writeOnly = ModelsSchemas.writeOnly);
return model;
};
const formatModels = function (ModelsSchemas, key) {
var model = formatBase(ModelsSchemas, key)
if (ModelsSchemas.type == 'object' || !ModelsSchemas.type) {
model.itemArray = formatModelsObject(ModelsSchemas.properties, ModelsSchemas.$ref);
} else if (ModelsSchemas.type == 'array') {
model.itemArray = formatModelsArray(ModelsSchemas.items)
}
return model;
}
const renderAnnotation = (item, key) => ' // ' + (item.annotate || item.name || '') + (key ? ' ' + key : '') + ' (' + (item.format || item.type) + ') ' + (item.checked ? '必填' : '') + (item.enum ? ' 备选值 :' + JSON.stringify(item.enum) : '') + '\n';
const formatArrayString = function (Schemas, model) {
var _array = [];
_array.push('[' + renderAnnotation(Schemas));
var _model = Schemas;
if (typeof Schemas.itemArray == 'string') {
if (Schemas.itemArray.indexOf('#/components/schemas/') != -1 && text.test(Schemas.itemArray)) {
var _key = Schemas.itemArray.replace('List<', '').replace('>', '');
model[_key] && (_model = model[_key]);
} else if (Schemas.itemArray.indexOf('#/components/schemas/') != -1 && model[Schemas.itemArray]) {
_model = model[Schemas.itemArray];
};
};
if (_model.type == 'object') {
if (_model.itemArray) {
for (let i = 0; i < _model.itemArray.length; i++) {
const element = _model.itemArray[i];
if (element.itemArray == Schemas.itemArray) {
element.itemArray = [];
}
}
}
_array.push(formatObjectString(_model, model));
} else if (_model.type == 'array' && _model.itemArray.length) {
_array.push(formatArrayString(_model.itemArray, model));
} else if (_model.type == 'array' && _model.itemArray.length == 0) {
_array.push('');
} else {
for (let i = 0; i < _model.itemArray.length; i++) {
let element = _model.itemArray[i];
_array.push('\'\'' + renderAnnotation(element));
if (i != _model.itemArray.length - 1) {
_array.push(',\n')
};
}
};
_array.push(']\n');
return _array.join('');
}
var text = /^List\<.*\>$/
const formatObjectString = function (Schemas, model) {
var _array = [];
if (typeof Schemas.itemArray == 'string') {
// console.log(model);
// 验证这是一个数组类型
if (Schemas.itemArray.indexOf('#/components/schemas/') != -1 && text.test(Schemas.itemArray)) {
var _key = Schemas.itemArray.replace('List<', '').replace('>', '');
model[_key] && (Schemas = model[_key]);
} else if (Schemas.itemArray.indexOf('#/components/schemas/') != -1 && model[Schemas.itemArray]) {
Schemas = model[Schemas.itemArray];
};
};
if (Schemas.type != 'array' && Schemas.type != 'object') {
_array.push('\'\'' + renderAnnotation(Schemas));
} else {
_array.push('{' + renderAnnotation(Schemas, Schemas.key));
for (let i = 0; i < Schemas.itemArray.length; i++) {
const element = Schemas.itemArray[i];
if (element.type == 'object') {
_array.push(element.key + ':' + formatObjectString(element, model));
if (i != Schemas.itemArray.length - 1) {
_array.push(',\n')
};
} else if (element.type == 'array') {
_array.push(element.key + ':' + formatArrayString(element, model));
if (i != Schemas.itemArray.length - 1) {
_array.push(',\n')
};
} else {
_array.push(element.key + ': \'\' ,' + renderAnnotation(element));
}
}
_array.push('}\n');
}
return _array.join('');
}
const formatString = function (Schemas, model) {
if (Schemas.type == 'array') {
return formatArrayString(Schemas, model);
} else if (Schemas.type == 'object') {
return formatObjectString(Schemas, model);
} else {
return '\'\'' + renderAnnotation(Schemas);
}
};
const formatResponseArrayString = function (value, Schemas, model) {
var _array = [];
_array.push('[' + renderAnnotation(Schemas));
if (typeof Schemas.itemArray == 'string') {
if (Schemas.itemArray.indexOf('#/components/schemas/') != -1 && text.test(Schemas.itemArray)) {
var _key = Schemas.itemArray.replace('List<', '').replace('>', '');
Schemas[_key] && (Schemas = model[_key]);
} else if (Schemas.itemArray.indexOf('#/components/schemas/') != -1 && model[Schemas.itemArray]) {
Schemas = model[Schemas.itemArray];
};
};
for (let i = 0; i < value.length; i++) {
const _valueItem = value[i];
if (Schemas.type == 'object') {
_array.push(formatResponseObjectString(_valueItem, Schemas, model));
if (i != value.length - 1) {
_array.push(',\n')
};
} else if (Schemas.type == 'array') {
_array.push(formatResponseArrayString(_valueItem, Schemas.itemArray, model));
if (i != value.length - 1) {
_array.push(',\n')
};
} else {
var $value = '';
if (_Schemas.type == 'string') {
$value = '\'' + _valueItem + '\'';
} else {
$value = _valueItem.toString();
};
_array.push('\'' + $value + '\'' + renderAnnotation(element));
}
}
_array.push(']\n');
return _array.join('');
}
const formatResponseObjectString = function (value, Schemas, model) {
var _array = [];
if (typeof Schemas.itemArray == 'string') {
if (Schemas.itemArray.indexOf('#/components/schemas/') != -1 && text.test(Schemas.itemArray)) {
var _key = Schemas.itemArray.replace('List<', '').replace('>', '');
model[_key] && (Schemas = model[_key]);
} else if (Schemas.itemArray.indexOf('#/components/schemas/') != -1 && model[Schemas.itemArray]) {
Schemas = model[Schemas.itemArray];
};
};
var _length = Object.keys(value).length;
var keyIndex = 0;
if (Schemas.type != 'array' && Schemas.type != 'object') {
_array.push('\'\'' + renderAnnotation(Schemas));
} else {
_array.push('{' + renderAnnotation(Schemas, Schemas.key));
var _SchemasMapping = {};
Schemas.itemArray.forEach(ele => {
_SchemasMapping[ele.key] = ele;
});
for (const key in value) {
const _value = value[key];
const _Schemas = _SchemasMapping[key];
keyIndex++;
if (!_Schemas) {
var $value = '';
_array.push(key + ': \'' + _value + '\' ,');
} else if (_Schemas.type == 'object') {
_array.push(key + ':' + formatResponseObjectString(_value, _Schemas, model));
if (keyIndex != _length - 1) {
_array.push(',\n')
};
} else if (_Schemas.type == 'array') {
_array.push(key + ':' + formatResponseArrayString(_value, _Schemas, model));
if (keyIndex != _length - 1) {
_array.push(',\n')
};
} else {
var $value = '';
if (_Schemas.type == 'string') {
$value = '\'' + _value + '\'';
} else {
$value = _value.toString();
}
_array.push((_Schemas.key == '<*>' ? key : _Schemas.key) + ': ' + $value + ' ,' + renderAnnotation(_Schemas));
}
}
_array.push('}\n');
}
return _array.join('');
}
const formatResponse = function (value, Schemas, model) {
if (Schemas.type == 'array') {
return formatResponseArrayString(value, Schemas, model);
} else if (Schemas.type == 'object') {
return formatResponseObjectString(value, Schemas, model);
} else {
if (Schemas.type == 'string') {
return '\'' + value + '\'' + renderAnnotation(Schemas)
} else {
return value.toString() + renderAnnotation(Schemas);
}
}
};
module.exports = {
String: formatString,
Models: formatModels,
Response: formatResponse,
}
package.json
javascript"> "bin": {
"ds": "./bin/cli.js"
},
输入命令 ds swagger