new working directory allows absolute paths; allow multiple proxies with named configs

This commit is contained in:
2024-02-29 13:09:47 +01:00
parent da23dc2815
commit fcfec6b2f9
4 changed files with 67 additions and 35 deletions
+21 -18
View File
@@ -8,40 +8,43 @@ namespace ViteProxy;
public static class ViteProxyApplicationBuilderExtensions public static class ViteProxyApplicationBuilderExtensions
{ {
public static IApplicationBuilder UseViteStaticFiles(this IApplicationBuilder app) /// <summary>
/// Provides static files from the vite working directory or a custom directory or from the named vite settings
/// </summary>
/// <param name="app">The app builder</param>
/// <param name="path">Provide a file path for static file delivery</param>
/// <param name="configName">When vite proxy is added via named options these can be used here for correct retrieval of the vite working directory</param>
/// <returns>The app builde</returns>
public static IApplicationBuilder UseViteStaticFiles(this IApplicationBuilder app, string path = null, string configName = null)
{ {
IWebHostEnvironment env = app.ApplicationServices.GetRequiredService<IWebHostEnvironment>(); IWebHostEnvironment env = app.ApplicationServices.GetRequiredService<IWebHostEnvironment>();
IOptions<ViteProxyOptions> options = app.ApplicationServices.GetRequiredService<IOptions<ViteProxyOptions>>();
string workingDirectory = (options.Value.WorkingDirectory ?? String.Empty).Trim('/');
if (workingDirectory == null) if (path == null && configName == null)
{ {
return app; IOptions<ViteProxyOptions> options = app.ApplicationServices.GetRequiredService<IOptions<ViteProxyOptions>>();
path = options.Value.WorkingDirectory;
} }
app.UseStaticFiles(); if (configName != null)
app.UseStaticFiles(new StaticFileOptions
{ {
FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, workingDirectory)) using IServiceScope scope = app.ApplicationServices.CreateScope();
}); IOptionsSnapshot<ViteProxyOptions> optionsSnapschat = scope.ServiceProvider.GetRequiredService<IOptionsSnapshot<ViteProxyOptions>>();
ViteProxyOptions options = optionsSnapschat.Get(configName);
return app; path = options.WorkingDirectory;
} }
public static IApplicationBuilder UseViteStaticFiles(this IApplicationBuilder app, string path)
{
IWebHostEnvironment env = app.ApplicationServices.GetRequiredService<IWebHostEnvironment>();
if (path == null) if (path == null)
{ {
return app; return app;
} }
// TODO build full path
ViteWorkingDirectory workingDirectory = new(env, path);
app.UseStaticFiles(); app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions app.UseStaticFiles(new StaticFileOptions
{ {
FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, path)) FileProvider = new PhysicalFileProvider(workingDirectory.Path)
}); });
return app; return app;
+10 -13
View File
@@ -8,15 +8,17 @@ namespace ViteProxy;
public class ViteProxyService : IHostedService public class ViteProxyService : IHostedService
{ {
ViteProxyOptions options; ViteProxyOptions options;
ViteWorkingDirectory workingDirectory;
ILogger<ViteProxyService> logger; ILogger<ViteProxyService> logger;
string workingDirectory;
bool isRunning = false; bool isRunning = false;
public ViteProxyService(IWebHostEnvironment env, ILogger<ViteProxyService> logger, IOptions<ViteProxyOptions> options) public ViteProxyService(IWebHostEnvironment env, ILogger<ViteProxyService> logger, IOptions<ViteProxyOptions> options) : this(env, logger, options.Value ?? new()) { }
public ViteProxyService(IWebHostEnvironment env, ILogger<ViteProxyService> logger, ViteProxyOptions options)
{ {
this.options = options.Value ?? new(); this.options = options ?? new();
this.workingDirectory = Path.Combine(env.ContentRootPath, (this.options.WorkingDirectory ?? String.Empty).Trim('/')); this.workingDirectory = new ViteWorkingDirectory(env, options.WorkingDirectory);
this.logger = logger; this.logger = logger;
} }
@@ -30,16 +32,11 @@ public class ViteProxyService : IHostedService
} }
// locate npm version and throw if it is not installed // locate npm version and throw if it is not installed
Version npmVersion = await FindNpmVersion(); Version npmVersion = await FindNpmVersion() ?? throw new Exception("Please install node+npm to use the vite dev service (https://www.npmjs.com/)");
if (npmVersion == null)
{
throw new Exception("Please install node+npm to use the vite dev service (https://www.npmjs.com/)");
}
// start vite server // start vite server
ProcessProxy viteProcess = await StartDevServer(options.Port); ProcessProxy viteProcess = await StartDevServer(options.Port);
logger.LogInformation("vite listening on: http://localhost:{port}", options.Port); logger.LogInformation("vite listening on: http://localhost:{port} (path: {workingDirectory})", options.Port, this.workingDirectory.Path);
} }
public Task StopAsync(CancellationToken cancellationToken) public Task StopAsync(CancellationToken cancellationToken)
@@ -55,7 +52,7 @@ public class ViteProxyService : IHostedService
{ {
Version version = null; Version version = null;
ProcessProxy process = new ProcessProxy(workingDirectory, "npm").Argument("-v").Capture((value, err) => ProcessProxy process = new ProcessProxy(workingDirectory.Path, "npm").Argument("-v").Capture((value, err) =>
{ {
if (version == null && !value.Contains("not recognized") && Version.TryParse(value, out Version _version)) if (version == null && !value.Contains("not recognized") && Version.TryParse(value, out Version _version))
{ {
@@ -79,7 +76,7 @@ public class ViteProxyService : IHostedService
PidUtils.KillPort((ushort)port, true); PidUtils.KillPort((ushort)port, true);
// create and run the vite script // create and run the vite script
ProcessProxy process = new ProcessProxy(workingDirectory, "npm", options.ForwardLog) ProcessProxy process = new ProcessProxy(workingDirectory.Path, "npm", options.ForwardLog)
.Argument("run " + options.ScriptName) .Argument("run " + options.ScriptName)
.EnvVar("PORT", port.ToString()) .EnvVar("PORT", port.ToString())
.Capture(CaptureLog); .Capture(CaptureLog);
+11 -4
View File
@@ -1,5 +1,8 @@
using Microsoft.Extensions.Configuration; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace ViteProxy; namespace ViteProxy;
@@ -28,12 +31,16 @@ public static class ViteProxyServiceCollectionExtensions
} }
public static IServiceCollection AddViteProxy(this IServiceCollection services, IConfiguration namedConfigurationSection) public static IServiceCollection AddViteProxy(this IServiceCollection services, string configName, IConfiguration namedConfigurationSection)
{ {
services.AddLogging(); services.AddLogging();
services.AddOptions(); services.AddOptions();
services.AddHostedService<ViteProxyService>(); services.AddHostedService((svc) => new ViteProxyService(
services.AddOptions<ViteProxyOptions>().Bind(namedConfigurationSection); env: svc.GetService<IWebHostEnvironment>(),
logger: svc.GetService<ILogger<ViteProxyService>>(),
options: svc.GetService<IOptionsSnapshot<ViteProxyOptions>>().Get(configName)
));
services.AddOptions<ViteProxyOptions>(configName).Bind(namedConfigurationSection);
return services; return services;
} }
+25
View File
@@ -0,0 +1,25 @@
using Microsoft.AspNetCore.Hosting;
namespace ViteProxy;
internal class ViteWorkingDirectory
{
public string Path { get; protected set; }
public string InputPath { get; protected set; }
public ViteWorkingDirectory(IWebHostEnvironment env, string inputPath)
{
InputPath = inputPath;
string path = inputPath.Replace('\\', '/').Trim().TrimEnd('/');
if (System.IO.Path.IsPathFullyQualified(path))
{
Path = path;
}
else
{
Path = System.IO.Path.Combine(env.ContentRootPath, path);
}
}
}