From 1909d0cccfd78e3204b8235c8324e08f51195daf Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 28 May 2021 14:05:00 +0200 Subject: [PATCH] core-*-api: revert breaking changes and un-deprecate AppContext.getPlugins() Signed-off-by: Patrik Oldsberg --- packages/core-app-api/src/app/App.tsx | 4 ++ .../core-app-api/src/app/AppContext.test.tsx | 5 +++ packages/core-app-api/src/app/types.ts | 5 +++ packages/core-app-api/src/routing/types.ts | 5 ++- .../core-plugin-api/src/apis/system/ApiRef.ts | 14 ++++++- packages/core-plugin-api/src/app/types.ts | 6 +++ .../core-plugin-api/src/routing/RouteRef.ts | 41 +++++++++++++++++-- packages/core-plugin-api/src/routing/types.ts | 17 ++++++++ 8 files changed, 92 insertions(+), 5 deletions(-) diff --git a/packages/core-app-api/src/app/App.tsx b/packages/core-app-api/src/app/App.tsx index fa33103652..a5ba5c4bca 100644 --- a/packages/core-app-api/src/app/App.tsx +++ b/packages/core-app-api/src/app/App.tsx @@ -155,6 +155,10 @@ function useConfigLoader( class AppContextImpl implements AppContext { constructor(private readonly app: PrivateAppImpl) {} + getPlugins(): BackstagePlugin[] { + return this.app.getPlugins(); + } + getSystemIcon(key: string): IconComponent | undefined { return this.app.getSystemIcon(key); } diff --git a/packages/core-app-api/src/app/AppContext.test.tsx b/packages/core-app-api/src/app/AppContext.test.tsx index 4299e46265..224499b148 100644 --- a/packages/core-app-api/src/app/AppContext.test.tsx +++ b/packages/core-app-api/src/app/AppContext.test.tsx @@ -36,6 +36,7 @@ describe('v1 consumer', () => { it('should provide an app context', () => { const mockContext: AppContextV1 = { + getPlugins: jest.fn(), getComponents: jest.fn(), getSystemIcon: jest.fn(), }; @@ -47,6 +48,10 @@ describe('v1 consumer', () => { }); const result = renderedHook.result.current; + expect(mockContext.getPlugins).toHaveBeenCalledTimes(0); + result.getPlugins(); + expect(mockContext.getPlugins).toHaveBeenCalledTimes(1); + expect(mockContext.getComponents).toHaveBeenCalledTimes(0); result.getComponents(); expect(mockContext.getComponents).toHaveBeenCalledTimes(1); diff --git a/packages/core-app-api/src/app/types.ts b/packages/core-app-api/src/app/types.ts index ceed0fdfef..85be0c5f53 100644 --- a/packages/core-app-api/src/app/types.ts +++ b/packages/core-app-api/src/app/types.ts @@ -227,6 +227,11 @@ export type BackstageApp = { }; export type AppContext = { + /** + * Get a list of all plugins that are installed in the app. + */ + getPlugins(): BackstagePlugin[]; + /** * Get a common or custom icon for this app. */ diff --git a/packages/core-app-api/src/routing/types.ts b/packages/core-app-api/src/routing/types.ts index 128ea37d2c..53128642f9 100644 --- a/packages/core-app-api/src/routing/types.ts +++ b/packages/core-app-api/src/routing/types.ts @@ -21,7 +21,10 @@ import { } from '@backstage/core-plugin-api'; import { getOrCreateGlobalSingleton } from '../lib/globalObject'; -type RouteRefType = Exclude; +type RouteRefType = Exclude< + keyof RouteRef, + 'params' | 'path' | 'title' | 'icon' +>; export const routeRefType: RouteRefType = getOrCreateGlobalSingleton( 'route-ref-type', () => Symbol('route-ref-type'), diff --git a/packages/core-plugin-api/src/apis/system/ApiRef.ts b/packages/core-plugin-api/src/apis/system/ApiRef.ts index 470f4cec39..397402cdc3 100644 --- a/packages/core-plugin-api/src/apis/system/ApiRef.ts +++ b/packages/core-plugin-api/src/apis/system/ApiRef.ts @@ -16,7 +16,13 @@ import type { ApiRef } from './types'; -export type ApiRefConfig = { id: string }; +export type ApiRefConfig = { + id: string; + /** + * @deprecated Will be removed in the future + */ + description?: string; +}; class ApiRefImpl implements ApiRef { constructor(private readonly config: ApiRefConfig) { @@ -35,6 +41,12 @@ class ApiRefImpl implements ApiRef { return this.config.id; } + get description() { + // eslint-disable-next-line no-console + console.warn('Deprecated use of ApiRef.description'); + return this.config.description; + } + // Utility for getting type of an api, using `typeof apiRef.T` get T(): T { throw new Error(`tried to read ApiRef.T of ${this}`); diff --git a/packages/core-plugin-api/src/app/types.ts b/packages/core-plugin-api/src/app/types.ts index d779f1fadd..66796fd5a4 100644 --- a/packages/core-plugin-api/src/app/types.ts +++ b/packages/core-plugin-api/src/app/types.ts @@ -17,6 +17,7 @@ import { ComponentType } from 'react'; import { ProfileInfo } from '../apis/definitions'; import { IconComponent } from '../icons'; +import { BackstagePlugin } from '../plugin/types'; export type BootErrorPageProps = { step: 'load-config' | 'load-chunk'; @@ -68,6 +69,11 @@ export type AppComponents = { }; export type AppContext = { + /** + * Get a list of all plugins that are installed in the app. + */ + getPlugins(): BackstagePlugin[]; + /** * Get a common or custom icon for this app. */ diff --git a/packages/core-plugin-api/src/routing/RouteRef.ts b/packages/core-plugin-api/src/routing/RouteRef.ts index 2cd18794b6..f6499ccc9f 100644 --- a/packages/core-plugin-api/src/routing/RouteRef.ts +++ b/packages/core-plugin-api/src/routing/RouteRef.ts @@ -21,6 +21,15 @@ import { ParamKeys, OptionalParams, } from './types'; +import { IconComponent } from '../icons/types'; + +// TODO(Rugvip): Remove this in the next breaking release, it's exported but unused +export type RouteRefConfig = { + params?: ParamKeys; + path?: string; + icon?: IconComponent; + title: string; +}; export class RouteRefImpl implements RouteRef { @@ -29,8 +38,26 @@ export class RouteRefImpl constructor( private readonly id: string, readonly params: ParamKeys, + private readonly config: { + path?: string; + icon?: IconComponent; + title?: string; + }, ) {} + get icon() { + return this.config.icon; + } + + // TODO(Rugvip): Remove this, routes are looked up via the registry instead + get path() { + return this.config.path ?? ''; + } + + get title() { + return this.config.title ?? this.id; + } + toString() { return `routeRef{type=absolute,id=${this.id}}`; } @@ -46,15 +73,23 @@ export function createRouteRef< ParamKey extends string = never >(config: { /** The id of the route ref, used to identify it when printed */ - id: string; + id?: string; /** A list of parameter names that the path that this route ref is bound to must contain */ 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> { - if (!config.id) { + const id = config.id || config.title; + if (!id) { throw new Error('RouteRef must be provided a non-empty id'); } return new RouteRefImpl( - config.id, + id, (config.params ?? []) as ParamKeys>, + config, ); } diff --git a/packages/core-plugin-api/src/routing/types.ts b/packages/core-plugin-api/src/routing/types.ts index aba66dc1e7..0089e29e4b 100644 --- a/packages/core-plugin-api/src/routing/types.ts +++ b/packages/core-plugin-api/src/routing/types.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { IconComponent } from '../icons/types'; import { getOrCreateGlobalSingleton } from '../lib/globalObject'; export type AnyParams = { [param in string]: string } | undefined; @@ -42,6 +43,14 @@ export type RouteRef = { readonly [routeRefType]: 'absolute'; params: ParamKeys; + + // 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; + /** @deprecated titles are no longer accessed via RouteRefs */ + title?: string; }; export type SubRouteRef = { @@ -70,6 +79,14 @@ export type AnyRouteRef = | SubRouteRef | ExternalRouteRef; +// TODO(Rugvip): None of these should be found in the wild anymore, remove in next minor release +/** @deprecated */ +export type ConcreteRoute = {}; +/** @deprecated */ +export type AbsoluteRouteRef = RouteRef<{}>; +/** @deprecated */ +export type MutableRouteRef = RouteRef<{}>; + // A duplicate of the react-router RouteObject, but with routeRef added export interface BackstageRouteObject { caseSensitive: boolean;