From 62fe6089f7188bbf3e0d894e45723d65100f8dad Mon Sep 17 00:00:00 2001 From: ChiaraBm Date: Sun, 1 Dec 2024 20:04:29 +0100 Subject: [PATCH] Improved asset service. Removed now unused plugin asset streaming endpoint --- .../{ => Assets}/AssetsController.cs | 6 +- .../AssetsPluginsController.cs} | 20 ++---- Moonlight.ApiServer/Services/AssetService.cs | 61 ++++++++++++++++++- Moonlight.ApiServer/Services/PluginService.cs | 29 ++++----- Moonlight.ApiServer/Startup.cs | 4 +- Moonlight.Client/Startup.cs | 17 +----- 6 files changed, 83 insertions(+), 54 deletions(-) rename Moonlight.ApiServer/Http/Controllers/{ => Assets}/AssetsController.cs (73%) rename Moonlight.ApiServer/Http/Controllers/{PluginsStreamController.cs => Assets/AssetsPluginsController.cs} (56%) diff --git a/Moonlight.ApiServer/Http/Controllers/AssetsController.cs b/Moonlight.ApiServer/Http/Controllers/Assets/AssetsController.cs similarity index 73% rename from Moonlight.ApiServer/Http/Controllers/AssetsController.cs rename to Moonlight.ApiServer/Http/Controllers/Assets/AssetsController.cs index 4257e4e5..efc31ee9 100644 --- a/Moonlight.ApiServer/Http/Controllers/AssetsController.cs +++ b/Moonlight.ApiServer/Http/Controllers/Assets/AssetsController.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Moonlight.ApiServer.Services; using Moonlight.Shared.Http.Responses.Assets; -namespace Moonlight.ApiServer.Http.Controllers; +namespace Moonlight.ApiServer.Http.Controllers.Assets; [ApiController] [Route("api/assets")] @@ -20,8 +20,8 @@ public class AssetsController : Controller { return new FrontendAssetResponse() { - CssFiles = AssetService.CssFiles.ToArray(), - JavascriptFiles = AssetService.JavascriptFiles.ToArray(), + CssFiles = AssetService.GetCssAssets(), + JavascriptFiles = AssetService.GetJavascriptAssets(), }; } } \ No newline at end of file diff --git a/Moonlight.ApiServer/Http/Controllers/PluginsStreamController.cs b/Moonlight.ApiServer/Http/Controllers/Assets/AssetsPluginsController.cs similarity index 56% rename from Moonlight.ApiServer/Http/Controllers/PluginsStreamController.cs rename to Moonlight.ApiServer/Http/Controllers/Assets/AssetsPluginsController.cs index e145faca..de90a1a0 100644 --- a/Moonlight.ApiServer/Http/Controllers/PluginsStreamController.cs +++ b/Moonlight.ApiServer/Http/Controllers/Assets/AssetsPluginsController.cs @@ -1,23 +1,19 @@ using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Caching.Memory; using MoonCore.Exceptions; using MoonCore.Models; using Moonlight.ApiServer.Services; -using Moonlight.Shared.Http.Responses.PluginsStream; -namespace Moonlight.ApiServer.Http.Controllers; +namespace Moonlight.ApiServer.Http.Controllers.Assets; [ApiController] -[Route("api/pluginsStream")] -public class PluginsStreamController : Controller +[Route("api/assets/plugins")] +public class AssetsPluginsController : Controller { private readonly PluginService PluginService; - private readonly IMemoryCache Cache; - public PluginsStreamController(PluginService pluginService, IMemoryCache cache) + public AssetsPluginsController(PluginService pluginService) { PluginService = pluginService; - Cache = cache; } [HttpGet] @@ -29,7 +25,7 @@ public class PluginsStreamController : Controller [HttpGet("stream")] public async Task GetAssembly([FromQuery(Name = "assembly")] string assembly) { - var assembliesMap = PluginService.AssemblyMap; + var assembliesMap = PluginService.ClientAssemblyMap; if (assembliesMap.ContainsKey(assembly)) throw new HttpApiException("The requested assembly could not be found", 404); @@ -38,10 +34,4 @@ public class PluginsStreamController : Controller await Results.File(path).ExecuteAsync(HttpContext); } - - [HttpGet("assets")] - public Task GetAssetManifest() - { - return Task.FromResult(PluginService.PluginsAssetManifest); - } } \ No newline at end of file diff --git a/Moonlight.ApiServer/Services/AssetService.cs b/Moonlight.ApiServer/Services/AssetService.cs index 92064a04..58499a2b 100644 --- a/Moonlight.ApiServer/Services/AssetService.cs +++ b/Moonlight.ApiServer/Services/AssetService.cs @@ -5,6 +5,63 @@ namespace Moonlight.ApiServer.Services; [Singleton] public class AssetService { - public readonly List CssFiles = new(); - public readonly List JavascriptFiles = new(); + public string[] CssFiles { get; private set; } + public string[] JavascriptFiles { get; private set; } + + private bool HasBeenCollected = false; + + private readonly List AdditionalCssAssets = new(); + private readonly List AdditionalJavascriptAssets = new(); + + private readonly PluginService PluginService; + + public AssetService(PluginService pluginService) + { + PluginService = pluginService; + } + + public void CollectAssets() + { + // CSS + var cssFiles = new List(); + + cssFiles.AddRange(AdditionalCssAssets); + cssFiles.AddRange(PluginService.AssetMap.Keys.Where(x => x.EndsWith(".css"))); + + CssFiles = cssFiles.ToArray(); + + // Javascript + var jsFiles = new List(); + + jsFiles.AddRange(AdditionalJavascriptAssets); + jsFiles.AddRange(PluginService.AssetMap.Keys.Where(x => x.EndsWith(".js"))); + + JavascriptFiles = jsFiles.ToArray(); + } + + public void AddCssAsset(string asset) + => AdditionalCssAssets.Add(asset); + + public void AddJavascriptAsset(string asset) + => AdditionalJavascriptAssets.Add(asset); + + public string[] GetCssAssets() + { + if (HasBeenCollected) + return CssFiles; + + CollectAssets(); + + return CssFiles; + } + + public string[] GetJavascriptAssets() + { + if (HasBeenCollected) + return JavascriptFiles; + + CollectAssets(); + + return JavascriptFiles; + } } \ No newline at end of file diff --git a/Moonlight.ApiServer/Services/PluginService.cs b/Moonlight.ApiServer/Services/PluginService.cs index 0b52e636..1a7c5b8f 100644 --- a/Moonlight.ApiServer/Services/PluginService.cs +++ b/Moonlight.ApiServer/Services/PluginService.cs @@ -8,11 +8,10 @@ namespace Moonlight.ApiServer.Services; public class PluginService { - public readonly List Plugins = new(); - public readonly Dictionary AssetMap = new(); - public HostedPluginsManifest HostedPluginsManifest; - public PluginsAssetManifest PluginsAssetManifest; - public Dictionary AssemblyMap; + public List Plugins { get; private set; } = new(); + public Dictionary AssetMap { get; private set; } = new(); + public HostedPluginsManifest HostedPluginsManifest { get; private set; } + public Dictionary ClientAssemblyMap { get; private set; } private static string PluginsFolder = PathBuilder.Dir("storage", "plugins"); private readonly ILogger Logger; @@ -75,7 +74,7 @@ public class PluginService continue; Logger.LogError( - "Unable to load plugin '{id}' ({path}) because the dependency {dependency} is missing", + "Unable to load plugin '{id}' ({path}) because the dependency '{dependency}' is missing", plugin.Manifest.Id, plugin.Path, dependency @@ -90,24 +89,17 @@ public class PluginService Plugins.RemoveAll(x => pluginsToNotLoad.Contains(x.Manifest.Id)); // Generate assembly map for client - AssemblyMap = GetAssemblies("client"); + ClientAssemblyMap = GetAssemblies("client"); // Generate plugin stream manifest for client HostedPluginsManifest = new() { - Assemblies = AssemblyMap.Keys.ToArray(), + Assemblies = ClientAssemblyMap.Keys.ToArray(), Entrypoints = GetEntrypoints("client") }; // Generate asset map GenerateAssetMap(); - - // Generate asset manifest - PluginsAssetManifest = new() - { - CssFiles = AssetMap.Keys.Where(x => x.EndsWith(".css")).ToArray(), - JavascriptFiles = AssetMap.Keys.Where(x => x.EndsWith(".js")).ToArray(), - }; } public Dictionary GetAssemblies(string section) @@ -116,7 +108,12 @@ public class PluginService foreach (var plugin in Plugins) { - foreach (var file in Directory.EnumerateFiles(PathBuilder.Dir(plugin.Path, "bin", section))) + var binaryPath = PathBuilder.Dir(plugin.Path, "bin", section); + + if(!Directory.Exists(binaryPath)) + continue; + + foreach (var file in Directory.EnumerateFiles(binaryPath)) { if (!file.EndsWith(".dll")) continue; diff --git a/Moonlight.ApiServer/Startup.cs b/Moonlight.ApiServer/Startup.cs index 7066f130..0a686fca 100644 --- a/Moonlight.ApiServer/Startup.cs +++ b/Moonlight.ApiServer/Startup.cs @@ -176,10 +176,10 @@ public class Startup switch (extension) { case ".css": - assetService.CssFiles.Add(nextArg); + assetService.AddCssAsset(nextArg); break; case ".js": - assetService.JavascriptFiles.Add(nextArg); + assetService.AddJavascriptAsset(nextArg); break; default: Logger.LogWarning("Unknown asset extension {extension}. Ignoring it", extension); diff --git a/Moonlight.Client/Startup.cs b/Moonlight.Client/Startup.cs index 4e05acb2..06647c77 100644 --- a/Moonlight.Client/Startup.cs +++ b/Moonlight.Client/Startup.cs @@ -62,7 +62,6 @@ public class Startup await BuildWebAssemblyHost(); - await LoadPluginAssets(); await LoadAssets(); await WebAssemblyHost.RunAsync(); @@ -176,7 +175,7 @@ public class Startup ); // Build source from the retrieved data - var pluginsStreamUrl = $"{WebAssemblyHostBuilder.HostEnvironment.BaseAddress}api/pluginsStream"; + var pluginsStreamUrl = $"{WebAssemblyHostBuilder.HostEnvironment.BaseAddress}api/assets/plugins"; PluginLoaderService.AddHttpHostedSource(pluginsStreamUrl); // Perform assembly loading @@ -188,20 +187,6 @@ public class Startup WebAssemblyHostBuilder.Services.AddSingleton(ApplicationAssemblyService); } - private async Task LoadPluginAssets() - { - var apiClient = WebAssemblyHost.Services.GetRequiredService(); - var assetManifest = await apiClient.GetJson("api/pluginsStream/assets"); - - var jsRuntime = WebAssemblyHost.Services.GetRequiredService(); - - foreach (var cssFile in assetManifest.CssFiles) - await jsRuntime.InvokeVoidAsync("moonlight.assets.loadCss", cssFile); - - foreach (var javascriptFile in assetManifest.JavascriptFiles) - await jsRuntime.InvokeVoidAsync("moonlight.assets.loadJavascript", javascriptFile); - } - #endregion #region Logging