Files
grafana/packages/grafana-runtime/src/services/pluginExtensions/getPluginExtensions.ts
T
db0cc24f2b Plugin extensions: Introduce new registry for added links (#92343)
* 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>
2024-08-30 10:09:01 +02:00

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,
};
};