feat: freeze v1 transport contracts (#4)
quality-gate / quality (push) Successful in 51s

Closes #4
This commit is contained in:
KyuubiYoru
2026-07-16 04:52:38 +02:00
parent e626b89909
commit 69c8b2d2bc
43 changed files with 3737 additions and 12 deletions
@@ -0,0 +1,126 @@
using System.Text.Json.Serialization;
namespace FinalFactory.Rendezvous.Contracts;
[JsonConverter(typeof(GameIdJsonConverter))]
public readonly struct GameId : IEquatable<GameId>
{
public GameId(string value)
{
if (!ContractValidation.IsSlug(value, ContractLimits.GameIdMaxCharacters))
{
throw new ArgumentException("Game IDs must be lowercase URL-safe slugs.", nameof(value));
}
Value = value;
}
public string Value { get; }
public static bool TryParse(string? value, out GameId gameId)
{
if (ContractValidation.IsSlug(value, ContractLimits.GameIdMaxCharacters))
{
gameId = new GameId(value!);
return true;
}
gameId = default;
return false;
}
public bool Equals(GameId other) => string.Equals(Value, other.Value, StringComparison.Ordinal);
public override bool Equals(object? obj) => obj is GameId other && Equals(other);
public override int GetHashCode() => StringComparer.Ordinal.GetHashCode(Value ?? string.Empty);
public override string ToString() => Value ?? string.Empty;
public static bool operator ==(GameId left, GameId right) => left.Equals(right);
public static bool operator !=(GameId left, GameId right) => !left.Equals(right);
}
[JsonConverter(typeof(EnvironmentIdJsonConverter))]
public readonly struct EnvironmentId : IEquatable<EnvironmentId>
{
public EnvironmentId(string value)
{
if (!ContractValidation.IsSlug(value, ContractLimits.EnvironmentIdMaxCharacters))
{
throw new ArgumentException("Environment IDs must be lowercase URL-safe slugs.", nameof(value));
}
Value = value;
}
public string Value { get; }
public static bool TryParse(string? value, out EnvironmentId environmentId)
{
if (ContractValidation.IsSlug(value, ContractLimits.EnvironmentIdMaxCharacters))
{
environmentId = new EnvironmentId(value!);
return true;
}
environmentId = default;
return false;
}
public bool Equals(EnvironmentId other) => string.Equals(Value, other.Value, StringComparison.Ordinal);
public override bool Equals(object? obj) => obj is EnvironmentId other && Equals(other);
public override int GetHashCode() => StringComparer.Ordinal.GetHashCode(Value ?? string.Empty);
public override string ToString() => Value ?? string.Empty;
public static bool operator ==(EnvironmentId left, EnvironmentId right) => left.Equals(right);
public static bool operator !=(EnvironmentId left, EnvironmentId right) => !left.Equals(right);
}
[JsonConverter(typeof(RegionIdJsonConverter))]
public readonly struct RegionId : IEquatable<RegionId>
{
public RegionId(string value)
{
if (!ContractValidation.IsSlug(value, ContractLimits.RegionIdMaxCharacters))
{
throw new ArgumentException("Region IDs must be lowercase URL-safe slugs.", nameof(value));
}
Value = value;
}
public string Value { get; }
public static bool TryParse(string? value, out RegionId regionId)
{
if (ContractValidation.IsSlug(value, ContractLimits.RegionIdMaxCharacters))
{
regionId = new RegionId(value!);
return true;
}
regionId = default;
return false;
}
public bool Equals(RegionId other) => string.Equals(Value, other.Value, StringComparison.Ordinal);
public override bool Equals(object? obj) => obj is RegionId other && Equals(other);
public override int GetHashCode() => StringComparer.Ordinal.GetHashCode(Value ?? string.Empty);
public override string ToString() => Value ?? string.Empty;
public static bool operator ==(RegionId left, RegionId right) => left.Equals(right);
public static bool operator !=(RegionId left, RegionId right) => !left.Equals(right);
}
internal sealed class GameIdJsonConverter : StringIdentifierJsonConverter<GameId>
{
protected override GameId Parse(string value) => new(value);
protected override string Format(GameId value) => value.Value;
}
internal sealed class EnvironmentIdJsonConverter : StringIdentifierJsonConverter<EnvironmentId>
{
protected override EnvironmentId Parse(string value) => new(value);
protected override string Format(EnvironmentId value) => value.Value;
}
internal sealed class RegionIdJsonConverter : StringIdentifierJsonConverter<RegionId>
{
protected override RegionId Parse(string value) => new(value);
protected override string Format(RegionId value) => value.Value;
}