Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions src/Aspire.Hosting.NodeJs/NodeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -475,11 +475,29 @@ public static IResourceBuilder<TResource> WithYarn<TResource>(this IResourceBuil
return resource;
}

private static string[] GetDefaultYarnInstallArgs(IResourceBuilder<JavaScriptAppResource> resource) =>
resource.ApplicationBuilder.ExecutionContext.IsPublishMode &&
File.Exists(Path.Combine(resource.Resource.WorkingDirectory, "yarn.lock"))
? ["--immutable"]
: [];
private static string[] GetDefaultYarnInstallArgs(IResourceBuilder<JavaScriptAppResource> resource)
{
var workingDirectory = resource.Resource.WorkingDirectory;
if (!resource.ApplicationBuilder.ExecutionContext.IsPublishMode ||
!File.Exists(Path.Combine(workingDirectory, "yarn.lock")))
{
// Not publish mode or no yarn.lock, use default install args
return [];
}

var yarnRcYml = Path.Combine(workingDirectory, ".yarnrc.yml");
var yarnBerryReleaseDir = Path.Combine(workingDirectory, ".yarn", "releases");
var hasYarnBerry = File.Exists(yarnRcYml) || Directory.Exists(yarnBerryReleaseDir);

if (hasYarnBerry)
{
// Yarn 2+ detected
return ["--immutable"];
}

// Fallback: default to Yarn v1.x behavior
return ["--frozen-lockfile"];
}

/// <summary>
/// Configures the Node.js resource to use pnmp as the package manager and optionally installs packages before the application starts.
Expand Down
34 changes: 33 additions & 1 deletion tests/Aspire.Hosting.NodeJs.Tests/PackageInstallationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ public void WithYarn_DefaultsArgsInPublishMode()
.WithYarn();

Assert.True(app.Resource.TryGetLastAnnotation<JavaScriptInstallCommandAnnotation>(out var installCommand));
Assert.Equal(["install", "--immutable"], installCommand.Args);
Assert.Equal(["install", "--frozen-lockfile"], installCommand.Args);

var app2 = builder.AddViteApp("test-app2", tempDir.Path)
.WithYarn(installArgs: ["--immutable-cache"]);
Expand All @@ -485,6 +485,38 @@ public void WithYarn_DefaultsArgsInPublishMode()
Assert.Equal(["install", "--immutable-cache"], installCommand.Args);
}

[Fact]
public void WithYarn_ReturnsImmutable_WhenYarnRcYmlExists()
{
using var tempDir = new TempDirectory();
File.WriteAllText(Path.Combine(tempDir.Path, "yarn.lock"), "empty");
File.WriteAllText(Path.Combine(tempDir.Path, ".yarnrc.yml"), "empty"); // .yarnrc.yml present

using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish);

var app = builder.AddViteApp("test-app", tempDir.Path)
.WithYarn();

Assert.True(app.Resource.TryGetLastAnnotation<JavaScriptInstallCommandAnnotation>(out var installCommand));
Assert.Equal(["install", "--immutable"], installCommand.Args);
}

[Fact]
public void WithYarn_ReturnsImmutable_WhenYarnReleasesDirExists()
{
using var tempDir = new TempDirectory();
File.WriteAllText(Path.Combine(tempDir.Path, "yarn.lock"), "empty");
Directory.CreateDirectory(Path.Combine(tempDir.Path, ".yarn", "releases"));

using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish);

var app = builder.AddViteApp("test-app", tempDir.Path)
.WithYarn();

Assert.True(app.Resource.TryGetLastAnnotation<JavaScriptInstallCommandAnnotation>(out var installCommand));
Assert.Equal(["install", "--immutable"], installCommand.Args);
}

[Fact]
public void WithPnpm_DefaultsArgsInPublishMode()
{
Expand Down
Loading