From 659651bfcca1f9e9ae71b22a19b812c33d89654b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Oct 2023 17:26:04 +0200 Subject: [PATCH] frontend-app-api: added utility for collecting route IDs Signed-off-by: Patrik Oldsberg --- .../src/routing/collectRouteIds.test.ts | 51 ++++++++++++++ .../src/routing/collectRouteIds.ts | 70 +++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 packages/frontend-app-api/src/routing/collectRouteIds.test.ts create mode 100644 packages/frontend-app-api/src/routing/collectRouteIds.ts diff --git a/packages/frontend-app-api/src/routing/collectRouteIds.test.ts b/packages/frontend-app-api/src/routing/collectRouteIds.test.ts new file mode 100644 index 0000000000..95a5afd8cd --- /dev/null +++ b/packages/frontend-app-api/src/routing/collectRouteIds.test.ts @@ -0,0 +1,51 @@ +/* + * 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 { + createRouteRef, + createExternalRouteRef, + createPlugin, +} from '@backstage/frontend-plugin-api'; +import { collectRouteIds } from './collectRouteIds'; + +describe('collectRouteIds', () => { + it('should assign IDs to routes', () => { + const ref = createRouteRef(); + const extRef = createExternalRouteRef(); + + expect(String(ref)).toMatch( + /^RouteRef\{created at '.*collectRouteIds\.test\.ts.*'\}$/, + ); + expect(String(extRef)).toMatch( + /^ExternalRouteRef\{created at '.*collectRouteIds\.test\.ts.*'\}$/, + ); + + const collected = collectRouteIds([ + createPlugin({ id: 'test', routes: { ref }, externalRoutes: { extRef } }), + ]); + expect(Object.fromEntries(collected.routes)).toEqual({ + 'plugin.test.routes.ref': ref, + }); + expect(Object.fromEntries(collected.externalRoutes)).toEqual({ + 'plugin.test.externalRoutes.extRef': extRef, + }); + + expect(String(ref)).toBe('RouteRef{plugin.test.routes.ref}'); + expect(String(extRef)).toBe( + 'ExternalRouteRef{plugin.test.externalRoutes.extRef}', + ); + }); +}); diff --git a/packages/frontend-app-api/src/routing/collectRouteIds.ts b/packages/frontend-app-api/src/routing/collectRouteIds.ts new file mode 100644 index 0000000000..7e2a4cad2e --- /dev/null +++ b/packages/frontend-app-api/src/routing/collectRouteIds.ts @@ -0,0 +1,70 @@ +/* + * 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 { + BackstagePlugin, + ExtensionOverrides, + RouteRef, + SubRouteRef, + ExternalRouteRef, +} from '@backstage/frontend-plugin-api'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { toInternalRouteRef } from '../../../frontend-plugin-api/src/routing/RouteRef'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { toInternalExternalRouteRef } from '../../../frontend-plugin-api/src/routing/ExternalRouteRef'; + +/** @internal */ +export interface RouteRefsById { + routes: Map; + externalRoutes: Map; +} + +/** @internal */ +export function collectRouteIds( + features: (BackstagePlugin | ExtensionOverrides)[], +): RouteRefsById { + const routesById = new Map(); + const externalRoutesById = new Map(); + + for (const feature of features) { + if (feature.$$type !== '@backstage/BackstagePlugin') { + continue; + } + + for (const [name, ref] of Object.entries(feature.routes)) { + const refId = `plugin.${feature.id}.routes.${name}`; + if (routesById.has(refId)) { + throw new Error(`Unexpected duplicate route '${refId}'`); + } + + const internalRef = toInternalRouteRef(ref); + internalRef.setId(refId); + routesById.set(refId, ref); + } + for (const [name, ref] of Object.entries(feature.externalRoutes)) { + const refId = `plugin.${feature.id}.externalRoutes.${name}`; + if (externalRoutesById.has(refId)) { + throw new Error(`Unexpected duplicate external route '${refId}'`); + } + + const internalRef = toInternalExternalRouteRef(ref); + internalRef.setId(refId); + externalRoutesById.set(refId, ref); + } + } + + return { routes: routesById, externalRoutes: externalRoutesById }; +}