diff --git a/MintPlayer.Dotnet.Tools.sln b/MintPlayer.Dotnet.Tools.sln index 72b0afc4..f9c5703b 100644 --- a/MintPlayer.Dotnet.Tools.sln +++ b/MintPlayer.Dotnet.Tools.sln @@ -75,6 +75,26 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Verz", "Verz", "{0D1D2D90-B EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MintPlayer.Verz", "Verz\MintPlayer.Verz\MintPlayer.Verz.csproj", "{D93E38AC-5865-4455-A94A-33B66C6328BE}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MintPlayer.Verz.Sdk.Dotnet", "Verz\Sdks\MintPlayer.Verz.Sdk.Dotnet\MintPlayer.Verz.Sdk.Dotnet.csproj", "{88F428E7-7505-4E11-8C2A-AD5581B63608}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sdks", "Sdks", "{AF872388-3655-45E5-9A48-849A50D0C90F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Registries", "Registries", "{E0414AFD-FC74-438B-8A76-5629421AFEBA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MintPlayer.Verz.Registry.NugetOrg", "Verz\Registries\MintPlayer.Verz.Registry.NugetOrg\MintPlayer.Verz.Registry.NugetOrg.csproj", "{7F0186AA-28B4-4FCF-84F8-0CF194F383F7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MintPlayer.Verz.Registry.GithubPackageRegistry", "Verz\Registries\MintPlayer.Verz.Registry.GithubPackageRegistry\MintPlayer.Verz.Registry.GithubPackageRegistry.csproj", "{C6B6C78A-AD7B-4016-8447-FEE4DAB4C056}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MintPlayer.Verz.Abstractions", "Verz\MintPlayer.Verz.Abstractions\MintPlayer.Verz.Abstractions.csproj", "{CFD067BC-C012-4CF4-9388-4880D9B48AEF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MintPlayer.Verz.Sdk.Nodejs", "Verz\Sdks\MintPlayer.Verz.Sdk.Nodejs\MintPlayer.Verz.Sdk.Nodejs.csproj", "{A7262DE6-BD19-4CB4-BE58-31FA2991708F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MintPlayer.Verz.Registry.NpmjsCom", "Verz\Registries\MintPlayer.Verz.Registry.NpmjsCom\MintPlayer.Verz.Registry.NpmjsCom.csproj", "{C25F28C9-3E97-4A6E-BCF2-86ABA65E19B2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MintPlayer.Verz.Sdk.Dotnet.Abstractions", "Verz\Sdks\MintPlayer.Verz.Sdk.Dotnet.Abstractions\MintPlayer.Verz.Sdk.Dotnet.Abstractions.csproj", "{DED5D1B6-9410-4505-99EF-EC0E935FFE3C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MintPlayer.Verz.Sdk.Nodejs.Abstractions", "Verz\Sdks\MintPlayer.Verz.Sdk.Nodejs.Abstractions\MintPlayer.Verz.Sdk.Nodejs.Abstractions.csproj", "{97961B06-5204-49E1-B49A-FCB79D9711ED}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MintPlayer.ObservableCollection.Extensions", "ObservableCollection\MintPlayer.ObservableCollection.Extensions\MintPlayer.ObservableCollection.Extensions.csproj", "{0833621C-AFB4-4E25-9A4D-7B2E44CA7E05}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MintPlayer.ObservableCollection.Avalonia.Desktop", "ObservableCollection\AvaloniaTest\MintPlayer.ObservableCollection.Avalonia.Desktop\MintPlayer.ObservableCollection.Avalonia.Desktop.csproj", "{0BFF0671-2B0D-49BE-A583-FE087034AB11}" @@ -91,6 +111,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MintPlayer.SourceGenerators EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InterfaceImplementationDebugging", "SourceGenerators\TestProjects\InterfaceImplementationDebugging\InterfaceImplementationDebugging.csproj", "{ABA2F1E2-B21B-425D-AB54-CC9EF317ADED}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ApiHash", "ApiHash", "{8972C435-9AB8-4C2A-AB33-A372D731F3DD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MintPlayer.ApiHash", "Verz\ApiHash\MintPlayer.ApiHash\MintPlayer.ApiHash.csproj", "{691498D2-8DD4-4E04-AEB5-05E8279A57E1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -193,6 +217,40 @@ Global {D93E38AC-5865-4455-A94A-33B66C6328BE}.Debug|Any CPU.Build.0 = Debug|Any CPU {D93E38AC-5865-4455-A94A-33B66C6328BE}.Release|Any CPU.ActiveCfg = Release|Any CPU {D93E38AC-5865-4455-A94A-33B66C6328BE}.Release|Any CPU.Build.0 = Release|Any CPU + {88F428E7-7505-4E11-8C2A-AD5581B63608}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {88F428E7-7505-4E11-8C2A-AD5581B63608}.Debug|Any CPU.Build.0 = Debug|Any CPU + {88F428E7-7505-4E11-8C2A-AD5581B63608}.Release|Any CPU.ActiveCfg = Release|Any CPU + {88F428E7-7505-4E11-8C2A-AD5581B63608}.Release|Any CPU.Build.0 = Release|Any CPU + {7F0186AA-28B4-4FCF-84F8-0CF194F383F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7F0186AA-28B4-4FCF-84F8-0CF194F383F7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F0186AA-28B4-4FCF-84F8-0CF194F383F7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7F0186AA-28B4-4FCF-84F8-0CF194F383F7}.Release|Any CPU.Build.0 = Release|Any CPU + {C6B6C78A-AD7B-4016-8447-FEE4DAB4C056}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C6B6C78A-AD7B-4016-8447-FEE4DAB4C056}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C6B6C78A-AD7B-4016-8447-FEE4DAB4C056}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C6B6C78A-AD7B-4016-8447-FEE4DAB4C056}.Release|Any CPU.Build.0 = Release|Any CPU + {CFD067BC-C012-4CF4-9388-4880D9B48AEF}.Debug|Any CPU.Active78A-AD7B-4016-8447-FEE4DAB4C056}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C6B6C78A-AD7B-4016-8447-FEE4DAB4C056}.Release|Any CPU.Build.0 = Release|Any CPU + {CFD067BC-C012-4CF4-9388-4880D9B48AEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CFD067BC-C012-4CF4-9388-4880D9B48AEF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CFD067BC-C012-4CF4-9388-4880D9B48AEF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CFD067BC-C012-4CF4-9388-4880D9B48AEF}.Release|Any CPU.Build.0 = Release|Any CPU + {A7262DE6-BD19-4CB4-BE58-31FA2991708F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A7262DE6-BD19-4CB4-BE58-31FA2991708F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A7262DE6-BD19-4CB4-BE58-31FA2991708F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A7262DE6-BD19-4CB4-BE58-31FA2991708F}.Release|Any CPU.Build.0 = Release|Any CPU + {C25F28C9-3E97-4A6E-BCF2-86ABA65E19B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C25F28C9-3E97-4A6E-BCF2-86ABA65E19B2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C25F28C9-3E97-4A6E-BCF2-86ABA65E19B2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C25F28C9-3E97-4A6E-BCF2-86ABA65E19B2}.Release|Any CPU.Build.0 = Release|Any CPU + {DED5D1B6-9410-4505-99EF-EC0E935FFE3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DED5D1B6-9410-4505-99EF-EC0E935FFE3C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DED5D1B6-9410-4505-99EF-EC0E935FFE3C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DED5D1B6-9410-4505-99EF-EC0E935FFE3C}.Release|Any CPU.Build.0 = Release|Any CPU + {97961B06-5204-49E1-B49A-FCB79D9711ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {97961B06-5204-49E1-B49A-FCB79D9711ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {97961B06-5204-49E1-B49A-FCB79D9711ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {97961B06-5204-49E1-B49A-FCB79D9711ED}.Release|Any CPU.Build.0 = Release|Any CPU {0833621C-AFB4-4E25-9A4D-7B2E44CA7E05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0833621C-AFB4-4E25-9A4D-7B2E44CA7E05}.Debug|Any CPU.Build.0 = Debug|Any CPU {0833621C-AFB4-4E25-9A4D-7B2E44CA7E05}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -217,6 +275,10 @@ Global {ABA2F1E2-B21B-425D-AB54-CC9EF317ADED}.Debug|Any CPU.Build.0 = Debug|Any CPU {ABA2F1E2-B21B-425D-AB54-CC9EF317ADED}.Release|Any CPU.ActiveCfg = Release|Any CPU {ABA2F1E2-B21B-425D-AB54-CC9EF317ADED}.Release|Any CPU.Build.0 = Release|Any CPU + {691498D2-8DD4-4E04-AEB5-05E8279A57E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {691498D2-8DD4-4E04-AEB5-05E8279A57E1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {691498D2-8DD4-4E04-AEB5-05E8279A57E1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {691498D2-8DD4-4E04-AEB5-05E8279A57E1}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -246,6 +308,17 @@ Global {82C6CB67-DDC0-4791-B975-39A970BD4CDC} = {C65054D9-CAD1-4124-B474-D03C178D9D78} {6F4991E0-B4D8-43BA-92C0-15DD37ED7CD3} = {C65054D9-CAD1-4124-B474-D03C178D9D78} {D93E38AC-5865-4455-A94A-33B66C6328BE} = {0D1D2D90-BCFA-47EE-8C72-2E10405F96DF} + {88F428E7-7505-4E11-8C2A-AD5581B63608} = {AF872388-3655-45E5-9A48-849A50D0C90F} + {AF872388-3655-45E5-9A48-849A50D0C90F} = {0D1D2D90-BCFA-47EE-8C72-2E10405F96DF} + {E0414AFD-FC74-438B-8A76-5629421AFEBA} = {0D1D2D90-BCFA-47EE-8C72-2E10405F96DF} + {7F0186AA-28B4-4FCF-84F8-0CF194F383F7} = {E0414AFD-FC74-438B-8A76-5629421AFEBA} + {C6B6C78A-AD7B-4016-8447-FEE4DAB4C056} = {E0414AFD-FC74-438B-8A76-5629421AFEBA} + {CFD067BC-C012-4CF4-9388-4880D9B48AEF} = {0D1D2D90-BCFA-47EE-8C72-2E10405F96DF} + {A7262DE6-BD19-4CB4-BE58-31FA2991708F} = {AF872388-3655-45E5-9A48-849A50D0C90F} + {C25F28C9-3E97-4A6E-BCF2-86ABA65E19B2} = {E0414AFD-FC74-438B-8A76-5629421AFEBA} + {DED5D1B6-9410-4505-99EF-EC0E935FFE3C} = {AF872388-3655-45E5-9A48-849A50D0C90F} + {97961B06-5204-49E1-B49A-FCB79D9711ED} = {AF872388-3655-45E5-9A48-849A50D0C90F} + {95347922-E7BA-4D46-8B9E-2FA9DC414795} = {C65054D9-CAD1-4124-B474-D03C178D9D78} {0833621C-AFB4-4E25-9A4D-7B2E44CA7E05} = {A67D3C5B-2DCD-45B7-BFB6-D019F39C67D9} {0BFF0671-2B0D-49BE-A583-FE087034AB11} = {9B869A7B-598C-4F67-B962-F00F08920850} {9B869A7B-598C-4F67-B962-F00F08920850} = {A67D3C5B-2DCD-45B7-BFB6-D019F39C67D9} @@ -254,6 +327,8 @@ Global {61A8B896-5E76-411F-951F-4D2BF0344281} = {1614A8B2-CA9A-4F94-B68A-BCC8ED244648} {9BF030D9-7CBB-458C-8051-E1D7FB9D7E46} = {1614A8B2-CA9A-4F94-B68A-BCC8ED244648} {ABA2F1E2-B21B-425D-AB54-CC9EF317ADED} = {1614A8B2-CA9A-4F94-B68A-BCC8ED244648} + {8972C435-9AB8-4C2A-AB33-A372D731F3DD} = {0D1D2D90-BCFA-47EE-8C72-2E10405F96DF} + {691498D2-8DD4-4E04-AEB5-05E8279A57E1} = {8972C435-9AB8-4C2A-AB33-A372D731F3DD} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D5378D43-9246-4355-8C4B-880DB15B07DA} diff --git a/StringExtensions/MintPlayer.StringExtensions/MintPlayer.StringExtensions.csproj b/StringExtensions/MintPlayer.StringExtensions/MintPlayer.StringExtensions.csproj index 14ccb46e..dbecaf34 100644 --- a/StringExtensions/MintPlayer.StringExtensions/MintPlayer.StringExtensions.csproj +++ b/StringExtensions/MintPlayer.StringExtensions/MintPlayer.StringExtensions.csproj @@ -8,7 +8,7 @@ true true - 9.0.0 + 9.1.0 Pieterjan De Clippel MintPlayer Generate random strings, string casing extensions, string.Format with placeholder tags diff --git a/StringExtensions/MintPlayer.StringExtensions/Repeat.cs b/StringExtensions/MintPlayer.StringExtensions/Repeat.cs new file mode 100644 index 00000000..facf6782 --- /dev/null +++ b/StringExtensions/MintPlayer.StringExtensions/Repeat.cs @@ -0,0 +1,10 @@ +namespace MintPlayer.StringExtensions; + +public static class RepeatExtensions +{ + public static string Repeat(this string text, int count) + => string.Join(string.Empty, Enumerable.Range(0, count).Select(_ => text)); + + public static string Repeat(this char c, int count) + => new string(Enumerable.Range(0, count).Select(_ => c).ToArray()); +} diff --git a/Verz/ApiHash/MintPlayer.ApiHash/ApiHasher.cs b/Verz/ApiHash/MintPlayer.ApiHash/ApiHasher.cs new file mode 100644 index 00000000..dabbc712 --- /dev/null +++ b/Verz/ApiHash/MintPlayer.ApiHash/ApiHasher.cs @@ -0,0 +1,19 @@ +using System.Security.Cryptography; +using System.Text; +using PublicApiGenerator; +using System.Reflection; + +namespace MintPlayer.ApiHash; + +public static class ApiHasher +{ + public static string ComputeHashFromAssembly(string assemblyPath) + { + var assembly = Assembly.LoadFrom(assemblyPath); + var apiText = ApiGenerator.GeneratePublicApi(assembly); + using var sha = SHA256.Create(); + var bytes = Encoding.UTF8.GetBytes(apiText); + var hash = sha.ComputeHash(bytes); + return Convert.ToHexString(hash).ToLowerInvariant(); + } +} diff --git a/Verz/ApiHash/MintPlayer.ApiHash/MintPlayer.ApiHash.csproj b/Verz/ApiHash/MintPlayer.ApiHash/MintPlayer.ApiHash.csproj new file mode 100644 index 00000000..b3115883 --- /dev/null +++ b/Verz/ApiHash/MintPlayer.ApiHash/MintPlayer.ApiHash.csproj @@ -0,0 +1,34 @@ + + + + net9.0 + enable + enable + + + + + + + + + + + + + + + + + + @(ApiHash->'%(Identity)') + + + + + + + + + + diff --git a/Verz/MintPlayer.Verz.Abstractions/IDevelopmentSdk.cs b/Verz/MintPlayer.Verz.Abstractions/IDevelopmentSdk.cs new file mode 100644 index 00000000..1b6fb14b --- /dev/null +++ b/Verz/MintPlayer.Verz.Abstractions/IDevelopmentSdk.cs @@ -0,0 +1,6 @@ +namespace MintPlayer.Verz.Abstractions; + +public interface IDevelopmentSdk +{ + Task GetPackageById(string packageId); +} diff --git a/Verz/MintPlayer.Verz.Abstractions/IPackageRegistry.cs b/Verz/MintPlayer.Verz.Abstractions/IPackageRegistry.cs new file mode 100644 index 00000000..c5a95ffc --- /dev/null +++ b/Verz/MintPlayer.Verz.Abstractions/IPackageRegistry.cs @@ -0,0 +1,6 @@ +namespace MintPlayer.Verz.Abstractions; + +public interface IPackageRegistry +{ + Task> GetPackageVersions(string packageId); +} diff --git a/Verz/MintPlayer.Verz.Abstractions/MintPlayer.Verz.Abstractions.csproj b/Verz/MintPlayer.Verz.Abstractions/MintPlayer.Verz.Abstractions.csproj new file mode 100644 index 00000000..3324e6eb --- /dev/null +++ b/Verz/MintPlayer.Verz.Abstractions/MintPlayer.Verz.Abstractions.csproj @@ -0,0 +1,13 @@ + + + + net9.0 + enable + enable + + + + + + + diff --git a/Verz/MintPlayer.Verz/App.cs b/Verz/MintPlayer.Verz/App.cs new file mode 100644 index 00000000..170cd2d3 --- /dev/null +++ b/Verz/MintPlayer.Verz/App.cs @@ -0,0 +1,255 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using MintPlayer.StringExtensions; +using MintPlayer.ApiHash; +using NuGet.Configuration; +using NuGet.Protocol; +using NuGet.Protocol.Core.Types; +using NuGet.Versioning; +using NuGet.Packaging; +using System.Reflection; +using System.Xml.Linq; +using System.Diagnostics; + +namespace MintPlayer.Verz; + +internal class App : IApp, IHelper +{ + public App() { } + + public async Task Run(string[] args) + { + if (args.Length >= 2 && args[0].Equals("dotnet", StringComparison.OrdinalIgnoreCase) && args[1].Equals("next", StringComparison.OrdinalIgnoreCase)) + { + await RunDotnetNext(args.Skip(2).ToArray()); + return; + } + + await ShowUsage(); + } + + public Task ShowUsage() + { + var versionString = Assembly.GetEntryAssembly()? + .GetCustomAttribute()? + .InformationalVersion + .ToString(); + + var versionLine = $"verz v{versionString}"; + + Console.WriteLine($""" + {versionLine} + {"-".Repeat(versionLine.Length)} + Usage: + verz dotnet next --project [--tfm ] [--nuget-config ] + """); + + return Task.CompletedTask; + } + + private static (string packageId, string assemblyName, string? tfm, int major) ReadProjectDetails(string csprojPath, string? tfmArg) + { + var doc = XDocument.Load(csprojPath); + XNamespace msbuild = doc.Root!.Name.Namespace; + var pg = doc.Root.Elements(msbuild + "PropertyGroup"); + var packageId = pg.Elements(msbuild + "PackageId").Select(e => e.Value).FirstOrDefault(); + var assemblyName = pg.Elements(msbuild + "AssemblyName").Select(e => e.Value).FirstOrDefault(); + var tfm = pg.Elements(msbuild + "TargetFramework").Select(e => e.Value).FirstOrDefault(); + var tfms = pg.Elements(msbuild + "TargetFrameworks").Select(e => e.Value).FirstOrDefault(); + if (string.IsNullOrWhiteSpace(packageId)) packageId = Path.GetFileNameWithoutExtension(csprojPath); + if (string.IsNullOrWhiteSpace(assemblyName)) assemblyName = packageId; + + string? selectedTfm = tfmArg; + if (string.IsNullOrWhiteSpace(selectedTfm)) + { + if (!string.IsNullOrWhiteSpace(tfm)) selectedTfm = tfm; + else if (!string.IsNullOrWhiteSpace(tfms)) + { + selectedTfm = tfms.Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) + .OrderByDescending(ParseTfmMajorMinor) + .FirstOrDefault(); + } + } + + if (string.IsNullOrWhiteSpace(selectedTfm)) throw new InvalidOperationException("Unable to resolve TargetFramework"); + var major = ParseTfmMajorMinor(selectedTfm).major; + return (packageId!, assemblyName!, selectedTfm, major); + } + + private static (int major, int minor) ParseTfmMajorMinor(string tfm) + { + if (tfm.StartsWith("netstandard")) + { + var v = tfm.Substring("netstandard".Length); + if (Version.TryParse(v, out var stdV)) return (stdV.Major, stdV.Minor); + return (2, 0); + } + if (tfm.StartsWith("net")) + { + var v = tfm.Substring(3); + if (Version.TryParse(v, out var netV)) return (netV.Major, netV.Minor); + } + return (0, 0); + } + + private static async Task BuildProject(string csprojPath, string configuration) + { + var psi = new ProcessStartInfo("dotnet", $"build \"{csprojPath}\" -c {configuration} --nologo") + { + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true, + WorkingDirectory = Path.GetDirectoryName(csprojPath)! + }; + var p = Process.Start(psi)!; + await p.WaitForExitAsync(); + if (p.ExitCode != 0) + { + var err = await p.StandardError.ReadToEndAsync(); + throw new Exception($"Build failed for {csprojPath}: {err}"); + } + } + + private static string GetBuiltAssemblyPath(string csprojPath, string configuration, string tfm, string assemblyName) + { + var projectDir = Path.GetDirectoryName(csprojPath)!; + var dllPath = Path.Combine(projectDir, "bin", configuration, tfm, assemblyName + ".dll"); + if (!File.Exists(dllPath)) throw new FileNotFoundException("Built assembly not found", dllPath); + return dllPath; + } + + private static IEnumerable GetPackageSources(string? nugetConfigPath) + { + ISettings settings; + if (!string.IsNullOrWhiteSpace(nugetConfigPath)) + { + var full = Path.GetFullPath(nugetConfigPath); + settings = Settings.LoadSpecificSettings(Path.GetDirectoryName(full)!, Path.GetFileName(full)); + } + else + { + settings = Settings.LoadDefaultSettings(Directory.GetCurrentDirectory()); + } + var provider = new PackageSourceProvider(settings); + return provider.LoadPackageSources().Where(s => s.IsEnabled); + } + + private static async Task> GetAllPackageVersions(string packageId, IEnumerable sources) + { + var cache = new SourceCacheContext(); + var versions = new HashSet(); + foreach (var source in sources) + { + var repo = Repository.Factory.GetCoreV3(source); + var finder = await repo.GetResourceAsync(); + var v = await finder.GetAllVersionsAsync(packageId, cache, NuGet.Common.NullLogger.Instance, CancellationToken.None); + foreach (var nv in v) versions.Add(nv); + } + return versions.OrderBy(v => v).ToArray(); + } + + private static async Task TryDownloadPackageAndComputeApiHash(string packageId, NuGetVersion version, IEnumerable sources, string tfm, string? preferredAssemblyName) + { + var cache = new SourceCacheContext(); + foreach (var source in sources) + { + try + { + var repo = Repository.Factory.GetCoreV3(source); + var finder = await repo.GetResourceAsync(); + using var mem = new MemoryStream(); + var ok = await finder.CopyNupkgToStreamAsync(packageId, version, mem, cache, NuGet.Common.NullLogger.Instance, CancellationToken.None); + if (!ok) continue; + mem.Position = 0; + using var reader = new PackageArchiveReader(mem); + var refItems = reader.GetFiles($"ref/{tfm}"); + var libItems = reader.GetFiles($"lib/{tfm}"); + var dlls = refItems.Concat(libItems).Where(p => p.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)).ToArray(); + if (dlls.Length == 0) continue; + string? pick = null; + if (!string.IsNullOrWhiteSpace(preferredAssemblyName)) + { + pick = dlls.FirstOrDefault(p => Path.GetFileNameWithoutExtension(p).Equals(preferredAssemblyName, StringComparison.OrdinalIgnoreCase)); + } + pick ??= dlls.First(); + using var s = reader.GetStream(pick); + var tempDir = Path.Combine(Path.GetTempPath(), "verz", Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(tempDir); + var tempDll = Path.Combine(tempDir, Path.GetFileName(pick)); + using (var fs = File.Create(tempDll)) + { + await s.CopyToAsync(fs); + } + try + { + return ApiHasher.ComputeHashFromAssembly(tempDll); + } + finally + { + try { Directory.Delete(tempDir, true); } catch { } + } + } + catch + { + // try next source + } + } + return null; + } + + private async Task RunDotnetNext(string[] args) + { + string? csproj = null; + string? tfm = null; + string? nugetConfig = null; + for (int i = 0; i < args.Length; i++) + { + switch (args[i]) + { + case "--project": + csproj = args[++i]; + break; + case "--tfm": + tfm = args[++i]; + break; + case "--nuget-config": + nugetConfig = args[++i]; + break; + } + } + if (string.IsNullOrWhiteSpace(csproj) || !File.Exists(csproj)) throw new FileNotFoundException("Project file not found", csproj); + + var (packageId, assemblyName, resolvedTfm, tfmMajor) = ReadProjectDetails(csproj, tfm); + + await BuildProject(csproj, "Release"); + var assemblyPath = GetBuiltAssemblyPath(csproj, "Release", resolvedTfm!, assemblyName); + var currentApiHash = ApiHasher.ComputeHashFromAssembly(assemblyPath); + + var sources = GetPackageSources(nugetConfig).ToArray(); + var versions = await GetAllPackageVersions(packageId, sources); + var bandVersions = versions.Where(v => v.Major == tfmMajor && string.IsNullOrEmpty(v.Release)).ToArray(); + if (bandVersions.Length == 0) + { + Console.WriteLine($"{tfmMajor}.0.0"); + return; + } + + var latest = bandVersions.Max(); + var previousHash = await TryDownloadPackageAndComputeApiHash(packageId, latest, sources, resolvedTfm!, assemblyName); + if (previousHash == null) + { + Console.WriteLine($"{latest.Major}.{latest.Minor}.{latest.Patch + 1}"); + return; + } + + if (string.Equals(previousHash, currentApiHash, StringComparison.Ordinal)) + { + Console.WriteLine($"{latest.Major}.{latest.Minor}.{latest.Patch + 1}"); + } + else + { + Console.WriteLine($"{latest.Major}.{latest.Minor + 1}.0"); + } + } +} diff --git a/Verz/MintPlayer.Verz/MintPlayer.Verz.csproj b/Verz/MintPlayer.Verz/MintPlayer.Verz.csproj index fbf411ef..3e75ed84 100644 --- a/Verz/MintPlayer.Verz/MintPlayer.Verz.csproj +++ b/Verz/MintPlayer.Verz/MintPlayer.Verz.csproj @@ -2,7 +2,8 @@ Exe - net6.0;net8.0;net9.0 + net9.0 + 13 enable enable 0.0.1 @@ -12,6 +13,26 @@ true verz + 1d1306ff-f7b1-4dab-bea1-99d2d582db9f + + + + + + + + + + + + + + + + + + + diff --git a/Verz/MintPlayer.Verz/Program.cs b/Verz/MintPlayer.Verz/Program.cs index 33986699..8afc20ad 100644 --- a/Verz/MintPlayer.Verz/Program.cs +++ b/Verz/MintPlayer.Verz/Program.cs @@ -1,2 +1,66 @@ // dotnet tool install --global MintPlayer.Verz -Console.WriteLine("Hello, World!"); + +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Hosting.Internal; +using MintPlayer.Verz; + +var app = Host.CreateDefaultBuilder() + .ConfigureAppConfiguration((context, config) => { }) + .ConfigureServices((context, services) => + { + services.AddSingleton(); + services.AddSingleton(); + + services + .AddNugetOrgRegistry() + .AddNpmjsComRegistry() + .AddGithubPackageRegistry("MintPlayer", context.Configuration.GetValue("GithubPAT")!) + ; + services + .AddDotnetSDK() + .AddNodejsSDK(); + }) + .Build(); + +var runner = app.Services.GetRequiredService(); +var helper = app.Services.GetRequiredService(); +if (args.Length is 1 && args[0] is "--help") +{ + await helper.ShowUsage(); + return; +} + +#if DEBUG +await runner.Run(args); +#else +try +{ + await runner.Run(args); +} +catch (Exception ex) +{ + await helper.ShowUsage(); +} +#endif + +internal interface IApp +{ + Task Run(string[] args); +} + +internal interface IHelper +{ + Task ShowUsage(); +} + +//public interface IAllDotnetPackageSources +//{ + +//} + +//internal class AllDotnetPackageSources : IAllDotnetPackageSources +//{ + +//} diff --git a/Verz/MintPlayer.Verz/Properties/launchSettings.json b/Verz/MintPlayer.Verz/Properties/launchSettings.json new file mode 100644 index 00000000..4288c4ae --- /dev/null +++ b/Verz/MintPlayer.Verz/Properties/launchSettings.json @@ -0,0 +1,10 @@ +{ + "profiles": { + "MintPlayer.Verz": { + "commandName": "Project", + "environmentVariables": { + "DOTNET_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/Verz/Registries/MintPlayer.Verz.Registry.GithubPackageRegistry/Extensions.cs b/Verz/Registries/MintPlayer.Verz.Registry.GithubPackageRegistry/Extensions.cs new file mode 100644 index 00000000..4815469b --- /dev/null +++ b/Verz/Registries/MintPlayer.Verz.Registry.GithubPackageRegistry/Extensions.cs @@ -0,0 +1,17 @@ +using Microsoft.Extensions.DependencyInjection; +using MintPlayer.Verz.Abstractions; +using MintPlayer.Verz.Registry.GithubPackageRegistry; +using MintPlayer.Verz.Sdk.Dotnet.Abstractions; +using MintPlayer.Verz.Sdk.Nodejs.Abstractions; + +namespace MintPlayer.Verz; + +public static class Extensions +{ + public static IServiceCollection AddGithubPackageRegistry(this IServiceCollection services, string organization, string token) + => services + .AddSingleton(provider => new GithubPackageRegistry(organization, token)) + .AddSingleton(provider => provider.GetRequiredService()) + .AddSingleton(provider => provider.GetRequiredService()) + .AddSingleton(provider => provider.GetRequiredService()); +} diff --git a/Verz/Registries/MintPlayer.Verz.Registry.GithubPackageRegistry/GithubPackageRegistry.cs b/Verz/Registries/MintPlayer.Verz.Registry.GithubPackageRegistry/GithubPackageRegistry.cs new file mode 100644 index 00000000..8b2c0021 --- /dev/null +++ b/Verz/Registries/MintPlayer.Verz.Registry.GithubPackageRegistry/GithubPackageRegistry.cs @@ -0,0 +1,51 @@ +using MintPlayer.Verz.Abstractions; +using MintPlayer.Verz.Sdk.Dotnet.Abstractions; +using MintPlayer.Verz.Sdk.Nodejs.Abstractions; +using NuGet.Configuration; +using NuGet.Protocol; +using NuGet.Protocol.Core.Types; +using System.Diagnostics.CodeAnalysis; + +namespace MintPlayer.Verz.Registry.GithubPackageRegistry; + +internal interface IGithubPackageRegistry : IFeedSupportsDotnetSDK, IFeedSupportsNodejsSDK { } + +internal class GithubPackageRegistry : IGithubPackageRegistry +{ + private readonly string organization; + private readonly string token; + private SourceCacheContext? cache; + private FindPackageByIdResource? nugetPackageFinder; + public GithubPackageRegistry(string organization, string token) + { + this.organization = organization; + this.token = token; + } + + // https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-nuget-registry + public string NugetFeedUrl => $"https://nuget.pkg.github.com/{organization}/index.json"; + + // https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry + public string NpmFeed => "https://npm.pkg.github.com"; + + public async Task> GetPackageVersions(string packageId) + { + if (nugetPackageFinder == null) + await InitializeFeed(); + + var packageVersions = await nugetPackageFinder.GetAllVersionsAsync(packageId, cache, NuGet.Common.NullLogger.Instance, CancellationToken.None); + return packageVersions.Select(v => string.IsNullOrEmpty(v.Release) + ? v.ToString() + : $"{v.Version}-{v.Release}"); + } + + [MemberNotNull(nameof(nugetPackageFinder))] + public async Task InitializeFeed() + { + var feed = new PackageSource(NugetFeedUrl, "github.com"); + feed.Credentials = new PackageSourceCredential("github.com", organization, token, true, null); // goto github.com/settings/tokens + var repository = Repository.Factory.GetCoreV3(feed); + nugetPackageFinder = await repository.GetResourceAsync(); + cache = new SourceCacheContext(); + } +} diff --git a/Verz/Registries/MintPlayer.Verz.Registry.GithubPackageRegistry/MintPlayer.Verz.Registry.GithubPackageRegistry.csproj b/Verz/Registries/MintPlayer.Verz.Registry.GithubPackageRegistry/MintPlayer.Verz.Registry.GithubPackageRegistry.csproj new file mode 100644 index 00000000..d171fc9d --- /dev/null +++ b/Verz/Registries/MintPlayer.Verz.Registry.GithubPackageRegistry/MintPlayer.Verz.Registry.GithubPackageRegistry.csproj @@ -0,0 +1,15 @@ + + + + net9.0 + enable + enable + + + + + + + + + diff --git a/Verz/Registries/MintPlayer.Verz.Registry.NpmjsCom/Extensions.cs b/Verz/Registries/MintPlayer.Verz.Registry.NpmjsCom/Extensions.cs new file mode 100644 index 00000000..79d219fb --- /dev/null +++ b/Verz/Registries/MintPlayer.Verz.Registry.NpmjsCom/Extensions.cs @@ -0,0 +1,15 @@ +using Microsoft.Extensions.DependencyInjection; +using MintPlayer.Verz.Abstractions; +using MintPlayer.Verz.Registry.NpmjsCom; +using MintPlayer.Verz.Sdk.Nodejs.Abstractions; + +namespace MintPlayer.Verz; + +public static class Extensions +{ + public static IServiceCollection AddNpmjsComRegistry(this IServiceCollection services) + => services + .AddSingleton() + .AddSingleton(provider => provider.GetRequiredService()) + .AddSingleton(provider => provider.GetRequiredService()); +} diff --git a/Verz/Registries/MintPlayer.Verz.Registry.NpmjsCom/MintPlayer.Verz.Registry.NpmjsCom.csproj b/Verz/Registries/MintPlayer.Verz.Registry.NpmjsCom/MintPlayer.Verz.Registry.NpmjsCom.csproj new file mode 100644 index 00000000..17c2ad7b --- /dev/null +++ b/Verz/Registries/MintPlayer.Verz.Registry.NpmjsCom/MintPlayer.Verz.Registry.NpmjsCom.csproj @@ -0,0 +1,14 @@ + + + + net9.0 + enable + enable + + + + + + + + diff --git a/Verz/Registries/MintPlayer.Verz.Registry.NpmjsCom/NpmjsComPackageRegistry.cs b/Verz/Registries/MintPlayer.Verz.Registry.NpmjsCom/NpmjsComPackageRegistry.cs new file mode 100644 index 00000000..5b7b17c0 --- /dev/null +++ b/Verz/Registries/MintPlayer.Verz.Registry.NpmjsCom/NpmjsComPackageRegistry.cs @@ -0,0 +1,16 @@ +using MintPlayer.Verz.Abstractions; +using MintPlayer.Verz.Sdk.Nodejs.Abstractions; + +namespace MintPlayer.Verz.Registry.NpmjsCom; + +internal interface INpmjsComPackageRegistry : IPackageRegistry, IFeedSupportsNodejsSDK { } + +internal class NpmjsComPackageRegistry : INpmjsComPackageRegistry +{ + public string NpmFeed => "https://registry.npmjs.org"; + + public Task> GetPackageVersions(string packageId) + { + return Task.FromResult>([]); + } +} diff --git a/Verz/Registries/MintPlayer.Verz.Registry.NugetOrg/Extensions.cs b/Verz/Registries/MintPlayer.Verz.Registry.NugetOrg/Extensions.cs new file mode 100644 index 00000000..85e4678a --- /dev/null +++ b/Verz/Registries/MintPlayer.Verz.Registry.NugetOrg/Extensions.cs @@ -0,0 +1,15 @@ +using Microsoft.Extensions.DependencyInjection; +using MintPlayer.Verz.Abstractions; +using MintPlayer.Verz.Registry.NugetOrg; +using MintPlayer.Verz.Sdk.Dotnet.Abstractions; + +namespace MintPlayer.Verz; + +public static class Extensions +{ + public static IServiceCollection AddNugetOrgRegistry(this IServiceCollection services) + => services + .AddSingleton() + .AddSingleton(provider => provider.GetRequiredService()) + .AddSingleton(provider => provider.GetRequiredService()); +} diff --git a/Verz/Registries/MintPlayer.Verz.Registry.NugetOrg/MintPlayer.Verz.Registry.NugetOrg.csproj b/Verz/Registries/MintPlayer.Verz.Registry.NugetOrg/MintPlayer.Verz.Registry.NugetOrg.csproj new file mode 100644 index 00000000..2a0704ab --- /dev/null +++ b/Verz/Registries/MintPlayer.Verz.Registry.NugetOrg/MintPlayer.Verz.Registry.NugetOrg.csproj @@ -0,0 +1,14 @@ + + + + net9.0 + enable + enable + + + + + + + + diff --git a/Verz/Registries/MintPlayer.Verz.Registry.NugetOrg/NugetOrgPackageRegistry.cs b/Verz/Registries/MintPlayer.Verz.Registry.NugetOrg/NugetOrgPackageRegistry.cs new file mode 100644 index 00000000..3bec599f --- /dev/null +++ b/Verz/Registries/MintPlayer.Verz.Registry.NugetOrg/NugetOrgPackageRegistry.cs @@ -0,0 +1,36 @@ +using MintPlayer.Verz.Abstractions; +using MintPlayer.Verz.Sdk.Dotnet.Abstractions; +using NuGet.Configuration; +using NuGet.Protocol; +using NuGet.Protocol.Core.Types; + +namespace MintPlayer.Verz.Registry.NugetOrg; + +internal interface INugetOrgPackageRegistry : IFeedSupportsDotnetSDK { } + +internal class NugetOrgPackageRegistry : INugetOrgPackageRegistry +{ + private FindPackageByIdResource? nugetPackageFinder; + private SourceCacheContext? cache; + + public string NugetFeedUrl => "https://api.nuget.org/v3/index.json"; + + public async Task> GetPackageVersions(string packageId) + { + if (nugetPackageFinder == null) + await InitializeFeed(); + + var packageVersions = await nugetPackageFinder.GetAllVersionsAsync(packageId, cache, NuGet.Common.NullLogger.Instance, CancellationToken.None); + return packageVersions.Select(v => string.IsNullOrEmpty(v.Release) + ? v.ToString() + : $"{v.Version}-{v.Release}"); + } + + public async Task InitializeFeed() + { + var feed = new PackageSource(NugetFeedUrl, "nuget.org"); + var repository = Repository.Factory.GetCoreV3(feed); + nugetPackageFinder = await repository.GetResourceAsync(); + cache = new SourceCacheContext(); + } +} \ No newline at end of file diff --git a/Verz/Sdks/MintPlayer.Verz.Sdk.Dotnet.Abstractions/IFeedSupportsDotnetSDK.cs b/Verz/Sdks/MintPlayer.Verz.Sdk.Dotnet.Abstractions/IFeedSupportsDotnetSDK.cs new file mode 100644 index 00000000..b32796ff --- /dev/null +++ b/Verz/Sdks/MintPlayer.Verz.Sdk.Dotnet.Abstractions/IFeedSupportsDotnetSDK.cs @@ -0,0 +1,9 @@ +using MintPlayer.Verz.Abstractions; + +namespace MintPlayer.Verz.Sdk.Dotnet.Abstractions; + +public interface IFeedSupportsDotnetSDK : IPackageRegistry +{ + string NugetFeedUrl { get; } + Task InitializeFeed(); +} diff --git a/Verz/Sdks/MintPlayer.Verz.Sdk.Dotnet.Abstractions/MintPlayer.Verz.Sdk.Dotnet.Abstractions.csproj b/Verz/Sdks/MintPlayer.Verz.Sdk.Dotnet.Abstractions/MintPlayer.Verz.Sdk.Dotnet.Abstractions.csproj new file mode 100644 index 00000000..1148782e --- /dev/null +++ b/Verz/Sdks/MintPlayer.Verz.Sdk.Dotnet.Abstractions/MintPlayer.Verz.Sdk.Dotnet.Abstractions.csproj @@ -0,0 +1,14 @@ + + + + net9.0 + enable + enable + + + + + + + + diff --git a/Verz/Sdks/MintPlayer.Verz.Sdk.Dotnet/DotnetSDK.cs b/Verz/Sdks/MintPlayer.Verz.Sdk.Dotnet/DotnetSDK.cs new file mode 100644 index 00000000..2d945ed1 --- /dev/null +++ b/Verz/Sdks/MintPlayer.Verz.Sdk.Dotnet/DotnetSDK.cs @@ -0,0 +1,19 @@ +using MintPlayer.Verz.Abstractions; +using MintPlayer.Verz.Sdk.Dotnet.Abstractions; + +namespace MintPlayer.Verz.Sdk.Dotnet; + +internal class DotnetSDK : IDevelopmentSdk +{ + private readonly IEnumerable dotnetFeeds; + public DotnetSDK(IEnumerable dotnetFeeds) + { + this.dotnetFeeds = dotnetFeeds; + } + + public Task GetPackageById(string packageId) + { + throw new NotImplementedException(); + //dotnetFeeds.Select(feed => feed.NugetFeedUrl) + } +} diff --git a/Verz/Sdks/MintPlayer.Verz.Sdk.Dotnet/Extensions.cs b/Verz/Sdks/MintPlayer.Verz.Sdk.Dotnet/Extensions.cs new file mode 100644 index 00000000..bbe4da99 --- /dev/null +++ b/Verz/Sdks/MintPlayer.Verz.Sdk.Dotnet/Extensions.cs @@ -0,0 +1,11 @@ +using Microsoft.Extensions.DependencyInjection; +using MintPlayer.Verz.Abstractions; +using MintPlayer.Verz.Sdk.Dotnet; + +namespace MintPlayer.Verz; + +public static class Extensions +{ + public static IServiceCollection AddDotnetSDK(this IServiceCollection services) + => services.AddSingleton(); +} diff --git a/Verz/Sdks/MintPlayer.Verz.Sdk.Dotnet/MintPlayer.Verz.Sdk.Dotnet.csproj b/Verz/Sdks/MintPlayer.Verz.Sdk.Dotnet/MintPlayer.Verz.Sdk.Dotnet.csproj new file mode 100644 index 00000000..3af5e10b --- /dev/null +++ b/Verz/Sdks/MintPlayer.Verz.Sdk.Dotnet/MintPlayer.Verz.Sdk.Dotnet.csproj @@ -0,0 +1,18 @@ + + + + net9.0 + enable + enable + + + + + + + + + + + + diff --git a/Verz/Sdks/MintPlayer.Verz.Sdk.Nodejs.Abstractions/IFeedSupportsNodejsSDK.cs b/Verz/Sdks/MintPlayer.Verz.Sdk.Nodejs.Abstractions/IFeedSupportsNodejsSDK.cs new file mode 100644 index 00000000..ece156fe --- /dev/null +++ b/Verz/Sdks/MintPlayer.Verz.Sdk.Nodejs.Abstractions/IFeedSupportsNodejsSDK.cs @@ -0,0 +1,8 @@ +using MintPlayer.Verz.Abstractions; + +namespace MintPlayer.Verz.Sdk.Nodejs.Abstractions; + +public interface IFeedSupportsNodejsSDK : IPackageRegistry +{ + string NpmFeed { get; } +} diff --git a/Verz/Sdks/MintPlayer.Verz.Sdk.Nodejs.Abstractions/MintPlayer.Verz.Sdk.Nodejs.Abstractions.csproj b/Verz/Sdks/MintPlayer.Verz.Sdk.Nodejs.Abstractions/MintPlayer.Verz.Sdk.Nodejs.Abstractions.csproj new file mode 100644 index 00000000..828b849e --- /dev/null +++ b/Verz/Sdks/MintPlayer.Verz.Sdk.Nodejs.Abstractions/MintPlayer.Verz.Sdk.Nodejs.Abstractions.csproj @@ -0,0 +1,13 @@ + + + + net9.0 + enable + enable + + + + + + + diff --git a/Verz/Sdks/MintPlayer.Verz.Sdk.Nodejs/Extensions.cs b/Verz/Sdks/MintPlayer.Verz.Sdk.Nodejs/Extensions.cs new file mode 100644 index 00000000..b9d899ed --- /dev/null +++ b/Verz/Sdks/MintPlayer.Verz.Sdk.Nodejs/Extensions.cs @@ -0,0 +1,11 @@ +using Microsoft.Extensions.DependencyInjection; +using MintPlayer.Verz.Sdk.Nodejs; +using MintPlayer.Verz.Abstractions; + +namespace MintPlayer.Verz; + +public static class Extensions +{ + public static IServiceCollection AddNodejsSDK(this IServiceCollection services) + => services.AddSingleton(); +} diff --git a/Verz/Sdks/MintPlayer.Verz.Sdk.Nodejs/MintPlayer.Verz.Sdk.Nodejs.csproj b/Verz/Sdks/MintPlayer.Verz.Sdk.Nodejs/MintPlayer.Verz.Sdk.Nodejs.csproj new file mode 100644 index 00000000..21f25cfd --- /dev/null +++ b/Verz/Sdks/MintPlayer.Verz.Sdk.Nodejs/MintPlayer.Verz.Sdk.Nodejs.csproj @@ -0,0 +1,17 @@ + + + + net9.0 + enable + enable + + + + + + + + + + + diff --git a/Verz/Sdks/MintPlayer.Verz.Sdk.Nodejs/NodejsSDK.cs b/Verz/Sdks/MintPlayer.Verz.Sdk.Nodejs/NodejsSDK.cs new file mode 100644 index 00000000..cc0c5423 --- /dev/null +++ b/Verz/Sdks/MintPlayer.Verz.Sdk.Nodejs/NodejsSDK.cs @@ -0,0 +1,11 @@ +using MintPlayer.Verz.Abstractions; + +namespace MintPlayer.Verz.Sdk.Nodejs; + +internal class NodejsSDK : IDevelopmentSdk +{ + public Task GetPackageById(string packageId) + { + throw new NotImplementedException(); + } +}