Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(spec): allow additional fields on enum refs #2816

Merged
merged 1 commit into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 35 additions & 24 deletions e2e/api-spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,8 @@
"description": "Test",
"required": false,
"schema": {
"default": "test",
"type": "string"
"type": "string",
"default": "test"
}
},
{
Expand Down Expand Up @@ -277,8 +277,8 @@
"description": "Test",
"required": false,
"schema": {
"default": "test",
"type": "string"
"type": "string",
"default": "test"
}
},
{
Expand Down Expand Up @@ -415,8 +415,8 @@
"description": "Test",
"required": false,
"schema": {
"default": "test",
"type": "string"
"type": "string",
"default": "test"
}
},
{
Expand Down Expand Up @@ -474,8 +474,8 @@
"description": "Test",
"required": false,
"schema": {
"default": "test",
"type": "string"
"type": "string",
"default": "test"
}
},
{
Expand Down Expand Up @@ -610,8 +610,8 @@
"description": "Test",
"required": false,
"schema": {
"default": "test",
"type": "string"
"type": "string",
"default": "test"
}
},
{
Expand Down Expand Up @@ -662,8 +662,8 @@
"description": "Test",
"required": false,
"schema": {
"default": "test",
"type": "string"
"type": "string",
"default": "test"
}
},
{
Expand Down Expand Up @@ -720,8 +720,8 @@
"description": "Test",
"required": false,
"schema": {
"default": "test",
"type": "string"
"type": "string",
"default": "test"
}
},
{
Expand Down Expand Up @@ -784,8 +784,8 @@
"description": "Test",
"required": false,
"schema": {
"default": "test",
"type": "string"
"type": "string",
"default": "test"
}
},
{
Expand Down Expand Up @@ -828,8 +828,8 @@
"description": "Test",
"required": false,
"schema": {
"default": "test",
"type": "string"
"type": "string",
"default": "test"
}
},
{
Expand Down Expand Up @@ -885,8 +885,8 @@
"description": "Test",
"required": false,
"schema": {
"default": "test",
"type": "string"
"type": "string",
"default": "test"
}
},
{
Expand Down Expand Up @@ -937,8 +937,8 @@
"description": "Test",
"required": false,
"schema": {
"default": "test",
"type": "string"
"type": "string",
"default": "test"
}
},
{
Expand Down Expand Up @@ -1049,6 +1049,9 @@
},
"LettersEnum": {
"type": "string",
"description": "A small assortment of letters?",
"deprecated": true,
"default": "A",
"enum": [
"A",
"B",
Expand Down Expand Up @@ -1128,6 +1131,9 @@
"$ref": "#/components/schemas/LettersEnum"
}
},
"enumWithRef": {
"$ref": "#/components/schemas/LettersEnum"
},
"tag": {
"description": "tag",
"allOf": [
Expand All @@ -1151,7 +1157,8 @@
"options",
"enumWithDescription",
"enum",
"enumArr"
"enumArr",
"enumWithRef"
]
},
"Cat": {
Expand Down Expand Up @@ -1223,6 +1230,9 @@
"C"
]
}
},
"enumWithRef": {
"$ref": "#/components/schemas/LettersEnum"
}
},
"required": [
Expand All @@ -1234,7 +1244,8 @@
"urls",
"_options",
"enum",
"enumArr"
"enumArr",
"enumWithRef"
]
},
"Letter": {
Expand Down
2 changes: 1 addition & 1 deletion e2e/express.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe('Express Swagger', () => {
const doc = JSON.stringify(document, null, 2);

try {
let api = await SwaggerParser.validate(document as any);
const api = await SwaggerParser.validate(document as any);
console.log(
'API name: %s, Version: %s',
api.info.title,
Expand Down
2 changes: 1 addition & 1 deletion e2e/fastify.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe('Fastify Swagger', () => {
const doc = JSON.stringify(document, null, 2);

try {
let api = await SwaggerParser.validate(document as any);
const api = await SwaggerParser.validate(document as any);
console.log(
'API name: %s, Version: %s',
api.info.title,
Expand Down
9 changes: 9 additions & 0 deletions e2e/src/cats/classes/cat.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,13 @@ export class Cat {
isArray: true
})
enumArr: LettersEnum;

@ApiProperty({
enum: LettersEnum,
enumName: 'LettersEnum',
description: 'A small assortment of letters?',
default: 'A',
deprecated: true,
})
enumWithRef: LettersEnum
}
9 changes: 9 additions & 0 deletions e2e/src/cats/dto/create-cat.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ export class CreateCatDto {
})
readonly enumArr: LettersEnum;

@ApiProperty({
enum: LettersEnum,
enumName: 'LettersEnum',
description: 'A small assortment of letters?',
default: 'A',
deprecated: true,
})
readonly enumWithRef: LettersEnum

@ApiProperty({ description: 'tag', required: false })
readonly tag: TagDto;

Expand Down
2 changes: 1 addition & 1 deletion e2e/validate-schema.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ describe('Validate OpenAPI schema', () => {
writeFileSync(join(__dirname, 'api-spec.json'), doc);

try {
let api = await SwaggerParser.validate(document as any);
const api = await SwaggerParser.validate(document as any);
console.log(
'API name: %s, Version: %s',
api.info.title,
Expand Down
37 changes: 21 additions & 16 deletions lib/services/schema-object-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,21 +300,25 @@ export class SchemaObjectFactory {
const enumName = metadata.enumName;
const $ref = getSchemaPath(enumName);

if (!(enumName in schemas)) {
const enumType: string = (
metadata.isArray
? metadata.items['type']
: metadata.type
) ?? 'string';

schemas[enumName] = {
type: enumType,
enum:
metadata.isArray && metadata.items
? metadata.items['enum']
: metadata.enum
};
}
// Allow given fields to be part of the referenced enum schema
const additionalParams = ['description', 'deprecated', 'default']
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not sure if we should just allow all fields, so I added an allowlist here. I did not find any information in the swagger spec on what they technically support on an enum ref field.

const additionalFields = additionalParams.reduce((acc, param) =>
({...acc, ...(metadata[param] && { [param]: metadata[param] })}), {});

const enumType: string = (
metadata.isArray
? metadata.items['type']
: metadata.type
) ?? 'string';

schemas[enumName] = {
type: enumType,
...additionalFields,
enum:
metadata.isArray && metadata.items
? metadata.items['enum']
: metadata.enum
};

const _schemaObject = {
...metadata,
Expand All @@ -324,7 +328,7 @@ export class SchemaObjectFactory {

const refHost = metadata.isArray ? { items: { $ref } } : { $ref };
const paramObject = { ..._schemaObject, ...refHost };
const pathsToOmit = ['enum', 'enumName'];
const pathsToOmit = ['enum', 'enumName', ...additionalParams];

if (!metadata.isArray) {
pathsToOmit.push('type');
Expand Down Expand Up @@ -498,6 +502,7 @@ export class SchemaObjectFactory {
schemas
);
}

if (isString(typeRef)) {
if (isEnumMetadata(metadata)) {
return this.createEnumSchemaType(key, metadata, schemas);
Expand Down