diff --git a/packages/app-next-example-plugin/src/plugin.tsx b/packages/app-next-example-plugin/src/plugin.tsx index 7c41405c59..818e8abc84 100644 --- a/packages/app-next-example-plugin/src/plugin.tsx +++ b/packages/app-next-example-plugin/src/plugin.tsx @@ -16,13 +16,15 @@ import React from 'react'; import { - createPageExtension, + PageBlueprint, createFrontendPlugin, } from '@backstage/frontend-plugin-api'; -export const ExamplePage = createPageExtension({ - defaultPath: '/example', - loader: () => import('./Component').then(m => ), +export const ExamplePage = PageBlueprint.make({ + params: { + defaultPath: '/example', + loader: () => import('./Component').then(m => ), + }, }); /** @public */ diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index 4d803b3991..216666be8f 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -18,12 +18,11 @@ import React from 'react'; import Grid from '@material-ui/core/Grid'; import { - createApiExtension, + ApiBlueprint, + NavItemBlueprint, + PageBlueprint, createApiFactory, - createNavItemExtension, - createPageExtension, createFrontendPlugin, - createSchemaFromZod, } from '@backstage/frontend-plugin-api'; import { @@ -31,10 +30,6 @@ import { convertLegacyRouteRef, } from '@backstage/core-compat-api'; -import { - createEntityCardExtension, - createEntityContentExtension, -} from '@backstage/plugin-catalog-react/alpha'; import { ApiEntity, parseEntityRef, @@ -46,161 +41,190 @@ import { rootRoute, registerComponentRouteRef } from './routes'; import { apiDocsConfigRef } from './config'; import { AppIcon } from '@backstage/core-components'; -const apiDocsNavItem = createNavItemExtension({ - title: 'APIs', - routeRef: convertLegacyRouteRef(rootRoute), - icon: () => compatWrapper(), -}); +import { + EntityCardBlueprint, + EntityContentBlueprint, +} from '@backstage/plugin-catalog-react/alpha'; -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); - }, - }; - }, - }), -}); - -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: ({ config }) => - import('./components/ApiExplorerPage').then(m => - compatWrapper( - , - ), - ), -}); - -const apiDocsHasApisEntityCard = createEntityCardExtension({ - name: 'has-apis', - // 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', - )!! - ); +const apiDocsNavItem = NavItemBlueprint.make({ + params: { + title: 'APIs', + routeRef: convertLegacyRouteRef(rootRoute), + icon: () => compatWrapper(), }, - loader: () => - import('./components/ApisCards').then(m => - compatWrapper(), - ), }); -const apiDocsDefinitionEntityCard = createEntityCardExtension({ +const apiDocsConfigApi = ApiBlueprint.make({ + namespace: 'api-docs', + params: { + factory: createApiFactory({ + api: apiDocsConfigRef, + deps: {}, + factory: () => { + const definitionWidgets = defaultDefinitionWidgets(); + return { + getApiDefinitionWidget: (apiEntity: ApiEntity) => { + return definitionWidgets.find(d => d.type === apiEntity.spec.type); + }, + }; + }, + }), + }, +}); + +const apiDocsExplorerPage = PageBlueprint.makeWithOverrides({ + config: { + schema: { + // Ommiting columns and actions for now as their types are too complex to map to zod + initiallySelectedFilter: z => + z.enum(['owned', 'starred', 'all']).optional(), + }, + }, + factory(originalFactory, { config }) { + return originalFactory({ + defaultPath: '/api-docs', + routeRef: convertLegacyRouteRef(rootRoute), + loader: () => + import('./components/ApiExplorerPage').then(m => + compatWrapper( + , + ), + ), + }); + }, +}); + +const apiDocsHasApisEntityCard = EntityCardBlueprint.make({ + name: 'has-apis', + params: { + // 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(), + ), + }, +}); + +const apiDocsDefinitionEntityCard = EntityCardBlueprint.make({ name: 'definition', - filter: 'kind:api', - loader: () => - import('./components/ApiDefinitionCard').then(m => - compatWrapper(), - ), + params: { + filter: 'kind:api', + loader: () => + import('./components/ApiDefinitionCard').then(m => + compatWrapper(), + ), + }, }); -const apiDocsConsumedApisEntityCard = createEntityCardExtension({ +const apiDocsConsumedApisEntityCard = EntityCardBlueprint.make({ name: 'consumed-apis', - // 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(), - ), + params: { + // 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(), + ), + }, }); -const apiDocsProvidedApisEntityCard = createEntityCardExtension({ +const apiDocsProvidedApisEntityCard = EntityCardBlueprint.make({ name: 'provided-apis', - // 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(), - ), + params: { + // 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(), + ), + }, }); -const apiDocsConsumingComponentsEntityCard = createEntityCardExtension({ +const apiDocsConsumingComponentsEntityCard = EntityCardBlueprint.make({ name: 'consuming-components', - // Ommiting configSchema for now - // We are skipping variants - // See: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 - filter: 'kind:api', - loader: () => - import('./components/ComponentsCards').then(m => - compatWrapper(), - ), + params: { + // Ommiting configSchema for now + // We are skipping variants + // See: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + filter: 'kind:api', + loader: () => + import('./components/ComponentsCards').then(m => + compatWrapper(), + ), + }, }); -const apiDocsProvidingComponentsEntityCard = createEntityCardExtension({ +const apiDocsProvidingComponentsEntityCard = EntityCardBlueprint.make({ name: 'providing-components', - // Ommiting configSchema for now - // We are skipping variants - // See: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 - filter: 'kind:api', - loader: () => - import('./components/ComponentsCards').then(m => - compatWrapper(), - ), + params: { + // Ommiting configSchema for now + // We are skipping variants + // See: https://github.com/backstage/backstage/pull/22619#discussion_r1477333252 + filter: 'kind:api', + loader: () => + import('./components/ComponentsCards').then(m => + compatWrapper(), + ), + }, }); -const apiDocsDefinitionEntityContent = createEntityContentExtension({ +const apiDocsDefinitionEntityContent = EntityContentBlueprint.make({ name: 'definition', - defaultPath: '/defintion', - defaultTitle: 'Definition', - filter: 'kind:api', - loader: async () => - import('./components/ApiDefinitionCard').then(m => - compatWrapper( - - - - - , + params: { + defaultPath: '/defintion', + defaultTitle: 'Definition', + filter: 'kind:api', + loader: async () => + import('./components/ApiDefinitionCard').then(m => + compatWrapper( + + + + + , + ), ), - ), + }, }); -const apiDocsApisEntityContent = createEntityContentExtension({ +const apiDocsApisEntityContent = EntityContentBlueprint.make({ name: 'apis', - defaultPath: '/apis', - defaultTitle: 'APIs', - filter: 'kind:component', - loader: async () => - import('./components/ApisCards').then(m => - compatWrapper( - - - - - - - - , + params: { + defaultPath: '/apis', + defaultTitle: 'APIs', + filter: 'kind:component', + loader: async () => + import('./components/ApisCards').then(m => + compatWrapper( + + + + + + + + , + ), ), - ), + }, }); export default createFrontendPlugin({ diff --git a/plugins/home/src/alpha.tsx b/plugins/home/src/alpha.tsx index e31fe833f6..ce96b18943 100644 --- a/plugins/home/src/alpha.tsx +++ b/plugins/home/src/alpha.tsx @@ -20,7 +20,7 @@ import { coreExtensionData, createExtensionDataRef, createExtensionInput, - createPageExtension, + PageBlueprint, createFrontendPlugin, createRouteRef, } from '@backstage/frontend-plugin-api'; @@ -35,31 +35,34 @@ export const titleExtensionDataRef = createExtensionDataRef().with({ id: 'title', }); -const homePage = createPageExtension({ - defaultPath: '/home', - routeRef: rootRouteRef, +const homePage = PageBlueprint.makeWithOverrides({ inputs: { props: createExtensionInput( - { - children: coreExtensionData.reactElement.optional(), - title: titleExtensionDataRef.optional(), - }, - + [ + coreExtensionData.reactElement.optional(), + titleExtensionDataRef.optional(), + ], { singleton: true, optional: true, }, ), }, - loader: ({ inputs }) => - import('./components/').then(m => - compatWrapper( - , - ), - ), + factory: (originalFactory, { inputs }) => { + return originalFactory({ + defaultPath: '/home', + routeRef: rootRouteRef, + loader: () => + import('./components/').then(m => + compatWrapper( + , + ), + ), + }); + }, }); /** diff --git a/plugins/kubernetes/src/alpha/pages.tsx b/plugins/kubernetes/src/alpha/pages.tsx index 8b5db150bd..a58ffec94f 100644 --- a/plugins/kubernetes/src/alpha/pages.tsx +++ b/plugins/kubernetes/src/alpha/pages.tsx @@ -16,18 +16,20 @@ import React from 'react'; // Add this line to import React -import { createPageExtension } from '@backstage/frontend-plugin-api'; +import { PageBlueprint } from '@backstage/frontend-plugin-api'; import { compatWrapper, convertLegacyRouteRef, } from '@backstage/core-compat-api'; import { rootCatalogKubernetesRouteRef } from '../plugin'; -export const kubernetesPage = createPageExtension({ - defaultPath: '/kubernetes', - // you can reuse the existing routeRef - // by wrapping into the convertLegacyRouteRef. - routeRef: convertLegacyRouteRef(rootCatalogKubernetesRouteRef), - // these inputs usually match the props required by the component. - loader: () => import('../Router').then(m => compatWrapper()), +export const kubernetesPage = PageBlueprint.make({ + params: { + defaultPath: '/kubernetes', + // you can reuse the existing routeRef + // by wrapping into the convertLegacyRouteRef. + routeRef: convertLegacyRouteRef(rootCatalogKubernetesRouteRef), + // these inputs usually match the props required by the component. + loader: () => import('../Router').then(m => compatWrapper()), + }, });