forked from williamboman/mason-lspconfig.nvim
-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.lua
117 lines (101 loc) · 4.22 KB
/
client.lua
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
117
local _ = require "mason-core.functional"
local log = require "mason-core.log"
local fetch = require "mason-core.fetch"
local spawn = require "mason-core.spawn"
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}
---@param path string
---@return Result: JSON decoded response.
local function api_call(path)
return spawn
.gh({ "api", path })
: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
---@async
---@param repo string: The GitHub repo ("username/repo").
---@return Result: of GitHubRelease[]
function M.fetch_releases(repo)
log.fmt_trace("Fetching GitHub releases for repo=%s", repo)
local path = ("repos/%s/releases"):format(repo)
return 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 api_call(path):map_err(function()
return ("Failed to fetch release %q for GitHub repository %s."):format(tag_name, repo)
end)
end
---@param opts {include_prerelease: boolean, tag_name_pattern: string}
function M.release_predicate(opts)
local is_not_draft = _.prop_eq("draft", false)
local is_not_prerelease = _.prop_eq("prerelease", false)
local tag_name_matches = _.prop_satisfies(_.matches(opts.tag_name_pattern), "tag_name")
return _.all_pass {
_.if_else(_.always(opts.include_prerelease), _.T, is_not_prerelease),
_.if_else(_.always(opts.tag_name_pattern), tag_name_matches, _.T),
is_not_draft,
}
end
---@alias FetchLatestGithubReleaseOpts {tag_name_pattern:string|nil, include_prerelease: boolean}
---@async
---@param repo string: The GitHub repo ("username/repo").
---@param opts FetchLatestGithubReleaseOpts|nil
---@return Result: of GitHubRelease
function M.fetch_latest_release(repo, opts)
opts = opts or {
tag_name_pattern = nil,
include_prerelease = false,
}
return M.fetch_releases(repo):map_catching(
---@param releases GitHubRelease[]
function(releases)
local is_stable_release = M.release_predicate(opts)
---@type GitHubRelease|nil
local latest_release = _.find_first(is_stable_release, releases)
if not latest_release then
log.fmt_info("Failed to find latest release. repo=%s, opts=%s", repo, opts)
error "Failed to find latest release."
end
log.fmt_debug("Resolved latest version repo=%s, tag_name=%s", repo, latest_release.tag_name)
return latest_release
end
)
end
---@async
---@param repo string: The GitHub repo ("username/repo").
---@return Result: of GitHubTag[]
function M.fetch_tags(repo)
local path = ("repos/%s/tags"):format(repo)
return 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)
-- https://github.com/williamboman/vercel-github-api-latest-tag-proxy
return fetch(("https://latest-github-tag.redwill.se/api/latest-tag?repo=%s"):format(repo))
:map_catching(vim.json.decode)
:map(_.prop "tag")
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 api_call "rate_limit"
end
return M