@backstage/core-compat-api 0.4.5-next.1 → 0.5.0-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @backstage/core-compat-api
2
2
 
3
+ ## 0.5.0-next.2
4
+
5
+ ### Minor Changes
6
+
7
+ - e4ddf22: **BREAKING**: The `defaultPath` override of `convertLegacyPageExtension` has been renamed to `path`, in order to align with the same update that was made to the `PageBlueprint`.
8
+
9
+ ### Patch Changes
10
+
11
+ - e4ddf22: Internal update to align with new blueprint parameter naming in the new frontend system.
12
+ - 5d31d66: Updated the usage of the `RouterBlueprint` and `AppRootWrapperBlueprint` to use the lowercase `component` parameter
13
+ - Updated dependencies
14
+ - @backstage/frontend-plugin-api@0.11.0-next.1
15
+ - @backstage/plugin-catalog-react@1.20.0-next.2
16
+ - @backstage/core-plugin-api@1.10.9
17
+ - @backstage/version-bridge@1.0.11
18
+
3
19
  ## 0.4.5-next.1
4
20
 
5
21
  ### Patch Changes
@@ -62,8 +62,8 @@ function collectEntityPageContents(entityPageElement, context) {
62
62
  name,
63
63
  factory(originalFactory, { apis }) {
64
64
  return originalFactory({
65
- defaultPath: normalizeRoutePath(pageNode.path),
66
- defaultTitle: pageNode.title,
65
+ path: normalizeRoutePath(pageNode.path),
66
+ title: pageNode.title,
67
67
  filter: mergedIf && ((entity) => mergedIf(entity, { apis })),
68
68
  loader: () => Promise.resolve(pageNode.children)
69
69
  });
@@ -1 +1 @@
1
- {"version":3,"file":"collectEntityPageContents.esm.js","sources":["../src/collectEntityPageContents.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ApiHolder,\n getComponentData,\n BackstagePlugin as LegacyBackstagePlugin,\n} from '@backstage/core-plugin-api';\nimport { ExtensionDefinition } from '@backstage/frontend-plugin-api';\nimport { JSX, ReactNode, isValidElement, Children } from 'react';\nimport {\n EntityCardBlueprint,\n EntityContentBlueprint,\n} from '@backstage/plugin-catalog-react/alpha';\nimport { normalizeRoutePath } from './normalizeRoutePath';\n\nconst ENTITY_SWITCH_KEY = 'core.backstage.entitySwitch';\nconst ENTITY_ROUTE_KEY = 'plugin.catalog.entityLayoutRoute';\n\n// Placeholder to make sure internal types here are consistent\ntype Entity = { apiVersion: string; kind: string };\n\ntype EntityFilter = (entity: Entity, ctx: { apis: ApiHolder }) => boolean;\ntype AsyncEntityFilter = (\n entity: Entity,\n context: { apis: ApiHolder },\n) => boolean | Promise<boolean>;\n\nfunction allFilters(\n ...ifs: (EntityFilter | undefined)[]\n): EntityFilter | undefined {\n const filtered = ifs.filter(Boolean) as EntityFilter[];\n if (!filtered.length) {\n return undefined;\n }\n if (filtered.length === 1) {\n return filtered[0];\n }\n return (entity, ctx) => filtered.every(ifFunc => ifFunc(entity, ctx));\n}\n\nfunction anyFilters(\n ...ifs: (EntityFilter | undefined)[]\n): EntityFilter | undefined {\n const filtered = ifs.filter(Boolean) as EntityFilter[];\n if (!filtered.length) {\n return undefined;\n }\n if (filtered.length === 1) {\n return filtered[0];\n }\n return (entity, ctx) => filtered.some(ifFunc => ifFunc(entity, ctx));\n}\n\nfunction invertFilter(ifFunc?: EntityFilter): EntityFilter {\n if (!ifFunc) {\n return () => true;\n }\n return (entity, ctx) => !ifFunc(entity, ctx);\n}\n\nexport function collectEntityPageContents(\n entityPageElement: JSX.Element,\n context: {\n discoverExtension(\n extension: ExtensionDefinition,\n plugin?: LegacyBackstagePlugin,\n ): void;\n },\n) {\n let cardCounter = 1;\n let routeCounter = 1;\n\n function traverse(element: ReactNode, parentFilter?: EntityFilter) {\n if (!isValidElement(element)) {\n return;\n }\n\n const pageNode = maybeParseEntityPageNode(element);\n if (pageNode) {\n if (pageNode.type === 'route') {\n const mergedIf = allFilters(parentFilter, pageNode.if);\n\n if (pageNode.path === '/') {\n context.discoverExtension(\n EntityCardBlueprint.makeWithOverrides({\n name: `discovered-${cardCounter++}`,\n factory(originalFactory, { apis }) {\n return originalFactory({\n type: 'content',\n filter: mergedIf && (entity => mergedIf(entity, { apis })),\n loader: () => Promise.resolve(pageNode.children),\n });\n },\n }),\n );\n } else {\n const name = `discovered-${routeCounter++}`;\n\n context.discoverExtension(\n EntityContentBlueprint.makeWithOverrides({\n name,\n factory(originalFactory, { apis }) {\n return originalFactory({\n defaultPath: normalizeRoutePath(pageNode.path),\n defaultTitle: pageNode.title,\n filter: mergedIf && (entity => mergedIf(entity, { apis })),\n loader: () => Promise.resolve(pageNode.children),\n });\n },\n }),\n getComponentData<LegacyBackstagePlugin>(\n pageNode.children,\n 'core.plugin',\n ),\n );\n }\n }\n if (pageNode.type === 'switch') {\n if (pageNode.renderMultipleMatches === 'all') {\n for (const entityCase of pageNode.cases) {\n traverse(\n entityCase.children,\n allFilters(parentFilter, entityCase.if),\n );\n }\n } else {\n let previousIf: EntityFilter = () => false;\n for (const entityCase of pageNode.cases) {\n const didNotMatchEarlier = invertFilter(previousIf);\n traverse(\n entityCase.children,\n allFilters(parentFilter, entityCase.if, didNotMatchEarlier),\n );\n previousIf = anyFilters(previousIf, entityCase.if)!;\n }\n }\n }\n return;\n }\n\n Children.forEach(\n (element.props as { children?: ReactNode })?.children,\n child => {\n traverse(child, parentFilter);\n },\n );\n }\n\n traverse(entityPageElement);\n}\n\ntype EntityRoute = {\n type: 'route';\n path: string;\n title: string;\n if?: EntityFilter;\n children: JSX.Element;\n};\n\ntype EntitySwitchCase = {\n if?: EntityFilter;\n children: ReactNode;\n};\n\ntype EntitySwitch = {\n type: 'switch';\n cases: EntitySwitchCase[];\n renderMultipleMatches: 'first' | 'all';\n};\n\nfunction wrapAsyncEntityFilter(\n asyncFilter?: AsyncEntityFilter,\n): EntityFilter | undefined {\n if (!asyncFilter) {\n return asyncFilter;\n }\n let loggedError = false;\n return (entity, ctx) => {\n const result = asyncFilter(entity, ctx);\n if (result && typeof result === 'object' && 'then' in result) {\n if (!loggedError) {\n // eslint-disable-next-line no-console\n console.error(\n `collectEntityPageContents does not support async entity filters, skipping filter ${asyncFilter}`,\n );\n loggedError = true;\n }\n return false;\n }\n return result;\n };\n}\n\nfunction maybeParseEntityPageNode(\n element: JSX.Element,\n): EntityRoute | EntitySwitch | undefined {\n if (getComponentData(element, ENTITY_ROUTE_KEY)) {\n const props = element.props as EntityRoute;\n return {\n type: 'route',\n path: props.path,\n title: props.title,\n if: props.if,\n children: props.children,\n };\n }\n\n const parentProps = element.props as {\n children?: ReactNode;\n renderMultipleMatches?: 'first' | 'all';\n };\n\n const children = Children.toArray(parentProps?.children);\n if (!children.length) {\n return undefined;\n }\n\n const cases = [];\n for (const child of children) {\n if (!getComponentData(child, ENTITY_SWITCH_KEY)) {\n return undefined;\n }\n const props = (child as { props: EntitySwitchCase }).props;\n\n cases.push({\n if: wrapAsyncEntityFilter(props.if),\n children: props.children,\n });\n }\n return {\n type: 'switch',\n cases,\n renderMultipleMatches: parentProps?.renderMultipleMatches ?? 'first',\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"collectEntityPageContents.esm.js","sources":["../src/collectEntityPageContents.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ApiHolder,\n getComponentData,\n BackstagePlugin as LegacyBackstagePlugin,\n} from '@backstage/core-plugin-api';\nimport { ExtensionDefinition } from '@backstage/frontend-plugin-api';\nimport { JSX, ReactNode, isValidElement, Children } from 'react';\nimport {\n EntityCardBlueprint,\n EntityContentBlueprint,\n} from '@backstage/plugin-catalog-react/alpha';\nimport { normalizeRoutePath } from './normalizeRoutePath';\n\nconst ENTITY_SWITCH_KEY = 'core.backstage.entitySwitch';\nconst ENTITY_ROUTE_KEY = 'plugin.catalog.entityLayoutRoute';\n\n// Placeholder to make sure internal types here are consistent\ntype Entity = { apiVersion: string; kind: string };\n\ntype EntityFilter = (entity: Entity, ctx: { apis: ApiHolder }) => boolean;\ntype AsyncEntityFilter = (\n entity: Entity,\n context: { apis: ApiHolder },\n) => boolean | Promise<boolean>;\n\nfunction allFilters(\n ...ifs: (EntityFilter | undefined)[]\n): EntityFilter | undefined {\n const filtered = ifs.filter(Boolean) as EntityFilter[];\n if (!filtered.length) {\n return undefined;\n }\n if (filtered.length === 1) {\n return filtered[0];\n }\n return (entity, ctx) => filtered.every(ifFunc => ifFunc(entity, ctx));\n}\n\nfunction anyFilters(\n ...ifs: (EntityFilter | undefined)[]\n): EntityFilter | undefined {\n const filtered = ifs.filter(Boolean) as EntityFilter[];\n if (!filtered.length) {\n return undefined;\n }\n if (filtered.length === 1) {\n return filtered[0];\n }\n return (entity, ctx) => filtered.some(ifFunc => ifFunc(entity, ctx));\n}\n\nfunction invertFilter(ifFunc?: EntityFilter): EntityFilter {\n if (!ifFunc) {\n return () => true;\n }\n return (entity, ctx) => !ifFunc(entity, ctx);\n}\n\nexport function collectEntityPageContents(\n entityPageElement: JSX.Element,\n context: {\n discoverExtension(\n extension: ExtensionDefinition,\n plugin?: LegacyBackstagePlugin,\n ): void;\n },\n) {\n let cardCounter = 1;\n let routeCounter = 1;\n\n function traverse(element: ReactNode, parentFilter?: EntityFilter) {\n if (!isValidElement(element)) {\n return;\n }\n\n const pageNode = maybeParseEntityPageNode(element);\n if (pageNode) {\n if (pageNode.type === 'route') {\n const mergedIf = allFilters(parentFilter, pageNode.if);\n\n if (pageNode.path === '/') {\n context.discoverExtension(\n EntityCardBlueprint.makeWithOverrides({\n name: `discovered-${cardCounter++}`,\n factory(originalFactory, { apis }) {\n return originalFactory({\n type: 'content',\n filter: mergedIf && (entity => mergedIf(entity, { apis })),\n loader: () => Promise.resolve(pageNode.children),\n });\n },\n }),\n );\n } else {\n const name = `discovered-${routeCounter++}`;\n\n context.discoverExtension(\n EntityContentBlueprint.makeWithOverrides({\n name,\n factory(originalFactory, { apis }) {\n return originalFactory({\n path: normalizeRoutePath(pageNode.path),\n title: pageNode.title,\n filter: mergedIf && (entity => mergedIf(entity, { apis })),\n loader: () => Promise.resolve(pageNode.children),\n });\n },\n }),\n getComponentData<LegacyBackstagePlugin>(\n pageNode.children,\n 'core.plugin',\n ),\n );\n }\n }\n if (pageNode.type === 'switch') {\n if (pageNode.renderMultipleMatches === 'all') {\n for (const entityCase of pageNode.cases) {\n traverse(\n entityCase.children,\n allFilters(parentFilter, entityCase.if),\n );\n }\n } else {\n let previousIf: EntityFilter = () => false;\n for (const entityCase of pageNode.cases) {\n const didNotMatchEarlier = invertFilter(previousIf);\n traverse(\n entityCase.children,\n allFilters(parentFilter, entityCase.if, didNotMatchEarlier),\n );\n previousIf = anyFilters(previousIf, entityCase.if)!;\n }\n }\n }\n return;\n }\n\n Children.forEach(\n (element.props as { children?: ReactNode })?.children,\n child => {\n traverse(child, parentFilter);\n },\n );\n }\n\n traverse(entityPageElement);\n}\n\ntype EntityRoute = {\n type: 'route';\n path: string;\n title: string;\n if?: EntityFilter;\n children: JSX.Element;\n};\n\ntype EntitySwitchCase = {\n if?: EntityFilter;\n children: ReactNode;\n};\n\ntype EntitySwitch = {\n type: 'switch';\n cases: EntitySwitchCase[];\n renderMultipleMatches: 'first' | 'all';\n};\n\nfunction wrapAsyncEntityFilter(\n asyncFilter?: AsyncEntityFilter,\n): EntityFilter | undefined {\n if (!asyncFilter) {\n return asyncFilter;\n }\n let loggedError = false;\n return (entity, ctx) => {\n const result = asyncFilter(entity, ctx);\n if (result && typeof result === 'object' && 'then' in result) {\n if (!loggedError) {\n // eslint-disable-next-line no-console\n console.error(\n `collectEntityPageContents does not support async entity filters, skipping filter ${asyncFilter}`,\n );\n loggedError = true;\n }\n return false;\n }\n return result;\n };\n}\n\nfunction maybeParseEntityPageNode(\n element: JSX.Element,\n): EntityRoute | EntitySwitch | undefined {\n if (getComponentData(element, ENTITY_ROUTE_KEY)) {\n const props = element.props as EntityRoute;\n return {\n type: 'route',\n path: props.path,\n title: props.title,\n if: props.if,\n children: props.children,\n };\n }\n\n const parentProps = element.props as {\n children?: ReactNode;\n renderMultipleMatches?: 'first' | 'all';\n };\n\n const children = Children.toArray(parentProps?.children);\n if (!children.length) {\n return undefined;\n }\n\n const cases = [];\n for (const child of children) {\n if (!getComponentData(child, ENTITY_SWITCH_KEY)) {\n return undefined;\n }\n const props = (child as { props: EntitySwitchCase }).props;\n\n cases.push({\n if: wrapAsyncEntityFilter(props.if),\n children: props.children,\n });\n }\n return {\n type: 'switch',\n cases,\n renderMultipleMatches: parentProps?.renderMultipleMatches ?? 'first',\n };\n}\n"],"names":[],"mappings":"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"}
@@ -126,7 +126,7 @@ function collectLegacyRoutes(flatRoutesElement, entityPage) {
126
126
  },
127
127
  factory(originalFactory, { inputs: _inputs }) {
128
128
  return originalFactory({
129
- defaultPath: normalizeRoutePath(path),
129
+ path: normalizeRoutePath(path),
130
130
  routeRef: routeRef ? convertLegacyRouteRef(routeRef) : void 0,
131
131
  loader: async () => compatWrapper(
132
132
  route.props.children ? /* @__PURE__ */ jsx(Routes, { children: /* @__PURE__ */ jsx(Route, { path: "*", element: routeElement, children: /* @__PURE__ */ jsx(Route, { path: "*", element: route.props.children }) }) }) : routeElement
@@ -187,7 +187,7 @@ function collectLegacyRoutes(flatRoutesElement, entityPage) {
187
187
  ...Array.from(plugin.getApis()).map(
188
188
  (factory) => ApiBlueprint.make({
189
189
  name: factory.api.id,
190
- params: (define) => define(factory)
190
+ params: (defineParams) => defineParams(factory)
191
191
  })
192
192
  )
193
193
  ],
@@ -1 +1 @@
1
- {"version":3,"file":"collectLegacyRoutes.esm.js","sources":["../src/collectLegacyRoutes.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AnyRouteRefParams,\n BackstagePlugin as LegacyBackstagePlugin,\n RouteRef,\n createPlugin,\n getComponentData,\n} from '@backstage/core-plugin-api';\nimport {\n FrontendPlugin,\n ExtensionDefinition,\n coreExtensionData,\n createExtension,\n createExtensionInput,\n createFrontendPlugin,\n ApiBlueprint,\n PageBlueprint,\n FrontendModule,\n createFrontendModule,\n} from '@backstage/frontend-plugin-api';\nimport { Children, ReactNode, isValidElement } from 'react';\nimport { Route, Routes } from 'react-router-dom';\nimport {\n convertLegacyRouteRef,\n convertLegacyRouteRefs,\n} from './convertLegacyRouteRef';\nimport { compatWrapper } from './compatWrapper';\nimport { collectEntityPageContents } from './collectEntityPageContents';\nimport { normalizeRoutePath } from './normalizeRoutePath';\n\n/*\n\n# Legacy interoperability\n\nUse-cases (prioritized):\n 1. Slowly migrate over an existing app to DI, piece by piece\n 2. Use a legacy plugin in a new DI app\n 3. Use DI in an existing legacy app\n\nStarting point: use-case #1\n\nPotential solutions:\n 1. Codemods (we're not considering this for now)\n 2. Legacy apps are migrated bottom-up, i.e. keep legacy root, replace pages with DI\n 3. Legacy apps are migrated top-down i.e. switch out base to DI, legacy adapter allows for usage of existing app structure\n\nChosen path: #3\n\nExisting tasks:\n - Adopters can migrate their existing app gradually (~4)\n - Example-app uses legacy base with DI adapters\n - Create an API that lets you inject DI into existing apps - working assumption is that this is enough\n - Adopters can use legacy plugins in DI through adapters (~8)\n - App-next uses DI base with legacy adapters\n - Create a legacy adapter that is able to take an existing extension tree\n\n*/\n\n// Creates a shim extension whose purpose is to build up the tree (anchored at\n// the root page) of paths/routeRefs so that the app can bind them properly.\nfunction makeRoutingShimExtension(options: {\n name: string;\n parentExtensionId: string;\n routePath?: string;\n routeRef?: RouteRef;\n}) {\n const { name, parentExtensionId, routePath, routeRef } = options;\n return createExtension({\n kind: 'routing-shim',\n name,\n attachTo: { id: parentExtensionId, input: 'childRoutingShims' },\n inputs: {\n childRoutingShims: createExtensionInput([\n coreExtensionData.routePath.optional(),\n coreExtensionData.routeRef.optional(),\n ]),\n },\n output: [\n coreExtensionData.routePath.optional(),\n coreExtensionData.routeRef.optional(),\n ],\n *factory() {\n if (routePath !== undefined) {\n yield coreExtensionData.routePath(routePath);\n }\n\n if (routeRef) {\n yield coreExtensionData.routeRef(convertLegacyRouteRef(routeRef));\n }\n },\n });\n}\n\nexport function visitRouteChildren(options: {\n children: ReactNode;\n parentExtensionId: string;\n context: {\n pluginId: string;\n extensions: ExtensionDefinition[];\n getUniqueName: () => string;\n discoverPlugin: (plugin: LegacyBackstagePlugin) => void;\n };\n}): void {\n const { children, parentExtensionId, context } = options;\n const { pluginId, extensions, getUniqueName, discoverPlugin } = context;\n\n Children.forEach(children, node => {\n if (!isValidElement(node)) {\n return;\n }\n\n const plugin = getComponentData<LegacyBackstagePlugin>(node, 'core.plugin');\n const routeRef = getComponentData<RouteRef<AnyRouteRefParams>>(\n node,\n 'core.mountPoint',\n );\n const routePath: string | undefined = node.props?.path;\n\n if (plugin) {\n // We just mark the plugin as discovered, but don't change the context\n discoverPlugin(plugin);\n }\n\n let nextParentExtensionId = parentExtensionId;\n if (routeRef || routePath) {\n const nextParentExtensionName = getUniqueName();\n nextParentExtensionId = `routing-shim:${pluginId}/${nextParentExtensionName}`;\n extensions.push(\n makeRoutingShimExtension({\n name: nextParentExtensionName,\n parentExtensionId,\n routePath,\n routeRef,\n }),\n );\n }\n\n visitRouteChildren({\n children: node.props.children,\n parentExtensionId: nextParentExtensionId,\n context,\n });\n });\n}\n\n/** @internal */\nexport function collectLegacyRoutes(\n flatRoutesElement: JSX.Element,\n entityPage?: JSX.Element,\n): (FrontendPlugin | FrontendModule)[] {\n const output = new Array<FrontendPlugin | FrontendModule>();\n\n const pluginExtensions = new Map<\n LegacyBackstagePlugin,\n ExtensionDefinition[]\n >();\n\n const getUniqueName = (() => {\n let currentIndex = 1;\n return () => String(currentIndex++);\n })();\n\n // Placeholder plugin for any routes that don't belong to a plugin\n const orphanRoutesPlugin = createPlugin({ id: 'converted-orphan-routes' });\n\n const getPluginExtensions = (plugin: LegacyBackstagePlugin) => {\n let extensions = pluginExtensions.get(plugin);\n if (!extensions) {\n extensions = [];\n pluginExtensions.set(plugin, extensions);\n }\n return extensions;\n };\n\n Children.forEach(flatRoutesElement.props.children, (route: ReactNode) => {\n if (route === null) {\n return;\n }\n // TODO(freben): Handle feature flag and permissions framework wrapper elements\n if (!isValidElement(route)) {\n throw new Error(\n `Invalid element inside FlatRoutes, expected Route but found element of type ${typeof route}.`,\n );\n }\n if (route.type !== Route) {\n throw new Error(\n `Invalid element inside FlatRoutes, expected Route but found ${route.type}.`,\n );\n }\n const routeElement = route.props.element;\n const path: string | undefined = route.props.path;\n const plugin =\n getComponentData<LegacyBackstagePlugin>(routeElement, 'core.plugin') ??\n orphanRoutesPlugin;\n const routeRef = getComponentData<RouteRef>(\n routeElement,\n 'core.mountPoint',\n );\n if (path === undefined) {\n throw new Error(\n `Route element inside FlatRoutes had no path prop value given`,\n );\n }\n\n const extensions = getPluginExtensions(plugin);\n const pageExtensionName = extensions.length ? getUniqueName() : undefined;\n const pageExtensionId = `page:${plugin.getId()}${\n pageExtensionName ? `/${pageExtensionName}` : pageExtensionName\n }`;\n\n extensions.push(\n PageBlueprint.makeWithOverrides({\n name: pageExtensionName,\n inputs: {\n childRoutingShims: createExtensionInput([\n coreExtensionData.routePath.optional(),\n coreExtensionData.routeRef.optional(),\n ]),\n },\n factory(originalFactory, { inputs: _inputs }) {\n // todo(blam): why do we not use the inputs here?\n return originalFactory({\n defaultPath: normalizeRoutePath(path),\n routeRef: routeRef ? convertLegacyRouteRef(routeRef) : undefined,\n loader: async () =>\n compatWrapper(\n route.props.children ? (\n <Routes>\n <Route path=\"*\" element={routeElement}>\n <Route path=\"*\" element={route.props.children} />\n </Route>\n </Routes>\n ) : (\n routeElement\n ),\n ),\n });\n },\n }),\n );\n\n visitRouteChildren({\n children: route.props.children,\n parentExtensionId: pageExtensionId,\n context: {\n pluginId: plugin.getId(),\n extensions,\n getUniqueName,\n discoverPlugin: getPluginExtensions,\n },\n });\n });\n\n if (entityPage) {\n collectEntityPageContents(entityPage, {\n discoverExtension(extension, plugin) {\n if (!plugin || plugin.getId() === 'catalog') {\n getPluginExtensions(orphanRoutesPlugin).push(extension);\n } else {\n getPluginExtensions(plugin).push(extension);\n }\n },\n });\n\n const extensions = new Array<ExtensionDefinition>();\n visitRouteChildren({\n children: entityPage,\n parentExtensionId: `page:catalog/entity`,\n context: {\n pluginId: 'catalog',\n extensions,\n getUniqueName,\n discoverPlugin(plugin) {\n if (plugin.getId() !== 'catalog') {\n getPluginExtensions(plugin);\n }\n },\n },\n });\n\n output.push(\n createFrontendModule({\n pluginId: 'catalog',\n extensions,\n }),\n );\n }\n\n for (const [plugin, extensions] of pluginExtensions) {\n output.push(\n createFrontendPlugin({\n pluginId: plugin.getId(),\n extensions: [\n ...extensions,\n ...Array.from(plugin.getApis()).map(factory =>\n ApiBlueprint.make({\n name: factory.api.id,\n params: define => define(factory),\n }),\n ),\n ],\n routes: convertLegacyRouteRefs(plugin.routes ?? {}),\n externalRoutes: convertLegacyRouteRefs(plugin.externalRoutes ?? {}),\n }),\n );\n }\n\n return output;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"collectLegacyRoutes.esm.js","sources":["../src/collectLegacyRoutes.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AnyRouteRefParams,\n BackstagePlugin as LegacyBackstagePlugin,\n RouteRef,\n createPlugin,\n getComponentData,\n} from '@backstage/core-plugin-api';\nimport {\n FrontendPlugin,\n ExtensionDefinition,\n coreExtensionData,\n createExtension,\n createExtensionInput,\n createFrontendPlugin,\n ApiBlueprint,\n PageBlueprint,\n FrontendModule,\n createFrontendModule,\n} from '@backstage/frontend-plugin-api';\nimport { Children, ReactNode, isValidElement } from 'react';\nimport { Route, Routes } from 'react-router-dom';\nimport {\n convertLegacyRouteRef,\n convertLegacyRouteRefs,\n} from './convertLegacyRouteRef';\nimport { compatWrapper } from './compatWrapper';\nimport { collectEntityPageContents } from './collectEntityPageContents';\nimport { normalizeRoutePath } from './normalizeRoutePath';\n\n/*\n\n# Legacy interoperability\n\nUse-cases (prioritized):\n 1. Slowly migrate over an existing app to DI, piece by piece\n 2. Use a legacy plugin in a new DI app\n 3. Use DI in an existing legacy app\n\nStarting point: use-case #1\n\nPotential solutions:\n 1. Codemods (we're not considering this for now)\n 2. Legacy apps are migrated bottom-up, i.e. keep legacy root, replace pages with DI\n 3. Legacy apps are migrated top-down i.e. switch out base to DI, legacy adapter allows for usage of existing app structure\n\nChosen path: #3\n\nExisting tasks:\n - Adopters can migrate their existing app gradually (~4)\n - Example-app uses legacy base with DI adapters\n - Create an API that lets you inject DI into existing apps - working assumption is that this is enough\n - Adopters can use legacy plugins in DI through adapters (~8)\n - App-next uses DI base with legacy adapters\n - Create a legacy adapter that is able to take an existing extension tree\n\n*/\n\n// Creates a shim extension whose purpose is to build up the tree (anchored at\n// the root page) of paths/routeRefs so that the app can bind them properly.\nfunction makeRoutingShimExtension(options: {\n name: string;\n parentExtensionId: string;\n routePath?: string;\n routeRef?: RouteRef;\n}) {\n const { name, parentExtensionId, routePath, routeRef } = options;\n return createExtension({\n kind: 'routing-shim',\n name,\n attachTo: { id: parentExtensionId, input: 'childRoutingShims' },\n inputs: {\n childRoutingShims: createExtensionInput([\n coreExtensionData.routePath.optional(),\n coreExtensionData.routeRef.optional(),\n ]),\n },\n output: [\n coreExtensionData.routePath.optional(),\n coreExtensionData.routeRef.optional(),\n ],\n *factory() {\n if (routePath !== undefined) {\n yield coreExtensionData.routePath(routePath);\n }\n\n if (routeRef) {\n yield coreExtensionData.routeRef(convertLegacyRouteRef(routeRef));\n }\n },\n });\n}\n\nexport function visitRouteChildren(options: {\n children: ReactNode;\n parentExtensionId: string;\n context: {\n pluginId: string;\n extensions: ExtensionDefinition[];\n getUniqueName: () => string;\n discoverPlugin: (plugin: LegacyBackstagePlugin) => void;\n };\n}): void {\n const { children, parentExtensionId, context } = options;\n const { pluginId, extensions, getUniqueName, discoverPlugin } = context;\n\n Children.forEach(children, node => {\n if (!isValidElement(node)) {\n return;\n }\n\n const plugin = getComponentData<LegacyBackstagePlugin>(node, 'core.plugin');\n const routeRef = getComponentData<RouteRef<AnyRouteRefParams>>(\n node,\n 'core.mountPoint',\n );\n const routePath: string | undefined = node.props?.path;\n\n if (plugin) {\n // We just mark the plugin as discovered, but don't change the context\n discoverPlugin(plugin);\n }\n\n let nextParentExtensionId = parentExtensionId;\n if (routeRef || routePath) {\n const nextParentExtensionName = getUniqueName();\n nextParentExtensionId = `routing-shim:${pluginId}/${nextParentExtensionName}`;\n extensions.push(\n makeRoutingShimExtension({\n name: nextParentExtensionName,\n parentExtensionId,\n routePath,\n routeRef,\n }),\n );\n }\n\n visitRouteChildren({\n children: node.props.children,\n parentExtensionId: nextParentExtensionId,\n context,\n });\n });\n}\n\n/** @internal */\nexport function collectLegacyRoutes(\n flatRoutesElement: JSX.Element,\n entityPage?: JSX.Element,\n): (FrontendPlugin | FrontendModule)[] {\n const output = new Array<FrontendPlugin | FrontendModule>();\n\n const pluginExtensions = new Map<\n LegacyBackstagePlugin,\n ExtensionDefinition[]\n >();\n\n const getUniqueName = (() => {\n let currentIndex = 1;\n return () => String(currentIndex++);\n })();\n\n // Placeholder plugin for any routes that don't belong to a plugin\n const orphanRoutesPlugin = createPlugin({ id: 'converted-orphan-routes' });\n\n const getPluginExtensions = (plugin: LegacyBackstagePlugin) => {\n let extensions = pluginExtensions.get(plugin);\n if (!extensions) {\n extensions = [];\n pluginExtensions.set(plugin, extensions);\n }\n return extensions;\n };\n\n Children.forEach(flatRoutesElement.props.children, (route: ReactNode) => {\n if (route === null) {\n return;\n }\n // TODO(freben): Handle feature flag and permissions framework wrapper elements\n if (!isValidElement(route)) {\n throw new Error(\n `Invalid element inside FlatRoutes, expected Route but found element of type ${typeof route}.`,\n );\n }\n if (route.type !== Route) {\n throw new Error(\n `Invalid element inside FlatRoutes, expected Route but found ${route.type}.`,\n );\n }\n const routeElement = route.props.element;\n const path: string | undefined = route.props.path;\n const plugin =\n getComponentData<LegacyBackstagePlugin>(routeElement, 'core.plugin') ??\n orphanRoutesPlugin;\n const routeRef = getComponentData<RouteRef>(\n routeElement,\n 'core.mountPoint',\n );\n if (path === undefined) {\n throw new Error(\n `Route element inside FlatRoutes had no path prop value given`,\n );\n }\n\n const extensions = getPluginExtensions(plugin);\n const pageExtensionName = extensions.length ? getUniqueName() : undefined;\n const pageExtensionId = `page:${plugin.getId()}${\n pageExtensionName ? `/${pageExtensionName}` : pageExtensionName\n }`;\n\n extensions.push(\n PageBlueprint.makeWithOverrides({\n name: pageExtensionName,\n inputs: {\n childRoutingShims: createExtensionInput([\n coreExtensionData.routePath.optional(),\n coreExtensionData.routeRef.optional(),\n ]),\n },\n factory(originalFactory, { inputs: _inputs }) {\n // todo(blam): why do we not use the inputs here?\n return originalFactory({\n path: normalizeRoutePath(path),\n routeRef: routeRef ? convertLegacyRouteRef(routeRef) : undefined,\n loader: async () =>\n compatWrapper(\n route.props.children ? (\n <Routes>\n <Route path=\"*\" element={routeElement}>\n <Route path=\"*\" element={route.props.children} />\n </Route>\n </Routes>\n ) : (\n routeElement\n ),\n ),\n });\n },\n }),\n );\n\n visitRouteChildren({\n children: route.props.children,\n parentExtensionId: pageExtensionId,\n context: {\n pluginId: plugin.getId(),\n extensions,\n getUniqueName,\n discoverPlugin: getPluginExtensions,\n },\n });\n });\n\n if (entityPage) {\n collectEntityPageContents(entityPage, {\n discoverExtension(extension, plugin) {\n if (!plugin || plugin.getId() === 'catalog') {\n getPluginExtensions(orphanRoutesPlugin).push(extension);\n } else {\n getPluginExtensions(plugin).push(extension);\n }\n },\n });\n\n const extensions = new Array<ExtensionDefinition>();\n visitRouteChildren({\n children: entityPage,\n parentExtensionId: `page:catalog/entity`,\n context: {\n pluginId: 'catalog',\n extensions,\n getUniqueName,\n discoverPlugin(plugin) {\n if (plugin.getId() !== 'catalog') {\n getPluginExtensions(plugin);\n }\n },\n },\n });\n\n output.push(\n createFrontendModule({\n pluginId: 'catalog',\n extensions,\n }),\n );\n }\n\n for (const [plugin, extensions] of pluginExtensions) {\n output.push(\n createFrontendPlugin({\n pluginId: plugin.getId(),\n extensions: [\n ...extensions,\n ...Array.from(plugin.getApis()).map(factory =>\n ApiBlueprint.make({\n name: factory.api.id,\n params: defineParams => defineParams(factory),\n }),\n ),\n ],\n routes: convertLegacyRouteRefs(plugin.routes ?? {}),\n externalRoutes: convertLegacyRouteRefs(plugin.externalRoutes ?? {}),\n }),\n );\n }\n\n return output;\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ForwardsCompatProvider.esm.js","sources":["../../src/compatWrapper/ForwardsCompatProvider.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ApiHolder,\n ApiRef,\n AppContext,\n useApp,\n} from '@backstage/core-plugin-api';\nimport {\n AnyRouteRefParams,\n ComponentRef,\n ComponentsApi,\n CoreErrorBoundaryFallbackProps,\n CoreNotFoundErrorPageProps,\n CoreProgressProps,\n ExternalRouteRef,\n IconComponent,\n IconsApi,\n RouteFunc,\n RouteRef,\n RouteResolutionApi,\n RouteResolutionApiResolveOptions,\n SubRouteRef,\n componentsApiRef,\n coreComponentRefs,\n iconsApiRef,\n routeResolutionApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { ComponentType, useMemo } from 'react';\nimport { ReactNode } from 'react';\nimport { toLegacyPlugin } from './BackwardsCompatProvider';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { ApiProvider } from '../../../core-app-api/src/apis/system/ApiProvider';\nimport { useVersionedContext } from '@backstage/version-bridge';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { type RouteResolver } from '../../../core-plugin-api/src/routing/useRouteRef';\nimport { convertLegacyRouteRef } from '../convertLegacyRouteRef';\n\nclass CompatComponentsApi implements ComponentsApi {\n readonly #Progress: ComponentType<CoreProgressProps>;\n readonly #NotFoundErrorPage: ComponentType<CoreNotFoundErrorPageProps>;\n readonly #ErrorBoundaryFallback: ComponentType<CoreErrorBoundaryFallbackProps>;\n\n constructor(app: AppContext) {\n const components = app.getComponents();\n const ErrorBoundaryFallback = (props: CoreErrorBoundaryFallbackProps) => (\n <components.ErrorBoundaryFallback\n {...props}\n plugin={props.plugin && toLegacyPlugin(props.plugin)}\n />\n );\n this.#Progress = components.Progress;\n this.#NotFoundErrorPage = components.NotFoundErrorPage;\n this.#ErrorBoundaryFallback = ErrorBoundaryFallback;\n }\n\n getComponent<T extends {}>(ref: ComponentRef<T>): ComponentType<T> {\n switch (ref.id) {\n case coreComponentRefs.progress.id:\n return this.#Progress as ComponentType<any>;\n case coreComponentRefs.notFoundErrorPage.id:\n return this.#NotFoundErrorPage as ComponentType<any>;\n case coreComponentRefs.errorBoundaryFallback.id:\n return this.#ErrorBoundaryFallback as ComponentType<any>;\n default:\n throw new Error(\n `No backwards compatible component is available for ref '${ref.id}'`,\n );\n }\n }\n}\n\nclass CompatIconsApi implements IconsApi {\n readonly #app: AppContext;\n\n constructor(app: AppContext) {\n this.#app = app;\n }\n\n getIcon(key: string): IconComponent | undefined {\n return this.#app.getSystemIcon(key);\n }\n\n listIconKeys(): string[] {\n return Object.keys(this.#app.getSystemIcons());\n }\n}\n\nclass CompatRouteResolutionApi implements RouteResolutionApi {\n readonly #routeResolver: RouteResolver;\n\n constructor(routeResolver: RouteResolver) {\n this.#routeResolver = routeResolver;\n }\n\n resolve<TParams extends AnyRouteRefParams>(\n anyRouteRef:\n | RouteRef<TParams>\n | SubRouteRef<TParams>\n | ExternalRouteRef<TParams>,\n options?: RouteResolutionApiResolveOptions | undefined,\n ): RouteFunc<TParams> | undefined {\n const legacyRef = convertLegacyRouteRef(anyRouteRef as RouteRef<TParams>);\n return this.#routeResolver.resolve(legacyRef, options?.sourcePath ?? '/');\n }\n}\n\nclass ForwardsCompatApis implements ApiHolder {\n readonly #componentsApi: ComponentsApi;\n readonly #iconsApi: IconsApi;\n readonly #routeResolutionApi: RouteResolutionApi;\n\n constructor(app: AppContext, routeResolver: RouteResolver) {\n this.#componentsApi = new CompatComponentsApi(app);\n this.#iconsApi = new CompatIconsApi(app);\n this.#routeResolutionApi = new CompatRouteResolutionApi(routeResolver);\n }\n\n get<T>(ref: ApiRef<any>): T | undefined {\n if (ref.id === componentsApiRef.id) {\n return this.#componentsApi as T;\n } else if (ref.id === iconsApiRef.id) {\n return this.#iconsApi as T;\n } else if (ref.id === routeResolutionApiRef.id) {\n return this.#routeResolutionApi as T;\n }\n return undefined;\n }\n}\n\nfunction NewAppApisProvider(props: { children: ReactNode }) {\n const app = useApp();\n const versionedRouteResolverContext = useVersionedContext<{\n 1: RouteResolver;\n }>('routing-context');\n if (!versionedRouteResolverContext) {\n throw new Error('Routing context is not available');\n }\n const routeResolver = versionedRouteResolverContext.atVersion(1);\n if (!routeResolver) {\n throw new Error('RoutingContext v1 not available');\n }\n\n const appFallbackApis = useMemo(\n () => new ForwardsCompatApis(app, routeResolver),\n [app, routeResolver],\n );\n\n return <ApiProvider apis={appFallbackApis}>{props.children}</ApiProvider>;\n}\n\nexport function ForwardsCompatProvider(props: { children: ReactNode }) {\n return <NewAppApisProvider>{props.children}</NewAppApisProvider>;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ForwardsCompatProvider.esm.js","sources":["../../src/compatWrapper/ForwardsCompatProvider.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ApiHolder,\n ApiRef,\n AppContext,\n useApp,\n} from '@backstage/core-plugin-api';\nimport {\n AnyRouteRefParams,\n ComponentRef,\n ComponentsApi,\n CoreErrorBoundaryFallbackProps,\n CoreNotFoundErrorPageProps,\n CoreProgressProps,\n ExternalRouteRef,\n IconComponent,\n IconsApi,\n RouteFunc,\n RouteRef,\n RouteResolutionApi,\n SubRouteRef,\n componentsApiRef,\n coreComponentRefs,\n iconsApiRef,\n routeResolutionApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { ComponentType, useMemo } from 'react';\nimport { ReactNode } from 'react';\nimport { toLegacyPlugin } from './BackwardsCompatProvider';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { ApiProvider } from '../../../core-app-api/src/apis/system/ApiProvider';\nimport { useVersionedContext } from '@backstage/version-bridge';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { type RouteResolver } from '../../../core-plugin-api/src/routing/useRouteRef';\nimport { convertLegacyRouteRef } from '../convertLegacyRouteRef';\n\nclass CompatComponentsApi implements ComponentsApi {\n readonly #Progress: ComponentType<CoreProgressProps>;\n readonly #NotFoundErrorPage: ComponentType<CoreNotFoundErrorPageProps>;\n readonly #ErrorBoundaryFallback: ComponentType<CoreErrorBoundaryFallbackProps>;\n\n constructor(app: AppContext) {\n const components = app.getComponents();\n const ErrorBoundaryFallback = (props: CoreErrorBoundaryFallbackProps) => (\n <components.ErrorBoundaryFallback\n {...props}\n plugin={props.plugin && toLegacyPlugin(props.plugin)}\n />\n );\n this.#Progress = components.Progress;\n this.#NotFoundErrorPage = components.NotFoundErrorPage;\n this.#ErrorBoundaryFallback = ErrorBoundaryFallback;\n }\n\n getComponent<T extends {}>(ref: ComponentRef<T>): ComponentType<T> {\n switch (ref.id) {\n case coreComponentRefs.progress.id:\n return this.#Progress as ComponentType<any>;\n case coreComponentRefs.notFoundErrorPage.id:\n return this.#NotFoundErrorPage as ComponentType<any>;\n case coreComponentRefs.errorBoundaryFallback.id:\n return this.#ErrorBoundaryFallback as ComponentType<any>;\n default:\n throw new Error(\n `No backwards compatible component is available for ref '${ref.id}'`,\n );\n }\n }\n}\n\nclass CompatIconsApi implements IconsApi {\n readonly #app: AppContext;\n\n constructor(app: AppContext) {\n this.#app = app;\n }\n\n getIcon(key: string): IconComponent | undefined {\n return this.#app.getSystemIcon(key);\n }\n\n listIconKeys(): string[] {\n return Object.keys(this.#app.getSystemIcons());\n }\n}\n\nclass CompatRouteResolutionApi implements RouteResolutionApi {\n readonly #routeResolver: RouteResolver;\n\n constructor(routeResolver: RouteResolver) {\n this.#routeResolver = routeResolver;\n }\n\n resolve<TParams extends AnyRouteRefParams>(\n anyRouteRef:\n | RouteRef<TParams>\n | SubRouteRef<TParams>\n | ExternalRouteRef<TParams>,\n options?: { sourcePath?: string },\n ): RouteFunc<TParams> | undefined {\n const legacyRef = convertLegacyRouteRef(anyRouteRef as RouteRef<TParams>);\n return this.#routeResolver.resolve(legacyRef, options?.sourcePath ?? '/');\n }\n}\n\nclass ForwardsCompatApis implements ApiHolder {\n readonly #componentsApi: ComponentsApi;\n readonly #iconsApi: IconsApi;\n readonly #routeResolutionApi: RouteResolutionApi;\n\n constructor(app: AppContext, routeResolver: RouteResolver) {\n this.#componentsApi = new CompatComponentsApi(app);\n this.#iconsApi = new CompatIconsApi(app);\n this.#routeResolutionApi = new CompatRouteResolutionApi(routeResolver);\n }\n\n get<T>(ref: ApiRef<any>): T | undefined {\n if (ref.id === componentsApiRef.id) {\n return this.#componentsApi as T;\n } else if (ref.id === iconsApiRef.id) {\n return this.#iconsApi as T;\n } else if (ref.id === routeResolutionApiRef.id) {\n return this.#routeResolutionApi as T;\n }\n return undefined;\n }\n}\n\nfunction NewAppApisProvider(props: { children: ReactNode }) {\n const app = useApp();\n const versionedRouteResolverContext = useVersionedContext<{\n 1: RouteResolver;\n }>('routing-context');\n if (!versionedRouteResolverContext) {\n throw new Error('Routing context is not available');\n }\n const routeResolver = versionedRouteResolverContext.atVersion(1);\n if (!routeResolver) {\n throw new Error('RoutingContext v1 not available');\n }\n\n const appFallbackApis = useMemo(\n () => new ForwardsCompatApis(app, routeResolver),\n [app, routeResolver],\n );\n\n return <ApiProvider apis={appFallbackApis}>{props.children}</ApiProvider>;\n}\n\nexport function ForwardsCompatProvider(props: { children: ReactNode }) {\n return <NewAppApisProvider>{props.children}</NewAppApisProvider>;\n}\n"],"names":[],"mappings":"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"}
@@ -18,7 +18,7 @@ function convertLegacyAppOptions(options = {}) {
18
18
  const extensions = deduplicatedApis.map(
19
19
  (factory) => ApiBlueprint.make({
20
20
  name: factory.api.id,
21
- params: (define) => define(factory)
21
+ params: (defineParams) => defineParams(factory)
22
22
  })
23
23
  );
24
24
  if (icons) {
@@ -76,7 +76,7 @@ function convertLegacyAppOptions(options = {}) {
76
76
  if (Router) {
77
77
  extensions.push(
78
78
  RouterBlueprint.make({
79
- params: { Component: componentCompatWrapper(Router) }
79
+ params: { component: componentCompatWrapper(Router) }
80
80
  })
81
81
  );
82
82
  }
@@ -1 +1 @@
1
- {"version":3,"file":"convertLegacyAppOptions.esm.js","sources":["../src/convertLegacyAppOptions.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ComponentType } from 'react';\nimport {\n ApiBlueprint,\n coreComponentRefs,\n CoreErrorBoundaryFallbackProps,\n createComponentExtension,\n createExtension,\n createFrontendModule,\n ExtensionDefinition,\n FrontendModule,\n IconBundleBlueprint,\n RouterBlueprint,\n SignInPageBlueprint,\n ThemeBlueprint,\n} from '@backstage/frontend-plugin-api';\nimport {\n AnyApiFactory,\n AppComponents,\n AppTheme,\n BackstagePlugin,\n FeatureFlag,\n IconComponent,\n} from '@backstage/core-plugin-api';\nimport { toLegacyPlugin } from './compatWrapper/BackwardsCompatProvider';\nimport { compatWrapper } from './compatWrapper';\n\nfunction componentCompatWrapper<TProps extends {}>(\n Component: ComponentType<TProps>,\n) {\n return (props: TProps) => compatWrapper(<Component {...props} />);\n}\n\n/**\n * @public\n */\nexport function convertLegacyAppOptions(\n options: {\n apis?: Iterable<AnyApiFactory>;\n\n icons?: { [key in string]: IconComponent };\n\n plugins?: Array<BackstagePlugin>;\n\n components?: Partial<AppComponents>;\n\n themes?: AppTheme[];\n\n featureFlags?: (FeatureFlag & Omit<FeatureFlag, 'pluginId'>)[];\n } = {},\n): FrontendModule {\n const { apis, icons, plugins, components, themes, featureFlags } = options;\n\n const allApis = [\n ...(plugins?.flatMap(plugin => [...plugin.getApis()]) ?? []),\n ...(apis ?? []),\n ];\n const deduplicatedApis = Array.from(\n new Map(allApis.map(api => [api.api.id, api])).values(),\n );\n const extensions: ExtensionDefinition[] = deduplicatedApis.map(factory =>\n ApiBlueprint.make({\n name: factory.api.id,\n params: define => define(factory),\n }),\n );\n\n if (icons) {\n extensions.push(\n IconBundleBlueprint.make({\n name: 'app-options',\n params: { icons },\n }),\n );\n }\n\n if (themes) {\n // IF any themes are provided we need to disable the default ones, unless they are overridden\n for (const id of ['light', 'dark']) {\n if (!themes.some(theme => theme.id === id)) {\n extensions.push(\n createExtension({\n kind: 'theme',\n name: id,\n attachTo: { id: 'api:app/app-theme', input: 'themes' },\n disabled: true,\n output: [],\n factory: () => [],\n }),\n );\n }\n }\n extensions.push(\n ...themes.map(theme =>\n ThemeBlueprint.make({\n name: theme.id,\n params: { theme },\n }),\n ),\n );\n }\n\n if (components) {\n const {\n BootErrorPage,\n ErrorBoundaryFallback,\n NotFoundErrorPage,\n Progress,\n Router,\n SignInPage,\n ThemeProvider,\n } = components;\n\n if (BootErrorPage) {\n throw new Error(\n 'components.BootErrorPage is not supported by convertLegacyAppOptions',\n );\n }\n if (ThemeProvider) {\n throw new Error(\n 'components.ThemeProvider is not supported by convertLegacyAppOptions',\n );\n }\n if (Router) {\n extensions.push(\n RouterBlueprint.make({\n params: { Component: componentCompatWrapper(Router) },\n }),\n );\n }\n if (SignInPage) {\n extensions.push(\n SignInPageBlueprint.make({\n params: {\n loader: () => Promise.resolve(componentCompatWrapper(SignInPage)),\n },\n }),\n );\n }\n if (Progress) {\n extensions.push(\n createComponentExtension({\n ref: coreComponentRefs.progress,\n loader: { sync: () => componentCompatWrapper(Progress) },\n }),\n );\n }\n if (NotFoundErrorPage) {\n extensions.push(\n createComponentExtension({\n ref: coreComponentRefs.notFoundErrorPage,\n loader: { sync: () => componentCompatWrapper(NotFoundErrorPage) },\n }),\n );\n }\n if (ErrorBoundaryFallback) {\n const WrappedErrorBoundaryFallback = (\n props: CoreErrorBoundaryFallbackProps,\n ) =>\n compatWrapper(\n <ErrorBoundaryFallback\n {...props}\n plugin={props.plugin && toLegacyPlugin(props.plugin)}\n />,\n );\n extensions.push(\n createComponentExtension({\n ref: coreComponentRefs.errorBoundaryFallback,\n loader: {\n sync: () => componentCompatWrapper(WrappedErrorBoundaryFallback),\n },\n }),\n );\n }\n }\n\n return createFrontendModule({\n pluginId: 'app',\n extensions,\n featureFlags,\n });\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"convertLegacyAppOptions.esm.js","sources":["../src/convertLegacyAppOptions.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ComponentType } from 'react';\nimport {\n ApiBlueprint,\n coreComponentRefs,\n CoreErrorBoundaryFallbackProps,\n createComponentExtension,\n createExtension,\n createFrontendModule,\n ExtensionDefinition,\n FrontendModule,\n IconBundleBlueprint,\n RouterBlueprint,\n SignInPageBlueprint,\n ThemeBlueprint,\n} from '@backstage/frontend-plugin-api';\nimport {\n AnyApiFactory,\n AppComponents,\n AppTheme,\n BackstagePlugin,\n FeatureFlag,\n IconComponent,\n} from '@backstage/core-plugin-api';\nimport { toLegacyPlugin } from './compatWrapper/BackwardsCompatProvider';\nimport { compatWrapper } from './compatWrapper';\n\nfunction componentCompatWrapper<TProps extends {}>(\n Component: ComponentType<TProps>,\n) {\n return (props: TProps) => compatWrapper(<Component {...props} />);\n}\n\n/**\n * @public\n */\nexport function convertLegacyAppOptions(\n options: {\n apis?: Iterable<AnyApiFactory>;\n\n icons?: { [key in string]: IconComponent };\n\n plugins?: Array<BackstagePlugin>;\n\n components?: Partial<AppComponents>;\n\n themes?: AppTheme[];\n\n featureFlags?: (FeatureFlag & Omit<FeatureFlag, 'pluginId'>)[];\n } = {},\n): FrontendModule {\n const { apis, icons, plugins, components, themes, featureFlags } = options;\n\n const allApis = [\n ...(plugins?.flatMap(plugin => [...plugin.getApis()]) ?? []),\n ...(apis ?? []),\n ];\n const deduplicatedApis = Array.from(\n new Map(allApis.map(api => [api.api.id, api])).values(),\n );\n const extensions: ExtensionDefinition[] = deduplicatedApis.map(factory =>\n ApiBlueprint.make({\n name: factory.api.id,\n params: defineParams => defineParams(factory),\n }),\n );\n\n if (icons) {\n extensions.push(\n IconBundleBlueprint.make({\n name: 'app-options',\n params: { icons },\n }),\n );\n }\n\n if (themes) {\n // IF any themes are provided we need to disable the default ones, unless they are overridden\n for (const id of ['light', 'dark']) {\n if (!themes.some(theme => theme.id === id)) {\n extensions.push(\n createExtension({\n kind: 'theme',\n name: id,\n attachTo: { id: 'api:app/app-theme', input: 'themes' },\n disabled: true,\n output: [],\n factory: () => [],\n }),\n );\n }\n }\n extensions.push(\n ...themes.map(theme =>\n ThemeBlueprint.make({\n name: theme.id,\n params: { theme },\n }),\n ),\n );\n }\n\n if (components) {\n const {\n BootErrorPage,\n ErrorBoundaryFallback,\n NotFoundErrorPage,\n Progress,\n Router,\n SignInPage,\n ThemeProvider,\n } = components;\n\n if (BootErrorPage) {\n throw new Error(\n 'components.BootErrorPage is not supported by convertLegacyAppOptions',\n );\n }\n if (ThemeProvider) {\n throw new Error(\n 'components.ThemeProvider is not supported by convertLegacyAppOptions',\n );\n }\n if (Router) {\n extensions.push(\n RouterBlueprint.make({\n params: { component: componentCompatWrapper(Router) },\n }),\n );\n }\n if (SignInPage) {\n extensions.push(\n SignInPageBlueprint.make({\n params: {\n loader: () => Promise.resolve(componentCompatWrapper(SignInPage)),\n },\n }),\n );\n }\n if (Progress) {\n extensions.push(\n createComponentExtension({\n ref: coreComponentRefs.progress,\n loader: { sync: () => componentCompatWrapper(Progress) },\n }),\n );\n }\n if (NotFoundErrorPage) {\n extensions.push(\n createComponentExtension({\n ref: coreComponentRefs.notFoundErrorPage,\n loader: { sync: () => componentCompatWrapper(NotFoundErrorPage) },\n }),\n );\n }\n if (ErrorBoundaryFallback) {\n const WrappedErrorBoundaryFallback = (\n props: CoreErrorBoundaryFallbackProps,\n ) =>\n compatWrapper(\n <ErrorBoundaryFallback\n {...props}\n plugin={props.plugin && toLegacyPlugin(props.plugin)}\n />,\n );\n extensions.push(\n createComponentExtension({\n ref: coreComponentRefs.errorBoundaryFallback,\n loader: {\n sync: () => componentCompatWrapper(WrappedErrorBoundaryFallback),\n },\n }),\n );\n }\n }\n\n return createFrontendModule({\n pluginId: 'app',\n extensions,\n featureFlags,\n });\n}\n"],"names":[],"mappings":"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"}
@@ -20,7 +20,7 @@ function convertLegacyPageExtension(LegacyExtension, overrides) {
20
20
  return PageBlueprint.make({
21
21
  name: overrides?.name ?? kebabName,
22
22
  params: {
23
- defaultPath: overrides?.defaultPath ?? `/${kebabName}`,
23
+ path: overrides?.path ?? `/${kebabName}`,
24
24
  routeRef: mountPoint && convertLegacyRouteRef(mountPoint),
25
25
  loader: async () => compatWrapper(element)
26
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"convertLegacyPageExtension.esm.js","sources":["../src/convertLegacyPageExtension.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n getComponentData,\n RouteRef as LegacyRouteRef,\n} from '@backstage/core-plugin-api';\nimport {\n ExtensionDefinition,\n PageBlueprint,\n} from '@backstage/frontend-plugin-api';\nimport kebabCase from 'lodash/kebabCase';\nimport { convertLegacyRouteRef } from './convertLegacyRouteRef';\nimport { ComponentType } from 'react';\nimport { compatWrapper } from './compatWrapper';\n\n/** @public */\nexport function convertLegacyPageExtension(\n LegacyExtension: ComponentType<{}>,\n overrides?: {\n name?: string;\n defaultPath?: string;\n },\n): ExtensionDefinition {\n const element = <LegacyExtension />;\n\n const extName = getComponentData<string>(element, 'core.extensionName');\n if (!extName) {\n throw new Error('Extension has no name');\n }\n\n const mountPoint = getComponentData<LegacyRouteRef>(\n element,\n 'core.mountPoint',\n );\n\n const name = extName.endsWith('Page')\n ? extName.slice(0, -'Page'.length)\n : extName;\n const kebabName = kebabCase(name);\n\n return PageBlueprint.make({\n name: overrides?.name ?? kebabName,\n params: {\n defaultPath: overrides?.defaultPath ?? `/${kebabName}`,\n routeRef: mountPoint && convertLegacyRouteRef(mountPoint),\n loader: async () => compatWrapper(element),\n },\n });\n}\n"],"names":[],"mappings":";;;;;;;AA8BgB,SAAA,0BAAA,CACd,iBACA,SAIqB,EAAA;AACrB,EAAM,MAAA,OAAA,uBAAW,eAAgB,EAAA,EAAA,CAAA;AAEjC,EAAM,MAAA,OAAA,GAAU,gBAAyB,CAAA,OAAA,EAAS,oBAAoB,CAAA;AACtE,EAAA,IAAI,CAAC,OAAS,EAAA;AACZ,IAAM,MAAA,IAAI,MAAM,uBAAuB,CAAA;AAAA;AAGzC,EAAA,MAAM,UAAa,GAAA,gBAAA;AAAA,IACjB,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAM,MAAA,IAAA,GAAO,OAAQ,CAAA,QAAA,CAAS,MAAM,CAAA,GAChC,OAAQ,CAAA,KAAA,CAAM,CAAG,EAAA,CAAC,MAAO,CAAA,MAAM,CAC/B,GAAA,OAAA;AACJ,EAAM,MAAA,SAAA,GAAY,UAAU,IAAI,CAAA;AAEhC,EAAA,OAAO,cAAc,IAAK,CAAA;AAAA,IACxB,IAAA,EAAM,WAAW,IAAQ,IAAA,SAAA;AAAA,IACzB,MAAQ,EAAA;AAAA,MACN,WAAa,EAAA,SAAA,EAAW,WAAe,IAAA,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA;AAAA,MACpD,QAAA,EAAU,UAAc,IAAA,qBAAA,CAAsB,UAAU,CAAA;AAAA,MACxD,MAAA,EAAQ,YAAY,aAAA,CAAc,OAAO;AAAA;AAC3C,GACD,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"convertLegacyPageExtension.esm.js","sources":["../src/convertLegacyPageExtension.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n getComponentData,\n RouteRef as LegacyRouteRef,\n} from '@backstage/core-plugin-api';\nimport {\n ExtensionDefinition,\n PageBlueprint,\n} from '@backstage/frontend-plugin-api';\nimport kebabCase from 'lodash/kebabCase';\nimport { convertLegacyRouteRef } from './convertLegacyRouteRef';\nimport { ComponentType } from 'react';\nimport { compatWrapper } from './compatWrapper';\n\n/** @public */\nexport function convertLegacyPageExtension(\n LegacyExtension: ComponentType<{}>,\n overrides?: {\n name?: string;\n path?: string;\n /**\n * @deprecated Use the `path` param instead.\n */\n defaultPath?: [Error: `Use the 'path' override instead`];\n },\n): ExtensionDefinition {\n const element = <LegacyExtension />;\n\n const extName = getComponentData<string>(element, 'core.extensionName');\n if (!extName) {\n throw new Error('Extension has no name');\n }\n\n const mountPoint = getComponentData<LegacyRouteRef>(\n element,\n 'core.mountPoint',\n );\n\n const name = extName.endsWith('Page')\n ? extName.slice(0, -'Page'.length)\n : extName;\n const kebabName = kebabCase(name);\n\n return PageBlueprint.make({\n name: overrides?.name ?? kebabName,\n params: {\n path: overrides?.path ?? `/${kebabName}`,\n routeRef: mountPoint && convertLegacyRouteRef(mountPoint),\n loader: async () => compatWrapper(element),\n },\n });\n}\n"],"names":[],"mappings":";;;;;;;AA8BgB,SAAA,0BAAA,CACd,iBACA,SAQqB,EAAA;AACrB,EAAM,MAAA,OAAA,uBAAW,eAAgB,EAAA,EAAA,CAAA;AAEjC,EAAM,MAAA,OAAA,GAAU,gBAAyB,CAAA,OAAA,EAAS,oBAAoB,CAAA;AACtE,EAAA,IAAI,CAAC,OAAS,EAAA;AACZ,IAAM,MAAA,IAAI,MAAM,uBAAuB,CAAA;AAAA;AAGzC,EAAA,MAAM,UAAa,GAAA,gBAAA;AAAA,IACjB,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAM,MAAA,IAAA,GAAO,OAAQ,CAAA,QAAA,CAAS,MAAM,CAAA,GAChC,OAAQ,CAAA,KAAA,CAAM,CAAG,EAAA,CAAC,MAAO,CAAA,MAAM,CAC/B,GAAA,OAAA;AACJ,EAAM,MAAA,SAAA,GAAY,UAAU,IAAI,CAAA;AAEhC,EAAA,OAAO,cAAc,IAAK,CAAA;AAAA,IACxB,IAAA,EAAM,WAAW,IAAQ,IAAA,SAAA;AAAA,IACzB,MAAQ,EAAA;AAAA,MACN,IAAM,EAAA,SAAA,EAAW,IAAQ,IAAA,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA;AAAA,MACtC,QAAA,EAAU,UAAc,IAAA,qBAAA,CAAsB,UAAU,CAAA;AAAA,MACxD,MAAA,EAAQ,YAAY,aAAA,CAAc,OAAO;AAAA;AAC3C,GACD,CAAA;AACH;;;;"}
@@ -5,7 +5,7 @@ function convertLegacyPlugin(legacyPlugin, options) {
5
5
  const apiExtensions = Array.from(legacyPlugin.getApis()).map(
6
6
  (factory) => ApiBlueprint.make({
7
7
  name: factory.api.id,
8
- params: (define) => define(factory)
8
+ params: (defineParams) => defineParams(factory)
9
9
  })
10
10
  );
11
11
  return createFrontendPlugin({
@@ -1 +1 @@
1
- {"version":3,"file":"convertLegacyPlugin.esm.js","sources":["../src/convertLegacyPlugin.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BackstagePlugin as LegacyBackstagePlugin } from '@backstage/core-plugin-api';\nimport {\n ApiBlueprint,\n ExtensionDefinition,\n FrontendPlugin as NewBackstagePlugin,\n createFrontendPlugin,\n} from '@backstage/frontend-plugin-api';\nimport { convertLegacyRouteRefs } from './convertLegacyRouteRef';\n\n/** @public */\nexport function convertLegacyPlugin(\n legacyPlugin: LegacyBackstagePlugin,\n options: { extensions: ExtensionDefinition[] },\n): NewBackstagePlugin {\n const apiExtensions = Array.from(legacyPlugin.getApis()).map(factory =>\n ApiBlueprint.make({\n name: factory.api.id,\n params: define => define(factory),\n }),\n );\n return createFrontendPlugin({\n pluginId: legacyPlugin.getId(),\n featureFlags: [...legacyPlugin.getFeatureFlags()],\n routes: convertLegacyRouteRefs(legacyPlugin.routes ?? {}),\n externalRoutes: convertLegacyRouteRefs(legacyPlugin.externalRoutes ?? {}),\n extensions: [...apiExtensions, ...options.extensions],\n });\n}\n"],"names":[],"mappings":";;;AA0BgB,SAAA,mBAAA,CACd,cACA,OACoB,EAAA;AACpB,EAAA,MAAM,gBAAgB,KAAM,CAAA,IAAA,CAAK,YAAa,CAAA,OAAA,EAAS,CAAE,CAAA,GAAA;AAAA,IAAI,CAAA,OAAA,KAC3D,aAAa,IAAK,CAAA;AAAA,MAChB,IAAA,EAAM,QAAQ,GAAI,CAAA,EAAA;AAAA,MAClB,MAAA,EAAQ,CAAU,MAAA,KAAA,MAAA,CAAO,OAAO;AAAA,KACjC;AAAA,GACH;AACA,EAAA,OAAO,oBAAqB,CAAA;AAAA,IAC1B,QAAA,EAAU,aAAa,KAAM,EAAA;AAAA,IAC7B,YAAc,EAAA,CAAC,GAAG,YAAA,CAAa,iBAAiB,CAAA;AAAA,IAChD,MAAQ,EAAA,sBAAA,CAAuB,YAAa,CAAA,MAAA,IAAU,EAAE,CAAA;AAAA,IACxD,cAAgB,EAAA,sBAAA,CAAuB,YAAa,CAAA,cAAA,IAAkB,EAAE,CAAA;AAAA,IACxE,YAAY,CAAC,GAAG,aAAe,EAAA,GAAG,QAAQ,UAAU;AAAA,GACrD,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"convertLegacyPlugin.esm.js","sources":["../src/convertLegacyPlugin.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BackstagePlugin as LegacyBackstagePlugin } from '@backstage/core-plugin-api';\nimport {\n ApiBlueprint,\n ExtensionDefinition,\n FrontendPlugin as NewBackstagePlugin,\n createFrontendPlugin,\n} from '@backstage/frontend-plugin-api';\nimport { convertLegacyRouteRefs } from './convertLegacyRouteRef';\n\n/** @public */\nexport function convertLegacyPlugin(\n legacyPlugin: LegacyBackstagePlugin,\n options: { extensions: ExtensionDefinition[] },\n): NewBackstagePlugin {\n const apiExtensions = Array.from(legacyPlugin.getApis()).map(factory =>\n ApiBlueprint.make({\n name: factory.api.id,\n params: defineParams => defineParams(factory),\n }),\n );\n return createFrontendPlugin({\n pluginId: legacyPlugin.getId(),\n featureFlags: [...legacyPlugin.getFeatureFlags()],\n routes: convertLegacyRouteRefs(legacyPlugin.routes ?? {}),\n externalRoutes: convertLegacyRouteRefs(legacyPlugin.externalRoutes ?? {}),\n extensions: [...apiExtensions, ...options.extensions],\n });\n}\n"],"names":[],"mappings":";;;AA0BgB,SAAA,mBAAA,CACd,cACA,OACoB,EAAA;AACpB,EAAA,MAAM,gBAAgB,KAAM,CAAA,IAAA,CAAK,YAAa,CAAA,OAAA,EAAS,CAAE,CAAA,GAAA;AAAA,IAAI,CAAA,OAAA,KAC3D,aAAa,IAAK,CAAA;AAAA,MAChB,IAAA,EAAM,QAAQ,GAAI,CAAA,EAAA;AAAA,MAClB,MAAA,EAAQ,CAAgB,YAAA,KAAA,YAAA,CAAa,OAAO;AAAA,KAC7C;AAAA,GACH;AACA,EAAA,OAAO,oBAAqB,CAAA;AAAA,IAC1B,QAAA,EAAU,aAAa,KAAM,EAAA;AAAA,IAC7B,YAAc,EAAA,CAAC,GAAG,YAAA,CAAa,iBAAiB,CAAA;AAAA,IAChD,MAAQ,EAAA,sBAAA,CAAuB,YAAa,CAAA,MAAA,IAAU,EAAE,CAAA;AAAA,IACxD,cAAgB,EAAA,sBAAA,CAAuB,YAAa,CAAA,cAAA,IAAkB,EAAE,CAAA;AAAA,IACxE,YAAY,CAAC,GAAG,aAAe,EAAA,GAAG,QAAQ,UAAU;AAAA,GACrD,CAAA;AACH;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"RouteRef.esm.js","sources":["../../../../../frontend-plugin-api/src/routing/RouteRef.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { describeParentCallSite } from './describeParentCallSite';\nimport { AnyRouteRefParams } from './types';\n\n/**\n * Absolute route reference.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport interface RouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> {\n readonly $$type: '@backstage/RouteRef';\n readonly T: TParams;\n}\n\n/** @internal */\nexport interface InternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> extends RouteRef<TParams> {\n readonly version: 'v1';\n getParams(): string[];\n getDescription(): string;\n\n setId(id: string): void;\n}\n\n/** @internal */\nexport function toInternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n>(resource: RouteRef<TParams>): InternalRouteRef<TParams> {\n const r = resource as InternalRouteRef<TParams>;\n if (r.$$type !== '@backstage/RouteRef') {\n throw new Error(`Invalid RouteRef, bad type '${r.$$type}'`);\n }\n\n return r;\n}\n\n/** @internal */\nexport function isRouteRef(opaque: { $$type: string }): opaque is RouteRef {\n return opaque.$$type === '@backstage/RouteRef';\n}\n\n/** @internal */\nexport class RouteRefImpl implements InternalRouteRef {\n readonly $$type = '@backstage/RouteRef';\n readonly version = 'v1';\n declare readonly T: never;\n\n #id?: string;\n #params: string[];\n #creationSite: string;\n\n constructor(readonly params: string[] = [], creationSite: string) {\n this.#params = params;\n this.#creationSite = creationSite;\n }\n\n getParams(): string[] {\n return this.#params;\n }\n\n getDescription(): string {\n if (this.#id) {\n return this.#id;\n }\n return `created at '${this.#creationSite}'`;\n }\n\n get #name() {\n return this.$$type.slice('@backstage/'.length);\n }\n\n setId(id: string): void {\n if (!id) {\n throw new Error(`${this.#name} id must be a non-empty string`);\n }\n if (this.#id && this.#id !== id) {\n throw new Error(\n `${this.#name} was referenced twice as both '${this.#id}' and '${id}'`,\n );\n }\n this.#id = id;\n }\n\n toString(): string {\n return `${this.#name}{${this.getDescription()}}`;\n }\n}\n\n/**\n * Create a {@link RouteRef} from a route descriptor.\n *\n * @param config - Description of the route reference to be created.\n * @public\n */\nexport function createRouteRef<\n // Params is the type that we care about and the one to be embedded in the route ref.\n // For example, given the params ['name', 'kind'], Params will be {name: string, kind: string}\n TParams extends { [param in TParamKeys]: string } | undefined = undefined,\n TParamKeys extends string = string,\n>(config?: {\n /** A list of parameter names that the path that this route ref is bound to must contain */\n readonly params: string extends TParamKeys ? (keyof TParams)[] : TParamKeys[];\n}): RouteRef<\n keyof TParams extends never\n ? undefined\n : string extends TParamKeys\n ? TParams\n : { [param in TParamKeys]: string }\n> {\n return new RouteRefImpl(\n config?.params as string[] | undefined,\n describeParentCallSite(),\n ) as RouteRef<any>;\n}\n"],"names":[],"mappings":"AA+CO,SAAS,mBAEd,QAAwD,EAAA;AACxD,EAAA,MAAM,CAAI,GAAA,QAAA;AACV,EAAI,IAAA,CAAA,CAAE,WAAW,qBAAuB,EAAA;AACtC,IAAA,MAAM,IAAI,KAAA,CAAM,CAA+B,4BAAA,EAAA,CAAA,CAAE,MAAM,CAAG,CAAA,CAAA,CAAA;AAAA;AAG5D,EAAO,OAAA,CAAA;AACT;;;;"}
1
+ {"version":3,"file":"RouteRef.esm.js","sources":["../../../../../frontend-plugin-api/src/routing/RouteRef.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { describeParentCallSite } from './describeParentCallSite';\nimport { AnyRouteRefParams } from './types';\n\n/**\n * Absolute route reference.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport interface RouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> {\n readonly $$type: '@backstage/RouteRef';\n readonly T: TParams;\n}\n\n/** @internal */\nexport interface InternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> extends RouteRef<TParams> {\n readonly version: 'v1';\n getParams(): string[];\n getDescription(): string;\n\n alias: string | undefined;\n\n setId(id: string): void;\n}\n\n/** @internal */\nexport function toInternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n>(resource: RouteRef<TParams>): InternalRouteRef<TParams> {\n const r = resource as InternalRouteRef<TParams>;\n if (r.$$type !== '@backstage/RouteRef') {\n throw new Error(`Invalid RouteRef, bad type '${r.$$type}'`);\n }\n\n return r;\n}\n\n/** @internal */\nexport function isRouteRef(opaque: { $$type: string }): opaque is RouteRef {\n return opaque.$$type === '@backstage/RouteRef';\n}\n\n/** @internal */\nexport class RouteRefImpl implements InternalRouteRef {\n readonly $$type = '@backstage/RouteRef';\n readonly version = 'v1';\n declare readonly T: never;\n\n #id?: string;\n readonly #params: string[];\n readonly #creationSite: string;\n readonly #alias?: string;\n\n constructor(\n readonly params: string[] = [],\n creationSite: string,\n alias?: string,\n ) {\n this.#params = params;\n this.#creationSite = creationSite;\n this.#alias = alias;\n }\n\n getParams(): string[] {\n return this.#params;\n }\n\n get alias(): string | undefined {\n return this.#alias;\n }\n\n getDescription(): string {\n if (this.#id) {\n return this.#id;\n }\n return `created at '${this.#creationSite}'`;\n }\n\n get #name() {\n return this.$$type.slice('@backstage/'.length);\n }\n\n setId(id: string): void {\n if (!id) {\n throw new Error(`${this.#name} id must be a non-empty string`);\n }\n if (this.#id && this.#id !== id) {\n throw new Error(\n `${this.#name} was referenced twice as both '${this.#id}' and '${id}'`,\n );\n }\n this.#id = id;\n }\n\n toString(): string {\n return `${this.#name}{${this.getDescription()}}`;\n }\n}\n\n/**\n * Create a {@link RouteRef} from a route descriptor.\n *\n * @param config - Description of the route reference to be created.\n * @public\n */\nexport function createRouteRef<\n // Params is the type that we care about and the one to be embedded in the route ref.\n // For example, given the params ['name', 'kind'], Params will be {name: string, kind: string}\n TParams extends { [param in TParamKeys]: string } | undefined = undefined,\n TParamKeys extends string = string,\n>(config?: {\n /** A list of parameter names that the path that this route ref is bound to must contain */\n readonly params?: string extends TParamKeys\n ? (keyof TParams)[]\n : TParamKeys[];\n\n aliasFor?: string;\n}): RouteRef<\n keyof TParams extends never\n ? undefined\n : string extends TParamKeys\n ? TParams\n : { [param in TParamKeys]: string }\n> {\n return new RouteRefImpl(\n config?.params as string[] | undefined,\n describeParentCallSite(),\n config?.aliasFor,\n ) as RouteRef<any>;\n}\n"],"names":[],"mappings":"AAiDO,SAAS,mBAEd,QAAwD,EAAA;AACxD,EAAA,MAAM,CAAI,GAAA,QAAA;AACV,EAAI,IAAA,CAAA,CAAE,WAAW,qBAAuB,EAAA;AACtC,IAAA,MAAM,IAAI,KAAA,CAAM,CAA+B,4BAAA,EAAA,CAAA,CAAE,MAAM,CAAG,CAAA,CAAA,CAAA;AAAA;AAG5D,EAAO,OAAA,CAAA;AACT;;;;"}
package/dist/index.d.ts CHANGED
@@ -110,7 +110,11 @@ declare function convertLegacyPlugin(legacyPlugin: BackstagePlugin, options: {
110
110
  /** @public */
111
111
  declare function convertLegacyPageExtension(LegacyExtension: ComponentType<{}>, overrides?: {
112
112
  name?: string;
113
- defaultPath?: string;
113
+ path?: string;
114
+ /**
115
+ * @deprecated Use the `path` param instead.
116
+ */
117
+ defaultPath?: [Error: `Use the 'path' override instead`];
114
118
  }): ExtensionDefinition;
115
119
 
116
120
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/core-compat-api",
3
- "version": "0.4.5-next.1",
3
+ "version": "0.5.0-next.2",
4
4
  "backstage": {
5
5
  "role": "web-library"
6
6
  },
@@ -32,17 +32,17 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@backstage/core-plugin-api": "1.10.9",
35
- "@backstage/frontend-plugin-api": "0.11.0-next.0",
36
- "@backstage/plugin-catalog-react": "1.20.0-next.1",
35
+ "@backstage/frontend-plugin-api": "0.11.0-next.1",
36
+ "@backstage/plugin-catalog-react": "1.20.0-next.2",
37
37
  "@backstage/version-bridge": "1.0.11",
38
38
  "lodash": "^4.17.21"
39
39
  },
40
40
  "devDependencies": {
41
- "@backstage/cli": "0.33.2-next.0",
41
+ "@backstage/cli": "0.34.0-next.1",
42
42
  "@backstage/core-app-api": "1.18.0",
43
- "@backstage/frontend-app-api": "0.11.5-next.1",
44
- "@backstage/frontend-test-utils": "0.3.5-next.1",
45
- "@backstage/plugin-catalog": "1.31.2-next.1",
43
+ "@backstage/frontend-app-api": "0.12.0-next.2",
44
+ "@backstage/frontend-test-utils": "0.3.5-next.2",
45
+ "@backstage/plugin-catalog": "1.31.2-next.2",
46
46
  "@backstage/test-utils": "1.7.11-next.0",
47
47
  "@backstage/types": "1.2.1",
48
48
  "@testing-library/jest-dom": "^6.0.0",