| File: src\Shared\NpmVersionHelper.cs | Web Access |
| Project: src\src\Aspire.Cli\Aspire.Cli.csproj (aspire) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Semver; namespace Aspire.Shared; /// <summary> /// Helpers for parsing and comparing npm-style version ranges. /// </summary> internal static class NpmVersionHelper { /// <summary> /// Determines whether the existing dependency version should be upgraded to the desired version. /// Returns <c>true</c> when both versions are parseable and the desired version is newer. /// </summary> internal static bool ShouldUpgrade(string existingVersion, string desiredVersion) { return TryParseNpmVersion(existingVersion, out var existingSemVersion) && TryParseNpmVersion(desiredVersion, out var desiredSemVersion) && SemVersion.ComparePrecedence(existingSemVersion, desiredSemVersion) < 0; } /// <summary> /// Attempts to extract a comparable <see cref="SemVersion"/> from an npm version range string. /// Strips range operators (<c>^</c>, <c>~</c>, <c>>=</c>, <c><=</c>, <c>></c>, <c><</c>, <c>=</c>) /// and parses the remaining version. Returns <c>false</c> for union ranges (<c>||</c>), /// workspace references, file paths, and symlinks. /// </summary> internal static bool TryParseNpmVersion(string version, out SemVersion semVersion) { var normalizedVersion = version.Trim(); if (normalizedVersion.Contains("||", StringComparison.Ordinal) || normalizedVersion.StartsWith("workspace:", StringComparison.OrdinalIgnoreCase) || normalizedVersion.StartsWith("file:", StringComparison.OrdinalIgnoreCase) || normalizedVersion.StartsWith("link:", StringComparison.OrdinalIgnoreCase)) { semVersion = default!; return false; } while (normalizedVersion.Length > 0) { if (normalizedVersion.StartsWith(">=", StringComparison.Ordinal) || normalizedVersion.StartsWith("<=", StringComparison.Ordinal)) { normalizedVersion = normalizedVersion[2..].TrimStart(); continue; } if (normalizedVersion[0] is '^' or '~' or '>' or '<' or '=') { normalizedVersion = normalizedVersion[1..].TrimStart(); continue; } break; } if (SemVersion.TryParse(normalizedVersion, SemVersionStyles.Strict, out var strictVersion) && strictVersion is not null) { semVersion = strictVersion; return true; } if (SemVersion.TryParse(normalizedVersion, SemVersionStyles.Any, out var anyVersion) && anyVersion is not null) { semVersion = anyVersion; return true; } semVersion = default!; return false; } }