From e8bc1d99d9df55cecdefc8399346cf11ec2433b9 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 16 Apr 2026 22:17:34 +0200 Subject: [PATCH] frontend-app-api: deduplicate joinPaths utility in routing Extract the identical joinPaths function from both extractRouteInfoFromAppNode.ts and RouteResolver.ts into a shared joinPaths.ts module, then import it from both consumers. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .../src/routing/RouteResolver.ts | 10 +------- .../routing/extractRouteInfoFromAppNode.ts | 10 +------- .../frontend-app-api/src/routing/joinPaths.ts | 24 +++++++++++++++++++ 3 files changed, 26 insertions(+), 18 deletions(-) create mode 100644 packages/frontend-app-api/src/routing/joinPaths.ts diff --git a/packages/frontend-app-api/src/routing/RouteResolver.ts b/packages/frontend-app-api/src/routing/RouteResolver.ts index 7fd7ef934c..a19105b387 100644 --- a/packages/frontend-app-api/src/routing/RouteResolver.ts +++ b/packages/frontend-app-api/src/routing/RouteResolver.ts @@ -31,15 +31,7 @@ import { OpaqueSubRouteRef, } from '@internal/frontend'; import { RouteAliasResolver } from './RouteAliasResolver'; - -// Joins a list of paths together, avoiding trailing and duplicate slashes -export function joinPaths(...paths: string[]): string { - const normalized = paths.join('/').replace(/\/\/+/g, '/'); - if (normalized !== '/' && normalized.endsWith('/')) { - return normalized.slice(0, -1); - } - return normalized; -} +import { joinPaths } from './joinPaths'; /** * Resolves the absolute route ref that our target route ref is pointing pointing to, as well diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts index 4d88fb5fb1..062a54f709 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts @@ -21,6 +21,7 @@ import { createExactRouteAliasResolver, RouteAliasResolver, } from './RouteAliasResolver'; +import { joinPaths } from './joinPaths'; /** @internal */ export type RouteInfo = { @@ -41,15 +42,6 @@ export const MATCH_ALL_ROUTE: BackstageRouteObject = { routeRefs: new Set(), }; -// Joins a list of paths together, avoiding trailing and duplicate slashes -export function joinPaths(...paths: string[]): string { - const normalized = paths.join('/').replace(/\/\/+/g, '/'); - if (normalized !== '/' && normalized.endsWith('/')) { - return normalized.slice(0, -1); - } - return normalized; -} - export function extractRouteInfoFromAppNode( node: AppNode, routeAliasResolver: RouteAliasResolver, diff --git a/packages/frontend-app-api/src/routing/joinPaths.ts b/packages/frontend-app-api/src/routing/joinPaths.ts new file mode 100644 index 0000000000..89b84bb51c --- /dev/null +++ b/packages/frontend-app-api/src/routing/joinPaths.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +// Joins a list of paths together, avoiding trailing and duplicate slashes +export function joinPaths(...paths: string[]): string { + const normalized = paths.join('/').replace(/\/\/+/g, '/'); + if (normalized !== '/' && normalized.endsWith('/')) { + return normalized.slice(0, -1); + } + return normalized; +}