diff --git a/README.md b/README.md
index e789a8d..03064fd 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,21 @@
# AspSpaService
-
-
+
+
+
+
+
+
+
The Asp Net Core plugin for integrating SPA application with Asp Net Core.
This plugin can be used with any web framework in same manner.
# Usage
+Install package via nugget
+```
+dotnet add package AspSpaService
+```
+
Change your Startup.cs configuration file as follows:
```cs
using AspSpaService;
@@ -25,13 +35,43 @@ using AspSpaService;
var p = Path.Combine(wd,"samples", "hello-vue"); // path to your vuejs project
app.UseSpa(
spa => {
- spa.UseAspSpaDevelopmentServer("yarn", "serve", p, new Dictionary(), TimeSpan.FromSeconds(15), null);
+ spa.UseAspSpaDevelopmentServer(
+ // command for nodejs process
+ // string
+ "yarn",
+ // argument for nodejs process
+ // string
+ "serve",
+ // working directory
+ // string
+ p,
+ // environment variables
+ new Dictionary(),
+ // timeout for waiting node js process is ready to use
+ TimeSpan.FromSeconds(15),
+ // message when timeout has been exceeded
+ // has defaul value = "Timeout has been exceeded" (can be ommited!)
+ // string
+ "Timeout has been exceeded",
+ //logInformation for node js process
+ // bool (true by default)
+ true,
+ //logError for node js process
+ // some bundler emits many error strings during compilation
+ // bool (false by default)
+ false,
+ //unsubscribeWhenReady
+ // stop logging nodejs output when it ready to use
+ // bool (true by default)
+ true
+ );
}
);
}
}
```
+This library starts NodeJS process, and waiting for it emits line with served valid Uri
## Sample configuratons
In folder sample/webapi has the web empty project that shows, how to use your favorite web framework with asp.
@@ -46,7 +86,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
var p = Path.Combine(wd,"samples", "hello-vue"); // path to your vuejs project
app.UseSpa(
spa => {
- spa.UseAspSpaDevelopmentServer("yarn", "serve", p, new Dictionary(), TimeSpan.FromSeconds(15), null);
+ spa.UseAspSpaDevelopmentServer("yarn", "serve", p, new Dictionary(), TimeSpan.FromSeconds(15), "Timeout has been exceeded");
}
);
}
@@ -62,7 +102,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
var p = Path.Combine(wd,"samples", "hello-vite"); // path to your vitejs project
app.UseSpa(
spa => {
- spa.UseAspSpaDevelopmentServer("yarn", "dev", p, new Dictionary(), TimeSpan.FromSeconds(15), null);
+ spa.UseAspSpaDevelopmentServer("yarn", "dev", p, new Dictionary(), TimeSpan.FromSeconds(15), "Timeout has been exceeded");
}
);
}
@@ -78,7 +118,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
var p = Path.Combine(wd,"samples", "hello-nuxt"); // path to your nuxt project
app.UseSpa(
spa => {
- spa.UseAspSpaDevelopmentServer("yarn", "dev", p, new Dictionary(), TimeSpan.FromSeconds(15), null);
+ spa.UseAspSpaDevelopmentServer("yarn", "dev", p, new Dictionary(), TimeSpan.FromSeconds(15), "Timeout has been exceeded");
}
);
}
@@ -94,7 +134,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
var p = Path.Combine(wd,"samples", "hello-react"); // path to your react project
app.UseSpa(
spa => {
- spa.UseAspSpaDevelopmentServer("yarn", "start", p, new Dictionary(), TimeSpan.FromSeconds(15), null);
+ spa.UseAspSpaDevelopmentServer("yarn", "start", p, new Dictionary(), TimeSpan.FromSeconds(15), "Timeout has been exceeded");
}
);
}
@@ -111,7 +151,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
var p = Path.Combine(wd,"samples", "hello-svelte"); // path to your svelte project
app.UseSpa(
spa => {
- spa.UseAspSpaDevelopmentServer("yarn", "dev", p, new Dictionary(), TimeSpan.FromSeconds(15), null);
+ spa.UseAspSpaDevelopmentServer("yarn", "dev", p, new Dictionary(), TimeSpan.FromSeconds(15), "Timeout has been exceeded");
}
);
}
diff --git a/samples/webapi/Startup.cs b/samples/webapi/Startup.cs
index 9caf47f..4ef5c7f 100644
--- a/samples/webapi/Startup.cs
+++ b/samples/webapi/Startup.cs
@@ -33,7 +33,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
// var p = Path.Combine(wd,"samples", "hello-vue");
// app.UseSpa(
// spa => {
- // spa.UseAspSpaDevelopmentServer("yarn", "serve", p, new Dictionary(), TimeSpan.FromSeconds(15), null);
+ // spa.UseAspSpaDevelopmentServer("yarn", "serve", p, new Dictionary(), TimeSpan.FromSeconds(10), "Timeout has been exceeded");
// }
// );
// // this block starts vite spa application
@@ -47,7 +47,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
var p = Path.Combine(wd,"samples", "hello-nuxt");
app.UseSpa(
spa => {
- spa.UseAspSpaDevelopmentServer("yarn", "dev", p, new Dictionary(), TimeSpan.FromSeconds(15), null);
+ spa.UseAspSpaDevelopmentServer("yarn", "dev", p, new Dictionary(), TimeSpan.FromSeconds(10), null);
}
);
// this block starts react spa application
diff --git a/src/AspSpaService/AspSpaService.csproj b/src/AspSpaService/AspSpaService.csproj
index 5d9a454..aeca00c 100644
--- a/src/AspSpaService/AspSpaService.csproj
+++ b/src/AspSpaService/AspSpaService.csproj
@@ -3,7 +3,7 @@
netcoreapp3.1
AspSpaService
- 1.0.1
+ 1.0.2
Aleksandr Kolesnikov
true
AspSpaService
@@ -12,7 +12,9 @@
MIT
git
https://github.com/kolesnikovav/AspSpaService.git
+ The Asp Net Core plugin for integrating SPA application with Asp Net Core project
The Asp Net Core plugin for integrating SPA application with Asp Net Core. This plugin can be used with any web framework in same manner.
+ ASP;Asp Net Core; SPA; vue; vite; nuxt; react; svelte
diff --git a/src/AspSpaService/AspSpaServiceMiddlewareExtentions.cs b/src/AspSpaService/AspSpaServiceMiddlewareExtentions.cs
index cf0b92a..51a7ae8 100644
--- a/src/AspSpaService/AspSpaServiceMiddlewareExtentions.cs
+++ b/src/AspSpaService/AspSpaServiceMiddlewareExtentions.cs
@@ -40,6 +40,9 @@ private static NodeRunner GetNodeRunner(IApplicationBuilder builder)
/// Environment variables for node dev server
/// Timeout for node process waiting
/// Message when timeout is exceeded
+ /// Log node process output
+ /// Log node js process error
+ /// Stop logging when nodejs process is ready
public static void UseAspSpaDevelopmentServer(
this ISpaBuilder spaBuilder,
string command,
@@ -47,7 +50,10 @@ public static void UseAspSpaDevelopmentServer(
string workingDirectory,
Dictionary envVars,
TimeSpan timeout,
- string timeoutExceedMessage)
+ string timeoutExceedMessage = "Timeout has been exceeded ",
+ bool logInformation = true,
+ bool logError = false,
+ bool unsubscribeWhenReady = true)
{
if (spaBuilder == null)
{
@@ -64,11 +70,20 @@ public static void UseAspSpaDevelopmentServer(
runner.WorkingDirectory = workingDirectory;
runner.EnvVars = envVars;
runner.Timeout = timeout;
+ runner.TimeoutExceedMessage = timeoutExceedMessage;
runner.Launch(logger);
if (runner.Uri != null)
{
+ if (unsubscribeWhenReady)
+ {
+ runner.UnsubscribeLog(logger);
+ }
spaBuilder.UseProxyToSpaDevelopmentServer(runner.Uri);
}
+ else
+ {
+
+ }
}
private static ILogger GetOrCreateLogger(
IApplicationBuilder appBuilder,
diff --git a/src/AspSpaService/NodeRunner.cs b/src/AspSpaService/NodeRunner.cs
index 56d2c98..0bf6d90 100644
--- a/src/AspSpaService/NodeRunner.cs
+++ b/src/AspSpaService/NodeRunner.cs
@@ -43,9 +43,17 @@ public class NodeRunner: IDisposable
/// Environment variables for node process
///
public Dictionary EnvVars {get;set;} = new Dictionary();
- ///
- /// Indicates where node process is being served
- ///
+ ///
+ /// Log Node JS Process messages
+ ///
+ public bool LogResult { get; set; } = true;
+ ///
+ /// Log Node JS Process error messages
+ ///
+ public bool LogError { get; set; } = false;
+ ///
+ /// Indicates where node process is being served
+ ///
public Uri Uri {
get => this._uri;
}
@@ -91,13 +99,49 @@ public void Launch(ILogger logger)
this._nodeProcess = Process.Start(p);
this.streamOutputReader = new NodeStreamReader(this._nodeProcess.StandardOutput);
this.streamErrorReader = new NodeStreamReader(this._nodeProcess.StandardError);
- if (logger != null)
+ this.streamOutputReader.OnReceivedLine += this.onResiveLineResult;
+ if (LogError)
{
- this.AttachToLogger(logger);
+ this.streamErrorReader.OnReceivedLine += this.onResiveLineResult;
}
- this.streamOutputReader.OnReceivedLine += this.onResiveLineResult;
- this.streamErrorReader.OnReceivedLine += this.onResiveLineResult;
+ this._nodeProcess.Exited += (a, b) =>
+ {
+ if (logger != null)
+ {
+ logger.LogError("Node JS Process has been exited with code " + this._nodeProcess.ExitCode.ToString());
+ }
+ };
+ var cStart = DateTime.Now;
this._awaiter.WaitOne(this.Timeout);
+ var cExit = DateTime.Now;
+ bool timeoutHasBeenExceeded = (this.Timeout == null) ? false : TimeSpan.Compare(cExit - cStart, this.Timeout) > 0;
+ if (this.Uri == null)
+ {
+ //unsubscribe events
+ this.streamOutputReader.OnReceivedLine -= this.onResiveLineResult;
+ if (LogError)
+ {
+ this.streamOutputReader.OnReceivedLine -= this.onResiveLineResult;
+ }
+ if (this._nodeProcess != null)
+ {
+ logger.LogError("Disposing Node JS Process");
+ if (this._nodeProcess != null && !this._nodeProcess.HasExited)
+ {
+ this._nodeProcess.Kill(true);
+ this._nodeProcess = null;
+ }
+ this._uri = null;
+ logger.LogError("Disposing Node JS Process has been disposed");
+ }
+ if (logger != null)
+ {
+ if (timeoutHasBeenExceeded)
+ {
+ logger.LogError(this.TimeoutExceedMessage + this.Timeout.ToString());
+ }
+ }
+ }
}
catch(Exception ex)
{
@@ -105,29 +149,23 @@ public void Launch(ILogger logger)
throw new InvalidOperationException(message, ex);
}
}
- ///
- /// Attach to logger.
- ///
- /// The logger to attach
- private void AttachToLogger(ILogger logger)
+ ///
+ /// Stop logging node process output
+ ///
+ public void UnsubscribeLog(ILogger logger)
{
- // When the node task emits complete lines, pass them through to the real logger
- this.streamOutputReader.OnReceivedLine += line =>
- {
- logger.LogInformation(line);
- };
-
- this.streamErrorReader.OnReceivedLine += line =>
+ this.streamOutputReader.OnReceivedLine += this.onResiveLineResult;
+ if (LogError)
{
- logger.LogError(line);
- };
+ this.streamErrorReader.OnReceivedLine += this.onResiveLineResult;
+ }
}
///
/// Stop node process and disposes resources
///
public void Dispose()
{
- if (_nodeProcess != null && !_nodeProcess.HasExited)
+ if (this._nodeProcess != null && !this._nodeProcess.HasExited)
{
this._nodeProcess.Kill(true);
this._nodeProcess = null;