@xm-fe/create-api
Advanced tools
Comparing version 0.0.1 to 0.0.2
#!/usr/bin/env node | ||
// // import inquirer from "inquirer"; | ||
// const inquirer = require('inquirer') | ||
// inquirer | ||
// .prompt([ | ||
// { | ||
// type: "rawlist", // 交互类型 -- 有序单选 | ||
// message: "请选择一种水果:", // 引导词 | ||
// name: "projectId", // 自定义的字段名 | ||
// choices: ["潜艇SAAS/", | ||
// "summerfarm-manage(鲜沐后台)", | ||
// "pms-service(采购)/1164725", | ||
// "summerfarm-crm(CRM)/1295278", | ||
// "TMS(配送)/1409074", | ||
// "summerfarm-wms(WMS)/1965722", | ||
// "OFC(履约)/2020406", | ||
// "saas-manage (帆台后台)/2437205", | ||
// "saas-oms (帆台大后台)/2437206", | ||
// "saas-mall (帆台商城)/2437207" | ||
// ], // 选项列表 | ||
// }, | ||
// ]) | ||
// .then((answers) => { | ||
// console.log(answers); | ||
// }); | ||
const main = require('../src/index') | ||
main() |
{ | ||
"name": "@xm-fe/create-api", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"description": "API快速导入", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
"capi": "node bin/capi.js" | ||
}, | ||
@@ -12,3 +12,2 @@ "bin": { | ||
}, | ||
"files":["bin", "src"], | ||
"repository": { | ||
@@ -24,5 +23,8 @@ "type": "git", | ||
"dependencies": { | ||
"@xm-fe/xm-base": "0.0.10", | ||
"axios": "^1.3.4", | ||
"lodash": "^4.17.21" | ||
"inquirer": "^8.0.0", | ||
"lodash": "^4.17.21", | ||
"log4js": "^6.9.1" | ||
} | ||
} |
@@ -5,2 +5,5 @@ const fs = require('fs') | ||
const _ = require('lodash') | ||
const log4js = require('log4js') | ||
const logger = log4js.getLogger() | ||
var typeEnmu = { | ||
@@ -101,15 +104,25 @@ 'integer[]': 'number[]', | ||
const getCurrentInterfaceTpl = obj => { | ||
return ` | ||
/**${obj.description} */ | ||
export interface ${_.upperFirst(obj._name)} { | ||
const interfaceName = _.upperFirst(obj._name) | ||
try { | ||
return ` | ||
/**${obj.description} */ | ||
export interface ${interfaceName} { | ||
${Object.entries(obj.type === 'array' ? obj.items.properties : obj.properties) | ||
.map(([key, val]) => { | ||
return ` /**${val.description} */ | ||
` + (key.indexOf('.') > -1 || key.indexOf('[') > -1 ? `"${key}"` : key) + `${val._required ? '' : '?'}: ${toFeType(val._type)}` | ||
}) | ||
.join('\n')} | ||
} | ||
` | ||
} catch (error) { | ||
console.log('类型创建异常:', interfaceName, '使用any代替') | ||
${Object.entries(obj.type === 'array' ? obj.items.properties : obj.properties) | ||
.map(([key, val]) => { | ||
return ` /**${val.description} */ | ||
${key}${val._required ? '' : '?'}: ${toFeType(val._type)}` | ||
}) | ||
.join('\n')} | ||
return ` | ||
export type ${interfaceName} = any` | ||
} | ||
} | ||
` | ||
} | ||
const mkdir = dirname => { | ||
@@ -116,0 +129,0 @@ // 循环创建目录 |
@@ -5,13 +5,14 @@ const path = require('path') | ||
let useConfig = {} | ||
const defaultConfig = { | ||
// 生成目录 | ||
targetPath: `/src/apx`, | ||
truePath: `apis`, | ||
targetPath: `/src/apix`, | ||
truePath: `apix`, | ||
// targetTypePath: `/src/api-typess`, | ||
// 读本地文件生成 | ||
useLocal: false, | ||
runtimeProjectId: '', // 当前的工程id | ||
// 本地文件地址 | ||
localPath: `./test3.0.1.json`, | ||
remotePath: `http://127.0.0.1:4523/export/openapi/6?projectId=2517920&version=3.0`, | ||
remotePath: `http://127.0.0.1:4523/export/openapi?projectId=1164722&version=3.0`, | ||
language: 'ts', // 生成的项目语言类型 | ||
// 暂时搞不定的接口 | ||
@@ -27,7 +28,23 @@ ignorePath: [ | ||
appNameMap: { | ||
'1164722': 'summerfarm-manage', | ||
'1409074': 'tms', | ||
'954456': 'cosfo', | ||
'2517920': 'rs' | ||
954456: 'SAAS', | ||
1164722: 'summerfarm-manage', | ||
1164725: 'pms-service', | ||
1295278: 'summerfarm-crm', | ||
1409074: 'tms', | ||
1965722: 'summerfarm-wms', | ||
2020406: 'OFC', | ||
2437205: 'saas-manage', | ||
2437206: 'saas-oms', | ||
2437207: 'saas-mall', | ||
2517920: 'summerfarm-wnc', | ||
2546551: 'saas-pms', | ||
2546569: 'SCP', | ||
2546585: 'SRM', | ||
2546600: 'bms-service' | ||
}, | ||
/** | ||
* 接口项目前缀 | ||
* saas项目中访问 | ||
*/ | ||
apiPrefix: ['/summerfarm-manage', '/summerfarm-wms', '/summerfarm-wnc', '/pms-service', '/xianmu-manage', '/bms-service'], // 目前已经有的前缀 | ||
// 路径参数别名 | ||
@@ -127,3 +144,3 @@ paramsNumName: { | ||
*/ | ||
export function ${api.name}( | ||
export function ${api.fileName || api.name}( | ||
${pathParams ? pathParams : ''} | ||
@@ -146,3 +163,32 @@ ${api.queryParams ? `params?: ${api.queryParams._name},` : ''} | ||
` | ||
}, | ||
getApiCodeTplJs(api) { | ||
const pathParams = api.pathParams | ||
.map((param) => `${param.name}${param.required ? '' : '?'}: ${param._type},`) | ||
.join('\r\n') | ||
return ` | ||
import net from '@/utils/net' | ||
import { NetConfig } from '@/interface/IAxiosConfig' | ||
/** | ||
* ${api.summary} | ||
*/ | ||
export function ${api.fileName || api.name}( | ||
${pathParams ? pathParams : ''} | ||
${api.queryParams ? `params,` : ''} | ||
${api.bodyParams ? `data,` : ''} | ||
config | ||
) { | ||
return net( | ||
{ | ||
url: \`${api.url}\`, | ||
method: '${api.method}', | ||
${api.isDownload ? `_download: true,` : ''} | ||
${api.queryParams ? `params,` : ''} | ||
${api.bodyParams ? ` data,` : ''} | ||
}, | ||
config | ||
) | ||
} | ||
` | ||
} | ||
} | ||
@@ -152,4 +198,19 @@ | ||
const useConfigPath = path.join(process.cwd(), 'capi.config.js') // 上一层路径 | ||
const config = { ...defaultConfig } | ||
try { | ||
useConfig = require(useConfigPath) | ||
const { getApiCodeTpl, remotePath, language } = useConfig | ||
if(getApiCodeTpl) { | ||
config.getApiCodeTpl = getApiCodeTpl | ||
} | ||
if(remotePath) { | ||
config.remotePath = remotePath | ||
} | ||
if(language) { | ||
config.language = language | ||
} | ||
} catch (error) { | ||
@@ -159,3 +220,2 @@ console.log(`用户本地配置文件${useConfigPath} 解析失败,将使用默认配置`) | ||
const config = { ...defaultConfig, ...useConfig } | ||
@@ -188,2 +248,5 @@ if(!config.remotePath) { | ||
const URLparams = queryURLparams(config.remotePath) | ||
config.runtimeProjectId = URLparams.projectId | ||
module.exports = config |
const _ = require('lodash') | ||
const config = require('./config') | ||
const common = require('./common') | ||
const log4js = require('log4js') | ||
const logger = log4js.getLogger() | ||
@@ -91,6 +93,6 @@ const apiType = ['export', 'query', 'upsert', 'import'] | ||
apiPathList[apiPathList.length - 2] + | ||
'_' + | ||
apiPathList[apiPathList.length - 1] + | ||
config.paramsNumName[pathParamsCount] + | ||
'Net' | ||
'_' + | ||
apiPathList[apiPathList.length - 1] + | ||
config.paramsNumName[pathParamsCount] + | ||
'Net' | ||
) | ||
@@ -149,3 +151,3 @@ } else { | ||
if ( | ||
shouldAddListModel && | ||
shouldAddListModel && responseSchema.properties && | ||
!responseSchema.properties.msg && | ||
@@ -251,3 +253,3 @@ !responseSchema.properties.data && | ||
} catch (e) { | ||
console.log('接口解析异常:', apiPath) | ||
console.error('接口解析异常:', apiPath) | ||
} | ||
@@ -257,9 +259,23 @@ } | ||
function generateApiCode(api) { | ||
const api_ = JSON.parse(JSON.stringify(api)) | ||
if(api_.resType === 'Data') { | ||
api_.resType = 'any' | ||
} | ||
switch (api_.resType) { | ||
case 'Data': | ||
api_.resType = 'any' | ||
break; | ||
case 'integer': | ||
api_.resType = 'number' | ||
break; | ||
} | ||
return ` | ||
${common.generateRefType(api.bodyParams)} | ||
${common.generateRefType(api.resSchema)} | ||
${config.getApiCodeTpl(api)} | ||
${api.queryParams ? common.getInterfaceTpl(api.queryParams) : ''} | ||
${api.hasbodyParamsType ? common.getInterfaceTpl(api.bodyParams) : ''} | ||
${api.hasResType ? common.getInterfaceTpl(api.resSchema) : ''} | ||
${config.getApiCodeTpl(api_)} | ||
${api_.queryParams ? common.getInterfaceTpl(api_.queryParams) : ''} | ||
${api_.hasbodyParamsType ? common.getInterfaceTpl(api_.bodyParams) : ''} | ||
${api_.hasResType ? common.getInterfaceTpl(api_.resSchema) : ''} | ||
` | ||
@@ -266,0 +282,0 @@ } |
const common = require('./common') | ||
const log4js = require('log4js') | ||
const logger = log4js.getLogger() | ||
@@ -34,7 +36,7 @@ const handleType = components => { | ||
// } | ||
const generateTypeCode = typeData => common.generateRefType(typeData) + common.getInterfaceTpl(typeData) | ||
// const generateTypeCode = typeData => common.getInterfaceTpl(typeData) | ||
module.exports = { | ||
handleType, | ||
generateTypeCode, | ||
// generateTypeCode, | ||
} |
125
src/index.js
@@ -10,4 +10,17 @@ const fs = require('fs') | ||
const { queryURLparams } = require('./utils') | ||
const { isNumber } = require('@xm-fe/xm-base') | ||
require('./log') | ||
const log4js = require('log4js') | ||
const logger = log4js.getLogger() | ||
let appName = 'main' | ||
const typeMode = {} | ||
const apiTypeListMap = {} | ||
// 接口命名不符合规范的url | ||
const abnormalApi = [] | ||
// 当前api已经创建过的 接口类型 防止重复创建和循环引用 | ||
let createdType = [] | ||
async function main() { | ||
@@ -18,3 +31,16 @@ let apiData | ||
const re = await axios.get(config.remotePath) | ||
Object.keys(re.data.paths).forEach(api => { | ||
let newUrl = api | ||
const defaultPrefix = config.apiPrefix.find(prefix => api.indexOf(prefix) > -1) | ||
if (defaultPrefix) { | ||
newUrl = api.replace(defaultPrefix, '') | ||
re.data.paths[newUrl] = JSON.parse(JSON.stringify(re.data.paths[api])) | ||
delete re.data.paths[api] | ||
} | ||
}) | ||
apiData = re.data | ||
console.log(`请求成功!`) | ||
@@ -38,3 +64,5 @@ } else { | ||
} else { | ||
console.log(`warning:未检测到appName,生成至${config.targetPath}/main文件夹`) | ||
console.error('!!! projectId没有对应的文件名,请联系我', URLparams.projectId) | ||
console.error('!!! projectId没有对应的文件名,请联系我', URLparams.projectId) | ||
process.exit() | ||
} | ||
@@ -44,2 +72,7 @@ config.appName = appName | ||
cApi(apiData) | ||
// if (abnormalApi.length > 0) { | ||
// abnormalApi.forEach(item => { | ||
// console.warn('不符合规范的URL:', item) | ||
// }) | ||
// } | ||
console.log('创建成功!', config.targetPath) | ||
@@ -49,3 +82,3 @@ } | ||
const cApi = apiData => { | ||
const targetPath = path.join(process.cwd(), config.targetPath, appName, 'api') | ||
const targetPath = path.join(process.cwd(), config.targetPath, appName) | ||
common.mkdir(targetPath) | ||
@@ -55,14 +88,49 @@ const apiModuleMap = createApi.handlePaths(apiData.paths, apiData.components.schemas) | ||
Object.entries(apiModuleMap).forEach(([moduleName, apiList]) => { | ||
const modulePath = path.join(targetPath, moduleName) | ||
if (!fs.existsSync(modulePath)) { | ||
fs.mkdirSync(modulePath) | ||
} | ||
// 遍历模块内api | ||
apiList.forEach((api, idx) => { | ||
const filePath = path.resolve(modulePath, api.name + '.ts') | ||
// 清空 | ||
createdType = [] | ||
// 处理 - | ||
let name = api.url.split('-').map((item, index) => (index > 0 ? _.upperFirst(item) : item)).join('') | ||
// 处理 / | ||
name = name.split('/').map((item, index) => (index > 1 ? _.upperFirst(item) : item)).join('') | ||
// 如果以数字开头的不生成 | ||
if (isNumber(name[0]) || /^.*?(http|localhost|_|\,).*?$/.test(name)) { | ||
abnormalApi.push(api.url) | ||
return | ||
} | ||
name = name.replace(/\$\{.*?\}/g, '') | ||
// 会生成 .ts 文件 | ||
if (!name) { | ||
return | ||
} | ||
const fileName = name + (api.method === 'post' ? '' : _.upperFirst(api.method)) + 'Net' | ||
const filePath = path.resolve(targetPath, fileName + '.' + config.language) | ||
api.fileName = fileName | ||
try { | ||
// createApi.generateApiCode(api) | ||
fs.writeFileSync(filePath, createApi.generateApiCode(api)) | ||
let content = '' | ||
// 接口生成 | ||
content += createApi.generateApiCode(api) | ||
if (config.language === 'ts') { | ||
// 请求参数 | ||
if (api.bodyParams?._ref) { | ||
content += handleTypeLink(api.bodyParams._ref) | ||
} | ||
// 响应参数 | ||
content += handleTypeLink(api.resSchema._ref) | ||
} | ||
fs.writeFileSync(filePath, content) | ||
} catch (e) { | ||
console.log('接口创建异常:', api.url) | ||
console.error('接口创建异常:', api.url) | ||
} | ||
@@ -72,13 +140,16 @@ }) | ||
} | ||
const cType = apiData => { | ||
const apiTypeList = createType.handleType(apiData.components.schemas) | ||
const targetPath = path.join(process.cwd(), config.targetPath, appName, 'types') | ||
common.mkdir(targetPath) | ||
apiTypeList.forEach((item) => { | ||
apiTypeListMap[item._name] = item | ||
}) | ||
// 生成type | ||
apiTypeList.forEach(type => { | ||
const typePath = path.resolve(targetPath, type._name + '.ts') | ||
try { | ||
fs.writeFileSync(typePath, createType.generateTypeCode(type)) | ||
typeMode[type._name] = common.getInterfaceTpl(type) | ||
} catch (e) { | ||
console.log('类型创建异常:', type._name) | ||
console.error('类型创建异常:', type._name) | ||
console.error(e) | ||
} | ||
@@ -88,2 +159,26 @@ }) | ||
/** | ||
* 处理type间的引用关系, 根据type生成该type 中所以引用的type模板 | ||
* @param {*} apiData | ||
*/ | ||
const handleTypeLink = (resType) => { | ||
let typeStr = '' | ||
const creatType_ = (type) => { | ||
if (type !== 'null' && type && !createdType.includes(type)) { | ||
createdType.push(type) | ||
if(typeMode[type]) { | ||
typeStr += typeMode[type] | ||
} | ||
apiTypeListMap[type]?._refList?.forEach((item) => { | ||
creatType_(item) | ||
}) | ||
} | ||
} | ||
creatType_(resType) | ||
return typeStr | ||
} | ||
module.exports = main |
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
33434
12
911
2
5
+ Added@xm-fe/xm-base@0.0.10
+ Addedinquirer@^8.0.0
+ Addedlog4js@^6.9.1
+ Added@xm-fe/xm-base@0.0.10(transitive)
+ Addedansi-escapes@4.3.2(transitive)
+ Addedansi-regex@5.0.1(transitive)
+ Addedansi-styles@4.3.0(transitive)
+ Addedbase64-js@1.5.1(transitive)
+ Addedbl@4.1.0(transitive)
+ Addedbuffer@5.7.1(transitive)
+ Addedchalk@4.1.2(transitive)
+ Addedchardet@0.7.0(transitive)
+ Addedcli-cursor@3.1.0(transitive)
+ Addedcli-spinners@2.9.2(transitive)
+ Addedcli-width@3.0.0(transitive)
+ Addedclone@1.0.4(transitive)
+ Addedcolor-convert@2.0.1(transitive)
+ Addedcolor-name@1.1.4(transitive)
+ Addeddate-format@4.0.14(transitive)
+ Addeddebug@4.4.0(transitive)
+ Addeddefaults@1.0.4(transitive)
+ Addedemoji-regex@8.0.0(transitive)
+ Addedescape-string-regexp@1.0.5(transitive)
+ Addedexternal-editor@3.1.0(transitive)
+ Addedfigures@3.2.0(transitive)
+ Addedflatted@3.3.2(transitive)
+ Addedfs-extra@8.1.0(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedhas-flag@4.0.0(transitive)
+ Addediconv-lite@0.4.24(transitive)
+ Addedieee754@1.2.1(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedinquirer@8.2.6(transitive)
+ Addedintersection-observer@0.12.2(transitive)
+ Addedis-fullwidth-code-point@3.0.0(transitive)
+ Addedis-interactive@1.0.0(transitive)
+ Addedis-unicode-supported@0.1.0(transitive)
+ Addedjsonfile@4.0.0(transitive)
+ Addedlodash-es@4.17.21(transitive)
+ Addedlog-symbols@4.1.0(transitive)
+ Addedlog4js@6.9.1(transitive)
+ Addedmimic-fn@2.1.0(transitive)
+ Addedms@2.1.3(transitive)
+ Addedmute-stream@0.0.8(transitive)
+ Addednumber-precision@1.6.0(transitive)
+ Addedonetime@5.1.2(transitive)
+ Addedora@5.4.1(transitive)
+ Addedos-tmpdir@1.0.2(transitive)
+ Addedreadable-stream@3.6.2(transitive)
+ Addedrestore-cursor@3.1.0(transitive)
+ Addedrfdc@1.4.1(transitive)
+ Addedrun-async@2.4.1(transitive)
+ Addedrxjs@7.8.1(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsignal-exit@3.0.7(transitive)
+ Addedstreamroller@3.1.5(transitive)
+ Addedstring-width@4.2.3(transitive)
+ Addedstring_decoder@1.3.0(transitive)
+ Addedstrip-ansi@6.0.1(transitive)
+ Addedsupports-color@7.2.0(transitive)
+ Addedthrough@2.3.8(transitive)
+ Addedtmp@0.0.33(transitive)
+ Addedtslib@2.8.1(transitive)
+ Addedtype-fest@0.21.3(transitive)
+ Addeduniversalify@0.1.2(transitive)
+ Addedutil-deprecate@1.0.2(transitive)
+ Addedwcwidth@1.0.1(transitive)
+ Addedwrap-ansi@6.2.0(transitive)