Skip to content

Commit 89f905b

Browse files
committed
feat(openapi-v3): add operationId based on controller/method names
1 parent 8c7bd86 commit 89f905b

File tree

6 files changed

+73
-1
lines changed

6 files changed

+73
-1
lines changed

packages/openapi-v3/src/__tests__/integration/controller-spec.integration.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ describe('controller spec', () => {
6262
},
6363
},
6464
},
65+
'x-controller-name': 'FooController',
6566
'x-operation-name': 'create',
67+
operationId: 'FooController.create',
6668
},
6769
},
6870
},

packages/openapi-v3/src/__tests__/integration/operation-spec.integration.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import {expect} from '@loopback/testlab';
77
import {model, property} from '@loopback/repository';
8-
import {param, requestBody, getControllerSpec, post} from '../../';
8+
import {param, requestBody, getControllerSpec, post, get} from '../../';
99

1010
describe('operation arguments', () => {
1111
it('generate parameters and requestBody for operation', () => {
@@ -54,7 +54,9 @@ describe('operation arguments', () => {
5454
},
5555
'x-parameter-index': 3,
5656
},
57+
'x-controller-name': 'MyController',
5758
'x-operation-name': 'createUser',
59+
operationId: 'MyController.createUser',
5860
},
5961
},
6062
},
@@ -70,4 +72,34 @@ describe('operation arguments', () => {
7072
const spec = getControllerSpec(MyController);
7173
expect(spec).to.eql(expectedSpec);
7274
});
75+
76+
it('allows operation metadata in @get', () => {
77+
class MyController {
78+
@get('/users', {
79+
operationId: 'find_users',
80+
responses: {
81+
'200': {description: 'Users found'},
82+
},
83+
})
84+
async findUsers(): Promise<string[]> {
85+
return [];
86+
}
87+
}
88+
const expectedSpec = {
89+
paths: {
90+
'/users': {
91+
get: {
92+
responses: {
93+
'200': {description: 'Users found'},
94+
},
95+
'x-controller-name': 'MyController',
96+
'x-operation-name': 'findUsers',
97+
operationId: 'find_users',
98+
},
99+
},
100+
},
101+
};
102+
const spec = getControllerSpec(MyController);
103+
expect(spec).to.eql(expectedSpec);
104+
});
73105
});

packages/openapi-v3/src/__tests__/unit/decorators/operation.decorator.unit.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ describe('Routing metadata', () => {
6969
paths: {
7070
'/greet': {
7171
get: {
72+
'x-controller-name': 'MyController',
7273
'x-operation-name': 'greet',
74+
operationId: 'MyController.greet',
7375
...operationSpec,
7476
},
7577
},
@@ -93,7 +95,9 @@ describe('Routing metadata', () => {
9395
paths: {
9496
'/greeting': {
9597
post: {
98+
'x-controller-name': 'MyController',
9699
'x-operation-name': 'createGreeting',
100+
operationId: 'MyController.createGreeting',
97101
...operationSpec,
98102
},
99103
},
@@ -117,7 +121,9 @@ describe('Routing metadata', () => {
117121
paths: {
118122
'/greeting': {
119123
put: {
124+
'x-controller-name': 'MyController',
120125
'x-operation-name': 'updateGreeting',
126+
operationId: 'MyController.updateGreeting',
121127
...operationSpec,
122128
},
123129
},
@@ -141,7 +147,9 @@ describe('Routing metadata', () => {
141147
paths: {
142148
'/greeting': {
143149
patch: {
150+
'x-controller-name': 'MyController',
144151
'x-operation-name': 'patchGreeting',
152+
operationId: 'MyController.patchGreeting',
145153
...operationSpec,
146154
},
147155
},
@@ -165,7 +173,9 @@ describe('Routing metadata', () => {
165173
paths: {
166174
'/greeting': {
167175
delete: {
176+
'x-controller-name': 'MyController',
168177
'x-operation-name': 'deleteGreeting',
178+
operationId: 'MyController.deleteGreeting',
169179
...operationSpec,
170180
},
171181
},
@@ -189,7 +199,9 @@ describe('Routing metadata', () => {
189199
paths: {
190200
'/greeting': {
191201
post: {
202+
'x-controller-name': 'MyController',
192203
'x-operation-name': 'createGreeting',
204+
operationId: 'MyController.createGreeting',
193205
...operationSpec,
194206
},
195207
},
@@ -206,7 +218,9 @@ describe('Routing metadata', () => {
206218
const actualSpec = getControllerSpec(MyController);
207219

208220
expect(actualSpec.paths['/greet']['get']).to.eql({
221+
'x-controller-name': 'MyController',
209222
'x-operation-name': 'greet',
223+
operationId: 'MyController.greet',
210224
responses: {'200': {description: 'Return value of MyController.greet'}},
211225
});
212226
});
@@ -220,7 +234,9 @@ describe('Routing metadata', () => {
220234
const actualSpec = getControllerSpec(MyController);
221235

222236
expect(actualSpec.paths['/greeting']['post']).to.eql({
237+
'x-controller-name': 'MyController',
223238
'x-operation-name': 'createGreeting',
239+
operationId: 'MyController.createGreeting',
224240
responses: {
225241
'200': {description: 'Return value of MyController.createGreeting'},
226242
},
@@ -252,13 +268,17 @@ describe('Routing metadata', () => {
252268
paths: {
253269
'/parent': {
254270
get: {
271+
'x-controller-name': 'Child',
255272
'x-operation-name': 'getParentName',
273+
operationId: 'Child.getParentName',
256274
...operationSpec,
257275
},
258276
},
259277
'/child': {
260278
get: {
279+
'x-controller-name': 'Child',
261280
'x-operation-name': 'getChildName',
281+
operationId: 'Child.getChildName',
262282
...operationSpec,
263283
},
264284
},

packages/openapi-v3/src/__tests__/unit/decorators/param/param.decorator.unit.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ describe('Routing metadata for parameters', () => {
3232

3333
const expectedSpec = anOperationSpec()
3434
.withOperationName('greet')
35+
.withControllerName('MyController')
3536
.withParameter(paramSpec)
3637
.withResponse(200, {description: 'Return value of MyController.greet'})
3738
.build();
@@ -76,6 +77,7 @@ describe('Routing metadata for parameters', () => {
7677

7778
const expectedSpec = anOperationSpec()
7879
.withOperationName('update')
80+
.withControllerName('MyController')
7981
.withResponse(200, {description: 'Return value of MyController.update'})
8082
.withParameter({
8183
name: 'id',
@@ -145,6 +147,7 @@ describe('Routing metadata for parameters', () => {
145147

146148
const expectedSpec = anOperationSpec()
147149
.withOperationName('greet')
150+
.withControllerName('MyController')
148151
.withResponse(200, {description: 'Return value of MyController.greet'})
149152
.withParameter({
150153
name: 'names',
@@ -191,6 +194,7 @@ describe('Routing metadata for parameters', () => {
191194

192195
const expectedSpec = anOperationSpec()
193196
.withOperationName('greet')
197+
.withControllerName('MyController')
194198
.withResponse(200, {description: 'Return value of MyController.greet'})
195199
.withParameter({
196200
name: 'names',

packages/openapi-v3/src/controller-spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,18 @@ function resolveControllerSpec(constructor: Function): ControllerSpec {
186186
}
187187

188188
operationSpec['x-operation-name'] = op;
189+
operationSpec['x-controller-name'] =
190+
operationSpec['x-controller-name'] || constructor.name;
191+
192+
if (operationSpec.operationId == null) {
193+
// Build the operationId as `<controllerName>.<operationName>`
194+
// Please note API explorer (https://github.com/swagger-api/swagger-js/)
195+
// will normalize it as `<controllerName>_<operationName>`
196+
operationSpec.operationId =
197+
operationSpec['x-controller-name'] +
198+
'.' +
199+
operationSpec['x-operation-name'];
200+
}
189201

190202
if (!spec.paths[path]) {
191203
spec.paths[path] = {};

packages/rest/src/__tests__/unit/rest.server/rest.server.open-api-spec.unit.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ describe('RestServer.getApiSpec()', () => {
188188
responses: {'200': {description: ''}},
189189
'x-controller-name': 'MyController',
190190
'x-operation-name': 'greet',
191+
operationId: 'MyController.greet',
191192
tags: ['MyTag'],
192193
},
193194
},
@@ -248,6 +249,7 @@ describe('RestServer.getApiSpec()', () => {
248249
},
249250
'x-controller-name': 'MyController',
250251
'x-operation-name': 'greet',
252+
operationId: 'MyController.greet',
251253
tags: ['MyController'],
252254
},
253255
},

0 commit comments

Comments
 (0)