diff --git a/packages/frontend-app-api/src/apis/implementations/ComponentsApi/ComponentsApi.ts b/packages/frontend-app-api/src/apis/implementations/ComponentsApi/ComponentsApi.ts index 50d125e4ab..4d8bc47e24 100644 --- a/packages/frontend-app-api/src/apis/implementations/ComponentsApi/ComponentsApi.ts +++ b/packages/frontend-app-api/src/apis/implementations/ComponentsApi/ComponentsApi.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { ComponentType } from 'react'; import { ComponentRef, ComponentsApi } from '@backstage/frontend-plugin-api'; /** @@ -22,13 +23,13 @@ import { ComponentRef, ComponentsApi } from '@backstage/frontend-plugin-api'; * @internal */ export class DefaultComponentsApi implements ComponentsApi { - #components: Map, any>; + #components: Map, ComponentType>; constructor(components: Map, any>) { this.#components = components; } - getComponent(ref: ComponentRef): T { + getComponent(ref: ComponentRef): ComponentType { const impl = this.#components.get(ref); if (!impl) { throw new Error(`No implementation found for component ref ${ref}`); diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index e578c181fb..7342558560 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -286,7 +286,7 @@ export type CommonAnalyticsContext = { }; // @public (undocumented) -export type ComponentRef = { +export type ComponentRef = { id: string; T: T; }; @@ -294,7 +294,7 @@ export type ComponentRef = { // @public export interface ComponentsApi { // (undocumented) - getComponent(ref: ComponentRef): T; + getComponent(ref: ComponentRef): ComponentType; } // @public @@ -321,29 +321,29 @@ export interface ConfigurableExtensionDataRef< } // @public (undocumented) -export type CoreBootErrorPageComponent = ComponentType< - PropsWithChildren<{ - step: 'load-config' | 'load-chunk'; - error: Error; - }> ->; +export type CoreBootErrorPageProps = PropsWithChildren<{ + step: 'load-config' | 'load-chunk'; + error: Error; +}>; // @public (undocumented) export const coreComponentsRefs: { - progress: ComponentRef; - bootErrorPage: ComponentRef; - notFoundErrorPage: ComponentRef; - errorBoundaryFallback: ComponentRef; + progress: ComponentRef<{ + children?: ReactNode; + }>; + bootErrorPage: ComponentRef; + notFoundErrorPage: ComponentRef<{ + children?: ReactNode; + }>; + errorBoundaryFallback: ComponentRef; }; // @public (undocumented) -export type CoreErrorBoundaryFallbackComponent = ComponentType< - PropsWithChildren<{ - plugin?: BackstagePlugin; - error: Error; - resetError: () => void; - }> ->; +export type CoreErrorBoundaryFallbackProps = PropsWithChildren<{ + plugin?: BackstagePlugin; + error: Error; + resetError: () => void; +}>; // @public (undocumented) export const coreExtensionData: { @@ -356,20 +356,18 @@ export const coreExtensionData: { logoElements: ConfigurableExtensionDataRef; component: ConfigurableExtensionDataRef< { - ref: ComponentRef>; - impl: ComponentType; + ref: ComponentRef; + impl: ComponentType; }, {} >; }; // @public (undocumented) -export type CoreNotFoundErrorPageComponent = ComponentType< - PropsWithChildren<{}> ->; +export type CoreNotFoundErrorPageProps = PropsWithChildren<{}>; // @public (undocumented) -export type CoreProgressComponent = ComponentType>; +export type CoreProgressProps = PropsWithChildren<{}>; // @public (undocumented) export function createApiExtension< @@ -399,11 +397,11 @@ export { createApiRef }; // @public (undocumented) export function createComponentExtension< - TRef extends ComponentRef, + TProps extends {}, TConfig extends {}, TInputs extends AnyExtensionInputMap, >(options: { - ref: TRef; + ref: ComponentRef; name?: string; disabled?: boolean; inputs?: TInputs; @@ -413,13 +411,13 @@ export function createComponentExtension< lazy: (values: { config: TConfig; inputs: Expand>; - }) => Promise; + }) => Promise>; } | { sync: (values: { config: TConfig; inputs: Expand>; - }) => TRef['T']; + }) => ComponentType; }; }): ExtensionDefinition; diff --git a/packages/frontend-plugin-api/src/apis/definitions/ComponentsApi.ts b/packages/frontend-plugin-api/src/apis/definitions/ComponentsApi.ts index b55ed96549..dee17e7d97 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/ComponentsApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/ComponentsApi.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { ComponentType } from 'react'; import { createApiRef } from '@backstage/core-plugin-api'; import { ComponentRef } from '../../components'; @@ -24,7 +25,7 @@ import { ComponentRef } from '../../components'; */ export interface ComponentsApi { // TODO: Should component refs also provide the default implementation so that we're guaranteed to get a component? - getComponent(ref: ComponentRef): T; + getComponent(ref: ComponentRef): ComponentType; } /** diff --git a/packages/frontend-plugin-api/src/components/ComponentRef.tsx b/packages/frontend-plugin-api/src/components/ComponentRef.tsx index d096fa34f3..dd2e65a61f 100644 --- a/packages/frontend-plugin-api/src/components/ComponentRef.tsx +++ b/packages/frontend-plugin-api/src/components/ComponentRef.tsx @@ -15,20 +15,20 @@ */ import { - CoreBootErrorPageComponent, - CoreErrorBoundaryFallbackComponent, - CoreNotFoundErrorPageComponent, - CoreProgressComponent, + CoreBootErrorPageProps, + CoreErrorBoundaryFallbackProps, + CoreNotFoundErrorPageProps, + CoreProgressProps, } from '../types'; /** @public */ -export type ComponentRef = { +export type ComponentRef = { id: string; T: T; }; /** @public */ -export function createComponentRef(options: { +export function createComponentRef(options: { id: string; }): ComponentRef { const { id } = options; @@ -37,22 +37,22 @@ export function createComponentRef(options: { } as ComponentRef; } -const coreProgressComponentRef = createComponentRef({ +const coreProgressComponentRef = createComponentRef({ id: 'core.components.progress', }); const coreBootErrorPageComponentRef = - createComponentRef({ + createComponentRef({ id: 'core.components.bootErrorPage', }); const coreNotFoundErrorPageComponentRef = - createComponentRef({ + createComponentRef({ id: 'core.components.notFoundErrorPage', }); const coreErrorBoundaryFallbackComponentRef = - createComponentRef({ + createComponentRef({ id: 'core.components.errorBoundaryFallback', }); diff --git a/packages/frontend-plugin-api/src/components/ErrorBoundary.tsx b/packages/frontend-plugin-api/src/components/ErrorBoundary.tsx index e3765be386..be988dc14f 100644 --- a/packages/frontend-plugin-api/src/components/ErrorBoundary.tsx +++ b/packages/frontend-plugin-api/src/components/ErrorBoundary.tsx @@ -14,13 +14,13 @@ * limitations under the License. */ -import React, { Component, PropsWithChildren } from 'react'; +import React, { Component, ComponentType, PropsWithChildren } from 'react'; import { BackstagePlugin } from '../wiring'; -import { CoreErrorBoundaryFallbackComponent } from '../types'; +import { CoreErrorBoundaryFallbackProps } from '../types'; type ErrorBoundaryProps = PropsWithChildren<{ plugin?: BackstagePlugin; - fallback: CoreErrorBoundaryFallbackComponent; + fallback: ComponentType; }>; type ErrorBoundaryState = { error?: Error }; diff --git a/packages/frontend-plugin-api/src/extensions/createComponentExtension.tsx b/packages/frontend-plugin-api/src/extensions/createComponentExtension.tsx index 601ee81d11..816dee6054 100644 --- a/packages/frontend-plugin-api/src/extensions/createComponentExtension.tsx +++ b/packages/frontend-plugin-api/src/extensions/createComponentExtension.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { lazy } from 'react'; +import React, { lazy, ComponentType } from 'react'; import { AnyExtensionInputMap, ResolvedExtensionInputs, @@ -27,11 +27,11 @@ import { ExtensionBoundary, ComponentRef } from '../components'; /** @public */ export function createComponentExtension< - TRef extends ComponentRef, + TProps extends {}, TConfig extends {}, TInputs extends AnyExtensionInputMap, >(options: { - ref: TRef; + ref: ComponentRef; name?: string; disabled?: boolean; inputs?: TInputs; @@ -41,13 +41,13 @@ export function createComponentExtension< lazy: (values: { config: TConfig; inputs: Expand>; - }) => Promise; + }) => Promise>; } | { sync: (values: { config: TConfig; inputs: Expand>; - }) => TRef['T']; + }) => ComponentType; }; }) { return createExtension({ @@ -62,15 +62,17 @@ export function createComponentExtension< component: coreExtensionData.component, }, factory({ config, inputs, node }) { - let ExtensionComponent: TRef['T']; + let ExtensionComponent: ComponentType; if ('sync' in options.component) { ExtensionComponent = options.component.sync({ config, inputs }); } else { - const loader = options.component.lazy({ config, inputs }); + const lazyLoader = options.component.lazy; ExtensionComponent = lazy(() => - loader.then(component => ({ default: component })), - ); + lazyLoader({ config, inputs }).then(component => ({ + default: component, + })), + ) as unknown as ComponentType; } return { @@ -78,7 +80,7 @@ export function createComponentExtension< ref: options.ref, impl: props => ( - + ), }, diff --git a/packages/frontend-plugin-api/src/index.ts b/packages/frontend-plugin-api/src/index.ts index a38a7991fb..04cbddd336 100644 --- a/packages/frontend-plugin-api/src/index.ts +++ b/packages/frontend-plugin-api/src/index.ts @@ -31,8 +31,8 @@ export * from './apis/system'; export * from './wiring'; export type { - CoreProgressComponent, - CoreBootErrorPageComponent, - CoreNotFoundErrorPageComponent, - CoreErrorBoundaryFallbackComponent, + CoreProgressProps, + CoreBootErrorPageProps, + CoreNotFoundErrorPageProps, + CoreErrorBoundaryFallbackProps, } from './types'; diff --git a/packages/frontend-plugin-api/src/types.ts b/packages/frontend-plugin-api/src/types.ts index 3c79bcdf35..a69c483b5c 100644 --- a/packages/frontend-plugin-api/src/types.ts +++ b/packages/frontend-plugin-api/src/types.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { ComponentType, PropsWithChildren } from 'react'; +import { PropsWithChildren } from 'react'; import { BackstagePlugin } from './wiring'; // TODO(Rugvip): This might be a quite useful utility type, maybe add to @backstage/types? @@ -25,26 +25,20 @@ import { BackstagePlugin } from './wiring'; export type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; /** @public */ -export type CoreProgressComponent = ComponentType>; +export type CoreProgressProps = PropsWithChildren<{}>; /** @public */ -export type CoreBootErrorPageComponent = ComponentType< - PropsWithChildren<{ - step: 'load-config' | 'load-chunk'; - error: Error; - }> ->; +export type CoreBootErrorPageProps = PropsWithChildren<{ + step: 'load-config' | 'load-chunk'; + error: Error; +}>; /** @public */ -export type CoreNotFoundErrorPageComponent = ComponentType< - PropsWithChildren<{}> ->; +export type CoreNotFoundErrorPageProps = PropsWithChildren<{}>; /** @public */ -export type CoreErrorBoundaryFallbackComponent = ComponentType< - PropsWithChildren<{ - plugin?: BackstagePlugin; - error: Error; - resetError: () => void; - }> ->; +export type CoreErrorBoundaryFallbackProps = PropsWithChildren<{ + plugin?: BackstagePlugin; + error: Error; + resetError: () => void; +}>; diff --git a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts index 9bdb4b23eb..47a77414a0 100644 --- a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts +++ b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts @@ -47,7 +47,7 @@ export const coreExtensionData = { theme: createExtensionDataRef('core.theme'), logoElements: createExtensionDataRef('core.logos'), component: createExtensionDataRef<{ - ref: ComponentRef>; - impl: ComponentType; + ref: ComponentRef; + impl: ComponentType; }>('component.ref'), };