Merge pull request #29190 from backstage/rugvip/norm
core-compat-api: better normalization of discovered route paths
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-compat-api': patch
|
||||
---
|
||||
|
||||
Improved route path normalization when converting existing route elements in `converLegacyApp`, for example handling trailing `/*` in paths.
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
EntityCardBlueprint,
|
||||
EntityContentBlueprint,
|
||||
} from '@backstage/plugin-catalog-react/alpha';
|
||||
import { normalizeRoutePath } from './normalizeRoutePath';
|
||||
|
||||
const ENTITY_SWITCH_KEY = 'core.backstage.entitySwitch';
|
||||
const ENTITY_ROUTE_KEY = 'plugin.catalog.entityLayoutRoute';
|
||||
@@ -114,7 +115,7 @@ export function collectEntityPageContents(
|
||||
name,
|
||||
factory(originalFactory, { apis }) {
|
||||
return originalFactory({
|
||||
defaultPath: pageNode.path,
|
||||
defaultPath: normalizeRoutePath(pageNode.path),
|
||||
defaultTitle: pageNode.title,
|
||||
filter: mergedIf && (entity => mergedIf(entity, { apis })),
|
||||
loader: () => Promise.resolve(pageNode.children),
|
||||
|
||||
@@ -41,6 +41,7 @@ import {
|
||||
} from './convertLegacyRouteRef';
|
||||
import { compatWrapper } from './compatWrapper';
|
||||
import { collectEntityPageContents } from './collectEntityPageContents';
|
||||
import { normalizeRoutePath } from './normalizeRoutePath';
|
||||
|
||||
/*
|
||||
|
||||
@@ -236,7 +237,7 @@ export function collectLegacyRoutes(
|
||||
factory(originalFactory, { inputs: _inputs }) {
|
||||
// todo(blam): why do we not use the inputs here?
|
||||
return originalFactory({
|
||||
defaultPath: path[0] === '/' ? path.slice(1) : path,
|
||||
defaultPath: normalizeRoutePath(path),
|
||||
routeRef: routeRef ? convertLegacyRouteRef(routeRef) : undefined,
|
||||
loader: async () =>
|
||||
compatWrapper(
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2025 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 { normalizeRoutePath } from './normalizeRoutePath';
|
||||
|
||||
describe('normalizeRoutePath', () => {
|
||||
it('should normalize the path', () => {
|
||||
expect(normalizeRoutePath('')).toBe('/');
|
||||
expect(normalizeRoutePath('/')).toBe('/');
|
||||
expect(normalizeRoutePath('/*')).toBe('/');
|
||||
expect(normalizeRoutePath('/////')).toBe('/');
|
||||
expect(normalizeRoutePath('*//*//*')).toBe('/');
|
||||
expect(normalizeRoutePath('/foo')).toBe('/foo');
|
||||
expect(normalizeRoutePath('/foo/')).toBe('/foo');
|
||||
expect(normalizeRoutePath('/foo/*')).toBe('/foo');
|
||||
expect(normalizeRoutePath('/foo/**')).toBe('/foo');
|
||||
expect(normalizeRoutePath('/foo//**')).toBe('/foo');
|
||||
expect(normalizeRoutePath('/foo/*/*')).toBe('/foo');
|
||||
expect(normalizeRoutePath('//foo/*/*')).toBe('/foo');
|
||||
expect(normalizeRoutePath('/foo/bar//*/*')).toBe('/foo/bar');
|
||||
expect(normalizeRoutePath('/foo//bar//*/*')).toBe('/foo//bar');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2025 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Normalizes the path to make sure it always starts with a single '/' and do not end with '/' or '*' unless empty
|
||||
*/
|
||||
export function normalizeRoutePath(path: string) {
|
||||
let normalized = path;
|
||||
while (normalized.endsWith('/') || normalized.endsWith('*')) {
|
||||
normalized = normalized.slice(0, -1);
|
||||
}
|
||||
while (normalized.startsWith('/')) {
|
||||
normalized = normalized.slice(1);
|
||||
}
|
||||
if (!normalized) {
|
||||
return '/';
|
||||
}
|
||||
return `/${normalized}`;
|
||||
}
|
||||
Reference in New Issue
Block a user