Skip to content

Commit 920cf80

Browse files
authored
Merge pull request #16 from askvortcov/allowIgnoringOperationId
Allow ignoring operation
2 parents efbfba5 + e4c3846 commit 920cf80

14 files changed

+149
-95
lines changed

bin/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const params = program
2020
.option('--exportCore <value>', 'Write core files to disk', true)
2121
.option('--exportServices <value>', 'Write services to disk', true)
2222
.option('--exportModels <value>', 'Write models to disk', true)
23+
.option('--useOperationId <value>', 'Use operation id to generate operation names', true)
2324
.option('--exportSchemas <value>', 'Write schemas to disk', false)
2425
.option('--indent <value>', 'Indentation options [4, 2, tabs]', '4')
2526
.option('--postfixServices <value>', 'Service name postfix', 'Service')
@@ -51,6 +52,7 @@ if (OpenAPI) {
5152
exportServices: parseBooleanOrString(params.exportServices),
5253
exportModels: parseBooleanOrString(params.exportModels),
5354
exportSchemas: JSON.parse(params.exportSchemas) === true,
55+
useOperationId: JSON.parse(params.useOperationId) === true,
5456
indent: params.indent,
5557
postfixServices: params.postfixServices,
5658
postfixModels: params.postfixModels,

src/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export type Options = {
2424
exportServices?: boolean | string;
2525
exportModels?: boolean | string;
2626
exportSchemas?: boolean;
27+
useOperationId?: boolean;
2728
indent?: Indent;
2829
postfixServices?: string;
2930
postfixModels?: string;
@@ -45,6 +46,7 @@ export type Options = {
4546
* @param exportServices Generate services
4647
* @param exportModels Generate models
4748
* @param exportSchemas Generate schemas
49+
* @param ignoreOperationId Ignore operationId
4850
* @param indent Indentation options (4, 2 or tab)
4951
* @param postfixServices Service name postfix
5052
* @param postfixModels Model name postfix
@@ -63,6 +65,7 @@ export const generate = async ({
6365
exportServices = true,
6466
exportModels = true,
6567
exportSchemas = false,
68+
useOperationId = true,
6669
indent = Indent.SPACE_4,
6770
postfixServices = 'Service',
6871
postfixModels = '',
@@ -92,7 +95,7 @@ export const generate = async ({
9295
}
9396

9497
if (parser) {
95-
const client = parser(openApi);
98+
const client = parser(openApi, useOperationId);
9699
const clientFinal = postProcessClient(client);
97100
if (write) {
98101
await writeClient(

src/openApi/v2/index.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ import { getServiceVersion } from './parser/getServiceVersion';
88
/**
99
* Parse the OpenAPI specification to a Client model that contains
1010
* all the models, services and schema's we should output.
11-
* @param openApi The OpenAPI spec that we have loaded from disk.
11+
* @param openApi The OpenAPI spec that we have loaded from disk.
12+
* @param useOperationId should the operationId be used when generating operation names
1213
*/
13-
export const parse = (openApi: OpenApi): Client => {
14+
export const parse = (openApi: OpenApi, useOperationId: boolean): Client => {
1415
const version = getServiceVersion(openApi.info.version);
1516
const server = getServer(openApi);
1617
const models = getModels(openApi);
17-
const services = getServices(openApi);
18+
const services = getServices(openApi, useOperationId);
1819

1920
return { version, server, models, services };
2021
};

src/openApi/v2/parser/getOperation.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ export const getOperation = (
1717
method: string,
1818
tag: string,
1919
op: OpenApiOperation,
20-
pathParams: OperationParameters
20+
pathParams: OperationParameters,
21+
useOperationId: boolean
2122
): Operation => {
2223
const serviceName = getServiceName(tag);
23-
const operationName = getOperationName(url, method, op.operationId);
24+
const operationName = getOperationName(url, method, useOperationId, op.operationId);
2425

2526
// Create a new operation object for this method.
2627
const operation: Operation = {

src/openApi/v2/parser/getOperationName.spec.ts

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,32 @@ import { getOperationName } from './getOperationName';
22

33
describe('getOperationName', () => {
44
it('should produce correct result', () => {
5-
expect(getOperationName('/api/v{api-version}/users', 'GET', 'GetAllUsers')).toEqual('getAllUsers');
6-
expect(getOperationName('/api/v{api-version}/users', 'GET', undefined)).toEqual('getApiUsers');
7-
expect(getOperationName('/api/v{api-version}/users', 'POST', undefined)).toEqual('postApiUsers');
8-
expect(getOperationName('/api/v1/users', 'GET', 'GetAllUsers')).toEqual('getAllUsers');
9-
expect(getOperationName('/api/v1/users', 'GET', undefined)).toEqual('getApiV1Users');
10-
expect(getOperationName('/api/v1/users', 'POST', undefined)).toEqual('postApiV1Users');
11-
expect(getOperationName('/api/v1/users/{id}', 'GET', undefined)).toEqual('getApiV1Users');
12-
expect(getOperationName('/api/v1/users/{id}', 'POST', undefined)).toEqual('postApiV1Users');
5+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, 'GetAllUsers')).toEqual('getAllUsers');
6+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, undefined)).toEqual('getApiUsers');
7+
expect(getOperationName('/api/v{api-version}/users', 'POST', true, undefined)).toEqual('postApiUsers');
8+
expect(getOperationName('/api/v1/users', 'GET', true, 'GetAllUsers')).toEqual('getAllUsers');
9+
expect(getOperationName('/api/v1/users', 'GET', true, undefined)).toEqual('getApiV1Users');
10+
expect(getOperationName('/api/v1/users', 'POST', true, undefined)).toEqual('postApiV1Users');
11+
expect(getOperationName('/api/v1/users/{id}', 'GET', true, undefined)).toEqual('getApiV1UsersById');
12+
expect(getOperationName('/api/v1/users/{id}', 'POST', true, undefined)).toEqual('postApiV1UsersById');
1313

14-
expect(getOperationName('/api/v{api-version}/users', 'GET', 'fooBar')).toEqual('fooBar');
15-
expect(getOperationName('/api/v{api-version}/users', 'GET', 'FooBar')).toEqual('fooBar');
16-
expect(getOperationName('/api/v{api-version}/users', 'GET', 'Foo Bar')).toEqual('fooBar');
17-
expect(getOperationName('/api/v{api-version}/users', 'GET', 'foo bar')).toEqual('fooBar');
18-
expect(getOperationName('/api/v{api-version}/users', 'GET', 'foo-bar')).toEqual('fooBar');
19-
expect(getOperationName('/api/v{api-version}/users', 'GET', 'foo_bar')).toEqual('fooBar');
20-
expect(getOperationName('/api/v{api-version}/users', 'GET', 'foo.bar')).toEqual('fooBar');
21-
expect(getOperationName('/api/v{api-version}/users', 'GET', '@foo.bar')).toEqual('fooBar');
22-
expect(getOperationName('/api/v{api-version}/users', 'GET', '$foo.bar')).toEqual('fooBar');
23-
expect(getOperationName('/api/v{api-version}/users', 'GET', '_foo.bar')).toEqual('fooBar');
24-
expect(getOperationName('/api/v{api-version}/users', 'GET', '-foo.bar')).toEqual('fooBar');
25-
expect(getOperationName('/api/v{api-version}/users', 'GET', '123.foo.bar')).toEqual('fooBar');
14+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, 'fooBar')).toEqual('fooBar');
15+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, 'FooBar')).toEqual('fooBar');
16+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, 'Foo Bar')).toEqual('fooBar');
17+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, 'foo bar')).toEqual('fooBar');
18+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, 'foo-bar')).toEqual('fooBar');
19+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, 'foo_bar')).toEqual('fooBar');
20+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, 'foo.bar')).toEqual('fooBar');
21+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, '@foo.bar')).toEqual('fooBar');
22+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, '$foo.bar')).toEqual('fooBar');
23+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, '_foo.bar')).toEqual('fooBar');
24+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, '-foo.bar')).toEqual('fooBar');
25+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, '123.foo.bar')).toEqual('fooBar');
26+
27+
expect(getOperationName('/api/v1/users', 'GET', false, 'GetAllUsers')).toEqual('getApiV1Users');
28+
expect(getOperationName('/api/v{api-version}/users', 'GET', false, 'fooBar')).toEqual('getApiUsers');
29+
expect(
30+
getOperationName('/api/v{api-version}/users/{userId}/location/{locationId}', 'GET', false, 'fooBar')
31+
).toEqual('getApiUsersByUserIdLocationByLocationId');
2632
});
2733
});

src/openApi/v2/parser/getOperationName.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,19 @@ import sanitizeOperationName from '../../../utils/sanitizeOperationName';
77
* This will use the operation ID - if available - and otherwise fallback
88
* on a generated name from the URL
99
*/
10-
export const getOperationName = (url: string, method: string, operationId?: string): string => {
11-
if (operationId) {
10+
export const getOperationName = (
11+
url: string,
12+
method: string,
13+
useOperationId: boolean,
14+
operationId?: string
15+
): string => {
16+
if (useOperationId && operationId) {
1217
return camelCase(sanitizeOperationName(operationId).trim());
1318
}
1419

1520
const urlWithoutPlaceholders = url
1621
.replace(/[^/]*?{api-version}.*?\//g, '')
17-
.replace(/{(.*?)}/g, '')
22+
.replace(/{(.*?)}/g, 'by-$1')
1823
.replace(/\//g, '-');
1924

2025
return camelCase(`${method}-${urlWithoutPlaceholders}`);

src/openApi/v2/parser/getServices.spec.ts

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,31 @@ import { getServices } from './getServices';
22

33
describe('getServices', () => {
44
it('should create a unnamed service if tags are empty', () => {
5-
const services = getServices({
6-
swagger: '2.0',
7-
info: {
8-
title: 'x',
9-
version: '1',
10-
},
11-
paths: {
12-
'/api/trips': {
13-
get: {
14-
tags: [],
15-
responses: {
16-
200: {
17-
description: 'x',
18-
},
19-
default: {
20-
description: 'default',
5+
const services = getServices(
6+
{
7+
swagger: '2.0',
8+
info: {
9+
title: 'x',
10+
version: '1',
11+
},
12+
paths: {
13+
'/api/trips': {
14+
get: {
15+
tags: [],
16+
responses: {
17+
200: {
18+
description: 'x',
19+
},
20+
default: {
21+
description: 'default',
22+
},
2123
},
2224
},
2325
},
2426
},
2527
},
26-
});
28+
false
29+
);
2730

2831
expect(services).toHaveLength(1);
2932
expect(services[0].name).toEqual('Default');

src/openApi/v2/parser/getServices.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { getOperationParameters } from './getOperationParameters';
77
/**
88
* Get the OpenAPI services
99
*/
10-
export const getServices = (openApi: OpenApi): Service[] => {
10+
export const getServices = (openApi: OpenApi, useOperationId: boolean): Service[] => {
1111
const services = new Map<string, Service>();
1212
for (const url in openApi.paths) {
1313
if (openApi.paths.hasOwnProperty(url)) {
@@ -30,7 +30,15 @@ export const getServices = (openApi: OpenApi): Service[] => {
3030
const op = path[method]!;
3131
const tags = op.tags?.length ? op.tags.filter(unique) : ['Default'];
3232
tags.forEach(tag => {
33-
const operation = getOperation(openApi, url, method, tag, op, pathParams);
33+
const operation = getOperation(
34+
openApi,
35+
url,
36+
method,
37+
tag,
38+
op,
39+
pathParams,
40+
useOperationId
41+
);
3442

3543
// If we have already declared a service, then we should fetch that and
3644
// append the new method to it. Otherwise we should create a new service object.

src/openApi/v3/index.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ import { getServiceVersion } from './parser/getServiceVersion';
88
/**
99
* Parse the OpenAPI specification to a Client model that contains
1010
* all the models, services and schema's we should output.
11-
* @param openApi The OpenAPI spec that we have loaded from disk.
11+
* @param openApi The OpenAPI spec that we have loaded from disk.
12+
* @param useOperationId should the operationId be used when generating operation names
1213
*/
13-
export const parse = (openApi: OpenApi): Client => {
14+
export const parse = (openApi: OpenApi, useOperationId: boolean): Client => {
1415
const version = getServiceVersion(openApi.info.version);
1516
const server = getServer(openApi);
1617
const models = getModels(openApi);
17-
const services = getServices(openApi);
18+
const services = getServices(openApi, useOperationId);
1819

1920
return { version, server, models, services };
2021
};

src/openApi/v3/parser/getOperation.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@ export const getOperation = (
2020
method: string,
2121
tag: string,
2222
op: OpenApiOperation,
23-
pathParams: OperationParameters
23+
pathParams: OperationParameters,
24+
useOperationId: boolean
2425
): Operation => {
2526
const serviceName = getServiceName(tag);
26-
const operationName = getOperationName(url, method, op.operationId);
27+
const operationName = getOperationName(url, method, useOperationId, op.operationId);
2728

2829
// Create a new operation object for this method.
2930
const operation: Operation = {

src/openApi/v3/parser/getOperationName.spec.ts

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,32 @@ import { getOperationName } from './getOperationName';
22

33
describe('getOperationName', () => {
44
it('should produce correct result', () => {
5-
expect(getOperationName('/api/v{api-version}/users', 'GET', 'GetAllUsers')).toEqual('getAllUsers');
6-
expect(getOperationName('/api/v{api-version}/users', 'GET', undefined)).toEqual('getApiUsers');
7-
expect(getOperationName('/api/v{api-version}/users', 'POST', undefined)).toEqual('postApiUsers');
8-
expect(getOperationName('/api/v1/users', 'GET', 'GetAllUsers')).toEqual('getAllUsers');
9-
expect(getOperationName('/api/v1/users', 'GET', undefined)).toEqual('getApiV1Users');
10-
expect(getOperationName('/api/v1/users', 'POST', undefined)).toEqual('postApiV1Users');
11-
expect(getOperationName('/api/v1/users/{id}', 'GET', undefined)).toEqual('getApiV1Users');
12-
expect(getOperationName('/api/v1/users/{id}', 'POST', undefined)).toEqual('postApiV1Users');
5+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, 'GetAllUsers')).toEqual('getAllUsers');
6+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, undefined)).toEqual('getApiUsers');
7+
expect(getOperationName('/api/v{api-version}/users', 'POST', true, undefined)).toEqual('postApiUsers');
8+
expect(getOperationName('/api/v1/users', 'GET', true, 'GetAllUsers')).toEqual('getAllUsers');
9+
expect(getOperationName('/api/v1/users', 'GET', true, undefined)).toEqual('getApiV1Users');
10+
expect(getOperationName('/api/v1/users', 'POST', true, undefined)).toEqual('postApiV1Users');
11+
expect(getOperationName('/api/v1/users/{id}', 'GET', true, undefined)).toEqual('getApiV1UsersById');
12+
expect(getOperationName('/api/v1/users/{id}', 'POST', true, undefined)).toEqual('postApiV1UsersById');
1313

14-
expect(getOperationName('/api/v{api-version}/users', 'GET', 'fooBar')).toEqual('fooBar');
15-
expect(getOperationName('/api/v{api-version}/users', 'GET', 'FooBar')).toEqual('fooBar');
16-
expect(getOperationName('/api/v{api-version}/users', 'GET', 'Foo Bar')).toEqual('fooBar');
17-
expect(getOperationName('/api/v{api-version}/users', 'GET', 'foo bar')).toEqual('fooBar');
18-
expect(getOperationName('/api/v{api-version}/users', 'GET', 'foo-bar')).toEqual('fooBar');
19-
expect(getOperationName('/api/v{api-version}/users', 'GET', 'foo_bar')).toEqual('fooBar');
20-
expect(getOperationName('/api/v{api-version}/users', 'GET', 'foo.bar')).toEqual('fooBar');
21-
expect(getOperationName('/api/v{api-version}/users', 'GET', '@foo.bar')).toEqual('fooBar');
22-
expect(getOperationName('/api/v{api-version}/users', 'GET', '$foo.bar')).toEqual('fooBar');
23-
expect(getOperationName('/api/v{api-version}/users', 'GET', '_foo.bar')).toEqual('fooBar');
24-
expect(getOperationName('/api/v{api-version}/users', 'GET', '-foo.bar')).toEqual('fooBar');
25-
expect(getOperationName('/api/v{api-version}/users', 'GET', '123.foo.bar')).toEqual('fooBar');
14+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, 'fooBar')).toEqual('fooBar');
15+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, 'FooBar')).toEqual('fooBar');
16+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, 'Foo Bar')).toEqual('fooBar');
17+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, 'foo bar')).toEqual('fooBar');
18+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, 'foo-bar')).toEqual('fooBar');
19+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, 'foo_bar')).toEqual('fooBar');
20+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, 'foo.bar')).toEqual('fooBar');
21+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, '@foo.bar')).toEqual('fooBar');
22+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, '$foo.bar')).toEqual('fooBar');
23+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, '_foo.bar')).toEqual('fooBar');
24+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, '-foo.bar')).toEqual('fooBar');
25+
expect(getOperationName('/api/v{api-version}/users', 'GET', true, '123.foo.bar')).toEqual('fooBar');
26+
27+
expect(getOperationName('/api/v1/users', 'GET', false, 'GetAllUsers')).toEqual('getApiV1Users');
28+
expect(getOperationName('/api/v{api-version}/users', 'GET', false, 'fooBar')).toEqual('getApiUsers');
29+
expect(
30+
getOperationName('/api/v{api-version}/users/{userId}/location/{locationId}', 'GET', false, 'fooBar')
31+
).toEqual('getApiUsersByUserIdLocationByLocationId');
2632
});
2733
});

src/openApi/v3/parser/getOperationName.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,19 @@ import sanitizeOperationName from '../../../utils/sanitizeOperationName';
77
* This will use the operation ID - if available - and otherwise fallback
88
* on a generated name from the URL
99
*/
10-
export const getOperationName = (url: string, method: string, operationId?: string): string => {
11-
if (operationId) {
10+
export const getOperationName = (
11+
url: string,
12+
method: string,
13+
useOperationId: boolean,
14+
operationId?: string
15+
): string => {
16+
if (useOperationId && operationId) {
1217
return camelCase(sanitizeOperationName(operationId).trim());
1318
}
1419

1520
const urlWithoutPlaceholders = url
1621
.replace(/[^/]*?{api-version}.*?\//g, '')
17-
.replace(/{(.*?)}/g, '')
22+
.replace(/{(.*?)}/g, 'by-$1')
1823
.replace(/\//g, '-');
1924

2025
return camelCase(`${method}-${urlWithoutPlaceholders}`);

0 commit comments

Comments
 (0)