2024-08-19 08:43:11 +02:00
import type { PluginExposedComponentConfig , PluginExtensionConfig } from '@grafana/data' ;
2024-08-27 11:14:04 +02:00
import { PluginAddedComponentConfig } from '@grafana/data/src/types/pluginExtensions' ;
2023-03-02 15:42:00 +01:00
import type { AppPluginConfig } from '@grafana/runtime' ;
2023-05-10 11:03:15 +02:00
import { startMeasure , stopMeasure } from 'app/core/utils/metrics' ;
2023-11-14 08:35:40 +01:00
import { getPluginSettings } from 'app/features/plugins/pluginSettings' ;
2022-04-22 14:33:13 +01:00
2024-04-24 09:33:16 +02:00
import { ReactivePluginExtensionsRegistry } from './extensions/reactivePluginExtensionRegistry' ;
2024-08-27 11:14:04 +02:00
import { AddedComponentsRegistry } from './extensions/registry/AddedComponentsRegistry' ;
2024-08-19 08:43:11 +02:00
import { ExposedComponentsRegistry } from './extensions/registry/ExposedComponentsRegistry' ;
2023-03-02 15:42:00 +01:00
import * as pluginLoader from './plugin_loader' ;
2021-11-10 19:06:55 +01:00
2023-03-02 15:42:00 +01:00
export type PluginPreloadResult = {
pluginId : string ;
error? : unknown ;
2023-05-31 09:26:37 +02:00
extensionConfigs : PluginExtensionConfig [ ] ;
2024-08-19 08:43:11 +02:00
exposedComponentConfigs : PluginExposedComponentConfig [ ] ;
2024-08-27 11:14:04 +02:00
addedComponentConfigs : PluginAddedComponentConfig [ ] ;
} ;
type PluginExtensionRegistries = {
extensionsRegistry : ReactivePluginExtensionsRegistry ;
addedComponentsRegistry : AddedComponentsRegistry ;
exposedComponentsRegistry : ExposedComponentsRegistry ;
2023-03-02 15:42:00 +01:00
} ;
2024-04-24 15:37:22 +02:00
export async function preloadPlugins (
apps : AppPluginConfig [ ] = [ ] ,
2024-08-27 11:14:04 +02:00
registries : PluginExtensionRegistries ,
2024-04-24 15:37:22 +02:00
eventName = 'frontend_plugins_preload'
) {
startMeasure ( eventName ) ;
2024-04-24 09:33:16 +02:00
const promises = apps . filter ( ( config ) = > config . preload ) . map ( ( config ) = > preload ( config ) ) ;
const preloadedPlugins = await Promise . all ( promises ) ;
for ( const preloadedPlugin of preloadedPlugins ) {
2024-08-19 08:43:11 +02:00
if ( preloadedPlugin . error ) {
console . error ( ` [Plugins] Skip loading extensions for " ${ preloadedPlugin . pluginId } " due to an error. ` ) ;
continue ;
}
2024-08-27 11:14:04 +02:00
registries . extensionsRegistry . register ( preloadedPlugin ) ;
registries . exposedComponentsRegistry . register ( {
2024-08-19 08:43:11 +02:00
pluginId : preloadedPlugin.pluginId ,
configs : preloadedPlugin.exposedComponentConfigs ,
} ) ;
2024-08-27 11:14:04 +02:00
registries . addedComponentsRegistry . register ( {
pluginId : preloadedPlugin.pluginId ,
configs : preloadedPlugin.addedComponentConfigs ,
} ) ;
2024-04-24 09:33:16 +02:00
}
2024-04-24 15:37:22 +02:00
stopMeasure ( eventName ) ;
2021-11-10 19:06:55 +01:00
}
2023-03-02 15:42:00 +01:00
async function preload ( config : AppPluginConfig ) : Promise < PluginPreloadResult > {
const { path , version , id : pluginId } = config ;
2021-11-10 19:06:55 +01:00
try {
2023-05-10 11:03:15 +02:00
startMeasure ( ` frontend_plugin_preload_ ${ pluginId } ` ) ;
2023-06-05 10:51:36 +02:00
const { plugin } = await pluginLoader . importPluginModule ( {
path ,
version ,
2023-11-10 11:44:54 +01:00
isAngular : config.angular.detected ,
2023-06-05 10:51:36 +02:00
pluginId ,
} ) ;
2024-08-27 11:14:04 +02:00
const { extensionConfigs = [ ] , exposedComponentConfigs = [ ] , addedComponentConfigs = [ ] } = plugin ;
2023-11-14 08:35:40 +01:00
// Fetching meta-information for the preloaded app plugin and caching it for later.
// (The function below returns a promise, but it's not awaited for a reason: we don't want to block the preload process, we would only like to cache the result for later.)
getPluginSettings ( pluginId ) ;
2024-08-27 11:14:04 +02:00
return { pluginId , extensionConfigs , exposedComponentConfigs , addedComponentConfigs } ;
2023-03-02 15:42:00 +01:00
} catch ( error ) {
console . error ( ` [Plugins] Failed to preload plugin: ${ path } (version: ${ version } ) ` , error ) ;
2024-08-27 11:14:04 +02:00
return { pluginId , extensionConfigs : [ ] , error , exposedComponentConfigs : [ ] , addedComponentConfigs : [ ] } ;
2023-05-10 11:03:15 +02:00
} finally {
stopMeasure ( ` frontend_plugin_preload_ ${ pluginId } ` ) ;
2021-11-10 19:06:55 +01:00
}
}