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

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.
Files changed (28) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/apis/implementations/AnalyticsApi/MultipleAnalyticsApi.esm.js.map +1 -1
  3. package/dist/apis/implementations/AnalyticsApi/NoOpAnalyticsApi.esm.js.map +1 -1
  4. package/dist/collectEntityPageContents.esm.js.map +1 -1
  5. package/dist/collectLegacyRoutes.esm.js.map +1 -1
  6. package/dist/compatWrapper/BackwardsCompatProvider.esm.js +5 -17
  7. package/dist/compatWrapper/BackwardsCompatProvider.esm.js.map +1 -1
  8. package/dist/compatWrapper/ForwardsCompatProvider.esm.js +5 -5
  9. package/dist/compatWrapper/ForwardsCompatProvider.esm.js.map +1 -1
  10. package/dist/compatWrapper/compatWrapper.esm.js.map +1 -1
  11. package/dist/convertLegacyApp.esm.js +4 -3
  12. package/dist/convertLegacyApp.esm.js.map +1 -1
  13. package/dist/convertLegacyAppOptions.esm.js +20 -16
  14. package/dist/convertLegacyAppOptions.esm.js.map +1 -1
  15. package/dist/convertLegacyPageExtension.esm.js.map +1 -1
  16. package/dist/convertLegacyPlugin.esm.js.map +1 -1
  17. package/dist/convertLegacyRouteRef.esm.js.map +1 -1
  18. package/dist/core-app-api/src/apis/system/ApiAggregator.esm.js.map +1 -1
  19. package/dist/core-app-api/src/apis/system/ApiProvider.esm.js.map +1 -1
  20. package/dist/core-app-api/src/app/AppContext.esm.js.map +1 -1
  21. package/dist/core-plugin-api/src/routing/types.esm.js.map +1 -1
  22. package/dist/frontend-plugin-api/src/routing/ExternalRouteRef.esm.js.map +1 -1
  23. package/dist/frontend-plugin-api/src/routing/RouteRef.esm.js.map +1 -1
  24. package/dist/frontend-plugin-api/src/routing/SubRouteRef.esm.js.map +1 -1
  25. package/dist/index.d.ts +16 -4
  26. package/dist/index.esm.js +1 -1
  27. package/dist/normalizeRoutePath.esm.js.map +1 -1
  28. package/package.json +12 -12
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # @backstage/core-compat-api
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 62c3628: Rename `createLegacyApp` to `createLegacyAppRoot` as it better refers to the purpose of the function.
8
+ - 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`.
9
+
10
+ ### Patch Changes
11
+
12
+ - e4ddf22: Internal update to align with new blueprint parameter naming in the new frontend system.
13
+ - f2f133c: Internal update to use the new variant of `ApiBlueprint`.
14
+ - fda1bbc: The `compatWrapper` has been switched to use the new `SwappableComponentsApi` instead of the old `ComponentsApi` in its bridging to the old frontend system.
15
+ - 5d31d66: Updated the usage of the `RouterBlueprint` and `AppRootWrapperBlueprint` to use the lowercase `component` parameter
16
+ - Updated dependencies
17
+ - @backstage/frontend-plugin-api@0.11.0
18
+ - @backstage/plugin-catalog-react@1.20.0
19
+
20
+ ## 0.5.0-next.3
21
+
22
+ ### Patch Changes
23
+
24
+ - fda1bbc: The `compatWrapper` has been switched to use the new `SwappableComponentsApi` instead of the old `ComponentsApi` in its bridging to the old frontend system.
25
+ - Updated dependencies
26
+ - @backstage/frontend-plugin-api@0.11.0-next.2
27
+
3
28
  ## 0.5.0-next.2
4
29
 
5
30
  ### Minor Changes
@@ -1 +1 @@
1
- {"version":3,"file":"MultipleAnalyticsApi.esm.js","sources":["../../../../src/apis/implementations/AnalyticsApi/MultipleAnalyticsApi.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 */\nimport { AnalyticsApi, AnalyticsEvent } from '@backstage/core-plugin-api';\nimport {\n AnalyticsApi as NewAnalyicsApi,\n AnalyticsEvent as NewAnalyicsEvent,\n} from '@backstage/frontend-plugin-api';\n\n/**\n * An implementation of the AnalyticsApi that can be used to forward analytics\n * events to multiple concrete implementations.\n *\n * @public\n *\n * @example\n *\n * ```jsx\n * createApiFactory({\n * api: analyticsApiRef,\n * deps: { configApi: configApiRef, identityApi: identityApiRef, storageApi: storageApiRef },\n * factory: ({ configApi, identityApi, storageApi }) =>\n * MultipleAnalyticsApi.fromApis([\n * VendorAnalyticsApi.fromConfig(configApi, { identityApi }),\n * CustomAnalyticsApi.fromConfig(configApi, { identityApi, storageApi }),\n * ]),\n * });\n * ```\n */\nexport class MultipleAnalyticsApi implements AnalyticsApi, NewAnalyicsApi {\n private constructor(\n private readonly actualApis: (AnalyticsApi | NewAnalyicsApi)[],\n ) {}\n\n /**\n * Create an AnalyticsApi implementation from an array of concrete\n * implementations.\n *\n * @example\n *\n * ```jsx\n * MultipleAnalyticsApi.fromApis([\n * SomeAnalyticsApi.fromConfig(configApi),\n * new CustomAnalyticsApi(),\n * ]);\n * ```\n */\n static fromApis(actualApis: (AnalyticsApi | NewAnalyicsApi)[]) {\n return new MultipleAnalyticsApi(actualApis);\n }\n\n /**\n * Forward the event to all configured analytics API implementations.\n */\n captureEvent(event: AnalyticsEvent | NewAnalyicsEvent): void {\n this.actualApis.forEach(analyticsApi => {\n try {\n analyticsApi.captureEvent(event as AnalyticsEvent & NewAnalyicsEvent);\n } catch {\n /* ignored */\n }\n });\n }\n}\n"],"names":[],"mappings":"AAyCO,MAAM,oBAA6D,CAAA;AAAA,EAChE,YACW,UACjB,EAAA;AADiB,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAAA;AAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeH,OAAO,SAAS,UAA+C,EAAA;AAC7D,IAAO,OAAA,IAAI,qBAAqB,UAAU,CAAA;AAAA;AAC5C;AAAA;AAAA;AAAA,EAKA,aAAa,KAAgD,EAAA;AAC3D,IAAK,IAAA,CAAA,UAAA,CAAW,QAAQ,CAAgB,YAAA,KAAA;AACtC,MAAI,IAAA;AACF,QAAA,YAAA,CAAa,aAAa,KAA0C,CAAA;AAAA,OAC9D,CAAA,MAAA;AAAA;AAER,KACD,CAAA;AAAA;AAEL;;;;"}
1
+ {"version":3,"file":"MultipleAnalyticsApi.esm.js","sources":["../../../../src/apis/implementations/AnalyticsApi/MultipleAnalyticsApi.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 */\nimport { AnalyticsApi, AnalyticsEvent } from '@backstage/core-plugin-api';\nimport {\n AnalyticsApi as NewAnalyicsApi,\n AnalyticsEvent as NewAnalyicsEvent,\n} from '@backstage/frontend-plugin-api';\n\n/**\n * An implementation of the AnalyticsApi that can be used to forward analytics\n * events to multiple concrete implementations.\n *\n * @public\n *\n * @example\n *\n * ```jsx\n * createApiFactory({\n * api: analyticsApiRef,\n * deps: { configApi: configApiRef, identityApi: identityApiRef, storageApi: storageApiRef },\n * factory: ({ configApi, identityApi, storageApi }) =>\n * MultipleAnalyticsApi.fromApis([\n * VendorAnalyticsApi.fromConfig(configApi, { identityApi }),\n * CustomAnalyticsApi.fromConfig(configApi, { identityApi, storageApi }),\n * ]),\n * });\n * ```\n */\nexport class MultipleAnalyticsApi implements AnalyticsApi, NewAnalyicsApi {\n private constructor(\n private readonly actualApis: (AnalyticsApi | NewAnalyicsApi)[],\n ) {}\n\n /**\n * Create an AnalyticsApi implementation from an array of concrete\n * implementations.\n *\n * @example\n *\n * ```jsx\n * MultipleAnalyticsApi.fromApis([\n * SomeAnalyticsApi.fromConfig(configApi),\n * new CustomAnalyticsApi(),\n * ]);\n * ```\n */\n static fromApis(actualApis: (AnalyticsApi | NewAnalyicsApi)[]) {\n return new MultipleAnalyticsApi(actualApis);\n }\n\n /**\n * Forward the event to all configured analytics API implementations.\n */\n captureEvent(event: AnalyticsEvent | NewAnalyicsEvent): void {\n this.actualApis.forEach(analyticsApi => {\n try {\n analyticsApi.captureEvent(event as AnalyticsEvent & NewAnalyicsEvent);\n } catch {\n /* ignored */\n }\n });\n }\n}\n"],"names":[],"mappings":"AAyCO,MAAM,oBAAA,CAA6D;AAAA,EAChE,YACW,UAAA,EACjB;AADiB,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeH,OAAO,SAAS,UAAA,EAA+C;AAC7D,IAAA,OAAO,IAAI,qBAAqB,UAAU,CAAA;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,KAAA,EAAgD;AAC3D,IAAA,IAAA,CAAK,UAAA,CAAW,QAAQ,CAAA,YAAA,KAAgB;AACtC,MAAA,IAAI;AACF,QAAA,YAAA,CAAa,aAAa,KAA0C,CAAA;AAAA,MACtE,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AACF;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"NoOpAnalyticsApi.esm.js","sources":["../../../../src/apis/implementations/AnalyticsApi/NoOpAnalyticsApi.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 { AnalyticsApi, AnalyticsEvent } from '@backstage/core-plugin-api';\nimport {\n AnalyticsApi as NewAnalyicsApi,\n AnalyticsEvent as NewAnalyicsEvent,\n} from '@backstage/frontend-plugin-api';\n\n/**\n * Base implementation for the AnalyticsApi that does nothing.\n *\n * @public\n */\nexport class NoOpAnalyticsApi implements AnalyticsApi, NewAnalyicsApi {\n captureEvent(_event: AnalyticsEvent | NewAnalyicsEvent): void {}\n}\n"],"names":[],"mappings":"AA2BO,MAAM,gBAAyD,CAAA;AAAA,EACpE,aAAa,MAAiD,EAAA;AAAA;AAChE;;;;"}
1
+ {"version":3,"file":"NoOpAnalyticsApi.esm.js","sources":["../../../../src/apis/implementations/AnalyticsApi/NoOpAnalyticsApi.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 { AnalyticsApi, AnalyticsEvent } from '@backstage/core-plugin-api';\nimport {\n AnalyticsApi as NewAnalyicsApi,\n AnalyticsEvent as NewAnalyicsEvent,\n} from '@backstage/frontend-plugin-api';\n\n/**\n * Base implementation for the AnalyticsApi that does nothing.\n *\n * @public\n */\nexport class NoOpAnalyticsApi implements AnalyticsApi, NewAnalyicsApi {\n captureEvent(_event: AnalyticsEvent | NewAnalyicsEvent): void {}\n}\n"],"names":[],"mappings":"AA2BO,MAAM,gBAAA,CAAyD;AAAA,EACpE,aAAa,MAAA,EAAiD;AAAA,EAAC;AACjE;;;;"}
@@ -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 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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"}
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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"}
@@ -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 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
+ {"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,7 +1,7 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { useMemo } from 'react';
3
3
  import { AppContextProvider } from '../core-app-api/src/app/AppContext.esm.js';
4
- import { useApi, appTreeApiRef, componentsApiRef, iconsApiRef, coreComponentRefs, routeResolutionApiRef, createFrontendPlugin } from '@backstage/frontend-plugin-api';
4
+ import { useApi, routeResolutionApiRef, appTreeApiRef, iconsApiRef, Progress, NotFoundErrorPage, ErrorDisplay, createFrontendPlugin } from '@backstage/frontend-plugin-api';
5
5
  import { getOrCreateGlobalSingleton, createVersionedContext, createVersionedValueMap } from '@backstage/version-bridge';
6
6
  import { convertLegacyRouteRef } from '../convertLegacyRouteRef.esm.js';
7
7
 
@@ -42,21 +42,11 @@ function toNewPlugin(plugin) {
42
42
  }
43
43
  function LegacyAppContextProvider(props) {
44
44
  const appTreeApi = useApi(appTreeApiRef);
45
- const componentsApi = useApi(componentsApiRef);
46
45
  const iconsApi = useApi(iconsApiRef);
47
46
  const appContext = useMemo(() => {
48
47
  const { tree } = appTreeApi.getTree();
49
48
  let gatheredPlugins = void 0;
50
- const ErrorBoundaryFallback = componentsApi.getComponent(
51
- coreComponentRefs.errorBoundaryFallback
52
- );
53
- const ErrorBoundaryFallbackWrapper = ({ plugin, ...rest }) => /* @__PURE__ */ jsx(
54
- ErrorBoundaryFallback,
55
- {
56
- ...rest,
57
- plugin: plugin && toNewPlugin(plugin)
58
- }
59
- );
49
+ const ErrorBoundaryFallbackWrapper = ({ plugin, ...rest }) => /* @__PURE__ */ jsx(ErrorDisplay, { ...rest, plugin: plugin && toNewPlugin(plugin) });
60
50
  return {
61
51
  getPlugins() {
62
52
  if (gatheredPlugins) {
@@ -82,15 +72,13 @@ function LegacyAppContextProvider(props) {
82
72
  },
83
73
  getComponents() {
84
74
  return {
85
- NotFoundErrorPage: componentsApi.getComponent(
86
- coreComponentRefs.notFoundErrorPage
87
- ),
75
+ NotFoundErrorPage,
88
76
  BootErrorPage() {
89
77
  throw new Error(
90
78
  "The BootErrorPage app component should not be accessed by plugins"
91
79
  );
92
80
  },
93
- Progress: componentsApi.getComponent(coreComponentRefs.progress),
81
+ Progress,
94
82
  Router() {
95
83
  throw new Error(
96
84
  "The Router app component should not be accessed by plugins"
@@ -100,7 +88,7 @@ function LegacyAppContextProvider(props) {
100
88
  };
101
89
  }
102
90
  };
103
- }, [appTreeApi, componentsApi, iconsApi]);
91
+ }, [appTreeApi, iconsApi]);
104
92
  return /* @__PURE__ */ jsx(AppContextProvider, { appContext, children: props.children });
105
93
  }
106
94
  const RoutingContext = createVersionedContext(
@@ -1 +1 @@
1
- {"version":3,"file":"BackwardsCompatProvider.esm.js","sources":["../../src/compatWrapper/BackwardsCompatProvider.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 { useMemo } from 'react';\nimport { ReactNode } from 'react';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { AppContextProvider } from '../../../core-app-api/src/app/AppContext';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { RouteResolver } from '../../../core-plugin-api/src/routing/useRouteRef';\nimport {\n createFrontendPlugin as createNewPlugin,\n FrontendPlugin as NewFrontendPlugin,\n appTreeApiRef,\n componentsApiRef,\n coreComponentRefs,\n iconsApiRef,\n useApi,\n routeResolutionApiRef,\n} from '@backstage/frontend-plugin-api';\nimport {\n AppComponents,\n IconComponent,\n BackstagePlugin as LegacyBackstagePlugin,\n RouteRef,\n} from '@backstage/core-plugin-api';\nimport {\n VersionedValue,\n createVersionedContext,\n createVersionedValueMap,\n getOrCreateGlobalSingleton,\n} from '@backstage/version-bridge';\nimport { convertLegacyRouteRef } from '../convertLegacyRouteRef';\n\n// Make sure that we only convert each new plugin instance to its legacy equivalent once\nconst legacyPluginStore = getOrCreateGlobalSingleton(\n 'legacy-plugin-compatibility-store',\n () => new WeakMap<NewFrontendPlugin, LegacyBackstagePlugin>(),\n);\n\nexport function toLegacyPlugin(\n plugin: NewFrontendPlugin,\n): LegacyBackstagePlugin {\n let legacy = legacyPluginStore.get(plugin);\n if (legacy) {\n return legacy;\n }\n\n const errorMsg = 'Not implemented in legacy plugin compatibility layer';\n const notImplemented = () => {\n throw new Error(errorMsg);\n };\n\n legacy = {\n getId(): string {\n return plugin.id;\n },\n get routes() {\n return {};\n },\n get externalRoutes() {\n return {};\n },\n getApis: notImplemented,\n getFeatureFlags: notImplemented,\n provide: notImplemented,\n };\n\n legacyPluginStore.set(plugin, legacy);\n return legacy;\n}\n\n// TODO: Currently a very naive implementation, may need some more work\nfunction toNewPlugin(plugin: LegacyBackstagePlugin): NewFrontendPlugin {\n return createNewPlugin({\n pluginId: plugin.getId(),\n });\n}\n\n// Recreates the old AppContext APIs using the various new APIs that replaced it\nfunction LegacyAppContextProvider(props: { children: ReactNode }) {\n const appTreeApi = useApi(appTreeApiRef);\n const componentsApi = useApi(componentsApiRef);\n const iconsApi = useApi(iconsApiRef);\n\n const appContext = useMemo(() => {\n const { tree } = appTreeApi.getTree();\n\n let gatheredPlugins: LegacyBackstagePlugin[] | undefined = undefined;\n\n const ErrorBoundaryFallback = componentsApi.getComponent(\n coreComponentRefs.errorBoundaryFallback,\n );\n const ErrorBoundaryFallbackWrapper: AppComponents['ErrorBoundaryFallback'] =\n ({ plugin, ...rest }) => (\n <ErrorBoundaryFallback\n {...rest}\n plugin={plugin && toNewPlugin(plugin)}\n />\n );\n\n return {\n getPlugins(): LegacyBackstagePlugin[] {\n if (gatheredPlugins) {\n return gatheredPlugins;\n }\n\n const pluginSet = new Set<LegacyBackstagePlugin>();\n for (const node of tree.nodes.values()) {\n const plugin = node.spec.plugin;\n if (plugin) {\n pluginSet.add(toLegacyPlugin(plugin));\n }\n }\n gatheredPlugins = Array.from(pluginSet);\n\n return gatheredPlugins;\n },\n\n getSystemIcon(key: string): IconComponent | undefined {\n return iconsApi.getIcon(key);\n },\n\n getSystemIcons(): Record<string, IconComponent> {\n return Object.fromEntries(\n iconsApi.listIconKeys().map(key => [key, iconsApi.getIcon(key)!]),\n );\n },\n\n getComponents(): AppComponents {\n return {\n NotFoundErrorPage: componentsApi.getComponent(\n coreComponentRefs.notFoundErrorPage,\n ),\n BootErrorPage() {\n throw new Error(\n 'The BootErrorPage app component should not be accessed by plugins',\n );\n },\n Progress: componentsApi.getComponent(coreComponentRefs.progress),\n Router() {\n throw new Error(\n 'The Router app component should not be accessed by plugins',\n );\n },\n ErrorBoundaryFallback: ErrorBoundaryFallbackWrapper,\n };\n },\n };\n }, [appTreeApi, componentsApi, iconsApi]);\n\n return (\n <AppContextProvider appContext={appContext}>\n {props.children}\n </AppContextProvider>\n );\n}\n\nconst RoutingContext = createVersionedContext<{ 1: RouteResolver }>(\n 'routing-context',\n);\n\nfunction LegacyRoutingProvider(props: { children: ReactNode }) {\n const routeResolutionApi = useApi(routeResolutionApiRef);\n\n const value = useMemo<VersionedValue<{ 1: RouteResolver }>>(() => {\n return createVersionedValueMap({\n 1: {\n resolve(anyRouteRef, location) {\n const sourcePath =\n typeof location === 'string' ? location : location.pathname ?? '';\n\n return routeResolutionApi.resolve(\n // This removes the requirement to use convertLegacyRouteRef inside plugins, but\n // they still need to converted when passed to the plugin instance\n convertLegacyRouteRef(anyRouteRef as RouteRef),\n { sourcePath },\n );\n },\n },\n });\n }, [routeResolutionApi]);\n\n return (\n <RoutingContext.Provider value={value}>\n {props.children}\n </RoutingContext.Provider>\n );\n}\n\nexport function BackwardsCompatProvider(props: { children: ReactNode }) {\n return (\n <LegacyRoutingProvider>\n <LegacyAppContextProvider>{props.children}</LegacyAppContextProvider>\n </LegacyRoutingProvider>\n );\n}\n"],"names":["createNewPlugin"],"mappings":"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"}
1
+ {"version":3,"file":"BackwardsCompatProvider.esm.js","sources":["../../src/compatWrapper/BackwardsCompatProvider.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 { useMemo } from 'react';\nimport { ReactNode } from 'react';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { AppContextProvider } from '../../../core-app-api/src/app/AppContext';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { RouteResolver } from '../../../core-plugin-api/src/routing/useRouteRef';\nimport {\n createFrontendPlugin as createNewPlugin,\n FrontendPlugin as NewFrontendPlugin,\n appTreeApiRef,\n iconsApiRef,\n useApi,\n routeResolutionApiRef,\n ErrorDisplay,\n NotFoundErrorPage,\n Progress,\n} from '@backstage/frontend-plugin-api';\nimport {\n AppComponents,\n IconComponent,\n BackstagePlugin as LegacyBackstagePlugin,\n RouteRef,\n} from '@backstage/core-plugin-api';\nimport {\n VersionedValue,\n createVersionedContext,\n createVersionedValueMap,\n getOrCreateGlobalSingleton,\n} from '@backstage/version-bridge';\nimport { convertLegacyRouteRef } from '../convertLegacyRouteRef';\n\n// Make sure that we only convert each new plugin instance to its legacy equivalent once\nconst legacyPluginStore = getOrCreateGlobalSingleton(\n 'legacy-plugin-compatibility-store',\n () => new WeakMap<NewFrontendPlugin, LegacyBackstagePlugin>(),\n);\n\nexport function toLegacyPlugin(\n plugin: NewFrontendPlugin,\n): LegacyBackstagePlugin {\n let legacy = legacyPluginStore.get(plugin);\n if (legacy) {\n return legacy;\n }\n\n const errorMsg = 'Not implemented in legacy plugin compatibility layer';\n const notImplemented = () => {\n throw new Error(errorMsg);\n };\n\n legacy = {\n getId(): string {\n return plugin.id;\n },\n get routes() {\n return {};\n },\n get externalRoutes() {\n return {};\n },\n getApis: notImplemented,\n getFeatureFlags: notImplemented,\n provide: notImplemented,\n };\n\n legacyPluginStore.set(plugin, legacy);\n return legacy;\n}\n\n// TODO: Currently a very naive implementation, may need some more work\nfunction toNewPlugin(plugin: LegacyBackstagePlugin): NewFrontendPlugin {\n return createNewPlugin({\n pluginId: plugin.getId(),\n });\n}\n\n// Recreates the old AppContext APIs using the various new APIs that replaced it\nfunction LegacyAppContextProvider(props: { children: ReactNode }) {\n const appTreeApi = useApi(appTreeApiRef);\n const iconsApi = useApi(iconsApiRef);\n\n const appContext = useMemo(() => {\n const { tree } = appTreeApi.getTree();\n\n let gatheredPlugins: LegacyBackstagePlugin[] | undefined = undefined;\n\n const ErrorBoundaryFallbackWrapper: AppComponents['ErrorBoundaryFallback'] =\n ({ plugin, ...rest }) => (\n <ErrorDisplay {...rest} plugin={plugin && toNewPlugin(plugin)} />\n );\n\n return {\n getPlugins(): LegacyBackstagePlugin[] {\n if (gatheredPlugins) {\n return gatheredPlugins;\n }\n\n const pluginSet = new Set<LegacyBackstagePlugin>();\n for (const node of tree.nodes.values()) {\n const plugin = node.spec.plugin;\n if (plugin) {\n pluginSet.add(toLegacyPlugin(plugin));\n }\n }\n gatheredPlugins = Array.from(pluginSet);\n\n return gatheredPlugins;\n },\n\n getSystemIcon(key: string): IconComponent | undefined {\n return iconsApi.getIcon(key);\n },\n\n getSystemIcons(): Record<string, IconComponent> {\n return Object.fromEntries(\n iconsApi.listIconKeys().map(key => [key, iconsApi.getIcon(key)!]),\n );\n },\n\n getComponents(): AppComponents {\n return {\n NotFoundErrorPage: NotFoundErrorPage,\n BootErrorPage() {\n throw new Error(\n 'The BootErrorPage app component should not be accessed by plugins',\n );\n },\n Progress: Progress,\n Router() {\n throw new Error(\n 'The Router app component should not be accessed by plugins',\n );\n },\n ErrorBoundaryFallback: ErrorBoundaryFallbackWrapper,\n };\n },\n };\n }, [appTreeApi, iconsApi]);\n\n return (\n <AppContextProvider appContext={appContext}>\n {props.children}\n </AppContextProvider>\n );\n}\n\nconst RoutingContext = createVersionedContext<{ 1: RouteResolver }>(\n 'routing-context',\n);\n\nfunction LegacyRoutingProvider(props: { children: ReactNode }) {\n const routeResolutionApi = useApi(routeResolutionApiRef);\n\n const value = useMemo<VersionedValue<{ 1: RouteResolver }>>(() => {\n return createVersionedValueMap({\n 1: {\n resolve(anyRouteRef, location) {\n const sourcePath =\n typeof location === 'string' ? location : location.pathname ?? '';\n\n return routeResolutionApi.resolve(\n // This removes the requirement to use convertLegacyRouteRef inside plugins, but\n // they still need to converted when passed to the plugin instance\n convertLegacyRouteRef(anyRouteRef as RouteRef),\n { sourcePath },\n );\n },\n },\n });\n }, [routeResolutionApi]);\n\n return (\n <RoutingContext.Provider value={value}>\n {props.children}\n </RoutingContext.Provider>\n );\n}\n\nexport function BackwardsCompatProvider(props: { children: ReactNode }) {\n return (\n <LegacyRoutingProvider>\n <LegacyAppContextProvider>{props.children}</LegacyAppContextProvider>\n </LegacyRoutingProvider>\n );\n}\n"],"names":["createNewPlugin"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { useApp } from '@backstage/core-plugin-api';
3
- import { componentsApiRef, iconsApiRef, routeResolutionApiRef, coreComponentRefs } from '@backstage/frontend-plugin-api';
3
+ import { swappableComponentsApiRef, iconsApiRef, routeResolutionApiRef, ErrorDisplay, NotFoundErrorPage, Progress } from '@backstage/frontend-plugin-api';
4
4
  import { useMemo } from 'react';
5
5
  import { toLegacyPlugin } from './BackwardsCompatProvider.esm.js';
6
6
  import { ApiProvider } from '../core-app-api/src/apis/system/ApiProvider.esm.js';
@@ -26,11 +26,11 @@ class CompatComponentsApi {
26
26
  }
27
27
  getComponent(ref) {
28
28
  switch (ref.id) {
29
- case coreComponentRefs.progress.id:
29
+ case Progress.ref.id:
30
30
  return this.#Progress;
31
- case coreComponentRefs.notFoundErrorPage.id:
31
+ case NotFoundErrorPage.ref.id:
32
32
  return this.#NotFoundErrorPage;
33
- case coreComponentRefs.errorBoundaryFallback.id:
33
+ case ErrorDisplay.ref.id:
34
34
  return this.#ErrorBoundaryFallback;
35
35
  default:
36
36
  throw new Error(
@@ -71,7 +71,7 @@ class ForwardsCompatApis {
71
71
  this.#routeResolutionApi = new CompatRouteResolutionApi(routeResolver);
72
72
  }
73
73
  get(ref) {
74
- if (ref.id === componentsApiRef.id) {
74
+ if (ref.id === swappableComponentsApiRef.id) {
75
75
  return this.#componentsApi;
76
76
  } else if (ref.id === iconsApiRef.id) {
77
77
  return this.#iconsApi;
@@ -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 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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"}
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 SwappableComponentRef,\n SwappableComponentsApi,\n ErrorDisplayProps,\n NotFoundErrorPageProps,\n ProgressProps,\n ExternalRouteRef,\n IconComponent,\n IconsApi,\n RouteFunc,\n RouteRef,\n RouteResolutionApi,\n SubRouteRef,\n swappableComponentsApiRef,\n iconsApiRef,\n routeResolutionApiRef,\n Progress,\n NotFoundErrorPage,\n ErrorDisplay,\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 SwappableComponentsApi {\n readonly #Progress: ComponentType<ProgressProps>;\n readonly #NotFoundErrorPage: ComponentType<NotFoundErrorPageProps>;\n readonly #ErrorBoundaryFallback: ComponentType<ErrorDisplayProps>;\n\n constructor(app: AppContext) {\n const components = app.getComponents();\n const ErrorBoundaryFallback = (props: ErrorDisplayProps) => (\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<\n TInnerComponentProps extends {},\n TExternalComponentProps extends {} = TInnerComponentProps,\n >(\n ref: SwappableComponentRef<TInnerComponentProps, TExternalComponentProps>,\n ): (props: TInnerComponentProps) => JSX.Element | null {\n switch (ref.id) {\n case Progress.ref.id:\n return this.#Progress as (props: object) => JSX.Element | null;\n case NotFoundErrorPage.ref.id:\n return this.#NotFoundErrorPage as (props: object) => JSX.Element | null;\n case ErrorDisplay.ref.id:\n return this.#ErrorBoundaryFallback as (\n props: object,\n ) => JSX.Element | null;\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: SwappableComponentsApi;\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 === swappableComponentsApiRef.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 +1 @@
1
- {"version":3,"file":"compatWrapper.esm.js","sources":["../../src/compatWrapper/compatWrapper.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 { useVersionedContext } from '@backstage/version-bridge';\nimport { ReactNode } from 'react';\nimport { BackwardsCompatProvider } from './BackwardsCompatProvider';\nimport { ForwardsCompatProvider } from './ForwardsCompatProvider';\n\nfunction BidirectionalCompatProvider(props: { children: ReactNode }) {\n const isInNewApp = !useVersionedContext<{ 1: unknown }>('app-context');\n\n if (isInNewApp) {\n return <BackwardsCompatProvider {...props} />;\n }\n\n return <ForwardsCompatProvider {...props} />;\n}\n\n/**\n * Wraps a React element in a bidirectional compatibility provider, allow APIs\n * from `@backstage/core-plugin-api` to be used in an app from `@backstage/frontend-app-api`,\n * and APIs from `@backstage/frontend-plugin-api` to be used in an app from `@backstage/core-app-api`.\n *\n * @public\n */\nexport function compatWrapper(element: ReactNode) {\n return <BidirectionalCompatProvider>{element}</BidirectionalCompatProvider>;\n}\n"],"names":[],"mappings":";;;;;AAqBA,SAAS,4BAA4B,KAAgC,EAAA;AACnE,EAAM,MAAA,UAAA,GAAa,CAAC,mBAAA,CAAoC,aAAa,CAAA;AAErE,EAAA,IAAI,UAAY,EAAA;AACd,IAAO,uBAAA,GAAA,CAAC,uBAAyB,EAAA,EAAA,GAAG,KAAO,EAAA,CAAA;AAAA;AAG7C,EAAO,uBAAA,GAAA,CAAC,sBAAwB,EAAA,EAAA,GAAG,KAAO,EAAA,CAAA;AAC5C;AASO,SAAS,cAAc,OAAoB,EAAA;AAChD,EAAO,uBAAA,GAAA,CAAC,+BAA6B,QAAQ,EAAA,OAAA,EAAA,CAAA;AAC/C;;;;"}
1
+ {"version":3,"file":"compatWrapper.esm.js","sources":["../../src/compatWrapper/compatWrapper.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 { useVersionedContext } from '@backstage/version-bridge';\nimport { ReactNode } from 'react';\nimport { BackwardsCompatProvider } from './BackwardsCompatProvider';\nimport { ForwardsCompatProvider } from './ForwardsCompatProvider';\n\nfunction BidirectionalCompatProvider(props: { children: ReactNode }) {\n const isInNewApp = !useVersionedContext<{ 1: unknown }>('app-context');\n\n if (isInNewApp) {\n return <BackwardsCompatProvider {...props} />;\n }\n\n return <ForwardsCompatProvider {...props} />;\n}\n\n/**\n * Wraps a React element in a bidirectional compatibility provider, allow APIs\n * from `@backstage/core-plugin-api` to be used in an app from `@backstage/frontend-app-api`,\n * and APIs from `@backstage/frontend-plugin-api` to be used in an app from `@backstage/core-app-api`.\n *\n * @public\n */\nexport function compatWrapper(element: ReactNode) {\n return <BidirectionalCompatProvider>{element}</BidirectionalCompatProvider>;\n}\n"],"names":[],"mappings":";;;;;AAqBA,SAAS,4BAA4B,KAAA,EAAgC;AACnE,EAAA,MAAM,UAAA,GAAa,CAAC,mBAAA,CAAoC,aAAa,CAAA;AAErE,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,uBAAO,GAAA,CAAC,uBAAA,EAAA,EAAyB,GAAG,KAAA,EAAO,CAAA;AAAA,EAC7C;AAEA,EAAA,uBAAO,GAAA,CAAC,sBAAA,EAAA,EAAwB,GAAG,KAAA,EAAO,CAAA;AAC5C;AASO,SAAS,cAAc,OAAA,EAAoB;AAChD,EAAA,uBAAO,GAAA,CAAC,+BAA6B,QAAA,EAAA,OAAA,EAAQ,CAAA;AAC/C;;;;"}
@@ -1,5 +1,5 @@
1
1
  import { cloneElement, Children, isValidElement, Fragment } from 'react';
2
- import { createExtension, createExtensionInput, coreExtensionData, createFrontendModule } from '@backstage/frontend-plugin-api';
2
+ import { createExtension, coreExtensionData, createExtensionInput, createFrontendModule } from '@backstage/frontend-plugin-api';
3
3
  import { getComponentData } from '@backstage/core-plugin-api';
4
4
  import { collectLegacyRoutes } from './collectLegacyRoutes.esm.js';
5
5
  import { compatWrapper } from './compatWrapper/compatWrapper.esm.js';
@@ -18,7 +18,7 @@ function selectChildren(rootNode, selector, strictError) {
18
18
  return selectChildren(node.props.children, selector);
19
19
  });
20
20
  }
21
- function convertLegacyApp(rootElement, options = {}) {
21
+ function convertLegacyAppRoot(rootElement, options = {}) {
22
22
  if (getComponentData(rootElement, "core.type") === "FlatRoutes") {
23
23
  return collectLegacyRoutes(rootElement, options?.entityPage);
24
24
  }
@@ -93,6 +93,7 @@ function convertLegacyApp(rootElement, options = {}) {
93
93
  })
94
94
  ];
95
95
  }
96
+ const convertLegacyApp = convertLegacyAppRoot;
96
97
 
97
- export { convertLegacyApp };
98
+ export { convertLegacyApp, convertLegacyAppRoot };
98
99
  //# sourceMappingURL=convertLegacyApp.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"convertLegacyApp.esm.js","sources":["../src/convertLegacyApp.ts"],"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 JSX,\n cloneElement,\n Children,\n Fragment,\n ReactElement,\n ReactNode,\n isValidElement,\n} from 'react';\nimport {\n FrontendModule,\n FrontendPlugin,\n coreExtensionData,\n createExtension,\n createExtensionInput,\n createFrontendModule,\n} from '@backstage/frontend-plugin-api';\nimport { getComponentData } from '@backstage/core-plugin-api';\nimport { collectLegacyRoutes } from './collectLegacyRoutes';\nimport { compatWrapper } from './compatWrapper';\n\nfunction selectChildren(\n rootNode: ReactNode,\n selector?: (element: ReactElement<{ children?: ReactNode }>) => boolean,\n strictError?: string,\n): Array<ReactElement<{ children?: ReactNode }>> {\n return Children.toArray(rootNode).flatMap(node => {\n if (!isValidElement<{ children?: ReactNode }>(node)) {\n return [];\n }\n\n if (node.type === Fragment) {\n return selectChildren(node.props.children, selector, strictError);\n }\n\n if (selector === undefined || selector(node)) {\n return [node];\n }\n\n if (strictError) {\n throw new Error(strictError);\n }\n\n return selectChildren(node.props.children, selector, strictError);\n });\n}\n\n/** @public */\nexport interface ConvertLegacyAppOptions {\n /**\n * By providing an entity page element here it will be split up and converted\n * into individual extensions for the catalog plugin in the new frontend\n * system.\n *\n * In order to use this option the entity page and other catalog extensions\n * must be removed from the legacy app, and the catalog plugin for the new\n * frontend system must be installed instead.\n *\n * In order for this conversion to work the entity page must be a plain React\n * element tree without any component wrapping anywhere between the root\n * element and the `EntityLayout.Route` elements.\n *\n * When enabling this conversion you are likely to encounter duplicate entity\n * page content provided both via the old structure and the new plugins. Any\n * duplicate content needs to be removed from the old structure.\n */\n entityPage?: JSX.Element;\n}\n\n/** @public */\nexport function convertLegacyApp(\n rootElement: JSX.Element,\n options: ConvertLegacyAppOptions = {},\n): (FrontendPlugin | FrontendModule)[] {\n if (getComponentData(rootElement, 'core.type') === 'FlatRoutes') {\n return collectLegacyRoutes(rootElement, options?.entityPage);\n }\n\n const appRouterEls = selectChildren(\n rootElement,\n el => getComponentData(el, 'core.type') === 'AppRouter',\n );\n if (appRouterEls.length !== 1) {\n throw new Error(\n \"Failed to convert legacy app, AppRouter element could not been found. Make sure it's at the top level of the App element tree\",\n );\n }\n\n const rootEls = selectChildren(\n appRouterEls[0].props.children,\n el =>\n Boolean(el.props.children) &&\n selectChildren(\n el.props.children,\n innerEl => getComponentData(innerEl, 'core.type') === 'FlatRoutes',\n ).length === 1,\n );\n if (rootEls.length !== 1) {\n throw new Error(\n \"Failed to convert legacy app, Root element containing FlatRoutes could not been found. Make sure it's within the AppRouter element of the App element tree\",\n );\n }\n const [rootEl] = rootEls;\n\n const routesEls = selectChildren(\n rootEls[0].props.children,\n el => getComponentData(el, 'core.type') === 'FlatRoutes',\n );\n if (routesEls.length !== 1) {\n throw new Error(\n 'Unexpectedly failed to find FlatRoutes in app element tree',\n );\n }\n const [routesEl] = routesEls;\n\n const CoreLayoutOverride = createExtension({\n name: 'layout',\n attachTo: { id: 'app/root', input: 'children' },\n inputs: {\n content: createExtensionInput([coreExtensionData.reactElement], {\n singleton: true,\n }),\n },\n output: [coreExtensionData.reactElement],\n factory({ inputs }) {\n // Clone the root element, this replaces the FlatRoutes declared in the app with out content input\n return [\n coreExtensionData.reactElement(\n compatWrapper(\n cloneElement(\n rootEl,\n undefined,\n inputs.content.get(coreExtensionData.reactElement),\n ),\n ),\n ),\n ];\n },\n });\n const CoreNavOverride = createExtension({\n name: 'nav',\n attachTo: { id: 'app/layout', input: 'nav' },\n output: [],\n factory: () => [],\n disabled: true,\n });\n\n const collectedRoutes = collectLegacyRoutes(routesEl, options?.entityPage);\n\n return [\n ...collectedRoutes,\n createFrontendModule({\n pluginId: 'app',\n extensions: [CoreLayoutOverride, CoreNavOverride],\n }),\n ];\n}\n"],"names":[],"mappings":";;;;;;AAqCA,SAAS,cAAA,CACP,QACA,EAAA,QAAA,EACA,WAC+C,EAAA;AAC/C,EAAA,OAAO,QAAS,CAAA,OAAA,CAAQ,QAAQ,CAAA,CAAE,QAAQ,CAAQ,IAAA,KAAA;AAChD,IAAI,IAAA,CAAC,cAAyC,CAAA,IAAI,CAAG,EAAA;AACnD,MAAA,OAAO,EAAC;AAAA;AAGV,IAAI,IAAA,IAAA,CAAK,SAAS,QAAU,EAAA;AAC1B,MAAA,OAAO,cAAe,CAAA,IAAA,CAAK,KAAM,CAAA,QAAA,EAAU,QAAqB,CAAA;AAAA;AAGlE,IAAA,IAAI,QAAa,KAAA,KAAA,CAAA,IAAa,QAAS,CAAA,IAAI,CAAG,EAAA;AAC5C,MAAA,OAAO,CAAC,IAAI,CAAA;AAAA;AAOd,IAAA,OAAO,cAAe,CAAA,IAAA,CAAK,KAAM,CAAA,QAAA,EAAU,QAAqB,CAAA;AAAA,GACjE,CAAA;AACH;AAyBO,SAAS,gBACd,CAAA,WAAA,EACA,OAAmC,GAAA,EACE,EAAA;AACrC,EAAA,IAAI,gBAAiB,CAAA,WAAA,EAAa,WAAW,CAAA,KAAM,YAAc,EAAA;AAC/D,IAAO,OAAA,mBAAA,CAAoB,WAAa,EAAA,OAAA,EAAS,UAAU,CAAA;AAAA;AAG7D,EAAA,MAAM,YAAe,GAAA,cAAA;AAAA,IACnB,WAAA;AAAA,IACA,CAAM,EAAA,KAAA,gBAAA,CAAiB,EAAI,EAAA,WAAW,CAAM,KAAA;AAAA,GAC9C;AACA,EAAI,IAAA,YAAA,CAAa,WAAW,CAAG,EAAA;AAC7B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA;AAGF,EAAA,MAAM,OAAU,GAAA,cAAA;AAAA,IACd,YAAA,CAAa,CAAC,CAAA,CAAE,KAAM,CAAA,QAAA;AAAA,IACtB,CACE,EAAA,KAAA,OAAA,CAAQ,EAAG,CAAA,KAAA,CAAM,QAAQ,CACzB,IAAA,cAAA;AAAA,MACE,GAAG,KAAM,CAAA,QAAA;AAAA,MACT,CAAW,OAAA,KAAA,gBAAA,CAAiB,OAAS,EAAA,WAAW,CAAM,KAAA;AAAA,MACtD,MAAW,KAAA;AAAA,GACjB;AACA,EAAI,IAAA,OAAA,CAAQ,WAAW,CAAG,EAAA;AACxB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA;AAEF,EAAM,MAAA,CAAC,MAAM,CAAI,GAAA,OAAA;AAEjB,EAAA,MAAM,SAAY,GAAA,cAAA;AAAA,IAChB,OAAA,CAAQ,CAAC,CAAA,CAAE,KAAM,CAAA,QAAA;AAAA,IACjB,CAAM,EAAA,KAAA,gBAAA,CAAiB,EAAI,EAAA,WAAW,CAAM,KAAA;AAAA,GAC9C;AACA,EAAI,IAAA,SAAA,CAAU,WAAW,CAAG,EAAA;AAC1B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA;AAEF,EAAM,MAAA,CAAC,QAAQ,CAAI,GAAA,SAAA;AAEnB,EAAA,MAAM,qBAAqB,eAAgB,CAAA;AAAA,IACzC,IAAM,EAAA,QAAA;AAAA,IACN,QAAU,EAAA,EAAE,EAAI,EAAA,UAAA,EAAY,OAAO,UAAW,EAAA;AAAA,IAC9C,MAAQ,EAAA;AAAA,MACN,OAAS,EAAA,oBAAA,CAAqB,CAAC,iBAAA,CAAkB,YAAY,CAAG,EAAA;AAAA,QAC9D,SAAW,EAAA;AAAA,OACZ;AAAA,KACH;AAAA,IACA,MAAA,EAAQ,CAAC,iBAAA,CAAkB,YAAY,CAAA;AAAA,IACvC,OAAA,CAAQ,EAAE,MAAA,EAAU,EAAA;AAElB,MAAO,OAAA;AAAA,QACL,iBAAkB,CAAA,YAAA;AAAA,UAChB,aAAA;AAAA,YACE,YAAA;AAAA,cACE,MAAA;AAAA,cACA,KAAA,CAAA;AAAA,cACA,MAAO,CAAA,OAAA,CAAQ,GAAI,CAAA,iBAAA,CAAkB,YAAY;AAAA;AACnD;AACF;AACF,OACF;AAAA;AACF,GACD,CAAA;AACD,EAAA,MAAM,kBAAkB,eAAgB,CAAA;AAAA,IACtC,IAAM,EAAA,KAAA;AAAA,IACN,QAAU,EAAA,EAAE,EAAI,EAAA,YAAA,EAAc,OAAO,KAAM,EAAA;AAAA,IAC3C,QAAQ,EAAC;AAAA,IACT,OAAA,EAAS,MAAM,EAAC;AAAA,IAChB,QAAU,EAAA;AAAA,GACX,CAAA;AAED,EAAA,MAAM,eAAkB,GAAA,mBAAA,CAAoB,QAAU,EAAA,OAAA,EAAS,UAAU,CAAA;AAEzE,EAAO,OAAA;AAAA,IACL,GAAG,eAAA;AAAA,IACH,oBAAqB,CAAA;AAAA,MACnB,QAAU,EAAA,KAAA;AAAA,MACV,UAAA,EAAY,CAAC,kBAAA,EAAoB,eAAe;AAAA,KACjD;AAAA,GACH;AACF;;;;"}
1
+ {"version":3,"file":"convertLegacyApp.esm.js","sources":["../src/convertLegacyApp.ts"],"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 JSX,\n cloneElement,\n Children,\n Fragment,\n ReactElement,\n ReactNode,\n isValidElement,\n} from 'react';\nimport {\n FrontendModule,\n FrontendPlugin,\n coreExtensionData,\n createExtension,\n createExtensionInput,\n createFrontendModule,\n} from '@backstage/frontend-plugin-api';\nimport { getComponentData } from '@backstage/core-plugin-api';\nimport { collectLegacyRoutes } from './collectLegacyRoutes';\nimport { compatWrapper } from './compatWrapper';\n\nfunction selectChildren(\n rootNode: ReactNode,\n selector?: (element: ReactElement<{ children?: ReactNode }>) => boolean,\n strictError?: string,\n): Array<ReactElement<{ children?: ReactNode }>> {\n return Children.toArray(rootNode).flatMap(node => {\n if (!isValidElement<{ children?: ReactNode }>(node)) {\n return [];\n }\n\n if (node.type === Fragment) {\n return selectChildren(node.props.children, selector, strictError);\n }\n\n if (selector === undefined || selector(node)) {\n return [node];\n }\n\n if (strictError) {\n throw new Error(strictError);\n }\n\n return selectChildren(node.props.children, selector, strictError);\n });\n}\n\n/** @public */\nexport interface ConvertLegacyAppRootOptions {\n /**\n * By providing an entity page element here it will be split up and converted\n * into individual extensions for the catalog plugin in the new frontend\n * system.\n *\n * In order to use this option the entity page and other catalog extensions\n * must be removed from the legacy app, and the catalog plugin for the new\n * frontend system must be installed instead.\n *\n * In order for this conversion to work the entity page must be a plain React\n * element tree without any component wrapping anywhere between the root\n * element and the `EntityLayout.Route` elements.\n *\n * When enabling this conversion you are likely to encounter duplicate entity\n * page content provided both via the old structure and the new plugins. Any\n * duplicate content needs to be removed from the old structure.\n */\n entityPage?: JSX.Element;\n}\n\n/** @public */\nexport function convertLegacyAppRoot(\n rootElement: JSX.Element,\n options: ConvertLegacyAppRootOptions = {},\n): (FrontendPlugin | FrontendModule)[] {\n if (getComponentData(rootElement, 'core.type') === 'FlatRoutes') {\n return collectLegacyRoutes(rootElement, options?.entityPage);\n }\n\n const appRouterEls = selectChildren(\n rootElement,\n el => getComponentData(el, 'core.type') === 'AppRouter',\n );\n if (appRouterEls.length !== 1) {\n throw new Error(\n \"Failed to convert legacy app, AppRouter element could not been found. Make sure it's at the top level of the App element tree\",\n );\n }\n\n const rootEls = selectChildren(\n appRouterEls[0].props.children,\n el =>\n Boolean(el.props.children) &&\n selectChildren(\n el.props.children,\n innerEl => getComponentData(innerEl, 'core.type') === 'FlatRoutes',\n ).length === 1,\n );\n if (rootEls.length !== 1) {\n throw new Error(\n \"Failed to convert legacy app, Root element containing FlatRoutes could not been found. Make sure it's within the AppRouter element of the App element tree\",\n );\n }\n const [rootEl] = rootEls;\n\n const routesEls = selectChildren(\n rootEls[0].props.children,\n el => getComponentData(el, 'core.type') === 'FlatRoutes',\n );\n if (routesEls.length !== 1) {\n throw new Error(\n 'Unexpectedly failed to find FlatRoutes in app element tree',\n );\n }\n const [routesEl] = routesEls;\n\n const CoreLayoutOverride = createExtension({\n name: 'layout',\n attachTo: { id: 'app/root', input: 'children' },\n inputs: {\n content: createExtensionInput([coreExtensionData.reactElement], {\n singleton: true,\n }),\n },\n output: [coreExtensionData.reactElement],\n factory({ inputs }) {\n // Clone the root element, this replaces the FlatRoutes declared in the app with out content input\n return [\n coreExtensionData.reactElement(\n compatWrapper(\n cloneElement(\n rootEl,\n undefined,\n inputs.content.get(coreExtensionData.reactElement),\n ),\n ),\n ),\n ];\n },\n });\n const CoreNavOverride = createExtension({\n name: 'nav',\n attachTo: { id: 'app/layout', input: 'nav' },\n output: [],\n factory: () => [],\n disabled: true,\n });\n\n const collectedRoutes = collectLegacyRoutes(routesEl, options?.entityPage);\n\n return [\n ...collectedRoutes,\n createFrontendModule({\n pluginId: 'app',\n extensions: [CoreLayoutOverride, CoreNavOverride],\n }),\n ];\n}\n\n/**\n * @public\n * @deprecated\n * Use `convertLegacyAppRoot` instead.\n */\nexport const convertLegacyApp = convertLegacyAppRoot;\n\n/**\n * @public\n * @deprecated\n * Use `ConvertLegacyAppRootOptions` instead.\n */\nexport type ConvertLegacyAppOptions = ConvertLegacyAppRootOptions;\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { ApiBlueprint, IconBundleBlueprint, createExtension, ThemeBlueprint, RouterBlueprint, SignInPageBlueprint, createComponentExtension, coreComponentRefs, createFrontendModule } from '@backstage/frontend-plugin-api';
2
+ import { ApiBlueprint, IconBundleBlueprint, createExtension, ThemeBlueprint, RouterBlueprint, SignInPageBlueprint, SwappableComponentBlueprint, Progress, NotFoundErrorPage, ErrorDisplay, createFrontendModule } from '@backstage/frontend-plugin-api';
3
3
  import { toLegacyPlugin } from './compatWrapper/BackwardsCompatProvider.esm.js';
4
4
  import { compatWrapper } from './compatWrapper/compatWrapper.esm.js';
5
5
 
@@ -57,8 +57,8 @@ function convertLegacyAppOptions(options = {}) {
57
57
  const {
58
58
  BootErrorPage,
59
59
  ErrorBoundaryFallback,
60
- NotFoundErrorPage,
61
- Progress,
60
+ NotFoundErrorPage: NotFoundErrorPage$1,
61
+ Progress: Progress$1,
62
62
  Router,
63
63
  SignInPage,
64
64
  ThemeProvider
@@ -89,19 +89,23 @@ function convertLegacyAppOptions(options = {}) {
89
89
  })
90
90
  );
91
91
  }
92
- if (Progress) {
92
+ if (Progress$1) {
93
93
  extensions.push(
94
- createComponentExtension({
95
- ref: coreComponentRefs.progress,
96
- loader: { sync: () => componentCompatWrapper(Progress) }
94
+ SwappableComponentBlueprint.make({
95
+ params: (define) => define({
96
+ component: Progress,
97
+ loader: () => componentCompatWrapper(Progress$1)
98
+ })
97
99
  })
98
100
  );
99
101
  }
100
- if (NotFoundErrorPage) {
102
+ if (NotFoundErrorPage$1) {
101
103
  extensions.push(
102
- createComponentExtension({
103
- ref: coreComponentRefs.notFoundErrorPage,
104
- loader: { sync: () => componentCompatWrapper(NotFoundErrorPage) }
104
+ SwappableComponentBlueprint.make({
105
+ params: (define) => define({
106
+ component: NotFoundErrorPage,
107
+ loader: () => componentCompatWrapper(NotFoundErrorPage$1)
108
+ })
105
109
  })
106
110
  );
107
111
  }
@@ -116,11 +120,11 @@ function convertLegacyAppOptions(options = {}) {
116
120
  )
117
121
  );
118
122
  extensions.push(
119
- createComponentExtension({
120
- ref: coreComponentRefs.errorBoundaryFallback,
121
- loader: {
122
- sync: () => componentCompatWrapper(WrappedErrorBoundaryFallback)
123
- }
123
+ SwappableComponentBlueprint.make({
124
+ params: (define) => define({
125
+ component: ErrorDisplay,
126
+ loader: () => componentCompatWrapper(WrappedErrorBoundaryFallback)
127
+ })
124
128
  })
125
129
  );
126
130
  }
@@ -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: 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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"}
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 SwappableComponentBlueprint,\n ApiBlueprint,\n ErrorDisplayProps,\n createExtension,\n createFrontendModule,\n ExtensionDefinition,\n FrontendModule,\n IconBundleBlueprint,\n RouterBlueprint,\n SignInPageBlueprint,\n ThemeBlueprint,\n ErrorDisplay as SwappableErrorDisplay,\n NotFoundErrorPage as SwappableNotFoundErrorPage,\n Progress as SwappableProgress,\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 SwappableComponentBlueprint.make({\n params: define =>\n define({\n component: SwappableProgress,\n loader: () => componentCompatWrapper(Progress),\n }),\n }),\n );\n }\n\n if (NotFoundErrorPage) {\n extensions.push(\n SwappableComponentBlueprint.make({\n params: define =>\n define({\n component: SwappableNotFoundErrorPage,\n loader: () => componentCompatWrapper(NotFoundErrorPage),\n }),\n }),\n );\n }\n\n if (ErrorBoundaryFallback) {\n const WrappedErrorBoundaryFallback = (props: ErrorDisplayProps) =>\n compatWrapper(\n <ErrorBoundaryFallback\n {...props}\n plugin={props.plugin && toLegacyPlugin(props.plugin)}\n />,\n );\n\n extensions.push(\n SwappableComponentBlueprint.make({\n params: define =>\n define({\n component: SwappableErrorDisplay,\n loader: () =>\n componentCompatWrapper(WrappedErrorBoundaryFallback),\n }),\n }),\n );\n }\n }\n\n return createFrontendModule({\n pluginId: 'app',\n extensions,\n featureFlags,\n });\n}\n"],"names":["NotFoundErrorPage","Progress","SwappableProgress","SwappableNotFoundErrorPage","SwappableErrorDisplay"],"mappings":";;;;;AA4CA,SAAS,uBACP,SAAA,EACA;AACA,EAAA,OAAO,CAAC,KAAA,KAAkB,aAAA,qBAAe,SAAA,EAAA,EAAW,GAAG,OAAO,CAAE,CAAA;AAClE;AAKO,SAAS,uBAAA,CACd,OAAA,GAYI,EAAC,EACW;AAChB,EAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAO,SAAS,UAAA,EAAY,MAAA,EAAQ,cAAa,GAAI,OAAA;AAEnE,EAAA,MAAM,OAAA,GAAU;AAAA,IACd,GAAI,OAAA,EAAS,OAAA,CAAQ,CAAA,MAAA,KAAU,CAAC,GAAG,MAAA,CAAO,OAAA,EAAS,CAAC,CAAA,IAAK,EAAC;AAAA,IAC1D,GAAI,QAAQ;AAAC,GACf;AACA,EAAA,MAAM,mBAAmB,KAAA,CAAM,IAAA;AAAA,IAC7B,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,CAAA,GAAA,KAAO,CAAC,GAAA,CAAI,GAAA,CAAI,EAAA,EAAI,GAAG,CAAC,CAAC,EAAE,MAAA;AAAO,GACxD;AACA,EAAA,MAAM,aAAoC,gBAAA,CAAiB,GAAA;AAAA,IAAI,CAAA,OAAA,KAC7D,aAAa,IAAA,CAAK;AAAA,MAChB,IAAA,EAAM,QAAQ,GAAA,CAAI,EAAA;AAAA,MAClB,MAAA,EAAQ,CAAA,YAAA,KAAgB,YAAA,CAAa,OAAO;AAAA,KAC7C;AAAA,GACH;AAEA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,UAAA,CAAW,IAAA;AAAA,MACT,oBAAoB,IAAA,CAAK;AAAA,QACvB,IAAA,EAAM,aAAA;AAAA,QACN,MAAA,EAAQ,EAAE,KAAA;AAAM,OACjB;AAAA,KACH;AAAA,EACF;AAEA,EAAA,IAAI,MAAA,EAAQ;AAEV,IAAA,KAAA,MAAW,EAAA,IAAM,CAAC,OAAA,EAAS,MAAM,CAAA,EAAG;AAClC,MAAA,IAAI,CAAC,MAAA,CAAO,IAAA,CAAK,WAAS,KAAA,CAAM,EAAA,KAAO,EAAE,CAAA,EAAG;AAC1C,QAAA,UAAA,CAAW,IAAA;AAAA,UACT,eAAA,CAAgB;AAAA,YACd,IAAA,EAAM,OAAA;AAAA,YACN,IAAA,EAAM,EAAA;AAAA,YACN,QAAA,EAAU,EAAE,EAAA,EAAI,mBAAA,EAAqB,OAAO,QAAA,EAAS;AAAA,YACrD,QAAA,EAAU,IAAA;AAAA,YACV,QAAQ,EAAC;AAAA,YACT,OAAA,EAAS,MAAM;AAAC,WACjB;AAAA,SACH;AAAA,MACF;AAAA,IACF;AACA,IAAA,UAAA,CAAW,IAAA;AAAA,MACT,GAAG,MAAA,CAAO,GAAA;AAAA,QAAI,CAAA,KAAA,KACZ,eAAe,IAAA,CAAK;AAAA,UAClB,MAAM,KAAA,CAAM,EAAA;AAAA,UACZ,MAAA,EAAQ,EAAE,KAAA;AAAM,SACjB;AAAA;AACH,KACF;AAAA,EACF;AAEA,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,MAAM;AAAA,MACJ,aAAA;AAAA,MACA,qBAAA;AAAA,yBACAA,mBAAA;AAAA,gBACAC,UAAA;AAAA,MACA,MAAA;AAAA,MACA,UAAA;AAAA,MACA;AAAA,KACF,GAAI,UAAA;AAEJ,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,UAAA,CAAW,IAAA;AAAA,QACT,gBAAgB,IAAA,CAAK;AAAA,UACnB,MAAA,EAAQ,EAAE,SAAA,EAAW,sBAAA,CAAuB,MAAM,CAAA;AAAE,SACrD;AAAA,OACH;AAAA,IACF;AACA,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,UAAA,CAAW,IAAA;AAAA,QACT,oBAAoB,IAAA,CAAK;AAAA,UACvB,MAAA,EAAQ;AAAA,YACN,QAAQ,MAAM,OAAA,CAAQ,OAAA,CAAQ,sBAAA,CAAuB,UAAU,CAAC;AAAA;AAClE,SACD;AAAA,OACH;AAAA,IACF;AACA,IAAA,IAAIA,UAAA,EAAU;AACZ,MAAA,UAAA,CAAW,IAAA;AAAA,QACT,4BAA4B,IAAA,CAAK;AAAA,UAC/B,MAAA,EAAQ,YACN,MAAA,CAAO;AAAA,YACL,SAAA,EAAWC,QAAA;AAAA,YACX,MAAA,EAAQ,MAAM,sBAAA,CAAuBD,UAAQ;AAAA,WAC9C;AAAA,SACJ;AAAA,OACH;AAAA,IACF;AAEA,IAAA,IAAID,mBAAA,EAAmB;AACrB,MAAA,UAAA,CAAW,IAAA;AAAA,QACT,4BAA4B,IAAA,CAAK;AAAA,UAC/B,MAAA,EAAQ,YACN,MAAA,CAAO;AAAA,YACL,SAAA,EAAWG,iBAAA;AAAA,YACX,MAAA,EAAQ,MAAM,sBAAA,CAAuBH,mBAAiB;AAAA,WACvD;AAAA,SACJ;AAAA,OACH;AAAA,IACF;AAEA,IAAA,IAAI,qBAAA,EAAuB;AACzB,MAAA,MAAM,4BAAA,GAA+B,CAAC,KAAA,KACpC,aAAA;AAAA,wBACE,GAAA;AAAA,UAAC,qBAAA;AAAA,UAAA;AAAA,YACE,GAAG,KAAA;AAAA,YACJ,MAAA,EAAQ,KAAA,CAAM,MAAA,IAAU,cAAA,CAAe,MAAM,MAAM;AAAA;AAAA;AACrD,OACF;AAEF,MAAA,UAAA,CAAW,IAAA;AAAA,QACT,4BAA4B,IAAA,CAAK;AAAA,UAC/B,MAAA,EAAQ,YACN,MAAA,CAAO;AAAA,YACL,SAAA,EAAWI,YAAA;AAAA,YACX,MAAA,EAAQ,MACN,sBAAA,CAAuB,4BAA4B;AAAA,WACtD;AAAA,SACJ;AAAA,OACH;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,oBAAA,CAAqB;AAAA,IAC1B,QAAA,EAAU,KAAA;AAAA,IACV,UAAA;AAAA,IACA;AAAA,GACD,CAAA;AACH;;;;"}
@@ -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 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;;;;"}
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":";;;;;;;AA8BO,SAAS,0BAAA,CACd,iBACA,SAAA,EAQqB;AACrB,EAAA,MAAM,OAAA,uBAAW,eAAA,EAAA,EAAgB,CAAA;AAEjC,EAAA,MAAM,OAAA,GAAU,gBAAA,CAAyB,OAAA,EAAS,oBAAoB,CAAA;AACtE,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,MAAM,uBAAuB,CAAA;AAAA,EACzC;AAEA,EAAA,MAAM,UAAA,GAAa,gBAAA;AAAA,IACjB,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,QAAA,CAAS,MAAM,CAAA,GAChC,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,CAAC,MAAA,CAAO,MAAM,CAAA,GAC/B,OAAA;AACJ,EAAA,MAAM,SAAA,GAAY,UAAU,IAAI,CAAA;AAEhC,EAAA,OAAO,cAAc,IAAA,CAAK;AAAA,IACxB,IAAA,EAAM,WAAW,IAAA,IAAQ,SAAA;AAAA,IACzB,MAAA,EAAQ;AAAA,MACN,IAAA,EAAM,SAAA,EAAW,IAAA,IAAQ,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA;AAAA,MACtC,QAAA,EAAU,UAAA,IAAc,qBAAA,CAAsB,UAAU,CAAA;AAAA,MACxD,MAAA,EAAQ,YAAY,aAAA,CAAc,OAAO;AAAA;AAC3C,GACD,CAAA;AACH;;;;"}
@@ -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: 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
+ {"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":";;;AA0BO,SAAS,mBAAA,CACd,cACA,OAAA,EACoB;AACpB,EAAA,MAAM,gBAAgB,KAAA,CAAM,IAAA,CAAK,YAAA,CAAa,OAAA,EAAS,CAAA,CAAE,GAAA;AAAA,IAAI,CAAA,OAAA,KAC3D,aAAa,IAAA,CAAK;AAAA,MAChB,IAAA,EAAM,QAAQ,GAAA,CAAI,EAAA;AAAA,MAClB,MAAA,EAAQ,CAAA,YAAA,KAAgB,YAAA,CAAa,OAAO;AAAA,KAC7C;AAAA,GACH;AACA,EAAA,OAAO,oBAAA,CAAqB;AAAA,IAC1B,QAAA,EAAU,aAAa,KAAA,EAAM;AAAA,IAC7B,YAAA,EAAc,CAAC,GAAG,YAAA,CAAa,iBAAiB,CAAA;AAAA,IAChD,MAAA,EAAQ,sBAAA,CAAuB,YAAA,CAAa,MAAA,IAAU,EAAE,CAAA;AAAA,IACxD,cAAA,EAAgB,sBAAA,CAAuB,YAAA,CAAa,cAAA,IAAkB,EAAE,CAAA;AAAA,IACxE,YAAY,CAAC,GAAG,aAAA,EAAe,GAAG,QAAQ,UAAU;AAAA,GACrD,CAAA;AACH;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"convertLegacyRouteRef.esm.js","sources":["../src/convertLegacyRouteRef.ts"],"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 RouteRef as LegacyRouteRef,\n SubRouteRef as LegacySubRouteRef,\n ExternalRouteRef as LegacyExternalRouteRef,\n AnyRouteRefParams,\n} from '@backstage/core-plugin-api';\n\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { routeRefType } from '../../core-plugin-api/src/routing/types';\n\nimport {\n RouteRef,\n SubRouteRef,\n ExternalRouteRef,\n createRouteRef,\n createSubRouteRef,\n createExternalRouteRef,\n} from '@backstage/frontend-plugin-api';\n\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalRouteRef } from '../../frontend-plugin-api/src/routing/RouteRef';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalSubRouteRef } from '../../frontend-plugin-api/src/routing/SubRouteRef';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalExternalRouteRef } from '../../frontend-plugin-api/src/routing/ExternalRouteRef';\n\n/**\n * Converts a legacy route ref type to the new system.\n *\n * @public\n */\nexport type ToNewRouteRef<\n T extends LegacyRouteRef | LegacySubRouteRef | LegacyExternalRouteRef,\n> = T extends LegacyRouteRef<infer IParams>\n ? RouteRef<IParams>\n : T extends LegacySubRouteRef<infer IParams>\n ? SubRouteRef<IParams>\n : T extends LegacyExternalRouteRef<infer IParams>\n ? ExternalRouteRef<IParams>\n : never;\n\n/**\n * Converts a collection of legacy route refs to the new system.\n * This is particularly useful when defining plugin `routes` and `externalRoutes`.\n *\n * @public\n */\nexport function convertLegacyRouteRefs<\n TRefs extends {\n [name in string]:\n | LegacyRouteRef\n | LegacySubRouteRef\n | LegacyExternalRouteRef;\n },\n>(refs: TRefs): { [KName in keyof TRefs]: ToNewRouteRef<TRefs[KName]> } {\n return Object.fromEntries(\n Object.entries(refs).map(([name, ref]) => [\n name,\n convertLegacyRouteRef(ref as LegacyRouteRef),\n ]),\n ) as { [KName in keyof TRefs]: ToNewRouteRef<TRefs[KName]> };\n}\n\n/**\n * A temporary helper to convert a legacy route ref to the new system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(\n ref: LegacyRouteRef<TParams>,\n): RouteRef<TParams>;\n\n/**\n * A temporary helper to convert a legacy sub route ref to the new system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createSubRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(\n ref: LegacySubRouteRef<TParams>,\n): SubRouteRef<TParams>;\n\n/**\n * A temporary helper to convert a legacy external route ref to the new system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createExternalRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(\n ref: LegacyExternalRouteRef<TParams>,\n): ExternalRouteRef<TParams>;\n\n/**\n * A temporary helper to convert a new route ref to the legacy system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(\n ref: RouteRef<TParams>,\n): LegacyRouteRef<TParams>;\n\n/**\n * A temporary helper to convert a new sub route ref to the legacy system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createSubRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(\n ref: SubRouteRef<TParams>,\n): LegacySubRouteRef<TParams>;\n\n/**\n * A temporary helper to convert a new external route ref to the legacy system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createExternalRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(\n ref: ExternalRouteRef<TParams>,\n): LegacyExternalRouteRef<TParams, true>;\nexport function convertLegacyRouteRef(\n ref:\n | LegacyRouteRef\n | LegacySubRouteRef\n | LegacyExternalRouteRef\n | RouteRef\n | SubRouteRef\n | ExternalRouteRef,\n):\n | RouteRef\n | SubRouteRef\n | ExternalRouteRef\n | LegacyRouteRef\n | LegacySubRouteRef\n | LegacyExternalRouteRef {\n const isNew = '$$type' in ref;\n const oldType = (ref as unknown as { [routeRefType]: unknown })[routeRefType];\n\n // Ref has already been converted\n if (isNew && oldType) {\n return ref as any;\n }\n\n if (isNew) {\n return convertNewToOld(\n ref as unknown as RouteRef | SubRouteRef | ExternalRouteRef,\n );\n }\n\n return convertOldToNew(ref, oldType);\n}\n\nfunction convertNewToOld(\n ref: RouteRef | SubRouteRef | ExternalRouteRef,\n): LegacyRouteRef | LegacySubRouteRef | LegacyExternalRouteRef {\n if (ref.$$type === '@backstage/RouteRef') {\n const newRef = toInternalRouteRef(ref);\n return Object.assign(ref, {\n [routeRefType]: 'absolute',\n params: newRef.getParams(),\n title: newRef.getDescription(),\n } as Omit<LegacyRouteRef, '$$routeRefType'>) as unknown as LegacyRouteRef;\n }\n if (ref.$$type === '@backstage/SubRouteRef') {\n const newRef = toInternalSubRouteRef(ref);\n return Object.assign(ref, {\n [routeRefType]: 'sub',\n parent: convertLegacyRouteRef(newRef.getParent()),\n params: newRef.getParams(),\n } as Omit<LegacySubRouteRef, '$$routeRefType' | 'path'>) as unknown as LegacySubRouteRef;\n }\n if (ref.$$type === '@backstage/ExternalRouteRef') {\n const newRef = toInternalExternalRouteRef(ref);\n return Object.assign(ref, {\n [routeRefType]: 'external',\n optional: true,\n params: newRef.getParams(),\n defaultTarget: newRef.getDefaultTarget(),\n } as Omit<LegacyExternalRouteRef, '$$routeRefType' | 'optional'>) as unknown as LegacyExternalRouteRef;\n }\n\n throw new Error(\n `Failed to convert route ref, unknown type '${(ref as any).$$type}'`,\n );\n}\n\nfunction convertOldToNew(\n ref: LegacyRouteRef | LegacySubRouteRef | LegacyExternalRouteRef,\n type: unknown,\n): RouteRef | SubRouteRef | ExternalRouteRef {\n if (type === 'absolute') {\n const legacyRef = ref as LegacyRouteRef;\n const legacyRefStr = String(legacyRef);\n const newRef = toInternalRouteRef(\n createRouteRef<{ [key in string]: string }>({\n params: legacyRef.params as string[],\n }),\n );\n return Object.assign(legacyRef, {\n $$type: '@backstage/RouteRef' as const,\n version: 'v1',\n T: newRef.T,\n getParams() {\n return newRef.getParams();\n },\n getDescription() {\n return legacyRefStr;\n },\n setId(id: string) {\n newRef.setId(id);\n },\n toString() {\n return legacyRefStr;\n },\n });\n }\n if (type === 'sub') {\n const legacyRef = ref as LegacySubRouteRef;\n const legacyRefStr = String(legacyRef);\n const newRef = toInternalSubRouteRef(\n createSubRouteRef({\n path: legacyRef.path,\n parent: convertLegacyRouteRef(legacyRef.parent),\n }),\n );\n return Object.assign(legacyRef, {\n $$type: '@backstage/SubRouteRef' as const,\n version: 'v1',\n T: newRef.T,\n getParams() {\n return newRef.getParams();\n },\n getParent() {\n return newRef.getParent();\n },\n getDescription() {\n return legacyRefStr;\n },\n toString() {\n return legacyRefStr;\n },\n });\n }\n if (type === 'external') {\n const legacyRef = ref as LegacyExternalRouteRef;\n const legacyRefStr = String(legacyRef);\n const newRef = toInternalExternalRouteRef(\n createExternalRouteRef<{ [key in string]: string }>({\n params: legacyRef.params as string[],\n defaultTarget:\n 'getDefaultTarget' in legacyRef\n ? (legacyRef.getDefaultTarget as () => string | undefined)()\n : undefined,\n }),\n );\n return Object.assign(legacyRef, {\n $$type: '@backstage/ExternalRouteRef' as const,\n version: 'v1',\n T: newRef.T,\n getParams() {\n return newRef.getParams();\n },\n getDescription() {\n return legacyRefStr;\n },\n // This might already be implemented in the legacy ref, but we override it just to be sure\n getDefaultTarget() {\n return newRef.getDefaultTarget();\n },\n setId(id: string) {\n newRef.setId(id);\n },\n toString() {\n return legacyRefStr;\n },\n });\n }\n\n throw new Error(`Failed to convert legacy route ref, unknown type '${type}'`);\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"convertLegacyRouteRef.esm.js","sources":["../src/convertLegacyRouteRef.ts"],"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 RouteRef as LegacyRouteRef,\n SubRouteRef as LegacySubRouteRef,\n ExternalRouteRef as LegacyExternalRouteRef,\n AnyRouteRefParams,\n} from '@backstage/core-plugin-api';\n\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { routeRefType } from '../../core-plugin-api/src/routing/types';\n\nimport {\n RouteRef,\n SubRouteRef,\n ExternalRouteRef,\n createRouteRef,\n createSubRouteRef,\n createExternalRouteRef,\n} from '@backstage/frontend-plugin-api';\n\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalRouteRef } from '../../frontend-plugin-api/src/routing/RouteRef';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalSubRouteRef } from '../../frontend-plugin-api/src/routing/SubRouteRef';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalExternalRouteRef } from '../../frontend-plugin-api/src/routing/ExternalRouteRef';\n\n/**\n * Converts a legacy route ref type to the new system.\n *\n * @public\n */\nexport type ToNewRouteRef<\n T extends LegacyRouteRef | LegacySubRouteRef | LegacyExternalRouteRef,\n> = T extends LegacyRouteRef<infer IParams>\n ? RouteRef<IParams>\n : T extends LegacySubRouteRef<infer IParams>\n ? SubRouteRef<IParams>\n : T extends LegacyExternalRouteRef<infer IParams>\n ? ExternalRouteRef<IParams>\n : never;\n\n/**\n * Converts a collection of legacy route refs to the new system.\n * This is particularly useful when defining plugin `routes` and `externalRoutes`.\n *\n * @public\n */\nexport function convertLegacyRouteRefs<\n TRefs extends {\n [name in string]:\n | LegacyRouteRef\n | LegacySubRouteRef\n | LegacyExternalRouteRef;\n },\n>(refs: TRefs): { [KName in keyof TRefs]: ToNewRouteRef<TRefs[KName]> } {\n return Object.fromEntries(\n Object.entries(refs).map(([name, ref]) => [\n name,\n convertLegacyRouteRef(ref as LegacyRouteRef),\n ]),\n ) as { [KName in keyof TRefs]: ToNewRouteRef<TRefs[KName]> };\n}\n\n/**\n * A temporary helper to convert a legacy route ref to the new system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(\n ref: LegacyRouteRef<TParams>,\n): RouteRef<TParams>;\n\n/**\n * A temporary helper to convert a legacy sub route ref to the new system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createSubRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(\n ref: LegacySubRouteRef<TParams>,\n): SubRouteRef<TParams>;\n\n/**\n * A temporary helper to convert a legacy external route ref to the new system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createExternalRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(\n ref: LegacyExternalRouteRef<TParams>,\n): ExternalRouteRef<TParams>;\n\n/**\n * A temporary helper to convert a new route ref to the legacy system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(\n ref: RouteRef<TParams>,\n): LegacyRouteRef<TParams>;\n\n/**\n * A temporary helper to convert a new sub route ref to the legacy system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createSubRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(\n ref: SubRouteRef<TParams>,\n): LegacySubRouteRef<TParams>;\n\n/**\n * A temporary helper to convert a new external route ref to the legacy system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createExternalRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(\n ref: ExternalRouteRef<TParams>,\n): LegacyExternalRouteRef<TParams, true>;\nexport function convertLegacyRouteRef(\n ref:\n | LegacyRouteRef\n | LegacySubRouteRef\n | LegacyExternalRouteRef\n | RouteRef\n | SubRouteRef\n | ExternalRouteRef,\n):\n | RouteRef\n | SubRouteRef\n | ExternalRouteRef\n | LegacyRouteRef\n | LegacySubRouteRef\n | LegacyExternalRouteRef {\n const isNew = '$$type' in ref;\n const oldType = (ref as unknown as { [routeRefType]: unknown })[routeRefType];\n\n // Ref has already been converted\n if (isNew && oldType) {\n return ref as any;\n }\n\n if (isNew) {\n return convertNewToOld(\n ref as unknown as RouteRef | SubRouteRef | ExternalRouteRef,\n );\n }\n\n return convertOldToNew(ref, oldType);\n}\n\nfunction convertNewToOld(\n ref: RouteRef | SubRouteRef | ExternalRouteRef,\n): LegacyRouteRef | LegacySubRouteRef | LegacyExternalRouteRef {\n if (ref.$$type === '@backstage/RouteRef') {\n const newRef = toInternalRouteRef(ref);\n return Object.assign(ref, {\n [routeRefType]: 'absolute',\n params: newRef.getParams(),\n title: newRef.getDescription(),\n } as Omit<LegacyRouteRef, '$$routeRefType'>) as unknown as LegacyRouteRef;\n }\n if (ref.$$type === '@backstage/SubRouteRef') {\n const newRef = toInternalSubRouteRef(ref);\n return Object.assign(ref, {\n [routeRefType]: 'sub',\n parent: convertLegacyRouteRef(newRef.getParent()),\n params: newRef.getParams(),\n } as Omit<LegacySubRouteRef, '$$routeRefType' | 'path'>) as unknown as LegacySubRouteRef;\n }\n if (ref.$$type === '@backstage/ExternalRouteRef') {\n const newRef = toInternalExternalRouteRef(ref);\n return Object.assign(ref, {\n [routeRefType]: 'external',\n optional: true,\n params: newRef.getParams(),\n defaultTarget: newRef.getDefaultTarget(),\n } as Omit<LegacyExternalRouteRef, '$$routeRefType' | 'optional'>) as unknown as LegacyExternalRouteRef;\n }\n\n throw new Error(\n `Failed to convert route ref, unknown type '${(ref as any).$$type}'`,\n );\n}\n\nfunction convertOldToNew(\n ref: LegacyRouteRef | LegacySubRouteRef | LegacyExternalRouteRef,\n type: unknown,\n): RouteRef | SubRouteRef | ExternalRouteRef {\n if (type === 'absolute') {\n const legacyRef = ref as LegacyRouteRef;\n const legacyRefStr = String(legacyRef);\n const newRef = toInternalRouteRef(\n createRouteRef<{ [key in string]: string }>({\n params: legacyRef.params as string[],\n }),\n );\n return Object.assign(legacyRef, {\n $$type: '@backstage/RouteRef' as const,\n version: 'v1',\n T: newRef.T,\n getParams() {\n return newRef.getParams();\n },\n getDescription() {\n return legacyRefStr;\n },\n setId(id: string) {\n newRef.setId(id);\n },\n toString() {\n return legacyRefStr;\n },\n });\n }\n if (type === 'sub') {\n const legacyRef = ref as LegacySubRouteRef;\n const legacyRefStr = String(legacyRef);\n const newRef = toInternalSubRouteRef(\n createSubRouteRef({\n path: legacyRef.path,\n parent: convertLegacyRouteRef(legacyRef.parent),\n }),\n );\n return Object.assign(legacyRef, {\n $$type: '@backstage/SubRouteRef' as const,\n version: 'v1',\n T: newRef.T,\n getParams() {\n return newRef.getParams();\n },\n getParent() {\n return newRef.getParent();\n },\n getDescription() {\n return legacyRefStr;\n },\n toString() {\n return legacyRefStr;\n },\n });\n }\n if (type === 'external') {\n const legacyRef = ref as LegacyExternalRouteRef;\n const legacyRefStr = String(legacyRef);\n const newRef = toInternalExternalRouteRef(\n createExternalRouteRef<{ [key in string]: string }>({\n params: legacyRef.params as string[],\n defaultTarget:\n 'getDefaultTarget' in legacyRef\n ? (legacyRef.getDefaultTarget as () => string | undefined)()\n : undefined,\n }),\n );\n return Object.assign(legacyRef, {\n $$type: '@backstage/ExternalRouteRef' as const,\n version: 'v1',\n T: newRef.T,\n getParams() {\n return newRef.getParams();\n },\n getDescription() {\n return legacyRefStr;\n },\n // This might already be implemented in the legacy ref, but we override it just to be sure\n getDefaultTarget() {\n return newRef.getDefaultTarget();\n },\n setId(id: string) {\n newRef.setId(id);\n },\n toString() {\n return legacyRefStr;\n },\n });\n }\n\n throw new Error(`Failed to convert legacy route ref, unknown type '${type}'`);\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ApiAggregator.esm.js","sources":["../../../../../../core-app-api/src/apis/system/ApiAggregator.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 { ApiRef, ApiHolder } from '@backstage/core-plugin-api';\n\n/**\n * An ApiHolder that queries multiple other holders from for\n * an Api implementation, returning the first one encountered..\n */\nexport class ApiAggregator implements ApiHolder {\n private readonly holders: ApiHolder[];\n\n constructor(...holders: ApiHolder[]) {\n this.holders = holders;\n }\n\n get<T>(apiRef: ApiRef<T>): T | undefined {\n for (const holder of this.holders) {\n const api = holder.get(apiRef);\n if (api) {\n return api;\n }\n }\n return undefined;\n }\n}\n"],"names":[],"mappings":"AAsBO,MAAM,aAAmC,CAAA;AAAA,EAC7B,OAAA;AAAA,EAEjB,eAAe,OAAsB,EAAA;AACnC,IAAA,IAAA,CAAK,OAAU,GAAA,OAAA;AAAA;AACjB,EAEA,IAAO,MAAkC,EAAA;AACvC,IAAW,KAAA,MAAA,MAAA,IAAU,KAAK,OAAS,EAAA;AACjC,MAAM,MAAA,GAAA,GAAM,MAAO,CAAA,GAAA,CAAI,MAAM,CAAA;AAC7B,MAAA,IAAI,GAAK,EAAA;AACP,QAAO,OAAA,GAAA;AAAA;AACT;AAEF,IAAO,OAAA,KAAA,CAAA;AAAA;AAEX;;;;"}
1
+ {"version":3,"file":"ApiAggregator.esm.js","sources":["../../../../../../core-app-api/src/apis/system/ApiAggregator.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 { ApiRef, ApiHolder } from '@backstage/core-plugin-api';\n\n/**\n * An ApiHolder that queries multiple other holders from for\n * an Api implementation, returning the first one encountered..\n */\nexport class ApiAggregator implements ApiHolder {\n private readonly holders: ApiHolder[];\n\n constructor(...holders: ApiHolder[]) {\n this.holders = holders;\n }\n\n get<T>(apiRef: ApiRef<T>): T | undefined {\n for (const holder of this.holders) {\n const api = holder.get(apiRef);\n if (api) {\n return api;\n }\n }\n return undefined;\n }\n}\n"],"names":[],"mappings":"AAsBO,MAAM,aAAA,CAAmC;AAAA,EAC7B,OAAA;AAAA,EAEjB,eAAe,OAAA,EAAsB;AACnC,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AAAA,EAEA,IAAO,MAAA,EAAkC;AACvC,IAAA,KAAA,MAAW,MAAA,IAAU,KAAK,OAAA,EAAS;AACjC,MAAA,MAAM,GAAA,GAAM,MAAA,CAAO,GAAA,CAAI,MAAM,CAAA;AAC7B,MAAA,IAAI,GAAA,EAAK;AACP,QAAA,OAAO,GAAA;AAAA,MACT;AAAA,IACF;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AACF;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ApiProvider.esm.js","sources":["../../../../../../core-app-api/src/apis/system/ApiProvider.tsx"],"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 { useContext, ReactNode, PropsWithChildren } from 'react';\nimport PropTypes from 'prop-types';\nimport { ApiHolder } from '@backstage/core-plugin-api';\nimport { ApiAggregator } from './ApiAggregator';\nimport {\n createVersionedValueMap,\n createVersionedContext,\n} from '@backstage/version-bridge';\n\n/**\n * Prop types for the ApiProvider component.\n * @public\n */\nexport type ApiProviderProps = {\n apis: ApiHolder;\n children: ReactNode;\n};\n\nconst ApiContext = createVersionedContext<{ 1: ApiHolder }>('api-context');\n\n/**\n * Provides an {@link @backstage/core-plugin-api#ApiHolder} for consumption in\n * the React tree.\n *\n * @public\n */\nexport const ApiProvider = (props: PropsWithChildren<ApiProviderProps>) => {\n const { apis, children } = props;\n const parentHolder = useContext(ApiContext)?.atVersion(1);\n const holder = parentHolder ? new ApiAggregator(apis, parentHolder) : apis;\n\n return (\n <ApiContext.Provider\n value={createVersionedValueMap({ 1: holder })}\n children={children}\n />\n );\n};\n\nApiProvider.propTypes = {\n apis: PropTypes.shape({ get: PropTypes.func.isRequired }).isRequired,\n children: PropTypes.node,\n};\n"],"names":[],"mappings":";;;;;;AAkCA,MAAM,UAAA,GAAa,uBAAyC,aAAa,CAAA;AAQ5D,MAAA,WAAA,GAAc,CAAC,KAA+C,KAAA;AACzE,EAAM,MAAA,EAAE,IAAM,EAAA,QAAA,EAAa,GAAA,KAAA;AAC3B,EAAA,MAAM,YAAe,GAAA,UAAA,CAAW,UAAU,CAAA,EAAG,UAAU,CAAC,CAAA;AACxD,EAAA,MAAM,SAAS,YAAe,GAAA,IAAI,aAAc,CAAA,IAAA,EAAM,YAAY,CAAI,GAAA,IAAA;AAEtE,EACE,uBAAA,GAAA;AAAA,IAAC,UAAW,CAAA,QAAA;AAAA,IAAX;AAAA,MACC,KAAO,EAAA,uBAAA,CAAwB,EAAE,CAAA,EAAG,QAAQ,CAAA;AAAA,MAC5C;AAAA;AAAA,GACF;AAEJ;AAEA,WAAA,CAAY,SAAY,GAAA;AAAA,EACtB,IAAA,EAAM,UAAU,KAAM,CAAA,EAAE,KAAK,SAAU,CAAA,IAAA,CAAK,UAAW,EAAC,CAAE,CAAA,UAAA;AAAA,EAC1D,UAAU,SAAU,CAAA;AACtB,CAAA;;;;"}
1
+ {"version":3,"file":"ApiProvider.esm.js","sources":["../../../../../../core-app-api/src/apis/system/ApiProvider.tsx"],"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 { useContext, ReactNode, PropsWithChildren } from 'react';\nimport PropTypes from 'prop-types';\nimport { ApiHolder } from '@backstage/core-plugin-api';\nimport { ApiAggregator } from './ApiAggregator';\nimport {\n createVersionedValueMap,\n createVersionedContext,\n} from '@backstage/version-bridge';\n\n/**\n * Prop types for the ApiProvider component.\n * @public\n */\nexport type ApiProviderProps = {\n apis: ApiHolder;\n children: ReactNode;\n};\n\nconst ApiContext = createVersionedContext<{ 1: ApiHolder }>('api-context');\n\n/**\n * Provides an {@link @backstage/core-plugin-api#ApiHolder} for consumption in\n * the React tree.\n *\n * @public\n */\nexport const ApiProvider = (props: PropsWithChildren<ApiProviderProps>) => {\n const { apis, children } = props;\n const parentHolder = useContext(ApiContext)?.atVersion(1);\n const holder = parentHolder ? new ApiAggregator(apis, parentHolder) : apis;\n\n return (\n <ApiContext.Provider\n value={createVersionedValueMap({ 1: holder })}\n children={children}\n />\n );\n};\n\nApiProvider.propTypes = {\n apis: PropTypes.shape({ get: PropTypes.func.isRequired }).isRequired,\n children: PropTypes.node,\n};\n"],"names":[],"mappings":";;;;;;AAkCA,MAAM,UAAA,GAAa,uBAAyC,aAAa,CAAA;AAQlE,MAAM,WAAA,GAAc,CAAC,KAAA,KAA+C;AACzE,EAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAS,GAAI,KAAA;AAC3B,EAAA,MAAM,YAAA,GAAe,UAAA,CAAW,UAAU,CAAA,EAAG,UAAU,CAAC,CAAA;AACxD,EAAA,MAAM,SAAS,YAAA,GAAe,IAAI,aAAA,CAAc,IAAA,EAAM,YAAY,CAAA,GAAI,IAAA;AAEtE,EAAA,uBACE,GAAA;AAAA,IAAC,UAAA,CAAW,QAAA;AAAA,IAAX;AAAA,MACC,KAAA,EAAO,uBAAA,CAAwB,EAAE,CAAA,EAAG,QAAQ,CAAA;AAAA,MAC5C;AAAA;AAAA,GACF;AAEJ;AAEA,WAAA,CAAY,SAAA,GAAY;AAAA,EACtB,IAAA,EAAM,UAAU,KAAA,CAAM,EAAE,KAAK,SAAA,CAAU,IAAA,CAAK,UAAA,EAAY,CAAA,CAAE,UAAA;AAAA,EAC1D,UAAU,SAAA,CAAU;AACtB,CAAA;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"AppContext.esm.js","sources":["../../../../../core-app-api/src/app/AppContext.tsx"],"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 { PropsWithChildren } from 'react';\nimport {\n createVersionedValueMap,\n createVersionedContext,\n} from '@backstage/version-bridge';\nimport { AppContext as AppContextV1 } from './types';\n\nconst AppContext = createVersionedContext<{ 1: AppContextV1 }>('app-context');\n\ntype Props = {\n appContext: AppContextV1;\n};\n\nexport const AppContextProvider = ({\n appContext,\n children,\n}: PropsWithChildren<Props>) => {\n const versionedValue = createVersionedValueMap({ 1: appContext });\n\n return <AppContext.Provider value={versionedValue} children={children} />;\n};\n"],"names":[],"mappings":";;;AAuBA,MAAM,UAAA,GAAa,uBAA4C,aAAa,CAAA;AAMrE,MAAM,qBAAqB,CAAC;AAAA,EACjC,UAAA;AAAA,EACA;AACF,CAAgC,KAAA;AAC9B,EAAA,MAAM,cAAiB,GAAA,uBAAA,CAAwB,EAAE,CAAA,EAAG,YAAY,CAAA;AAEhE,EAAA,2BAAQ,UAAW,CAAA,QAAA,EAAX,EAAoB,KAAA,EAAO,gBAAgB,QAAoB,EAAA,CAAA;AACzE;;;;"}
1
+ {"version":3,"file":"AppContext.esm.js","sources":["../../../../../core-app-api/src/app/AppContext.tsx"],"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 { PropsWithChildren } from 'react';\nimport {\n createVersionedValueMap,\n createVersionedContext,\n} from '@backstage/version-bridge';\nimport { AppContext as AppContextV1 } from './types';\n\nconst AppContext = createVersionedContext<{ 1: AppContextV1 }>('app-context');\n\ntype Props = {\n appContext: AppContextV1;\n};\n\nexport const AppContextProvider = ({\n appContext,\n children,\n}: PropsWithChildren<Props>) => {\n const versionedValue = createVersionedValueMap({ 1: appContext });\n\n return <AppContext.Provider value={versionedValue} children={children} />;\n};\n"],"names":[],"mappings":";;;AAuBA,MAAM,UAAA,GAAa,uBAA4C,aAAa,CAAA;AAMrE,MAAM,qBAAqB,CAAC;AAAA,EACjC,UAAA;AAAA,EACA;AACF,CAAA,KAAgC;AAC9B,EAAA,MAAM,cAAA,GAAiB,uBAAA,CAAwB,EAAE,CAAA,EAAG,YAAY,CAAA;AAEhE,EAAA,2BAAQ,UAAA,CAAW,QAAA,EAAX,EAAoB,KAAA,EAAO,gBAAgB,QAAA,EAAoB,CAAA;AACzE;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.esm.js","sources":["../../../../../core-plugin-api/src/routing/types.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 { getOrCreateGlobalSingleton } from '@backstage/version-bridge';\n\n/**\n * Catch-all type for route params.\n *\n * @public\n */\nexport type AnyRouteRefParams = { [param in string]: string } | undefined;\n\n/**\n * @deprecated use {@link AnyRouteRefParams} instead\n * @public\n */\nexport type AnyParams = AnyRouteRefParams;\n\n/**\n * Type describing the key type of a route parameter mapping.\n *\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type ParamKeys<Params extends AnyParams> = [AnyRouteRefParams] extends [\n Params,\n]\n ? string[]\n : keyof Params extends never\n ? []\n : Array<keyof Params>;\n\n/**\n * Optional route params.\n *\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type OptionalParams<Params extends { [param in string]: string }> =\n Params[keyof Params] extends never ? undefined : Params;\n\n/**\n * TS magic for handling route parameters.\n *\n * @remarks\n *\n * The extra TS magic here is to require a single params argument if the RouteRef\n * had at least one param defined, but require 0 arguments if there are no params defined.\n * Without this we'd have to pass in empty object to all parameter-less RouteRefs\n * just to make TypeScript happy, or we would have to make the argument optional in\n * which case you might forget to pass it in when it is actually required.\n *\n * @public\n */\nexport type RouteFunc<Params extends AnyParams> = (\n ...[params]: Params extends undefined ? readonly [] : readonly [Params]\n) => string;\n\n/**\n * This symbol is what we use at runtime to determine whether a given object\n * is a type of RouteRef or not. It doesn't work well in TypeScript though since\n * the `unique symbol` will refer to different values between package versions.\n * For that reason we use the marker $$routeRefType to represent the symbol at\n * compile-time instead of using the symbol directly.\n *\n * @internal\n */\nexport const routeRefType: unique symbol = getOrCreateGlobalSingleton<any>(\n 'route-ref-type',\n () => Symbol('route-ref-type'),\n);\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 type RouteRef<Params extends AnyParams = any> = {\n /** @deprecated access to this property will be removed in the future */\n $$routeRefType: 'absolute'; // See routeRefType above\n\n /** @deprecated access to this property will be removed in the future */\n params: ParamKeys<Params>;\n};\n\n/**\n * Descriptor of a route relative to an absolute {@link RouteRef}.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport type SubRouteRef<Params extends AnyParams = any> = {\n /** @deprecated access to this property will be removed in the future */\n $$routeRefType: 'sub'; // See routeRefType above\n\n /** @deprecated access to this property will be removed in the future */\n parent: RouteRef;\n\n path: string;\n\n /** @deprecated access to this property will be removed in the future */\n params: ParamKeys<Params>;\n};\n\n/**\n * Route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport type ExternalRouteRef<\n Params extends AnyParams = any,\n Optional extends boolean = any,\n> = {\n /** @deprecated access to this property will be removed in the future */\n $$routeRefType: 'external'; // See routeRefType above\n\n /** @deprecated access to this property will be removed in the future */\n params: ParamKeys<Params>;\n\n optional?: Optional;\n};\n\n/**\n * @internal\n */\nexport type AnyRouteRef =\n | RouteRef<any>\n | SubRouteRef<any>\n | ExternalRouteRef<any, any>;\n\n/**\n * A duplicate of the react-router RouteObject, but with routeRef added\n * @internal\n */\nexport interface BackstageRouteObject {\n caseSensitive: boolean;\n children?: BackstageRouteObject[];\n element: React.ReactNode;\n path: string;\n routeRefs: Set<RouteRef>;\n}\n"],"names":[],"mappings":";;AAgFO,MAAM,YAA8B,GAAA,0BAAA;AAAA,EACzC,gBAAA;AAAA,EACA,MAAM,OAAO,gBAAgB;AAC/B;;;;"}
1
+ {"version":3,"file":"types.esm.js","sources":["../../../../../core-plugin-api/src/routing/types.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 { getOrCreateGlobalSingleton } from '@backstage/version-bridge';\n\n/**\n * Catch-all type for route params.\n *\n * @public\n */\nexport type AnyRouteRefParams = { [param in string]: string } | undefined;\n\n/**\n * @deprecated use {@link AnyRouteRefParams} instead\n * @public\n */\nexport type AnyParams = AnyRouteRefParams;\n\n/**\n * Type describing the key type of a route parameter mapping.\n *\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type ParamKeys<Params extends AnyParams> = [AnyRouteRefParams] extends [\n Params,\n]\n ? string[]\n : keyof Params extends never\n ? []\n : Array<keyof Params>;\n\n/**\n * Optional route params.\n *\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type OptionalParams<Params extends { [param in string]: string }> =\n Params[keyof Params] extends never ? undefined : Params;\n\n/**\n * TS magic for handling route parameters.\n *\n * @remarks\n *\n * The extra TS magic here is to require a single params argument if the RouteRef\n * had at least one param defined, but require 0 arguments if there are no params defined.\n * Without this we'd have to pass in empty object to all parameter-less RouteRefs\n * just to make TypeScript happy, or we would have to make the argument optional in\n * which case you might forget to pass it in when it is actually required.\n *\n * @public\n */\nexport type RouteFunc<Params extends AnyParams> = (\n ...[params]: Params extends undefined ? readonly [] : readonly [Params]\n) => string;\n\n/**\n * This symbol is what we use at runtime to determine whether a given object\n * is a type of RouteRef or not. It doesn't work well in TypeScript though since\n * the `unique symbol` will refer to different values between package versions.\n * For that reason we use the marker $$routeRefType to represent the symbol at\n * compile-time instead of using the symbol directly.\n *\n * @internal\n */\nexport const routeRefType: unique symbol = getOrCreateGlobalSingleton<any>(\n 'route-ref-type',\n () => Symbol('route-ref-type'),\n);\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 type RouteRef<Params extends AnyParams = any> = {\n /** @deprecated access to this property will be removed in the future */\n $$routeRefType: 'absolute'; // See routeRefType above\n\n /** @deprecated access to this property will be removed in the future */\n params: ParamKeys<Params>;\n};\n\n/**\n * Descriptor of a route relative to an absolute {@link RouteRef}.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport type SubRouteRef<Params extends AnyParams = any> = {\n /** @deprecated access to this property will be removed in the future */\n $$routeRefType: 'sub'; // See routeRefType above\n\n /** @deprecated access to this property will be removed in the future */\n parent: RouteRef;\n\n path: string;\n\n /** @deprecated access to this property will be removed in the future */\n params: ParamKeys<Params>;\n};\n\n/**\n * Route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport type ExternalRouteRef<\n Params extends AnyParams = any,\n Optional extends boolean = any,\n> = {\n /** @deprecated access to this property will be removed in the future */\n $$routeRefType: 'external'; // See routeRefType above\n\n /** @deprecated access to this property will be removed in the future */\n params: ParamKeys<Params>;\n\n optional?: Optional;\n};\n\n/**\n * @internal\n */\nexport type AnyRouteRef =\n | RouteRef<any>\n | SubRouteRef<any>\n | ExternalRouteRef<any, any>;\n\n/**\n * A duplicate of the react-router RouteObject, but with routeRef added\n * @internal\n */\nexport interface BackstageRouteObject {\n caseSensitive: boolean;\n children?: BackstageRouteObject[];\n element: React.ReactNode;\n path: string;\n routeRefs: Set<RouteRef>;\n}\n"],"names":[],"mappings":";;AAgFO,MAAM,YAAA,GAA8B,0BAAA;AAAA,EACzC,gBAAA;AAAA,EACA,MAAM,OAAO,gBAAgB;AAC/B;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ExternalRouteRef.esm.js","sources":["../../../../../frontend-plugin-api/src/routing/ExternalRouteRef.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 { RouteRefImpl } from './RouteRef';\nimport { describeParentCallSite } from './describeParentCallSite';\nimport { AnyRouteRefParams } from './types';\n\n/**\n * Route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport interface ExternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> {\n readonly $$type: '@backstage/ExternalRouteRef';\n readonly T: TParams;\n}\n\n/** @internal */\nexport interface InternalExternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> extends ExternalRouteRef<TParams> {\n readonly version: 'v1';\n getParams(): string[];\n getDescription(): string;\n getDefaultTarget(): string | undefined;\n\n setId(id: string): void;\n}\n\n/** @internal */\nexport function toInternalExternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n>(resource: ExternalRouteRef<TParams>): InternalExternalRouteRef<TParams> {\n const r = resource as InternalExternalRouteRef<TParams>;\n if (r.$$type !== '@backstage/ExternalRouteRef') {\n throw new Error(`Invalid ExternalRouteRef, bad type '${r.$$type}'`);\n }\n\n return r;\n}\n\n/** @internal */\nexport function isExternalRouteRef(opaque: {\n $$type: string;\n}): opaque is ExternalRouteRef {\n return opaque.$$type === '@backstage/ExternalRouteRef';\n}\n\n/** @internal */\nclass ExternalRouteRefImpl\n extends RouteRefImpl\n implements InternalExternalRouteRef\n{\n readonly $$type = '@backstage/ExternalRouteRef' as any;\n\n constructor(\n readonly params: string[] = [],\n readonly defaultTarget: string | undefined,\n creationSite: string,\n ) {\n super(params, creationSite);\n }\n\n getDefaultTarget() {\n return this.defaultTarget;\n }\n}\n\n/**\n * Creates a route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @param options - Description of the route reference to be created.\n * @public\n */\nexport function createExternalRouteRef<\n TParams extends { [param in TParamKeys]: string } | undefined = undefined,\n TParamKeys extends string = string,\n>(options?: {\n /**\n * The parameters that will be provided to the external route reference.\n */\n readonly params?: string extends TParamKeys\n ? (keyof TParams)[]\n : TParamKeys[];\n\n /**\n * The route (typically in another plugin) that this should map to by default.\n *\n * The string is expected to be on the standard `<plugin id>.<route id>` form,\n * for example `techdocs.docRoot`.\n */\n defaultTarget?: string;\n}): ExternalRouteRef<\n keyof TParams extends never\n ? undefined\n : string extends TParamKeys\n ? TParams\n : { [param in TParamKeys]: string }\n> {\n return new ExternalRouteRefImpl(\n options?.params as string[] | undefined,\n options?.defaultTarget,\n describeParentCallSite(),\n );\n}\n"],"names":[],"mappings":"AAiDO,SAAS,2BAEd,QAAwE,EAAA;AACxE,EAAA,MAAM,CAAI,GAAA,QAAA;AACV,EAAI,IAAA,CAAA,CAAE,WAAW,6BAA+B,EAAA;AAC9C,IAAA,MAAM,IAAI,KAAA,CAAM,CAAuC,oCAAA,EAAA,CAAA,CAAE,MAAM,CAAG,CAAA,CAAA,CAAA;AAAA;AAGpE,EAAO,OAAA,CAAA;AACT;;;;"}
1
+ {"version":3,"file":"ExternalRouteRef.esm.js","sources":["../../../../../frontend-plugin-api/src/routing/ExternalRouteRef.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 { RouteRefImpl } from './RouteRef';\nimport { describeParentCallSite } from './describeParentCallSite';\nimport { AnyRouteRefParams } from './types';\n\n/**\n * Route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport interface ExternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> {\n readonly $$type: '@backstage/ExternalRouteRef';\n readonly T: TParams;\n}\n\n/** @internal */\nexport interface InternalExternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> extends ExternalRouteRef<TParams> {\n readonly version: 'v1';\n getParams(): string[];\n getDescription(): string;\n getDefaultTarget(): string | undefined;\n\n setId(id: string): void;\n}\n\n/** @internal */\nexport function toInternalExternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n>(resource: ExternalRouteRef<TParams>): InternalExternalRouteRef<TParams> {\n const r = resource as InternalExternalRouteRef<TParams>;\n if (r.$$type !== '@backstage/ExternalRouteRef') {\n throw new Error(`Invalid ExternalRouteRef, bad type '${r.$$type}'`);\n }\n\n return r;\n}\n\n/** @internal */\nexport function isExternalRouteRef(opaque: {\n $$type: string;\n}): opaque is ExternalRouteRef {\n return opaque.$$type === '@backstage/ExternalRouteRef';\n}\n\n/** @internal */\nclass ExternalRouteRefImpl\n extends RouteRefImpl\n implements InternalExternalRouteRef\n{\n readonly $$type = '@backstage/ExternalRouteRef' as any;\n\n constructor(\n readonly params: string[] = [],\n readonly defaultTarget: string | undefined,\n creationSite: string,\n ) {\n super(params, creationSite);\n }\n\n getDefaultTarget() {\n return this.defaultTarget;\n }\n}\n\n/**\n * Creates a route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @param options - Description of the route reference to be created.\n * @public\n */\nexport function createExternalRouteRef<\n TParams extends { [param in TParamKeys]: string } | undefined = undefined,\n TParamKeys extends string = string,\n>(options?: {\n /**\n * The parameters that will be provided to the external route reference.\n */\n readonly params?: string extends TParamKeys\n ? (keyof TParams)[]\n : TParamKeys[];\n\n /**\n * The route (typically in another plugin) that this should map to by default.\n *\n * The string is expected to be on the standard `<plugin id>.<route id>` form,\n * for example `techdocs.docRoot`.\n */\n defaultTarget?: string;\n}): ExternalRouteRef<\n keyof TParams extends never\n ? undefined\n : string extends TParamKeys\n ? TParams\n : { [param in TParamKeys]: string }\n> {\n return new ExternalRouteRefImpl(\n options?.params as string[] | undefined,\n options?.defaultTarget,\n describeParentCallSite(),\n );\n}\n"],"names":[],"mappings":"AAiDO,SAAS,2BAEd,QAAA,EAAwE;AACxE,EAAA,MAAM,CAAA,GAAI,QAAA;AACV,EAAA,IAAI,CAAA,CAAE,WAAW,6BAAA,EAA+B;AAC9C,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oCAAA,EAAuC,CAAA,CAAE,MAAM,CAAA,CAAA,CAAG,CAAA;AAAA,EACpE;AAEA,EAAA,OAAO,CAAA;AACT;;;;"}
@@ -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 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;;;;"}
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,QAAA,EAAwD;AACxD,EAAA,MAAM,CAAA,GAAI,QAAA;AACV,EAAA,IAAI,CAAA,CAAE,WAAW,qBAAA,EAAuB;AACtC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,4BAAA,EAA+B,CAAA,CAAE,MAAM,CAAA,CAAA,CAAG,CAAA;AAAA,EAC5D;AAEA,EAAA,OAAO,CAAA;AACT;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"SubRouteRef.esm.js","sources":["../../../../../frontend-plugin-api/src/routing/SubRouteRef.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 { RouteRef, toInternalRouteRef } from './RouteRef';\nimport { AnyRouteRefParams } from './types';\n\n// Should match the pattern in react-router\nconst PARAM_PATTERN = /^\\w+$/;\n\n/**\n * Descriptor of a route relative to an absolute {@link RouteRef}.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport interface SubRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> {\n readonly $$type: '@backstage/SubRouteRef';\n\n readonly T: TParams;\n\n readonly path: string;\n}\n\n/** @internal */\nexport interface InternalSubRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> extends SubRouteRef<TParams> {\n readonly version: 'v1';\n\n getParams(): string[];\n getParent(): RouteRef;\n getDescription(): string;\n}\n\n/** @internal */\nexport function toInternalSubRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n>(resource: SubRouteRef<TParams>): InternalSubRouteRef<TParams> {\n const r = resource as InternalSubRouteRef<TParams>;\n if (r.$$type !== '@backstage/SubRouteRef') {\n throw new Error(`Invalid SubRouteRef, bad type '${r.$$type}'`);\n }\n\n return r;\n}\n\n/** @internal */\nexport function isSubRouteRef(opaque: {\n $$type: string;\n}): opaque is SubRouteRef {\n return opaque.$$type === '@backstage/SubRouteRef';\n}\n\n/** @internal */\nexport class SubRouteRefImpl<TParams extends AnyRouteRefParams>\n implements SubRouteRef<TParams>\n{\n readonly $$type = '@backstage/SubRouteRef';\n readonly version = 'v1';\n declare readonly T: never;\n\n #params: string[];\n #parent: RouteRef;\n\n constructor(readonly path: string, params: string[], parent: RouteRef) {\n this.#params = params;\n this.#parent = parent;\n }\n\n getParams(): string[] {\n return this.#params;\n }\n\n getParent(): RouteRef {\n return this.#parent;\n }\n\n getDescription(): string {\n const parent = toInternalRouteRef(this.#parent);\n return `at ${this.path} with parent ${parent.getDescription()}`;\n }\n\n toString(): string {\n return `SubRouteRef{${this.getDescription()}}`;\n }\n}\n\n/**\n * Used in {@link PathParams} type declaration.\n * @ignore\n */\ntype ParamPart<S extends string> = S extends `:${infer Param}` ? Param : never;\n\n/**\n * Used in {@link PathParams} type declaration.\n * @ignore\n */\ntype ParamNames<S extends string> = S extends `${infer Part}/${infer Rest}`\n ? ParamPart<Part> | ParamNames<Rest>\n : ParamPart<S>;\n/**\n * This utility type helps us infer a Param object type from a string path\n * For example, `/foo/:bar/:baz` inferred to `{ bar: string, baz: string }`\n * @ignore\n */\ntype PathParams<S extends string> = { [name in ParamNames<S>]: string };\n\n/**\n * Merges a param object type with an optional params type into a params object.\n * @ignore\n */\ntype MergeParams<\n P1 extends { [param in string]: string },\n P2 extends AnyRouteRefParams,\n> = (P1[keyof P1] extends never ? {} : P1) & (P2 extends undefined ? {} : P2);\n\n/**\n * Convert empty params to undefined.\n * @ignore\n */\ntype TrimEmptyParams<Params extends { [param in string]: string }> =\n keyof Params extends never ? undefined : Params;\n\n/**\n * Creates a SubRouteRef type given the desired parameters and parent route parameters.\n * The parameters types are merged together while ensuring that there is no overlap between the two.\n *\n * @ignore\n */\ntype MakeSubRouteRef<\n Params extends { [param in string]: string },\n ParentParams extends AnyRouteRefParams,\n> = keyof Params & keyof ParentParams extends never\n ? SubRouteRef<TrimEmptyParams<MergeParams<Params, ParentParams>>>\n : never;\n\n/**\n * Create a {@link SubRouteRef} from a route descriptor.\n *\n * @param config - Description of the route reference to be created.\n * @public\n */\nexport function createSubRouteRef<\n Path extends string,\n ParentParams extends AnyRouteRefParams = never,\n>(config: {\n path: Path;\n parent: RouteRef<ParentParams>;\n}): MakeSubRouteRef<PathParams<Path>, ParentParams> {\n const { path, parent } = config;\n type Params = PathParams<Path>;\n\n const internalParent = toInternalRouteRef(parent);\n const parentParams = internalParent.getParams();\n\n // Collect runtime parameters from the path, e.g. ['bar', 'baz'] from '/foo/:bar/:baz'\n const pathParams = path\n .split('/')\n .filter(p => p.startsWith(':'))\n .map(p => p.substring(1));\n const params = [...parentParams, ...pathParams];\n\n if (parentParams.some(p => pathParams.includes(p as string))) {\n throw new Error(\n 'SubRouteRef may not have params that overlap with its parent',\n );\n }\n if (!path.startsWith('/')) {\n throw new Error(`SubRouteRef path must start with '/', got '${path}'`);\n }\n if (path.endsWith('/')) {\n throw new Error(`SubRouteRef path must not end with '/', got '${path}'`);\n }\n for (const param of pathParams) {\n if (!PARAM_PATTERN.test(param)) {\n throw new Error(`SubRouteRef path has invalid param, got '${param}'`);\n }\n }\n\n // We ensure that the type of the return type is sane here\n const subRouteRef = new SubRouteRefImpl(\n path,\n params as string[],\n parent,\n ) as SubRouteRef<TrimEmptyParams<MergeParams<Params, ParentParams>>>;\n\n // But skip type checking of the return value itself, because the conditional\n // type checking of the parent parameter overlap is tricky to express.\n return subRouteRef as any;\n}\n"],"names":[],"mappings":"AAqDO,SAAS,sBAEd,QAA8D,EAAA;AAC9D,EAAA,MAAM,CAAI,GAAA,QAAA;AACV,EAAI,IAAA,CAAA,CAAE,WAAW,wBAA0B,EAAA;AACzC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAkC,+BAAA,EAAA,CAAA,CAAE,MAAM,CAAG,CAAA,CAAA,CAAA;AAAA;AAG/D,EAAO,OAAA,CAAA;AACT;;;;"}
1
+ {"version":3,"file":"SubRouteRef.esm.js","sources":["../../../../../frontend-plugin-api/src/routing/SubRouteRef.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 { RouteRef, toInternalRouteRef } from './RouteRef';\nimport { AnyRouteRefParams } from './types';\n\n// Should match the pattern in react-router\nconst PARAM_PATTERN = /^\\w+$/;\n\n/**\n * Descriptor of a route relative to an absolute {@link RouteRef}.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport interface SubRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> {\n readonly $$type: '@backstage/SubRouteRef';\n\n readonly T: TParams;\n\n readonly path: string;\n}\n\n/** @internal */\nexport interface InternalSubRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> extends SubRouteRef<TParams> {\n readonly version: 'v1';\n\n getParams(): string[];\n getParent(): RouteRef;\n getDescription(): string;\n}\n\n/** @internal */\nexport function toInternalSubRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n>(resource: SubRouteRef<TParams>): InternalSubRouteRef<TParams> {\n const r = resource as InternalSubRouteRef<TParams>;\n if (r.$$type !== '@backstage/SubRouteRef') {\n throw new Error(`Invalid SubRouteRef, bad type '${r.$$type}'`);\n }\n\n return r;\n}\n\n/** @internal */\nexport function isSubRouteRef(opaque: {\n $$type: string;\n}): opaque is SubRouteRef {\n return opaque.$$type === '@backstage/SubRouteRef';\n}\n\n/** @internal */\nexport class SubRouteRefImpl<TParams extends AnyRouteRefParams>\n implements SubRouteRef<TParams>\n{\n readonly $$type = '@backstage/SubRouteRef';\n readonly version = 'v1';\n declare readonly T: never;\n\n #params: string[];\n #parent: RouteRef;\n\n constructor(readonly path: string, params: string[], parent: RouteRef) {\n this.#params = params;\n this.#parent = parent;\n }\n\n getParams(): string[] {\n return this.#params;\n }\n\n getParent(): RouteRef {\n return this.#parent;\n }\n\n getDescription(): string {\n const parent = toInternalRouteRef(this.#parent);\n return `at ${this.path} with parent ${parent.getDescription()}`;\n }\n\n toString(): string {\n return `SubRouteRef{${this.getDescription()}}`;\n }\n}\n\n/**\n * Used in {@link PathParams} type declaration.\n * @ignore\n */\ntype ParamPart<S extends string> = S extends `:${infer Param}` ? Param : never;\n\n/**\n * Used in {@link PathParams} type declaration.\n * @ignore\n */\ntype ParamNames<S extends string> = S extends `${infer Part}/${infer Rest}`\n ? ParamPart<Part> | ParamNames<Rest>\n : ParamPart<S>;\n/**\n * This utility type helps us infer a Param object type from a string path\n * For example, `/foo/:bar/:baz` inferred to `{ bar: string, baz: string }`\n * @ignore\n */\ntype PathParams<S extends string> = { [name in ParamNames<S>]: string };\n\n/**\n * Merges a param object type with an optional params type into a params object.\n * @ignore\n */\ntype MergeParams<\n P1 extends { [param in string]: string },\n P2 extends AnyRouteRefParams,\n> = (P1[keyof P1] extends never ? {} : P1) & (P2 extends undefined ? {} : P2);\n\n/**\n * Convert empty params to undefined.\n * @ignore\n */\ntype TrimEmptyParams<Params extends { [param in string]: string }> =\n keyof Params extends never ? undefined : Params;\n\n/**\n * Creates a SubRouteRef type given the desired parameters and parent route parameters.\n * The parameters types are merged together while ensuring that there is no overlap between the two.\n *\n * @ignore\n */\ntype MakeSubRouteRef<\n Params extends { [param in string]: string },\n ParentParams extends AnyRouteRefParams,\n> = keyof Params & keyof ParentParams extends never\n ? SubRouteRef<TrimEmptyParams<MergeParams<Params, ParentParams>>>\n : never;\n\n/**\n * Create a {@link SubRouteRef} from a route descriptor.\n *\n * @param config - Description of the route reference to be created.\n * @public\n */\nexport function createSubRouteRef<\n Path extends string,\n ParentParams extends AnyRouteRefParams = never,\n>(config: {\n path: Path;\n parent: RouteRef<ParentParams>;\n}): MakeSubRouteRef<PathParams<Path>, ParentParams> {\n const { path, parent } = config;\n type Params = PathParams<Path>;\n\n const internalParent = toInternalRouteRef(parent);\n const parentParams = internalParent.getParams();\n\n // Collect runtime parameters from the path, e.g. ['bar', 'baz'] from '/foo/:bar/:baz'\n const pathParams = path\n .split('/')\n .filter(p => p.startsWith(':'))\n .map(p => p.substring(1));\n const params = [...parentParams, ...pathParams];\n\n if (parentParams.some(p => pathParams.includes(p as string))) {\n throw new Error(\n 'SubRouteRef may not have params that overlap with its parent',\n );\n }\n if (!path.startsWith('/')) {\n throw new Error(`SubRouteRef path must start with '/', got '${path}'`);\n }\n if (path.endsWith('/')) {\n throw new Error(`SubRouteRef path must not end with '/', got '${path}'`);\n }\n for (const param of pathParams) {\n if (!PARAM_PATTERN.test(param)) {\n throw new Error(`SubRouteRef path has invalid param, got '${param}'`);\n }\n }\n\n // We ensure that the type of the return type is sane here\n const subRouteRef = new SubRouteRefImpl(\n path,\n params as string[],\n parent,\n ) as SubRouteRef<TrimEmptyParams<MergeParams<Params, ParentParams>>>;\n\n // But skip type checking of the return value itself, because the conditional\n // type checking of the parent parameter overlap is tricky to express.\n return subRouteRef as any;\n}\n"],"names":[],"mappings":"AAqDO,SAAS,sBAEd,QAAA,EAA8D;AAC9D,EAAA,MAAM,CAAA,GAAI,QAAA;AACV,EAAA,IAAI,CAAA,CAAE,WAAW,wBAAA,EAA0B;AACzC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,+BAAA,EAAkC,CAAA,CAAE,MAAM,CAAA,CAAA,CAAG,CAAA;AAAA,EAC/D;AAEA,EAAA,OAAO,CAAA;AACT;;;;"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode, JSX, ComponentType } from 'react';
3
- import { AnalyticsApi, AnalyticsEvent, AnyApiFactory, IconComponent, BackstagePlugin, AppComponents, AppTheme, FeatureFlag, RouteRef, SubRouteRef, ExternalRouteRef, AnyRouteRefParams } from '@backstage/core-plugin-api';
3
+ import { AnalyticsApi, AnalyticsEvent, AnyApiFactory, IconComponent, BackstagePlugin, AppComponents, AppTheme, FeatureFlag, AnyRouteRefParams, RouteRef, SubRouteRef, ExternalRouteRef } from '@backstage/core-plugin-api';
4
4
  import { AnalyticsApi as AnalyticsApi$1, AnalyticsEvent as AnalyticsEvent$1, FrontendPlugin, FrontendModule, ExtensionDefinition, RouteRef as RouteRef$1, SubRouteRef as SubRouteRef$1, ExternalRouteRef as ExternalRouteRef$1 } from '@backstage/frontend-plugin-api';
5
5
 
6
6
  /**
@@ -65,7 +65,7 @@ declare class NoOpAnalyticsApi implements AnalyticsApi, AnalyticsApi$1 {
65
65
  }
66
66
 
67
67
  /** @public */
68
- interface ConvertLegacyAppOptions {
68
+ interface ConvertLegacyAppRootOptions {
69
69
  /**
70
70
  * By providing an entity page element here it will be split up and converted
71
71
  * into individual extensions for the catalog plugin in the new frontend
@@ -86,7 +86,19 @@ interface ConvertLegacyAppOptions {
86
86
  entityPage?: JSX.Element;
87
87
  }
88
88
  /** @public */
89
- declare function convertLegacyApp(rootElement: JSX.Element, options?: ConvertLegacyAppOptions): (FrontendPlugin | FrontendModule)[];
89
+ declare function convertLegacyAppRoot(rootElement: JSX.Element, options?: ConvertLegacyAppRootOptions): (FrontendPlugin | FrontendModule)[];
90
+ /**
91
+ * @public
92
+ * @deprecated
93
+ * Use `convertLegacyAppRoot` instead.
94
+ */
95
+ declare const convertLegacyApp: typeof convertLegacyAppRoot;
96
+ /**
97
+ * @public
98
+ * @deprecated
99
+ * Use `ConvertLegacyAppRootOptions` instead.
100
+ */
101
+ type ConvertLegacyAppOptions = ConvertLegacyAppRootOptions;
90
102
 
91
103
  /**
92
104
  * @public
@@ -189,4 +201,4 @@ declare function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(ref: S
189
201
  */
190
202
  declare function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(ref: ExternalRouteRef$1<TParams>): ExternalRouteRef<TParams, true>;
191
203
 
192
- export { type ConvertLegacyAppOptions, MultipleAnalyticsApi, NoOpAnalyticsApi, type ToNewRouteRef, compatWrapper, convertLegacyApp, convertLegacyAppOptions, convertLegacyPageExtension, convertLegacyPlugin, convertLegacyRouteRef, convertLegacyRouteRefs };
204
+ export { type ConvertLegacyAppOptions, type ConvertLegacyAppRootOptions, MultipleAnalyticsApi, NoOpAnalyticsApi, type ToNewRouteRef, compatWrapper, convertLegacyApp, convertLegacyAppOptions, convertLegacyAppRoot, convertLegacyPageExtension, convertLegacyPlugin, convertLegacyRouteRef, convertLegacyRouteRefs };
package/dist/index.esm.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export { compatWrapper } from './compatWrapper/compatWrapper.esm.js';
2
2
  export { MultipleAnalyticsApi } from './apis/implementations/AnalyticsApi/MultipleAnalyticsApi.esm.js';
3
3
  export { NoOpAnalyticsApi } from './apis/implementations/AnalyticsApi/NoOpAnalyticsApi.esm.js';
4
- export { convertLegacyApp } from './convertLegacyApp.esm.js';
4
+ export { convertLegacyApp, convertLegacyAppRoot } from './convertLegacyApp.esm.js';
5
5
  export { convertLegacyAppOptions } from './convertLegacyAppOptions.esm.js';
6
6
  export { convertLegacyPlugin } from './convertLegacyPlugin.esm.js';
7
7
  export { convertLegacyPageExtension } from './convertLegacyPageExtension.esm.js';
@@ -1 +1 @@
1
- {"version":3,"file":"normalizeRoutePath.esm.js","sources":["../src/normalizeRoutePath.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\n/**\n * Normalizes the path to make sure it always starts with a single '/' and do not end with '/' or '*' unless empty\n */\nexport function normalizeRoutePath(path: string) {\n let normalized = path;\n while (normalized.endsWith('/') || normalized.endsWith('*')) {\n normalized = normalized.slice(0, -1);\n }\n while (normalized.startsWith('/')) {\n normalized = normalized.slice(1);\n }\n if (!normalized) {\n return '/';\n }\n return `/${normalized}`;\n}\n"],"names":[],"mappings":"AAmBO,SAAS,mBAAmB,IAAc,EAAA;AAC/C,EAAA,IAAI,UAAa,GAAA,IAAA;AACjB,EAAA,OAAO,WAAW,QAAS,CAAA,GAAG,KAAK,UAAW,CAAA,QAAA,CAAS,GAAG,CAAG,EAAA;AAC3D,IAAa,UAAA,GAAA,UAAA,CAAW,KAAM,CAAA,CAAA,EAAG,CAAE,CAAA,CAAA;AAAA;AAErC,EAAO,OAAA,UAAA,CAAW,UAAW,CAAA,GAAG,CAAG,EAAA;AACjC,IAAa,UAAA,GAAA,UAAA,CAAW,MAAM,CAAC,CAAA;AAAA;AAEjC,EAAA,IAAI,CAAC,UAAY,EAAA;AACf,IAAO,OAAA,GAAA;AAAA;AAET,EAAA,OAAO,IAAI,UAAU,CAAA,CAAA;AACvB;;;;"}
1
+ {"version":3,"file":"normalizeRoutePath.esm.js","sources":["../src/normalizeRoutePath.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\n/**\n * Normalizes the path to make sure it always starts with a single '/' and do not end with '/' or '*' unless empty\n */\nexport function normalizeRoutePath(path: string) {\n let normalized = path;\n while (normalized.endsWith('/') || normalized.endsWith('*')) {\n normalized = normalized.slice(0, -1);\n }\n while (normalized.startsWith('/')) {\n normalized = normalized.slice(1);\n }\n if (!normalized) {\n return '/';\n }\n return `/${normalized}`;\n}\n"],"names":[],"mappings":"AAmBO,SAAS,mBAAmB,IAAA,EAAc;AAC/C,EAAA,IAAI,UAAA,GAAa,IAAA;AACjB,EAAA,OAAO,WAAW,QAAA,CAAS,GAAG,KAAK,UAAA,CAAW,QAAA,CAAS,GAAG,CAAA,EAAG;AAC3D,IAAA,UAAA,GAAa,UAAA,CAAW,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACrC;AACA,EAAA,OAAO,UAAA,CAAW,UAAA,CAAW,GAAG,CAAA,EAAG;AACjC,IAAA,UAAA,GAAa,UAAA,CAAW,MAAM,CAAC,CAAA;AAAA,EACjC;AACA,EAAA,IAAI,CAAC,UAAA,EAAY;AACf,IAAA,OAAO,GAAA;AAAA,EACT;AACA,EAAA,OAAO,IAAI,UAAU,CAAA,CAAA;AACvB;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/core-compat-api",
3
- "version": "0.5.0-next.2",
3
+ "version": "0.5.0",
4
4
  "backstage": {
5
5
  "role": "web-library"
6
6
  },
@@ -31,20 +31,20 @@
31
31
  "test": "backstage-cli package test"
32
32
  },
33
33
  "dependencies": {
34
- "@backstage/core-plugin-api": "1.10.9",
35
- "@backstage/frontend-plugin-api": "0.11.0-next.1",
36
- "@backstage/plugin-catalog-react": "1.20.0-next.2",
37
- "@backstage/version-bridge": "1.0.11",
34
+ "@backstage/core-plugin-api": "^1.10.9",
35
+ "@backstage/frontend-plugin-api": "^0.11.0",
36
+ "@backstage/plugin-catalog-react": "^1.20.0",
37
+ "@backstage/version-bridge": "^1.0.11",
38
38
  "lodash": "^4.17.21"
39
39
  },
40
40
  "devDependencies": {
41
- "@backstage/cli": "0.34.0-next.1",
42
- "@backstage/core-app-api": "1.18.0",
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
- "@backstage/test-utils": "1.7.11-next.0",
47
- "@backstage/types": "1.2.1",
41
+ "@backstage/cli": "^0.34.0",
42
+ "@backstage/core-app-api": "^1.18.0",
43
+ "@backstage/frontend-app-api": "^0.12.0",
44
+ "@backstage/frontend-test-utils": "^0.3.5",
45
+ "@backstage/plugin-catalog": "^1.31.2",
46
+ "@backstage/test-utils": "^1.7.11",
47
+ "@backstage/types": "^1.2.1",
48
48
  "@testing-library/jest-dom": "^6.0.0",
49
49
  "@testing-library/react": "^16.0.0",
50
50
  "@types/react": "^18.0.0",