core-api: restructure route ref types to use a symbol to determine type + deprecate more fields
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -50,14 +50,13 @@ import {
|
||||
} from '../extensions/traversal';
|
||||
import { IconComponent, IconComponentMap, IconKey } from '../icons';
|
||||
import { BackstagePlugin } from '../plugin';
|
||||
import { RouteRef } from '../routing';
|
||||
import { RouteRef, ExternalRouteRef } from '../routing';
|
||||
import {
|
||||
routeObjectCollector,
|
||||
routeParentCollector,
|
||||
routePathCollector,
|
||||
} from '../routing/collectors';
|
||||
import { RoutingProvider, validateRoutes } from '../routing/hooks';
|
||||
import { ExternalRouteRef } from '../routing/RouteRef';
|
||||
import { AppContextProvider } from './AppContext';
|
||||
import { AppIdentity } from './AppIdentity';
|
||||
import { AppThemeProvider } from './AppThemeProvider';
|
||||
|
||||
@@ -15,9 +15,8 @@
|
||||
*/
|
||||
|
||||
import { ComponentType } from 'react';
|
||||
import { RouteRef } from '../routing';
|
||||
import { RouteRef, ExternalRouteRef } from '../routing';
|
||||
import { AnyApiFactory } from '../apis/system';
|
||||
import { ExternalRouteRef } from '../routing/RouteRef';
|
||||
|
||||
export type RouteOptions = {
|
||||
// Whether the route path must match exactly, defaults to true.
|
||||
|
||||
@@ -14,19 +14,31 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { RouteRef } from './types';
|
||||
import { RouteRef, ExternalRouteRef, routeRefType } from './types';
|
||||
import { IconComponent } from '../icons';
|
||||
|
||||
// TODO(Rugvip): Remove this once we get rid of the deprecated fields, it's not exported
|
||||
export type RouteRefConfig<Params extends { [param in string]: string }> = {
|
||||
params?: Array<keyof Params>;
|
||||
/** @deprecated Route refs no longer decide their own path */
|
||||
path?: string;
|
||||
icon?: IconComponent;
|
||||
title: string;
|
||||
};
|
||||
|
||||
export class AbsoluteRouteRef<Params extends { [param in string]: string }> {
|
||||
constructor(private readonly config: RouteRefConfig<Params>) {}
|
||||
class RouteRefBaseBase {
|
||||
constructor(type: string, id: string) {
|
||||
this.toString = () => `routeRef{type=${type},id=${id}}`;
|
||||
}
|
||||
}
|
||||
|
||||
export class RouteRefImpl<
|
||||
Params extends { [param in string]: string }
|
||||
> extends RouteRefBaseBase {
|
||||
readonly [routeRefType] = 'absolute';
|
||||
|
||||
constructor(private readonly config: RouteRefConfig<Params>) {
|
||||
super('absolute', config.title);
|
||||
}
|
||||
|
||||
get icon() {
|
||||
return this.config.icon;
|
||||
@@ -40,10 +52,6 @@ export class AbsoluteRouteRef<Params extends { [param in string]: string }> {
|
||||
get title() {
|
||||
return this.config.title;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `routeRef{title=${this.title}}`;
|
||||
}
|
||||
}
|
||||
|
||||
export function createRouteRef<
|
||||
@@ -58,22 +66,27 @@ export function createRouteRef<
|
||||
params?: ParamKey[];
|
||||
/** @deprecated Route refs no longer decide their own path */
|
||||
path?: string;
|
||||
/** @deprecated Route refs no longer decide their own icon */
|
||||
icon?: IconComponent;
|
||||
/** @deprecated Route refs no longer decide their own title */
|
||||
title: string;
|
||||
}): RouteRef<Params> {
|
||||
return new AbsoluteRouteRef<Params>(config);
|
||||
return new RouteRefImpl<Params>(config);
|
||||
}
|
||||
|
||||
export class ExternalRouteRef<Optional extends boolean = true> {
|
||||
readonly optional: boolean;
|
||||
export class ExternalRouteRefImpl<
|
||||
Optional extends boolean
|
||||
> extends RouteRefBaseBase {
|
||||
readonly [routeRefType] = 'external';
|
||||
|
||||
private constructor({ id, optional }: ExternalRouteRefOptions<Optional>) {
|
||||
this.toString = () => `externalRouteRef{${id}}`;
|
||||
this.optional = Boolean(optional);
|
||||
constructor(id: string, readonly optional: Optional) {
|
||||
super('external', id);
|
||||
}
|
||||
}
|
||||
|
||||
export type ExternalRouteRefOptions<Optional extends boolean = false> = {
|
||||
export function createExternalRouteRef<
|
||||
Optional extends boolean = false
|
||||
>(options: {
|
||||
/**
|
||||
* An identifier for this route, used to identify it in error messages
|
||||
*/
|
||||
@@ -86,14 +99,9 @@ export type ExternalRouteRefOptions<Optional extends boolean = false> = {
|
||||
* if they aren't, `useRouteRef` will return `undefined`.
|
||||
*/
|
||||
optional?: Optional;
|
||||
};
|
||||
|
||||
export function createExternalRouteRef<Optional extends boolean = false>(
|
||||
options: ExternalRouteRefOptions<Optional>,
|
||||
): ExternalRouteRef<Optional> {
|
||||
return new ((ExternalRouteRef as unknown) as {
|
||||
new (options: ExternalRouteRefOptions<Optional>): ExternalRouteRef<
|
||||
Optional
|
||||
>;
|
||||
})(options);
|
||||
}): ExternalRouteRef<Optional> {
|
||||
return new ExternalRouteRefImpl<Optional>(
|
||||
options.id,
|
||||
Boolean(options.optional) as Optional,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -38,10 +38,9 @@ import {
|
||||
import {
|
||||
createRouteRef,
|
||||
createExternalRouteRef,
|
||||
ExternalRouteRef,
|
||||
RouteRefConfig,
|
||||
} from './RouteRef';
|
||||
import { AnyRouteRef, RouteRef } from './types';
|
||||
import { AnyRouteRef, RouteRef, ExternalRouteRef } from './types';
|
||||
|
||||
const mockConfig = (extra?: Partial<RouteRefConfig<{}>>) => ({
|
||||
path: '/unused',
|
||||
|
||||
@@ -15,9 +15,13 @@
|
||||
*/
|
||||
|
||||
import React, { createContext, ReactNode, useContext, useMemo } from 'react';
|
||||
import { AnyRouteRef, BackstageRouteObject, RouteRef } from './types';
|
||||
import {
|
||||
AnyRouteRef,
|
||||
BackstageRouteObject,
|
||||
RouteRef,
|
||||
ExternalRouteRef,
|
||||
} from './types';
|
||||
import { generatePath, matchRoutes, useLocation } from 'react-router-dom';
|
||||
import { ExternalRouteRef } from './RouteRef';
|
||||
|
||||
// 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.
|
||||
|
||||
@@ -19,12 +19,9 @@ export type {
|
||||
AbsoluteRouteRef,
|
||||
ConcreteRoute,
|
||||
MutableRouteRef,
|
||||
ExternalRouteRef,
|
||||
} from './types';
|
||||
export { FlatRoutes } from './FlatRoutes';
|
||||
export {
|
||||
createRouteRef,
|
||||
createExternalRouteRef,
|
||||
ExternalRouteRef,
|
||||
} from './RouteRef';
|
||||
export { createRouteRef, createExternalRouteRef } from './RouteRef';
|
||||
export type { RouteRefConfig } from './RouteRef';
|
||||
export { useRouteRef } from './hooks';
|
||||
|
||||
@@ -15,35 +15,41 @@
|
||||
*/
|
||||
|
||||
import { IconComponent } from '../icons';
|
||||
import { ExternalRouteRef } from './RouteRef';
|
||||
import { getGlobalSingleton } from '../lib/globalObject';
|
||||
|
||||
// @ts-ignore, we're just embedding the Params type for usage in other places
|
||||
export type RouteRef<Params extends { [param in string]: string } = {}> = {
|
||||
// TODO(Rugvip): Remove path, look up via registry instead
|
||||
export const routeRefType: unique symbol = getGlobalSingleton<any>(
|
||||
'route-ref-type',
|
||||
() => Symbol('route-ref-type'),
|
||||
);
|
||||
|
||||
export type RouteRef<Params extends { [param in string]: string } = any> = {
|
||||
[routeRefType]: 'absolute';
|
||||
|
||||
params?: keyof Params;
|
||||
|
||||
// TODO(Rugvip): Remove all of these once plugins don't rely on the path
|
||||
/** @deprecated paths are no longer accessed directly from RouteRefs, use useRouteRef instead */
|
||||
path: string;
|
||||
/** @deprecated icons are no longer accessed via RouteRefs */
|
||||
icon?: IconComponent;
|
||||
title: string;
|
||||
/** @deprecated titles are no longer accessed via RouteRefs */
|
||||
title?: string;
|
||||
};
|
||||
|
||||
export type ExternalRouteRef<Optional extends boolean = any> = {
|
||||
[routeRefType]: 'external';
|
||||
|
||||
optional?: Optional;
|
||||
};
|
||||
|
||||
export type AnyRouteRef = RouteRef<any> | ExternalRouteRef<any>;
|
||||
|
||||
/**
|
||||
* This type should not be used
|
||||
* @deprecated
|
||||
*/
|
||||
// TODO(Rugvip): None of these should be found in the wild anymore, remove in next minor release
|
||||
/** @deprecated */
|
||||
export type ConcreteRoute = {};
|
||||
|
||||
/**
|
||||
* This type should not be used, use RouteRef instead
|
||||
* @deprecated
|
||||
*/
|
||||
/** @deprecated */
|
||||
export type AbsoluteRouteRef = RouteRef<{}>;
|
||||
|
||||
/**
|
||||
* This type should not be used, use RouteRef instead
|
||||
* @deprecated
|
||||
*/
|
||||
/** @deprecated */
|
||||
export type MutableRouteRef = RouteRef<{}>;
|
||||
|
||||
// A duplicate of the react-router RouteObject, but with routeRef added
|
||||
|
||||
Reference in New Issue
Block a user