From be91552709a51e2ba0e295853eb90eb67cfd05d6 Mon Sep 17 00:00:00 2001 From: "kongjing@dian.so" Date: Mon, 7 Nov 2022 14:28:16 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9Eswagger=E7=94=9F?= =?UTF-8?q?=E6=88=90=E7=9A=84=E6=9C=AC=E8=88=B0=E6=A0=87=E8=AE=B0=EF=BC=8C?= =?UTF-8?q?=E4=BF=AE=E5=A4=8Daction=E5=8F=82=E6=95=B0=E7=9A=84=E5=AF=BC?= =?UTF-8?q?=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/api/global.d.ts | 2 + packages/api/src/bin.ts | 2 +- packages/api/src/create-action/create.ts | 2 +- packages/api/src/file.ts | 78 +++++++++++++++++++----- packages/api/src/swagger/transform.ts | 6 +- 5 files changed, 72 insertions(+), 18 deletions(-) diff --git a/packages/api/global.d.ts b/packages/api/global.d.ts index b2852e8c..5756fdac 100755 --- a/packages/api/global.d.ts +++ b/packages/api/global.d.ts @@ -10,6 +10,8 @@ declare module '*.json' { const value: any export default value } +// 定义接口的方案类型:前端代码定义、服务端swagger定义 +type IApiType = 'FRONT' | 'SWAGGER' declare namespace NodeJS { interface ProcessEnv { diff --git a/packages/api/src/bin.ts b/packages/api/src/bin.ts index abd655db..48a38a12 100755 --- a/packages/api/src/bin.ts +++ b/packages/api/src/bin.ts @@ -39,7 +39,7 @@ program .option('-p, --path ', 'request types path') .option('-u, --url ', 'the url of swagger data') .option('-mod, --modules ', 'swagger tag item split with comma') - .option('-a, --actions ', 'if create request method') + .option('-a, --action ', 'if create request method') .action(swagger) program.parse(process.argv) diff --git a/packages/api/src/create-action/create.ts b/packages/api/src/create-action/create.ts index 0c67b02d..5f1a049b 100755 --- a/packages/api/src/create-action/create.ts +++ b/packages/api/src/create-action/create.ts @@ -14,7 +14,7 @@ export function createDefaultModel({ if (key !== 'Record' && item.url && item.description) { packages.push(key) requestActionsStr += ` - // ${item.description} + // ${item.description || '暂无描述'} export const ${ key + fileName.replace(/^\S/, function (s) { diff --git a/packages/api/src/file.ts b/packages/api/src/file.ts index 1c46b826..c904e332 100755 --- a/packages/api/src/file.ts +++ b/packages/api/src/file.ts @@ -23,19 +23,14 @@ if (fs.existsSync(API_UI_DATA_PATH)) { } export function workFile(targetUrl: string, action: boolean) { - const globPaths = [`${targetUrl}/*.ts`, `${targetUrl}/ **/*.ts`] + const globPaths = [`${targetUrl}/*.ts`, `${targetUrl}/**/*.ts`] const writeActionTarget = path_.resolve(targetUrl, dirPath || '../') if (!fs.existsSync(writeActionTarget)) { fs.mkdirSync(writeActionTarget) } return new Promise((resolve) => { - globMax(globPaths, async (err, paths: string[]) => { - if (err) { - log.error(err.toString()) - process.exit(1) - } - + globMax(globPaths, async (paths: string[]) => { await workUnit(paths, action, writeActionTarget) if (!fs.existsSync(path_.join(CWD, './.cache'))) { @@ -106,6 +101,8 @@ function workUnit(paths: string[], action: boolean, writeActionTarget: string) { for (let i = 0; i < paths.length; i++) { const p = paths[i] if (p) { + const fileCode = fs.readFileSync(p, 'utf-8') + const apiTypeComments = getApiTypeComments(fileCode) const parseRes = parser(p) const fileArr = p.split('/') const fileName = fileArr[fileArr.length - 1]?.replace('.ts', '') @@ -133,10 +130,14 @@ function workUnit(paths: string[], action: boolean, writeActionTarget: string) { const prettierConfig = await getPrettierConfig() - const formatContent = prettier.format(content, { - ...prettierConfig, - parser: 'typescript', - }) + const formatContent = prettier.format( + `${apiTypeComments} + ${content}`, + { + ...prettierConfig, + parser: 'typescript', + }, + ) fs.writeFileSync( path_.resolve(writeActionTarget, `${fileName}.ts`), @@ -156,19 +157,68 @@ function workUnit(paths: string[], action: boolean, writeActionTarget: string) { } async function globMax(files, callback) { - let allPaths: string[] = [] + const allPaths: string[] = [] for (let i = 0; i < files.length; i++) { const pats = await globSync(files[i]) - if (pats) allPaths = allPaths.concat(pats) + pats.forEach((it) => { + if (!allPaths.includes(it)) { + allPaths.push(it) + } + }) } + callback(allPaths) } async function globSync(file): Promise { return new Promise((resolve, reject) => { glob(file, (err, pats) => { - if (err) reject(err) + if (err) { + console.info(err, '????') + reject(err) + } resolve(pats) }) }) } + +function getApiTypeComments(codeStr: string) { + const commentsMatch = codeStr.match(/\/\*\*[\w\W]{4,100}\*\//) + let comments = '/** @type front */' + if (commentsMatch) { + const commentsStr = commentsMatch[0] + const comm: Record = parseComments(commentsStr) + if (comm['type'].includes('swagger')) { + comments = '/** @type from swagger */' + } + } + + return comments +} + +function parseComments(comments = '') { + const res = {} + if (comments && comments.includes('\n')) { + const arr = comments + .split('\n') + .filter((item) => item.includes('@')) + .map((item) => item.replace(/^[\s]+/g, '')) + .map((item) => item.replace('* ', '')) + .map((item) => item.replace('@', '')) + .map((item) => item.replace(/[\s]+/, '##')) + + arr.forEach((item) => { + const cons = item.split('##') + if (cons[0]) res[cons[0]] = cons[1] + }) + } else if (comments) { + const arr = comments + .replace(/\/\*\*[\s]*/, '') + .replace(/[\s]*\*\//, '') + .replace('@', '') + .split(' ') + if (arr[0]) res[arr[0]] = arr[1] + } + + return res +} diff --git a/packages/api/src/swagger/transform.ts b/packages/api/src/swagger/transform.ts index 8989a14e..1f849b6d 100755 --- a/packages/api/src/swagger/transform.ts +++ b/packages/api/src/swagger/transform.ts @@ -20,6 +20,8 @@ const DEAULT_RESPONSE = `{ */ success: boolean }` +const API_TYPE_COMMENTS = `/** @type swagger(标注swagger生成的代码,请确认后修改) */ +` export async function transform( data: Record, @@ -134,7 +136,7 @@ export async function transform( ` await fs.writeFileSync( pat.join(typesUrl, `${createTypeFileName?.(nn)}.ts`), - formatTs(`${baseImport}${mode.codes}`), + formatTs(`${API_TYPE_COMMENTS}${baseImport}${mode.codes}`), ) } /** todo 只生成使用的基础类型 */ @@ -406,7 +408,7 @@ function createComments(params?: Record) { function resetRepeatName(name) { if (/[0-9]{1,4}$/g.test(name)) { - let words = name.replace(/[0-9]{1,4}$/g, '') + const words = name.replace(/[0-9]{1,4}$/g, '') let num = name.match(/[0-9]{1,4}$/g)[0] || 0 num = Number(num) + 1