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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
local _ = require "mason-core.functional"
local fetch = require "mason-core.fetch"
local api = {}
-- https://github.com/mason-org/mason-registry-api
local BASE_URL = "https://api.mason-registry.dev"
local stringify_params = _.compose(_.join "&", _.map(_.join "="), _.sort_by(_.head), _.to_pairs)
---@alias ApiFetchOpts { params: table<string, any>? }
---@async
---@param path string
---@param opts ApiFetchOpts?
---@return Result # JSON decoded response.
function api.get(path, opts)
if opts and opts.params then
local params = stringify_params(opts.params)
path = ("%s?%s"):format(path, params)
end
return fetch(("%s%s"):format(BASE_URL, path), {
headers = {
Accept = "application/vnd.mason-registry.v1+json; q=1.0, application/json; q=0.8",
},
}):map_catching(vim.json.decode)
end
---@alias ApiSignature<T> async fun(path_params: T, opts?: ApiFetchOpts): Result
---@param char string
local function percent_encode(char)
return ("%%%x"):format(string.byte(char, 1, 1))
end
api.encode_uri_component = _.gsub("[!#%$&'%(%)%*%+,/:;=%?@%[%]]", percent_encode)
---@param path_template string
local function get(path_template)
---@async
---@param path_params table
---@param opts ApiFetchOpts?
return function(path_params, opts)
local path = path_template:gsub("{([%w_%.0-9]+)}", function(prop)
return path_params[prop]
end)
-- This is done so that test stubs trigger as expected (you have to explicitly match against nil arguments)
if opts then
return api.get(path, opts)
else
return api.get(path)
end
end
end
api.github = {
releases = {
---@type ApiSignature<{ repo: string }>
latest = get "/api/github/{repo}/releases/latest",
---@type ApiSignature<{ repo: string }>
all = get "/api/github/{repo}/releases/all",
},
tags = {
---@type ApiSignature<{ repo: string }>
latest = get "/api/github/{repo}/tags/latest",
---@type ApiSignature<{ repo: string }>
all = get "/api/github/{repo}/tags/all",
},
}
api.npm = {
versions = {
---@type ApiSignature<{ package: string }>
latest = get "/api/npm/{package}/versions/latest",
---@type ApiSignature<{ package: string }>
all = get "/api/npm/{package}/versions/all",
},
}
api.pypi = {
versions = {
---@type ApiSignature<{ package: string }>
latest = get "/api/pypi/{package}/versions/latest",
---@type ApiSignature<{ package: string }>
all = get "/api/pypi/{package}/versions/all",
---@type ApiSignature<{ package: string, version: string }>
get = get "/api/pypi/{package}/versions/{version}",
},
}
api.rubygems = {
versions = {
---@type ApiSignature<{ gem: string }>
latest = get "/api/rubygems/{gem}/versions/latest",
---@type ApiSignature<{ gem: string }>
all = get "/api/rubygems/{gem}/versions/all",
},
}
api.packagist = {
versions = {
---@type ApiSignature<{ pkg: string }>
latest = get "/api/packagist/{pkg}/versions/latest",
---@type ApiSignature<{ pkg: string }>
all = get "/api/packagist/{pkg}/versions/all",
},
}
api.crate = {
versions = {
---@type ApiSignature<{ crate: string }>
latest = get "/api/crate/{crate}/versions/latest",
---@type ApiSignature<{ crate: string }>
all = get "/api/crate/{crate}/versions/all",
},
}
api.golang = {
versions = {
---@type ApiSignature<{ pkg: string }>
all = get "/api/golang/{pkg}/versions/all",
},
}
api.openvsx = {
versions = {
---@type ApiSignature<{ namespace: string, extension: string }>
latest = get "/api/openvsx/{namespace}/{extension}/versions/latest",
---@type ApiSignature<{ namespace: string, extension: string }>
all = get "/api/openvsx/{namespace}/{extension}/versions/all",
},
}
return api
|