public Visualizer(string baseDir) { _baseDir = baseDir; var services = new ServiceCollection(); services.AddNodeServices(); var options = new NodeServicesOptions(services.BuildServiceProvider()) { ProjectPath = Directory.GetCurrentDirectory() }; _node = NodeServicesFactory.CreateNodeServices(options); }
private static INodeServices CreateNodeServicesInstance( IApplicationBuilder appBuilder, string sourcePath) { // Unlike other consumers of NodeServices, AngularCliMiddleware dosen't share Node instances, nor does it // use your DI configuration. It's important for AngularCliMiddleware to have its own private Node instance // because it must *not* restart when files change (it's designed to watch for changes and rebuild). var nodeServicesOptions = new NodeServicesOptions(appBuilder.ApplicationServices) { WatchFileExtensions = new string[] { }, // Don't watch anything ProjectPath = Path.Combine(Directory.GetCurrentDirectory(), sourcePath), }; return(NodeServicesFactory.CreateNodeServices(nodeServicesOptions)); }
public HandlerFactoryFixture() { var resolvers = new List <IMetadataReferenceResolver> { new DefaultMetadataReferenceResolver() }; var builder = new DefaultAssemblyBuilder(new DefaultAssemblyLoadContextProvider(), resolvers); var options = new NodeServicesOptions(new ServiceCollection().BuildServiceProvider()) { ProjectPath = Directory.GetCurrentDirectory() }; var nodeServices = NodeServicesFactory.CreateNodeServices(options); Factory = new HandlerFactory(builder, nodeServices, typeof(string).GetTypeInfo().Assembly); // mscorlib }
public static void Validate(string typescriptSource) { if (s_nodeServices == null) { var options = new NodeServicesOptions(NullServiceProvider.Instance); s_nodeServices = NodeServicesFactory.CreateNodeServices(options); } var task = s_nodeServices.InvokeAsync <string>("TypeScriptValidator.js", typescriptSource); var result = task.GetAwaiter().GetResult(); if (result != "success") { Assert.Fail("\n" + typescriptSource + "\n\nErrors:\n" + result); } }
/// <summary> /// Adds NodeServices support to the <paramref name="serviceCollection"/>. /// </summary> /// <param name="serviceCollection">The <see cref="IServiceCollection"/>.</param> /// <param name="setupAction">A callback that will be invoked to populate the <see cref="NodeServicesOptions"/>.</param> public static void AddNodeServices(this IServiceCollection serviceCollection, Action <NodeServicesOptions> setupAction) { if (setupAction == null) { throw new ArgumentNullException(nameof(setupAction)); } serviceCollection.AddSingleton(typeof(INodeServices), serviceProvider => { // First we let NodeServicesOptions take its defaults from the IServiceProvider, // then we let the developer override those options var options = new NodeServicesOptions(serviceProvider); setupAction(options); return(NodeServicesFactory.CreateNodeServices(options)); }); }
public Task <NodePackage> GetInstalledPackageAsync(string path) { var pp = this.ParsePath(path); return(cache.GetOrCreateAsync <NodePackage>(pp.Package + "@" + pp.Version, async entry => { entry.SlidingExpiration = TimeSpan.FromHours(1); await InstallAsync(pp); var options = this.Options.NodeServicesOptions ?? new NodeServicesOptions(services) { ProjectPath = pp.TagFolder, NodeInstanceOutputLogger = services.GetService <ILogger <NodePackageService> >() }; if (this.Options.EnvironmentVariables != null) { if (options.EnvironmentVariables == null) { options.EnvironmentVariables = new Dictionary <string, string>(); } foreach (var item in this.Options.EnvironmentVariables) { options.EnvironmentVariables[item.Key] = item.Value; } } var s = NodeServicesFactory.CreateNodeServices(options); entry.RegisterPostEvictionCallback((x1, x2, x3, x4) => { try { s.Dispose(); } catch (Exception ex) { Trace.WriteLine(ex); } }); return new NodePackage { Path = pp, NodeServices = s }; })); }
/// <summary> /// Initializes a new instance of the <see cref="NodeRenderEngine" /> class. /// </summary> /// <param name="serviceProvider">The service provider.</param> /// <param name="options">The options.</param> public NodeRenderEngine(IServiceProvider serviceProvider, NodeRenderEngineOptions options) { _options = options; var nodeOptions = new NodeServicesOptions(serviceProvider) { HostingModel = options.NodeHostingModel, ProjectPath = options.ProjectDirectory, WatchFileExtensions = options.WatchFileExtensions }; if (options.NodeInstanceOutputLogger != null) { nodeOptions.NodeInstanceOutputLogger = options.NodeInstanceOutputLogger; } _nodeServices = NodeServicesFactory.CreateNodeServices(nodeOptions); }
public static IServiceCollection AddSmidgeJavaScriptServices(this IServiceCollection services) { services.AddSingleton <SmidgeJavaScriptServices>(provider => { var env = provider.GetRequiredService <IHostingEnvironment>(); return(new SmidgeJavaScriptServices(NodeServicesFactory.CreateNodeServices( new NodeServicesOptions(provider) { ProjectPath = env.ContentRootPath, WatchFileExtensions = new string[] { } }))); }); //pre processors services.AddSingleton <IPreProcessor, UglifyNodeMinifier>(); return(services); }
private static async Task RunServiceAsync(CancellationToken cancellationToken = default(CancellationToken)) { // Start server INodeServices nodeService = ServiceLocator.Current.GetService <INodeServices>(); if (nodeService == null) { nodeService = NodeServicesFactory.CreateNodeServices(new NodeServicesOptions(ServiceLocator.Current)); } string result = nodeService.InvokeAsync <string>("server.js").Result; PrintNodeJsOutput(result); await AwaitCancellation(cancellationToken); //await nodeService.InvokeAsync<string>("Shutdown").Result; }
/// <summary> /// Creates a new instance of <see cref="PrerenderTagHelper"/>. /// </summary> /// <param name="serviceProvider">The <see cref="IServiceProvider"/>.</param> public VueRenderTagHelper(IServiceProvider serviceProvider) { _hostEnv = (IHostingEnvironment)serviceProvider.GetService(typeof(IHostingEnvironment)); _nodeServices = (INodeServices)serviceProvider.GetService(typeof(INodeServices)) ?? _fallbackNodeServices; _applicationBasePath = _hostEnv.ContentRootPath; var applicationLifetime = (IApplicationLifetime)serviceProvider.GetService(typeof(IApplicationLifetime)); _applicationStoppingToken = applicationLifetime.ApplicationStopping; // 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. if (_nodeServices == null) { _nodeServices = _fallbackNodeServices = NodeServicesFactory.CreateNodeServices( new NodeServicesOptions(serviceProvider)); } }
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); }
public PugRenderingTestsFixture() { var optionsMock = new Mock <IOptions <PugzorViewEngineOptions> >(); optionsMock.SetupGet(q => q.Value) .Returns(new PugzorViewEngineOptions { // true: makes a lot of tests to fail Pretty = false }); var mockServices = new Mock <IServiceProvider>(); var nodeServiceOptions = new NodeServicesOptions(mockServices.Object) { ProjectPath = TemporaryDirectoryHelper.CreateTemporaryDirectory(true) }; var nodeServices = NodeServicesFactory.CreateNodeServices(nodeServiceOptions); Renderer = new PugRendering(nodeServices, optionsMock.Object); }
public void Setup() { var websiteInfo = new Mock <IWebsiteInfo>(); websiteInfo.Setup(x => x.GetBasePath()).Returns("/"); websiteInfo.Setup(x => x.GetBaseUrl()).Returns(new Uri("http://test.com")); _jsMin = new JsMinifier(); _nuglify = new NuglifyJs( new NuglifySettings(new NuglifyCodeSettings(null), new CssSettings()), Mock.Of <ISourceMapDeclaration>()); var nodeServices = new SmidgeJavaScriptServices(NodeServicesFactory.CreateNodeServices( new NodeServicesOptions(new NullServiceProvider()) { ProjectPath = AssemblyPath, WatchFileExtensions = new string[] {} })); _jsUglify = new UglifyNodeMinifier(nodeServices); }
public NodeBindingTests() { var options = new NodeServicesOptions { ApplicationStoppingToken = stopTokenSource.Token, ProjectPath = AppDomain.CurrentDomain.BaseDirectory, NodeInstanceOutputLogger = Mock.Of <ILogger>(), DebuggingPort = 9000, LaunchWithDebugging = true }; options.UseSocketHosting(); nodeServices = NodeServicesFactory.CreateNodeServices(options); rpcHost = new JsonRpcBindingHost(js => new LineDelimitedJsonConnection(js)); rpcHost.Repository.AddBinding("test", new TestBound()); var initTask = nodeServices.InvokeExportAsync <Stream>("binding-init", "initialize", rpcHost.Repository.Objects); this.initTask = initTask.ContinueWith(t => (rpcHost.Connection as LineDelimitedJsonConnection)?.Initialize(t.Result, t.Result)); }
public static async Task <TResult> RunAsync <TData, TResult>(string module, TData data) { var services = new ServiceCollection(); services.AddNodeServices(a => { // a.ProjectPath = Directory.GetCurrentDirectory(); // Set any properties that you want on 'options' here }); var serviceProvider = services.BuildServiceProvider(); var options = new NodeServicesOptions(serviceProvider) { ProjectPath = Directory.GetCurrentDirectory() + "/tmphost", InvocationTimeoutMilliseconds = 60000 * 5, }; var nodeServices = NodeServicesFactory.CreateNodeServices(options); var sb = new StringBuilder(); // sb.AppendLine("return function (data,callback){"); sb.AppendLine("var requirejs = require(\"requirejs\");"); sb.AppendLine($"var r = requirejs.config({{ baseUrl:'{Path.Combine(Directory.GetCurrentDirectory(), "artifacts/app").Replace("\\", "/")}'}});"); sb.AppendLine("module.exports= function (callback,data){ try{"); sb.AppendLine($"r([\"{module}\"], function (program) {{ program.default(data, callback); }},function(err){{ console.log('host failed'); callback(err,null) }})"); sb.AppendLine("}catch(error){console.log('host catch');callback(error,null); }}"); Directory.CreateDirectory("tmphost"); File.WriteAllText("tmphost/run.js", sb.ToString()); return(await nodeServices.InvokeAsync <TResult>("./run", data)); // return JToken.FromObject(await Edge.Func(sb.ToString())(data)).ToObject<TResult>(); }
/// <summary> /// Initializes a new instance of the <see cref="NodeRenderEngine" /> class. /// </summary> /// <param name="serviceProvider">The service provider.</param> /// <param name="options">The options.</param> public NodeRenderEngine(IServiceProvider serviceProvider, NodeRenderEngineOptions options) { _options = options; var nodeOptions = new NodeServicesOptions(serviceProvider ?? new EmptyServiceProvider()) { ProjectPath = options.ProjectDirectory, WatchFileExtensions = options.WatchFileExtensions, EnvironmentVariables = options.EnvironmentVariables, DebuggingPort = options.DebuggingPort, LaunchWithDebugging = options.LaunchWithDebugging }; if (options.NodeInstanceFactory != null) { nodeOptions.NodeInstanceFactory = options.NodeInstanceFactory; } if (options.NodeInstanceOutputLogger != null) { nodeOptions.NodeInstanceOutputLogger = options.NodeInstanceOutputLogger; } _nodeServices = NodeServicesFactory.CreateNodeServices(nodeOptions); }
/// <summary> /// Sends a message using Gmail API /// </summary> /// <param name="msg">Message to send</param> /// <returns>JSON serialized string of a result object</returns> public string Send(EmailMessage msg) { string emailTemplate = GetMsgTemplate(msg.template.templateId); if (null == emailTemplate) { _logger.LogError($"Unable to load Email template with id {msg.template.templateId}"); return(null); } string htmlBody = null; string subject = null; ServiceCollection services = new ServiceCollection(); services.AddNodeServices(); using (ServiceProvider serviceProvider = services.BuildServiceProvider()) { NodeServicesOptions options = new NodeServicesOptions(serviceProvider) /* Assign/override any other options here */ } { ; using (INodeServices nodeServices = NodeServicesFactory.CreateNodeServices(options)) { htmlBody = nodeServices.InvokeAsync <string>("pugcompile", emailTemplate, null == msg.bodyModel ? null: JsonConvert.DeserializeObject(msg.bodyModel)).Result; subject = nodeServices.InvokeAsync <string>("pugcompile", msg.template.subjectTemplate, null == msg.subjectModel ? null : JsonConvert.DeserializeObject(msg.subjectModel)).Result; } } services.Clear(); if (null == subject) { _logger.LogError($"Unable to load email subject"); return(null); } if (null == emailTemplate) { _logger.LogError($"Unable to load Email template with id {msg.template.templateId}"); return(null); } UserCredential credential; string[] scopes = { GmailService.Scope.GmailSend }; using (FileStream stream = new FileStream("credentials.json", FileMode.Open, FileAccess.Read)) { // The file token.json stores the user's access and refresh tokens, and is created // automatically when the authorization flow completes for the first time. string credPath = "token.json"; credential = GoogleWebAuthorizationBroker.AuthorizeAsync( GoogleClientSecrets.Load(stream).Secrets, scopes, "user", CancellationToken.None, new FileDataStore(credPath, true)).Result; _logger.LogInformation("Google credential file saved to: " + credPath); } // Create Gmail API service. using (GmailService service = new GmailService(new BaseClientService.Initializer() { HttpClientInitializer = credential, ApplicationName = "MailGmail", })) { Google.Apis.Gmail.v1.Data.Message message = CreateGmailMessage(msg.from, msg.to, subject, htmlBody); Google.Apis.Gmail.v1.Data.Message messageResult = service.Users.Messages.Send(message, "me").Execute(); return(JsonConvert.SerializeObject(messageResult)); } }
private async Task <int> OnExecuteAsync(CommandLineApplication app) { if (string.IsNullOrEmpty(Url) && string.IsNullOrEmpty(RemotePageLocation) && !HelloWorld) { app.ShowHelp(); return(0); } Console.WriteLine(HostFolder); Directory.CreateDirectory(HostFolder); Directory.CreateDirectory("output"); await InstallNPMPackage(HostFolder, "requirejs"); await InstallNPMPackage(HostFolder, "puppeteer"); await InstallNPMPackage(HostFolder, "websocket"); await InstallNPMPackage(HostFolder, "isomorphic-fetch"); await InstallNPMPackage(HostFolder, "earthml-temply-headless"); var engine = new RazorLightEngineBuilder() .UseEmbeddedResourcesProject(typeof(Program)) .UseMemoryCachingProvider() .Build(); Console.WriteLine(string.Join(" ", app.RemainingArguments)); var args = new JObject(); for (var j = 0; j < app.RemainingArguments.Count; j += 2) { args[app.RemainingArguments[j].Trim('-')] = app.RemainingArguments[j + 1]; } IWebHost host = new WebHostBuilder() .UseKestrel() .Configure(appbuilder => { appbuilder.Use(async(context, next) => { Console.WriteLine(context.Request.Path); if (context.Request.Path == "/installDependencies") { var dps = JToken.Parse(await new StreamReader(context.Request.Body).ReadToEndAsync()); foreach (JProperty dependency in dps.SelectToken("$.dependencies")) { await InstallNPMPackage(HostFolder, dependency.Name, dependency.Value.ToString()); } context.Response.StatusCode = 200; return; } if (context.Request.Path == "/hello-world") { await context.Response.WriteAsync(@"<html><head><script src=""node_modules/requirejs/require.js""></script></head><body><script type=""text/javascript"">require.config({paths:{'earthml-temply-headless':'node_modules/earthml-temply-headless/artifacts/src'}}); require(['earthml-temply-headless/remotepage/remotepage'],(RemotePageModule)=>{console.log(RemotePageModule);let rp = new RemotePageModule.RemotePage(); rp.helloWorld(); })</script></body></html>"); return; } if (context.Request.Path == "/") { try { string result = await engine.CompileRenderAsync("GenericRemoteHost.cshtml", new { Name = "John Doe" }); await context.Response.WriteAsync(result); } catch (Exception ex) { Console.WriteLine(ex); } return; } await next(); Console.WriteLine($"{context.Request.Path} {context.Response.StatusCode}"); }); foreach (var volumne in Volumes) { appbuilder.Map(volumne.Split(':').Last(), (b) => { b.Use(async(ctx, next) => { await next(); Console.WriteLine($"{ctx.Request.Path} {ctx.Response.StatusCode}"); }); b.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider(string.Join(":", volumne.Split(':').Reverse().Skip(1).Reverse())) }); }); } //appbuilder.Map("/appinsight", (b) => //{ // b.UseStaticFiles(new StaticFileOptions { FileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider(@"C:\dev\EarthML\EarthML.TemplyHeadless\samples\ApplicationInsightsGraphGenerator\wwwroot") }); //}); //appbuilder.Map("/AscendRegistration", (b) => //{ // b.UseStaticFiles(new StaticFileOptions { FileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider(@"C:\dev\Ascend\AscendRecording\AscendRecording\www\libs\AscendRegistration") }); //}); //appbuilder.Map("/node_modules/earthml-temply-headless/artifacts/src", (b) => //{ // b.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider("C:/dev/EarthML/EarthML.TemplyHeadless/src/EarthML.TemplyHeadless/artifacts/src") }); //}); appbuilder.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider(HostFolder) }); }) .Build(); await host.StartAsync();; if (HelloWorld) { Url = host.ServerFeatures.Get <IServerAddressesFeature>().Addresses .Select(a => a.Replace("://+", "://localhost").Replace("[::]", "127.0.0.1")).FirstOrDefault() + "/hello-world"; } if (!string.IsNullOrEmpty(RemotePageLocation)) { Url = host.ServerFeatures.Get <IServerAddressesFeature>().Addresses .Select(a => a.Replace("://+", "://localhost").Replace("[::]", "127.0.0.1")).FirstOrDefault() + $"?remote-main={RemotePageMain}&remote-location={WebUtility.UrlEncode(RemotePageLocation)}"; } { var services = new ServiceCollection(); services.AddNodeServices(a => { // a.ProjectPath = Directory.GetCurrentDirectory(); // Set any properties that you want on 'options' here }); var serviceProvider = services.BuildServiceProvider(); var options = new NodeServicesOptions(serviceProvider) { ProjectPath = HostFolder, InvocationTimeoutMilliseconds = 60000 * 10, WatchFileExtensions = new string[] { } }; var _nodeServices = NodeServicesFactory.CreateNodeServices(options); try { var data = await RequireJS.RunAsync <object, JToken>(_nodeServices, HostFolder, "earthml-temply-headless/Headless/headless", new { url = Url, headlessHost = host.ServerFeatures.Get <IServerAddressesFeature>().Addresses .Select(a => a.Replace("://+", "://localhost").Replace("[::]", "127.0.0.1")).FirstOrDefault(), headless = true, size = new { width = Width, height = Height }, data = args, inputPrefix = InputFolder, outputPrefix = OutputFolder }); Console.WriteLine(data.ToString()); }catch (Exception ex) { Console.WriteLine(ex); await Task.Delay(60000); } } if (host != null) { await host.StopAsync(); } return(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)); } }
public HandlerFactory() : this(AssemblyBuilder.Default.Value, NodeServicesFactory.CreateNodeServices(DefaultNodeServicesOptions())) { }
public HandlerFactory() : this( new DefaultAssemblyBuilder(new DefaultAssemblyLoadContextProvider(), new IMetadataReferenceResolver[] { new DefaultMetadataReferenceResolver() }), NodeServicesFactory.CreateNodeServices(DefaultNodeServicesOptions())) { }