installPlugin method
Future<PluginOperationResult>
installPlugin(
- String plugin, [
- PluginScope scope = PluginScope.user
Install a plugin (settings-first).
Order of operations:
- Look up plugin in marketplaces.
- Write settings (declares intent).
- Cache plugin and record version hint (materialization).
Implementation
Future<PluginOperationResult> installPlugin(
String plugin, [
PluginScope scope = PluginScope.user,
]) async {
assertInstallableScope(scope);
final id = parsePluginIdentifier(plugin);
final entry = await getPluginByIdFn(plugin);
if (entry == null) {
final location =
id.marketplace != null
? 'marketplace "${id.marketplace}"'
: 'any configured marketplace';
return PluginOperationResult(
success: false,
message: 'Plugin "${id.name}" not found in $location',
);
}
final pluginId = '${entry.name}@${id.marketplace ?? 'default'}';
if (isPluginBlockedByPolicy(pluginId)) {
return PluginOperationResult(
success: false,
message:
'Plugin "${entry.name}" is blocked by your organization\'s policy '
'and cannot be installed',
);
}
// Validate the manifest.
final validation = validateManifest(entry);
if (!validation.isValid) {
return PluginOperationResult(
success: false,
message:
'Plugin "${id.name}" has an invalid manifest: '
'${validation.errors.join('; ')}',
);
}
// Write settings (the intent declaration).
final settingSource = scopeToSettingSource(scope);
final current = getSettingsEnabledPlugins(settingSource) ?? {};
updateSettings(settingSource, {
'enabledPlugins': {...current, pluginId: true},
});
clearAllCaches();
return PluginOperationResult(
success: true,
message:
'Successfully installed plugin: $pluginId (scope: ${scope.name})',
pluginId: pluginId,
pluginName: entry.name,
scope: scope,
);
}