diff --git a/packages/core-compat-api/package.json b/packages/core-compat-api/package.json
index 76c3bc6b4e..19d3104103 100644
--- a/packages/core-compat-api/package.json
+++ b/packages/core-compat-api/package.json
@@ -25,9 +25,21 @@
},
"devDependencies": {
"@backstage/cli": "workspace:^",
+ "@backstage/core-app-api": "workspace:^",
+ "@backstage/plugin-puppetdb": "workspace:^",
+ "@backstage/plugin-stackstorm": "workspace:^",
+ "@oriflame/backstage-plugin-score-card": "^0.7.0",
"@testing-library/jest-dom": "^5.10.1"
},
"files": [
"dist"
- ]
+ ],
+ "peerDependencies": {
+ "react": "*",
+ "react-router-dom": "*"
+ },
+ "dependencies": {
+ "@backstage/core-plugin-api": "workspace:^",
+ "@backstage/frontend-plugin-api": "workspace:^"
+ }
}
diff --git a/packages/core-compat-api/src/collectLegacyRoutes.test.tsx b/packages/core-compat-api/src/collectLegacyRoutes.test.tsx
new file mode 100644
index 0000000000..530013c283
--- /dev/null
+++ b/packages/core-compat-api/src/collectLegacyRoutes.test.tsx
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2023 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import { FlatRoutes } from '@backstage/core-app-api';
+import { createPageExtension } from '@backstage/frontend-plugin-api';
+import { PuppetDbPage } from '@backstage/plugin-puppetdb';
+import { StackstormPage } from '@backstage/plugin-stackstorm';
+import { ScoreBoardPage } from '@oriflame/backstage-plugin-score-card';
+import { Route } from 'react-router-dom';
+
+import { getComponentData } from '@backstage/core-plugin-api';
+import { collectLegacyRoutes } from './collectLegacyRoutes';
+
+jest.mock('@backstage/frontend-plugin-api', () => ({
+ ...jest.requireActual('@backstage/frontend-plugin-api'),
+ createPageExtension: opts => opts,
+}));
+
+describe('collectLegacyRoutes', () => {
+ it('should collect legacy routes', () => {
+ const collected = collectLegacyRoutes(
+
+ } />
+ } />
+ } />
+ ,
+ );
+
+ expect(collected).toEqual([
+ createPageExtension({
+ id: 'plugin.score-card.page',
+ defaultPath: 'score-board',
+ routeRef: getComponentData(, 'core.mountPoint'),
+ loader: expect.any(Function),
+ }),
+ createPageExtension({
+ id: 'plugin.stackstorm.page',
+ defaultPath: 'stackstorm',
+ routeRef: getComponentData(, 'core.mountPoint'),
+ loader: expect.any(Function),
+ }),
+ createPageExtension({
+ id: 'plugin.puppetDb.page',
+ defaultPath: 'puppetdb',
+ routeRef: getComponentData(, 'core.mountPoint'),
+ loader: expect.any(Function),
+ }),
+ // ??????????????
+ ]);
+ });
+});
diff --git a/packages/core-compat-api/src/collectLegacyRoutes.tsx b/packages/core-compat-api/src/collectLegacyRoutes.tsx
new file mode 100644
index 0000000000..b40ae78439
--- /dev/null
+++ b/packages/core-compat-api/src/collectLegacyRoutes.tsx
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2023 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { ReactNode } from 'react';
+import { Extension, createPageExtension } from '@backstage/frontend-plugin-api';
+import { Route, Routes } from 'react-router-dom';
+import {
+ BackstagePlugin,
+ RouteRef,
+ getComponentData,
+} from '@backstage/core-plugin-api';
+
+export function collectLegacyRoutes(
+ flatRoutesElement: JSX.Element,
+): Extension[] {
+ // const results = traverseElementTree({
+ // root,
+ // discoverers: [childDiscoverer, routeElementDiscoverer],
+ // collectors: {
+ // foo: createCollector(
+ // () => new Set(),
+ // (acc, node) => {
+ // const plugin = getComponentData(node, 'core.plugin');
+ // if (plugin) {
+ // acc.add(plugin);
+ // }
+ // },
+ // )
+ // },
+ // })
+ const results = new Array>();
+
+ React.Children.forEach(
+ flatRoutesElement.props.children,
+ (route: ReactNode) => {
+ if (!React.isValidElement(route)) {
+ return;
+ }
+
+ // TODO(freben): Handle feature flag and permissions framework wrapper elements
+ if (route.type !== Route) {
+ return;
+ }
+
+ const routeElement = route.props.element;
+
+ // TODO: to support deeper extension component, e.g. hidden within , use https://github.com/backstage/backstage/blob/518a34646b79ec2028cc0ed6bc67d4366c51c4d6/packages/core-app-api/src/routing/collectors.tsx#L69
+ const plugin = getComponentData(
+ routeElement,
+ 'core.plugin',
+ );
+ if (!plugin) {
+ return;
+ }
+
+ const routeRef = getComponentData(
+ routeElement,
+ 'core.mountPoint',
+ );
+
+ const pluginId = plugin.getId();
+ const path: string = route.props.path;
+
+ const detectedExtension = createPageExtension({
+ id: `plugin.${pluginId}.page`,
+ defaultPath: path[0] === '/' ? path.slice(1) : path,
+ routeRef,
+
+ loader: async () =>
+ route.props.children ? (
+
+
+
+
+
+ ) : (
+ routeElement
+ ),
+ });
+
+ plugin.getApis(); // Create DI API extensions from these
+
+ // TODO: Create converted plugin instance instead. We need to move over APIs etc.
+ results.push(detectedExtension);
+ },
+ );
+
+ // TODO: For every legacy plugin that we find, make sure any matching plugin is disabled in the new system
+ return results;
+}
diff --git a/yarn.lock b/yarn.lock
index 0d17afeec6..1c101630dc 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3957,7 +3957,16 @@ __metadata:
resolution: "@backstage/core-compat-api@workspace:packages/core-compat-api"
dependencies:
"@backstage/cli": "workspace:^"
+ "@backstage/core-app-api": "workspace:^"
+ "@backstage/core-plugin-api": "workspace:^"
+ "@backstage/frontend-plugin-api": "workspace:^"
+ "@backstage/plugin-puppetdb": "workspace:^"
+ "@backstage/plugin-stackstorm": "workspace:^"
+ "@oriflame/backstage-plugin-score-card": ^0.7.0
"@testing-library/jest-dom": ^5.10.1
+ peerDependencies:
+ react: "*"
+ react-router-dom: "*"
languageName: unknown
linkType: soft