Skip to content

Commit 025b88a

Browse files
Merge pull request #598 from openapi-ui/feat/supportParseEnumDescByReg
feat: add supportParseEnumEescByReg func
2 parents 30d2941 + 58c7213 commit 025b88a

File tree

8 files changed

+89
-2
lines changed

8 files changed

+89
-2
lines changed

.changeset/eight-donuts-rush.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'openapi-ts-request': minor
3+
---
4+
5+
feat: add supportParseEnumDescByReg func

README-en_US.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ $ openapi --help
210210
--isOnlyGenTypeScriptType <boolean> only generate typescript type (default: false)
211211
--isCamelCase <boolean> camelCase naming of controller files and request client (default: true)
212212
--isSupportParseEnumDesc <boolean> parse enum description to generate enum label (default: false)
213+
--supportParseEnumDescByReg <string> custom regex for parsing enum description
213214
-h, --help display help for command
214215
```
215216

@@ -251,6 +252,7 @@ openapi -i ./spec.json -o ./apis
251252
| isOnlyGenTypeScriptType | no | boolean | false | only generate typescript type |
252253
| isCamelCase | no | boolean | true | camelCase naming of controller files and request client |
253254
| isSupportParseEnumDesc | no | boolean | false | parse enum description to generate enum label, format example: `UserRole:User(Normal User)=0,Agent(Agent)=1,Admin(Administrator)=2` |
255+
| supportParseEnumDescByReg | no | string \| RegExp | - | custom regex for parsing enum descriptions. If set, replaces default parseDescriptionEnum method. Example: `/([^\s=<>/&;]+(?:\s+[^\s=<>/&;]+)*)\s*=\s*(\d+)/g` matches "Normal = 0" or "SampleMaker = 1" |
254256
| binaryMediaTypes | no | string[] | - | custom binary media types list, default includes: ['application/octet-stream', 'application/pdf', 'image/*', 'video/*', 'audio/*'] |
255257
| hook | no | [Custom Hook](#Custom-Hook) | - | custom hook |
256258

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ $ openapi --help
210210
--isOnlyGenTypeScriptType <boolean> only generate typescript type (default: false)
211211
--isCamelCase <boolean> camelCase naming of controller files and request client (default: true)
212212
--isSupportParseEnumDesc <boolean> parse enum description to generate enum label (default: false)
213+
--supportParseEnumDescByReg <string> custom regex for parsing enum description
213214
-h, --help display help for command
214215
```
215216

@@ -251,6 +252,7 @@ openapi --i ./spec.json --o ./apis
251252
| isOnlyGenTypeScriptType || boolean | false | 仅生成 typescript 类型 |
252253
| isCamelCase || boolean | true | 小驼峰命名文件和请求函数 |
253254
| isSupportParseEnumDesc || boolean | false | 解析枚举描述生成枚举标签,格式参考:`系统用户角色:User(普通用户)=0,Agent(经纪人)=1,Admin(管理员)=2` |
255+
| supportParseEnumDescByReg || string \| RegExp | - | 自定义正则表达式,用于解析 description 中的枚举定义。如果设置了此参数,将使用此正则表达式替代默认的 parseDescriptionEnum 方法。例如:`/([^\s=<>/&;]+(?:\s+[^\s=<>/&;]+)*)\s*=\s*(\d+)/g` 可以匹配 "普通 = 0" 或 "SampleMaker = 1" 这样的格式 |
254256
| binaryMediaTypes || string[] | - | 自定义二进制媒体类型列表,默认包含:['application/octet-stream', 'application/pdf', 'image/*', 'video/*', 'audio/*'] |
255257
| hook || [Custom Hook](#Custom-Hook) | - | 自定义 hook |
256258

agents.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ else if (isNodeProject) {
6969
| `isOnlyGenTypeScriptType` | boolean | `false` | Only types, no request functions | Type-only needs |
7070
| `isCamelCase` | boolean | `true` | Use camelCase naming | Consistent naming |
7171
| `isSupportParseEnumDesc` | boolean | `false` | Parse enum descriptions | Labeled enums |
72+
| `supportParseEnumDescByReg` | `string \| RegExp` | - | Custom regex for parsing enum descriptions. If set, replaces default parseDescriptionEnum method. Example: `/([^\s=<>/&;]+(?:\s+[^\s=<>/&;]+)*)\s*=\s*(\d+)/g` matches "普通 = 0" or "SampleMaker = 1" | Custom enum description formats |
7273

7374
#### Request Customization
7475

@@ -118,6 +119,7 @@ else if (isNodeProject) {
118119
| "支持文件上传" | Check OpenAPI for multipart | Auto-detects file uploads |
119120
| "翻译中文标签" | `isTranslateToEnglishTag: true` | Chinese to English tags |
120121
| "解析枚举描述" | `isSupportParseEnumDesc: true` | Enum with descriptions |
122+
| "自定义枚举解析正则" | `supportParseEnumDescByReg: /pattern/g` | Custom enum description parsing |
121123
| "生成JSON验证" | `isGenJsonSchemas: true` | Schema validation |
122124
| "前缀API路径" | `apiPrefix: "'api'"` | Add prefix to paths |
123125

@@ -205,6 +207,8 @@ else if (isNodeProject) {
205207
isTranslateToEnglishTag: true,
206208
isDisplayTypeLabel: true,
207209
isSupportParseEnumDesc: true,
210+
// Custom regex for parsing enum descriptions like "普通 = 0" or "SampleMaker = 1"
211+
supportParseEnumDescByReg: /([^\s=<>/&;]+(?:\s+[^\s=<>/&;]+)*)\s*=\s*(\d+)/g,
208212
isCamelCase: true,
209213
filterCaseInsensitive: true,
210214
}

src/bin/openapi.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ const params = program
9797
'parse enum description to generate enum label',
9898
false
9999
)
100+
.option(
101+
'--supportParseEnumDescByReg <string>',
102+
'custom regex for parsing enum description'
103+
)
100104
.parse(process.argv)
101105
.opts();
102106

@@ -144,6 +148,9 @@ const baseGenerate = (_params_: OptionValues): GenerateServiceProps => {
144148
isCamelCase: JSON.parse(_params_.isCamelCase as string) === true,
145149
isSupportParseEnumDesc:
146150
JSON.parse(_params_.isSupportParseEnumDesc as string) === true,
151+
supportParseEnumDescByReg: _params_.supportParseEnumDescByReg as
152+
| string
153+
| RegExp,
147154
};
148155

149156
return options;

src/generator/serviceGenarator.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ import {
100100
isSchemaObject,
101101
markAllowedSchema,
102102
parseDescriptionEnum,
103+
parseDescriptionEnumByReg,
103104
replaceDot,
104105
resolveRefs,
105106
resolveTypeName,
@@ -1551,8 +1552,17 @@ export default class ServiceGenerator {
15511552
}).join(',')}}`;
15521553
} else {
15531554
if (numberEnum.includes(schemaObject.type) || isAllNumber(enumArray)) {
1554-
if (this.config.isSupportParseEnumDesc && schemaObject.description) {
1555-
const enumMap = parseDescriptionEnum(schemaObject.description);
1555+
if (
1556+
(this.config.isSupportParseEnumDesc ||
1557+
this.config.supportParseEnumDescByReg) &&
1558+
schemaObject.description
1559+
) {
1560+
const enumMap = this.config.isSupportParseEnumDesc
1561+
? parseDescriptionEnum(schemaObject.description)
1562+
: parseDescriptionEnumByReg(
1563+
schemaObject.description,
1564+
this.config.supportParseEnumDescByReg
1565+
);
15561566
enumLabelTypeStr = `{${map(enumArray, (value) => {
15571567
const enumLabel = enumMap.get(Number(value));
15581568
return `${Number(value)}:"${enumLabel}"`;

src/generator/util.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,57 @@ export const parseDescriptionEnum = (
573573
return enumMap;
574574
};
575575

576+
/**
577+
* 通过自定义正则表达式解析 description 中的枚举翻译
578+
* @param description 描述文本
579+
* @param regex 自定义正则表达式,用于匹配枚举项,例如:(\S+)\s*=\s*(\S+)
580+
* @returns Map<number, string> 枚举值到标签的映射
581+
*/
582+
export const parseDescriptionEnumByReg = (
583+
description: string,
584+
regex: string | RegExp
585+
): Map<number, string> => {
586+
const enumMap = new Map<number, string>();
587+
if (!description) return enumMap;
588+
589+
// 将字符串正则转换为 RegExp 对象,确保有全局标志
590+
let regExp: RegExp;
591+
if (typeof regex === 'string') {
592+
const flagsMatch = regex.match(/\/([gimsuy]*)$/);
593+
if (flagsMatch) {
594+
const parts = regex.split('/');
595+
const pattern = parts.slice(1, -1).join('/');
596+
const flags = flagsMatch[1] || '';
597+
regExp = new RegExp(pattern, flags.includes('g') ? flags : flags + 'g');
598+
} else {
599+
regExp = new RegExp(regex, 'g');
600+
}
601+
} else {
602+
const flags = regex.flags;
603+
regExp = flags.includes('g')
604+
? regex
605+
: new RegExp(regex.source, flags + 'g');
606+
}
607+
608+
// 匹配所有结果,然后对每个匹配结果按 = 拆分
609+
let match: RegExpExecArray | null;
610+
while ((match = regExp.exec(description)) !== null) {
611+
const fullMatch = match[0].trim();
612+
// 按 = 拆分,左边是标签,右边是值
613+
const parts = fullMatch.split(/\s*=\s*/);
614+
if (parts.length >= 2) {
615+
const label = parts[0].trim();
616+
const valueStr = parts[1].trim();
617+
const numValue = Number(valueStr);
618+
if (label && valueStr && !isNaN(numValue)) {
619+
enumMap.set(numValue, label);
620+
}
621+
}
622+
}
623+
624+
return enumMap;
625+
};
626+
576627
/**
577628
* 获取默认的二进制媒体类型列表
578629
*/

src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ export type GenerateServiceProps = {
159159
* 是否使用 description 中的枚举定义
160160
*/
161161
isSupportParseEnumDesc?: boolean;
162+
/**
163+
* 自定义正则表达式,用于解析 description 中的枚举定义
164+
* 如果设置了此参数,将使用此正则表达式替代默认的 parseDescriptionEnum 方法
165+
* 例如:/([^\s=<>/&;]+(?:\s+[^\s=<>/&;]+)*)\s*=\s*(\d+)/g 可以匹配 "普通 = 0" 或 "SampleMaker = 1" 这样的格式
166+
*/
167+
supportParseEnumDescByReg?: string | RegExp;
162168
/**
163169
* 命名空间名称,默认为API,不需要关注
164170
*/

0 commit comments

Comments
 (0)