File size: 2,444 Bytes
3ce1a40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
namespace Repoverse.Core.Model;

/// <summary>Stable internal identity for a repository: lower-cased "owner/name".</summary>
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);

/// <summary>
/// GitHub-sourced facts about a repository. Nothing in here is inferred by Repoverse;
/// derived values live in <see cref="DerivedRepository"/> with provenance.
/// </summary>
public sealed record CanonicalRepository
{
    public required RepoId Id { get; init; }
    public string? Description { get; init; }
    public string? PrimaryLanguage { get; init; }
    /// <summary>Bytes of code per language, as reported by GitHub's languages endpoint.</summary>
    public IReadOnlyDictionary<string, long> Languages { get; init; } = new Dictionary<string, long>();
    public IReadOnlyList<string> 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<Release> Releases { get; init; } = [];
    public IReadOnlyList<TreeEntry> Tree { get; init; } = [];
    /// <summary>Other repos in the world this one depends on (from manifests / submodules).</summary>
    public IReadOnlyList<RepoId> DependsOn { get; init; } = [];
    /// <summary>Opaque version marker of the snapshot this record came from (e.g. pushed_at + ETag).</summary>
    public string SnapshotId { get; init; } = "";
}