private static async Task <int> StartVueCliServerAsync( string sourcePath, string npmScriptName, ILogger logger, int portNumber, ScriptRunnerType runner, string regex, bool forceKill = false, bool wsl = false) { if (portNumber < 80) { portNumber = TcpPortFinder.FindAvailablePort(); } else { // if the port we want to use is occupied, terminate the process utilizing that port. // this occurs when "stop" is used from the debugger and the middleware does not have the opportunity to kill the process PidUtils.KillPort((ushort)portNumber, forceKill); } logger.LogInformation($"Starting server on port {portNumber}..."); var envVars = new Dictionary <string, string> { { "PORT", portNumber.ToString() }, { "DEV_SERVER_PORT", portNumber.ToString() }, // vue cli 3 uses --port {number}, included below { "BROWSER", "none" }, // We don't want vue-cli to open its own extra browser window pointing to the internal dev server port { "CODESANDBOX_SSE", true.ToString() }, // this will make vue cli use client side HMR inference }; var npmScriptRunner = new ScriptRunner(sourcePath, npmScriptName, $"--port {portNumber:0}", envVars, runner: runner, wsl: wsl); AppDomain.CurrentDomain.DomainUnload += (s, e) => npmScriptRunner?.Kill(); AppDomain.CurrentDomain.ProcessExit += (s, e) => npmScriptRunner?.Kill(); AppDomain.CurrentDomain.UnhandledException += (s, e) => npmScriptRunner?.Kill(); npmScriptRunner.AttachToLogger(logger); using (var stdErrReader = new EventedStreamStringReader(npmScriptRunner.StdErr)) { try { // Although the Vue dev server may eventually tell us the URL it's listening on, // it doesn't do so until it's finished compiling, and even then only if there were // no compiler warnings. So instead of waiting for that, consider it ready as soon // as it starts listening for requests. await npmScriptRunner.StdOut.WaitForMatch(new Regex(!string.IsNullOrWhiteSpace(regex) ? regex : DefaultRegex, RegexOptions.None, RegexMatchTimeout)); } catch (EndOfStreamException ex) { throw new InvalidOperationException( $"The NPM script '{npmScriptName}' exited without indicating that the " + $"server was listening for requests. The error output was: " + $"{stdErrReader.ReadAsString()}", ex); } } return(portNumber); }
private static async Task <int> StartVueCliServerAsync( string sourcePath, string npmScriptName, ILogger logger, int portNumber, ScriptRunnerType runner, string regex) { if (portNumber < 80) { portNumber = TcpPortFinder.FindAvailablePort(); } logger.LogInformation($"Starting server on port {portNumber}..."); var envVars = new Dictionary <string, string> { { "PORT", portNumber.ToString() }, { "DEV_SERVER_PORT", portNumber.ToString() }, // vue cli 3 uses --port {number}, included below { "BROWSER", "none" }, // We don't want vue-cli to open its own extra browser window pointing to the internal dev server port }; var npmScriptRunner = new ScriptRunner(sourcePath, npmScriptName, $"--port {portNumber:0}", envVars, runner: runner); npmScriptRunner.AttachToLogger(logger); using (var stdErrReader = new EventedStreamStringReader(npmScriptRunner.StdErr)) { try { // Although the Vue dev server may eventually tell us the URL it's listening on, // it doesn't do so until it's finished compiling, and even then only if there were // no compiler warnings. So instead of waiting for that, consider it ready as soon // as it starts listening for requests. await npmScriptRunner.StdOut.WaitForMatch(new Regex(!string.IsNullOrWhiteSpace(regex) ? regex : DefaultRegex, RegexOptions.None, RegexMatchTimeout)); } catch (EndOfStreamException ex) { throw new InvalidOperationException( $"The NPM script '{npmScriptName}' exited without indicating that the " + $"server was listening for requests. The error output was: " + $"{stdErrReader.ReadAsString()}", ex); } } return(portNumber); }