From b782c86eb6242b71240e8d1df72aab374d73e34a Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sat, 28 Mar 2026 09:03:47 -0700 Subject: [PATCH 1/4] Deprecate Aspire.Hosting.NodeJs in CLI integration list Add Aspire.Hosting.NodeJs to the deprecated packages filter in both BundleNuGetPackageCache and NuGetPackageCache so it no longer appears in 'aspire add' integration listings. The replacement package is Aspire.Hosting.JavaScript. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/Aspire.Cli/NuGet/BundleNuGetPackageCache.cs | 3 ++- src/Aspire.Cli/NuGet/NuGetPackageCache.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Aspire.Cli/NuGet/BundleNuGetPackageCache.cs b/src/Aspire.Cli/NuGet/BundleNuGetPackageCache.cs index 7b21897deed..b06994fe212 100644 --- a/src/Aspire.Cli/NuGet/BundleNuGetPackageCache.cs +++ b/src/Aspire.Cli/NuGet/BundleNuGetPackageCache.cs @@ -24,7 +24,8 @@ internal sealed class BundleNuGetPackageCache : INuGetPackageCache // List of deprecated packages that should be filtered by default private static readonly HashSet s_deprecatedPackages = new(StringComparer.OrdinalIgnoreCase) { - "Aspire.Hosting.Dapr" + "Aspire.Hosting.Dapr", + "Aspire.Hosting.NodeJs" }; public BundleNuGetPackageCache( diff --git a/src/Aspire.Cli/NuGet/NuGetPackageCache.cs b/src/Aspire.Cli/NuGet/NuGetPackageCache.cs index 3ca8347e88d..9f17c6fdd83 100644 --- a/src/Aspire.Cli/NuGet/NuGetPackageCache.cs +++ b/src/Aspire.Cli/NuGet/NuGetPackageCache.cs @@ -26,7 +26,8 @@ internal sealed class NuGetPackageCache(IDotNetCliRunner cliRunner, IMemoryCache // List of deprecated packages that should be filtered by default private static readonly HashSet s_deprecatedPackages = new(StringComparer.OrdinalIgnoreCase) { - "Aspire.Hosting.Dapr" + "Aspire.Hosting.Dapr", + "Aspire.Hosting.NodeJs" }; public async Task> GetTemplatePackagesAsync(DirectoryInfo workingDirectory, bool prerelease, FileInfo? nugetConfigFile, CancellationToken cancellationToken) From a371480f69720a7f6ed902f7a8f5c5387b6a9fbf Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sat, 28 Mar 2026 09:08:42 -0700 Subject: [PATCH 2/4] Extract shared DeprecatedPackages static class Remove duplicated s_deprecatedPackages HashSet from both BundleNuGetPackageCache and NuGetPackageCache. Consolidate into a single DeprecatedPackages.All in NuGetPackageCache.cs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/Aspire.Cli/NuGet/BundleNuGetPackageCache.cs | 9 +-------- src/Aspire.Cli/NuGet/NuGetPackageCache.cs | 17 +++++++++++------ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/Aspire.Cli/NuGet/BundleNuGetPackageCache.cs b/src/Aspire.Cli/NuGet/BundleNuGetPackageCache.cs index b06994fe212..768842654e7 100644 --- a/src/Aspire.Cli/NuGet/BundleNuGetPackageCache.cs +++ b/src/Aspire.Cli/NuGet/BundleNuGetPackageCache.cs @@ -21,13 +21,6 @@ internal sealed class BundleNuGetPackageCache : INuGetPackageCache private readonly ILogger _logger; private readonly IFeatures _features; - // List of deprecated packages that should be filtered by default - private static readonly HashSet s_deprecatedPackages = new(StringComparer.OrdinalIgnoreCase) - { - "Aspire.Hosting.Dapr", - "Aspire.Hosting.NodeJs" - }; - public BundleNuGetPackageCache( IBundleService bundleService, ILogger logger, @@ -227,7 +220,7 @@ private IEnumerable FilterPackages(IEnumerable packa // Apply deprecated package filter unless the user wants to show deprecated packages if (isOfficialPackage && !_features.IsFeatureEnabled(KnownFeatures.ShowDeprecatedPackages, defaultValue: false)) { - return !s_deprecatedPackages.Contains(p.Id); + return !DeprecatedPackages.All.Contains(p.Id); } return isOfficialPackage; diff --git a/src/Aspire.Cli/NuGet/NuGetPackageCache.cs b/src/Aspire.Cli/NuGet/NuGetPackageCache.cs index 9f17c6fdd83..3a27b28a669 100644 --- a/src/Aspire.Cli/NuGet/NuGetPackageCache.cs +++ b/src/Aspire.Cli/NuGet/NuGetPackageCache.cs @@ -19,16 +19,21 @@ internal interface INuGetPackageCache Task> GetPackagesAsync(DirectoryInfo workingDirectory, string packageId, Func? filter, bool prerelease, FileInfo? nugetConfigFile, bool useCache, CancellationToken cancellationToken); } -internal sealed class NuGetPackageCache(IDotNetCliRunner cliRunner, IMemoryCache memoryCache, AspireCliTelemetry telemetry, IFeatures features) : INuGetPackageCache +/// +/// Packages that have been superseded and should be hidden from integration listings by default. +/// +internal static class DeprecatedPackages { - private const int SearchPageSize = 1000; - - // List of deprecated packages that should be filtered by default - private static readonly HashSet s_deprecatedPackages = new(StringComparer.OrdinalIgnoreCase) + public static readonly HashSet All = new(StringComparer.OrdinalIgnoreCase) { "Aspire.Hosting.Dapr", "Aspire.Hosting.NodeJs" }; +} + +internal sealed class NuGetPackageCache(IDotNetCliRunner cliRunner, IMemoryCache memoryCache, AspireCliTelemetry telemetry, IFeatures features) : INuGetPackageCache +{ + private const int SearchPageSize = 1000; public async Task> GetTemplatePackagesAsync(DirectoryInfo workingDirectory, bool prerelease, FileInfo? nugetConfigFile, CancellationToken cancellationToken) { @@ -134,7 +139,7 @@ public async Task> GetPackagesAsync(DirectoryInfo work // Apply deprecated package filter unless the user wants to show deprecated packages if (isOfficialPackage && !features.IsFeatureEnabled(KnownFeatures.ShowDeprecatedPackages, defaultValue: false)) { - return !s_deprecatedPackages.Contains(p.Id); + return !DeprecatedPackages.All.Contains(p.Id); } return isOfficialPackage; From 92d6c5628273e7bfb18718cca8d84d3aa9a13d1d Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sat, 28 Mar 2026 09:15:58 -0700 Subject: [PATCH 3/4] Add Aspire.Hosting.NodeJs to deprecation filter tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/Aspire.Cli.Tests/NuGet/NuGetPackageCacheTests.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/Aspire.Cli.Tests/NuGet/NuGetPackageCacheTests.cs b/tests/Aspire.Cli.Tests/NuGet/NuGetPackageCacheTests.cs index 27ef3717480..13f6e902557 100644 --- a/tests/Aspire.Cli.Tests/NuGet/NuGetPackageCacheTests.cs +++ b/tests/Aspire.Cli.Tests/NuGet/NuGetPackageCacheTests.cs @@ -60,6 +60,7 @@ public async Task DeprecatedPackagesAreFilteredByDefault() return (0, [ new NuGetPackage { Id = "Aspire.Hosting.Redis", Version = "9.4.0", Source = "nuget.org" }, new NuGetPackage { Id = "Aspire.Hosting.Dapr", Version = "9.4.0", Source = "nuget.org" }, // Deprecated + new NuGetPackage { Id = "Aspire.Hosting.NodeJs", Version = "9.4.0", Source = "nuget.org" }, // Deprecated new NuGetPackage { Id = "Aspire.Hosting.PostgreSQL", Version = "9.4.0", Source = "nuget.org" } ]); }; @@ -78,6 +79,7 @@ public async Task DeprecatedPackagesAreFilteredByDefault() Assert.Contains("Aspire.Hosting.Redis", packageIds); Assert.Contains("Aspire.Hosting.PostgreSQL", packageIds); Assert.DoesNotContain("Aspire.Hosting.Dapr", packageIds); + Assert.DoesNotContain("Aspire.Hosting.NodeJs", packageIds); } [Fact] @@ -98,6 +100,7 @@ public async Task DeprecatedPackagesAreIncludedWhenShowDeprecatedPackagesEnabled return (0, [ new NuGetPackage { Id = "Aspire.Hosting.Redis", Version = "9.4.0", Source = "nuget.org" }, new NuGetPackage { Id = "Aspire.Hosting.Dapr", Version = "9.4.0", Source = "nuget.org" }, // Deprecated + new NuGetPackage { Id = "Aspire.Hosting.NodeJs", Version = "9.4.0", Source = "nuget.org" }, // Deprecated new NuGetPackage { Id = "Aspire.Hosting.PostgreSQL", Version = "9.4.0", Source = "nuget.org" } ]); }; @@ -116,6 +119,7 @@ public async Task DeprecatedPackagesAreIncludedWhenShowDeprecatedPackagesEnabled Assert.Contains("Aspire.Hosting.Redis", packageIds); Assert.Contains("Aspire.Hosting.PostgreSQL", packageIds); Assert.Contains("Aspire.Hosting.Dapr", packageIds); + Assert.Contains("Aspire.Hosting.NodeJs", packageIds); } [Fact] From efbe226466a14a4ac3bc26c5ee3a3a1a430b30c0 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sat, 28 Mar 2026 09:45:18 -0700 Subject: [PATCH 4/4] Use FrozenSet and IsDeprecated helper for immutability Replace mutable HashSet with FrozenSet and expose via DeprecatedPackages.IsDeprecated() to prevent accidental mutation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/Aspire.Cli/NuGet/BundleNuGetPackageCache.cs | 2 +- src/Aspire.Cli/NuGet/NuGetPackageCache.cs | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Aspire.Cli/NuGet/BundleNuGetPackageCache.cs b/src/Aspire.Cli/NuGet/BundleNuGetPackageCache.cs index 768842654e7..6821eecfb93 100644 --- a/src/Aspire.Cli/NuGet/BundleNuGetPackageCache.cs +++ b/src/Aspire.Cli/NuGet/BundleNuGetPackageCache.cs @@ -220,7 +220,7 @@ private IEnumerable FilterPackages(IEnumerable packa // Apply deprecated package filter unless the user wants to show deprecated packages if (isOfficialPackage && !_features.IsFeatureEnabled(KnownFeatures.ShowDeprecatedPackages, defaultValue: false)) { - return !DeprecatedPackages.All.Contains(p.Id); + return !DeprecatedPackages.IsDeprecated(p.Id); } return isOfficialPackage; diff --git a/src/Aspire.Cli/NuGet/NuGetPackageCache.cs b/src/Aspire.Cli/NuGet/NuGetPackageCache.cs index 3a27b28a669..c6b8ff47ddf 100644 --- a/src/Aspire.Cli/NuGet/NuGetPackageCache.cs +++ b/src/Aspire.Cli/NuGet/NuGetPackageCache.cs @@ -3,6 +3,7 @@ using Aspire.Cli.DotNet; using Aspire.Cli.Resources; +using System.Collections.Frozen; using System.Globalization; using Aspire.Cli.Telemetry; using Microsoft.Extensions.Caching.Memory; @@ -24,11 +25,13 @@ internal interface INuGetPackageCache /// internal static class DeprecatedPackages { - public static readonly HashSet All = new(StringComparer.OrdinalIgnoreCase) + private static readonly FrozenSet s_all = new[] { "Aspire.Hosting.Dapr", "Aspire.Hosting.NodeJs" - }; + }.ToFrozenSet(StringComparer.OrdinalIgnoreCase); + + public static bool IsDeprecated(string packageId) => s_all.Contains(packageId); } internal sealed class NuGetPackageCache(IDotNetCliRunner cliRunner, IMemoryCache memoryCache, AspireCliTelemetry telemetry, IFeatures features) : INuGetPackageCache @@ -139,7 +142,7 @@ public async Task> GetPackagesAsync(DirectoryInfo work // Apply deprecated package filter unless the user wants to show deprecated packages if (isOfficialPackage && !features.IsFeatureEnabled(KnownFeatures.ShowDeprecatedPackages, defaultValue: false)) { - return !DeprecatedPackages.All.Contains(p.Id); + return !DeprecatedPackages.IsDeprecated(p.Id); } return isOfficialPackage;