From 9e8046f2bc797873f864d026c46961b41dfc7644 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 5 Feb 2024 16:25:31 +0100 Subject: [PATCH 01/19] feat(api-docs): configure alpha subpath Signed-off-by: Camila Belo --- plugins/api-docs/package.json | 19 ++++++++++++++++--- plugins/api-docs/src/alpha.tsx | 15 +++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 plugins/api-docs/src/alpha.tsx diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 0cdf564de9..934fcab62f 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -6,9 +6,22 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.tsx", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.tsx" + ], + "package.json": [ + "package.json" + ] + } }, "backstage": { "role": "frontend-plugin" diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx new file mode 100644 index 0000000000..94adcafa53 --- /dev/null +++ b/plugins/api-docs/src/alpha.tsx @@ -0,0 +1,15 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ From ae8716c94c24572b33801c23bda8cdd4306c3c8c Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 5 Feb 2024 16:28:59 +0100 Subject: [PATCH 02/19] feat(api-docs): create new plugin Signed-off-by: Camila Belo --- plugins/api-docs/package.json | 2 ++ plugins/api-docs/src/alpha.tsx | 15 +++++++++++++++ yarn.lock | 2 ++ 3 files changed, 19 insertions(+) diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 934fcab62f..d29a389911 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -48,8 +48,10 @@ "dependencies": { "@asyncapi/react-component": "1.2.13", "@backstage/catalog-model": "workspace:^", + "@backstage/core-compat-api": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", "@backstage/plugin-catalog": "workspace:^", "@backstage/plugin-catalog-common": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index 94adcafa53..eddd29b65d 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -13,3 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +import { createPlugin } from '@backstage/frontend-plugin-api'; +import { convertLegacyRouteRef } from '@backstage/core-compat-api'; +import { rootRoute, registerComponentRouteRef } from './routes'; + +export default createPlugin({ + id: 'api-docs', + routes: { + root: convertLegacyRouteRef(rootRoute), + }, + externalRoutes: { + registerApi: convertLegacyRouteRef(registerComponentRouteRef), + }, + extensions: [], +}); diff --git a/yarn.lock b/yarn.lock index 93ebfa68aa..90529db61f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4556,9 +4556,11 @@ __metadata: "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/core-app-api": "workspace:^" + "@backstage/core-compat-api": "workspace:^" "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" "@backstage/plugin-catalog": "workspace:^" "@backstage/plugin-catalog-common": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" From bf4fec6841ebc0ee25ce06609c6bfa63a7956213 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 5 Feb 2024 16:32:30 +0100 Subject: [PATCH 03/19] feat(api-docs): migrate config api Signed-off-by: Camila Belo --- plugins/api-docs/src/alpha.tsx | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index eddd29b65d..6449af0460 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -14,9 +14,32 @@ * limitations under the License. */ -import { createPlugin } from '@backstage/frontend-plugin-api'; +import { + createApiExtension, + createApiFactory, + createPlugin, +} from '@backstage/frontend-plugin-api'; import { convertLegacyRouteRef } from '@backstage/core-compat-api'; +import { ApiEntity } from '@backstage/catalog-model'; + +import { defaultDefinitionWidgets } from './components/ApiDefinitionCard'; import { rootRoute, registerComponentRouteRef } from './routes'; +import { apiDocsConfigRef } from './config'; + +const ApiDocsConfigApi = createApiExtension({ + factory: createApiFactory({ + api: apiDocsConfigRef, + deps: {}, + factory: () => { + const definitionWidgets = defaultDefinitionWidgets(); + return { + getApiDefinitionWidget: (apiEntity: ApiEntity) => { + return definitionWidgets.find(d => d.type === apiEntity.spec.type); + }, + }; + }, + }), +}); export default createPlugin({ id: 'api-docs', @@ -26,5 +49,5 @@ export default createPlugin({ externalRoutes: { registerApi: convertLegacyRouteRef(registerComponentRouteRef), }, - extensions: [], + extensions: [ApiDocsConfigApi], }); From 8adb0759ea2a5a975fac2fa22b6ddfc59a00e68d Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 5 Feb 2024 16:35:52 +0100 Subject: [PATCH 04/19] feat(api-docs): migrate explorer page to new system Signed-off-by: Camila Belo --- plugins/api-docs/src/alpha.tsx | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index 6449af0460..d8cc0265eb 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -14,10 +14,14 @@ * limitations under the License. */ +import React from 'react'; + import { createApiExtension, createApiFactory, + createPageExtension, createPlugin, + createSchemaFromZod, } from '@backstage/frontend-plugin-api'; import { convertLegacyRouteRef } from '@backstage/core-compat-api'; import { ApiEntity } from '@backstage/catalog-model'; @@ -41,6 +45,23 @@ const ApiDocsConfigApi = createApiExtension({ }), }); +const ApiDocsExplorerPage = createPageExtension({ + defaultPath: '/api-docs', + routeRef: convertLegacyRouteRef(rootRoute), + // Mapping DefaultApiExplorerPageProps to config + configSchema: createSchemaFromZod(z => + z.object({ + path: z.string().default('/api-docs'), + initiallySelectedFilter: z.enum(['owned', 'starred', 'all']).optional(), + // Ommiting columns and actions for now as their types are too complex to map to zod + }), + ), + loader: () => + import('./components/ApiExplorerPage').then(m => ( + + )), +}); + export default createPlugin({ id: 'api-docs', routes: { @@ -49,5 +70,5 @@ export default createPlugin({ externalRoutes: { registerApi: convertLegacyRouteRef(registerComponentRouteRef), }, - extensions: [ApiDocsConfigApi], + extensions: [ApiDocsConfigApi, ApiDocsExplorerPage], }); From 4ac8133912125f9ccc65e855e49e8a4eb73ffe79 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 5 Feb 2024 17:20:49 +0100 Subject: [PATCH 05/19] feat(api-docs): migrate definition entity card Signed-off-by: Camila Belo --- plugins/api-docs/src/alpha.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index d8cc0265eb..36fdc27cff 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -29,6 +29,7 @@ import { ApiEntity } from '@backstage/catalog-model'; import { defaultDefinitionWidgets } from './components/ApiDefinitionCard'; import { rootRoute, registerComponentRouteRef } from './routes'; import { apiDocsConfigRef } from './config'; +import { createEntityCardExtension } from '@backstage/plugin-catalog-react/alpha'; const ApiDocsConfigApi = createApiExtension({ factory: createApiFactory({ @@ -62,6 +63,12 @@ const ApiDocsExplorerPage = createPageExtension({ )), }); +const ApiDocsDefinitionEntityCard = createEntityCardExtension({ + name: 'api-definition', + loader: () => + import('./components/ApiDefinitionCard').then(m => ), +}); + export default createPlugin({ id: 'api-docs', routes: { @@ -70,5 +77,9 @@ export default createPlugin({ externalRoutes: { registerApi: convertLegacyRouteRef(registerComponentRouteRef), }, - extensions: [ApiDocsConfigApi, ApiDocsExplorerPage], + extensions: [ + ApiDocsConfigApi, + ApiDocsExplorerPage, + ApiDocsDefinitionEntityCard, + ], }); From 6ab0663936ac005fce57ed7f13c32231baaf27e9 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 5 Feb 2024 17:29:42 +0100 Subject: [PATCH 06/19] feat(api-docs): migrate consumed apis entity card Signed-off-by: Camila Belo --- plugins/api-docs/src/alpha.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index 36fdc27cff..15a2b30e60 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -69,6 +69,15 @@ const ApiDocsDefinitionEntityCard = createEntityCardExtension({ import('./components/ApiDefinitionCard').then(m => ), }); +const ApiDocsConsumedApisEntityCard = createEntityCardExtension({ + name: 'consumed-apis', + // Ommiting configSchema for now + // we are skipping variations, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + // and columns are too complex to map to zod + loader: () => + import('./components/ApisCards').then(m => ), +}); + export default createPlugin({ id: 'api-docs', routes: { @@ -81,5 +90,6 @@ export default createPlugin({ ApiDocsConfigApi, ApiDocsExplorerPage, ApiDocsDefinitionEntityCard, + ApiDocsConsumedApisEntityCard, ], }); From 2d4c1a4eb79b7b390c37658bf2000f0944ed6bc1 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 5 Feb 2024 17:38:04 +0100 Subject: [PATCH 07/19] feat(api-docs): migrate consuming components entity card Signed-off-by: Camila Belo --- plugins/api-docs/src/alpha.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index 15a2b30e60..e0e796a3bc 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -78,6 +78,16 @@ const ApiDocsConsumedApisEntityCard = createEntityCardExtension({ import('./components/ApisCards').then(m => ), }); +const ApiDocsConsumingComponentsEntityCard = createEntityCardExtension({ + name: 'consuming-components', + // Ommiting configSchema for now + // we are skipping variations, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + loader: () => + import('./components/ComponentsCards').then(m => ( + + )), +}); + export default createPlugin({ id: 'api-docs', routes: { @@ -91,5 +101,6 @@ export default createPlugin({ ApiDocsExplorerPage, ApiDocsDefinitionEntityCard, ApiDocsConsumedApisEntityCard, + ApiDocsConsumingComponentsEntityCard, ], }); From 9d6787273f88a5104e82019ab7cd3cf07af5c474 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 5 Feb 2024 17:42:33 +0100 Subject: [PATCH 08/19] feat(api-docs): migrate has apis entity card Signed-off-by: Camila Belo --- plugins/api-docs/src/alpha.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index e0e796a3bc..b13aa4494c 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -78,6 +78,13 @@ const ApiDocsConsumedApisEntityCard = createEntityCardExtension({ import('./components/ApisCards').then(m => ), }); +const ApiDocsHasApisEntityCard = createEntityCardExtension({ + name: 'has-apis', + // we are skipping variations, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + // and columns are too complex to map to zod + loader: () => import('./components/ApisCards').then(m => ), +}); + const ApiDocsConsumingComponentsEntityCard = createEntityCardExtension({ name: 'consuming-components', // Ommiting configSchema for now @@ -99,6 +106,7 @@ export default createPlugin({ extensions: [ ApiDocsConfigApi, ApiDocsExplorerPage, + ApiDocsHasApisEntityCard, ApiDocsDefinitionEntityCard, ApiDocsConsumedApisEntityCard, ApiDocsConsumingComponentsEntityCard, From 514671e6cea2ac9029cca2867f1e565a2b68a322 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 5 Feb 2024 17:53:52 +0100 Subject: [PATCH 09/19] feat(api-docs): migrate provided apis entity card Signed-off-by: Camila Belo --- plugins/api-docs/src/alpha.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index b13aa4494c..842275a984 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -85,6 +85,14 @@ const ApiDocsHasApisEntityCard = createEntityCardExtension({ loader: () => import('./components/ApisCards').then(m => ), }); +const ApiDocsProvidedApisEntityCard = createEntityCardExtension({ + name: 'provided-apis', + // we are skipping variations, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + // and columns are too complex to map to zod + loader: () => + import('./components/ApisCards').then(m => ), +}); + const ApiDocsConsumingComponentsEntityCard = createEntityCardExtension({ name: 'consuming-components', // Ommiting configSchema for now @@ -108,6 +116,7 @@ export default createPlugin({ ApiDocsExplorerPage, ApiDocsHasApisEntityCard, ApiDocsDefinitionEntityCard, + ApiDocsProvidedApisEntityCard, ApiDocsConsumedApisEntityCard, ApiDocsConsumingComponentsEntityCard, ], From c3787791e37d379c090bbfde7055469e8794e176 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 5 Feb 2024 17:57:48 +0100 Subject: [PATCH 10/19] feat(api-docs): migrate providing components entity card Signed-off-by: Camila Belo --- plugins/api-docs/src/alpha.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index 842275a984..7f145fad68 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -103,6 +103,16 @@ const ApiDocsConsumingComponentsEntityCard = createEntityCardExtension({ )), }); +const ApiDocsProvidingComponentsEntityCard = createEntityCardExtension({ + name: 'providing-components', + // Ommiting configSchema for now + // we are skipping variations, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + loader: () => + import('./components/ComponentsCards').then(m => ( + + )), +}); + export default createPlugin({ id: 'api-docs', routes: { @@ -119,5 +129,6 @@ export default createPlugin({ ApiDocsProvidedApisEntityCard, ApiDocsConsumedApisEntityCard, ApiDocsConsumingComponentsEntityCard, + ApiDocsProvidingComponentsEntityCard, ], }); From 17d4e5b65919a18076b35561b8c809c7a745e6e1 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Mon, 5 Feb 2024 23:56:53 +0100 Subject: [PATCH 11/19] refactor(api-docs): variants code comments Signed-off-by: Camila Belo --- plugins/api-docs/src/alpha.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index 7f145fad68..6b0827adda 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -72,7 +72,7 @@ const ApiDocsDefinitionEntityCard = createEntityCardExtension({ const ApiDocsConsumedApisEntityCard = createEntityCardExtension({ name: 'consumed-apis', // Ommiting configSchema for now - // we are skipping variations, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 // and columns are too complex to map to zod loader: () => import('./components/ApisCards').then(m => ), @@ -80,14 +80,14 @@ const ApiDocsConsumedApisEntityCard = createEntityCardExtension({ const ApiDocsHasApisEntityCard = createEntityCardExtension({ name: 'has-apis', - // we are skipping variations, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 // and columns are too complex to map to zod loader: () => import('./components/ApisCards').then(m => ), }); const ApiDocsProvidedApisEntityCard = createEntityCardExtension({ name: 'provided-apis', - // we are skipping variations, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 // and columns are too complex to map to zod loader: () => import('./components/ApisCards').then(m => ), @@ -96,7 +96,7 @@ const ApiDocsProvidedApisEntityCard = createEntityCardExtension({ const ApiDocsConsumingComponentsEntityCard = createEntityCardExtension({ name: 'consuming-components', // Ommiting configSchema for now - // we are skipping variations, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 loader: () => import('./components/ComponentsCards').then(m => ( @@ -106,7 +106,7 @@ const ApiDocsConsumingComponentsEntityCard = createEntityCardExtension({ const ApiDocsProvidingComponentsEntityCard = createEntityCardExtension({ name: 'providing-components', // Ommiting configSchema for now - // we are skipping variations, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 loader: () => import('./components/ComponentsCards').then(m => ( From fff681b45fd3ba008923fcbecd19a15bd02081da Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 6 Feb 2024 08:25:57 +0100 Subject: [PATCH 12/19] refactor(api-docs): use compat wrapper Signed-off-by: Camila Belo --- plugins/api-docs/src/alpha.tsx | 41 ++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index 6b0827adda..83398e8430 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -23,7 +23,10 @@ import { createPlugin, createSchemaFromZod, } from '@backstage/frontend-plugin-api'; -import { convertLegacyRouteRef } from '@backstage/core-compat-api'; +import { + compatWrapper, + convertLegacyRouteRef, +} from '@backstage/core-compat-api'; import { ApiEntity } from '@backstage/catalog-model'; import { defaultDefinitionWidgets } from './components/ApiDefinitionCard'; @@ -57,16 +60,22 @@ const ApiDocsExplorerPage = createPageExtension({ // Ommiting columns and actions for now as their types are too complex to map to zod }), ), - loader: () => - import('./components/ApiExplorerPage').then(m => ( - - )), + loader: ({ config }) => + import('./components/ApiExplorerPage').then(m => + compatWrapper( + , + ), + ), }); const ApiDocsDefinitionEntityCard = createEntityCardExtension({ name: 'api-definition', loader: () => - import('./components/ApiDefinitionCard').then(m => ), + import('./components/ApiDefinitionCard').then(m => + compatWrapper(), + ), }); const ApiDocsConsumedApisEntityCard = createEntityCardExtension({ @@ -75,7 +84,9 @@ const ApiDocsConsumedApisEntityCard = createEntityCardExtension({ // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 // and columns are too complex to map to zod loader: () => - import('./components/ApisCards').then(m => ), + import('./components/ApisCards').then(m => + compatWrapper(), + ), }); const ApiDocsHasApisEntityCard = createEntityCardExtension({ @@ -90,7 +101,9 @@ const ApiDocsProvidedApisEntityCard = createEntityCardExtension({ // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 // and columns are too complex to map to zod loader: () => - import('./components/ApisCards').then(m => ), + import('./components/ApisCards').then(m => + compatWrapper(), + ), }); const ApiDocsConsumingComponentsEntityCard = createEntityCardExtension({ @@ -98,9 +111,9 @@ const ApiDocsConsumingComponentsEntityCard = createEntityCardExtension({ // Ommiting configSchema for now // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 loader: () => - import('./components/ComponentsCards').then(m => ( - - )), + import('./components/ComponentsCards').then(m => + compatWrapper(), + ), }); const ApiDocsProvidingComponentsEntityCard = createEntityCardExtension({ @@ -108,9 +121,9 @@ const ApiDocsProvidingComponentsEntityCard = createEntityCardExtension({ // Ommiting configSchema for now // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 loader: () => - import('./components/ComponentsCards').then(m => ( - - )), + import('./components/ComponentsCards').then(m => + compatWrapper(), + ), }); export default createPlugin({ From 46a220e8460b2c4619da50d363c5d5fa6901161c Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 6 Feb 2024 08:30:15 +0100 Subject: [PATCH 13/19] refactor(api-docs): reorder extension definitions Signed-off-by: Camila Belo --- packages/app-next/app-config.yaml | 15 ++++++++++++ plugins/api-docs/src/alpha.tsx | 38 ++++++++++++++++++++++++------- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/packages/app-next/app-config.yaml b/packages/app-next/app-config.yaml index b07f556742..fad0300680 100644 --- a/packages/app-next/app-config.yaml +++ b/packages/app-next/app-config.yaml @@ -11,6 +11,7 @@ app: # - apis.plugin.graphiql.browse.gitlab: true - graphiql-endpoint:graphiql/gitlab: true + # Entity page cards - entity-card:catalog/about - entity-card:catalog/labels - entity-card:catalog/links: @@ -21,7 +22,21 @@ app: config: height: 300 - entity-card:azure-devops/readme + - entity-card:api-docs/consumed-apis: + config: + filter: kind:component + - entity-card:api-docs/provided-apis: + config: + filter: kind:component + - entity-card:api-docs/providing-components: + config: + filter: kind:api + - entity-card:api-docs/consuming-components: + config: + filter: kind:api + # Entity page content + - entity-content:api-docs/definition - entity-content:techdocs - entity-content:azure-devops/pipelines - entity-content:azure-devops/pull-requests diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index 83398e8430..fcb536e245 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -32,7 +32,11 @@ import { ApiEntity } from '@backstage/catalog-model'; import { defaultDefinitionWidgets } from './components/ApiDefinitionCard'; import { rootRoute, registerComponentRouteRef } from './routes'; import { apiDocsConfigRef } from './config'; -import { createEntityCardExtension } from '@backstage/plugin-catalog-react/alpha'; +import { + createEntityCardExtension, + createEntityContentExtension, +} from '@backstage/plugin-catalog-react/alpha'; +import { Grid } from '@material-ui/core'; const ApiDocsConfigApi = createApiExtension({ factory: createApiFactory({ @@ -70,6 +74,13 @@ const ApiDocsExplorerPage = createPageExtension({ ), }); +const ApiDocsHasApisEntityCard = createEntityCardExtension({ + name: 'has-apis', + // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + // and columns are too complex to map to zod + loader: () => import('./components/ApisCards').then(m => ), +}); + const ApiDocsDefinitionEntityCard = createEntityCardExtension({ name: 'api-definition', loader: () => @@ -89,13 +100,6 @@ const ApiDocsConsumedApisEntityCard = createEntityCardExtension({ ), }); -const ApiDocsHasApisEntityCard = createEntityCardExtension({ - name: 'has-apis', - // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 - // and columns are too complex to map to zod - loader: () => import('./components/ApisCards').then(m => ), -}); - const ApiDocsProvidedApisEntityCard = createEntityCardExtension({ name: 'provided-apis', // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 @@ -126,6 +130,23 @@ const ApiDocsProvidingComponentsEntityCard = createEntityCardExtension({ ), }); +const ApiDocsDefinitionEntityContent = createEntityContentExtension({ + name: 'definition', + defaultPath: '/defintion', + defaultTitle: 'Definition', + filter: 'is:api', + loader: async () => + import('./components/ApiDefinitionCard').then(m => + compatWrapper( + + + + + , + ), + ), +}); + export default createPlugin({ id: 'api-docs', routes: { @@ -143,5 +164,6 @@ export default createPlugin({ ApiDocsConsumedApisEntityCard, ApiDocsConsumingComponentsEntityCard, ApiDocsProvidingComponentsEntityCard, + ApiDocsDefinitionEntityContent, ], }); From 12b18699479dba50ef11aca296f0e1368c8bcf04 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 6 Feb 2024 11:08:38 +0100 Subject: [PATCH 14/19] fix(catalog): entity cards tab filtering Signed-off-by: Camila Belo --- packages/app-next/app-config.yaml | 1 + plugins/api-docs/api-report-alpha.md | 22 +++++ plugins/api-docs/src/alpha.tsx | 2 +- .../catalog/src/alpha/EntityOverviewPage.tsx | 74 +--------------- .../src/alpha/filter/FilterWrapper.tsx | 88 +++++++++++++++++++ plugins/catalog/src/alpha/pages.tsx | 30 ++++--- 6 files changed, 133 insertions(+), 84 deletions(-) create mode 100644 plugins/api-docs/api-report-alpha.md create mode 100644 plugins/catalog/src/alpha/filter/FilterWrapper.tsx diff --git a/packages/app-next/app-config.yaml b/packages/app-next/app-config.yaml index fad0300680..dd2fe84a87 100644 --- a/packages/app-next/app-config.yaml +++ b/packages/app-next/app-config.yaml @@ -37,6 +37,7 @@ app: # Entity page content - entity-content:api-docs/definition + - entity-content:api-docs/apis - entity-content:techdocs - entity-content:azure-devops/pipelines - entity-content:azure-devops/pull-requests diff --git a/plugins/api-docs/api-report-alpha.md b/plugins/api-docs/api-report-alpha.md new file mode 100644 index 0000000000..1d22283884 --- /dev/null +++ b/plugins/api-docs/api-report-alpha.md @@ -0,0 +1,22 @@ +## API Report File for "@backstage/plugin-api-docs" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackstagePlugin } from '@backstage/frontend-plugin-api'; +import { ExternalRouteRef } from '@backstage/frontend-plugin-api'; +import { RouteRef } from '@backstage/frontend-plugin-api'; + +// @public (undocumented) +const _default: BackstagePlugin< + { + root: RouteRef; + }, + { + registerApi: ExternalRouteRef; + } +>; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index fcb536e245..98655d56ba 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -134,7 +134,7 @@ const ApiDocsDefinitionEntityContent = createEntityContentExtension({ name: 'definition', defaultPath: '/defintion', defaultTitle: 'Definition', - filter: 'is:api', + filter: 'kind:api', loader: async () => import('./components/ApiDefinitionCard').then(m => compatWrapper( diff --git a/plugins/catalog/src/alpha/EntityOverviewPage.tsx b/plugins/catalog/src/alpha/EntityOverviewPage.tsx index 932e13d962..85c318cf3f 100644 --- a/plugins/catalog/src/alpha/EntityOverviewPage.tsx +++ b/plugins/catalog/src/alpha/EntityOverviewPage.tsx @@ -17,8 +17,8 @@ import { Entity } from '@backstage/catalog-model'; import { useEntity } from '@backstage/plugin-catalog-react'; import Grid from '@material-ui/core/Grid'; -import React, { useMemo } from 'react'; -import { parseFilterExpression } from './filter/parseFilterExpression'; +import React from 'react'; +import { FilterWrapper } from './filter/FilterWrapper'; interface EntityOverviewPageProps { cards: Array<{ @@ -28,80 +28,12 @@ interface EntityOverviewPageProps { }>; } -// Keeps track of what filter expression strings that we've seen duplicates of -// with functions, or which emitted parsing errors for so far -const seenParseErrorExpressionStrings = new Set(); -const seenDuplicateExpressionStrings = new Set(); - -// Given an optional filter function and an optional filter expression, make -// sure that at most one of them was given, and return a filter function that -// does the right thing. -function buildFilterFn( - filterFunction?: (entity: Entity) => boolean, - filterExpression?: string, -): (entity: Entity) => boolean { - if ( - filterFunction && - filterExpression && - !seenDuplicateExpressionStrings.has(filterExpression) - ) { - // eslint-disable-next-line no-console - console.warn( - `Duplicate entity filter methods found, both '${filterExpression}' as well as a callback function, which is not permitted - using the callback`, - ); - seenDuplicateExpressionStrings.add(filterExpression); - } - - const filter = filterFunction || filterExpression; - if (!filter) { - return () => true; - } else if (typeof filter === 'function') { - return subject => filter(subject); - } - - const result = parseFilterExpression(filter); - if ( - result.expressionParseErrors.length && - !seenParseErrorExpressionStrings.has(filter) - ) { - // eslint-disable-next-line no-console - console.warn( - `Error(s) in entity filter expression '${filter}'`, - result.expressionParseErrors, - ); - seenParseErrorExpressionStrings.add(filter); - } - - return result.filterFn; -} - -// Handles the memoized parsing of filter expressions for each card -function CardWrapper(props: { - entity: Entity; - element: React.JSX.Element; - filterFunction?: (entity: Entity) => boolean; - filterExpression?: string; -}) { - const { entity, element, filterFunction, filterExpression } = props; - - const filterFn = useMemo( - () => buildFilterFn(filterFunction, filterExpression), - [filterFunction, filterExpression], - ); - - return filterFn(entity) ? ( - - {element} - - ) : null; -} - export function EntityOverviewPage(props: EntityOverviewPageProps) { const { entity } = useEntity(); return ( {props.cards.map((card, index) => ( - + ))} ); diff --git a/plugins/catalog/src/alpha/filter/FilterWrapper.tsx b/plugins/catalog/src/alpha/filter/FilterWrapper.tsx new file mode 100644 index 0000000000..e0e74fe481 --- /dev/null +++ b/plugins/catalog/src/alpha/filter/FilterWrapper.tsx @@ -0,0 +1,88 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity } from '@backstage/catalog-model'; +import Grid from '@material-ui/core/Grid'; +import React, { useMemo } from 'react'; +import { parseFilterExpression } from './parseFilterExpression'; + +// Keeps track of what filter expression strings that we've seen duplicates of +// with functions, or which emitted parsing errors for so far +const seenParseErrorExpressionStrings = new Set(); +const seenDuplicateExpressionStrings = new Set(); + +// Given an optional filter function and an optional filter expression, make +// sure that at most one of them was given, and return a filter function that +// does the right thing. +export function buildFilterFn( + filterFunction?: (entity: Entity) => boolean, + filterExpression?: string, +): (entity: Entity) => boolean { + if ( + filterFunction && + filterExpression && + !seenDuplicateExpressionStrings.has(filterExpression) + ) { + // eslint-disable-next-line no-console + console.warn( + `Duplicate entity filter methods found, both '${filterExpression}' as well as a callback function, which is not permitted - using the callback`, + ); + seenDuplicateExpressionStrings.add(filterExpression); + } + + const filter = filterFunction || filterExpression; + if (!filter) { + return () => true; + } else if (typeof filter === 'function') { + return subject => filter(subject); + } + + const result = parseFilterExpression(filter); + if ( + result.expressionParseErrors.length && + !seenParseErrorExpressionStrings.has(filter) + ) { + // eslint-disable-next-line no-console + console.warn( + `Error(s) in entity filter expression '${filter}'`, + result.expressionParseErrors, + ); + seenParseErrorExpressionStrings.add(filter); + } + + return result.filterFn; +} + +// Handles the memoized parsing of filter expressions +export function FilterWrapper(props: { + entity: Entity; + element: React.JSX.Element; + filterFunction?: (entity: Entity) => boolean; + filterExpression?: string; +}) { + const { entity, element, filterFunction, filterExpression } = props; + + const filterFn = useMemo( + () => buildFilterFn(filterFunction, filterExpression), + [filterFunction, filterExpression], + ); + + return filterFn(entity) ? ( + + {element} + + ) : null; +} diff --git a/plugins/catalog/src/alpha/pages.tsx b/plugins/catalog/src/alpha/pages.tsx index 3f40796da9..15f7d6cc91 100644 --- a/plugins/catalog/src/alpha/pages.tsx +++ b/plugins/catalog/src/alpha/pages.tsx @@ -31,6 +31,7 @@ import { import { catalogExtensionData } from '@backstage/plugin-catalog-react/alpha'; import { rootRouteRef } from '../routes'; import { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl'; +import { buildFilterFn } from './filter/FilterWrapper'; export const catalogPage = createPageExtension({ defaultPath: '/catalog', @@ -57,24 +58,29 @@ export const catalogEntityPage = createPageExtension({ path: coreExtensionData.routePath, routeRef: coreExtensionData.routeRef.optional(), title: catalogExtensionData.entityContentTitle, + filterFunction: catalogExtensionData.entityFilterFunction.optional(), + filterExpression: catalogExtensionData.entityFilterExpression.optional(), }), }, loader: async ({ inputs }) => { const { EntityLayout } = await import('../components/EntityLayout'); const Component = () => { + const { entity, ...rest } = useEntityFromUrl(); return ( - - - {inputs.contents.map(content => ( - - {content.output.element} - - ))} - + + {entity ? ( + + {inputs.contents + .filter(({ output: { filterFunction, filterExpression } }) => + buildFilterFn(filterFunction, filterExpression)(entity), + ) + .map(({ output: { path, title, element } }) => ( + + {element} + + ))} + + ) : null} ); }; From 76fa7742957d20311e9c2291e116d9371a33ff36 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 6 Feb 2024 11:57:05 +0100 Subject: [PATCH 15/19] feat(api-docs): create nav item extension Signed-off-by: Camila Belo --- plugins/api-docs/src/alpha.tsx | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index 98655d56ba..14a27ddd57 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -19,6 +19,7 @@ import React from 'react'; import { createApiExtension, createApiFactory, + createNavItemExtension, createPageExtension, createPlugin, createSchemaFromZod, @@ -37,6 +38,19 @@ import { createEntityContentExtension, } from '@backstage/plugin-catalog-react/alpha'; import { Grid } from '@material-ui/core'; +import { useApp } from '@backstage/core-plugin-api'; + +function ApiIcon() { + const app = useApp(); + const Component = app.getSystemIcon('kind:api')!; + return ; +} + +const ApiDocsNavItem = createNavItemExtension({ + title: 'APIs', + routeRef: convertLegacyRouteRef(rootRoute), + icon: () => compatWrapper(), +}); const ApiDocsConfigApi = createApiExtension({ factory: createApiFactory({ @@ -147,6 +161,26 @@ const ApiDocsDefinitionEntityContent = createEntityContentExtension({ ), }); +const ApiDocsApisEntityContent = createEntityContentExtension({ + name: 'apis', + defaultPath: '/apis', + defaultTitle: 'APIs', + filter: 'kind:component has:apis', + loader: async () => + import('./components/ApisCards').then(m => + compatWrapper( + + + + + + + + , + ), + ), +}); + export default createPlugin({ id: 'api-docs', routes: { @@ -156,6 +190,7 @@ export default createPlugin({ registerApi: convertLegacyRouteRef(registerComponentRouteRef), }, extensions: [ + ApiDocsNavItem, ApiDocsConfigApi, ApiDocsExplorerPage, ApiDocsHasApisEntityCard, @@ -165,5 +200,6 @@ export default createPlugin({ ApiDocsConsumingComponentsEntityCard, ApiDocsProvidingComponentsEntityCard, ApiDocsDefinitionEntityContent, + ApiDocsApisEntityContent, ], }); From 101d3a70676c259fb1e785960ffc4de84b2b747f Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 6 Feb 2024 15:22:53 +0100 Subject: [PATCH 16/19] docs(api-docs): add alpha readme file Signed-off-by: Camila Belo --- packages/app-next/app-config.yaml | 4 + plugins/api-docs/README-alpha.md | 1180 +++++++++++++++++++++++++++++ plugins/api-docs/README.md | 3 + plugins/api-docs/src/alpha.tsx | 6 +- 4 files changed, 1190 insertions(+), 3 deletions(-) create mode 100644 plugins/api-docs/README-alpha.md diff --git a/packages/app-next/app-config.yaml b/packages/app-next/app-config.yaml index dd2fe84a87..1eba16e6f8 100644 --- a/packages/app-next/app-config.yaml +++ b/packages/app-next/app-config.yaml @@ -1,6 +1,7 @@ app: experimental: packages: 'all' # ✨ + routes: bindings: catalog.viewTechDoc: techdocs.docRoot @@ -22,6 +23,9 @@ app: config: height: 300 - entity-card:azure-devops/readme + - entity-card:api-docs/has-apis: + config: + filter: kind:component - entity-card:api-docs/consumed-apis: config: filter: kind:component diff --git a/plugins/api-docs/README-alpha.md b/plugins/api-docs/README-alpha.md new file mode 100644 index 0000000000..3abd2b0a90 --- /dev/null +++ b/plugins/api-docs/README-alpha.md @@ -0,0 +1,1180 @@ +# Api Docs + +> [!WARNING] +> This documentation is made for those using the experimental new Frontend system. +> If you are not using the new frontend system, please go [here](./README.md). + +This is an extension for the catalog plugin that provides components to discover and display API entities. +APIs define the interface between components, see the [system model](https://backstage.io/docs/features/software-catalog/system-model) for details. +They are defined in machine readable formats and provide a human readable documentation. + +The plugin provides a standalone list of APIs, as well as an integration into the API tab of a catalog entity. + + + + + + + +Right now, the following API formats are supported: + +- [OpenAPI](https://swagger.io/specification/) 2 & 3 +- [AsyncAPI](https://www.asyncapi.com/docs/reference/specification/latest) +- [GraphQL](https://graphql.org/learn/schema/) + +Other formats are displayed as plain text, but this can easily be extended. + +To fill the catalog with APIs, [provide entities of kind API](https://backstage.io/docs/features/software-catalog/descriptor-format#kind-api). +To link that a component provides or consumes an API, see the [`providesApis`](https://backstage.io/docs/features/software-catalog/descriptor-format#specprovidesapis-optional) and [`consumesApis`](https://backstage.io/docs/features/software-catalog/descriptor-format#specconsumesapis-optional) properties on the Component kind. + +## Table of Content + +- [Installation](#installation) +- [Customization](#customization) + - [Packages](#packages) + - [Routes](#routes) + - [Extensions](#extensions) + - [Apis Nav Item](#apis-nav-item) + - [Apis Explorer Page](#apis-explore-page) + - [Apis Entity Cards](#apis-entities-cards) + - [Has Apis Entity Card](#has-apis-entity-card) + - [Definition Entity Card](#definition-entity-card) + - [Provided Apis Entity Card](#provided-apis-entity-card) + - [Consumed Apis Entity Card](#consumed-apis-entity-card) + - [Providing Components Entity Card](#providing-components-entity-card) + - [Consuming Components Entity Card](#consuming-components-entity-card) + - [Apis Entity Contents](#apis-entity-contents) + - [Definition Entity Content](#definition-entity-content) + - [Apis Entity Content](#apis-entity-content) + - [Apis Config Api](#apis-config-api) + - [Custom Api Renderings](#custom-api-renderings) + - [Adding Swagger UI Interceptor](#adding-requestinterceptor-to-swagger-ui) + - [Providing Swagger UI Specific Supported Methods](#provide-specific-supported-methods-to-swagger-ui) + - [Integrations](#integrations) + - [Implementing OAuth 2 Authorization Code flow with Swagger UI](#implementing-oauth-2-authorization-code-flow-with-swagger-ui) + +## Installation + +1. Install the `api-docs` plugin in you Backstage app: + +```bash +# From your Backstage root directory +yarn --cwd packages/app add @backstage/plugin-api-docs +``` + +2. In the app config file, enable the api docs entity cards and tabs so that the they begins to be presented on the catalog entity page: + +```yaml +# app-config.yaml +app: + experimental: + # Auto discovering all plugins extensions + packages: all + extensions: + # Enabling some entity Cards + # The cards will be displayed in the same order it appears in this setting list + # Shows a table of components that provides a particular api + - entity-card:api-docs/providing-components: + config: + # Presenting the card ony for entites of kind api + filter: kind:api + # Shows a table of components that consumes a particular api + - entity-card:api-docs/consuming-components: + config: + # Presenting the card ony for entites of kind api + filter: kind:api + # Enabling some Contents + # The contents will be displayed in the same order it appears in this setting list + # Shows a "Definition" tab for entities of kind api + - entity-content:api-docs/definition + # Shows an "Apis" tab for entities of kind component + - entity-content:api-docs/apis +``` + +3. Then start the app, navigate to an entity's page and see the cards and contents in there; +4. You can also access the Apis explorer page by clicking on the "APIs" sidebar item. + +## Customization + +### Packages + +This plugin features can be discovered automatically as soon as you install it, and it is also possible to only be enabled for certain [environments](https://backstage.io/docs/conf/writing/#configuration-files). See the examples below: + +_Enabling auto discovering the plugin extensions in production_ + +```yaml +# app-config.production.yaml +# Overriding configurations for the local production environment +app: + experimental: + packages: + # Only the following packages will be included + include: + - '@backstage/plugin-api-docs' +``` + +_Disabling auto discovering the plugin extensions in development_ + +```yaml +# app-config.local.yaml +# Overriding configurations for the local development environment +app: + experimental: + packages: + # All but the following package will be included + exclude: + - '@backstage/plugin-api-docs' +``` + +For more options of package configurations, see [this](https://backstage.io/docs/frontend-system/architecture/app/#feature-discovery) documentation. + +### Routes + +The `api-docs` plugin exposes regular and external routes that can be used to configure route bindings. + +| Key | Type | Description | +| ------------- | -------------- | -------------------------------------- | +| `root` | Regular route | A route ref to the Apis Explorer page. | +| `registerApi` | External route | A route ref to Register Api page. | + +As an example, here is an association between the external register api page and a regular route from another plugin: + +```yaml +# app-config.yaml +app: + routes: + bindings: + # example binding the external register api route + api-docs.registerApi: . +``` + +Additionally, it is possible to point a route from another plugin to the Apis explorer page: + +```yaml +# app-config.yaml +app: + routes: + bindings: + # example binding a external route to the apis explorer page + .: api-docs.root +``` + +Route binding is also possible through code. For more information, see [this](https://backstage.io/docs/frontend-system/architecture/routes#binding-external-route-references) documentation. + +### Extensions + +#### Apis Nav Item + +This [nav item](https://backstage.io/docs/reference/frontend-plugin-api.createnavitemextension) extension adds a link to the Apis Explorer page in the main app sidebar. + +| kind | Namespace | Name | Id | +| ---------- | ---------- | ---- | ------------------- | +| `nav-item` | `api-docs` | - | `nav-item:api-docs` | + +##### Disable + +This extension is enabled by default when you install the `api-docs` plugin, but you can disable it and prevent it from showing up in the sidebar by setting the following configuration: + +```yaml +# app-config.yaml +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + # example disabling the apis docs nav item extension + - nav-item:api-docs: false + # or + # - nav-item:api-docs: + # disabled: true +``` + +To enable the extension again, simple remove the previous `nav-item:api-docs: false` configuration or do: + +```yaml +# app-config.yaml +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + - nav-item:api-docs + # or + # - nav-item:api-docs: true + # or + # - nav-item:api-docs: + # disabled: false +``` + +##### Config + +The apis nav item can be customized under the `app.extensions.nav-item:api-docs.config` key in `app-config.yaml`. Configurations include: + +```yaml +# app-config.yaml +# example configuring the apis docs nav item extension +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + - nav-item:api-docs: + config: + # The nav item title text, defaults to "APIs" + title: 'Apis Explorer' + # The nav item path text, defaults to "/api-docs" + path: '/apis-explorer' +``` + +##### Override + +The apis nav item icon can only be changed by overriding the extension, as the icon cannot be changed via the `app-config.yaml` file. + +Here is an example overriding the nav item extension with a custom icon component: + +```tsx +import { createExtensionOverrides, createNavItemExtension } from '@backstage/backstage-plugin-api'; +import { convertLegacyRouteRef } from '@backstage/core-compat-api'; + +export default createExtensionOverrides( + extensions: [ + createNavItemExtension({ + // These namespace is necessary so the system knows that this extension will override the default nav item provided by the 'api-docs' plugin + namespace: 'api-docs', + // It's your choice whether to use the original extension's title or a different one + title: 'APIs', + // To continue pointing to the same page as the original extension, use the same route ref + routeRef: convertLegacyRouteRef(rootRoute), + // Custom icon components are loaded here + loader: () => import('./components').then(m => ) + }) + ] +); +``` + +For more information about where to place extension overrides, see the official [documentation](https://backstage.io/docs/frontend-system/architecture/extension-overrides). + +#### Apis Explore Page + +This `api-docs` plugin installs an "Apis Explore" page extension that helps you visualize apis registered in the Backstage software catalog. + +| kind | Namespace | Name | Id | +| ------ | ---------- | ---- | --------------- | +| `page` | `api-docs` | - | `page:api-docs` | + +##### Disable/Enable + +The explore page extension is enable by default when you install the `api-docs` plugin, for disabling it, set the configuration below: + +> [!CAUTION] +> The `api-docs` plugin also install a sidebar item that points to this page, remember to disable the nav item as well otherwise it will point to a not found page. + +```yaml +# app-config.yaml +# example disabling the apis docs explorer page +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + - page:api-docs: false + # or + # - page:api-docs: + # disabled: true +``` + +To enable the extension again, simple remove the previous `page:api-docs: false` configuration or do: + +```yaml +# app-config.yaml +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + - page:api-docs + # or + # - page:api-docs: true + # or + # - page:api-docs: + # disabled: false +``` + +##### Override + +The explorer page implementation can be overridden in situations where its default extension is not customizable enough. + +Here is an example overriding the APIs Explorer page component: + +```tsx +import { createExtensionOverrides, createPageExtension } from '@backstage/backstage-plugin-api'; +import { convertLegacyRouteRef } from '@backstage/core-compat-api'; + +export default createExtensionOverrides( + extensions: [ + createPageExtension({ + // These namespace is necessary so the system knows that this extension will override the default explorer page provided by the 'api-docs' plugin + namespace: 'api-docs', + // Ommitting name since we are overriding a plugin index page + // It's up to you whether to use the original default path or not, but links that are hardcoded to the default path won't work if you change it + defaultPath: '/api-docs', + // Associating the page with a different route ref may result in the sidebar item or external plugin route pointing to an unreachable page + routeRef: convertLegacyRouteRef(rootRoute), + // Custom page components are loaded here + loader: () => import('./components').then(m => ) + }) + ] +); +``` + +#### Apis Entities Cards + +The `api-docs` provide some entity cards you can enable to customize the Software Catalog entity page. + +> [!IMPORTANT] +> The order in which cards are listed in the configuration file will determine the order in which they appear in overview cards and tab lists on entity pages. + +See a complete cards list below: + +##### Has Apis Entity Card + +An [entity card](https://github.com/backstage/backstage/blob/master/plugins/catalog-react/api-report-alpha.md) extension that renders a table of entities that have an api relation with a particular Software catalog entity. + +| kind | Namespace | Name | Id | +| ------------- | ---------- | ---------- | ------------------------------- | +| `entity-card` | `api-docs` | `has-apis` | `entity-card:api-docs/has-apis` | + +###### Disable + +This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled regardless of the extension's default definition, add the following configuration: + +```yaml +# app-config.yaml +# example disabling the apis docs has apis entity card extension +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + # use false as value for disabling the extension and true for enabling + - entity-card:api-docs/has-apis: false + # or + # - entity-card:api-docs/has-apis: + # - config: + # # set 'true' for enabling it again + # disabled: true +``` + +###### Config + +For now there is only one configuration available for this entity cards extension, which is setting an entity filter that determines when the cards should be displayed on the entity page. +Here is an example showing the `has-apis` overview cards only for entities of kind component: + +```yaml +# app-config.yaml +# example setting the extension to only show up for entities with kind "component" +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + - entity-card:api-docs/has-apis: + config: + # For more information about entity cards filters, check out this pull request + # https://github.com/backstage/backstage/pull/21480 + filter: 'kind:component' +``` + +###### Override + +Use extension overrides for completely re-implementing the has apis entity card extension: + +```tsx +import { createExtensionOverrides } from '@backstage/backstage-plugin-api'; +import { createEntityCardExtension } from '@backstage/plugin-catalog-react/alpha'; + +export default createExtensionOverrides({ + extensions: [ + createEntityCardExtension({ + // These namespace and name necessary so the system knows that this extension will override the default 'has-apis' entity card extension provided by the 'api-docs' plugin + namespace: 'api-docs', + name: 'has-apis', + // Returing a custom card component + loader: () => + import('./components').then(m => ), + }), + ], +}); +``` + +For more information about where to place extension overrides, see the official [documentation](https://backstage.io/docs/frontend-system/architecture/extension-overrides). + +##### Definition Entity Card + +An Entity Card extension that renders an entity api definition widget. + +| kind | Namespace | Name | Id | +| ------------- | ---------- | ---------------- | ------------------------------------- | +| `entity-card` | `api-docs` | `api-definition` | `entity-card:api-docs/api-definition` | + +###### Disable + +This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled regardless of the extension's default definition, add the following configuration: + +```yaml +# app-config.yaml +# example disabling the api definition entity card extension +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + # use false as value for disabling the extension and true for enabling + - entity-card:api-docs/api-definition: false + # or + # - entity-card:api-docs/api-definition: + # - config: + # # set 'true' for enabling it again + # disabled: true +``` + +###### Config + +For now there is only one configuration available for this entity cards extension, which is setting an entity filter that determines when the cards should be displayed on the entity page. +Here is an example showing the `api-definition` overview cards only for entities of kind component: + +```yaml +# app-config.yaml +# example setting the extension to only show up for entities with kind "component" +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + - entity-card:api-docs/api-definition: + config: + # For more information about entity cards filters, check out this pull request + # https://github.com/backstage/backstage/pull/21480 + filter: 'kind:component' +``` + +###### Override + +Use extension overrides for completely re-implementing the has apis entity card extension: + +```tsx +import { createExtensionOverrides } from '@backstage/backstage-plugin-api'; +import { createEntityCardExtension } from '@backstage/plugin-catalog-react/alpha'; + +export default createExtensionOverrides({ + extensions: [ + createEntityCardExtension({ + // These namespace and name necessary so the system knows that this extension will override the default 'api-definition' entity card extension provided by the 'api-docs' plugin + namespace: 'api-docs', + name: 'api-definition', + // Returing a custom card component + loader: () => + import('./components').then(m => ), + }), + ], +}); +``` + +For more information about where to place extension overrides, see the official [documentation](https://backstage.io/docs/frontend-system/architecture/extension-overrides). + +##### Provided Apis Entity Card + +An Entity Card extension that renders a table of apis provided by a particular Software Catalog Component. + +| kind | Namespace | Name | Id | +| ------------- | ---------- | --------------- | ------------------------------------ | +| `entity-card` | `api-docs` | `provided-apis` | `entity-card:api-docs/provided-apis` | + +###### Disable + +This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled regardless of the extension's default definition, add the following configuration: + +```yaml +# app-config.yaml +# example disabling the provided apis entity card extension +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + # use false as value for disabling the extension and true for enabling + - entity-card:api-docs/provided-apis: false + # or + # - entity-card:api-docs/provided-apis: + # - config: + # # set 'true' for enabling it again + # disabled: true +``` + +###### Config + +For now there is only one configuration available for this entity cards extension, which is setting an entity filter that determines when the cards should be displayed on the entity page. +Here is an example showing the `provided-apis` overview cards only for entities of kind component: + +```yaml +# app-config.yaml +# example setting the extension to only show up for entities with kind "component" +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + - entity-card:api-docs/provided-apis: + config: + # For more information about entity cards filters, check out this pull request + # https://github.com/backstage/backstage/pull/21480 + filter: 'kind:component' +``` + +###### Override + +Use extension overrides for completely re-implementing the has apis entity card extension: + +```tsx +import { createExtensionOverrides } from '@backstage/backstage-plugin-api'; +import { createEntityCardExtension } from '@backstage/plugin-catalog-react/alpha'; + +export default createExtensionOverrides({ + extensions: [ + createEntityCardExtension({ + // These namespace and name necessary so the system knows that this extension will override the default 'provided-apis' entity card extension provided by the 'api-docs' plugin + namespace: 'api-docs', + name: 'provided-apis', + // Returing a custom card component + loader: () => + import('./components').then(m => ), + }), + ], +}); +``` + +For more information about where to place extension overrides, see the official [documentation](https://backstage.io/docs/frontend-system/architecture/extension-overrides). + +##### Consumed Apis Entity Card + +An Entity Card extension that renders a table of apis consumed by a particular Software Catalog Component. + +| kind | Namespace | Name | Id | +| ------------- | ---------- | --------------- | ------------------------------------ | +| `entity-card` | `api-docs` | `consumed-apis` | `entity-card:api-docs/consumed-apis` | + +###### Disable + +This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled regardless of the extension's default definition, add the following configuration: + +```yaml +# app-config.yaml +# example disabling the consumed apis entity card extension +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + # use false as value for disabling the extension and true for enabling + - entity-card:api-docs/consumed-apis: false + # or + # - entity-card:api-docs/consumed-apis: + # - config: + # # set 'true' for enabling it again + # disabled: true +``` + +###### Config + +For now there is only one configuration available for this entity cards extension, which is setting an entity filter that determines when the cards should be displayed on the entity page. +Here is an example showing the `consumed-apis` overview cards only for entities of kind component: + +```yaml +# app-config.yaml +# example setting the extension to only show up for entities with kind "component" +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + - entity-card:api-docs/consumed-apis: + config: + # For more information about entity cards filters, check out this pull request + # https://github.com/backstage/backstage/pull/21480 + filter: 'kind:component' +``` + +###### Override + +Use extension overrides for completely re-implementing the has apis entity card extension: + +```tsx +import { createExtensionOverrides } from '@backstage/backstage-plugin-api'; +import { createEntityCardExtension } from '@backstage/plugin-catalog-react/alpha'; + +export default createExtensionOverrides({ + extensions: [ + createEntityCardExtension({ + // These namespace and name necessary so the system knows that this extension will override the default 'consumed-apis' entity card extension provided by the 'api-docs' plugin + namespace: 'api-docs', + name: 'consumed-apis', + // Returing a custom card component + loader: () => + import('./components').then(m => ), + }), + ], +}); +``` + +For more information about where to place extension overrides, see the official [documentation](https://backstage.io/docs/frontend-system/architecture/extension-overrides). + +##### Providing Components Entity Card + +An Entity Card extension that renders a table of components that provides a particular Software Catalog api. + +| kind | Namespace | Name | Id | +| ------------- | ---------- | ---------------------- | ------------------------------------------- | +| `entity-card` | `api-docs` | `providing-components` | `entity-card:api-docs/providing-components` | + +###### Disable + +This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled regardless of the extension's default definition, add the following configuration: + +```yaml +# app-config.yaml +# example disabling the providing components entity card extension +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + # use false as value for disabling the extension and true for enabling + - entity-card:api-docs/providing-components: false + # or + # - entity-card:api-docs/providing-components: + # - config: + # # set 'true' for enabling it again + # disabled: true +``` + +###### Config + +For now there is only one configuration available for this entity cards extension, which is setting an entity filter that determines when the cards should be displayed on the entity page. +Here is an example showing the `providing-components` overview cards only for entities of kind component: + +```yaml +# app-config.yaml +# example setting the extension to only show up for entities with kind "component" +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + - entity-card:api-docs/providing-components: + config: + # For more information about entity cards filters, check out this pull request + # https://github.com/backstage/backstage/pull/21480 + filter: 'kind:component' +``` + +###### Override + +Use extension overrides for completely re-implementing the has apis entity card extension: + +```tsx +import { createExtensionOverrides } from '@backstage/backstage-plugin-api'; +import { createEntityCardExtension } from '@backstage/plugin-catalog-react/alpha'; + +export default createExtensionOverrides({ + extensions: [ + createEntityCardExtension({ + // These namespace and name necessary so the system knows that this extension will override the default 'providing-components' entity card extension provided by the 'api-docs' plugin + namespace: 'api-docs', + name: 'providing-components', + // Returing a custom card component + loader: () => + import('./components').then(m => ), + }), + ], +}); +``` + +For more information about where to place extension overrides, see the official [documentation](https://backstage.io/docs/frontend-system/architecture/extension-overrides). + +##### Consuming Components Entity Card + +An Entity Card extension that renders a table of components that consumes a particular Software Catalog api. + +| kind | Namespace | Name | Id | +| ------------- | ---------- | ---------------------- | ------------------------------------------- | +| `entity-card` | `api-docs` | `consuming-components` | `entity-card:api-docs/consuming-components` | + +###### Disable + +This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled regardless of the extension's default definition, add the following configuration: + +```yaml +# app-config.yaml +# example disabling the consuming components entity card extension +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + # use false as value for disabling the extension and true for enabling + - entity-card:api-docs/consuming-components: false + # or + # - entity-card:api-docs/consuming-components: + # - config: + # # set 'true' for enabling it again + # disabled: true +``` + +###### Config + +For now there is only one configuration available for this entity cards extension, which is setting an entity filter that determines when the cards should be displayed on the entity page. +Here is an example showing the `consuming-components` overview cards only for entities of kind component: + +```yaml +# app-config.yaml +# example setting the extension to only show up for entities with kind "component" +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + - entity-card:api-docs/consuming-components: + config: + # For more information about entity cards filters, check out this pull request + # https://github.com/backstage/backstage/pull/21480 + filter: 'kind:component' +``` + +###### Override + +Use extension overrides for completely re-implementing the has apis entity card extension: + +```tsx +import { createExtensionOverrides } from '@backstage/backstage-plugin-api'; +import { createEntityCardExtension } from '@backstage/plugin-catalog-react/alpha'; + +export default createExtensionOverrides({ + extensions: [ + createEntityCardExtension({ + // These namespace and name necessary so the system knows that this extension will override the default 'consuming-components' entity card extension provided by the 'api-docs' plugin + namespace: 'api-docs', + name: 'consuming-components', + // Returing a custom card component + loader: () => + import('./components').then(m => ), + }), + ], +}); +``` + +For more information about where to place extension overrides, see the official [documentation](https://backstage.io/docs/frontend-system/architecture/extension-overrides). + +### Apis Entity Contents + +The `api-docs` provide some entity contents you can enable to customize the Software Catalog entity page. + +> [!IMPORTANT] +> The order in which contents are listed in the configuration file will determine the order in which they appear in overview contents and tab lists on entity pages. + +See a complete contents list below: + +##### Definition Entity Content + +An Entity Content extension that renders a tab in the entity page showing a particular entity api definition. + +| kind | Namespace | Name | Id | +| ---------------- | ---------- | ------------ | ------------------------------------ | +| `entity-content` | `api-docs` | `definition` | `entity-content:api-docs/definition` | + +###### Disable + +This content is disabled by default when you install the `api-docs` plugin, but if you want make sure the content will always be disabled independently of the extension default definition, add this configuration: + +```yaml +# app-config.yaml +# example disabling the definition entity content extension +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + # use false as value for disabling the extension and true for enabling + - entity-content:api-docs/definition: false + # or + # - entity-content:api-docs/definition: + # - config: + # # set 'true' for enabling it again + # disabled: true +``` + +###### Config + +There are a few configuration options for this entity content extension, see the list below: + +```yaml +# app-config.yaml +# example setting the extension to only show up for entities with kind "api" +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + - entity-content:api-docs/definition: + config: + # A text-based query used to filter whether the entity contentextension should be rendered or not. + # For more information about entity cards filters, check out this pull request + # https://github.com/backstage/backstage/pull/21480 + # defaults to 'kind:api' + filter: 'kind:api' + # The entity content table title + # defaults to 'Definition' + title: 'Definition' + # the content tab path + # default to "/definition" + path: '/definition' +``` + +###### Override + +Use extension overrides for completely re-implementing the has apis entity card extension: + +```tsx +import { createExtensionOverrides } from '@backstage/backstage-plugin-api'; +import { createEntityContentExtension } from '@backstage/plugin-catalog-react/alpha'; + +export default createExtensionOverrides({ + extensions: [ + createEntityContentExtension({ + // These namespace and name necessary so the system knows that this extension will override the default 'definition' entity content extension provided by the 'api-docs' plugin + namespace: 'api-docs', + name: 'definition', + // Returing a custom content component + loader: () => + import('./components').then(m => ( + + )), + }), + ], +}); +``` + +For more information about where to place extension overrides, see the official [documentation](https://backstage.io/docs/frontend-system/architecture/extension-overrides). + +##### Apis Entity Content + +An Entity Content extension that renders a tab in the entity page showing a particular entity consumed and provided apis. + +| kind | Namespace | Name | Id | +| ---------------- | ---------- | ------ | ------------------------------ | +| `entity-content` | `api-docs` | `apis` | `entity-content:api-docs/apis` | + +###### Disable + +This content is disabled by default when you install the `api-docs` plugin, but if you want make sure the content will always be disabled independently of the extension default definition, add this configuration: + +```yaml +# app-config.yaml +# example disabling the apis entity content extension +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + # use false as value for disabling the extension and true for enabling + - entity-content:api-docs/apis: false + # or + # - entity-content:api-docs/apis: + # - config: + # # set 'true' for enabling it again + # disabled: true +``` + +###### Config + +There are a few configuration options for this entity content extension, see the list below: + +```yaml +# app-config.yaml +# example setting the extension to only show up for entities of kind "content" +app: + extensions: + # this is the extension id and it follows the naming pattern bellow: + # /: + - entity-content:api-docs/apis: + config: + # A text-based query used to filter whether the entity contentextension should be rendered or not. + # For more information about entity cards filters, check out this pull request + # https://github.com/backstage/backstage/pull/21480 + # defaults to 'kind:component' + filter: 'kind:component' + # The entity content table title + # defaults to 'Definition' + title: 'Definition' + # the content tab path + # default to "/definition" + path: '/definition' +``` + +###### Override + +Use extension overrides for completely re-implementing the apis entity content extension: + +```tsx +import { createExtensionOverrides } from '@backstage/backstage-plugin-api'; +import { createEntityContentExtension } from '@backstage/plugin-catalog-react/alpha'; + +export default createExtensionOverrides({ + extensions: [ + createEntityContentExtension({ + // These namespace and name necessary so the system knows that this extension will override the default 'apis' entity content extension provided by the 'api-docs' plugin + namespace: 'api-docs', + name: 'apis', + // Returing a custom content component + loader: () => + import('./components').then(m => ), + }), + ], +}); +``` + +For more information about where to place extension overrides, see the official [documentation](https://backstage.io/docs/frontend-system/architecture/extension-overrides). + +#### Apis Config Api + +This is an api used by the `api-docs` plugin to get the api definition widget. + +| kind | Namespace | Name | Id | +| ----- | ------------------------ | ---- | ---------------------------- | +| `api` | `plugin.api-docs.config` | - | `api:plugin.api-docs.config` | + +Changing the widgets returned by this API requires [overriding](https://backstage.io/docs/frontend-system/architecture/extension-overrides) the default extension implementation. Here are a few common override cases: + +##### Custom Api Renderings + +Add support for additional API types by providing a custom implementation for the `apiDocsConfigRef` and also use this to override the rendering of one of the already supported types. + +This is an example with a made-up renderer for SQL schemas: + +```tsx +import { + createExtensionOverrides, + createApiExtenion, + createApiFactory, +} from '@backstage/frontend-plugin-api'; +import { ApiEntity } from '@backstage/catalog-model'; +import { + apiDocsConfigRef, + ApiDefinitionWidget, + defaultDefinitionWidgets, +} from '@backstage/plugin-api-docs'; +import { SqlRenderer } from '...'; + +export default createExtensionOverrides({ + extensions: [ + createApiExtenion({ + factory: createApiFactory({ + api: apiDocsConfigRef, + deps: {}, + factory: () => { + // load the default widgets + const definitionWidgets = defaultDefinitionWidgets(); + return { + getApiDefinitionWidget: (apiEntity: ApiEntity) => { + // custom rendering for sql + if (apiEntity.spec.type === 'sql') { + return { + type: 'sql', + title: 'SQL', + component: definition => ( + + ), + } as ApiDefinitionWidget; + } + + // fallback to the defaults + return definitionWidgets.find( + d => d.type === apiEntity.spec.type, + ); + }, + }; + }, + }), + }), + ], +}); +``` + +##### Adding `requestInterceptor` to Swagger UI + +Override the config api to configure a [`requestInterceptor` for Swagger UI](https://github.com/swagger-api/swagger-ui/tree/master/flavors/swagger-ui-react#requestinterceptor-proptypesfunc) as following: + +```tsx +import { + createExtensionOverrides, + createApiExtenion, + createApiFactory, +} from '@backstage/frontend-plugin-api'; +import { + apiDocsConfigRef, + defaultDefinitionWidgets, + OpenApiDefinitionWidget, +} from '@backstage/plugin-api-docs'; +import { ApiEntity } from '@backstage/catalog-model'; + +export default createExtensionOverrides({ + extensions: [ + createApiExtenion({ + factory: createApiFactory({ + api: apiDocsConfigRef, + deps: {}, + factory: () => { + // Overriding openapi definition widget to add header + const requestInterceptor = (req: any) => { + req.headers.append('myheader', 'wombats'); + return req; + }; + const definitionWidgets = defaultDefinitionWidgets().map(obj => { + if (obj.type === 'openapi') { + return { + ...obj, + component: definition => ( + + ), + }; + } + return obj; + }); + + return { + getApiDefinitionWidget: (apiEntity: ApiEntity) => { + return definitionWidgets.find( + d => d.type === apiEntity.spec.type, + ); + }, + }; + }, + }), + }), + ], +}); +``` + +In the same way as the `requestInterceptor` you can override any property of Swagger UI. + +##### Provide Specific Supported Methods to Swagger UI + +This can be done through utilising the [supportedSubmitMethods prop](https://github.com/swagger-api/swagger-ui/tree/master/flavors/swagger-ui-react#supportedsubmitmethods-proptypesarrayofproptypesoneofget-put-post-delete-options-head-patch-trace). +If you want to limit the HTTP methods available for the `Try It Out` feature of an OpenAPI API component, you will need to override the config api and list the permitted methods for your API in the `supportedSubmitMethods` parameter: + +```tsx +import { + createExtensionOverrides, + createApiExtenion, + createApiFactory, +} from '@backstage/frontend-plugin-api'; +import { + apiDocsConfigRef, + defaultDefinitionWidgets, + OpenApiDefinitionWidget, +} from '@backstage/plugin-api-docs'; +import { ApiEntity } from '@backstage/catalog-model'; + +export default createExtensionOverrides({ + extensions: [ + createApiExtenion({ + factory: createApiFactory({ + api: apiDocsConfigRef, + deps: {}, + factory: () => { + const supportedSubmitMethods = ['get', 'post', 'put', 'delete']; + const definitionWidgets = defaultDefinitionWidgets().map(obj => { + if (obj.type === 'openapi') { + return { + ...obj, + component: definition => ( + + ), + }; + } + return obj; + }); + + return { + getApiDefinitionWidget: (apiEntity: ApiEntity) => { + return definitionWidgets.find( + d => d.type === apiEntity.spec.type, + ); + }, + }; + }, + }), + }), + ], +}); +``` + +N.B. if you wish to disable the `Try It Out` feature for your API, you can provide an empty list to the `supportedSubmitMethods` parameter. + +### Integrations + +#### Implementing OAuth 2 Authorization Code flow with Swagger UI + +##### Adding `oauth2-redirect.html` to support OAuth2 `redirect_uri` route + +The Swagger UI package by expects to have a route to `/oauth2-redirect.html` which processes +the redirect callback for the OAuth2 Authorization Code flow, however, this file is not installed +by this plugin. + +Grab a copy of [`oauth2-redirect.html`](https://github.com/swagger-api/swagger-ui/blob/master/dist/oauth2-redirect.html) +and put it in the `app/public/` directory in order to enable Swagger UI to complete this redirection. + +This also may require you to adjust `Content Security Policy` header settings of your Backstage application, so that the script in `oauth2-redirect.html` can be executed. Since the script is static we can add the hash of it directly to our CSP policy, which we do by adding the following to the `csp` section of the app configuration: + +```yaml +script-src: + - "'self'" + - "'unsafe-eval'" # this is required for scaffolder usage, and ajv validation. + - "'sha256-GeDavzSZ8O71Jggf/pQkKbt52dfZkrdNMQ3e+Ox+AkI='" # oauth2-redirect.html +``` + +##### Configuring your OAuth2 Client + +You'll need to make sure your OAuth2 client has been registered in your OAuth2 Authentication Server (AS) +with the appropriate `redirect_uris`, `scopes` and `grant_types`. For example, if your AS supports +the [OAuth 2.0 Dynamic Client Registration Protocol](https://tools.ietf.org/html/rfc7591), an example +POST request body would look like this: + +```json +{ + "client_name": "Example Backstage api-docs plugin Swagger UI Client", + "redirect_uris": [ + "https://www.getpostman.com/oauth2/callback", + "http://localhost:3000/oauth2-redirect.html" + "https:///oauth2-redirect.html" + ], + "scope": "read_pets write_pets", + "grant_types": [ + "authorization_code" + ] +} +``` + +The above `redirect_uris` are: + +- [Postman](https://www.postman.com/) testing: `https://www.getpostman.com/oauth2/callback` +- Local Backstage app development: `http://localhost:3000/oauth2-redirect.html` +- Backstage app production: `https:///oauth2-redirect.html` + +##### Configuring OAuth2 in your OpenAPI 3.0 schema + +To configure [OAuth 2 Authorization Code](https://swagger.io/docs/specification/authentication/oauth2/) flow +in your OpenAPI 3.0 schema you'll need something like this snippet: + +```yaml +components: + securitySchemes: + oauth: + type: oauth2 + description: OAuth2 service + flows: + authorizationCode: + authorizationUrl: https://api.example.com/oauth2/authorize + tokenUrl: https://api.example.com/oauth2/token + scopes: + read_pets: read your pets + write_pets: modify pets in your account +security: + oauth: + - [read_pets, write_pets] +``` diff --git a/plugins/api-docs/README.md b/plugins/api-docs/README.md index 9b8eb1669e..c9a8073982 100644 --- a/plugins/api-docs/README.md +++ b/plugins/api-docs/README.md @@ -1,5 +1,8 @@ # API Documentation +> Disclaimer: +> If you are looking for documentation on the experimental new frontend system support, please go [here](./README-alpha.md). + This is an extension for the catalog plugin that provides components to discover and display API entities. APIs define the interface between components, see the [system model](https://backstage.io/docs/features/software-catalog/system-model) for details. They are defined in machine readable formats and provide a human readable documentation. diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index 14a27ddd57..df7f45dcd3 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -42,8 +42,8 @@ import { useApp } from '@backstage/core-plugin-api'; function ApiIcon() { const app = useApp(); - const Component = app.getSystemIcon('kind:api')!; - return ; + const KindApiSystemIcon = app.getSystemIcon('kind:api')!; + return ; } const ApiDocsNavItem = createNavItemExtension({ @@ -165,7 +165,7 @@ const ApiDocsApisEntityContent = createEntityContentExtension({ name: 'apis', defaultPath: '/apis', defaultTitle: 'APIs', - filter: 'kind:component has:apis', + filter: 'kind:component', loader: async () => import('./components/ApisCards').then(m => compatWrapper( From 172a717ea2747278184f22b3369542cd46dd3f89 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 8 Feb 2024 09:38:10 +0100 Subject: [PATCH 17/19] chore: add changeset files Signed-off-by: Camila Belo --- .changeset/serious-dryers-grin.md | 5 +++++ .changeset/silver-crabs-exercise.md | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/serious-dryers-grin.md create mode 100644 .changeset/silver-crabs-exercise.md diff --git a/.changeset/serious-dryers-grin.md b/.changeset/serious-dryers-grin.md new file mode 100644 index 0000000000..24d17f4959 --- /dev/null +++ b/.changeset/serious-dryers-grin.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Fix entity content extension filtering. diff --git a/.changeset/silver-crabs-exercise.md b/.changeset/silver-crabs-exercise.md new file mode 100644 index 0000000000..ff34b5a3c3 --- /dev/null +++ b/.changeset/silver-crabs-exercise.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': minor +--- + +Migrate the `api-docs` to the new frontend system. It is experimental and available via alpha subpath. From adbaf94c5fa804f001babced32f57419cee15c57 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 8 Feb 2024 15:55:27 +0100 Subject: [PATCH 18/19] refactor(api-docs): apply review suggestions Signed-off-by: Camila Belo --- plugins/api-docs/README-alpha.md | 20 ++++++------- plugins/api-docs/src/alpha.tsx | 51 +++++++++++++++++--------------- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/plugins/api-docs/README-alpha.md b/plugins/api-docs/README-alpha.md index 3abd2b0a90..fa7de413af 100644 --- a/plugins/api-docs/README-alpha.md +++ b/plugins/api-docs/README-alpha.md @@ -406,9 +406,9 @@ For more information about where to place extension overrides, see the official An Entity Card extension that renders an entity api definition widget. -| kind | Namespace | Name | Id | -| ------------- | ---------- | ---------------- | ------------------------------------- | -| `entity-card` | `api-docs` | `api-definition` | `entity-card:api-docs/api-definition` | +| kind | Namespace | Name | Id | +| ------------- | ---------- | ------------ | --------------------------------- | +| `entity-card` | `api-docs` | `definition` | `entity-card:api-docs/definition` | ###### Disable @@ -416,15 +416,15 @@ This card is disabled by default when you install the `api-docs` plugin, but to ```yaml # app-config.yaml -# example disabling the api definition entity card extension +# example disabling the definition entity card extension app: extensions: # this is the extension id and it follows the naming pattern bellow: # /: # use false as value for disabling the extension and true for enabling - - entity-card:api-docs/api-definition: false + - entity-card:api-docs/definition: false # or - # - entity-card:api-docs/api-definition: + # - entity-card:api-docs/definition: # - config: # # set 'true' for enabling it again # disabled: true @@ -433,7 +433,7 @@ app: ###### Config For now there is only one configuration available for this entity cards extension, which is setting an entity filter that determines when the cards should be displayed on the entity page. -Here is an example showing the `api-definition` overview cards only for entities of kind component: +Here is an example showing the `definition` overview cards only for entities of kind component: ```yaml # app-config.yaml @@ -442,7 +442,7 @@ app: extensions: # this is the extension id and it follows the naming pattern bellow: # /: - - entity-card:api-docs/api-definition: + - entity-card:api-docs/definition: config: # For more information about entity cards filters, check out this pull request # https://github.com/backstage/backstage/pull/21480 @@ -460,9 +460,9 @@ import { createEntityCardExtension } from '@backstage/plugin-catalog-react/alpha export default createExtensionOverrides({ extensions: [ createEntityCardExtension({ - // These namespace and name necessary so the system knows that this extension will override the default 'api-definition' entity card extension provided by the 'api-docs' plugin + // These namespace and name necessary so the system knows that this extension will override the default 'definition' entity card extension provided by the 'api-docs' plugin namespace: 'api-docs', - name: 'api-definition', + name: 'definition', // Returing a custom card component loader: () => import('./components').then(m => ), diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index df7f45dcd3..6b43b68e63 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -46,13 +46,13 @@ function ApiIcon() { return ; } -const ApiDocsNavItem = createNavItemExtension({ +const apiDocsNavItem = createNavItemExtension({ title: 'APIs', routeRef: convertLegacyRouteRef(rootRoute), icon: () => compatWrapper(), }); -const ApiDocsConfigApi = createApiExtension({ +const apiDocsConfigApi = createApiExtension({ factory: createApiFactory({ api: apiDocsConfigRef, deps: {}, @@ -67,7 +67,7 @@ const ApiDocsConfigApi = createApiExtension({ }), }); -const ApiDocsExplorerPage = createPageExtension({ +const apiDocsExplorerPage = createPageExtension({ defaultPath: '/api-docs', routeRef: convertLegacyRouteRef(rootRoute), // Mapping DefaultApiExplorerPageProps to config @@ -88,22 +88,25 @@ const ApiDocsExplorerPage = createPageExtension({ ), }); -const ApiDocsHasApisEntityCard = createEntityCardExtension({ +const apiDocsHasApisEntityCard = createEntityCardExtension({ name: 'has-apis', // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 // and columns are too complex to map to zod - loader: () => import('./components/ApisCards').then(m => ), + loader: () => + import('./components/ApisCards').then(m => + compatWrapper(), + ), }); -const ApiDocsDefinitionEntityCard = createEntityCardExtension({ - name: 'api-definition', +const apiDocsDefinitionEntityCard = createEntityCardExtension({ + name: 'definition', loader: () => import('./components/ApiDefinitionCard').then(m => compatWrapper(), ), }); -const ApiDocsConsumedApisEntityCard = createEntityCardExtension({ +const apiDocsConsumedApisEntityCard = createEntityCardExtension({ name: 'consumed-apis', // Ommiting configSchema for now // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 @@ -114,7 +117,7 @@ const ApiDocsConsumedApisEntityCard = createEntityCardExtension({ ), }); -const ApiDocsProvidedApisEntityCard = createEntityCardExtension({ +const apiDocsProvidedApisEntityCard = createEntityCardExtension({ name: 'provided-apis', // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 // and columns are too complex to map to zod @@ -124,7 +127,7 @@ const ApiDocsProvidedApisEntityCard = createEntityCardExtension({ ), }); -const ApiDocsConsumingComponentsEntityCard = createEntityCardExtension({ +const apiDocsConsumingComponentsEntityCard = createEntityCardExtension({ name: 'consuming-components', // Ommiting configSchema for now // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 @@ -134,7 +137,7 @@ const ApiDocsConsumingComponentsEntityCard = createEntityCardExtension({ ), }); -const ApiDocsProvidingComponentsEntityCard = createEntityCardExtension({ +const apiDocsProvidingComponentsEntityCard = createEntityCardExtension({ name: 'providing-components', // Ommiting configSchema for now // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 @@ -144,7 +147,7 @@ const ApiDocsProvidingComponentsEntityCard = createEntityCardExtension({ ), }); -const ApiDocsDefinitionEntityContent = createEntityContentExtension({ +const apiDocsDefinitionEntityContent = createEntityContentExtension({ name: 'definition', defaultPath: '/defintion', defaultTitle: 'Definition', @@ -161,7 +164,7 @@ const ApiDocsDefinitionEntityContent = createEntityContentExtension({ ), }); -const ApiDocsApisEntityContent = createEntityContentExtension({ +const apiDocsApisEntityContent = createEntityContentExtension({ name: 'apis', defaultPath: '/apis', defaultTitle: 'APIs', @@ -190,16 +193,16 @@ export default createPlugin({ registerApi: convertLegacyRouteRef(registerComponentRouteRef), }, extensions: [ - ApiDocsNavItem, - ApiDocsConfigApi, - ApiDocsExplorerPage, - ApiDocsHasApisEntityCard, - ApiDocsDefinitionEntityCard, - ApiDocsProvidedApisEntityCard, - ApiDocsConsumedApisEntityCard, - ApiDocsConsumingComponentsEntityCard, - ApiDocsProvidingComponentsEntityCard, - ApiDocsDefinitionEntityContent, - ApiDocsApisEntityContent, + apiDocsNavItem, + apiDocsConfigApi, + apiDocsExplorerPage, + apiDocsHasApisEntityCard, + apiDocsDefinitionEntityCard, + apiDocsProvidedApisEntityCard, + apiDocsConsumedApisEntityCard, + apiDocsConsumingComponentsEntityCard, + apiDocsProvidingComponentsEntityCard, + apiDocsDefinitionEntityContent, + apiDocsApisEntityContent, ], }); From 32c9e9617623e4169d9127566ffa01ddf9b3d292 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 8 Feb 2024 20:02:17 +0100 Subject: [PATCH 19/19] refactor(api-docs): apply more review suggestions Signed-off-by: Camila Belo --- packages/app-next/app-config.yaml | 20 +--- plugins/api-docs/README-alpha.md | 178 ++++++++++++++---------------- plugins/api-docs/src/alpha.tsx | 53 ++++++--- 3 files changed, 127 insertions(+), 124 deletions(-) diff --git a/packages/app-next/app-config.yaml b/packages/app-next/app-config.yaml index 1eba16e6f8..28d05c902b 100644 --- a/packages/app-next/app-config.yaml +++ b/packages/app-next/app-config.yaml @@ -23,21 +23,11 @@ app: config: height: 300 - entity-card:azure-devops/readme - - entity-card:api-docs/has-apis: - config: - filter: kind:component - - entity-card:api-docs/consumed-apis: - config: - filter: kind:component - - entity-card:api-docs/provided-apis: - config: - filter: kind:component - - entity-card:api-docs/providing-components: - config: - filter: kind:api - - entity-card:api-docs/consuming-components: - config: - filter: kind:api + - entity-card:api-docs/has-apis + - entity-card:api-docs/consumed-apis + - entity-card:api-docs/provided-apis + - entity-card:api-docs/providing-components + - entity-card:api-docs/consuming-components # Entity page content - entity-content:api-docs/definition diff --git a/plugins/api-docs/README-alpha.md b/plugins/api-docs/README-alpha.md index fa7de413af..cb94144e0c 100644 --- a/plugins/api-docs/README-alpha.md +++ b/plugins/api-docs/README-alpha.md @@ -57,39 +57,39 @@ To link that a component provides or consumes an API, see the [`providesApis`](h 1. Install the `api-docs` plugin in you Backstage app: -```bash -# From your Backstage root directory -yarn --cwd packages/app add @backstage/plugin-api-docs -``` + ```bash + # From your Backstage root directory + yarn --cwd packages/app add @backstage/plugin-api-docs + ``` -2. In the app config file, enable the api docs entity cards and tabs so that the they begins to be presented on the catalog entity page: +2. Enable which entity cards and tabs you would like to see on the catalog entity page: -```yaml -# app-config.yaml -app: - experimental: - # Auto discovering all plugins extensions - packages: all - extensions: - # Enabling some entity Cards - # The cards will be displayed in the same order it appears in this setting list - # Shows a table of components that provides a particular api - - entity-card:api-docs/providing-components: - config: - # Presenting the card ony for entites of kind api - filter: kind:api - # Shows a table of components that consumes a particular api - - entity-card:api-docs/consuming-components: - config: - # Presenting the card ony for entites of kind api - filter: kind:api - # Enabling some Contents - # The contents will be displayed in the same order it appears in this setting list - # Shows a "Definition" tab for entities of kind api - - entity-content:api-docs/definition - # Shows an "Apis" tab for entities of kind component - - entity-content:api-docs/apis -``` + ```yaml + # app-config.yaml + app: + experimental: + # Auto discovering all plugins extensions + packages: all + extensions: + # Enabling some entity Cards + # The cards will be displayed in the same order it appears in this setting list + # Shows a table of components that provides a particular api + - entity-card:api-docs/providing-components: + config: + # Presenting the card ony for entites of kind api + filter: kind:api + # Shows a table of components that consumes a particular api + - entity-card:api-docs/consuming-components: + config: + # Presenting the card ony for entites of kind api + filter: kind:api + # Enabling some Contents + # The contents will be displayed in the same order it appears in this setting list + # Shows a "Definition" tab for entities of kind api + - entity-content:api-docs/definition + # Shows an "Apis" tab for entities of kind component + - entity-content:api-docs/apis + ``` 3. Then start the app, navigate to an entity's page and see the cards and contents in there; 4. You can also access the Apis explorer page by clicking on the "APIs" sidebar item. @@ -98,35 +98,7 @@ app: ### Packages -This plugin features can be discovered automatically as soon as you install it, and it is also possible to only be enabled for certain [environments](https://backstage.io/docs/conf/writing/#configuration-files). See the examples below: - -_Enabling auto discovering the plugin extensions in production_ - -```yaml -# app-config.production.yaml -# Overriding configurations for the local production environment -app: - experimental: - packages: - # Only the following packages will be included - include: - - '@backstage/plugin-api-docs' -``` - -_Disabling auto discovering the plugin extensions in development_ - -```yaml -# app-config.local.yaml -# Overriding configurations for the local development environment -app: - experimental: - packages: - # All but the following package will be included - exclude: - - '@backstage/plugin-api-docs' -``` - -For more options of package configurations, see [this](https://backstage.io/docs/frontend-system/architecture/app/#feature-discovery) documentation. +By default, the `api-docs` can be automatically discovered, and it is also possible to enable this plugin only in certain [environments](https://backstage.io/docs/conf/writing/#configuration-files). For more package configuration options, see [this](https://backstage.io/docs/frontend-system/architecture/app/#feature-discovery) documentation. ### Routes @@ -167,7 +139,7 @@ Route binding is also possible through code. For more information, see [this](ht This [nav item](https://backstage.io/docs/reference/frontend-plugin-api.createnavitemextension) extension adds a link to the Apis Explorer page in the main app sidebar. -| kind | Namespace | Name | Id | +| Kind | Namespace | Name | Id | | ---------- | ---------- | ---- | ------------------- | | `nav-item` | `api-docs` | - | `nav-item:api-docs` | @@ -255,7 +227,7 @@ For more information about where to place extension overrides, see the official This `api-docs` plugin installs an "Apis Explore" page extension that helps you visualize apis registered in the Backstage software catalog. -| kind | Namespace | Name | Id | +| Kind | Namespace | Name | Id | | ------ | ---------- | ---- | --------------- | | `page` | `api-docs` | - | `page:api-docs` | @@ -297,7 +269,7 @@ app: ##### Override -The explorer page implementation can be overridden in situations where its default extension is not customizable enough. +The explorer page implementation can be [overridden](https://backstage.io/docs/frontend-system/architecture/extension-overrides) in situations where its default extension is not customizable enough. Here is an example overriding the APIs Explorer page component: @@ -335,13 +307,13 @@ See a complete cards list below: An [entity card](https://github.com/backstage/backstage/blob/master/plugins/catalog-react/api-report-alpha.md) extension that renders a table of entities that have an api relation with a particular Software catalog entity. -| kind | Namespace | Name | Id | +| Kind | Namespace | Name | Id | | ------------- | ---------- | ---------- | ------------------------------- | | `entity-card` | `api-docs` | `has-apis` | `entity-card:api-docs/has-apis` | ###### Disable -This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled regardless of the extension's default definition, add the following configuration: +This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled or enabled regardless of the extension's default definition, add the following configuration: ```yaml # app-config.yaml @@ -361,7 +333,8 @@ app: ###### Config -For now there is only one configuration available for this entity cards extension, which is setting an entity filter that determines when the cards should be displayed on the entity page. +For now there is only one configuration available for this entity card extension, which is setting an entity filter that determines when the card should be displayed on the entity page. + Here is an example showing the `has-apis` overview cards only for entities of kind component: ```yaml @@ -373,6 +346,7 @@ app: # /: - entity-card:api-docs/has-apis: config: + # The default value is a function that verifies it is a components has api pat of relations # For more information about entity cards filters, check out this pull request # https://github.com/backstage/backstage/pull/21480 filter: 'kind:component' @@ -404,15 +378,15 @@ For more information about where to place extension overrides, see the official ##### Definition Entity Card -An Entity Card extension that renders an entity api definition widget. +An [entity card](https://github.com/backstage/backstage/blob/master/plugins/catalog-react/api-report-alpha.md) extension that renders an entity api definition widget. -| kind | Namespace | Name | Id | +| Kind | Namespace | Name | Id | | ------------- | ---------- | ------------ | --------------------------------- | | `entity-card` | `api-docs` | `definition` | `entity-card:api-docs/definition` | ###### Disable -This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled regardless of the extension's default definition, add the following configuration: +This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled or enabled regardless of the extension's default definition, add the following configuration: ```yaml # app-config.yaml @@ -432,7 +406,8 @@ app: ###### Config -For now there is only one configuration available for this entity cards extension, which is setting an entity filter that determines when the cards should be displayed on the entity page. +For now there is only one configuration available for this entity card extension, which is setting an entity filter that determines when the card should be displayed on the entity page. + Here is an example showing the `definition` overview cards only for entities of kind component: ```yaml @@ -444,6 +419,7 @@ app: # /: - entity-card:api-docs/definition: config: + # Default to 'kind:api' # For more information about entity cards filters, check out this pull request # https://github.com/backstage/backstage/pull/21480 filter: 'kind:component' @@ -475,15 +451,15 @@ For more information about where to place extension overrides, see the official ##### Provided Apis Entity Card -An Entity Card extension that renders a table of apis provided by a particular Software Catalog Component. +An [entity card](https://github.com/backstage/backstage/blob/master/plugins/catalog-react/api-report-alpha.md) extension that renders a table of apis provided by a particular Software Catalog Component. -| kind | Namespace | Name | Id | +| Kind | Namespace | Name | Id | | ------------- | ---------- | --------------- | ------------------------------------ | | `entity-card` | `api-docs` | `provided-apis` | `entity-card:api-docs/provided-apis` | ###### Disable -This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled regardless of the extension's default definition, add the following configuration: +This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled or enabled regardless of the extension's default definition, add the following configuration: ```yaml # app-config.yaml @@ -503,7 +479,8 @@ app: ###### Config -For now there is only one configuration available for this entity cards extension, which is setting an entity filter that determines when the cards should be displayed on the entity page. +For now there is only one configuration available for this entity card extension, which is setting an entity filter that determines when the card should be displayed on the entity page. + Here is an example showing the `provided-apis` overview cards only for entities of kind component: ```yaml @@ -515,6 +492,7 @@ app: # /: - entity-card:api-docs/provided-apis: config: + # Default to 'kind:component' # For more information about entity cards filters, check out this pull request # https://github.com/backstage/backstage/pull/21480 filter: 'kind:component' @@ -546,15 +524,15 @@ For more information about where to place extension overrides, see the official ##### Consumed Apis Entity Card -An Entity Card extension that renders a table of apis consumed by a particular Software Catalog Component. +An [entity card](https://github.com/backstage/backstage/blob/master/plugins/catalog-react/api-report-alpha.md) extension that renders a table of apis consumed by a particular Software Catalog Component. -| kind | Namespace | Name | Id | +| Kind | Namespace | Name | Id | | ------------- | ---------- | --------------- | ------------------------------------ | | `entity-card` | `api-docs` | `consumed-apis` | `entity-card:api-docs/consumed-apis` | ###### Disable -This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled regardless of the extension's default definition, add the following configuration: +This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled or enabled regardless of the extension's default definition, add the following configuration: ```yaml # app-config.yaml @@ -574,7 +552,8 @@ app: ###### Config -For now there is only one configuration available for this entity cards extension, which is setting an entity filter that determines when the cards should be displayed on the entity page. +For now there is only one configuration available for this entity card extension, which is setting an entity filter that determines when the card should be displayed on the entity page. + Here is an example showing the `consumed-apis` overview cards only for entities of kind component: ```yaml @@ -586,6 +565,7 @@ app: # /: - entity-card:api-docs/consumed-apis: config: + # Default to 'kind:component' # For more information about entity cards filters, check out this pull request # https://github.com/backstage/backstage/pull/21480 filter: 'kind:component' @@ -617,15 +597,15 @@ For more information about where to place extension overrides, see the official ##### Providing Components Entity Card -An Entity Card extension that renders a table of components that provides a particular Software Catalog api. +An [entity card](https://github.com/backstage/backstage/blob/master/plugins/catalog-react/api-report-alpha.md) extension that renders a table of components that provides a particular Software Catalog api. -| kind | Namespace | Name | Id | +| Kind | Namespace | Name | Id | | ------------- | ---------- | ---------------------- | ------------------------------------------- | | `entity-card` | `api-docs` | `providing-components` | `entity-card:api-docs/providing-components` | ###### Disable -This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled regardless of the extension's default definition, add the following configuration: +This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled or enabled regardless of the extension's default definition, add the following configuration: ```yaml # app-config.yaml @@ -645,7 +625,8 @@ app: ###### Config -For now there is only one configuration available for this entity cards extension, which is setting an entity filter that determines when the cards should be displayed on the entity page. +For now there is only one configuration available for this entity card extension, which is setting an entity filter that determines when the card should be displayed on the entity page. + Here is an example showing the `providing-components` overview cards only for entities of kind component: ```yaml @@ -657,6 +638,7 @@ app: # /: - entity-card:api-docs/providing-components: config: + # Default to 'kind:api' # For more information about entity cards filters, check out this pull request # https://github.com/backstage/backstage/pull/21480 filter: 'kind:component' @@ -678,7 +660,9 @@ export default createExtensionOverrides({ name: 'providing-components', // Returing a custom card component loader: () => - import('./components').then(m => ), + import('./components').then(m => ( + + )), }), ], }); @@ -688,15 +672,15 @@ For more information about where to place extension overrides, see the official ##### Consuming Components Entity Card -An Entity Card extension that renders a table of components that consumes a particular Software Catalog api. +An [entity card](https://github.com/backstage/backstage/blob/master/plugins/catalog-react/api-report-alpha.md) extension that renders a table of components that consumes a particular Software Catalog api. -| kind | Namespace | Name | Id | +| Kind | Namespace | Name | Id | | ------------- | ---------- | ---------------------- | ------------------------------------------- | | `entity-card` | `api-docs` | `consuming-components` | `entity-card:api-docs/consuming-components` | ###### Disable -This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled regardless of the extension's default definition, add the following configuration: +This card is disabled by default when you install the `api-docs` plugin, but to ensure the card will always be disabled or enabled regardless of the extension's default definition, add the following configuration: ```yaml # app-config.yaml @@ -716,7 +700,8 @@ app: ###### Config -For now there is only one configuration available for this entity cards extension, which is setting an entity filter that determines when the cards should be displayed on the entity page. +For now there is only one configuration available for this entity card extension, which is setting an entity filter that determines when the card should be displayed on the entity page. + Here is an example showing the `consuming-components` overview cards only for entities of kind component: ```yaml @@ -728,6 +713,7 @@ app: # /: - entity-card:api-docs/consuming-components: config: + # Default to 'kind:api' # For more information about entity cards filters, check out this pull request # https://github.com/backstage/backstage/pull/21480 filter: 'kind:component' @@ -749,7 +735,9 @@ export default createExtensionOverrides({ name: 'consuming-components', // Returing a custom card component loader: () => - import('./components').then(m => ), + import('./components').then(m => ( + + )), }), ], }); @@ -762,21 +750,21 @@ For more information about where to place extension overrides, see the official The `api-docs` provide some entity contents you can enable to customize the Software Catalog entity page. > [!IMPORTANT] -> The order in which contents are listed in the configuration file will determine the order in which they appear in overview contents and tab lists on entity pages. +> The order in which contents are listed in the configuration file will determine the order in which they appear in overview contents and tabs on entity pages. See a complete contents list below: ##### Definition Entity Content -An Entity Content extension that renders a tab in the entity page showing a particular entity api definition. +An [entity content](https://github.com/backstage/backstage/blob/master/plugins/catalog-react/api-report-alpha.md) extension that renders a tab in the entity page showing a particular entity api definition. -| kind | Namespace | Name | Id | +| Kind | Namespace | Name | Id | | ---------------- | ---------- | ------------ | ------------------------------------ | | `entity-content` | `api-docs` | `definition` | `entity-content:api-docs/definition` | ###### Disable -This content is disabled by default when you install the `api-docs` plugin, but if you want make sure the content will always be disabled independently of the extension default definition, add this configuration: +This content is disabled by default when you install the `api-docs` plugin, but to ensure the content will always be disabled or enabled regardless of the extension's default definition, add the following configuration: ```yaml # app-config.yaml @@ -850,13 +838,13 @@ For more information about where to place extension overrides, see the official An Entity Content extension that renders a tab in the entity page showing a particular entity consumed and provided apis. -| kind | Namespace | Name | Id | +| Kind | Namespace | Name | Id | | ---------------- | ---------- | ------ | ------------------------------ | | `entity-content` | `api-docs` | `apis` | `entity-content:api-docs/apis` | ###### Disable -This content is disabled by default when you install the `api-docs` plugin, but if you want make sure the content will always be disabled independently of the extension default definition, add this configuration: +This content is disabled by default when you install the `api-docs` plugin, but to ensure the content will always be disabled or enabled regardless of the extension's default definition, add the following configuration: ```yaml # app-config.yaml @@ -928,7 +916,7 @@ For more information about where to place extension overrides, see the official This is an api used by the `api-docs` plugin to get the api definition widget. -| kind | Namespace | Name | Id | +| Kind | Namespace | Name | Id | | ----- | ------------------------ | ---- | ---------------------------- | | `api` | `plugin.api-docs.config` | - | `api:plugin.api-docs.config` | diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index 6b43b68e63..38b8db89c6 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -15,6 +15,7 @@ */ import React from 'react'; +import { Grid } from '@material-ui/core'; import { createApiExtension, @@ -24,21 +25,26 @@ import { createPlugin, createSchemaFromZod, } from '@backstage/frontend-plugin-api'; + import { compatWrapper, convertLegacyRouteRef, } from '@backstage/core-compat-api'; -import { ApiEntity } from '@backstage/catalog-model'; +import { useApp } from '@backstage/core-plugin-api'; -import { defaultDefinitionWidgets } from './components/ApiDefinitionCard'; -import { rootRoute, registerComponentRouteRef } from './routes'; -import { apiDocsConfigRef } from './config'; import { createEntityCardExtension, createEntityContentExtension, } from '@backstage/plugin-catalog-react/alpha'; -import { Grid } from '@material-ui/core'; -import { useApp } from '@backstage/core-plugin-api'; +import { + ApiEntity, + parseEntityRef, + RELATION_HAS_PART, +} from '@backstage/catalog-model'; + +import { defaultDefinitionWidgets } from './components/ApiDefinitionCard'; +import { rootRoute, registerComponentRouteRef } from './routes'; +import { apiDocsConfigRef } from './config'; function ApiIcon() { const app = useApp(); @@ -90,8 +96,19 @@ const apiDocsExplorerPage = createPageExtension({ const apiDocsHasApisEntityCard = createEntityCardExtension({ name: 'has-apis', - // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 - // and columns are too complex to map to zod + // Ommiting configSchema for now + // We are skipping variants and columns are too complex to map to zod + // See: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + filter: entity => { + return ( + entity.kind === 'Component' && + entity.relations?.some( + ({ type, targetRef }) => + type.toLocaleLowerCase('en-US') === RELATION_HAS_PART && + parseEntityRef(targetRef).kind === 'API', + )!! + ); + }, loader: () => import('./components/ApisCards').then(m => compatWrapper(), @@ -100,6 +117,7 @@ const apiDocsHasApisEntityCard = createEntityCardExtension({ const apiDocsDefinitionEntityCard = createEntityCardExtension({ name: 'definition', + filter: 'kind:api', loader: () => import('./components/ApiDefinitionCard').then(m => compatWrapper(), @@ -109,8 +127,9 @@ const apiDocsDefinitionEntityCard = createEntityCardExtension({ const apiDocsConsumedApisEntityCard = createEntityCardExtension({ name: 'consumed-apis', // Ommiting configSchema for now - // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 - // and columns are too complex to map to zod + // We are skipping variants and columns are too complex to map to zod + // See: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + filter: 'kind:component', loader: () => import('./components/ApisCards').then(m => compatWrapper(), @@ -119,8 +138,10 @@ const apiDocsConsumedApisEntityCard = createEntityCardExtension({ const apiDocsProvidedApisEntityCard = createEntityCardExtension({ name: 'provided-apis', - // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 - // and columns are too complex to map to zod + // Ommiting configSchema for now + // We are skipping variants and columns are too complex to map to zod + // See: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + filter: 'kind:component', loader: () => import('./components/ApisCards').then(m => compatWrapper(), @@ -130,7 +151,9 @@ const apiDocsProvidedApisEntityCard = createEntityCardExtension({ const apiDocsConsumingComponentsEntityCard = createEntityCardExtension({ name: 'consuming-components', // Ommiting configSchema for now - // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + // We are skipping variants + // See: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + filter: 'kind:api', loader: () => import('./components/ComponentsCards').then(m => compatWrapper(), @@ -140,7 +163,9 @@ const apiDocsConsumingComponentsEntityCard = createEntityCardExtension({ const apiDocsProvidingComponentsEntityCard = createEntityCardExtension({ name: 'providing-components', // Ommiting configSchema for now - // we are skipping variants, see: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + // We are skipping variants + // See: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + filter: 'kind:api', loader: () => import('./components/ComponentsCards').then(m => compatWrapper(),