diff --git a/packages/frontend-plugin-api/src/routing/types.ts b/packages/frontend-plugin-api/src/routing/types.ts index 2eaa25ba94..583bc4f815 100644 --- a/packages/frontend-plugin-api/src/routing/types.ts +++ b/packages/frontend-plugin-api/src/routing/types.ts @@ -14,8 +14,6 @@ * limitations under the License. */ -import { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; - /** * Catch-all type for route params. * @@ -23,53 +21,6 @@ import { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; */ export type AnyRouteParams = { [param in string]: string } | undefined; -/** - * TS magic for handling route parameters. - * - * @remarks - * - * The extra TS magic here is to require a single params argument if the RouteRef - * had at least one param defined, but require 0 arguments if there are no params defined. - * Without this we'd have to pass in empty object to all parameter-less RouteRefs - * just to make TypeScript happy, or we would have to make the argument optional in - * which case you might forget to pass it in when it is actually required. - * - * @public - */ -export type RouteFunc = ( - ...[params]: Params extends undefined ? readonly [] : readonly [Params] -) => string; - -/** - * This symbol is what we use at runtime to determine whether a given object - * is a type of RouteRef or not. It doesn't work well in TypeScript though since - * the `unique symbol` will refer to different values between package versions. - * For that reason we use the marker $$routeRefType to represent the symbol at - * compile-time instead of using the symbol directly. - * - * @internal - */ -export const routeRefType: unique symbol = getOrCreateGlobalSingleton( - 'route-ref-type', - () => Symbol('route-ref-type'), -); - -/** - * Optional route params. - * - * @internal - */ -export type OptionalParams = - Params[keyof Params] extends never ? undefined : Params; - -/** - * Type describing the key type of a route parameter mapping. - * - * @ignore - */ -export type ParamKeys = - keyof TParams extends never ? [] : (keyof TParams)[]; - /** * A duplicate of the react-router RouteObject, but with routeRef added * @internal diff --git a/packages/frontend-plugin-api/src/routing/useRouteRef.tsx b/packages/frontend-plugin-api/src/routing/useRouteRef.tsx index cf292b110f..3754d2e6d5 100644 --- a/packages/frontend-plugin-api/src/routing/useRouteRef.tsx +++ b/packages/frontend-plugin-api/src/routing/useRouteRef.tsx @@ -17,25 +17,41 @@ import { useMemo } from 'react'; import { matchRoutes, useLocation } from 'react-router-dom'; import { useVersionedContext } from '@backstage/version-bridge'; -import { - AnyParams, - ExternalRouteRef, - RouteFunc, - RouteRef, - SubRouteRef, -} from './types'; +import { AnyRouteParams } from './types'; +import { RouteRef } from './RouteRef'; +import { SubRouteRef } from './SubRouteRef'; +import { ExternalRouteRef } from './ExternalRouteRef'; + +/** + * TS magic for handling route parameters. + * + * @remarks + * + * The extra TS magic here is to require a single params argument if the RouteRef + * had at least one param defined, but require 0 arguments if there are no params defined. + * Without this we'd have to pass in empty object to all parameter-less RouteRefs + * just to make TypeScript happy, or we would have to make the argument optional in + * which case you might forget to pass it in when it is actually required. + * + * @public + */ +export type RouteFunc = ( + ...[params]: TParams extends undefined + ? readonly [] + : readonly [params: TParams] +) => string; /** * @internal */ export interface RouteResolver { - resolve( + resolve( anyRouteRef: - | RouteRef - | SubRouteRef - | ExternalRouteRef, + | RouteRef + | SubRouteRef + | ExternalRouteRef, sourceLocation: Parameters[1], - ): RouteFunc | undefined; + ): RouteFunc | undefined; } /** @@ -49,9 +65,12 @@ export interface RouteResolver { * @returns A function that will in turn return the concrete URL of the `routeRef`. * @public */ -export function useRouteRef( - routeRef: ExternalRouteRef, -): Optional extends true ? RouteFunc | undefined : RouteFunc; +export function useRouteRef< + TOptional extends boolean, + TParams extends AnyRouteParams, +>( + routeRef: ExternalRouteRef, +): TParams extends true ? RouteFunc | undefined : RouteFunc; /** * React hook for constructing URLs to routes. @@ -64,9 +83,9 @@ export function useRouteRef( * @returns A function that will in turn return the concrete URL of the `routeRef`. * @public */ -export function useRouteRef( - routeRef: RouteRef | SubRouteRef, -): RouteFunc; +export function useRouteRef( + routeRef: RouteRef | SubRouteRef, +): RouteFunc; /** * React hook for constructing URLs to routes. @@ -79,12 +98,12 @@ export function useRouteRef( * @returns A function that will in turn return the concrete URL of the `routeRef`. * @public */ -export function useRouteRef( +export function useRouteRef( routeRef: - | RouteRef - | SubRouteRef - | ExternalRouteRef, -): RouteFunc | undefined { + | RouteRef + | SubRouteRef + | ExternalRouteRef, +): RouteFunc | undefined { const { pathname } = useLocation(); const versionedContext = useVersionedContext<{ 1: RouteResolver }>( 'routing-context', diff --git a/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts b/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts index e24576372b..dbe34a4d01 100644 --- a/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts +++ b/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts @@ -15,14 +15,16 @@ */ import { useParams } from 'react-router-dom'; -import { RouteRef, AnyParams, SubRouteRef } from './types'; +import { AnyRouteParams } from './types'; +import { RouteRef } from './RouteRef'; +import { SubRouteRef } from './SubRouteRef'; /** * React hook for retrieving dynamic params from the current URL. * @param _routeRef - Ref of the current route. * @public */ -export function useRouteRefParams( +export function useRouteRefParams( _routeRef: RouteRef | SubRouteRef, ): Params { return useParams() as Params;