private static string GetAngularCliMiddlewareScriptPath(IApplicationBuilder appBuilder) { var script = EmbeddedResourceReader.Read(typeof(AngularCliMiddleware), _middlewareResourceName); var nodeScript = new StringAsTempFile(script, GetStoppingToken(appBuilder)); return(nodeScript.FileName); }
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); } }
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(); }
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); }
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); }
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(); }); }); }
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(); }); }); }
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); }
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); }
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); } }
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); } }
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 }
/// <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)); } }