Skip to content

Commit 263edc3

Browse files
Copilotaaronpowell
andcommitted
Add args parameter to package installation methods
Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>
1 parent d5f193b commit 263edc3

File tree

2 files changed

+108
-6
lines changed

2 files changed

+108
-6
lines changed

src/CommunityToolkit.Aspire.Hosting.NodeJS.Extensions/NodeJSHostingExtensions.cs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,17 +110,24 @@ public static IResourceBuilder<NodeAppResource> AddPnpmApp(this IDistributedAppl
110110
/// </summary>
111111
/// <param name="resource">The Node.js app resource.</param>
112112
/// <param name="useCI">When true use <code>npm ci</code> otherwise use <code>npm install</code> when installing packages.</param>
113+
/// <param name="args">Additional arguments to pass to the npm command.</param>
113114
/// <returns>A reference to the <see cref="IResourceBuilder{T}"/>.</returns>
114-
public static IResourceBuilder<NodeAppResource> WithNpmPackageInstallation(this IResourceBuilder<NodeAppResource> resource, bool useCI = false)
115+
public static IResourceBuilder<NodeAppResource> WithNpmPackageInstallation(this IResourceBuilder<NodeAppResource> resource, bool useCI = false, string[]? args = null)
115116
{
116117
// Only install packages during development, not in publish mode
117118
if (!resource.ApplicationBuilder.ExecutionContext.IsPublishMode)
118119
{
119120
var installerName = $"{resource.Resource.Name}-npm-install";
120121
var installer = new NpmInstallerResource(installerName, resource.Resource.WorkingDirectory);
121122

123+
var baseArgs = new List<string> { useCI ? "ci" : "install" };
124+
if (args != null)
125+
{
126+
baseArgs.AddRange(args);
127+
}
128+
122129
var installerBuilder = resource.ApplicationBuilder.AddResource(installer)
123-
.WithArgs([useCI ? "ci" : "install"])
130+
.WithArgs(baseArgs.ToArray())
124131
.WithParentRelationship(resource.Resource)
125132
.ExcludeFromManifest();
126133

@@ -135,17 +142,24 @@ public static IResourceBuilder<NodeAppResource> WithNpmPackageInstallation(this
135142
/// Ensures the Node.js packages are installed before the application starts using yarn as the package manager.
136143
/// </summary>
137144
/// <param name="resource">The Node.js app resource.</param>
145+
/// <param name="args">Additional arguments to pass to the yarn command.</param>
138146
/// <returns>A reference to the <see cref="IResourceBuilder{T}"/>.</returns>
139-
public static IResourceBuilder<NodeAppResource> WithYarnPackageInstallation(this IResourceBuilder<NodeAppResource> resource)
147+
public static IResourceBuilder<NodeAppResource> WithYarnPackageInstallation(this IResourceBuilder<NodeAppResource> resource, string[]? args = null)
140148
{
141149
// Only install packages during development, not in publish mode
142150
if (!resource.ApplicationBuilder.ExecutionContext.IsPublishMode)
143151
{
144152
var installerName = $"{resource.Resource.Name}-yarn-install";
145153
var installer = new YarnInstallerResource(installerName, resource.Resource.WorkingDirectory);
146154

155+
var baseArgs = new List<string> { "install" };
156+
if (args != null)
157+
{
158+
baseArgs.AddRange(args);
159+
}
160+
147161
var installerBuilder = resource.ApplicationBuilder.AddResource(installer)
148-
.WithArgs(["install"])
162+
.WithArgs(baseArgs.ToArray())
149163
.WithParentRelationship(resource.Resource)
150164
.ExcludeFromManifest();
151165

@@ -160,17 +174,24 @@ public static IResourceBuilder<NodeAppResource> WithYarnPackageInstallation(this
160174
/// Ensures the Node.js packages are installed before the application starts using pnpm as the package manager.
161175
/// </summary>
162176
/// <param name="resource">The Node.js app resource.</param>
177+
/// <param name="args">Additional arguments to pass to the pnpm command.</param>
163178
/// <returns>A reference to the <see cref="IResourceBuilder{T}"/>.</returns>
164-
public static IResourceBuilder<NodeAppResource> WithPnpmPackageInstallation(this IResourceBuilder<NodeAppResource> resource)
179+
public static IResourceBuilder<NodeAppResource> WithPnpmPackageInstallation(this IResourceBuilder<NodeAppResource> resource, string[]? args = null)
165180
{
166181
// Only install packages during development, not in publish mode
167182
if (!resource.ApplicationBuilder.ExecutionContext.IsPublishMode)
168183
{
169184
var installerName = $"{resource.Resource.Name}-pnpm-install";
170185
var installer = new PnpmInstallerResource(installerName, resource.Resource.WorkingDirectory);
171186

187+
var baseArgs = new List<string> { "install" };
188+
if (args != null)
189+
{
190+
baseArgs.AddRange(args);
191+
}
192+
172193
var installerBuilder = resource.ApplicationBuilder.AddResource(installer)
173-
.WithArgs(["install"])
194+
.WithArgs(baseArgs.ToArray())
174195
.WithParentRelationship(resource.Resource)
175196
.ExcludeFromManifest();
176197

tests/CommunityToolkit.Aspire.Hosting.NodeJS.Extensions.Tests/PackageInstallationTests.cs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,85 @@ public void WithNpmPackageInstallation_ExcludedFromPublishMode()
7070
// Verify no wait annotations were added
7171
Assert.False(nodeResource.TryGetAnnotationsOfType<WaitAnnotation>(out _));
7272
}
73+
74+
[Fact]
75+
public async Task WithNpmPackageInstallation_CanAcceptAdditionalArgs()
76+
{
77+
var builder = DistributedApplication.CreateBuilder();
78+
79+
var nodeApp = builder.AddNpmApp("test-app", "./test-app");
80+
var nodeAppWithArgs = builder.AddNpmApp("test-app-args", "./test-app-args");
81+
82+
// Test npm install with additional args
83+
nodeApp.WithNpmPackageInstallation(useCI: false, args: ["--legacy-peer-deps"]);
84+
nodeAppWithArgs.WithNpmPackageInstallation(useCI: true, args: ["--verbose", "--no-optional"]);
85+
86+
using var app = builder.Build();
87+
88+
var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();
89+
var installerResources = appModel.Resources.OfType<NpmInstallerResource>().ToList();
90+
91+
Assert.Equal(2, installerResources.Count);
92+
93+
var installResource = installerResources.Single(r => r.Name == "test-app-npm-install");
94+
var ciResource = installerResources.Single(r => r.Name == "test-app-args-npm-install");
95+
96+
// Verify install command with additional args
97+
var installArgs = await installResource.GetArgumentValuesAsync();
98+
Assert.Equal(2, installArgs.Count);
99+
Assert.Equal("install", installArgs[0]);
100+
Assert.Equal("--legacy-peer-deps", installArgs[1]);
101+
102+
// Verify ci command with additional args
103+
var ciArgs = await ciResource.GetArgumentValuesAsync();
104+
Assert.Equal(3, ciArgs.Count);
105+
Assert.Equal("ci", ciArgs[0]);
106+
Assert.Equal("--verbose", ciArgs[1]);
107+
Assert.Equal("--no-optional", ciArgs[2]);
108+
}
109+
110+
[Fact]
111+
public async Task WithYarnPackageInstallation_CanAcceptAdditionalArgs()
112+
{
113+
var builder = DistributedApplication.CreateBuilder();
114+
115+
var nodeApp = builder.AddYarnApp("test-yarn-app", "./test-yarn-app");
116+
nodeApp.WithYarnPackageInstallation(args: ["--frozen-lockfile", "--verbose"]);
117+
118+
using var app = builder.Build();
119+
120+
var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();
121+
var installerResources = appModel.Resources.OfType<YarnInstallerResource>().ToList();
122+
123+
var installerResource = Assert.Single(installerResources);
124+
Assert.Equal("test-yarn-app-yarn-install", installerResource.Name);
125+
126+
var args = await installerResource.GetArgumentValuesAsync();
127+
Assert.Equal(3, args.Count);
128+
Assert.Equal("install", args[0]);
129+
Assert.Equal("--frozen-lockfile", args[1]);
130+
Assert.Equal("--verbose", args[2]);
131+
}
132+
133+
[Fact]
134+
public async Task WithPnpmPackageInstallation_CanAcceptAdditionalArgs()
135+
{
136+
var builder = DistributedApplication.CreateBuilder();
137+
138+
var nodeApp = builder.AddPnpmApp("test-pnpm-app", "./test-pnpm-app");
139+
nodeApp.WithPnpmPackageInstallation(args: ["--frozen-lockfile"]);
140+
141+
using var app = builder.Build();
142+
143+
var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();
144+
var installerResources = appModel.Resources.OfType<PnpmInstallerResource>().ToList();
145+
146+
var installerResource = Assert.Single(installerResources);
147+
Assert.Equal("test-pnpm-app-pnpm-install", installerResource.Name);
148+
149+
var args = await installerResource.GetArgumentValuesAsync();
150+
Assert.Equal(2, args.Count);
151+
Assert.Equal("install", args[0]);
152+
Assert.Equal("--frozen-lockfile", args[1]);
153+
}
73154
}

0 commit comments

Comments
 (0)