Improved asset service. Removed now unused plugin asset streaming endpoint
This commit is contained in:
@@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using Moonlight.ApiServer.Services;
|
using Moonlight.ApiServer.Services;
|
||||||
using Moonlight.Shared.Http.Responses.Assets;
|
using Moonlight.Shared.Http.Responses.Assets;
|
||||||
|
|
||||||
namespace Moonlight.ApiServer.Http.Controllers;
|
namespace Moonlight.ApiServer.Http.Controllers.Assets;
|
||||||
|
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/assets")]
|
[Route("api/assets")]
|
||||||
@@ -20,8 +20,8 @@ public class AssetsController : Controller
|
|||||||
{
|
{
|
||||||
return new FrontendAssetResponse()
|
return new FrontendAssetResponse()
|
||||||
{
|
{
|
||||||
CssFiles = AssetService.CssFiles.ToArray(),
|
CssFiles = AssetService.GetCssAssets(),
|
||||||
JavascriptFiles = AssetService.JavascriptFiles.ToArray(),
|
JavascriptFiles = AssetService.GetJavascriptAssets(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,19 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
|
||||||
using MoonCore.Exceptions;
|
using MoonCore.Exceptions;
|
||||||
using MoonCore.Models;
|
using MoonCore.Models;
|
||||||
using Moonlight.ApiServer.Services;
|
using Moonlight.ApiServer.Services;
|
||||||
using Moonlight.Shared.Http.Responses.PluginsStream;
|
|
||||||
|
|
||||||
namespace Moonlight.ApiServer.Http.Controllers;
|
namespace Moonlight.ApiServer.Http.Controllers.Assets;
|
||||||
|
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/pluginsStream")]
|
[Route("api/assets/plugins")]
|
||||||
public class PluginsStreamController : Controller
|
public class AssetsPluginsController : Controller
|
||||||
{
|
{
|
||||||
private readonly PluginService PluginService;
|
private readonly PluginService PluginService;
|
||||||
private readonly IMemoryCache Cache;
|
|
||||||
|
|
||||||
public PluginsStreamController(PluginService pluginService, IMemoryCache cache)
|
public AssetsPluginsController(PluginService pluginService)
|
||||||
{
|
{
|
||||||
PluginService = pluginService;
|
PluginService = pluginService;
|
||||||
Cache = cache;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
@@ -29,7 +25,7 @@ public class PluginsStreamController : Controller
|
|||||||
[HttpGet("stream")]
|
[HttpGet("stream")]
|
||||||
public async Task GetAssembly([FromQuery(Name = "assembly")] string assembly)
|
public async Task GetAssembly([FromQuery(Name = "assembly")] string assembly)
|
||||||
{
|
{
|
||||||
var assembliesMap = PluginService.AssemblyMap;
|
var assembliesMap = PluginService.ClientAssemblyMap;
|
||||||
|
|
||||||
if (assembliesMap.ContainsKey(assembly))
|
if (assembliesMap.ContainsKey(assembly))
|
||||||
throw new HttpApiException("The requested assembly could not be found", 404);
|
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);
|
await Results.File(path).ExecuteAsync(HttpContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("assets")]
|
|
||||||
public Task<PluginsAssetManifest> GetAssetManifest()
|
|
||||||
{
|
|
||||||
return Task.FromResult(PluginService.PluginsAssetManifest);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,63 @@ namespace Moonlight.ApiServer.Services;
|
|||||||
[Singleton]
|
[Singleton]
|
||||||
public class AssetService
|
public class AssetService
|
||||||
{
|
{
|
||||||
public readonly List<string> CssFiles = new();
|
public string[] CssFiles { get; private set; }
|
||||||
public readonly List<string> JavascriptFiles = new();
|
public string[] JavascriptFiles { get; private set; }
|
||||||
|
|
||||||
|
private bool HasBeenCollected = false;
|
||||||
|
|
||||||
|
private readonly List<string> AdditionalCssAssets = new();
|
||||||
|
private readonly List<string> AdditionalJavascriptAssets = new();
|
||||||
|
|
||||||
|
private readonly PluginService PluginService;
|
||||||
|
|
||||||
|
public AssetService(PluginService pluginService)
|
||||||
|
{
|
||||||
|
PluginService = pluginService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CollectAssets()
|
||||||
|
{
|
||||||
|
// CSS
|
||||||
|
var cssFiles = new List<string>();
|
||||||
|
|
||||||
|
cssFiles.AddRange(AdditionalCssAssets);
|
||||||
|
cssFiles.AddRange(PluginService.AssetMap.Keys.Where(x => x.EndsWith(".css")));
|
||||||
|
|
||||||
|
CssFiles = cssFiles.ToArray();
|
||||||
|
|
||||||
|
// Javascript
|
||||||
|
var jsFiles = new List<string>();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -8,11 +8,10 @@ namespace Moonlight.ApiServer.Services;
|
|||||||
|
|
||||||
public class PluginService
|
public class PluginService
|
||||||
{
|
{
|
||||||
public readonly List<PluginMeta> Plugins = new();
|
public List<PluginMeta> Plugins { get; private set; } = new();
|
||||||
public readonly Dictionary<string, string> AssetMap = new();
|
public Dictionary<string, string> AssetMap { get; private set; } = new();
|
||||||
public HostedPluginsManifest HostedPluginsManifest;
|
public HostedPluginsManifest HostedPluginsManifest { get; private set; }
|
||||||
public PluginsAssetManifest PluginsAssetManifest;
|
public Dictionary<string, string> ClientAssemblyMap { get; private set; }
|
||||||
public Dictionary<string, string> AssemblyMap;
|
|
||||||
|
|
||||||
private static string PluginsFolder = PathBuilder.Dir("storage", "plugins");
|
private static string PluginsFolder = PathBuilder.Dir("storage", "plugins");
|
||||||
private readonly ILogger<PluginService> Logger;
|
private readonly ILogger<PluginService> Logger;
|
||||||
@@ -75,7 +74,7 @@ public class PluginService
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
Logger.LogError(
|
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.Manifest.Id,
|
||||||
plugin.Path,
|
plugin.Path,
|
||||||
dependency
|
dependency
|
||||||
@@ -90,24 +89,17 @@ public class PluginService
|
|||||||
Plugins.RemoveAll(x => pluginsToNotLoad.Contains(x.Manifest.Id));
|
Plugins.RemoveAll(x => pluginsToNotLoad.Contains(x.Manifest.Id));
|
||||||
|
|
||||||
// Generate assembly map for client
|
// Generate assembly map for client
|
||||||
AssemblyMap = GetAssemblies("client");
|
ClientAssemblyMap = GetAssemblies("client");
|
||||||
|
|
||||||
// Generate plugin stream manifest for client
|
// Generate plugin stream manifest for client
|
||||||
HostedPluginsManifest = new()
|
HostedPluginsManifest = new()
|
||||||
{
|
{
|
||||||
Assemblies = AssemblyMap.Keys.ToArray(),
|
Assemblies = ClientAssemblyMap.Keys.ToArray(),
|
||||||
Entrypoints = GetEntrypoints("client")
|
Entrypoints = GetEntrypoints("client")
|
||||||
};
|
};
|
||||||
|
|
||||||
// Generate asset map
|
// Generate asset map
|
||||||
GenerateAssetMap();
|
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<string, string> GetAssemblies(string section)
|
public Dictionary<string, string> GetAssemblies(string section)
|
||||||
@@ -116,7 +108,12 @@ public class PluginService
|
|||||||
|
|
||||||
foreach (var plugin in Plugins)
|
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"))
|
if (!file.EndsWith(".dll"))
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -176,10 +176,10 @@ public class Startup
|
|||||||
switch (extension)
|
switch (extension)
|
||||||
{
|
{
|
||||||
case ".css":
|
case ".css":
|
||||||
assetService.CssFiles.Add(nextArg);
|
assetService.AddCssAsset(nextArg);
|
||||||
break;
|
break;
|
||||||
case ".js":
|
case ".js":
|
||||||
assetService.JavascriptFiles.Add(nextArg);
|
assetService.AddJavascriptAsset(nextArg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Logger.LogWarning("Unknown asset extension {extension}. Ignoring it", extension);
|
Logger.LogWarning("Unknown asset extension {extension}. Ignoring it", extension);
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ public class Startup
|
|||||||
|
|
||||||
await BuildWebAssemblyHost();
|
await BuildWebAssemblyHost();
|
||||||
|
|
||||||
await LoadPluginAssets();
|
|
||||||
await LoadAssets();
|
await LoadAssets();
|
||||||
|
|
||||||
await WebAssemblyHost.RunAsync();
|
await WebAssemblyHost.RunAsync();
|
||||||
@@ -176,7 +175,7 @@ public class Startup
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Build source from the retrieved data
|
// Build source from the retrieved data
|
||||||
var pluginsStreamUrl = $"{WebAssemblyHostBuilder.HostEnvironment.BaseAddress}api/pluginsStream";
|
var pluginsStreamUrl = $"{WebAssemblyHostBuilder.HostEnvironment.BaseAddress}api/assets/plugins";
|
||||||
PluginLoaderService.AddHttpHostedSource(pluginsStreamUrl);
|
PluginLoaderService.AddHttpHostedSource(pluginsStreamUrl);
|
||||||
|
|
||||||
// Perform assembly loading
|
// Perform assembly loading
|
||||||
@@ -188,20 +187,6 @@ public class Startup
|
|||||||
WebAssemblyHostBuilder.Services.AddSingleton(ApplicationAssemblyService);
|
WebAssemblyHostBuilder.Services.AddSingleton(ApplicationAssemblyService);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task LoadPluginAssets()
|
|
||||||
{
|
|
||||||
var apiClient = WebAssemblyHost.Services.GetRequiredService<HttpApiClient>();
|
|
||||||
var assetManifest = await apiClient.GetJson<PluginsAssetManifest>("api/pluginsStream/assets");
|
|
||||||
|
|
||||||
var jsRuntime = WebAssemblyHost.Services.GetRequiredService<IJSRuntime>();
|
|
||||||
|
|
||||||
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
|
#endregion
|
||||||
|
|
||||||
#region Logging
|
#region Logging
|
||||||
|
|||||||
Reference in New Issue
Block a user