添加注释

This commit is contained in:
DESKTOP-I3JPKHK\wy 2026-04-23 09:19:24 +08:00
parent c6482c7f08
commit 4dc4427f2a
2 changed files with 142 additions and 1 deletions

View File

@ -384,6 +384,7 @@ const buildPlannedModuleExports = (selectedModules) => {
const buildModuleMap = (swagger) => {
const moduleMap = new Map()
const tagDescriptionMap = buildTagDescriptionMap(swagger.tags)
for (const [apiPath, pathItem] of Object.entries(swagger.paths || {})) {
for (const method of HTTP_METHOD_ORDER) {
@ -396,11 +397,17 @@ const buildModuleMap = (swagger) => {
const moduleName = extractModuleName(apiPath, operation)
const moduleKey = normalizeLookupKey(moduleName)
const aliases = new Set([moduleName, toKebabCase(moduleName), ...(operation.tags || [])])
const moduleDescription = resolveModuleDescription({
moduleName,
operation,
tagDescriptionMap,
})
if (!moduleMap.has(moduleKey)) {
moduleMap.set(moduleKey, {
aliases,
fileName: toKebabCase(moduleName),
moduleDescription,
moduleName,
operations: [],
})
@ -412,6 +419,10 @@ const buildModuleMap = (swagger) => {
moduleInfo.aliases.add(alias)
}
if (!moduleInfo.moduleDescription && moduleDescription) {
moduleInfo.moduleDescription = moduleDescription
}
moduleInfo.operations.push({
method,
operation,
@ -851,10 +862,17 @@ const generateModuleFile = ({ moduleInfo, paramStyle, schemas, requestImport, sw
AUTO_GENERATED_BANNER,
`// Swagger: ${swaggerUrl}`,
`// Module: ${moduleInfo.moduleName}`,
]
if (moduleInfo.moduleDescription) {
lines.push(`// Module description: ${escapeComment(moduleInfo.moduleDescription)}`)
}
lines.push(
`// Param style: ${paramStyle}`,
'',
`import request from '${requestImport}'`,
]
)
if (needsBuildUrl) {
lines.push(`import { buildUrl } from '${DEFAULT_SHARED_IMPORT}'`)
@ -1528,6 +1546,37 @@ const extractModuleName = (apiPath, operation) => {
return operation.tags?.[0] || segments[0] || 'default'
}
const buildTagDescriptionMap = (tags = []) => {
const descriptionMap = new Map()
for (const tag of tags) {
const tagName = String(tag?.name || '').trim()
const tagDescription = String(tag?.description || '').trim()
if (!tagName || !tagDescription) {
continue
}
descriptionMap.set(normalizeLookupKey(tagName), tagDescription)
}
return descriptionMap
}
const resolveModuleDescription = ({ moduleName, operation, tagDescriptionMap }) => {
const candidates = [...(operation.tags || []), moduleName]
for (const candidate of candidates) {
const description = tagDescriptionMap.get(normalizeLookupKey(candidate))
if (description) {
return description
}
}
return ''
}
const getEndpointName = (apiPath) => {
const segments = apiPath.split('/').filter(Boolean)

View File

@ -218,6 +218,98 @@ test('generated index includes namespace exports and flattened re-exports', asyn
}
})
test('generated module file includes module description from swagger tags', async () => {
const tempDir = await createTempDir()
try {
const swaggerPath = path.join(tempDir, 'swagger.json')
const outputDir = path.join(tempDir, 'generated')
await writeJson(swaggerPath, {
openapi: '3.0.0',
tags: [
{
name: 'Ranking',
description: '排行榜',
},
],
paths: {
'/api/v1/Ranking/GetList': {
get: {
responses: {
200: { description: 'OK' },
},
},
},
},
})
await generateApiFiles({
projectRoot: tempDir,
swaggerUrl: swaggerPath,
swaggerTimeoutMs: 1000,
outputDir,
requestImport: '../request',
paramStyle: 'object',
modules: [],
cleanOutput: true,
})
const rankingContent = await readFile(path.join(outputDir, 'ranking.js'))
assert.match(rankingContent, /\/\/ Module: Ranking/)
assert.match(rankingContent, /\/\/ Module description: 排行榜/)
} finally {
await fs.rm(tempDir, { recursive: true, force: true })
}
})
test('generated module file omits module description when swagger tags have no description', async () => {
const tempDir = await createTempDir()
try {
const swaggerPath = path.join(tempDir, 'swagger.json')
const outputDir = path.join(tempDir, 'generated')
await writeJson(swaggerPath, {
openapi: '3.0.0',
tags: [
{
name: 'Ranking',
},
],
paths: {
'/api/v1/Ranking/GetList': {
get: {
tags: ['Ranking'],
responses: {
200: { description: 'OK' },
},
},
},
},
})
await generateApiFiles({
projectRoot: tempDir,
swaggerUrl: swaggerPath,
swaggerTimeoutMs: 1000,
outputDir,
requestImport: '../request',
paramStyle: 'object',
modules: [],
cleanOutput: true,
})
const rankingContent = await readFile(path.join(outputDir, 'ranking.js'))
assert.match(rankingContent, /\/\/ Module: Ranking/)
assert.doesNotMatch(rankingContent, /\/\/ Module description:/)
} finally {
await fs.rm(tempDir, { recursive: true, force: true })
}
})
test('generation can skip generated index.js when generateIndexFile is false', async () => {
const tempDir = await createTempDir()