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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
local _ = require "mason-core.functional"
local log = require "mason-core.log"
local fetch = require "mason-core.fetch"
local spawn = require "mason-core.spawn"
local api = require "mason-registry.api"
local M = {}
---@alias GitHubReleaseAsset {url: string, id: integer, name: string, browser_download_url: string, created_at: string, updated_at: string, size: integer, download_count: integer}
---@alias GitHubRelease {tag_name: string, prerelease: boolean, draft: boolean, assets:GitHubReleaseAsset[]}
---@alias GitHubTag {name: string}
---@alias GitHubCommit {sha: string}
local stringify_params = _.compose(_.join "&", _.map(_.join "="), _.sort_by(_.head), _.to_pairs)
---@param path string
---@param opts { params: table<string, any>? }?
---@return Result # JSON decoded response.
local function gh_api_call(path, opts)
if opts and opts.params then
local params = stringify_params(opts.params)
path = ("%s?%s"):format(path, params)
end
return spawn
.gh({ "api", path, env = { CLICOLOR_FORCE = 0 } })
:map(_.prop "stdout")
:recover_catching(function()
return fetch(("https://api.github.com/%s"):format(path)):get_or_throw()
end)
:map_catching(vim.json.decode)
end
M.api_call = gh_api_call
---@async
---@param repo string The GitHub repo ("username/repo").
---@return Result # Result<GitHubRelease[]>
function M.fetch_releases(repo)
log.fmt_trace("Fetching GitHub releases for repo=%s", repo)
local path = ("repos/%s/releases"):format(repo)
return gh_api_call(path):map_err(function()
return ("Failed to fetch releases for GitHub repository %s."):format(repo)
end)
end
---@async
---@param repo string The GitHub repo ("username/repo").
---@param tag_name string The tag_name of the release to fetch.
function M.fetch_release(repo, tag_name)
log.fmt_trace("Fetching GitHub release for repo=%s, tag_name=%s", repo, tag_name)
local path = ("repos/%s/releases/tags/%s"):format(repo, tag_name)
return gh_api_call(path):map_err(function()
return ("Failed to fetch release %q for GitHub repository %s."):format(tag_name, repo)
end)
end
---@alias FetchLatestGithubReleaseOpts {include_prerelease: boolean}
---@async
---@param repo string The GitHub repo ("username/repo").
---@param opts FetchLatestGithubReleaseOpts?
---@return Result # Result<GitHubRelease>
function M.fetch_latest_release(repo, opts)
opts = opts or { include_prerelease = false }
local path = ("/api/repo/%s/latest-release"):format(repo)
return api.get(path, {
params = {
include_prerelease = opts.include_prerelease and "true" or "false",
},
})
end
---@async
---@param repo string The GitHub repo ("username/repo").
---@return Result # Result<GitHubTag[]>
function M.fetch_tags(repo)
local path = ("repos/%s/tags"):format(repo)
return gh_api_call(path):map_err(function()
return ("Failed to fetch tags for GitHub repository %s."):format(repo)
end)
end
---@async
---@param repo string The GitHub repo ("username/repo").
---@return Result # Result<string> The latest tag name.
function M.fetch_latest_tag(repo)
local path = ("/api/repo/%s/latest-tag"):format(repo)
return api.get(path):map(_.prop "tag")
end
---@async
---@param repo string The GitHub repo ("username/repo").
---@param opts { page: integer?, per_page: integer? }?
---@return Result # Result<GitHubCommit[]>
function M.fetch_commits(repo, opts)
local path = ("repos/%s/commits"):format(repo)
return gh_api_call(path, {
params = {
page = opts and opts.page or 1,
per_page = opts and opts.per_page or 30,
},
}):map_err(function()
return ("Failed to fetch commits for GitHub repository %s."):format(repo)
end)
end
---@alias GitHubRateLimit {limit: integer, remaining: integer, reset: integer, used: integer}
---@alias GitHubRateLimitResponse {resources: { core: GitHubRateLimit }}
---@async
--@return Result @of GitHubRateLimitResponse
function M.fetch_rate_limit()
return gh_api_call "rate_limit"
end
return M
|