|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Aspire.Hosting.ApplicationModel;
using Aspire.Hosting.Utils;
using Microsoft.Extensions.Hosting;
namespace Aspire.Hosting;
/// <summary>
/// Provides extension methods for adding Node applications to an <see cref="IDistributedApplicationBuilder"/>.
/// </summary>
public static class NodeAppHostingExtension
{
/// <summary>
/// Adds a node application to the application model. Node should available on the PATH.
/// </summary>
/// <param name="builder">The <see cref="IDistributedApplicationBuilder"/> to add the resource to.</param>
/// <param name="name">The name of the resource.</param>
/// <param name="scriptPath">The path to the script that Node will execute.</param>
/// <param name="workingDirectory">The working directory to use for the command. If null, the working directory of the current process is used.</param>
/// <param name="args">The arguments to pass to the command.</param>
/// <returns>A reference to the <see cref="IResourceBuilder{T}"/>.</returns>
public static IResourceBuilder<NodeAppResource> AddNodeApp(this IDistributedApplicationBuilder builder, [ResourceName] 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)!;
workingDirectory = PathNormalizer.NormalizePathForCurrentPlatform(Path.Combine(builder.AppHostDirectory, workingDirectory));
var resource = new NodeAppResource(name, "node", workingDirectory);
return builder.AddResource(resource)
.WithNodeDefaults()
.WithArgs(effectiveArgs);
}
/// <summary>
/// Adds a node application to the application model. Executes the npm command with the specified script name.
/// </summary>
/// <param name="builder">The <see cref="IDistributedApplicationBuilder"/> to add the resource to.</param>
/// <param name="name">The name of the resource.</param>
/// <param name="workingDirectory">The working directory to use for the command. If null, the working directory of the current process is used.</param>
/// <param name="scriptName">The npm script to execute. Defaults to "start".</param>
/// <param name="args">The arguments to pass to the command.</param>
/// <returns>A reference to the <see cref="IResourceBuilder{T}"/>.</returns>
public static IResourceBuilder<NodeAppResource> AddNpmApp(this IDistributedApplicationBuilder builder, [ResourceName] 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];
workingDirectory = PathNormalizer.NormalizePathForCurrentPlatform(Path.Combine(builder.AppHostDirectory, workingDirectory));
var resource = new NodeAppResource(name, "npm", workingDirectory);
return builder.AddResource(resource)
.WithNodeDefaults()
.WithArgs(allArgs);
}
private static IResourceBuilder<NodeAppResource> WithNodeDefaults(this IResourceBuilder<NodeAppResource> builder) =>
builder.WithOtlpExporter()
.WithEnvironment("NODE_ENV", builder.ApplicationBuilder.Environment.IsDevelopment() ? "development" : "production");
}
|