using System.Text.Json; namespace Sdt.Config; public static class WorkspaceLoader { private const string FileName = "sdt-workspace.json"; private static readonly JsonSerializerOptions JsonOptions = new() { PropertyNameCaseInsensitive = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, AllowTrailingCommas = true, ReadCommentHandling = JsonCommentHandling.Skip, }; /// /// Walks up from (or CWD) to find sdt-workspace.json. /// Returns null if not found. /// public static (WorkspaceConfig Config, string WorkspaceRoot)? FindAndLoad(string? startDir = null) { var dir = new DirectoryInfo(startDir ?? Directory.GetCurrentDirectory()); while (dir is not null) { var candidate = Path.Combine(dir.FullName, FileName); if (File.Exists(candidate)) { try { var json = File.ReadAllText(candidate); var config = JsonSerializer.Deserialize(json, JsonOptions) ?? throw new InvalidOperationException($"{FileName} deserialized to null."); return (config, dir.FullName); } catch (Exception ex) { throw new InvalidOperationException( $"Failed to parse {FileName} at {candidate}: {ex.Message}", ex); } } dir = dir.Parent!; } return null; } /// /// Resolves the absolute project root for a workspace project entry. /// public static string ResolveProjectRoot(string workspaceRoot, WorkspaceProject project) => Path.GetFullPath(Path.Combine(workspaceRoot, project.Path)); }