Skip to content

Commit 38e55c0

Browse files
committed
feat: 允许配置rpc方法名的生成规则
1 parent c0ba0e7 commit 38e55c0

File tree

9 files changed

+91
-16
lines changed

9 files changed

+91
-16
lines changed

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,34 @@ await client.user.getUsersById(opts);
204204

205205
**注意**:rpc-group模式下,如果没有提供tags,则默认合并到`default`分组
206206

207+
### rpcName
208+
209+
类型:`'method+uri' | 'operationId'`<br>
210+
默认值:`'method+uri'`
211+
212+
指定在rpc(-group)模式下方法名的生成规则。
213+
214+
假设有这么一段openapi文档:
215+
216+
```json
217+
{
218+
"paths": {
219+
"/client/users": {
220+
"get": {
221+
"operationId": "List_users",
222+
"parameters": [],
223+
"summary": "Users"
224+
}
225+
}
226+
}
227+
}
228+
```
229+
230+
1. 如果以 `method+uri` 的形式生成,则效果为:`openapi.getClientUsers()`
231+
2. 如果以 `operationId` 的形式生成,则效果为:`openapi.listUsers()`
232+
233+
**注意**:如果operationId字段不存在,则仍以`method+uri`的规则生成
234+
207235
### onDocumentLoaded
208236

209237
类型:`(docs: Document) => Document | void`

src/bin.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { pathToOpenapi } from './lib/path-to-openapi';
1010
import { saveToFile } from './lib/save-to-file';
1111
import { generateTemplate } from './lib/generate-template';
1212
import { filterTag } from './lib/filter-tag';
13-
import { filterUrl } from './lib/filter-url';
13+
import { filterUri } from './lib/filter-uri';
1414
import { readConfig } from './lib/read-config';
1515
import { SilentSpinner } from './silent-spinner';
1616

@@ -80,7 +80,7 @@ spinner.add({
8080
},
8181
task: async (ctx) => {
8282
ctx.configs.forEach((config, i) => {
83-
filterUrl(ctx.docs[i]!, config);
83+
filterUri(ctx.docs[i]!, config);
8484
});
8585
await sleep();
8686
},

src/define-config.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,29 @@ export interface OpenapiClientConfig {
4343
* ```
4444
*/
4545
classMode?: 'rest' | 'rpc' | 'rpc-group';
46+
/**
47+
* 指定在rpc(-group)模式下方法名的生成规则。默认:`method+uri`
48+
*
49+
* 假设有这么一段openapi文档:
50+
* ```json
51+
* {
52+
* "paths": {
53+
* "/client/users": {
54+
* "get": {
55+
* "operationId": "List_users",
56+
* "parameters": [],
57+
* "summary": "Users"
58+
* }
59+
* }
60+
* }
61+
* }
62+
* ```
63+
* 1. 如果以 `method+uri` 的形式生成,则效果为:`openapi.getClientUsers()`
64+
* 2. 如果以 `operationId` 的形式生成,则效果为:`openapi.listUsers()`
65+
*
66+
* 注意:如果operationId字段不存在,则仍以`method+uri`的规则生成
67+
*/
68+
rpcName?: 'method+uri' | 'operationId';
4669
/**
4770
* 加载完openapi文档后的事件,允许直接对文档进行修改
4871
*/

src/lib/document-to-meta.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import { snakeCase } from 'lodash-es';
44
import { parseParameters } from './parse-parameters';
55
import { parseRequestBody } from './parse-request-body';
66
import { parseResponse } from './parse-response';
7+
import type { OpenapiClientConfig } from '../define-config';
78

89
export type Metas = Record<
910
Methods,
1011
{
1112
key: string;
1213
uri: string;
1314
method: Methods;
15+
operationId?: string;
1416
contentTypes: string[];
1517
query: { optional: boolean; types: [string] | [] };
1618
params: { optional: boolean; types: [string] | [] };
@@ -23,7 +25,10 @@ export type Metas = Record<
2325
}[]
2426
>;
2527

26-
export const documentToMeta = (docs: OpenAPIV3.Document) => {
28+
export const documentToMeta = (
29+
docs: OpenAPIV3.Document,
30+
rpcName: OpenapiClientConfig['rpcName'],
31+
) => {
2732
const metas: Metas = {
2833
get: [],
2934
post: [],
@@ -39,7 +44,11 @@ export const documentToMeta = (docs: OpenAPIV3.Document) => {
3944
metas[method].push({
4045
uri,
4146
method,
42-
key: snakeCase(`${method}_${uri.replaceAll(/{(.+?)}/g, '_by_$1')}`),
47+
key: snakeCase(
48+
rpcName === 'operationId' && methodItem.operationId
49+
? methodItem.operationId
50+
: `${method}_${uri.replaceAll(/{(.+?)}/g, '_by_$1')}`,
51+
),
4352
query: parseParameters(docs, pathItem, methodItem, 'query'),
4453
params: parseParameters(docs, pathItem, methodItem, 'path'),
4554
...parseRequestBody(docs, methodItem),

src/lib/filter-url.ts renamed to src/lib/filter-uri.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { OpenAPIV3 } from 'openapi-types';
22
import type { OpenapiClientConfig } from '../define-config';
33

4-
export const filterUrl = (docs: OpenAPIV3.Document, config: OpenapiClientConfig) => {
4+
export const filterUri = (docs: OpenAPIV3.Document, config: OpenapiClientConfig) => {
55
if (!config.includeUriPrefix) return;
66
const patterns = Array.isArray(config.includeUriPrefix)
77
? config.includeUriPrefix

src/lib/generate-template.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ import { pickContentTypes } from './template';
99

1010
export const generateTemplate = async (
1111
docs: OpenAPIV3.Document,
12-
config: Pick<OpenapiClientConfig, 'projectName' | 'classMode'>,
12+
config: Pick<OpenapiClientConfig, 'projectName' | 'classMode' | 'rpcName'>,
1313
) => {
14-
const { projectName = '', classMode = 'rest' } = config;
14+
const { projectName = '', classMode = 'rest', rpcName = 'method+uri' } = config;
1515
const className = `OpenapiClient${upperFirst(camelCase(projectName))}`;
16-
const metas = documentToMeta(docs);
16+
const metas = documentToMeta(docs, rpcName);
1717

1818
const classTpl =
1919
classMode === 'rest'

test/bin.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ test('生成 bin.mjs', async () => {
1515
expect(existsSync(path.resolve('dist', 'bin.mjs')));
1616
});
1717

18-
test('生成runtime并合并代码', { timeout: 9_000 }, async () => {
18+
test('写入指定文件', { timeout: 9_000 }, async () => {
1919
execSync('node dist/bin.mjs', { encoding: 'utf8', stdio: 'inherit' });
2020
expect(readFileSync(path.resolve('src', 'openapi', 'openapi.ts'), 'utf8')).toContain(
2121
'export namespace OpenapiClient {',

test/lib/document-to-meta.test.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,20 @@ test('key从路由获取', () => {
1212
},
1313
});
1414

15-
expect(documentToMeta(docs)['get'][0]!.key).toBe('get_users_by_id_by_name');
15+
expect(documentToMeta(docs, 'method+uri')['get'][0]!.key).toBe(
16+
'get_users_by_id_by_name',
17+
);
18+
});
19+
20+
test('key从operationId获取', () => {
21+
const docs = getBasicDocument({
22+
'/users/{id}/{name}': {
23+
get: {
24+
operationId: 'Abc_def IJK',
25+
responses: {},
26+
},
27+
},
28+
});
29+
30+
expect(documentToMeta(docs, 'operationId')['get'][0]!.key).toBe('abc_def_ijk');
1631
});

test/lib/filter-url.test.ts renamed to test/lib/filter-uri.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { expect, test } from 'vitest';
22
import { getBasicDocument } from '../mocks/get-basic-document';
3-
import { filterUrl } from '../../src/lib/filter-url';
3+
import { filterUri } from '../../src/lib/filter-uri';
44

55
test('未指定过滤路由则不处理', () => {
66
const docs = getBasicDocument({
@@ -10,7 +10,7 @@ test('未指定过滤路由则不处理', () => {
1010
'/other': {},
1111
});
1212

13-
filterUrl(docs, { url: '' });
13+
filterUri(docs, { url: '' });
1414
expect(Object.keys(docs.paths)).toMatchInlineSnapshot(`
1515
[
1616
"/",
@@ -19,7 +19,7 @@ test('未指定过滤路由则不处理', () => {
1919
"/other",
2020
]
2121
`);
22-
filterUrl(docs, { url: '', includeUriPrefix: [] });
22+
filterUri(docs, { url: '', includeUriPrefix: [] });
2323
expect(Object.keys(docs.paths)).toMatchInlineSnapshot(`
2424
[
2525
"/",
@@ -38,7 +38,7 @@ test('不符合前缀的路由被删除', () => {
3838
'/other': {},
3939
});
4040

41-
filterUrl(docs, { url: '', includeUriPrefix: '/test' });
41+
filterUri(docs, { url: '', includeUriPrefix: '/test' });
4242
expect(Object.keys(docs.paths)).toMatchInlineSnapshot(`
4343
[
4444
"/test/a",
@@ -56,7 +56,7 @@ test('同时过滤多个路由', () => {
5656
'/foo/bar': {},
5757
});
5858

59-
filterUrl(docs, { url: '', includeUriPrefix: ['/test', '/foo'] });
59+
filterUri(docs, { url: '', includeUriPrefix: ['/test', '/foo'] });
6060
expect(Object.keys(docs.paths)).toMatchInlineSnapshot(`
6161
[
6262
"/test/a",
@@ -75,7 +75,7 @@ test('支持正则表达式', () => {
7575
'/foo/bar': {},
7676
});
7777

78-
filterUrl(docs, { url: '', includeUriPrefix: [/\/a/] });
78+
filterUri(docs, { url: '', includeUriPrefix: [/\/a/] });
7979
expect(Object.keys(docs.paths)).toMatchInlineSnapshot(`
8080
[
8181
"/test/a",

0 commit comments

Comments
 (0)