private static string GetAngularCliMiddlewareScriptPath(IApplicationBuilder appBuilder)
        {
            var script     = EmbeddedResourceReader.Read(typeof(AngularCliMiddleware), _middlewareResourceName);
            var nodeScript = new StringAsTempFile(script, GetStoppingToken(appBuilder));

            return(nodeScript.FileName);
        }
Ejemplo n.º 2
0
        public async Task BuiltInModuleResolved()
        {
            var stopTokenSource = new CancellationTokenSource();
            var options         = new NodeServicesOptions
            {
                ApplicationStoppingToken = stopTokenSource.Token,
                ProjectPath = AppDomain.CurrentDomain.BaseDirectory,
                NodeInstanceOutputLogger = Mock.Of <ILogger>(),
            };

            options.UseSocketHosting();

            using (var services = NodeServicesFactory.CreateNodeServices(options))
                using (var builtinModule = new StringAsTempFile("exports.add = function(a, b) {return a+b;}", stopTokenSource.Token))
                {
                    await services.InvokeExportAsync <object>("builtin-modules-init", "initialize",
                                                              new Dictionary <string, string>()
                    {
                        { "builtin", builtinModule.FileName }
                    });

                    var result = await services.InvokeExportAsync <int>("builtin-modules-test", "test", 1, 2);

                    stopTokenSource.Cancel();

                    Assert.Equal(3, result);
                }
        }
Ejemplo n.º 3
0
        static ReactRenderer()
        {
            // Consider populating this lazily
            var script = EmbeddedResourceReader.Read(typeof(ReactRenderer), "/Content/Node/react-rendering.js");

            nodeScript = new StringAsTempFile(script); // Will be cleaned up on process exit
        }
        /// <summary>
        /// Creates a new instance of <see cref="OutOfProcessNodeInstance"/>.
        /// </summary>
        /// <param name="entryPointScript">The path to the entry point script that the Node instance should load and execute.</param>
        /// <param name="projectPath">The root path of the current project. This is used when resolving Node.js module paths relative to the project root.</param>
        /// <param name="watchFileExtensions">The filename extensions that should be watched within the project root. The Node instance will automatically shut itself down if any matching file changes.</param>
        /// <param name="commandLineArguments">Additional command-line arguments to be passed to the Node.js instance.</param>
        /// <param name="nodeOutputLogger">The <see cref="ILog"/> to which the Node.js instance's stdout/stderr (and other log information) should be written.</param>
        /// <param name="environmentVars">Environment variables to be set on the Node.js process.</param>
        /// <param name="invocationTimeoutMilliseconds">The maximum duration, in milliseconds, to wait for RPC calls to complete.</param>
        /// <param name="launchWithDebugging">If true, passes a flag to the Node.js process telling it to accept V8 debugger connections.</param>
        /// <param name="debuggingPort">If debugging is enabled, the Node.js process should listen for V8 debugger connections on this port.</param>
        public OutOfProcessNodeInstance(
            string entryPointScript,
            string projectPath,
            string[] watchFileExtensions,
            string commandLineArguments,
            ILog nodeOutputLogger,
            IDictionary <string, string> environmentVars,
            int invocationTimeoutMilliseconds,
            bool launchWithDebugging,
            int debuggingPort)
        {
            if (nodeOutputLogger == null)
            {
                throw new ArgumentNullException(nameof(nodeOutputLogger));
            }

            OutputLogger      = nodeOutputLogger;
            _entryPointScript = new StringAsTempFile(entryPointScript);
            _invocationTimeoutMilliseconds = invocationTimeoutMilliseconds;
            _launchWithDebugging           = launchWithDebugging;

            var startInfo = PrepareNodeProcessStartInfo(_entryPointScript.FileName, projectPath, commandLineArguments,
                                                        environmentVars, _launchWithDebugging, debuggingPort);

            _nodeProcess         = LaunchNodeProcess(startInfo);
            _watchFileExtensions = watchFileExtensions;
            _fileSystemWatcher   = BeginFileWatcher(projectPath);
            ConnectToInputOutputStreams();
        }
Ejemplo n.º 5
0
        public static NodeHost CreateFromScript(string handlerScript, string projectPath, ILogger logger)
        {
            var handlerFile = new StringAsTempFile(handlerScript);
            var result      = NodeHost.Create(handlerFile.FileName, projectPath, logger);

            result._handlerFile = handlerFile;
            return(result);
        }
Ejemplo n.º 6
0
        public static NodeHost CreateFromScript(string handlerScript, string projectPath, CancellationToken applicationStopping, ILogger logger, IDictionary <string, string> environmentVars)
        {
            var handlerFile = new StringAsTempFile(handlerScript, applicationStopping);
            var result      = NodeHost.Create(handlerFile.FileName, projectPath, applicationStopping, logger, environmentVars);

            result._handlerFile = handlerFile;
            return(result);
        }
Ejemplo n.º 7
0
        private async Task <LibraryInformation> GetLibraryInformation()
        {
            using (StringAsTempFile file = new StringAsTempFile(GetResource($"{PATH}.BaseProcessor.js"), CancellationToken.None))
            {
                string result = await NodeServices.InvokeAsync <string>(file.FileName, GetLibrary());

                LibraryInformation libraryInformation = JsonConvert.DeserializeObject <LibraryInformation>(result);
                return(libraryInformation);
            }
        }
        static INodeServices fallbackNodeServices; // Used only if no INodeServices was registered with DI

        public static void UseWebpackDevMiddleware(this IApplicationBuilder appBuilder, WebpackDevMiddlewareOptions options = null)
        {
            // Validate options
            if (options != null)
            {
                if (options.ReactHotModuleReplacement && !options.HotModuleReplacement)
                {
                    throw new ArgumentException("To enable ReactHotModuleReplacement, you must also enable HotModuleReplacement.");
                }
            }

            // Get the NodeServices instance from DI
            var nodeServices = (INodeServices)appBuilder.ApplicationServices.GetService(typeof(INodeServices)) ?? fallbackNodeServices;

            // Consider removing the following. Having it means you can get away with not putting app.AddNodeServices()
            // in your startup file, but then again it might be confusing that you don't need to.
            var appEnv = (IApplicationEnvironment)appBuilder.ApplicationServices.GetService(typeof(IApplicationEnvironment));

            if (nodeServices == null)
            {
                nodeServices = fallbackNodeServices = Configuration.CreateNodeServices(NodeHostingModel.Http, appEnv.ApplicationBasePath);
            }

            // Get a filename matching the middleware Node script
            var script     = EmbeddedResourceReader.Read(typeof(WebpackDevMiddleware), "/Content/Node/webpack-dev-middleware.js");
            var nodeScript = new StringAsTempFile(script); // Will be cleaned up on process exit

            // Tell Node to start the server hosting webpack-dev-middleware
            var devServerOptions = new {
                webpackConfigPath = Path.Combine(appEnv.ApplicationBasePath, "webpack.config.js"),
                suppliedOptions   = options ?? new WebpackDevMiddlewareOptions()
            };
            var devServerInfo = nodeServices.InvokeExport <WebpackDevServerInfo>(nodeScript.FileName, "createWebpackDevServer", JsonConvert.SerializeObject(devServerOptions)).Result;

            // Proxy the corresponding requests through ASP.NET and into the Node listener
            appBuilder.Map(devServerInfo.PublicPath, builder => {
                builder.RunProxy(new ProxyOptions {
                    Host = WebpackDevMiddlewareHostname,
                    Port = devServerInfo.Port.ToString()
                });
            });

            // While it would be nice to proxy the /__webpack_hmr requests too, these return an EventStream,
            // and the Microsoft.Aspnet.Proxy code doesn't handle that entirely - it throws an exception after
            // a while. So, just serve a 302 for those.
            appBuilder.Map(WebpackHotMiddlewareEndpoint, builder => {
                builder.Use(next => async ctx => {
                    ctx.Response.Redirect($"http://localhost:{ devServerInfo.Port.ToString() }{ WebpackHotMiddlewareEndpoint }");
                    await Task.Yield();
                });
            });
        }
Ejemplo n.º 9
0
        public static void UseWebpackDevMiddleware(this IApplicationBuilder appBuilder, WebpackDevMiddlewareOptions options = null)
        {
            // Validate options
            if (options != null)
            {
                if (options.ReactHotModuleReplacement && !options.HotModuleReplacement)
                {
                    throw new ArgumentException("To enable ReactHotModuleReplacement, you must also enable HotModuleReplacement.");
                }
            }

            // Unlike other consumers of NodeServices, WebpackDevMiddleware dosen't share Node instances, nor does it
            // use your DI configuration. It's important for WebpackDevMiddleware to have its own private Node instance
            // because it must *not* restart when files change (if it did, you'd lose all the benefits of Webpack
            // middleware). And since this is a dev-time-only feature, it doesn't matter if the default transport isn't
            // as fast as some theoretical future alternative.
            var appEnv       = (IApplicationEnvironment)appBuilder.ApplicationServices.GetService(typeof(IApplicationEnvironment));
            var nodeServices = Configuration.CreateNodeServices(new NodeServicesOptions {
                HostingModel        = NodeHostingModel.Http,
                ProjectPath         = appEnv.ApplicationBasePath,
                WatchFileExtensions = new string[] {} // Don't watch anything
            });

            // Get a filename matching the middleware Node script
            var script     = EmbeddedResourceReader.Read(typeof(WebpackDevMiddleware), "/Content/Node/webpack-dev-middleware.js");
            var nodeScript = new StringAsTempFile(script); // Will be cleaned up on process exit

            // Tell Node to start the server hosting webpack-dev-middleware
            var devServerOptions = new {
                webpackConfigPath = Path.Combine(appEnv.ApplicationBasePath, "webpack.config.js"),
                suppliedOptions   = options ?? new WebpackDevMiddlewareOptions()
            };
            var devServerInfo = nodeServices.InvokeExport <WebpackDevServerInfo>(nodeScript.FileName, "createWebpackDevServer", JsonConvert.SerializeObject(devServerOptions)).Result;

            // Proxy the corresponding requests through ASP.NET and into the Node listener
            appBuilder.Map(devServerInfo.PublicPath, builder => {
                builder.RunProxy(new ProxyOptions {
                    Host = WebpackDevMiddlewareHostname,
                    Port = devServerInfo.Port.ToString()
                });
            });

            // While it would be nice to proxy the /__webpack_hmr requests too, these return an EventStream,
            // and the Microsoft.Aspnet.Proxy code doesn't handle that entirely - it throws an exception after
            // a while. So, just serve a 302 for those.
            appBuilder.Map(WebpackHotMiddlewareEndpoint, builder => {
                builder.Use(next => async ctx => {
                    ctx.Response.Redirect($"http://localhost:{ devServerInfo.Port.ToString() }{ WebpackHotMiddlewareEndpoint }");
                    await Task.Yield();
                });
            });
        }
Ejemplo n.º 10
0
        private static string GetNodeScriptFilename(CancellationToken applicationStoppingToken)
        {
            lock (CreateNodeScriptLock)
            {
                if (NodeScript == null)
                {
                    var script = EmbeddedResourceReader.Read(typeof(Renderer), "/Content/Node/prerenderer.js");
                    NodeScript = new StringAsTempFile(script, applicationStoppingToken); // Will be cleaned up on process exit
                }
            }

            return(NodeScript.FileName);
        }
Ejemplo n.º 11
0
        private static string GetNodeScriptFilename(CancellationToken applicationStoppingToken)
        {
            lock (CreateNodeScriptLock)
            {
                if (nodeScript == null)
                {
                    var script = EmbeddedResourceReader.Read(typeof(EmPageRenderer), RendererScriptPath);
                    nodeScript = new StringAsTempFile(script, applicationStoppingToken);
                }
            }

            return(nodeScript.FileName);
        }
        public static IApplicationBuilder UseParcelBundler(this IApplicationBuilder app, ParcelBundlerOptions options)
        {
            var environment = app.ApplicationServices.GetService <IHostingEnvironment>();

            var nodeServiceOptions = new NodeServicesOptions(app.ApplicationServices)
            {
                WatchFileExtensions = new string[] { }
            };

            string content = LoadScriptContent();
            var    script  = new StringAsTempFile(content, nodeServiceOptions.ApplicationStoppingToken);

            var node = NodeServicesFactory.CreateNodeServices(nodeServiceOptions);

            var args = new
            {
                entryPoints = options.EntryPoints,
                options     = new
                {
                    outDir         = Path.Combine(environment.WebRootPath, options.OutDir ?? ""),
                    outFile        = options.OutFile,
                    publicUrl      = options.PublicUrl,
                    watch          = options.Watch,
                    cache          = options.Cache,
                    cacheDir       = options.CacheDir,
                    contentHash    = options.ContentHash,
                    minify         = options.Minify,
                    scopeHoist     = options.ScopeHoist,
                    target         = options.Target?.ToString().ToLower(),
                    https          = options.Https?.ToParcelOptions(),
                    hmr            = options.HotModuleReload?.IsEnabled,
                    hmrPort        = options.HotModuleReload?.Port,
                    sourcemaps     = options.SourceMaps,
                    hmrHostname    = options.HotModuleReload?.Hostname,
                    detailedReport = options.DetailedReport
                }
            };

            var response = node.InvokeExportAsync <ParcelServerInfo>(script.FileName, "runParcelBundler", JsonConvert.SerializeObject(args, SerializerSettings))
                           .Result;

            return(app);
        }
Ejemplo n.º 13
0
        private async Task <DM.Citation> CreateCitationAsync(DE.Style style, DE.Format format, DM.ContentItem contentItem)
        {
            ExpandoObject         request     = new ExpandoObject();
            List <PM.ContentItem> requestList = new List <PM.ContentItem>();

            requestList.Add(PF.CiteProcFactory.Build("0", contentItem));
            requestList = _overrideManager.PreProcessCitation(style, requestList);
            requestList.ForEach(x => request.TryAdd(x.ID, x));
            using (StringAsTempFile file = new StringAsTempFile(GetContents(), CancellationToken.None))
            {
                string result = await NodeServices.InvokeAsync <string>(file.FileName,
                                                                        GetLibrary(),
                                                                        PL.Locale.GetLocale(),
                                                                        PD.Definition.GetDefinition(style),
                                                                        PF.CiteProcFactory.Build(format),
                                                                        JObject.Parse(request.ToSerializedJSON()));

                PM.Citation citation = JsonConvert.DeserializeObject <PM.Citation>(result);
                citation.ProcessExceptions();
                citation = _overrideManager.PostProcessCitation(style, citation);
                DM.Citation response = PF.CiteProcFactory.Build(citation);
                return(response);
            }
        }
Ejemplo n.º 14
0
        private async Task <DM.Bibliography> CreateBibliographyAsync(DE.Style style, DE.Format format, List <DM.ContentItem> contentItems)
        {
            ExpandoObject         request     = new ExpandoObject();
            List <PM.ContentItem> requestList = new List <PM.ContentItem>();

            requestList.AddRange(contentItems.Select((x, i) => PF.CiteProcFactory.Build(i.ToString(), x)));
            requestList = _overrideManager.PreProcessBibliography(style, requestList);
            requestList.ForEach(x => request.TryAdd(x.ID, x));
            using (StringAsTempFile file = new StringAsTempFile(GetContents(), CancellationToken.None))
            {
                string result = await NodeServices.InvokeAsync <string>(file.FileName,
                                                                        GetLibrary(),
                                                                        PL.Locale.GetLocale(),
                                                                        PD.Definition.GetDefinition(style),
                                                                        PF.CiteProcFactory.Build(format),
                                                                        JObject.Parse(request.ToSerializedJSON()));

                PM.Bibliography bibliography = JsonConvert.DeserializeObject <PM.Bibliography>(result);
                bibliography.ProcessExceptions();
                bibliography = _overrideManager.PostProcessBibliography(style, bibliography);
                DM.Bibliography response = PF.CiteProcFactory.Build(bibliography);
                return(response);
            }
        }
Ejemplo n.º 15
0
 static AngularRenderer() {
     // Consider populating this lazily
     var script = EmbeddedResourceReader.Read(typeof (AngularRenderer), "/Content/Node/angular-rendering.js");
     nodeScript = new StringAsTempFile(script); // Will be cleaned up on process exit
 }
Ejemplo n.º 16
0
        /// <summary>
        /// Enables Webpack dev middleware support. This hosts an instance of the Webpack compiler in memory
        /// in your application so that you can always serve up-to-date Webpack-built resources without having
        /// to run the compiler manually. Since the Webpack compiler instance is retained in memory, incremental
        /// compilation is vastly faster that re-running the compiler from scratch.
        ///
        /// Incoming requests that match Webpack-built files will be handled by returning the Webpack compiler
        /// output directly, regardless of files on disk. If compilation is in progress when the request arrives,
        /// the response will pause until updated compiler output is ready.
        /// </summary>
        /// <param name="appBuilder">The <see cref="IApplicationBuilder"/>.</param>
        /// <param name="options">Options for configuring the Webpack compiler instance.</param>
        public static void UseWebpackDevMiddleware(
            this IApplicationBuilder appBuilder,
            WebpackDevMiddlewareOptions options = null)
        {
            // Prepare options
            if (options == null)
            {
                options = new WebpackDevMiddlewareOptions();
            }

            // Validate options
            if (options.ReactHotModuleReplacement && !options.HotModuleReplacement)
            {
                throw new ArgumentException(
                          "To enable ReactHotModuleReplacement, you must also enable HotModuleReplacement.");
            }

            // Unlike other consumers of NodeServices, WebpackDevMiddleware dosen't share Node instances, nor does it
            // use your DI configuration. It's important for WebpackDevMiddleware to have its own private Node instance
            // because it must *not* restart when files change (if it did, you'd lose all the benefits of Webpack
            // middleware). And since this is a dev-time-only feature, it doesn't matter if the default transport isn't
            // as fast as some theoretical future alternative.
            var nodeServicesOptions = new NodeServicesOptions(appBuilder.ApplicationServices);

            nodeServicesOptions.WatchFileExtensions = new string[] { }; // Don't watch anything
            if (!string.IsNullOrEmpty(options.ProjectPath))
            {
                nodeServicesOptions.ProjectPath = options.ProjectPath;
            }

            if (options.EnvironmentVariables != null)
            {
                foreach (var kvp in options.EnvironmentVariables)
                {
                    nodeServicesOptions.EnvironmentVariables[kvp.Key] = kvp.Value;
                }
            }

            var nodeServices = NodeServicesFactory.CreateNodeServices(nodeServicesOptions);

            // Get a filename matching the middleware Node script
            var script = EmbeddedResourceReader.Read(typeof(WebpackDevMiddleware),
                                                     "/Content/Node/webpack-dev-middleware.js");
            var nodeScript = new StringAsTempFile(script, nodeServicesOptions.ApplicationStoppingToken); // Will be cleaned up on process exit

            // Ideally, this would be relative to the application's PathBase (so it could work in virtual directories)
            // but it's not clear that such information exists during application startup, as opposed to within the context
            // of a request.
            var hmrEndpoint = !string.IsNullOrEmpty(options.HotModuleReplacementEndpoint)
                ? options.HotModuleReplacementEndpoint
                : "/__webpack_hmr"; // Matches webpack's built-in default

            // Tell Node to start the server hosting webpack-dev-middleware
            var devServerOptions = new
            {
                webpackConfigPath = Path.Combine(nodeServicesOptions.ProjectPath, options.ConfigFile ?? DefaultConfigFile),
                suppliedOptions   = options,
                understandsMultiplePublicPaths  = true,
                hotModuleReplacementEndpointUrl = hmrEndpoint
            };
            var devServerInfo =
                nodeServices.InvokeExportAsync <WebpackDevServerInfo>(nodeScript.FileName, "createWebpackDevServer",
                                                                      JsonConvert.SerializeObject(devServerOptions, jsonSerializerSettings)).Result;

            // If we're talking to an older version of aspnet-webpack, it will return only a single PublicPath,
            // not an array of PublicPaths. Handle that scenario.
            if (devServerInfo.PublicPaths == null)
            {
                devServerInfo.PublicPaths = new[] { devServerInfo.PublicPath };
            }

            // Proxy the corresponding requests through ASP.NET and into the Node listener
            // Anything under /<publicpath> (e.g., /dist) is proxied as a normal HTTP request with a typical timeout (100s is the default from HttpClient),
            // plus /__webpack_hmr is proxied with infinite timeout, because it's an EventSource (long-lived request).
            foreach (var publicPath in devServerInfo.PublicPaths)
            {
                appBuilder.UseProxyToLocalWebpackDevMiddleware(publicPath + hmrEndpoint, devServerInfo.Port, Timeout.InfiniteTimeSpan);
                appBuilder.UseProxyToLocalWebpackDevMiddleware(publicPath, devServerInfo.Port, TimeSpan.FromSeconds(100));
            }
        }
        /// <summary>
        /// Enables Parcel dev middleware support. This hosts an instance of Parcel in memory
        /// in your application so that you can always serve up-to-date Parcel-built resources without having
        /// to run it manually. Since Parcel is retained in memory, incremental
        /// compilation is vastly faster that re-running it from scratch.
        ///
        /// Incoming requests that match Parcel-built files will be handled by returning the Parcel
        /// output directly, regardless of files on disk. If compilation is in progress when the request arrives,
        /// the response will pause until updated compiler output is ready.
        /// </summary>
        /// <param name="appBuilder">The <see cref="IApplicationBuilder"/>.</param>
        /// <param name="options">Options for configuring Parcel.</param>
        public static void UseParcelDevMiddleware(
            this IApplicationBuilder appBuilder,
            ParcelBundlerOptions options = null)
        {
            // Prepare options
            if (options == null)
            {
                options = new ParcelBundlerOptions();
            }

            // Unlike other consumers of NodeServices, ParcelDevMiddleware dosen't share Node instances, nor does it
            // use your DI configuration. It's important for ParcelDevMiddleware to have its own private Node instance
            // because it must *not* restart when files change (if it did, you'd lose all the benefits of Parcel
            // middleware). And since this is a dev-time-only feature, it doesn't matter if the default transport isn't
            // as fast as some theoretical future alternative.
            var nodeServicesOptions = new NodeServicesOptions(appBuilder.ApplicationServices);

            nodeServicesOptions.WatchFileExtensions = new string[] { }; // Don't watch anything
            if (!string.IsNullOrEmpty(options.ProjectPath))
            {
                nodeServicesOptions.ProjectPath = options.ProjectPath;
            }

            if (options.EnvironmentVariables != null)
            {
                foreach (var kvp in options.EnvironmentVariables)
                {
                    nodeServicesOptions.EnvironmentVariables[kvp.Key] = kvp.Value;
                }
            }

            var nodeServices = NodeServicesFactory.CreateNodeServices(nodeServicesOptions);

            // Get a filename matching the middleware Node script
            //Actual resource name: RudiBech.AspNetCore.SpaServices.Parcel.parcel-dev-middleware.js
            var script = EmbeddedResourceReader.Read(typeof(ParcelDevMiddelware), "/parcel-dev-middleware.js");

            // Will be cleaned up on process exit
            var nodeScript = new StringAsTempFile(script, nodeServicesOptions.ApplicationStoppingToken);

            // Tell Node to start the server hosting webpack-dev-middleware
            var parcelOptions = new
            {
                watch          = options.Watch,
                hmrPort        = options.Port,
                outDir         = options.OutDir,
                outFile        = options.OutFile,
                publicUrl      = options.PublicUrl,
                cache          = options.Cache,
                cacheDir       = options.CacheDir,
                minify         = options.Minify,
                target         = options.Target,
                logLevel       = (int)options.LogLevel,
                sourceMaps     = options.SourceMaps,
                detailedReport = options.DetailedReport,
                entryPoint     = options.EntryPoint
            };

            var devServerInfo =
                nodeServices.InvokeExportAsync <ParcelDevServerInfo>(nodeScript.FileName, "createParcelDevServer",
                                                                     JsonConvert.SerializeObject(parcelOptions, jsonSerializerSettings)).Result;

            // Proxy the corresponding requests through ASP.NET and into the Node listener
            // Anything under /<publicpath> (e.g., /dist) is proxied as a normal HTTP request with a typical timeout (100s is the default from HttpClient)
            foreach (var publicPath in devServerInfo.PublicPaths)
            {
                appBuilder.UseProxyToLocalParcelDevMiddleware(publicPath, devServerInfo.Port, TimeSpan.FromSeconds(100));
            }
        }