Skip to content

Commit f67f5c8

Browse files
committed
support for service.id array: add tests for full coverage, extend and fix type definitions, extend readme
1 parent 7e72538 commit f67f5c8

File tree

6 files changed

+138
-18
lines changed

6 files changed

+138
-18
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ __Options:__
8383
### `service.id`
8484

8585
Defines the name of the id in the swagger path, by default it is `'id'`;
86+
This can also be an array, if multiple ids are used. For example with feathers-objection or feathers-cassandra.
87+
For services that extend adapter-commons this is set as parameter in the options when initializing the service.
8688

8789
### `service.docs`
8890

@@ -119,7 +121,7 @@ __Options:__
119121
- `tags` (*optional*) - Give multiple tags
120122
- `model` (*optional*) - Override model that is parsed from path
121123
- `modelName` (*optional*) - Override modelName that is parsed from path
122-
- `idType` (*optional*) - The swagger type of ids used in paths for this service. value can be an array of types when `service.id` is set to array.
124+
- `idType` (*optional*) - The swagger type of ids used in paths for this service. Value can be an array of types when `service.id` is set as an array.
123125
- `idNames` (*optional*) - Object with path parameter names, to customize the idName on operation / method level
124126
- `get`|`update`|`patch`|`remove` - name of the path parameter for the specific method, use service.id to change it for all
125127
- `definition`(also `schema` for openapi v3) (*optional*) - Swagger definition of the model of the service, will be merged into global definitions (with all additional generated definitions)

lib/v3/generator.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ class OpenApiV3Generator extends AbstractApiGenerator {
334334
};
335335

336336
if (withId) {
337-
customDoc.parameters = withId ? idPathParameters(idName, idType, `ID of ${modelName}`) : [];
337+
customDoc.parameters = idPathParameters(idName, idType, `ID of ${modelName}`);
338338
}
339339

340340
if (['post', 'put', 'patch'].includes(httpMethod)) {

test/v2/generator.test.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,65 @@ describe('swagger v2 generator', function () {
239239
expect(specs.paths['/message'].get.responses[200].schema.$ref).to.equal('#/definitions/otherRef');
240240
expect(specs.paths['/message/{id}'].get.responses[200].schema.$ref).to.equal('#/definitions/getMessage');
241241
});
242+
243+
describe('array service.id', function () {
244+
it('array service.id should be consumed', function () {
245+
const service = memory({ id: ['firstId', 'secondId'] });
246+
service.docs = {
247+
definition: messageDefinition
248+
};
249+
250+
gen.addService(service, 'message');
251+
252+
expect(specs.paths['/message/{firstId},{secondId}'].get.parameters[0].type).to.equal('integer');
253+
expect(specs.paths['/message/{firstId},{secondId}'].get.parameters[1].type).to.equal('integer');
254+
});
255+
256+
it('array service.id should be consumed with custom idTypes', function () {
257+
const service = memory({ id: ['firstId', 'secondId'] });
258+
service.docs = {
259+
idType: ['string', 'integer'],
260+
definition: messageDefinition
261+
};
262+
263+
gen.addService(service, 'message');
264+
265+
expect(specs.paths['/message/{firstId},{secondId}'].get.parameters[0].type).to.equal('string');
266+
expect(specs.paths['/message/{firstId},{secondId}'].get.parameters[1].type).to.equal('integer');
267+
});
268+
269+
it('array service.id should be consumed with custom idNames', function () {
270+
const service = memory({ id: ['firstId', 'secondId'] });
271+
service.docs = {
272+
idType: ['string', 'integer'],
273+
idNames: {
274+
update: ['otherId', 'additionalId']
275+
},
276+
definition: messageDefinition
277+
};
278+
279+
gen.addService(service, 'message');
280+
281+
expect(specs.paths['/message/{firstId},{secondId}'].get.parameters[0].type).to.equal('string');
282+
expect(specs.paths['/message/{firstId},{secondId}'].get.parameters[1].type).to.equal('integer');
283+
expect(specs.paths['/message/{otherId},{additionalId}'].put.parameters[0].type).to.equal('string');
284+
expect(specs.paths['/message/{otherId},{additionalId}'].put.parameters[1].type).to.equal('integer');
285+
});
286+
287+
it('array service.id with custom service.idSeparator should be consumed', function () {
288+
const service = memory();
289+
service.options.id = ['firstId', 'secondId'];
290+
service.options.idSeparator = '|';
291+
service.docs = {
292+
definition: messageDefinition
293+
};
294+
295+
gen.addService(service, 'message');
296+
297+
expect(specs.paths['/message/{firstId}|{secondId}'].get.parameters[0].type).to.equal('integer');
298+
expect(specs.paths['/message/{firstId}|{secondId}'].get.parameters[1].type).to.equal('integer');
299+
});
300+
});
242301
});
243302

244303
// contains only tests that are v2 specific, tests that test "abstract" generator are part of v3 tests
@@ -302,6 +361,18 @@ describe('swagger v2 generator', function () {
302361
});
303362
});
304363

364+
it('should handle :__feathersId in path for service.id as array', function () {
365+
addCustomMethod(service, { path: '/:__feathersId/custom' });
366+
367+
service.id = ['firstId', 'secondId'];
368+
service.docs.idType = ['integer', 'string'];
369+
370+
gen.addService(service, 'message');
371+
372+
expect(specs.paths['/message/{firstId},{secondId}/custom'].post.parameters[0].type).to.equal('integer');
373+
expect(specs.paths['/message/{firstId},{secondId}/custom'].post.parameters[1].type).to.equal('string');
374+
});
375+
305376
it('custom path parameters should be handled', function () {
306377
addCustomMethod(service, { path: '/custom/:myId' });
307378

test/v3/generator.test.js

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -978,8 +978,7 @@ describe('openopi v3 generator', function () {
978978
it('array service.id should be consumed', function () {
979979
const specs = {};
980980
const gen = new OpenApi3Generator(specs, swaggerOptions);
981-
const service = memory();
982-
service.options.id = ['firstId', 'secondId'];
981+
const service = memory({ id: ['firstId', 'secondId'] });
983982
service.docs = {
984983
definition: messageDefinition
985984
};
@@ -990,20 +989,39 @@ describe('openopi v3 generator', function () {
990989
expect(specs.paths['/message/{firstId},{secondId}'].get.parameters[1].schema.type).to.equal('integer');
991990
});
992991

993-
it('array service.id should be consumed', function () {
992+
it('array service.id should be consumed with custom idTypes', function () {
994993
const specs = {};
995994
const gen = new OpenApi3Generator(specs, swaggerOptions);
996-
const service = memory();
997-
service.options.id = ['firstId', 'secondId'];
995+
const service = memory({ id: ['firstId', 'secondId'] });
996+
service.docs = {
997+
idType: ['string', 'integer'],
998+
definition: messageDefinition
999+
};
1000+
1001+
gen.addService(service, 'message');
1002+
1003+
expect(specs.paths['/message/{firstId},{secondId}'].get.parameters[0].schema.type).to.equal('string');
1004+
expect(specs.paths['/message/{firstId},{secondId}'].get.parameters[1].schema.type).to.equal('integer');
1005+
});
1006+
1007+
it('array service.id should be consumed with custom idNames', function () {
1008+
const specs = {};
1009+
const gen = new OpenApi3Generator(specs, swaggerOptions);
1010+
const service = memory({ id: ['firstId', 'secondId'] });
9981011
service.docs = {
9991012
idType: ['string', 'integer'],
1013+
idNames: {
1014+
update: ['otherId', 'additionalId']
1015+
},
10001016
definition: messageDefinition
10011017
};
10021018

10031019
gen.addService(service, 'message');
10041020

10051021
expect(specs.paths['/message/{firstId},{secondId}'].get.parameters[0].schema.type).to.equal('string');
10061022
expect(specs.paths['/message/{firstId},{secondId}'].get.parameters[1].schema.type).to.equal('integer');
1023+
expect(specs.paths['/message/{otherId},{additionalId}'].put.parameters[0].schema.type).to.equal('string');
1024+
expect(specs.paths['/message/{otherId},{additionalId}'].put.parameters[1].schema.type).to.equal('integer');
10071025
});
10081026

10091027
it('array service.id with custom service.idSeparator should be consumed', function () {
@@ -1136,6 +1154,18 @@ describe('openopi v3 generator', function () {
11361154
});
11371155
});
11381156

1157+
it('should handle :__feathersId in path for service.id as array', function () {
1158+
addCustomMethod(service, { path: '/:__feathersId/custom' });
1159+
1160+
service.id = ['firstId', 'secondId'];
1161+
service.docs.idType = ['integer', 'string'];
1162+
1163+
gen.addService(service, 'message');
1164+
1165+
expect(specs.paths['/message/{firstId},{secondId}/custom'].post.parameters[0].schema.type).to.equal('integer');
1166+
expect(specs.paths['/message/{firstId},{secondId}/custom'].post.parameters[1].schema.type).to.equal('string');
1167+
});
1168+
11391169
it('custom path parameters should be handled', function () {
11401170
addCustomMethod(service, { path: '/custom/:myId' });
11411171

types/index.d.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ interface UiIndexFn {
1616
interface FnGetOperationArgs {
1717
(options: feathersSwagger.GetOperationArgsOptions): {
1818
tag?: string,
19-
tags?: [string],
19+
tags?: string[],
2020
model?: string,
2121
modelName?: string,
2222
} & UnknownObject;
@@ -55,12 +55,12 @@ interface FnSchemasGenerator {
5555

5656
type FnOperationSpecsGeneratorOptions = {
5757
tag: string,
58-
tags: [string],
58+
tags: string[],
5959
model: string,
6060
modelName: string,
61-
idName: string,
62-
idType: string,
63-
security: [any],
61+
idName: string | string[],
62+
idType: string | string[],
63+
security: any[],
6464
securities: Securities,
6565
refs: OperationRefs,
6666
service: feathersSwagger.SwaggerService<any>,
@@ -161,10 +161,10 @@ declare namespace feathersSwagger {
161161
modelName?: string;
162162
idType?: string | string[];
163163
idNames?: {
164-
get?: string;
165-
update?: string;
166-
patch?: string;
167-
remove?: string;
164+
get?: string | string[];
165+
update?: string | string[];
166+
patch?: string | string[];
167+
remove?: string | string[];
168168
};
169169
securities?: Securities;
170170
refs?: OperationRefs;
@@ -216,4 +216,6 @@ declare namespace feathersSwagger {
216216
}): void;
217217

218218
function security(method: string, securities: Securities, security: UnknownObject[]): UnknownObject[];
219+
220+
function idPathParameters(idName: string | string[], idSeparator: string): string;
219221
}

types/test.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import swagger, {
44
GetOperationArgsOptions,
55
operation,
66
tag,
7-
security,
7+
security, idPathParameters,
88
} from 'feathers-swagger';
99

1010
// complete
@@ -255,7 +255,13 @@ const serviceEmptyRefs: ServiceSwaggerAddon = {
255255
// array idType
256256
const serviceIdTypeArray: ServiceSwaggerAddon = {
257257
docs: {
258-
idType: ['string'],
258+
idType: ['string', 'integer'],
259+
idNames: {
260+
get: ['firstName', 'secondName'],
261+
patch: ['firstName', 'secondName'],
262+
remove: ['firstName', 'secondName'],
263+
update: ['firstName', 'secondName'],
264+
}
259265
}
260266
};
261267

@@ -296,3 +302,12 @@ security(
296302
security([], [], [{ any: 'thing' }]);
297303
// $ExpectError
298304
security('find', [], ['wrong']);
305+
306+
idPathParameters('id', ',');
307+
idPathParameters(['first', 'second'], ',');
308+
// $ExpectError
309+
idPathParameters(12, ',');
310+
// $ExpectError
311+
idPathParameters([12, 13], ',');
312+
// $ExpectError
313+
idPathParameters('id', 12);

0 commit comments

Comments
 (0)