Plugin extensions: Introduce new registry for added components (#91877)

* add added component registry

* fix broken test

* add tests for usePluginComponents hook

* readd expose components

* add type assertion exceptions to betterer results

* use new addedComponent registry in legacy endpoints

* remove unused code

* cleanup

* revert test code

* remove commented code

* wrap in try catch

* pr feedback
This commit is contained in:
Erik Sundell
2024-08-27 11:14:04 +02:00
committed by GitHub
parent 419edef4dc
commit b648ce3acf
26 changed files with 1171 additions and 205 deletions
@@ -26,11 +26,11 @@ export {
usePluginExtensions,
usePluginLinkExtensions,
usePluginComponentExtensions,
usePluginComponents,
usePluginLinks,
} from './pluginExtensions/usePluginExtensions';
export { setPluginComponentHook, usePluginComponent } from './pluginExtensions/usePluginComponent';
export { setPluginComponentsHook, usePluginComponents } from './pluginExtensions/usePluginComponents';
export { isPluginExtensionLink, isPluginExtensionComponent } from './pluginExtensions/utils';
export { setCurrentUser } from './user';
@@ -16,6 +16,11 @@ export type GetPluginExtensionsOptions = {
limitPerPlugin?: number;
};
export type UsePluginComponentOptions = {
extensionPointId: string;
limitPerPlugin?: number;
};
export type GetPluginExtensionsResult<T = PluginExtension> = {
extensions: T[];
};
@@ -30,6 +35,11 @@ export type UsePluginComponentResult<Props = {}> = {
isLoading: boolean;
};
export type UsePluginComponentsResult<Props = {}> = {
components: Array<React.ComponentType<Props>>;
isLoading: boolean;
};
let singleton: GetPluginExtensions | undefined;
export function setPluginExtensionGetter(instance: GetPluginExtensions): void {
@@ -0,0 +1,24 @@
import { GetPluginExtensionsOptions, UsePluginComponentsResult } from './getPluginExtensions';
export type UsePluginComponents<Props extends object = {}> = (
options: GetPluginExtensionsOptions
) => UsePluginComponentsResult<Props>;
let singleton: UsePluginComponents | undefined;
export function setPluginComponentsHook(hook: UsePluginComponents): void {
// We allow overriding the registry in tests
if (singleton && process.env.NODE_ENV !== 'test') {
throw new Error('setPluginComponentsHook() function should only be called once, when Grafana is starting.');
}
singleton = hook;
}
export function usePluginComponents<Props extends object = {}>(
options: GetPluginExtensionsOptions
): UsePluginComponentsResult<Props> {
if (!singleton) {
throw new Error('setPluginComponentsHook(options) can only be used after the Grafana instance has started.');
}
return singleton(options) as UsePluginComponentsResult<Props>;
}
@@ -39,22 +39,6 @@ export function usePluginLinks(options: GetPluginExtensionsOptions): {
}, [extensions, isLoading]);
}
export function usePluginComponents<Props = {}>(
options: GetPluginExtensionsOptions
): { components: Array<React.ComponentType<Props>>; isLoading: boolean } {
const { extensions, isLoading } = usePluginExtensions(options);
return useMemo(
() => ({
components: extensions
.filter(isPluginExtensionComponent)
.map(({ component }) => component as React.ComponentType<Props>),
isLoading,
}),
[extensions, isLoading]
);
}
/**
* @deprecated Use usePluginLinks() instead.
*/