Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2b16e2067c | |||
| 4ece202cbb | |||
| 6bcabcdea8 | |||
| 214938b966 | |||
| ae1efdc527 | |||
| 7c581583d2 | |||
| a8f07fc203 | |||
| 0f1df639f8 | |||
| 2ce477f9b8 | |||
| fcfec6b2f9 |
+48
-48
@@ -8,27 +8,27 @@ namespace ViteProxy;
|
||||
|
||||
public class ProcessProxy
|
||||
{
|
||||
string workingDirectory;
|
||||
string script;
|
||||
Action<ProcessStartInfo> onProcessConfigure = null;
|
||||
Action<string, bool> captureLog = null;
|
||||
bool isWindows => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
|
||||
Dictionary<string, string> envVars = new();
|
||||
HashSet<string> arguments = new();
|
||||
bool forwardLog = false;
|
||||
readonly string _workingDirectory;
|
||||
readonly string _script;
|
||||
Action<ProcessStartInfo> _onProcessConfigure = null;
|
||||
Action<string, bool> _captureLog = null;
|
||||
bool IsWindows => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
|
||||
readonly Dictionary<string, string> _envVars = new();
|
||||
readonly HashSet<string> _arguments = new();
|
||||
readonly bool _forwardLog = false;
|
||||
|
||||
Process process = null;
|
||||
EventedStreamReader stdOut;
|
||||
EventedStreamReader stdErr;
|
||||
Process _process = null;
|
||||
EventedStreamReader _stdOut;
|
||||
EventedStreamReader _stdErr;
|
||||
|
||||
|
||||
|
||||
|
||||
public ProcessProxy(string workingDirectory, string script, bool forwardLog = false)
|
||||
{
|
||||
this.workingDirectory = workingDirectory;
|
||||
this.script = script;
|
||||
this.forwardLog = forwardLog;
|
||||
this._workingDirectory = workingDirectory;
|
||||
this._script = script;
|
||||
this._forwardLog = forwardLog;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public class ProcessProxy
|
||||
/// </summary>
|
||||
public ProcessProxy EnvVar(string key, string value)
|
||||
{
|
||||
envVars.Add(key, value);
|
||||
_envVars.Add(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public class ProcessProxy
|
||||
/// </summary>
|
||||
public ProcessProxy Argument(string argument)
|
||||
{
|
||||
arguments.Add(argument);
|
||||
_arguments.Add(argument);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public class ProcessProxy
|
||||
/// </summary>
|
||||
public ProcessProxy Configure(Action<ProcessStartInfo> onProcessConfigure)
|
||||
{
|
||||
this.onProcessConfigure = onProcessConfigure;
|
||||
this._onProcessConfigure = onProcessConfigure;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public class ProcessProxy
|
||||
/// </summary>
|
||||
public ProcessProxy Capture(Action<string, bool> action)
|
||||
{
|
||||
this.captureLog = action;
|
||||
this._captureLog = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -80,16 +80,16 @@ public class ProcessProxy
|
||||
{
|
||||
StartProcess();
|
||||
|
||||
using var stdErrReader = new EventedStreamStringReader(stdErr);
|
||||
using var stdErrReader = new EventedStreamStringReader(_stdErr);
|
||||
try
|
||||
{
|
||||
// TODO implement timeout
|
||||
// https://stackoverflow.com/questions/18760252/timeout-an-async-method-implemented-with-taskcompletionsource
|
||||
await stdOut.WaitForFinish();
|
||||
await _stdOut.WaitForFinish();
|
||||
}
|
||||
catch (EndOfStreamException ex)
|
||||
{
|
||||
throw new InvalidOperationException($"The script '{script}' exited without indicating that the server was listening for requests.\nThe error output was: " + $"{stdErrReader.ReadAsString()}", ex);
|
||||
throw new InvalidOperationException($"The script '{_script}' exited without indicating that the server was listening for requests.\nThe error output was: " + $"{stdErrReader.ReadAsString()}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,22 +102,22 @@ public class ProcessProxy
|
||||
{
|
||||
StartProcess();
|
||||
|
||||
using var stdErrReader = new EventedStreamStringReader(stdErr);
|
||||
using var stdErrReader = new EventedStreamStringReader(_stdErr);
|
||||
try
|
||||
{
|
||||
await stdOut.WaitForMatch(new Regex(startupCondition, RegexOptions.IgnoreCase, startupTimeout == default ? TimeSpan.FromMinutes(5) : startupTimeout));
|
||||
await _stdOut.WaitForMatch(new Regex(startupCondition, RegexOptions.IgnoreCase, startupTimeout == default ? TimeSpan.FromMinutes(5) : startupTimeout));
|
||||
}
|
||||
catch (EndOfStreamException ex)
|
||||
{
|
||||
throw new InvalidOperationException($"The script '{script}' exited without indicating that the server was listening for requests.\nThe error output was: " + $"{stdErrReader.ReadAsString()}", ex);
|
||||
throw new InvalidOperationException($"The script '{_script}' exited without indicating that the server was listening for requests.\nThe error output was: " + $"{stdErrReader.ReadAsString()}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Exit()
|
||||
{
|
||||
try { process?.Kill(); } catch { }
|
||||
try { process?.WaitForExit(); } catch { }
|
||||
try { _process?.Kill(); } catch { }
|
||||
try { _process?.WaitForExit(); } catch { }
|
||||
|
||||
AppDomain.CurrentDomain.DomainUnload -= UnloadHandler;
|
||||
AppDomain.CurrentDomain.ProcessExit -= UnloadHandler;
|
||||
@@ -130,18 +130,18 @@ public class ProcessProxy
|
||||
/// </summary>
|
||||
Process StartProcess()
|
||||
{
|
||||
string executable = script;
|
||||
string executable = _script;
|
||||
|
||||
StringBuilder command = new();
|
||||
command.Append(script);
|
||||
command.Append(_script);
|
||||
command.Append(' ');
|
||||
foreach (string arg in arguments)
|
||||
foreach (string arg in _arguments)
|
||||
{
|
||||
command.Append(arg);
|
||||
}
|
||||
string argumentList = command.ToString();
|
||||
|
||||
if (isWindows)
|
||||
if (IsWindows)
|
||||
{
|
||||
argumentList = $"/c {argumentList}";
|
||||
executable = "cmd";
|
||||
@@ -154,20 +154,20 @@ public class ProcessProxy
|
||||
RedirectStandardInput = true,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
WorkingDirectory = workingDirectory
|
||||
WorkingDirectory = _workingDirectory
|
||||
};
|
||||
|
||||
foreach (var envVar in envVars)
|
||||
foreach (var envVar in _envVars)
|
||||
{
|
||||
startInfo.Environment[envVar.Key] = envVar.Value;
|
||||
}
|
||||
|
||||
onProcessConfigure?.Invoke(startInfo);
|
||||
_onProcessConfigure?.Invoke(startInfo);
|
||||
|
||||
try
|
||||
{
|
||||
process = Process.Start(startInfo);
|
||||
process.EnableRaisingEvents = true;
|
||||
_process = Process.Start(startInfo);
|
||||
_process.EnableRaisingEvents = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -185,7 +185,7 @@ public class ProcessProxy
|
||||
AppDomain.CurrentDomain.ProcessExit += UnloadHandler;
|
||||
AppDomain.CurrentDomain.UnhandledException += UnloadHandler;
|
||||
|
||||
return process;
|
||||
return _process;
|
||||
}
|
||||
|
||||
|
||||
@@ -197,13 +197,13 @@ public class ProcessProxy
|
||||
|
||||
void AttachLogger(bool isStream = false)
|
||||
{
|
||||
stdOut = new EventedStreamReader(process.StandardOutput);
|
||||
stdErr = new EventedStreamReader(process.StandardError);
|
||||
_stdOut = new EventedStreamReader(_process.StandardOutput);
|
||||
_stdErr = new EventedStreamReader(_process.StandardError);
|
||||
|
||||
stdOut.OnReceivedLine += line => WriteToLog(line);
|
||||
stdOut.OnReceivedChunk += chunk => WriteToLog(chunk);
|
||||
stdErr.OnReceivedLine += line => WriteToLog(line, true);
|
||||
stdErr.OnReceivedChunk += chunk => WriteToLog(chunk, true);
|
||||
_stdOut.OnReceivedLine += line => WriteToLog(line);
|
||||
_stdOut.OnReceivedChunk += chunk => WriteToLog(chunk);
|
||||
_stdErr.OnReceivedLine += line => WriteToLog(line, true);
|
||||
_stdErr.OnReceivedChunk += chunk => WriteToLog(chunk, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -216,11 +216,11 @@ public class ProcessProxy
|
||||
|
||||
line = line.StartsWith("<s>") ? line.Substring(3) : line;
|
||||
|
||||
if (captureLog != null)
|
||||
if (_captureLog != null)
|
||||
{
|
||||
captureLog(line, isError);
|
||||
_captureLog(line, isError);
|
||||
}
|
||||
if (forwardLog)
|
||||
if (_forwardLog)
|
||||
{
|
||||
(isError ? Console.Error : Console.Out).WriteLine(line);
|
||||
}
|
||||
@@ -236,11 +236,11 @@ public class ProcessProxy
|
||||
return;
|
||||
}
|
||||
|
||||
if (captureLog != null)
|
||||
if (_captureLog != null)
|
||||
{
|
||||
captureLog(new String(chunk.Array, chunk.Offset, chunk.Count), isError);
|
||||
_captureLog(new String(chunk.Array, chunk.Offset, chunk.Count), isError);
|
||||
}
|
||||
if (forwardLog)
|
||||
if (_forwardLog)
|
||||
{
|
||||
(isError ? Console.Error : Console.Out).Write(chunk.Array, chunk.Offset, chunk.Count);
|
||||
}
|
||||
|
||||
+10
-8
@@ -1,17 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<RootNamespace>ViteProxy</RootNamespace>
|
||||
<AssemblyName>ViteProxy</AssemblyName>
|
||||
<Version>0.0.0</Version>
|
||||
<Version>1.3.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="../viteproxy-logo.png" Pack="true" PackagePath="\" />
|
||||
<None Include="../README.md" Pack="true" PackagePath="\" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<Product>ViteProxy</Product>
|
||||
<Title>ViteProxy</Title>
|
||||
<Copyright>Copyright © Tobias Klika 2022</Copyright>
|
||||
<Copyright>Copyright © Tobias Klika 2026</Copyright>
|
||||
<Tags>Vite, npm, middleware, server, development</Tags>
|
||||
<Authors>Tobias Klika</Authors>
|
||||
<Description>ViteProxy is a proxy for vite projects within ASP.NET Core.</Description>
|
||||
@@ -20,7 +25,8 @@
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<PackageId>ViteProxy</PackageId>
|
||||
<PackageProjectUrl>https://github.com/ceee/ViteProxy</PackageProjectUrl>
|
||||
<PackageIconUrl>https://raw.githubusercontent.com/ceee/ViteProxy/main/viteproxy-logo.png</PackageIconUrl>
|
||||
<PackageIcon>viteproxy-logo.png</PackageIcon>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
||||
@@ -31,9 +37,5 @@
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All"/>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -2,46 +2,55 @@
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ViteProxy;
|
||||
|
||||
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>();
|
||||
IOptions<ViteProxyOptions> options = app.ApplicationServices.GetRequiredService<IOptions<ViteProxyOptions>>();
|
||||
string workingDirectory = (options.Value.WorkingDirectory ?? String.Empty).Trim('/');
|
||||
|
||||
if (workingDirectory == null)
|
||||
// do not provide static files when not in development
|
||||
if (!env.IsDevelopment())
|
||||
{
|
||||
return app;
|
||||
}
|
||||
|
||||
app.UseStaticFiles();
|
||||
app.UseStaticFiles(new StaticFileOptions
|
||||
if (path == null && configName == null)
|
||||
{
|
||||
FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, workingDirectory))
|
||||
});
|
||||
IOptions<ViteProxyOptions> options = app.ApplicationServices.GetRequiredService<IOptions<ViteProxyOptions>>();
|
||||
path = options.Value.WorkingDirectory;
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
|
||||
public static IApplicationBuilder UseViteStaticFiles(this IApplicationBuilder app, string path)
|
||||
{
|
||||
IWebHostEnvironment env = app.ApplicationServices.GetRequiredService<IWebHostEnvironment>();
|
||||
if (configName != null)
|
||||
{
|
||||
using IServiceScope scope = app.ApplicationServices.CreateScope();
|
||||
IOptionsSnapshot<ViteProxyOptions> optionsSnapschat = scope.ServiceProvider.GetRequiredService<IOptionsSnapshot<ViteProxyOptions>>();
|
||||
ViteProxyOptions options = optionsSnapschat.Get(configName);
|
||||
path = options.WorkingDirectory;
|
||||
}
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
return app;
|
||||
}
|
||||
|
||||
app.UseStaticFiles();
|
||||
// TODO build full path
|
||||
ViteWorkingDirectory workingDirectory = new(env, path);
|
||||
|
||||
app.UseStaticFiles(new StaticFileOptions
|
||||
{
|
||||
FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, path))
|
||||
FileProvider = new PhysicalFileProvider(workingDirectory.Path)
|
||||
});
|
||||
|
||||
return app;
|
||||
|
||||
@@ -15,7 +15,7 @@ public class ViteProxyOptions
|
||||
/// <summary>
|
||||
/// Directory where the frontend files are located
|
||||
/// </summary>
|
||||
public string WorkingDirectory { get; set; }
|
||||
public string WorkingDirectory { get; set; } = "App";
|
||||
|
||||
/// <summary>
|
||||
/// Whether to enable the proxy or not
|
||||
|
||||
+25
-25
@@ -7,39 +7,38 @@ namespace ViteProxy;
|
||||
|
||||
public class ViteProxyService : IHostedService
|
||||
{
|
||||
ViteProxyOptions options;
|
||||
ILogger<ViteProxyService> logger;
|
||||
string workingDirectory;
|
||||
bool isRunning = false;
|
||||
readonly ViteProxyOptions _options;
|
||||
readonly ViteWorkingDirectory _workingDirectory;
|
||||
readonly ILogger<ViteProxyService> _logger;
|
||||
readonly IWebHostEnvironment _env;
|
||||
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.workingDirectory = Path.Combine(env.ContentRootPath, (this.options.WorkingDirectory ?? String.Empty).Trim('/'));
|
||||
this.logger = logger;
|
||||
_options = options ?? new();
|
||||
_workingDirectory = new ViteWorkingDirectory(env, _options.WorkingDirectory);
|
||||
_env = env;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (!this.options.Enabled)
|
||||
if (!_options.Enabled || !_env.IsDevelopment())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// locate npm version and throw if it is not installed
|
||||
Version npmVersion = await FindNpmVersion();
|
||||
|
||||
if (npmVersion == null)
|
||||
{
|
||||
throw new Exception("Please install node+npm to use the vite dev service (https://www.npmjs.com/)");
|
||||
}
|
||||
Version npmVersion = await FindNpmVersion() ?? throw new Exception("Please install node+npm to use the vite dev service (https://www.npmjs.com/)");
|
||||
|
||||
// start vite server
|
||||
ProcessProxy viteProcess = await StartDevServer(options.Port);
|
||||
logger.LogInformation("vite listening on: http://localhost:{port}", options.Port);
|
||||
ProcessProxy viteProcess = await StartDevServer(_options.Port);
|
||||
_logger.LogInformation("vite listening on: http://localhost:{port} (path: {workingDirectory})", _options.Port, _workingDirectory.Path);
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
@@ -55,7 +54,7 @@ public class ViteProxyService : IHostedService
|
||||
{
|
||||
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))
|
||||
{
|
||||
@@ -79,14 +78,15 @@ public class ViteProxyService : IHostedService
|
||||
PidUtils.KillPort((ushort)port, true);
|
||||
|
||||
// create and run the vite script
|
||||
ProcessProxy process = new ProcessProxy(workingDirectory, "npm", options.ForwardLog)
|
||||
.Argument("run " + options.ScriptName)
|
||||
ProcessProxy process = new ProcessProxy(_workingDirectory.Path, "npm", _options.ForwardLog)
|
||||
.Argument("run " + _options.ScriptName)
|
||||
.EnvVar("PORT", port.ToString())
|
||||
//.EnvVar("URL_PREFIX", "/@viteproxy/")
|
||||
.Capture(CaptureLog);
|
||||
|
||||
await process.RunAsync(options.StartupCondition, TimeSpan.FromSeconds(options.TimeoutInSeconds));
|
||||
await process.RunAsync(_options.StartupCondition, TimeSpan.FromSeconds(_options.TimeoutInSeconds));
|
||||
|
||||
isRunning = true;
|
||||
_isRunning = true;
|
||||
|
||||
return process;
|
||||
}
|
||||
@@ -94,18 +94,18 @@ public class ViteProxyService : IHostedService
|
||||
|
||||
void CaptureLog(string line, bool isError)
|
||||
{
|
||||
if (!isRunning)
|
||||
if (!_isRunning)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (isError)
|
||||
{
|
||||
logger.LogWarning(line);
|
||||
_logger.LogWarning(line);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogInformation(line);
|
||||
_logger.LogInformation(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +1,46 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ViteProxy;
|
||||
|
||||
public static class ViteProxyServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddViteProxy(this IServiceCollection services)
|
||||
public static IServiceCollection AddViteProxy(this IServiceCollection services, string configSectionPath = "Vite")
|
||||
{
|
||||
services.AddLogging();
|
||||
services.AddOptions();
|
||||
services.AddHostedService<ViteProxyService>();
|
||||
services.AddOptions<ViteProxyOptions>().BindConfiguration("Vite");
|
||||
services.AddOptions<ViteProxyOptions>().BindConfiguration(configSectionPath);
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
|
||||
public static IServiceCollection AddViteProxy(this IServiceCollection services, Action<ViteProxyOptions> configure)
|
||||
public static IServiceCollection AddViteProxy(this IServiceCollection services, Action<ViteProxyOptions> configure, string configSectionPath = "Vite")
|
||||
{
|
||||
services.AddLogging();
|
||||
services.AddOptions();
|
||||
services.AddHostedService<ViteProxyService>();
|
||||
services.AddOptions<ViteProxyOptions>().BindConfiguration("Vite");
|
||||
services.AddOptions<ViteProxyOptions>().BindConfiguration(configSectionPath);
|
||||
services.PostConfigure(configure);
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
|
||||
public static IServiceCollection AddViteProxy(this IServiceCollection services, IConfiguration namedConfigurationSection)
|
||||
public static IServiceCollection AddViteProxy(this IServiceCollection services, string configName, IConfiguration namedConfigurationSection)
|
||||
{
|
||||
services.AddLogging();
|
||||
services.AddOptions();
|
||||
services.AddHostedService<ViteProxyService>();
|
||||
services.AddOptions<ViteProxyOptions>().Bind(namedConfigurationSection);
|
||||
services.AddHostedService((svc) => new ViteProxyService(
|
||||
env: svc.GetService<IWebHostEnvironment>(),
|
||||
logger: svc.GetService<ILogger<ViteProxyService>>(),
|
||||
options: svc.GetService<IOptionsSnapshot<ViteProxyOptions>>().Get(configName)
|
||||
));
|
||||
services.AddOptions<ViteProxyOptions>(configName).Bind(namedConfigurationSection);
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user