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);
        }
Beispiel #2
0
        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);
        }