diff --git a/.changeset/hot-pillows-poke.md b/.changeset/hot-pillows-poke.md new file mode 100644 index 0000000000..8060e7121f --- /dev/null +++ b/.changeset/hot-pillows-poke.md @@ -0,0 +1,11 @@ +--- +'@backstage/plugin-user-settings': patch +'@backstage/plugin-scaffolder': patch +'@backstage/plugin-tech-radar': patch +'@backstage/plugin-graphiql': patch +'@backstage/plugin-techdocs': patch +'@backstage/plugin-catalog': patch +'@backstage/plugin-search': patch +--- + +Use `convertLegacyRouteRefs` to define routes in `/alpha` export plugin. diff --git a/.changeset/olive-singers-accept.md b/.changeset/olive-singers-accept.md new file mode 100644 index 0000000000..7e8cf7ae8d --- /dev/null +++ b/.changeset/olive-singers-accept.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-compat-api': patch +--- + +Added `convertLegacyRouteRefs` for bulk conversion of plugin routes. diff --git a/.changeset/twenty-taxis-mate.md b/.changeset/twenty-taxis-mate.md new file mode 100644 index 0000000000..65ed158e9b --- /dev/null +++ b/.changeset/twenty-taxis-mate.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-compat-api': patch +--- + +Plugins converted by `convertLegacyApp` now have their `routes` and `externalRoutes` included as well, allowing them to be used to bind external routes in configuration. diff --git a/packages/app-next/app-config.yaml b/packages/app-next/app-config.yaml index 77f4284455..1b77205d5e 100644 --- a/packages/app-next/app-config.yaml +++ b/packages/app-next/app-config.yaml @@ -5,6 +5,7 @@ app: bindings: plugin.pages.externalRoutes.pageX: plugin.pages.routes.pageX plugin.catalog.externalRoutes.viewTechDoc: plugin.techdocs.routes.docRoot + plugin.catalog.externalRoutes.createComponent: plugin.catalog-import.routes.importPage extensions: # - apis.plugin.graphiql.browse.gitlab: true diff --git a/packages/core-compat-api/api-report.md b/packages/core-compat-api/api-report.md index 494747be60..a7aae2b5b9 100644 --- a/packages/core-compat-api/api-report.md +++ b/packages/core-compat-api/api-report.md @@ -40,5 +40,26 @@ export function convertLegacyRouteRef< ref: ExternalRouteRef, ): ExternalRouteRef_2; +// @public +export function convertLegacyRouteRefs< + TRefs extends { + [name in string]: RouteRef | SubRouteRef | ExternalRouteRef; + }, +>( + refs: TRefs, +): { + [KName in keyof TRefs]: ToNewRouteRef; +}; + +// @public +export type ToNewRouteRef = + T extends RouteRef + ? RouteRef_2 + : T extends SubRouteRef + ? SubRouteRef_2 + : T extends ExternalRouteRef + ? ExternalRouteRef_2 + : never; + // (No @packageDocumentation comment for this package) ``` diff --git a/packages/core-compat-api/src/collectLegacyRoutes.tsx b/packages/core-compat-api/src/collectLegacyRoutes.tsx index 4d560b81d5..7ddb8c4f7e 100644 --- a/packages/core-compat-api/src/collectLegacyRoutes.tsx +++ b/packages/core-compat-api/src/collectLegacyRoutes.tsx @@ -32,7 +32,10 @@ import { } from '@backstage/frontend-plugin-api'; import React, { Children, ReactNode, isValidElement } from 'react'; import { Route, Routes } from 'react-router-dom'; -import { convertLegacyRouteRef } from './convertLegacyRouteRef'; +import { + convertLegacyRouteRef, + convertLegacyRouteRefs, +} from './convertLegacyRouteRef'; import { compatWrapper } from './compatWrapper'; /* @@ -244,6 +247,8 @@ export function collectLegacyRoutes( createApiExtension({ factory }), ), ], + routes: convertLegacyRouteRefs(plugin.routes ?? {}), + externalRoutes: convertLegacyRouteRefs(plugin.externalRoutes ?? {}), }), ); } diff --git a/packages/core-compat-api/src/convertLegacyRouteRef.ts b/packages/core-compat-api/src/convertLegacyRouteRef.ts index c5ee603722..36311dc081 100644 --- a/packages/core-compat-api/src/convertLegacyRouteRef.ts +++ b/packages/core-compat-api/src/convertLegacyRouteRef.ts @@ -40,6 +40,43 @@ import { toInternalSubRouteRef } from '../../frontend-plugin-api/src/routing/Sub // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { toInternalExternalRouteRef } from '../../frontend-plugin-api/src/routing/ExternalRouteRef'; +/** + * Converts a legacy route ref type to the new system. + * + * @public + */ +export type ToNewRouteRef< + T extends LegacyRouteRef | LegacySubRouteRef | LegacyExternalRouteRef, +> = T extends LegacyRouteRef + ? RouteRef + : T extends LegacySubRouteRef + ? SubRouteRef + : T extends LegacyExternalRouteRef + ? ExternalRouteRef + : never; + +/** + * Converts a collection of legacy route refs to the new system. + * This is particularly useful when defining plugin `routes` and `externalRoutes`. + * + * @public + */ +export function convertLegacyRouteRefs< + TRefs extends { + [name in string]: + | LegacyRouteRef + | LegacySubRouteRef + | LegacyExternalRouteRef; + }, +>(refs: TRefs): { [KName in keyof TRefs]: ToNewRouteRef } { + return Object.fromEntries( + Object.entries(refs).map(([name, ref]) => [ + name, + convertLegacyRouteRef(ref as LegacyRouteRef), + ]), + ) as { [KName in keyof TRefs]: ToNewRouteRef }; +} + /** * A temporary helper to convert a legacy route ref to the new system. * diff --git a/packages/core-compat-api/src/index.ts b/packages/core-compat-api/src/index.ts index 68e5d9cf19..b632bf8a57 100644 --- a/packages/core-compat-api/src/index.ts +++ b/packages/core-compat-api/src/index.ts @@ -16,4 +16,8 @@ export * from './compatWrapper'; export { convertLegacyApp } from './convertLegacyApp'; -export { convertLegacyRouteRef } from './convertLegacyRouteRef'; +export { + convertLegacyRouteRef, + convertLegacyRouteRefs, + type ToNewRouteRef, +} from './convertLegacyRouteRef'; diff --git a/plugins/catalog/src/alpha/plugin.tsx b/plugins/catalog/src/alpha/plugin.tsx index 99aacd27da..9a964c4e46 100644 --- a/plugins/catalog/src/alpha/plugin.tsx +++ b/plugins/catalog/src/alpha/plugin.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { convertLegacyRouteRef } from '@backstage/core-compat-api'; +import { convertLegacyRouteRefs } from '@backstage/core-compat-api'; import { createPlugin } from '@backstage/frontend-plugin-api'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; @@ -38,16 +38,16 @@ import searchResultItems from './searchResultItems'; /** @alpha */ export default createPlugin({ id: 'catalog', - routes: { - catalogIndex: convertLegacyRouteRef(rootRouteRef), - catalogEntity: convertLegacyRouteRef(entityRouteRef), - }, - externalRoutes: { - viewTechDoc: convertLegacyRouteRef(viewTechDocRouteRef), - createComponent: convertLegacyRouteRef(createComponentRouteRef), - createFromTemplate: convertLegacyRouteRef(createFromTemplateRouteRef), - unregisterRedirect: convertLegacyRouteRef(unregisterRedirectRouteRef), - }, + routes: convertLegacyRouteRefs({ + catalogIndex: rootRouteRef, + catalogEntity: entityRouteRef, + }), + externalRoutes: convertLegacyRouteRefs({ + viewTechDoc: viewTechDocRouteRef, + createComponent: createComponentRouteRef, + createFromTemplate: createFromTemplateRouteRef, + unregisterRedirect: unregisterRedirectRouteRef, + }), extensions: [ ...apis, ...pages, diff --git a/plugins/graphiql/src/alpha.tsx b/plugins/graphiql/src/alpha.tsx index fdd343020d..086f397d7a 100644 --- a/plugins/graphiql/src/alpha.tsx +++ b/plugins/graphiql/src/alpha.tsx @@ -37,6 +37,7 @@ import { graphiQLRouteRef } from './route-refs'; import { compatWrapper, convertLegacyRouteRef, + convertLegacyRouteRefs, } from '@backstage/core-compat-api'; /** @alpha */ @@ -128,7 +129,7 @@ export default createPlugin({ graphiqlGitlabGraphiQLEndpointExtension, graphiqlNavItem, ], - routes: { - root: convertLegacyRouteRef(graphiQLRouteRef), - }, + routes: convertLegacyRouteRefs({ + root: graphiQLRouteRef, + }), }); diff --git a/plugins/scaffolder/src/alpha.tsx b/plugins/scaffolder/src/alpha.tsx index 0d079f9c40..37e2978802 100644 --- a/plugins/scaffolder/src/alpha.tsx +++ b/plugins/scaffolder/src/alpha.tsx @@ -29,6 +29,7 @@ import CreateComponentIcon from '@material-ui/icons/AddCircleOutline'; import { compatWrapper, convertLegacyRouteRef, + convertLegacyRouteRefs, } from '@backstage/core-compat-api'; import { scmIntegrationsApiRef } from '@backstage/integration-react'; import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; @@ -85,17 +86,17 @@ const scaffolderNavItem = createNavItemExtension({ /** @alpha */ export default createPlugin({ id: 'scaffolder', - routes: { - root: convertLegacyRouteRef(rootRouteRef), - selectedTemplate: convertLegacyRouteRef(selectedTemplateRouteRef), - ongoingTask: convertLegacyRouteRef(scaffolderTaskRouteRef), - actions: convertLegacyRouteRef(actionsRouteRef), - listTasks: convertLegacyRouteRef(scaffolderListTaskRouteRef), - edit: convertLegacyRouteRef(editRouteRef), - }, - externalRoutes: { - registerComponent: convertLegacyRouteRef(registerComponentRouteRef), - viewTechDoc: convertLegacyRouteRef(viewTechDocRouteRef), - }, + routes: convertLegacyRouteRefs({ + root: rootRouteRef, + selectedTemplate: selectedTemplateRouteRef, + ongoingTask: scaffolderTaskRouteRef, + actions: actionsRouteRef, + listTasks: scaffolderListTaskRouteRef, + edit: editRouteRef, + }), + externalRoutes: convertLegacyRouteRefs({ + registerComponent: registerComponentRouteRef, + viewTechDoc: viewTechDocRouteRef, + }), extensions: [scaffolderApi, scaffolderPage, scaffolderNavItem], }); diff --git a/plugins/search/src/alpha.tsx b/plugins/search/src/alpha.tsx index a3a5023693..4f654548f5 100644 --- a/plugins/search/src/alpha.tsx +++ b/plugins/search/src/alpha.tsx @@ -70,6 +70,7 @@ import { UrlUpdater } from './components/SearchPage/SearchPage'; import { compatWrapper, convertLegacyRouteRef, + convertLegacyRouteRefs, } from '@backstage/core-compat-api'; /** @alpha */ @@ -248,7 +249,7 @@ export const searchNavItem = createNavItemExtension({ export default createPlugin({ id: 'search', extensions: [searchApi, searchPage, searchNavItem], - routes: { - root: convertLegacyRouteRef(rootRouteRef), - }, + routes: convertLegacyRouteRefs({ + root: rootRouteRef, + }), }); diff --git a/plugins/tech-radar/src/alpha.tsx b/plugins/tech-radar/src/alpha.tsx index 1fb5fa06f3..54e209fae3 100644 --- a/plugins/tech-radar/src/alpha.tsx +++ b/plugins/tech-radar/src/alpha.tsx @@ -27,6 +27,7 @@ import { SampleTechRadarApi } from './sample'; import { compatWrapper, convertLegacyRouteRef, + convertLegacyRouteRefs, } from '@backstage/core-compat-api'; import { rootRouteRef } from './plugin'; @@ -61,7 +62,7 @@ export const techRadarApi = createApiExtension({ export default createPlugin({ id: 'tech-radar', extensions: [techRadarPage, techRadarApi], - routes: { - root: convertLegacyRouteRef(rootRouteRef), - }, + routes: convertLegacyRouteRefs({ + root: rootRouteRef, + }), }); diff --git a/plugins/techdocs/src/alpha.tsx b/plugins/techdocs/src/alpha.tsx index ef564d469a..88dce3b48e 100644 --- a/plugins/techdocs/src/alpha.tsx +++ b/plugins/techdocs/src/alpha.tsx @@ -34,6 +34,7 @@ import { import { compatWrapper, convertLegacyRouteRef, + convertLegacyRouteRefs, } from '@backstage/core-compat-api'; import { techdocsApiRef, @@ -168,9 +169,9 @@ export default createPlugin({ techDocsEntityContent, techDocsSearchResultListItemExtension, ], - routes: { - root: convertLegacyRouteRef(rootRouteRef), - docRoot: convertLegacyRouteRef(rootDocsRouteRef), - entityContent: convertLegacyRouteRef(rootCatalogDocsRouteRef), - }, + routes: convertLegacyRouteRefs({ + root: rootRouteRef, + docRoot: rootDocsRouteRef, + entityContent: rootCatalogDocsRouteRef, + }), }); diff --git a/plugins/user-settings/src/alpha.tsx b/plugins/user-settings/src/alpha.tsx index 5dabd70739..f14db7233d 100644 --- a/plugins/user-settings/src/alpha.tsx +++ b/plugins/user-settings/src/alpha.tsx @@ -22,6 +22,7 @@ import { } from '@backstage/frontend-plugin-api'; import { convertLegacyRouteRef, + convertLegacyRouteRefs, compatWrapper, } from '@backstage/core-compat-api'; import SettingsIcon from '@material-ui/icons/Settings'; @@ -65,7 +66,7 @@ export const settingsNavItem = createNavItemExtension({ export default createPlugin({ id: 'user-settings', extensions: [userSettingsPage, settingsNavItem], - routes: { - root: convertLegacyRouteRef(settingsRouteRef), - }, + routes: convertLegacyRouteRefs({ + root: settingsRouteRef, + }), });