diff --git a/src/Aspire.Hosting.NodeJs/NodeAppResource.cs b/src/Aspire.Hosting.NodeJs/NodeAppResource.cs
index 6bb55c880d6..381d54a6200 100644
--- a/src/Aspire.Hosting.NodeJs/NodeAppResource.cs
+++ b/src/Aspire.Hosting.NodeJs/NodeAppResource.cs
@@ -1,5 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
using Aspire.Hosting.ApplicationModel;
namespace Aspire.Hosting;
@@ -11,7 +13,8 @@ namespace Aspire.Hosting;
/// The command to execute.
/// The working directory to use for the command. If null, the working directory of the current process is used.
public class NodeAppResource(string name, string command, string workingDirectory)
- : ExecutableResource(name, command, workingDirectory), IResourceWithServiceDiscovery
+ : ExecutableResource(ThrowIfNull(name), ThrowIfNull(command), ThrowIfNull(workingDirectory)), IResourceWithServiceDiscovery
{
-
+ private static string ThrowIfNull([NotNull] string? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null)
+ => argument ?? throw new ArgumentNullException(paramName);
}
diff --git a/src/Aspire.Hosting.NodeJs/NodeExtensions.cs b/src/Aspire.Hosting.NodeJs/NodeExtensions.cs
index e0dba211468..dcae1462ca4 100644
--- a/src/Aspire.Hosting.NodeJs/NodeExtensions.cs
+++ b/src/Aspire.Hosting.NodeJs/NodeExtensions.cs
@@ -22,6 +22,10 @@ public static class NodeAppHostingExtension
/// A reference to the .
public static IResourceBuilder AddNodeApp(this IDistributedApplicationBuilder builder, string name, string scriptPath, string? workingDirectory = null, string[]? args = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentNullException.ThrowIfNull(name);
+ ArgumentNullException.ThrowIfNull(scriptPath);
+
args ??= [];
string[] effectiveArgs = [scriptPath, .. args];
workingDirectory ??= Path.GetDirectoryName(scriptPath)!;
@@ -45,6 +49,12 @@ public static IResourceBuilder AddNodeApp(this IDistributedAppl
/// A reference to the .
public static IResourceBuilder AddNpmApp(this IDistributedApplicationBuilder builder, string name, string workingDirectory, string scriptName = "start", string[]? args = null)
{
+
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentNullException.ThrowIfNull(name);
+ ArgumentNullException.ThrowIfNull(workingDirectory);
+ ArgumentNullException.ThrowIfNull(scriptName);
+
string[] allArgs = args is { Length: > 0 }
? ["run", scriptName, "--", .. args]
: ["run", scriptName];
diff --git a/tests/Aspire.Hosting.NodeJs.Tests/NodeJsPublicApiTests.cs b/tests/Aspire.Hosting.NodeJs.Tests/NodeJsPublicApiTests.cs
new file mode 100644
index 00000000000..d0276726df4
--- /dev/null
+++ b/tests/Aspire.Hosting.NodeJs.Tests/NodeJsPublicApiTests.cs
@@ -0,0 +1,140 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Xunit;
+
+namespace Aspire.Hosting.NodeJs.Tests;
+
+public class NodeJsPublicApiTests
+{
+ [Fact]
+ public void AddNodeAppShouldThrowWhenBuilderIsNull()
+ {
+ IDistributedApplicationBuilder builder = null!;
+ var name = "nodeapp";
+ var scriptPath = ".\\app.js";
+
+ var action = () => builder.AddNodeApp(name: name, scriptPath: scriptPath);
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddNodeAppShouldThrowWhenNameIsNull()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+ string name = null!;
+ var scriptPath = ".\\app.js";
+
+ var action = () => builder.AddNodeApp(name: name, scriptPath: scriptPath);
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(name), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddNodeAppShouldThrowWhenScriptPathIsNull()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+ var name = "nodeapp";
+ string scriptPath = null!;
+
+ var action = () => builder.AddNodeApp(name: name, scriptPath: scriptPath);
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(scriptPath), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddNpmAppShouldThrowWhenBuilderIsNull()
+ {
+ IDistributedApplicationBuilder builder = null!;
+ var name = "npmapp";
+ var workingDirectory = ".\\app";
+
+ var action = () => builder.AddNpmApp(name: name, workingDirectory: workingDirectory);
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddNpmAppShouldThrowWhenWorkingDirectoryIsNull()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+ var name = "npmapp";
+ string workingDirectory = null!;
+
+ var action = () => builder.AddNpmApp(name: name, workingDirectory: workingDirectory);
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(workingDirectory), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddNpmAppShouldThrowWhenNameIsNull()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+ string name = null!;
+ var workingDirectory = ".\\app";
+
+ var action = () => builder.AddNpmApp(name: name, workingDirectory: workingDirectory);
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(name), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddNpmAppShouldThrowWhenScriptNameIsNull()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+ var name = "npmapp";
+ var workingDirectory = ".\\app";
+ string scriptName = null!;
+
+ var action = () => builder.AddNpmApp(name: name, workingDirectory: workingDirectory, scriptName: scriptName);
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(scriptName), exception.ParamName);
+ }
+
+ [Fact]
+ public void CtorNodeAppResourceShouldThrowWhenNameIsNull()
+ {
+ string name = null!;
+ var command = "start";
+ var workingDirectory = ".\\app";
+
+ var action = () => new NodeAppResource(name, command, workingDirectory);
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(name), exception.ParamName);
+ }
+
+ [Fact]
+ public void CtorNodeAppResourceShouldThrowWhenCommandIsNull()
+ {
+ var name = "nodeapp";
+ string command = null!;
+ var workingDirectory = ".\\app";
+
+ var action = () => new NodeAppResource(name, command, workingDirectory);
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(command), exception.ParamName);
+ }
+
+ [Fact]
+ public void CtorNodeAppResourceShouldThrowWhenWorkingDirectoryIsNull()
+ {
+ var name = "nodeapp";
+ var command = "start";
+ string workingDirectory = null!;
+
+ var action = () => new NodeAppResource(name, command, workingDirectory);
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(workingDirectory), exception.ParamName);
+ }
+}