using System.Text.Json; using System.Text.Json.Serialization; using StellaOps.Symbols.Core.Models; namespace StellaOps.Symbols.Ingestor.Cli; /// /// Writes symbol manifests to various formats. /// public static class ManifestWriter { private static readonly JsonSerializerOptions JsonOptions = new() { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, Converters = { new JsonStringEnumConverter() }, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }; /// /// Writes manifest to JSON file. /// public static async Task WriteJsonAsync( SymbolManifest manifest, string outputDir, CancellationToken cancellationToken = default) { Directory.CreateDirectory(outputDir); var fileName = $"{manifest.DebugId}.symbols.json"; var filePath = Path.Combine(outputDir, fileName); var json = JsonSerializer.Serialize(manifest, JsonOptions); await File.WriteAllTextAsync(filePath, json, cancellationToken).ConfigureAwait(false); return filePath; } /// /// Writes DSSE envelope to file. /// public static async Task WriteDsseAsync( string payload, string payloadType, string signature, string keyId, string outputDir, string debugId, CancellationToken cancellationToken = default) { Directory.CreateDirectory(outputDir); var envelope = new DsseEnvelope { PayloadType = payloadType, Payload = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(payload)), Signatures = [ new DsseSignature { KeyId = keyId, Sig = signature } ] }; var fileName = $"{debugId}.symbols.dsse.json"; var filePath = Path.Combine(outputDir, fileName); var json = JsonSerializer.Serialize(envelope, JsonOptions); await File.WriteAllTextAsync(filePath, json, cancellationToken).ConfigureAwait(false); return filePath; } /// /// Reads manifest from JSON file. /// public static async Task ReadJsonAsync( string filePath, CancellationToken cancellationToken = default) { var json = await File.ReadAllTextAsync(filePath, cancellationToken).ConfigureAwait(false); return JsonSerializer.Deserialize(json, JsonOptions); } } /// /// DSSE envelope structure. /// public sealed class DsseEnvelope { [JsonPropertyName("payloadType")] public string PayloadType { get; set; } = string.Empty; [JsonPropertyName("payload")] public string Payload { get; set; } = string.Empty; [JsonPropertyName("signatures")] public List Signatures { get; set; } = []; } /// /// DSSE signature. /// public sealed class DsseSignature { [JsonPropertyName("keyid")] public string KeyId { get; set; } = string.Empty; [JsonPropertyName("sig")] public string Sig { get; set; } = string.Empty; }