Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
414 changes: 414 additions & 0 deletions PLUGIN_UPGRADE.md

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions src/c#/GeneralUpdate.Bowl/GeneralUpdate.Bowl.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
<Compile Include="..\GeneralUpdate.Common\Internal\JsonContext\ReportRespJsonContext.cs" Link="Common\ReportRespJsonContext.cs" />
<Compile Include="..\GeneralUpdate.Common\Internal\JsonContext\VersionOSSJsonContext.cs" Link="Common\VersionOSSJsonContext.cs" />
<Compile Include="..\GeneralUpdate.Common\Internal\JsonContext\VersionRespJsonContext.cs" Link="Common\VersionRespJsonContext.cs" />
<Compile Include="..\GeneralUpdate.Common\Internal\JsonContext\PluginRespJsonContext.cs" Link="Common\PluginRespJsonContext.cs" />
<Compile Include="..\GeneralUpdate.Common\Internal\Pipeline\IMiddleware.cs" Link="Common\IMiddleware.cs" />
<Compile Include="..\GeneralUpdate.Common\Internal\Pipeline\PipelineBuilder.cs" Link="Common\PipelineBuilder.cs" />
<Compile Include="..\GeneralUpdate.Common\Internal\Pipeline\PipelineContext.cs" Link="Common\PipelineContext.cs" />
Expand All @@ -61,18 +62,22 @@
<Compile Include="..\GeneralUpdate.Common\Shared\Object\Configinfo.cs" Link="Common\Configinfo.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\DTO\BaseResponseDTO.cs" Link="Common\BaseResponseDTO.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\DTO\VersionRespDTO.cs" Link="Common\VersionRespDTO.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\DTO\PluginRespDTO.cs" Link="Common\PluginRespDTO.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\Enum\AppType.cs" Link="Common\AppType.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\Enum\Format.cs" Link="Common\Format.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\Enum\PlatformType.cs" Link="Common\PlatformType.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\Enum\ReportType.cs" Link="Common\ReportType.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\Enum\UpdateMode.cs" Link="Common\UpdateMode.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\Enum\PluginType.cs" Link="Common\PluginType.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\GlobalConfigInfo.cs" Link="Common\GlobalConfigInfo.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\GlobalConfigInfoOSS.cs" Link="Common\GlobalConfigInfoOSS.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\ObjectTranslator.cs" Link="Common\ObjectTranslator.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\Packet.cs" Link="Common\Packet.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\ProcessInfo.cs" Link="Common\ProcessInfo.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\VersionInfo.cs" Link="Common\VersionInfo.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\VersionOSS.cs" Link="Common\VersionOSS.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\PluginInfo.cs" Link="Common\PluginInfo.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\PluginCompatibilityChecker.cs" Link="Common\PluginCompatibilityChecker.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Service\VersionService.cs" Link="Common\VersionService.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Trace\GeneralTracer.cs" Link="Common\GeneralTracer.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Trace\TextTraceListener.cs" Link="Common\TextTraceListener.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
<Compile Include="..\GeneralUpdate.Common\Internal\JsonContext\ReportRespJsonContext.cs" Link="Common\ReportRespJsonContext.cs" />
<Compile Include="..\GeneralUpdate.Common\Internal\JsonContext\VersionOSSJsonContext.cs" Link="Common\VersionOSSJsonContext.cs" />
<Compile Include="..\GeneralUpdate.Common\Internal\JsonContext\VersionRespJsonContext.cs" Link="Common\VersionRespJsonContext.cs" />
<Compile Include="..\GeneralUpdate.Common\Internal\JsonContext\PluginRespJsonContext.cs" Link="Common\PluginRespJsonContext.cs" />
<Compile Include="..\GeneralUpdate.Common\Internal\Pipeline\IMiddleware.cs" Link="Common\IMiddleware.cs" />
<Compile Include="..\GeneralUpdate.Common\Internal\Pipeline\PipelineBuilder.cs" Link="Common\PipelineBuilder.cs" />
<Compile Include="..\GeneralUpdate.Common\Internal\Pipeline\PipelineContext.cs" Link="Common\PipelineContext.cs" />
Expand All @@ -59,22 +60,27 @@
<Compile Include="..\GeneralUpdate.Common\Shared\Object\Configinfo.cs" Link="Common\Configinfo.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\DTO\BaseResponseDTO.cs" Link="Common\BaseResponseDTO.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\DTO\VersionRespDTO.cs" Link="Common\VersionRespDTO.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\DTO\PluginRespDTO.cs" Link="Common\PluginRespDTO.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\Enum\AppType.cs" Link="Common\AppType.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\Enum\Format.cs" Link="Common\Format.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\Enum\PlatformType.cs" Link="Common\PlatformType.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\Enum\ReportType.cs" Link="Common\ReportType.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\Enum\UpdateMode.cs" Link="Common\UpdateMode.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\Enum\PluginType.cs" Link="Common\PluginType.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\GlobalConfigInfo.cs" Link="Common\GlobalConfigInfo.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\GlobalConfigInfoOSS.cs" Link="Common\GlobalConfigInfoOSS.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\ObjectTranslator.cs" Link="Common\ObjectTranslator.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\Packet.cs" Link="Common\Packet.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\ProcessInfo.cs" Link="Common\ProcessInfo.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\VersionInfo.cs" Link="Common\VersionInfo.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\VersionOSS.cs" Link="Common\VersionOSS.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\PluginInfo.cs" Link="Common\PluginInfo.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Object\PluginCompatibilityChecker.cs" Link="Common\PluginCompatibilityChecker.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Service\VersionService.cs" Link="Common\VersionService.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Trace\GeneralTracer.cs" Link="Common\GeneralTracer.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Trace\TextTraceListener.cs" Link="Common\TextTraceListener.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Trace\WindowsOutputDebugListener.cs" Link="Common\WindowsOutputDebugListener.cs" />
<Compile Include="..\GeneralUpdate.Common\Shared\Service\PluginUpdateService.cs" Link="Common\PluginUpdateService.cs" />
<Compile Include="..\GeneralUpdate.Differential\Binary\BinaryHandler.cs" Link="Common\BinaryHandler.cs" />
<Compile Include="..\GeneralUpdate.Differential\Binary\BZip2Constants.cs" Link="Common\BZip2Constants.cs" />
<Compile Include="..\GeneralUpdate.Differential\Binary\BZip2InputStream.cs" Link="Common\BZip2InputStream.cs" />
Expand Down
193 changes: 193 additions & 0 deletions src/c#/GeneralUpdate.ClientCore/PluginBootstrapExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using GeneralUpdate.Common.Internal;
using GeneralUpdate.Common.Shared.Object;
using GeneralUpdate.Common.Shared.Service;

namespace GeneralUpdate.ClientCore
{
/// <summary>
/// Extension methods for GeneralClientBootstrap to support plugin upgrades.
/// </summary>
public static class PluginBootstrapExtensions
{
/// <summary>
/// Validates and retrieves available plugin updates for the current client version.
/// </summary>
/// <param name="configInfo">Global configuration information.</param>
/// <param name="platform">Platform type.</param>
/// <returns>List of available plugin updates compatible with the current client version.</returns>
public static async Task<List<PluginInfo>> GetAvailablePluginUpdatesAsync(
GlobalConfigInfo configInfo,
int platform)
{
if (configInfo == null || string.IsNullOrEmpty(configInfo.PluginUpdateUrl))
{
return new List<PluginInfo>();
}

try
{
var availablePlugins = await PluginUpdateService.GetAvailablePlugins(
configInfo.PluginUpdateUrl,
configInfo.ClientVersion,
null, // Check all plugins
configInfo.AppSecretKey,
platform,
configInfo.ProductId,
configInfo.Scheme,
configInfo.Token);

return availablePlugins;
}
catch (Exception)
{
// Catch any exceptions from API calls or network issues
// Return empty list to allow application to continue
return new List<PluginInfo>();
}
}

/// <summary>
/// Automatically determines minimum required plugin versions for a new client version.
/// This is called when the client is being upgraded to ensure plugin compatibility.
/// </summary>
/// <param name="configInfo">Global configuration information.</param>
/// <param name="targetClientVersion">Target client version after upgrade.</param>
/// <param name="platform">Platform type.</param>
/// <param name="currentPlugins">Dictionary of currently installed plugins (PluginId -> Version).</param>
/// <returns>List of plugins that need to be upgraded.</returns>
public static async Task<List<PluginInfo>> GetRequiredPluginUpdatesForClientUpgradeAsync(
GlobalConfigInfo configInfo,
string targetClientVersion,
int platform,
Dictionary<string, string> currentPlugins)
{
if (configInfo == null || string.IsNullOrEmpty(configInfo.PluginUpdateUrl))
{
return new List<PluginInfo>();
}

try
{
var requiredPlugins = new List<PluginInfo>();

foreach (var currentPlugin in currentPlugins)
{
var minPlugin = await PluginUpdateService.GetMinimumSupportedPluginForClientVersion(
configInfo.PluginUpdateUrl,
targetClientVersion,
currentPlugin.Key,
configInfo.AppSecretKey,
platform,
configInfo.ProductId,
configInfo.Scheme,
configInfo.Token);

if (minPlugin != null)
{
try
{
var currentVersion = new Version(currentPlugin.Value);
var minVersion = new Version(minPlugin.Version);

// Only add if current version is below minimum required
if (currentVersion < minVersion)
{
requiredPlugins.Add(minPlugin);
}
}
catch (Exception)
{
// Skip plugins with version comparison errors
}
}
}

return requiredPlugins;
}
catch (Exception)
{
// Catch any exceptions from API calls or network issues
// Return empty list to allow application to continue
return new List<PluginInfo>();
}
}

/// <summary>
/// Filters plugin updates based on user selection.
/// Allows users to choose which plugins to upgrade, similar to VS Code.
/// </summary>
/// <param name="availablePlugins">List of available plugin updates.</param>
/// <param name="selectedPluginIds">List of plugin IDs selected by user for upgrade.</param>
/// <returns>List of plugins to upgrade based on user selection.</returns>
public static List<PluginInfo> SelectPluginsForUpgrade(
List<PluginInfo> availablePlugins,
List<string> selectedPluginIds)
{
if (availablePlugins == null || !availablePlugins.Any())
return new List<PluginInfo>();

if (selectedPluginIds == null || !selectedPluginIds.Any())
return new List<PluginInfo>();

return availablePlugins
.Where(p => !string.IsNullOrEmpty(p.PluginId) && selectedPluginIds.Contains(p.PluginId))
.ToList();
}

/// <summary>
/// Determines mandatory plugin updates that must be installed.
/// </summary>
/// <param name="availablePlugins">List of available plugin updates.</param>
/// <returns>List of mandatory plugins.</returns>
public static List<PluginInfo> GetMandatoryPluginUpdates(List<PluginInfo> availablePlugins)
{
return PluginUpdateService.GetMandatoryPlugins(availablePlugins);
}

/// <summary>
/// Checks if any plugin updates are incompatible with the current client version.
/// </summary>
/// <param name="clientVersion">Current client version.</param>
/// <param name="plugins">List of plugins to check.</param>
/// <returns>True if all plugins are compatible, false otherwise.</returns>
public static bool AreAllPluginsCompatible(string clientVersion, List<PluginInfo> plugins)
{
if (plugins == null || !plugins.Any())
return true;

return plugins.All(p => PluginUpdateService.IsPluginCompatible(clientVersion, p));
}

/// <summary>
/// Validates that selected plugins are compatible with a target client version.
/// Used before performing client upgrade to prevent compatibility issues.
/// </summary>
/// <param name="targetClientVersion">Target client version after upgrade.</param>
/// <param name="selectedPlugins">Plugins selected for installation.</param>
/// <returns>True if all selected plugins are compatible with target version.</returns>
public static bool ValidatePluginCompatibilityForUpgrade(
string targetClientVersion,
List<PluginInfo> selectedPlugins)
{
if (string.IsNullOrEmpty(targetClientVersion))
return false;

if (selectedPlugins == null || !selectedPlugins.Any())
return true;

foreach (var plugin in selectedPlugins)
{
if (!PluginUpdateService.IsPluginCompatible(targetClientVersion, plugin))
{
return false;
}
}

return true;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using GeneralUpdate.Common.Shared.Object;

namespace GeneralUpdate.Common.Internal.JsonContext;

[JsonSerializable(typeof(PluginRespDTO))]
public partial class PluginRespJsonContext : JsonSerializerContext;
5 changes: 5 additions & 0 deletions src/c#/GeneralUpdate.Common/Shared/Object/Configinfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ public class Configinfo
/// </summary>
public string Script { get; set; }

/// <summary>
/// Plugin validation API endpoint URL (optional).
/// </summary>
public string PluginUpdateUrl { get; set; }

public void Validate()
{
if (string.IsNullOrWhiteSpace(UpdateUrl) || !Uri.IsWellFormedUriString(UpdateUrl, UriKind.Absolute))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Collections.Generic;

namespace GeneralUpdate.Common.Shared.Object;

/// <summary>
/// Response DTO for plugin validation containing list of available plugin updates.
/// </summary>
public class PluginRespDTO : BaseResponseDTO<List<PluginInfo>>;
5 changes: 5 additions & 0 deletions src/c#/GeneralUpdate.Common/Shared/Object/Enum/AppType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,10 @@ public class AppType
/// upgrade program.
/// </summary>
public const int UpgradeApp = 2;

/// <summary>
/// plugin component.
/// </summary>
public const int Plugin = 3;
}
}
33 changes: 33 additions & 0 deletions src/c#/GeneralUpdate.Common/Shared/Object/Enum/PluginType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace GeneralUpdate.Common.Shared.Object.Enum
{
/// <summary>
/// Plugin type enumeration for different plugin formats.
/// </summary>
public enum PluginType
{
/// <summary>
/// JavaScript plugin using embedded script engine.
/// </summary>
JavaScript = 1,

/// <summary>
/// Lua plugin using embedded script engine.
/// </summary>
Lua = 2,

/// <summary>
/// Python plugin using embedded script engine.
/// </summary>
Python = 3,

/// <summary>
/// WebAssembly plugin.
/// </summary>
WASM = 4,

/// <summary>
/// External executable program with protocol communication.
/// </summary>
ExternalExecutable = 5
}
}
15 changes: 15 additions & 0 deletions src/c#/GeneralUpdate.Common/Shared/Object/GlobalConfigInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,19 @@ public class GlobalConfigInfo
/// Script to grant permissions to a specified file on Linux
/// </summary>
public string Script { get; set; }

/// <summary>
/// Plugin validation API endpoint URL.
/// </summary>
public string PluginUpdateUrl { get; set; }

/// <summary>
/// List of plugins available for update.
/// </summary>
public List<PluginInfo> AvailablePlugins { get; set; } = new List<PluginInfo>();

/// <summary>
/// List of plugins selected by user for upgrade.
/// </summary>
public List<PluginInfo> SelectedPlugins { get; set; } = new List<PluginInfo>();
}
Loading