From 62842ee38ab25e3e1547e58819d1549fa75ee363 Mon Sep 17 00:00:00 2001 From: Gabriel Dugny Date: Fri, 3 Jan 2025 14:00:14 +0100 Subject: [PATCH 1/2] feat: Improve JSON format of OpenAPI definition, allow YAML format By default, OpenAPI definition will now have JSON with spaces instead of minified JSON, for better visualization in the UI. Configuration `catalog.providers.backstageOpenapi.definitionFormat` was also added, and can take values `json` (default) or `yaml`, so organizations can use their preferred/standard format. Signed-off-by: Gabriel Dugny # Conflicts: # yarn.lock --- .changeset/nine-hounds-rest.md | 5 +++++ .../README.md | 1 + .../config.d.ts | 5 +++++ .../package.json | 3 ++- .../InternalOpenApiDocumentationProvider.ts | 22 +++++++++++++++++-- yarn.lock | 1 + 6 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 .changeset/nine-hounds-rest.md diff --git a/.changeset/nine-hounds-rest.md b/.changeset/nine-hounds-rest.md new file mode 100644 index 0000000000..1223b5cfa1 --- /dev/null +++ b/.changeset/nine-hounds-rest.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-backstage-openapi': minor +--- + +feat: Improve JSON format of OpenAPI definition, allow YAML format diff --git a/plugins/catalog-backend-module-backstage-openapi/README.md b/plugins/catalog-backend-module-backstage-openapi/README.md index c4342d42cf..15e14af128 100644 --- a/plugins/catalog-backend-module-backstage-openapi/README.md +++ b/plugins/catalog-backend-module-backstage-openapi/README.md @@ -28,6 +28,7 @@ catalog: - catalog - events - search + definitionFormat: 'yaml"' # Optional, defaults to 'json' entityOverrides: # All optional metadata: name: 'my-name' diff --git a/plugins/catalog-backend-module-backstage-openapi/config.d.ts b/plugins/catalog-backend-module-backstage-openapi/config.d.ts index 376c702999..7901f0424d 100644 --- a/plugins/catalog-backend-module-backstage-openapi/config.d.ts +++ b/plugins/catalog-backend-module-backstage-openapi/config.d.ts @@ -29,6 +29,11 @@ export interface Config { * Properties to override on the final entity object. */ entityOverrides?: object; + /** + * The format of the definition. + * @defaultValue json + */ + definitionFormat: 'json' | 'yaml'; }; }; }; diff --git a/plugins/catalog-backend-module-backstage-openapi/package.json b/plugins/catalog-backend-module-backstage-openapi/package.json index e7325a184f..675cf1a391 100644 --- a/plugins/catalog-backend-module-backstage-openapi/package.json +++ b/plugins/catalog-backend-module-backstage-openapi/package.json @@ -42,7 +42,8 @@ "cross-fetch": "^4.0.0", "lodash": "^4.17.21", "openapi-merge": "^1.3.2", - "uuid": "^11.0.0" + "uuid": "^11.0.0", + "yaml": "^2.7.0" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/plugins/catalog-backend-module-backstage-openapi/src/InternalOpenApiDocumentationProvider.ts b/plugins/catalog-backend-module-backstage-openapi/src/InternalOpenApiDocumentationProvider.ts index 3f5253d102..bc2a39d5bf 100644 --- a/plugins/catalog-backend-module-backstage-openapi/src/InternalOpenApiDocumentationProvider.ts +++ b/plugins/catalog-backend-module-backstage-openapi/src/InternalOpenApiDocumentationProvider.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +import yaml from 'yaml'; import { ANNOTATION_LOCATION, ANNOTATION_ORIGIN_LOCATION, @@ -155,6 +155,19 @@ const loadSpecs = async ({ return mergeSpecs({ baseUrl, specs }); }; +const formatDefinition = ( + definition: any, + format: string | 'json' | 'yaml', +) => { + if (format === 'json') { + return JSON.stringify(definition, null, 2); + } + if (format === 'yaml') { + return yaml.stringify(definition); + } + throw new Error(`Unsupported format type: ${format}`); +}; + export class InternalOpenApiDocumentationProvider implements EntityProvider { private connection?: EntityProviderConnection; private readonly scheduleFn: () => Promise; @@ -236,6 +249,10 @@ export class InternalOpenApiDocumentationProvider implements EntityProvider { const configToMerge = this.config.getOptional( 'catalog.providers.backstageOpenapi.entityOverrides', ); + const formatConfig = + this.config.getOptionalString( + 'catalog.providers.backstageOpenapi.definitionFormat', + ) ?? 'json'; const baseConfig = { metadata: { @@ -262,7 +279,7 @@ export class InternalOpenApiDocumentationProvider implements EntityProvider { }, spec: { type: 'openapi', - definition: JSON.stringify( + definition: formatDefinition( await loadSpecs({ baseUrl: this.config.getString('backend.baseUrl'), discovery: this.discovery, @@ -270,6 +287,7 @@ export class InternalOpenApiDocumentationProvider implements EntityProvider { plugins: pluginsToMerge, logger, }), + formatConfig, ), }, }; diff --git a/yarn.lock b/yarn.lock index 8ae7f225e3..013928163b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5797,6 +5797,7 @@ __metadata: openapi-merge: ^1.3.2 openapi3-ts: ^3.1.2 uuid: ^11.0.0 + yaml: ^2.7.0 languageName: unknown linkType: soft From c504fdce90d45be7f16ac7fe43b743e6060fc1df Mon Sep 17 00:00:00 2001 From: Gabriel Dugny Date: Fri, 21 Feb 2025 11:54:28 +0100 Subject: [PATCH 2/2] fix: format config is optional Signed-off-by: Gabriel Dugny Signed-off-by: Gabriel Dugny --- plugins/catalog-backend-module-backstage-openapi/config.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-backend-module-backstage-openapi/config.d.ts b/plugins/catalog-backend-module-backstage-openapi/config.d.ts index 7901f0424d..dc7cc6a5be 100644 --- a/plugins/catalog-backend-module-backstage-openapi/config.d.ts +++ b/plugins/catalog-backend-module-backstage-openapi/config.d.ts @@ -33,7 +33,7 @@ export interface Config { * The format of the definition. * @defaultValue json */ - definitionFormat: 'json' | 'yaml'; + definitionFormat?: 'json' | 'yaml'; }; }; };