tools/code/common/ApiRelease.cs (162 lines of code) (raw):
using Azure.Core.Pipeline;
using Flurl;
using LanguageExt;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
namespace common;
public sealed record ApiReleaseName : ResourceName
{
private ApiReleaseName(string value) : base(value) { }
public static ApiReleaseName From(string value) => new(value);
}
public sealed record ApiReleasesUri : ResourceUri
{
public required ApiUri Parent { get; init; }
private static string PathSegment { get; } = "releases";
protected override Uri Value => Parent.ToUri().AppendPathSegment(PathSegment).ToUri();
public static ApiReleasesUri From(ApiName name, ManagementServiceUri serviceUri) =>
new() { Parent = ApiUri.From(name, serviceUri) };
}
public sealed record ApiReleaseUri : ResourceUri
{
public required ApiReleasesUri Parent { get; init; }
public required ApiReleaseName Name { get; init; }
protected override Uri Value => Parent.ToUri().AppendPathSegment(Name.ToString()).ToUri();
public static ApiReleaseUri From(ApiReleaseName name, ApiName apiName, ManagementServiceUri serviceUri) =>
new()
{
Parent = ApiReleasesUri.From(apiName, serviceUri),
Name = name
};
}
public sealed record ApiReleasesDirectory : ResourceDirectory
{
public required ApiDirectory Parent { get; init; }
private static string Name { get; } = "releases";
protected override DirectoryInfo Value =>
Parent.ToDirectoryInfo().GetChildDirectory(Name);
public static ApiReleasesDirectory From(ApiName name, ManagementServiceDirectory serviceDirectory) =>
new() { Parent = ApiDirectory.From(name, serviceDirectory) };
public static Option<ApiReleasesDirectory> TryParse(DirectoryInfo? directory, ManagementServiceDirectory serviceDirectory) =>
directory is not null && directory.Name == Name
? from parent in ApiDirectory.TryParse(directory.Parent, serviceDirectory)
select new ApiReleasesDirectory { Parent = parent }
: Option<ApiReleasesDirectory>.None;
}
public sealed record ApiReleaseDirectory : ResourceDirectory
{
public required ApiReleasesDirectory Parent { get; init; }
public required ApiReleaseName Name { get; init; }
protected override DirectoryInfo Value =>
Parent.ToDirectoryInfo().GetChildDirectory(Name.ToString());
public static ApiReleaseDirectory From(ApiReleaseName name, ApiName apiName, ManagementServiceDirectory serviceDirectory) =>
new()
{
Parent = ApiReleasesDirectory.From(apiName, serviceDirectory),
Name = name
};
public static Option<ApiReleaseDirectory> TryParse(DirectoryInfo? directory, ManagementServiceDirectory serviceDirectory) =>
from parent in ApiReleasesDirectory.TryParse(directory?.Parent, serviceDirectory)
select new ApiReleaseDirectory
{
Parent = parent,
Name = ApiReleaseName.From(directory!.Name)
};
}
public sealed record ApiReleaseInformationFile : ResourceFile
{
public required ApiReleaseDirectory Parent { get; init; }
private static string Name { get; } = "apiReleaseInformation.json";
protected override FileInfo Value =>
Parent.ToDirectoryInfo().GetChildFile(Name);
public static ApiReleaseInformationFile From(ApiReleaseName name, ApiName apiName, ManagementServiceDirectory serviceDirectory) =>
new()
{
Parent = ApiReleaseDirectory.From(name, apiName, serviceDirectory)
};
public static Option<ApiReleaseInformationFile> TryParse(FileInfo? file, ManagementServiceDirectory serviceDirectory) =>
file is not null && file.Name == Name
? from parent in ApiReleaseDirectory.TryParse(file.Directory, serviceDirectory)
select new ApiReleaseInformationFile { Parent = parent }
: Option<ApiReleaseInformationFile>.None;
}
public sealed record ApiReleaseDto
{
[JsonPropertyName("properties")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public required ApiReleaseContract Properties { get; init; }
public record ApiReleaseContract
{
[JsonPropertyName("apiId")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string? ApiId { get; init; }
[JsonPropertyName("notes")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string? Notes { get; init; }
}
}
public static class ApiReleaseModule
{
public static async ValueTask DeleteAll(this ApiReleasesUri uri, HttpPipeline pipeline, CancellationToken cancellationToken) =>
await uri.ListNames(pipeline, cancellationToken)
.IterParallel(async name => await ApiReleaseUri.From(name, uri.Parent.Name, uri.Parent.Parent.ServiceUri)
.Delete(pipeline, cancellationToken),
cancellationToken);
public static IAsyncEnumerable<ApiReleaseName> ListNames(this ApiReleasesUri uri, HttpPipeline pipeline, CancellationToken cancellationToken) =>
pipeline.ListJsonObjects(uri.ToUri(), cancellationToken)
.Select(jsonObject => jsonObject.GetStringProperty("name"))
.Select(ApiReleaseName.From);
public static IAsyncEnumerable<(ApiReleaseName Name, ApiReleaseDto Dto)> List(this ApiReleasesUri apiReleasesUri, HttpPipeline pipeline, CancellationToken cancellationToken) =>
apiReleasesUri.ListNames(pipeline, cancellationToken)
.SelectAwait(async name =>
{
var uri = ApiReleaseUri.From(name, apiReleasesUri.Parent.Name, apiReleasesUri.Parent.Parent.ServiceUri);
var dto = await uri.GetDto(pipeline, cancellationToken);
return (name, dto);
});
public static async ValueTask<ApiReleaseDto> GetDto(this ApiReleaseUri uri, HttpPipeline pipeline, CancellationToken cancellationToken)
{
var content = await pipeline.GetContent(uri.ToUri(), cancellationToken);
return content.ToObjectFromJson<ApiReleaseDto>();
}
public static async ValueTask Delete(this ApiReleaseUri uri, HttpPipeline pipeline, CancellationToken cancellationToken) =>
await pipeline.DeleteResource(uri.ToUri(), waitForCompletion: true, cancellationToken);
public static async ValueTask PutDto(this ApiReleaseUri uri, ApiReleaseDto dto, HttpPipeline pipeline, CancellationToken cancellationToken)
{
var content = BinaryData.FromObjectAsJson(dto);
await pipeline.PutContent(uri.ToUri(), content, cancellationToken);
}
public static IEnumerable<ApiReleaseDirectory> ListDirectories(ApiName apiName, ManagementServiceDirectory serviceDirectory) =>
ApiReleasesDirectory.From(apiName, serviceDirectory)
.ToDirectoryInfo()
.ListDirectories("*")
.Select(directory => ApiReleaseName.From(directory.Name))
.Select(releaseName => ApiReleaseDirectory.From(releaseName, apiName, serviceDirectory));
public static IEnumerable<ApiReleaseDirectory> ListDirectories(ManagementServiceDirectory serviceDirectory) =>
ApiModule.ListDirectories(serviceDirectory)
.Select(apiDirectory => apiDirectory.Name)
.SelectMany(apiName => ListDirectories(apiName, serviceDirectory));
public static IEnumerable<ApiReleaseInformationFile> ListInformationFiles(ApiName apiName, ManagementServiceDirectory serviceDirectory) =>
ListDirectories(apiName, serviceDirectory)
.Select(directory => new ApiReleaseInformationFile { Parent = directory })
.Where(informationFile => informationFile.ToFileInfo().Exists());
public static IEnumerable<ApiReleaseInformationFile> ListInformationFiles(ManagementServiceDirectory serviceDirectory) =>
ApiModule.ListDirectories(serviceDirectory)
.Select(apiDirectory => apiDirectory.Name)
.SelectMany(apiName => ListInformationFiles(apiName, serviceDirectory));
public static async ValueTask WriteDto(this ApiReleaseInformationFile file, ApiReleaseDto dto, CancellationToken cancellationToken)
{
var content = BinaryData.FromObjectAsJson(dto, JsonObjectExtensions.SerializerOptions);
await file.ToFileInfo().OverwriteWithBinaryData(content, cancellationToken);
}
public static async ValueTask<ApiReleaseDto> ReadDto(this ApiReleaseInformationFile file, CancellationToken cancellationToken)
{
var content = await file.ToFileInfo().ReadAsBinaryData(cancellationToken);
return content.ToObjectFromJson<ApiReleaseDto>();
}
}