diff --git a/packages/openapi-v3/src/enhancers/index.ts b/packages/openapi-v3/src/enhancers/index.ts index de19b5eb0a6c..0a3a29255b7f 100644 --- a/packages/openapi-v3/src/enhancers/index.ts +++ b/packages/openapi-v3/src/enhancers/index.ts @@ -8,4 +8,6 @@ export * from './default-deprecate-schema.enhancer'; export * from './keys'; export * from './prune-schema.enhancer'; export * from './spec-enhancer.service'; +export * from './tags-schema.enhancer'; export * from './types'; + diff --git a/packages/openapi-v3/src/enhancers/tags-schema.enhancer.ts b/packages/openapi-v3/src/enhancers/tags-schema.enhancer.ts new file mode 100644 index 000000000000..acd1751348cf --- /dev/null +++ b/packages/openapi-v3/src/enhancers/tags-schema.enhancer.ts @@ -0,0 +1,48 @@ +import {bind} from '@loopback/core'; +import {OperationObject} from 'openapi3-ts'; +import {OpenApiSpec} from '../types'; +import {asSpecEnhancer, OASEnhancer} from './types'; + +/** + * A spec enhancer to combine OperationObject Tags OpenApiSpec into spec.tags + * + */ +@bind(asSpecEnhancer) +export class TagsEnhancer implements OASEnhancer { + name = 'tags'; + + modifySpec(spec: OpenApiSpec): OpenApiSpec { + try { + return this.tagsConsolidate(spec); + } catch { + console.log('Tags Enhancer failed, returned original spec.'); + return spec; + } + } + + /** + * Combine OperationObject Tags OpenApiSpec into spec.tags + * + */ + private tagsConsolidate(spec: OpenApiSpec): OpenApiSpec { + Object.keys(spec.paths).forEach(path => + Object.keys(spec.paths[path]).forEach(op => { + const OpObj = spec.paths[path][op] as OperationObject; + if (OpObj.tags) this.patchTags(OpObj.tags, spec); + }), + ); + + return spec; + } + + // TODO(dougal83) desc. resolution + private patchTags(tags: Array, spec: OpenApiSpec) { + if (!spec.tags) { + spec.tags = []; + } + tags.forEach(name => { + if (spec.tags!.findIndex(tag => tag.name === name) <= 0) + spec.tags!.push({name, description: ''}); + }); + } +} diff --git a/packages/rest/src/rest.server.ts b/packages/rest/src/rest.server.ts index 09164a730d34..d2a1e0d9076e 100644 --- a/packages/rest/src/rest.server.ts +++ b/packages/rest/src/rest.server.ts @@ -22,6 +22,7 @@ import { OperationObject, PruneEnhancer, ServerObject, + TagsEnhancer, } from '@loopback/openapi-v3'; import {AssertionError} from 'assert'; import cors from 'cors'; @@ -723,6 +724,8 @@ export class RestServer extends Context implements Server, HttpServerLike { spec = consolidationEnhancer.modifySpec(spec); const pruneEnhancer = new PruneEnhancer(); spec = pruneEnhancer.modifySpec(spec); + const tagsEnhancer = new TagsEnhancer(); + spec = tagsEnhancer.modifySpec(spec); const defaultDeprecateEnhancer = new DefaultDeprecateEnhancer(); spec = defaultDeprecateEnhancer.modifySpec(spec);