Preparations for plugin/module development

This commit is contained in:
Masu Baumgartner
2024-11-10 20:36:02 +01:00
parent 18810766ed
commit 96bb3a5c0f
9 changed files with 393 additions and 338 deletions

View File

@@ -1,10 +1,12 @@
using System.Reflection;
namespace Moonlight.ApiServer; namespace Moonlight.ApiServer;
public static class DevServer public static class DevServer
{ {
public async static Task Run(string[] args) public async static Task Run(string[] args, Assembly[] pluginAssemblies)
{ {
Console.WriteLine("Preparing development server"); Console.WriteLine("Preparing development server");
await Program.Main(args); await Startup.Run(args, pluginAssemblies);
} }
} }

View File

@@ -5,6 +5,16 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<IsPackable>true</IsPackable>
<Version>2.1.0</Version>
<Title>Moonlight.ApiServer</Title>
<Authors>Moonlight Panel</Authors>
<Description>A build of moonlight's api server as a nuget package to develop moonlight plugins/modules</Description>
<Copyright>Moonlight Panel</Copyright>
<PackageProjectUrl>https://github.com/Moonlight-Panel/Moonlight</PackageProjectUrl>
<RepositoryUrl>https://github.com/Moonlight-Panel/Moonlight</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>moonlight</PackageTags>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,198 +0,0 @@
using System.Reflection;
using MoonCore.Extended.Extensions;
using MoonCore.Extensions;
using MoonCore.Helpers;
using MoonCore.PluginFramework.Extensions;
using Moonlight.ApiServer;
using Moonlight.ApiServer.Configuration;
using Moonlight.ApiServer.Helpers;
using Moonlight.ApiServer.Http.Middleware;
using Moonlight.ApiServer.Interfaces.Auth;
using Moonlight.ApiServer.Interfaces.OAuth2;
using Moonlight.ApiServer.Interfaces.Startup;
public class Program
{
public static async Task Main(string[] args)
{
// Cry about it
#pragma warning disable ASP0000
// Fancy start console output... yes very fancy :>
var rainbow = new Crayon.Rainbow(0.5);
foreach (var c in "Moonlight")
{
Console.Write(
rainbow
.Next()
.Bold()
.Text(c.ToString())
);
}
Console.WriteLine();
// Storage i guess
Directory.CreateDirectory(PathBuilder.Dir("storage"));
// TODO: Load plugin/module assemblies
// Configure startup logger
var startupLoggerFactory = new LoggerFactory();
// TODO: Add direct extension method
var providers = LoggerBuildHelper.BuildFromConfiguration(configuration =>
{
configuration.Console.Enable = true;
configuration.Console.EnableAnsiMode = true;
configuration.FileLogging.Enable = false;
});
startupLoggerFactory.AddProviders(providers);
var startupLogger = startupLoggerFactory.CreateLogger("Startup");
// Configure startup interfaces
var startupServiceCollection = new ServiceCollection();
startupServiceCollection.AddConfiguration(options =>
{
options.UsePath(PathBuilder.Dir("storage"));
options.UseEnvironmentPrefix("MOONLIGHT");
options.AddConfiguration<AppConfiguration>("app");
});
startupServiceCollection.AddLogging(loggingBuilder => { loggingBuilder.AddProviders(providers); });
startupServiceCollection.AddPlugins(configuration =>
{
// Configure startup interfaces
configuration.AddInterface<IAppStartup>();
configuration.AddInterface<IDatabaseStartup>();
configuration.AddInterface<IEndpointStartup>();
// Configure assemblies to scan
configuration.AddAssembly(typeof(Program).Assembly);
});
var startupServiceProvider = startupServiceCollection.BuildServiceProvider();
var appStartupInterfaces = startupServiceProvider.GetRequiredService<IAppStartup[]>();
var config = startupServiceProvider.GetRequiredService<AppConfiguration>();
ApplicationStateHelper.SetConfiguration(config);
// Start the actual app
var builder = WebApplication.CreateBuilder(args);
await Startup.ConfigureLogging(builder);
await Startup.ConfigureDatabase(
builder,
startupLoggerFactory,
startupServiceProvider.GetRequiredService<IDatabaseStartup[]>()
);
// Call interfaces
foreach (var startupInterface in appStartupInterfaces)
{
try
{
await startupInterface.BuildApp(builder);
}
catch (Exception e)
{
startupLogger.LogCritical(
"An unhandled error occured while processing BuildApp call for interface '{interfaceName}': {e}",
startupInterface.GetType().FullName,
e
);
}
}
builder.Services.AddControllers();
builder.Services.AddSingleton(config);
builder.Services.AutoAddServices<Program>();
builder.Services.AddHttpClient();
await Startup.ConfigureTokenAuthentication(builder, config);
await Startup.ConfigureOAuth2(builder, startupLogger, config);
// Implementation service
builder.Services.AddPlugins(configuration =>
{
configuration.AddInterface<IOAuth2Provider>();
configuration.AddInterface<IAuthInterceptor>();
configuration.AddAssembly(typeof(Program).Assembly);
});
var app = builder.Build();
await Startup.PrepareDatabase(app);
if (config.Client.Enable)
{
if (app.Environment.IsDevelopment())
app.UseWebAssemblyDebugging();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
}
app.UseRouting();
app.UseApiErrorHandling();
await Startup.UseTokenAuthentication(app);
await Startup.UseOAuth2(app);
// Call interfaces
foreach (var startupInterface in appStartupInterfaces)
{
try
{
await startupInterface.ConfigureApp(app);
}
catch (Exception e)
{
startupLogger.LogCritical(
"An unhandled error occured while processing ConfigureApp call for interface '{interfaceName}': {e}",
startupInterface.GetType().FullName,
e
);
}
}
app.UseMiddleware<ApiAuthenticationMiddleware>();
app.UseMiddleware<AuthorizationMiddleware>();
// Call interfaces
var endpointStartupInterfaces = startupServiceProvider.GetRequiredService<IEndpointStartup[]>();
foreach (var endpointStartup in endpointStartupInterfaces)
{
try
{
await endpointStartup.ConfigureEndpoints(app);
}
catch (Exception e)
{
startupLogger.LogCritical(
"An unhandled error occured while processing ConfigureEndpoints call for interface '{interfaceName}': {e}",
endpointStartup.GetType().FullName,
e
);
}
}
app.MapControllers();
if (config.Client.Enable)
app.MapFallbackToFile("index.html");
await app.RunAsync();
}
}

View File

@@ -1,3 +1,4 @@
using System.Reflection;
using System.Text.Json; using System.Text.Json;
using MoonCore.Authentication; using MoonCore.Authentication;
using MoonCore.Exceptions; using MoonCore.Exceptions;
@@ -7,9 +8,12 @@ using MoonCore.Extended.Helpers;
using MoonCore.Extended.OAuth2.Consumer; using MoonCore.Extended.OAuth2.Consumer;
using MoonCore.Extensions; using MoonCore.Extensions;
using MoonCore.Helpers; using MoonCore.Helpers;
using MoonCore.PluginFramework.Extensions;
using Moonlight.ApiServer.Configuration; using Moonlight.ApiServer.Configuration;
using Moonlight.ApiServer.Database.Entities; using Moonlight.ApiServer.Database.Entities;
using Moonlight.ApiServer.Helpers; using Moonlight.ApiServer.Helpers;
using Moonlight.ApiServer.Http.Middleware;
using Moonlight.ApiServer.Interfaces.Auth;
using Moonlight.ApiServer.Interfaces.OAuth2; using Moonlight.ApiServer.Interfaces.OAuth2;
using Moonlight.ApiServer.Interfaces.Startup; using Moonlight.ApiServer.Interfaces.Startup;
using Moonlight.Shared.Http.Responses.OAuth2; using Moonlight.Shared.Http.Responses.OAuth2;
@@ -18,6 +22,202 @@ namespace Moonlight.ApiServer;
public static class Startup public static class Startup
{ {
public static async Task Main(string[] args)
=> await Run(args, []);
public static async Task Run(string[] args, Assembly[]? pluginAssemblies = null)
{
// Cry about it
#pragma warning disable ASP0000
// Fancy start console output... yes very fancy :>
var rainbow = new Crayon.Rainbow(0.5);
foreach (var c in "Moonlight")
{
Console.Write(
rainbow
.Next()
.Bold()
.Text(c.ToString())
);
}
Console.WriteLine();
// Storage i guess
Directory.CreateDirectory(PathBuilder.Dir("storage"));
// TODO: Load plugin/module assemblies
// Configure startup logger
var startupLoggerFactory = new LoggerFactory();
// TODO: Add direct extension method
var providers = LoggerBuildHelper.BuildFromConfiguration(configuration =>
{
configuration.Console.Enable = true;
configuration.Console.EnableAnsiMode = true;
configuration.FileLogging.Enable = false;
});
startupLoggerFactory.AddProviders(providers);
var startupLogger = startupLoggerFactory.CreateLogger("Startup");
// Configure startup interfaces
var startupServiceCollection = new ServiceCollection();
startupServiceCollection.AddConfiguration(options =>
{
options.UsePath(PathBuilder.Dir("storage"));
options.UseEnvironmentPrefix("MOONLIGHT");
options.AddConfiguration<AppConfiguration>("app");
});
startupServiceCollection.AddLogging(loggingBuilder => { loggingBuilder.AddProviders(providers); });
startupServiceCollection.AddPlugins(configuration =>
{
// Configure startup interfaces
configuration.AddInterface<IAppStartup>();
configuration.AddInterface<IDatabaseStartup>();
configuration.AddInterface<IEndpointStartup>();
// Configure assemblies to scan
configuration.AddAssembly(typeof(Startup).Assembly);
if(pluginAssemblies != null)
configuration.AddAssemblies(pluginAssemblies);
//TODO: Load plugins from file
});
var startupServiceProvider = startupServiceCollection.BuildServiceProvider();
var appStartupInterfaces = startupServiceProvider.GetRequiredService<IAppStartup[]>();
var config = startupServiceProvider.GetRequiredService<AppConfiguration>();
ApplicationStateHelper.SetConfiguration(config);
// Start the actual app
var builder = WebApplication.CreateBuilder(args);
await ConfigureLogging(builder);
await ConfigureDatabase(
builder,
startupLoggerFactory,
startupServiceProvider.GetRequiredService<IDatabaseStartup[]>()
);
// Call interfaces
foreach (var startupInterface in appStartupInterfaces)
{
try
{
await startupInterface.BuildApp(builder);
}
catch (Exception e)
{
startupLogger.LogCritical(
"An unhandled error occured while processing BuildApp call for interface '{interfaceName}': {e}",
startupInterface.GetType().FullName,
e
);
}
}
builder.Services.AddControllers();
builder.Services.AddSingleton(config);
builder.Services.AutoAddServices(typeof(Startup).Assembly);
builder.Services.AddHttpClient();
await ConfigureTokenAuthentication(builder, config);
await ConfigureOAuth2(builder, startupLogger, config);
// Implementation service
builder.Services.AddPlugins(configuration =>
{
configuration.AddInterface<IOAuth2Provider>();
configuration.AddInterface<IAuthInterceptor>();
configuration.AddAssembly(typeof(Startup).Assembly);
if(pluginAssemblies != null)
configuration.AddAssemblies(pluginAssemblies);
//TODO: Load plugins from file
});
var app = builder.Build();
await PrepareDatabase(app);
if (config.Client.Enable)
{
if (app.Environment.IsDevelopment())
app.UseWebAssemblyDebugging();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
}
app.UseRouting();
app.UseApiErrorHandling();
await UseTokenAuthentication(app);
await UseOAuth2(app);
// Call interfaces
foreach (var startupInterface in appStartupInterfaces)
{
try
{
await startupInterface.ConfigureApp(app);
}
catch (Exception e)
{
startupLogger.LogCritical(
"An unhandled error occured while processing ConfigureApp call for interface '{interfaceName}': {e}",
startupInterface.GetType().FullName,
e
);
}
}
app.UseMiddleware<ApiAuthenticationMiddleware>();
app.UseMiddleware<AuthorizationMiddleware>();
// Call interfaces
var endpointStartupInterfaces = startupServiceProvider.GetRequiredService<IEndpointStartup[]>();
foreach (var endpointStartup in endpointStartupInterfaces)
{
try
{
await endpointStartup.ConfigureEndpoints(app);
}
catch (Exception e)
{
startupLogger.LogCritical(
"An unhandled error occured while processing ConfigureEndpoints call for interface '{interfaceName}': {e}",
endpointStartup.GetType().FullName,
e
);
}
}
app.MapControllers();
if (config.Client.Enable)
app.MapFallbackToFile("index.html");
await app.RunAsync();
}
#region Logging #region Logging
public static async Task ConfigureLogging(IHostApplicationBuilder builder) public static async Task ConfigureLogging(IHostApplicationBuilder builder)
@@ -132,7 +332,7 @@ public static class Startup
authenticationConfig.ProcessRefresh = async (oldData, newData, serviceProvider) => authenticationConfig.ProcessRefresh = async (oldData, newData, serviceProvider) =>
{ {
var oauth2Providers = serviceProvider.GetRequiredService<IOAuth2Provider[]>(); var oauth2Providers = serviceProvider.GetRequiredService<IOAuth2Provider[]>();
// Find oauth2 provider // Find oauth2 provider
var provider = oauth2Providers.FirstOrDefault(); var provider = oauth2Providers.FirstOrDefault();
@@ -145,10 +345,10 @@ public static class Startup
{ {
return false; return false;
} }
// Load user from database if existent // Load user from database if existent
var userRepo = serviceProvider.GetRequiredService<DatabaseRepository<User>>(); var userRepo = serviceProvider.GetRequiredService<DatabaseRepository<User>>();
var user = userRepo var user = userRepo
.Get() .Get()
.FirstOrDefault(x => x.Id == userId); .FirstOrDefault(x => x.Id == userId);
@@ -159,12 +359,12 @@ public static class Startup
// Allow plugins to intercept the refresh call // Allow plugins to intercept the refresh call
//if (AuthInterceptors.Any(interceptor => !interceptor.AllowRefresh(user, serviceProvider))) //if (AuthInterceptors.Any(interceptor => !interceptor.AllowRefresh(user, serviceProvider)))
// return false; // return false;
// Check if it's time to resync with the oauth2 provider // Check if it's time to resync with the oauth2 provider
if (DateTime.UtcNow >= user.RefreshTimestamp) if (DateTime.UtcNow >= user.RefreshTimestamp)
{ {
var oAuth2Service = serviceProvider.GetRequiredService<OAuth2ConsumerService>(); var oAuth2Service = serviceProvider.GetRequiredService<OAuth2ConsumerService>();
try try
{ {
// It's time to refresh the access to the external oauth2 provider // It's time to refresh the access to the external oauth2 provider
@@ -194,7 +394,7 @@ public static class Startup
{ {
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>(); var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger("OAuth2 Refresh"); var logger = loggerFactory.CreateLogger("OAuth2 Refresh");
// We are handling this error more softly, because it will occur when a user hasn't logged in a long period of time // We are handling this error more softly, because it will occur when a user hasn't logged in a long period of time
logger.LogTrace("An error occured while refreshing external oauth2 access: {e}", e); logger.LogTrace("An error occured while refreshing external oauth2 access: {e}", e);
return false; return false;
@@ -213,7 +413,7 @@ public static class Startup
public static Task UseTokenAuthentication(WebApplication builder) public static Task UseTokenAuthentication(WebApplication builder)
{ {
builder.UseTokenAuthentication(); builder.UseTokenAuthentication();
return Task.CompletedTask; return Task.CompletedTask;
} }
@@ -289,13 +489,13 @@ public static class Startup
configuration.ProcessComplete = async (serviceProvider, accessData) => configuration.ProcessComplete = async (serviceProvider, accessData) =>
{ {
var oauth2Providers = serviceProvider.GetRequiredService<IOAuth2Provider[]>(); var oauth2Providers = serviceProvider.GetRequiredService<IOAuth2Provider[]>();
// Find oauth2 provider // Find oauth2 provider
var provider = oauth2Providers.FirstOrDefault(); var provider = oauth2Providers.FirstOrDefault();
if (provider == null) if (provider == null)
throw new HttpApiException("No oauth2 provider has been registered", 500); throw new HttpApiException("No oauth2 provider has been registered", 500);
try try
{ {
var user = await provider.Sync(serviceProvider, accessData.AccessToken); var user = await provider.Sync(serviceProvider, accessData.AccessToken);
@@ -313,14 +513,14 @@ public static class Startup
return new Dictionary<string, object>() return new Dictionary<string, object>()
{ {
{"userId", user.Id} { "userId", user.Id }
}; };
} }
catch (Exception e) catch (Exception e)
{ {
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>(); var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger(provider.GetType()); var logger = loggerFactory.CreateLogger(provider.GetType());
logger.LogTrace("An error occured while syncing user with oauth2 provider: {e}", e); logger.LogTrace("An error occured while syncing user with oauth2 provider: {e}", e);
throw new HttpApiException("Unable to synchronize with oauth2 provider", 400); throw new HttpApiException("Unable to synchronize with oauth2 provider", 400);
} }
@@ -351,9 +551,9 @@ public static class Startup
public static Task UseOAuth2(WebApplication application) public static Task UseOAuth2(WebApplication application)
{ {
application.UseOAuth2Consumer(); application.UseOAuth2Consumer();
return Task.CompletedTask; return Task.CompletedTask;
} }
#endregion #endregion
} }

View File

@@ -0,0 +1,12 @@
using System.Reflection;
namespace Moonlight.Client;
public class DevClient
{
public async static Task Run(string[] args, Assembly[] assemblies)
{
Console.WriteLine("Preparing development client");
await Startup.Run(args, assemblies);
}
}

View File

@@ -6,6 +6,16 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest> <ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<IsPackable>true</IsPackable>
<Version>2.1.0</Version>
<Title>Moonlight.Client</Title>
<Authors>Moonlight Panel</Authors>
<Description>A build of moonlight's client as a nuget package to develop moonlight plugins/modules</Description>
<Copyright>Moonlight Panel</Copyright>
<PackageProjectUrl>https://github.com/Moonlight-Panel/Moonlight</PackageProjectUrl>
<RepositoryUrl>https://github.com/Moonlight-Panel/Moonlight</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>moonlight</PackageTags>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,126 +1,3 @@
using System.Reflection; using Moonlight.Client;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using MoonCore.Blazor.Extensions;
using MoonCore.Blazor.Services;
using MoonCore.Blazor.Tailwind.Extensions;
using MoonCore.Blazor.Tailwind.Forms;
using MoonCore.Blazor.Tailwind.Forms.Components;
using MoonCore.Exceptions;
using MoonCore.Extensions;
using MoonCore.Helpers;
using MoonCore.Models;
using MoonCore.PluginFramework.Extensions;
using Moonlight.Client.Interfaces;
using Moonlight.Client.Services;
using Moonlight.Client.UI;
using Moonlight.Client.UI.Forms;
using Moonlight.Shared.Http.Requests.Auth;
using Moonlight.Shared.Http.Responses.Auth;
// Build pre run logger await Startup.Run(args, []);
var providers = LoggerBuildHelper.BuildFromConfiguration(configuration =>
{
configuration.Console.Enable = true;
configuration.Console.EnableAnsiMode = true;
configuration.FileLogging.Enable = false;
});
using var loggerFactory = new LoggerFactory(providers);
var logger = loggerFactory.CreateLogger("Startup");
// Fancy start console output... yes very fancy :>
Console.Write("Running ");
var rainbow = new Crayon.Rainbow(0.5);
foreach (var c in "Moonlight")
{
Console.Write(
rainbow
.Next()
.Bold()
.Text(c.ToString())
);
}
Console.WriteLine();
// Building app
var builder = WebAssemblyHostBuilder.CreateDefault(args);
// Configure application logging
builder.Logging.ClearProviders();
builder.Logging.AddProviders(providers);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(_ => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.AddTokenAuthentication();
builder.AddOAuth2();
/*
builder.Services.AddScoped(sp =>
{
var httpClient = sp.GetRequiredService<HttpClient>();
var localStorageService = sp.GetRequiredService<LocalStorageService>();
var result = new HttpApiClient(httpClient);
result.AddLocalStorageTokenAuthentication(localStorageService, async refreshToken =>
{
try
{
var httpApiClient = new HttpApiClient(httpClient);
var response = await httpApiClient.PostJson<RefreshResponse>(
"api/auth/refresh",
new RefreshRequest()
{
RefreshToken = refreshToken
}
);
return (new TokenPair()
{
AccessToken = response.AccessToken,
RefreshToken = response.RefreshToken
}, response.ExpiresAt);
}
catch (HttpApiException)
{
return (new TokenPair()
{
AccessToken = "unset",
RefreshToken = "unset"
}, DateTime.MinValue);
}
});
return result;
});*/
builder.Services.AddMoonCoreBlazorTailwind();
builder.Services.AddScoped<WindowService>();
builder.Services.AddScoped<LocalStorageService>();
builder.Services.AutoAddServices<Program>();
FormComponentRepository.Set<string, StringComponent>();
FormComponentRepository.Set<int, IntComponent>();
FormComponentRepository.Set<DateTime, DateComponent>();
// Interface service
builder.Services.AddPlugins(configuration =>
{
configuration.AddAssembly(Assembly.GetEntryAssembly()!);
configuration.AddInterface<IAppLoader>();
configuration.AddInterface<IAppScreen>();
configuration.AddInterface<ISidebarItemProvider>();
});
var app = builder.Build();
await app.RunAsync();

131
Moonlight.Client/Startup.cs Normal file
View File

@@ -0,0 +1,131 @@
using System.Reflection;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using MoonCore.Blazor.Extensions;
using MoonCore.Blazor.Services;
using MoonCore.Blazor.Tailwind.Extensions;
using MoonCore.Blazor.Tailwind.Forms;
using MoonCore.Blazor.Tailwind.Forms.Components;
using MoonCore.Extensions;
using MoonCore.Helpers;
using MoonCore.PluginFramework.Extensions;
using Moonlight.Client.Interfaces;
using Moonlight.Client.Services;
using Moonlight.Client.UI;
using Moonlight.Client.UI.Forms;
namespace Moonlight.Client;
public class Startup
{
public static async Task Run(string[] args, Assembly[] assemblies)
{
// Build pre run logger
var providers = LoggerBuildHelper.BuildFromConfiguration(configuration =>
{
configuration.Console.Enable = true;
configuration.Console.EnableAnsiMode = true;
configuration.FileLogging.Enable = false;
});
using var loggerFactory = new LoggerFactory(providers);
var logger = loggerFactory.CreateLogger("Startup");
// Fancy start console output... yes very fancy :>
Console.Write("Running ");
var rainbow = new Crayon.Rainbow(0.5);
foreach (var c in "Moonlight")
{
Console.Write(
rainbow
.Next()
.Bold()
.Text(c.ToString())
);
}
Console.WriteLine();
// Building app
var builder = WebAssemblyHostBuilder.CreateDefault(args);
// Configure application logging
builder.Logging.ClearProviders();
builder.Logging.AddProviders(providers);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(_ => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.AddTokenAuthentication();
builder.AddOAuth2();
/*
builder.Services.AddScoped(sp =>
{
var httpClient = sp.GetRequiredService<HttpClient>();
var localStorageService = sp.GetRequiredService<LocalStorageService>();
var result = new HttpApiClient(httpClient);
result.AddLocalStorageTokenAuthentication(localStorageService, async refreshToken =>
{
try
{
var httpApiClient = new HttpApiClient(httpClient);
var response = await httpApiClient.PostJson<RefreshResponse>(
"api/auth/refresh",
new RefreshRequest()
{
RefreshToken = refreshToken
}
);
return (new TokenPair()
{
AccessToken = response.AccessToken,
RefreshToken = response.RefreshToken
}, response.ExpiresAt);
}
catch (HttpApiException)
{
return (new TokenPair()
{
AccessToken = "unset",
RefreshToken = "unset"
}, DateTime.MinValue);
}
});
return result;
});*/
builder.Services.AddMoonCoreBlazorTailwind();
builder.Services.AddScoped<WindowService>();
builder.Services.AddScoped<LocalStorageService>();
builder.Services.AutoAddServices<Startup>();
FormComponentRepository.Set<string, StringComponent>();
FormComponentRepository.Set<int, IntComponent>();
FormComponentRepository.Set<DateTime, DateComponent>();
// Interface service
builder.Services.AddPlugins(configuration =>
{
configuration.AddAssembly(typeof(Startup).Assembly);
configuration.AddAssemblies(assemblies);
configuration.AddInterface<IAppLoader>();
configuration.AddInterface<IAppScreen>();
configuration.AddInterface<ISidebarItemProvider>();
});
var app = builder.Build();
await app.RunAsync();
}
}

View File

@@ -4,6 +4,17 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<IsPackable>true</IsPackable>
<Version>2.1.0</Version>
<Title>Moonlight.Shared</Title>
<Authors>Moonlight Panel</Authors>
<Description>A build of moonlight's shared classes as a nuget package to develop moonlight plugins/modules</Description>
<Copyright>Moonlight Panel</Copyright>
<PackageProjectUrl>https://github.com/Moonlight-Panel/Moonlight</PackageProjectUrl>
<RepositoryUrl>https://github.com/Moonlight-Panel/Moonlight</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>moonlight</PackageTags>
</PropertyGroup> </PropertyGroup>
</Project> </Project>