Skip to content

Commit

Permalink
feat: 允许配置rpc方法名的生成规则
Browse files Browse the repository at this point in the history
  • Loading branch information
geekact committed Jan 2, 2025
1 parent c0ba0e7 commit 38e55c0
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 16 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,34 @@ await client.user.getUsersById(opts);

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

### rpcName

类型:`'method+uri' | 'operationId'`<br>
默认值:`'method+uri'`

指定在rpc(-group)模式下方法名的生成规则。

假设有这么一段openapi文档:

```json
{
"paths": {
"/client/users": {
"get": {
"operationId": "List_users",
"parameters": [],
"summary": "Users"
}
}
}
}
```

1. 如果以 `method+uri` 的形式生成,则效果为:`openapi.getClientUsers()`
2. 如果以 `operationId` 的形式生成,则效果为:`openapi.listUsers()`

**注意**:如果operationId字段不存在,则仍以`method+uri`的规则生成

### onDocumentLoaded

类型:`(docs: Document) => Document | void`
Expand Down
4 changes: 2 additions & 2 deletions src/bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { pathToOpenapi } from './lib/path-to-openapi';
import { saveToFile } from './lib/save-to-file';
import { generateTemplate } from './lib/generate-template';
import { filterTag } from './lib/filter-tag';
import { filterUrl } from './lib/filter-url';
import { filterUri } from './lib/filter-uri';
import { readConfig } from './lib/read-config';
import { SilentSpinner } from './silent-spinner';

Expand Down Expand Up @@ -80,7 +80,7 @@ spinner.add({
},
task: async (ctx) => {
ctx.configs.forEach((config, i) => {
filterUrl(ctx.docs[i]!, config);
filterUri(ctx.docs[i]!, config);
});
await sleep();
},
Expand Down
23 changes: 23 additions & 0 deletions src/define-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,29 @@ export interface OpenapiClientConfig {
* ```
*/
classMode?: 'rest' | 'rpc' | 'rpc-group';
/**
* 指定在rpc(-group)模式下方法名的生成规则。默认:`method+uri`
*
* 假设有这么一段openapi文档:
* ```json
* {
* "paths": {
* "/client/users": {
* "get": {
* "operationId": "List_users",
* "parameters": [],
* "summary": "Users"
* }
* }
* }
* }
* ```
* 1. 如果以 `method+uri` 的形式生成,则效果为:`openapi.getClientUsers()`
* 2. 如果以 `operationId` 的形式生成,则效果为:`openapi.listUsers()`
*
* 注意:如果operationId字段不存在,则仍以`method+uri`的规则生成
*/
rpcName?: 'method+uri' | 'operationId';
/**
* 加载完openapi文档后的事件,允许直接对文档进行修改
*/
Expand Down
13 changes: 11 additions & 2 deletions src/lib/document-to-meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import { snakeCase } from 'lodash-es';
import { parseParameters } from './parse-parameters';
import { parseRequestBody } from './parse-request-body';
import { parseResponse } from './parse-response';
import type { OpenapiClientConfig } from '../define-config';

export type Metas = Record<
Methods,
{
key: string;
uri: string;
method: Methods;
operationId?: string;
contentTypes: string[];
query: { optional: boolean; types: [string] | [] };
params: { optional: boolean; types: [string] | [] };
Expand All @@ -23,7 +25,10 @@ export type Metas = Record<
}[]
>;

export const documentToMeta = (docs: OpenAPIV3.Document) => {
export const documentToMeta = (
docs: OpenAPIV3.Document,
rpcName: OpenapiClientConfig['rpcName'],
) => {
const metas: Metas = {
get: [],
post: [],
Expand All @@ -39,7 +44,11 @@ export const documentToMeta = (docs: OpenAPIV3.Document) => {
metas[method].push({
uri,
method,
key: snakeCase(`${method}_${uri.replaceAll(/{(.+?)}/g, '_by_$1')}`),
key: snakeCase(
rpcName === 'operationId' && methodItem.operationId
? methodItem.operationId
: `${method}_${uri.replaceAll(/{(.+?)}/g, '_by_$1')}`,
),
query: parseParameters(docs, pathItem, methodItem, 'query'),
params: parseParameters(docs, pathItem, methodItem, 'path'),
...parseRequestBody(docs, methodItem),
Expand Down
2 changes: 1 addition & 1 deletion src/lib/filter-url.ts → src/lib/filter-uri.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { OpenAPIV3 } from 'openapi-types';
import type { OpenapiClientConfig } from '../define-config';

export const filterUrl = (docs: OpenAPIV3.Document, config: OpenapiClientConfig) => {
export const filterUri = (docs: OpenAPIV3.Document, config: OpenapiClientConfig) => {
if (!config.includeUriPrefix) return;
const patterns = Array.isArray(config.includeUriPrefix)
? config.includeUriPrefix
Expand Down
6 changes: 3 additions & 3 deletions src/lib/generate-template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import { pickContentTypes } from './template';

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

const classTpl =
classMode === 'rest'
Expand Down
2 changes: 1 addition & 1 deletion test/bin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ test('生成 bin.mjs', async () => {
expect(existsSync(path.resolve('dist', 'bin.mjs')));
});

test('生成runtime并合并代码', { timeout: 9_000 }, async () => {
test('写入指定文件', { timeout: 9_000 }, async () => {
execSync('node dist/bin.mjs', { encoding: 'utf8', stdio: 'inherit' });
expect(readFileSync(path.resolve('src', 'openapi', 'openapi.ts'), 'utf8')).toContain(
'export namespace OpenapiClient {',
Expand Down
17 changes: 16 additions & 1 deletion test/lib/document-to-meta.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,20 @@ test('key从路由获取', () => {
},
});

expect(documentToMeta(docs)['get'][0]!.key).toBe('get_users_by_id_by_name');
expect(documentToMeta(docs, 'method+uri')['get'][0]!.key).toBe(
'get_users_by_id_by_name',
);
});

test('key从operationId获取', () => {
const docs = getBasicDocument({
'/users/{id}/{name}': {
get: {
operationId: 'Abc_def IJK',
responses: {},
},
},
});

expect(documentToMeta(docs, 'operationId')['get'][0]!.key).toBe('abc_def_ijk');
});
12 changes: 6 additions & 6 deletions test/lib/filter-url.test.ts → test/lib/filter-uri.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, test } from 'vitest';
import { getBasicDocument } from '../mocks/get-basic-document';
import { filterUrl } from '../../src/lib/filter-url';
import { filterUri } from '../../src/lib/filter-uri';

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

filterUrl(docs, { url: '' });
filterUri(docs, { url: '' });
expect(Object.keys(docs.paths)).toMatchInlineSnapshot(`
[
"/",
Expand All @@ -19,7 +19,7 @@ test('未指定过滤路由则不处理', () => {
"/other",
]
`);
filterUrl(docs, { url: '', includeUriPrefix: [] });
filterUri(docs, { url: '', includeUriPrefix: [] });
expect(Object.keys(docs.paths)).toMatchInlineSnapshot(`
[
"/",
Expand All @@ -38,7 +38,7 @@ test('不符合前缀的路由被删除', () => {
'/other': {},
});

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

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

filterUrl(docs, { url: '', includeUriPrefix: [/\/a/] });
filterUri(docs, { url: '', includeUriPrefix: [/\/a/] });
expect(Object.keys(docs.paths)).toMatchInlineSnapshot(`
[
"/test/a",
Expand Down

0 comments on commit 38e55c0

Please sign in to comment.