refactor: use unknown on component ref type
Co-authored-by: Philipp Hugenroth <philipph@spotify.com> Co-authored-by: Fredrik Adelöw <freben@gmail.com> Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com> Signed-off-by: Camila Belo <camilaibs@gmail.com>
This commit is contained in:
@@ -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<ComponentRef<any>, any>;
|
||||
#components: Map<ComponentRef<any>, ComponentType<any>>;
|
||||
|
||||
constructor(components: Map<ComponentRef<any>, any>) {
|
||||
this.#components = components;
|
||||
}
|
||||
|
||||
getComponent<T>(ref: ComponentRef<T>): T {
|
||||
getComponent<T extends {}>(ref: ComponentRef<T>): ComponentType<T> {
|
||||
const impl = this.#components.get(ref);
|
||||
if (!impl) {
|
||||
throw new Error(`No implementation found for component ref ${ref}`);
|
||||
|
||||
@@ -286,7 +286,7 @@ export type CommonAnalyticsContext = {
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type ComponentRef<T> = {
|
||||
export type ComponentRef<T extends {} = {}> = {
|
||||
id: string;
|
||||
T: T;
|
||||
};
|
||||
@@ -294,7 +294,7 @@ export type ComponentRef<T> = {
|
||||
// @public
|
||||
export interface ComponentsApi {
|
||||
// (undocumented)
|
||||
getComponent<T>(ref: ComponentRef<T>): T;
|
||||
getComponent<T extends {}>(ref: ComponentRef<T>): ComponentType<T>;
|
||||
}
|
||||
|
||||
// @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<CoreProgressComponent>;
|
||||
bootErrorPage: ComponentRef<CoreBootErrorPageComponent>;
|
||||
notFoundErrorPage: ComponentRef<CoreNotFoundErrorPageComponent>;
|
||||
errorBoundaryFallback: ComponentRef<CoreErrorBoundaryFallbackComponent>;
|
||||
progress: ComponentRef<{
|
||||
children?: ReactNode;
|
||||
}>;
|
||||
bootErrorPage: ComponentRef<CoreBootErrorPageProps>;
|
||||
notFoundErrorPage: ComponentRef<{
|
||||
children?: ReactNode;
|
||||
}>;
|
||||
errorBoundaryFallback: ComponentRef<CoreErrorBoundaryFallbackProps>;
|
||||
};
|
||||
|
||||
// @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<LogoElements, {}>;
|
||||
component: ConfigurableExtensionDataRef<
|
||||
{
|
||||
ref: ComponentRef<ComponentType<any>>;
|
||||
impl: ComponentType<any>;
|
||||
ref: ComponentRef;
|
||||
impl: ComponentType;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type CoreNotFoundErrorPageComponent = ComponentType<
|
||||
PropsWithChildren<{}>
|
||||
>;
|
||||
export type CoreNotFoundErrorPageProps = PropsWithChildren<{}>;
|
||||
|
||||
// @public (undocumented)
|
||||
export type CoreProgressComponent = ComponentType<PropsWithChildren<{}>>;
|
||||
export type CoreProgressProps = PropsWithChildren<{}>;
|
||||
|
||||
// @public (undocumented)
|
||||
export function createApiExtension<
|
||||
@@ -399,11 +397,11 @@ export { createApiRef };
|
||||
|
||||
// @public (undocumented)
|
||||
export function createComponentExtension<
|
||||
TRef extends ComponentRef<any>,
|
||||
TProps extends {},
|
||||
TConfig extends {},
|
||||
TInputs extends AnyExtensionInputMap,
|
||||
>(options: {
|
||||
ref: TRef;
|
||||
ref: ComponentRef<TProps>;
|
||||
name?: string;
|
||||
disabled?: boolean;
|
||||
inputs?: TInputs;
|
||||
@@ -413,13 +411,13 @@ export function createComponentExtension<
|
||||
lazy: (values: {
|
||||
config: TConfig;
|
||||
inputs: Expand<ResolvedExtensionInputs<TInputs>>;
|
||||
}) => Promise<TRef['T']>;
|
||||
}) => Promise<ComponentType<TProps>>;
|
||||
}
|
||||
| {
|
||||
sync: (values: {
|
||||
config: TConfig;
|
||||
inputs: Expand<ResolvedExtensionInputs<TInputs>>;
|
||||
}) => TRef['T'];
|
||||
}) => ComponentType<TProps>;
|
||||
};
|
||||
}): ExtensionDefinition<TConfig>;
|
||||
|
||||
|
||||
@@ -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<T>(ref: ComponentRef<T>): T;
|
||||
getComponent<T extends {}>(ref: ComponentRef<T>): ComponentType<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,20 +15,20 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
CoreBootErrorPageComponent,
|
||||
CoreErrorBoundaryFallbackComponent,
|
||||
CoreNotFoundErrorPageComponent,
|
||||
CoreProgressComponent,
|
||||
CoreBootErrorPageProps,
|
||||
CoreErrorBoundaryFallbackProps,
|
||||
CoreNotFoundErrorPageProps,
|
||||
CoreProgressProps,
|
||||
} from '../types';
|
||||
|
||||
/** @public */
|
||||
export type ComponentRef<T> = {
|
||||
export type ComponentRef<T extends {} = {}> = {
|
||||
id: string;
|
||||
T: T;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export function createComponentRef<T>(options: {
|
||||
export function createComponentRef<T extends {} = {}>(options: {
|
||||
id: string;
|
||||
}): ComponentRef<T> {
|
||||
const { id } = options;
|
||||
@@ -37,22 +37,22 @@ export function createComponentRef<T>(options: {
|
||||
} as ComponentRef<T>;
|
||||
}
|
||||
|
||||
const coreProgressComponentRef = createComponentRef<CoreProgressComponent>({
|
||||
const coreProgressComponentRef = createComponentRef<CoreProgressProps>({
|
||||
id: 'core.components.progress',
|
||||
});
|
||||
|
||||
const coreBootErrorPageComponentRef =
|
||||
createComponentRef<CoreBootErrorPageComponent>({
|
||||
createComponentRef<CoreBootErrorPageProps>({
|
||||
id: 'core.components.bootErrorPage',
|
||||
});
|
||||
|
||||
const coreNotFoundErrorPageComponentRef =
|
||||
createComponentRef<CoreNotFoundErrorPageComponent>({
|
||||
createComponentRef<CoreNotFoundErrorPageProps>({
|
||||
id: 'core.components.notFoundErrorPage',
|
||||
});
|
||||
|
||||
const coreErrorBoundaryFallbackComponentRef =
|
||||
createComponentRef<CoreErrorBoundaryFallbackComponent>({
|
||||
createComponentRef<CoreErrorBoundaryFallbackProps>({
|
||||
id: 'core.components.errorBoundaryFallback',
|
||||
});
|
||||
|
||||
|
||||
@@ -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<CoreErrorBoundaryFallbackProps>;
|
||||
}>;
|
||||
type ErrorBoundaryState = { error?: Error };
|
||||
|
||||
|
||||
@@ -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<any>,
|
||||
TProps extends {},
|
||||
TConfig extends {},
|
||||
TInputs extends AnyExtensionInputMap,
|
||||
>(options: {
|
||||
ref: TRef;
|
||||
ref: ComponentRef<TProps>;
|
||||
name?: string;
|
||||
disabled?: boolean;
|
||||
inputs?: TInputs;
|
||||
@@ -41,13 +41,13 @@ export function createComponentExtension<
|
||||
lazy: (values: {
|
||||
config: TConfig;
|
||||
inputs: Expand<ResolvedExtensionInputs<TInputs>>;
|
||||
}) => Promise<TRef['T']>;
|
||||
}) => Promise<ComponentType<TProps>>;
|
||||
}
|
||||
| {
|
||||
sync: (values: {
|
||||
config: TConfig;
|
||||
inputs: Expand<ResolvedExtensionInputs<TInputs>>;
|
||||
}) => TRef['T'];
|
||||
}) => ComponentType<TProps>;
|
||||
};
|
||||
}) {
|
||||
return createExtension({
|
||||
@@ -62,15 +62,17 @@ export function createComponentExtension<
|
||||
component: coreExtensionData.component,
|
||||
},
|
||||
factory({ config, inputs, node }) {
|
||||
let ExtensionComponent: TRef['T'];
|
||||
let ExtensionComponent: ComponentType<TProps>;
|
||||
|
||||
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<TProps>;
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -78,7 +80,7 @@ export function createComponentExtension<
|
||||
ref: options.ref,
|
||||
impl: props => (
|
||||
<ExtensionBoundary node={node}>
|
||||
<ExtensionComponent {...props} />
|
||||
<ExtensionComponent {...(props as TProps)} />
|
||||
</ExtensionBoundary>
|
||||
),
|
||||
},
|
||||
|
||||
@@ -31,8 +31,8 @@ export * from './apis/system';
|
||||
export * from './wiring';
|
||||
|
||||
export type {
|
||||
CoreProgressComponent,
|
||||
CoreBootErrorPageComponent,
|
||||
CoreNotFoundErrorPageComponent,
|
||||
CoreErrorBoundaryFallbackComponent,
|
||||
CoreProgressProps,
|
||||
CoreBootErrorPageProps,
|
||||
CoreNotFoundErrorPageProps,
|
||||
CoreErrorBoundaryFallbackProps,
|
||||
} from './types';
|
||||
|
||||
@@ -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> = T extends infer O ? { [K in keyof O]: O[K] } : never;
|
||||
|
||||
/** @public */
|
||||
export type CoreProgressComponent = ComponentType<PropsWithChildren<{}>>;
|
||||
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;
|
||||
}>;
|
||||
|
||||
@@ -47,7 +47,7 @@ export const coreExtensionData = {
|
||||
theme: createExtensionDataRef<AppTheme>('core.theme'),
|
||||
logoElements: createExtensionDataRef<LogoElements>('core.logos'),
|
||||
component: createExtensionDataRef<{
|
||||
ref: ComponentRef<ComponentType<any>>;
|
||||
impl: ComponentType<any>;
|
||||
ref: ComponentRef;
|
||||
impl: ComponentType;
|
||||
}>('component.ref'),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user