Files
grafana/public/app/features/plugins/pluginPreloader.ts
Sven Grossmann 478c1debe0 Plugin Loader: Wait for plugins to register their extensions (#106969)
* fix: mark apps as preloaded after being preloaded

* move marking as preloaded into `preload`

* add tests

* refactor: make it reuse promises of already loaded plugins

* fix: review notes

---------

Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com>
2025-06-25 06:49:25 +00:00

49 lines
1.5 KiB
TypeScript

import type {
PluginExtensionAddedLinkConfig,
PluginExtensionExposedComponentConfig,
PluginExtensionAddedComponentConfig,
} from '@grafana/data';
import type { AppPluginConfig } from '@grafana/runtime';
import { contextSrv } from 'app/core/services/context_srv';
import { getPluginSettings } from 'app/features/plugins/pluginSettings';
import { importAppPlugin } from './plugin_loader';
export type PluginPreloadResult = {
pluginId: string;
error?: unknown;
exposedComponentConfigs: PluginExtensionExposedComponentConfig[];
addedComponentConfigs?: PluginExtensionAddedComponentConfig[];
addedLinkConfigs?: PluginExtensionAddedLinkConfig[];
};
const preloadPromises = new Map<string, Promise<void>>();
export const clearPreloadedPluginsCache = () => {
preloadPromises.clear();
};
export async function preloadPlugins(apps: AppPluginConfig[] = []) {
// Create preload promises for each app, reusing existing promises if already loading
const promises = apps.map((app) => {
if (!preloadPromises.has(app.id)) {
preloadPromises.set(app.id, preload(app));
}
return preloadPromises.get(app.id)!;
});
await Promise.all(promises);
}
async function preload(config: AppPluginConfig): Promise<void> {
try {
const meta = await getPluginSettings(config.id, {
showErrorAlert: contextSrv.user.orgRole !== '',
});
await importAppPlugin(meta);
} catch (error) {
console.error(`[Plugins] Failed to preload plugin: ${config.path} (version: ${config.version})`, error);
}
}