namespace Repoverse.Core.Model; /// Stable internal identity for a repository: lower-cased "owner/name". public readonly record struct RepoId(string Owner, string Name) { public string Key => $"{Owner.ToLowerInvariant()}/{Name.ToLowerInvariant()}"; public override string ToString() => Key; public static RepoId Parse(string fullName) { var slash = fullName.IndexOf('/'); if (slash <= 0 || slash == fullName.Length - 1) throw new FormatException($"Expected 'owner/name', got '{fullName}'."); return new RepoId(fullName[..slash], fullName[(slash + 1)..]); } } public enum TreeEntryKind { File, Directory } public sealed record TreeEntry(string Path, TreeEntryKind Kind, long SizeBytes); public sealed record Release(string Tag, DateTimeOffset PublishedAt, bool Prerelease); /// /// GitHub-sourced facts about a repository. Nothing in here is inferred by Repoverse; /// derived values live in with provenance. /// public sealed record CanonicalRepository { public required RepoId Id { get; init; } public string? Description { get; init; } public string? PrimaryLanguage { get; init; } /// Bytes of code per language, as reported by GitHub's languages endpoint. public IReadOnlyDictionary Languages { get; init; } = new Dictionary(); public IReadOnlyList Topics { get; init; } = []; public long SizeKb { get; init; } public bool Archived { get; init; } public bool Fork { get; init; } public string DefaultBranch { get; init; } = "main"; public DateTimeOffset CreatedAt { get; init; } public DateTimeOffset PushedAt { get; init; } public string? License { get; init; } public int OpenIssues { get; init; } public int OpenPullRequests { get; init; } public int Contributors { get; init; } public int CommitsLast90Days { get; init; } public IReadOnlyList Releases { get; init; } = []; public IReadOnlyList Tree { get; init; } = []; /// Other repos in the world this one depends on (from manifests / submodules). public IReadOnlyList DependsOn { get; init; } = []; /// Opaque version marker of the snapshot this record came from (e.g. pushed_at + ETag). public string SnapshotId { get; init; } = ""; }