* 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 * initial commit * refactor sync method and hook * fix tests * subscribe to the correct registry * remove old registry * cleanup types * add use usePluginLinks hook * add more tests * fix import order * fix typo * fix and temporarly skip failing tests * wip * add hook tests * add more tests * remove old hook * fix versioning * add version to all extension point ids * remove cleanup * remove unused imports * revert touched file * fix test * test: remove hook creation * catch init error * send error to faro * fix broken hook * comment out call hook initialization * use the right import ofr isString * remove unused import * remove registryState type * pr feedback * Update public/app/features/plugins/extensions/validators.test.tsx Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> * Update public/app/features/plugins/extensions/validators.test.tsx Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> * remove no longer relevant comment * fix broken tests * Fixed test to verify that the memotization works properly. * simplify hooks --------- Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> Co-authored-by: Marcus Andersson <marcus.andersson@grafana.com>
93 lines
2.8 KiB
TypeScript
93 lines
2.8 KiB
TypeScript
import type { PluginExtension, PluginExtensionLink, PluginExtensionComponent } from '@grafana/data';
|
|
|
|
import { isPluginExtensionComponent, isPluginExtensionLink } from './utils';
|
|
|
|
export type GetPluginExtensions<T = PluginExtension> = (
|
|
options: GetPluginExtensionsOptions
|
|
) => GetPluginExtensionsResult<T>;
|
|
|
|
export type UsePluginExtensions<T = PluginExtension> = (
|
|
options: GetPluginExtensionsOptions
|
|
) => UsePluginExtensionsResult<T>;
|
|
|
|
export type GetPluginExtensionsOptions = {
|
|
extensionPointId: string;
|
|
context?: object | Record<string | symbol, unknown>;
|
|
limitPerPlugin?: number;
|
|
};
|
|
|
|
export type UsePluginComponentOptions = {
|
|
extensionPointId: string;
|
|
limitPerPlugin?: number;
|
|
};
|
|
|
|
export type GetPluginExtensionsResult<T = PluginExtension> = {
|
|
extensions: T[];
|
|
};
|
|
|
|
export type UsePluginExtensionsResult<T = PluginExtension> = {
|
|
extensions: T[];
|
|
isLoading: boolean;
|
|
};
|
|
|
|
export type UsePluginComponentResult<Props = {}> = {
|
|
component: React.ComponentType<Props> | undefined | null;
|
|
isLoading: boolean;
|
|
};
|
|
|
|
export type UsePluginComponentsResult<Props = {}> = {
|
|
components: Array<React.ComponentType<Props>>;
|
|
isLoading: boolean;
|
|
};
|
|
|
|
export type UsePluginLinksOptions = {
|
|
extensionPointId: string;
|
|
context?: object | Record<string | symbol, unknown>;
|
|
limitPerPlugin?: number;
|
|
};
|
|
|
|
export type UsePluginLinksResult = {
|
|
isLoading: boolean;
|
|
links: PluginExtensionLink[];
|
|
};
|
|
|
|
let singleton: GetPluginExtensions | undefined;
|
|
|
|
export function setPluginExtensionGetter(instance: GetPluginExtensions): void {
|
|
// We allow overriding the registry in tests
|
|
if (singleton && process.env.NODE_ENV !== 'test') {
|
|
throw new Error('setPluginExtensionGetter() function should only be called once, when Grafana is starting.');
|
|
}
|
|
singleton = instance;
|
|
}
|
|
|
|
function getPluginExtensionGetter(): GetPluginExtensions {
|
|
if (!singleton) {
|
|
throw new Error('getPluginExtensionGetter() can only be used after the Grafana instance has started.');
|
|
}
|
|
return singleton;
|
|
}
|
|
|
|
export const getPluginExtensions: GetPluginExtensions = (options) => getPluginExtensionGetter()(options);
|
|
|
|
export const getPluginLinkExtensions: GetPluginExtensions<PluginExtensionLink> = (options) => {
|
|
const { extensions } = getPluginExtensions(options);
|
|
|
|
return {
|
|
extensions: extensions.filter(isPluginExtensionLink),
|
|
};
|
|
};
|
|
|
|
// This getter doesn't support the `context` option (contextual information can be passed in as component props)
|
|
export const getPluginComponentExtensions = <Props = {}>(options: {
|
|
extensionPointId: string;
|
|
limitPerPlugin?: number;
|
|
}): { extensions: Array<PluginExtensionComponent<Props>> } => {
|
|
const { extensions } = getPluginExtensions(options);
|
|
const componentExtensions = extensions.filter(isPluginExtensionComponent) as Array<PluginExtensionComponent<Props>>;
|
|
|
|
return {
|
|
extensions: componentExtensions,
|
|
};
|
|
};
|