通过swagger-typescript-api获取的接口方法,默认的命名方式是后端的方法名,后端经常会在不同的controller下写很多相同的方法名(如list这种命名) 通过自定义调用generateApi,可以将命名规则改为 请求方法+路径
/* eslint-disable */
import path from 'node:path'
import { generateApi } from 'swagger-typescript-api'
const args = process.argv.slice(2)
const target = args[0]
function capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1)
}
function toPascalCase(str) {
const words = String(str)
.split(/[^a-zA-Z0-9]+/)
.filter(Boolean)
return words.map((w) => capitalize(w)).join('')
}
function toCamelCase(str) {
const pascal = toPascalCase(str)
if (!pascal) return ''
return pascal.charAt(0).toLowerCase() + pascal.slice(1)
}
function toSafeRouteName(name) {
const safe = toCamelCase(String(name).replace(/[^a-zA-Z0-9]+/g, ' '))
return safe || 'request'
}
function singular(word) {
// 简易处理,可换成更完善的库(如 pluralize)
if (word.endsWith('s')) return word.slice(0, -1)
return word
}
function joinSegments(segments) {
return segments.join('')
}
function main() {
generateApi({
name: 'ApiMailbox.ts',
fileName: 'ApiMailbox.ts',
// set to `false` to prevent the tool from writing to disk
url: 'http://127.0.0.1:3000/swagger-doc-json',
output: path.resolve(process.cwd(), './src/apiMailbox'),
httpClientType: 'axios',
generateRouteTypes: false,
hooks: {
onFormatRouteName: (routeInfo, templateRouteName) => {
/**
* routeInfo 示例:
* {
* method: 'get',
* route: '/users/{id}/roles',
* originalPath: '/users/{id}/roles',
* ... 其他字段
* }
*/
const httpMethod = (routeInfo.method || '').toLowerCase()
const rawPath = routeInfo.route || ''
const segmentMeta = rawPath
.split('/')
.filter(Boolean)
.map((segment) => {
const isParam = /^\{.+\}$/.test(segment)
const raw = segment.replace(/^\{|\}$/g, '')
return {
isParam,
raw,
name: toPascalCase(raw)
}
})
const resourceSegments = segmentMeta.filter((s) => !s.isParam).map((s) => s.name)
// 简单判断动作(可按需扩展更复杂逻辑)
const verbMap = {
get: 'get',
post: 'create',
put: 'update',
patch: 'patch',
delete: 'delete'
}
// 特殊:嵌套 + POST 往往表示“添加子资源”
// 例如 /users/{id}/roles POST -> addUserRole
if (httpMethod === 'post' && segmentMeta.length > 2 && resourceSegments.length >= 2) {
// 最后一个非参数段作为子资源
const last = resourceSegments[resourceSegments.length - 1]
return toSafeRouteName('add' + joinSegments(resourceSegments.slice(0, 1)) + singular(last))
}
// 构造核心资源名(主资源+可能的子资源)
let core = resourceSegments.map(capitalize).join('')
if (!core) {
core = 'Request'
}
// 拼接参数修饰(ByXxx...)
let byPart = ''
const paramNames = segmentMeta.filter((s) => s.isParam).map((s) => s.name)
if (paramNames.length) {
byPart = 'By' + paramNames.map(capitalize).join('And')
}
// 选择动词
let verb = verbMap[httpMethod] || httpMethod
// 如果是 GET 并且无参数且资源名复数 -> getUsers 这种就保留
// 如果是 GET + 有参数 -> getUserById
// 如果是 DELETE + 有子资源参数 -> deleteUserRoleByRoleId
// 已在通用逻辑覆盖
const customName = verb + core + byPart
const finalName = customName || templateRouteName || `${httpMethod}Request`
return toSafeRouteName(finalName)
}
},
prettier: {
// By default prettier config is load from your project
printWidth: 120,
tabWidth: 2,
trailingComma: 'all',
parser: 'typescript'
}
})
}
main()