using System; using System.Collections.Generic; using Codely.Newtonsoft.Json.Linq; using UnityTcp.Editor.Helpers; using UnityTcp.Editor.Tools.Jobs; namespace UnityTcp.Editor.Tools { /// /// [EXPERIMENTAL] Handles Unity Package Manager (UPM) operations. /// Supports installing, removing, and querying packages. /// Compatible with Unity 2022.3 LTS. /// /// Every action runs as a and answers only when the operation has /// actually finished — see for why installing and removing cannot be /// tracked any other way (UPM reloads the domain, which used to destroy the in-flight request /// and its update callback and strand the job as Pending). /// public static class ManagePackage { // UPM resolution reloads the domain, so the whole operation runs as a StepJob and answers // once it has actually finished. 300s covers a registry fetch plus the reload it triggers. private const int DefaultTimeoutSeconds = 300; private static object Run(StepJob job, JObject @params) => StepJobRunner.Start( CommandContext.RequestId, CommandContext.CommandType, job, @params["timeoutSeconds"]?.ToObject() ?? DefaultTimeoutSeconds); private static readonly Dictionary> ActionHandlers = new Dictionary> { { "install_package", InstallPackage }, { "remove_package", RemovePackage }, { "list_packages", p => Run(new ListPackagesJob(), p) }, }; public static object HandleCommand(JObject @params) => ActionRouter.Route(@params, ActionHandlers); private static object InstallPackage(JObject @params) { string idOrUrl = @params["id_or_url"]?.ToString(); string version = @params["version"]?.ToString(); // "com.unity.package" + "1.2.3" -> "com.unity.package@1.2.3" if (!string.IsNullOrEmpty(version) && !string.IsNullOrEmpty(idOrUrl) && !idOrUrl.Contains("@") && !idOrUrl.StartsWith("http")) { idOrUrl = $"{idOrUrl}@{version}"; } return Run(new UpmJob { Remove = false, Target = idOrUrl, PackageName = UpmJob.RegistryNameOf(idOrUrl), }, @params); } private static object RemovePackage(JObject @params) { string packageName = @params["package_name"]?.ToString(); return Run(new UpmJob { Remove = true, Target = packageName, PackageName = packageName, }, @params); } } }