aboutsummaryrefslogtreecommitdiffstats
path: root/lua
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2024-01-06 09:02:01 +0100
committerGitHub <noreply@github.com>2024-01-06 09:02:01 +0100
commit6c685476df4f202e371bdd3d726729d6f3f8b9f0 (patch)
tree53c96e8418f2669bdd5d345325d8542107d03ea3 /lua
parentfix(cargo): don't attempt to fetch versions when version targets commit SHA (... (diff)
downloadmason-6c685476df4f202e371bdd3d726729d6f3f8b9f0.tar
mason-6c685476df4f202e371bdd3d726729d6f3f8b9f0.tar.gz
mason-6c685476df4f202e371bdd3d726729d6f3f8b9f0.tar.bz2
mason-6c685476df4f202e371bdd3d726729d6f3f8b9f0.tar.lz
mason-6c685476df4f202e371bdd3d726729d6f3f8b9f0.tar.xz
mason-6c685476df4f202e371bdd3d726729d6f3f8b9f0.tar.zst
mason-6c685476df4f202e371bdd3d726729d6f3f8b9f0.zip
feat: add support for openvsx sources (#1589)
Diffstat (limited to 'lua')
-rw-r--r--lua/mason-core/installer/context.lua2
-rw-r--r--lua/mason-core/installer/managers/build.lua48
-rw-r--r--lua/mason-core/installer/managers/common.lua126
-rw-r--r--lua/mason-core/installer/registry/init.lua1
-rw-r--r--lua/mason-core/installer/registry/providers/generic/build.lua6
-rw-r--r--lua/mason-core/installer/registry/providers/generic/download.lua21
-rw-r--r--lua/mason-core/installer/registry/providers/github/build.lua6
-rw-r--r--lua/mason-core/installer/registry/providers/github/release.lua88
-rw-r--r--lua/mason-core/installer/registry/providers/npm.lua1
-rw-r--r--lua/mason-core/installer/registry/providers/openvsx.lua63
-rw-r--r--lua/mason-core/installer/registry/util.lua6
-rw-r--r--lua/mason-core/providers/init.lua5
-rw-r--r--lua/mason-core/semver.lua2
-rw-r--r--lua/mason-registry/api.lua9
-rw-r--r--lua/mason/providers/client/init.lua1
-rw-r--r--lua/mason/providers/client/openvsx.lua26
-rw-r--r--lua/mason/providers/registry-api/init.lua8
17 files changed, 276 insertions, 143 deletions
diff --git a/lua/mason-core/installer/context.lua b/lua/mason-core/installer/context.lua
index b12b540f..7637209f 100644
--- a/lua/mason-core/installer/context.lua
+++ b/lua/mason-core/installer/context.lua
@@ -241,7 +241,7 @@ function InstallContext:promote_cwd()
end
---@param rel_path string The relative path from the current working directory to change cwd to. Will only restore to the initial cwd after execution of fn (if provided).
----@param fn async (fun())? The function to run in the context of the given path.
+---@param fn async (fun(): any)? The function to run in the context of the given path.
function InstallContext:chdir(rel_path, fn)
local old_cwd = self.cwd:get()
self.cwd:set(path.concat { old_cwd, rel_path })
diff --git a/lua/mason-core/installer/managers/build.lua b/lua/mason-core/installer/managers/build.lua
deleted file mode 100644
index a1549a28..00000000
--- a/lua/mason-core/installer/managers/build.lua
+++ /dev/null
@@ -1,48 +0,0 @@
-local _ = require "mason-core.functional"
-local a = require "mason-core.async"
-local async_uv = require "mason-core.async.uv"
-local installer = require "mason-core.installer"
-local log = require "mason-core.log"
-local platform = require "mason-core.platform"
-local powershell = require "mason-core.managers.powershell"
-
-local M = {}
-
----@class BuildInstruction
----@field target? Platform | Platform[]
----@field run string
----@field staged? boolean
----@field env? table<string, string>
-
----@async
----@param build BuildInstruction
----@return Result
----@nodiscard
-function M.run(build)
- log.fmt_debug("build: run %s", build)
- local ctx = installer.context()
- if build.staged == false then
- ctx:promote_cwd()
- end
- return platform.when {
- unix = function()
- return ctx.spawn.bash {
- on_spawn = a.scope(function(_, stdio)
- local stdin = stdio[1]
- async_uv.write(stdin, "set -euxo pipefail;\n")
- async_uv.write(stdin, build.run)
- async_uv.shutdown(stdin)
- async_uv.close(stdin)
- end),
- env = build.env,
- }
- end,
- win = function()
- return powershell.command(build.run, {
- env = build.env,
- }, ctx.spawn)
- end,
- }
-end
-
-return M
diff --git a/lua/mason-core/installer/managers/common.lua b/lua/mason-core/installer/managers/common.lua
new file mode 100644
index 00000000..c730a3aa
--- /dev/null
+++ b/lua/mason-core/installer/managers/common.lua
@@ -0,0 +1,126 @@
+local Result = require "mason-core.result"
+local _ = require "mason-core.functional"
+local a = require "mason-core.async"
+local async_uv = require "mason-core.async.uv"
+local installer = require "mason-core.installer"
+local log = require "mason-core.log"
+local platform = require "mason-core.platform"
+local powershell = require "mason-core.managers.powershell"
+local std = require "mason-core.installer.managers.std"
+
+local M = {}
+
+---@class DownloadItem
+---@field download_url string
+---@field out_file string
+
+---@class FileDownloadSpec
+---@field file string | string[]
+
+local get_source_file = _.compose(_.head, _.split ":")
+local get_outfile = _.compose(_.last, _.split ":")
+
+---Normalizes file paths from e.g. "file:out-dir/" to "out-dir/file".
+---@param file string
+local function normalize_file_path(file)
+ local source_file = get_source_file(file)
+ local new_path = get_outfile(file)
+
+ -- a dir expression (e.g. "libexec/")
+ if _.matches("/$", new_path) then
+ return new_path .. source_file
+ end
+ return new_path
+end
+
+---@generic T : FileDownloadSpec
+---@type fun(download: T): T
+M.normalize_files = _.evolve {
+ file = _.cond {
+ { _.is "string", normalize_file_path },
+ { _.T, _.map(normalize_file_path) },
+ },
+}
+
+---@param download FileDownloadSpec
+---@param url_generator fun(file: string): string
+---@return DownloadItem[]
+function M.parse_downloads(download, url_generator)
+ local files = download.file
+ if type(files) == "string" then
+ files = { files }
+ end
+
+ return _.map(function(file)
+ local source_file = get_source_file(file)
+ local out_file = normalize_file_path(file)
+ return {
+ download_url = url_generator(source_file),
+ out_file = out_file,
+ }
+ end, files)
+end
+
+---@async
+---@param ctx InstallContext
+---@param downloads DownloadItem[]
+---@nodiscard
+function M.download_files(ctx, downloads)
+ return Result.try(function(try)
+ for __, download in ipairs(downloads) do
+ a.scheduler()
+ local out_dir = vim.fn.fnamemodify(download.out_file, ":h")
+ local out_file = vim.fn.fnamemodify(download.out_file, ":t")
+ if out_dir ~= "." then
+ try(Result.pcall(function()
+ ctx.fs:mkdirp(out_dir)
+ end))
+ end
+ try(ctx:chdir(out_dir, function()
+ return Result.try(function(try)
+ try(std.download_file(download.download_url, out_file))
+ try(std.unpack(out_file))
+ end)
+ end))
+ end
+ end)
+end
+
+---@class BuildInstruction
+---@field target? Platform | Platform[]
+---@field run string
+---@field staged? boolean
+---@field env? table<string, string>
+
+---@async
+---@param build BuildInstruction
+---@return Result
+---@nodiscard
+function M.run_build_instruction(build)
+ log.fmt_debug("build: run %s", build)
+ local ctx = installer.context()
+ if build.staged == false then
+ ctx:promote_cwd()
+ end
+ return platform.when {
+ unix = function()
+ return ctx.spawn.bash {
+ on_spawn = a.scope(function(_, stdio)
+ local stdin = stdio[1]
+ async_uv.write(stdin, "set -euxo pipefail;\n")
+ async_uv.write(stdin, build.run)
+ async_uv.shutdown(stdin)
+ async_uv.close(stdin)
+ end),
+ env = build.env,
+ }
+ end,
+ win = function()
+ return powershell.command(build.run, {
+ env = build.env,
+ }, ctx.spawn)
+ end,
+ }
+end
+
+return M
diff --git a/lua/mason-core/installer/registry/init.lua b/lua/mason-core/installer/registry/init.lua
index 0cec2161..e97a8430 100644
--- a/lua/mason-core/installer/registry/init.lua
+++ b/lua/mason-core/installer/registry/init.lua
@@ -33,6 +33,7 @@ M.register_provider("luarocks", _.lazy_require "mason-core.installer.registry.pr
M.register_provider("npm", _.lazy_require "mason-core.installer.registry.providers.npm")
M.register_provider("nuget", _.lazy_require "mason-core.installer.registry.providers.nuget")
M.register_provider("opam", _.lazy_require "mason-core.installer.registry.providers.opam")
+M.register_provider("openvsx", _.lazy_require "mason-core.installer.registry.providers.openvsx")
M.register_provider("pypi", _.lazy_require "mason-core.installer.registry.providers.pypi")
---@param purl Purl
diff --git a/lua/mason-core/installer/registry/providers/generic/build.lua b/lua/mason-core/installer/registry/providers/generic/build.lua
index 6d2769e1..a0d517d8 100644
--- a/lua/mason-core/installer/registry/providers/generic/build.lua
+++ b/lua/mason-core/installer/registry/providers/generic/build.lua
@@ -1,6 +1,6 @@
local Result = require "mason-core.result"
local _ = require "mason-core.functional"
-local build = require "mason-core.installer.managers.build"
+local common = require "mason-core.installer.managers.common"
local expr = require "mason-core.installer.registry.expr"
local util = require "mason-core.installer.registry.util"
@@ -15,7 +15,7 @@ local M = {}
function M.parse(source, purl, opts)
return Result.try(function(try)
---@type BuildInstruction
- local build_instruction = try(util.coalesce_by_target(source.build, opts):ok_or "PLATFORM_UNSUPPORTED")
+ local build_instruction = try(util.coalesce_by_target(source.build, opts))
if build_instruction.env then
local expr_ctx = { version = purl.version, target = build_instruction.target }
@@ -34,7 +34,7 @@ end
---@param ctx InstallContext
---@param source ParsedGenericBuildSource
function M.install(ctx, source)
- return build.run(source.build)
+ return common.run_build_instruction(source.build)
end
return M
diff --git a/lua/mason-core/installer/registry/providers/generic/download.lua b/lua/mason-core/installer/registry/providers/generic/download.lua
index a7e4d046..4622a844 100644
--- a/lua/mason-core/installer/registry/providers/generic/download.lua
+++ b/lua/mason-core/installer/registry/providers/generic/download.lua
@@ -1,5 +1,6 @@
local Result = require "mason-core.result"
local _ = require "mason-core.functional"
+local common = require "mason-core.installer.managers.common"
local expr = require "mason-core.installer.registry.expr"
local util = require "mason-core.installer.registry.util"
@@ -17,15 +18,25 @@ local M = {}
---@param opts PackageInstallOpts
function M.parse(source, purl, opts)
return Result.try(function(try)
- local download = try(util.coalesce_by_target(source.download, opts):ok_or "PLATFORM_UNSUPPORTED")
+ local download = try(util.coalesce_by_target(source.download, opts))
local expr_ctx = { version = purl.version }
---@type { files: table<string, string> }
local interpolated_download = try(expr.tbl_interpolate(download, expr_ctx))
+ ---@type DownloadItem[]
+ local downloads = _.map(function(pair)
+ ---@type DownloadItem
+ return {
+ out_file = pair[1],
+ download_url = pair[2],
+ }
+ end, _.to_pairs(interpolated_download.files))
+
---@class ParsedGenericDownloadSource : ParsedPackageSource
local parsed_source = {
download = interpolated_download,
+ downloads = downloads,
}
return parsed_source
end)
@@ -35,13 +46,7 @@ end
---@param ctx InstallContext
---@param source ParsedGenericDownloadSource
function M.install(ctx, source)
- local std = require "mason-core.installer.managers.std"
- return Result.try(function(try)
- for out_file, url in pairs(source.download.files) do
- try(std.download_file(url, out_file))
- try(std.unpack(out_file))
- end
- end)
+ return common.download_files(ctx, source.downloads)
end
return M
diff --git a/lua/mason-core/installer/registry/providers/github/build.lua b/lua/mason-core/installer/registry/providers/github/build.lua
index bda0b655..1c17bb1a 100644
--- a/lua/mason-core/installer/registry/providers/github/build.lua
+++ b/lua/mason-core/installer/registry/providers/github/build.lua
@@ -1,6 +1,6 @@
local Result = require "mason-core.result"
local _ = require "mason-core.functional"
-local build = require "mason-core.installer.managers.build"
+local common = require "mason-core.installer.managers.common"
local expr = require "mason-core.installer.registry.expr"
local util = require "mason-core.installer.registry.util"
@@ -15,7 +15,7 @@ local M = {}
function M.parse(source, purl, opts)
return Result.try(function(try)
---@type BuildInstruction
- local build_instruction = try(util.coalesce_by_target(source.build, opts):ok_or "PLATFORM_UNSUPPORTED")
+ local build_instruction = try(util.coalesce_by_target(source.build, opts))
local expr_ctx = { version = purl.version }
@@ -44,7 +44,7 @@ function M.install(ctx, source)
local std = require "mason-core.installer.managers.std"
return Result.try(function(try)
try(std.clone(source.repo, { rev = source.rev }))
- try(build.run(source.build))
+ try(common.run_build_instruction(source.build))
end)
end
diff --git a/lua/mason-core/installer/registry/providers/github/release.lua b/lua/mason-core/installer/registry/providers/github/release.lua
index 5fe95cab..8c8a8a8f 100644
--- a/lua/mason-core/installer/registry/providers/github/release.lua
+++ b/lua/mason-core/installer/registry/providers/github/release.lua
@@ -1,17 +1,13 @@
local Result = require "mason-core.result"
local _ = require "mason-core.functional"
-local a = require "mason-core.async"
+local common = require "mason-core.installer.managers.common"
local expr = require "mason-core.installer.registry.expr"
local providers = require "mason-core.providers"
local settings = require "mason.settings"
local util = require "mason-core.installer.registry.util"
----@class GitHubReleaseAsset
----@field target? Platform | Platform[]
----@field file string | string[]
-
---@class GitHubReleaseSource : RegistryPackageSource
----@field asset GitHubReleaseAsset | GitHubReleaseAsset[]
+---@field asset FileDownloadSpec | FileDownloadSpec[]
local M = {}
@@ -20,63 +16,22 @@ local M = {}
---@param opts PackageInstallOpts
function M.parse(source, purl, opts)
return Result.try(function(try)
- local asset = try(util.coalesce_by_target(source.asset, opts):ok_or "PLATFORM_UNSUPPORTED")
-
local expr_ctx = { version = purl.version }
+ ---@type FileDownloadSpec
+ local asset = try(util.coalesce_by_target(try(expr.tbl_interpolate(source.asset, expr_ctx)), opts))
- ---@type { out_file: string, download_url: string }[]
- local downloads = {}
-
- local interpolated_asset = try(expr.tbl_interpolate(asset, expr_ctx))
-
- ---@param file string
- ---@return Result # Result<{ source_file: string, out_file: string }>
- local function parse_asset_file(file)
- return Result.try(function(try)
- local asset_file_components = _.split(":", file)
- local source_file = try(expr.interpolate(_.head(asset_file_components), expr_ctx))
- local out_file = try(expr.interpolate(_.last(asset_file_components), expr_ctx))
-
- if _.matches("/$", out_file) then
- -- out_file is a dir expression (e.g. "libexec/")
- out_file = out_file .. source_file
- end
-
- return {
- source_file = source_file,
- out_file = out_file,
- }
- end)
- end
-
- local get_downloads = _.map(function(asset_file)
- return {
- out_file = asset_file.out_file,
- download_url = settings.current.github.download_url_template:format(
- ("%s/%s"):format(purl.namespace, purl.name),
- purl.version,
- asset_file.source_file
- ),
- }
+ local downloads = common.parse_downloads(asset, function(file)
+ return settings.current.github.download_url_template:format(
+ ("%s/%s"):format(purl.namespace, purl.name),
+ purl.version,
+ file
+ )
end)
- if type(asset.file) == "string" then
- local parsed_asset_file = try(parse_asset_file(asset.file))
- downloads = get_downloads { parsed_asset_file }
- interpolated_asset.file = parsed_asset_file.out_file
- else
- local parsed_asset_files = {}
- for _, file in ipairs(asset.file) do
- table.insert(parsed_asset_files, try(parse_asset_file(file)))
- end
- downloads = get_downloads(parsed_asset_files)
- interpolated_asset.file = _.map(_.prop "out_file", parsed_asset_files)
- end
-
---@class ParsedGitHubReleaseSource : ParsedPackageSource
local parsed_source = {
repo = ("%s/%s"):format(purl.namespace, purl.name),
- asset = interpolated_asset,
+ asset = common.normalize_files(asset),
downloads = downloads,
}
return parsed_source
@@ -87,26 +42,7 @@ end
---@param ctx InstallContext
---@param source ParsedGitHubReleaseSource
function M.install(ctx, source)
- local std = require "mason-core.installer.managers.std"
-
- return Result.try(function(try)
- for __, download in ipairs(source.downloads) do
- a.scheduler()
- local out_dir = vim.fn.fnamemodify(download.out_file, ":h")
- local out_file = vim.fn.fnamemodify(download.out_file, ":t")
- if out_dir ~= "." then
- try(Result.pcall(function()
- ctx.fs:mkdirp(out_dir)
- end))
- end
- try(ctx:chdir(out_dir, function()
- return Result.try(function(try)
- try(std.download_file(download.download_url, out_file))
- try(std.unpack(out_file))
- end)
- end))
- end
- end)
+ return common.download_files(ctx, source.downloads)
end
---@async
diff --git a/lua/mason-core/installer/registry/providers/npm.lua b/lua/mason-core/installer/registry/providers/npm.lua
index d1865b96..e8489fe8 100644
--- a/lua/mason-core/installer/registry/providers/npm.lua
+++ b/lua/mason-core/installer/registry/providers/npm.lua
@@ -1,7 +1,6 @@
local Result = require "mason-core.result"
local _ = require "mason-core.functional"
local providers = require "mason-core.providers"
-local util = require "mason-core.installer.registry.util"
---@param purl Purl
local function purl_to_npm(purl)
diff --git a/lua/mason-core/installer/registry/providers/openvsx.lua b/lua/mason-core/installer/registry/providers/openvsx.lua
new file mode 100644
index 00000000..df52807a
--- /dev/null
+++ b/lua/mason-core/installer/registry/providers/openvsx.lua
@@ -0,0 +1,63 @@
+local Result = require "mason-core.result"
+local common = require "mason-core.installer.managers.common"
+local expr = require "mason-core.installer.registry.expr"
+local providers = require "mason-core.providers"
+local util = require "mason-core.installer.registry.util"
+
+local M = {}
+
+---@class OpenVSXSourceDownload : FileDownloadSpec
+---@field target_platform? string
+
+---@class OpenVSXSource : RegistryPackageSource
+---@field download FileDownloadSpec | FileDownloadSpec[]
+
+---@param source OpenVSXSource
+---@param purl Purl
+---@param opts PackageInstallOpts
+function M.parse(source, purl, opts)
+ return Result.try(function(try)
+ local expr_ctx = { version = purl.version }
+ ---@type OpenVSXSourceDownload
+ local download = try(util.coalesce_by_target(try(expr.tbl_interpolate(source.download, expr_ctx)), opts))
+
+ local downloads = common.parse_downloads(download, function(file)
+ if download.target_platform then
+ return ("https://open-vsx.org/api/%s/%s/%s/%s/file/%s"):format(
+ purl.namespace,
+ purl.name,
+ download.target_platform,
+ purl.version,
+ file
+ )
+ else
+ return ("https://open-vsx.org/api/%s/%s/%s/file/%s"):format(
+ purl.namespace,
+ purl.name,
+ purl.version,
+ file
+ )
+ end
+ end)
+
+ ---@class ParsedOpenVSXSource : ParsedPackageSource
+ local parsed_source = {
+ download = common.normalize_files(download),
+ downloads = downloads,
+ }
+ return parsed_source
+ end)
+end
+
+---@param ctx InstallContext
+---@param source ParsedOpenVSXSource
+function M.install(ctx, source)
+ return common.download_files(ctx, source.downloads)
+end
+
+---@param purl Purl
+function M.get_versions(purl)
+ return providers.openvsx.get_all_versions(purl.namespace, purl.name)
+end
+
+return M
diff --git a/lua/mason-core/installer/registry/util.lua b/lua/mason-core/installer/registry/util.lua
index 33aa5c33..d0045a3e 100644
--- a/lua/mason-core/installer/registry/util.lua
+++ b/lua/mason-core/installer/registry/util.lua
@@ -10,10 +10,10 @@ local M = {}
---@generic T : { target: Platform | Platform[] }
---@param candidates T[] | T
---@param opts PackageInstallOpts
----@return Optional # Optional<T>
+---@return Result # Result<T>
function M.coalesce_by_target(candidates, opts)
if not vim.tbl_islist(candidates) then
- return Optional.of(candidates)
+ return Result.success(candidates)
end
return Optional.of_nilable(_.find_first(function(asset)
if opts.target then
@@ -33,7 +33,7 @@ function M.coalesce_by_target(candidates, opts)
return platform.is[asset.target]
end
end
- end, candidates))
+ end, candidates)):ok_or "PLATFORM_UNSUPPORTED"
end
---Checks whether a custom version of a package installation corresponds to a valid version.
diff --git a/lua/mason-core/providers/init.lua b/lua/mason-core/providers/init.lua
index 15e8081c..a97d1b60 100644
--- a/lua/mason-core/providers/init.lua
+++ b/lua/mason-core/providers/init.lua
@@ -44,6 +44,10 @@ local settings = require "mason.settings"
---@class GolangProvider
---@field get_all_versions? async fun(pkg: string): Result # Result<string[]>
+---@class OpenVSXProvider
+---@field get_latest_version? async fun(namespace: string, extension: string): Result # Result<Crate>
+---@field get_all_versions? async fun(namespace: string, extension: string): Result # Result<string[]>
+
---@class Provider
---@field github? GitHubProvider
---@field npm? NpmProvider
@@ -52,6 +56,7 @@ local settings = require "mason.settings"
---@field packagist? PackagistProvider
---@field crates? CratesProvider
---@field golang? GolangProvider
+---@field openvsx? OpenVSXProvider
local function service_mt(service)
return setmetatable({}, {
diff --git a/lua/mason-core/semver.lua b/lua/mason-core/semver.lua
index 635b7e36..4e45567d 100644
--- a/lua/mason-core/semver.lua
+++ b/lua/mason-core/semver.lua
@@ -4,12 +4,14 @@ local semver = require "mason-vendor.semver"
local M = {}
---@param version string
+---@return Semver
function M.new(version)
version = version:gsub("^v", "")
return semver(version)
end
---@param version string
+---@return Result # Result<Semver>
function M.parse(version)
return Result.pcall(M.new, version)
end
diff --git a/lua/mason-registry/api.lua b/lua/mason-registry/api.lua
index 853690b9..b4acea63 100644
--- a/lua/mason-registry/api.lua
+++ b/lua/mason-registry/api.lua
@@ -120,4 +120,13 @@ api.golang = {
},
}
+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
diff --git a/lua/mason/providers/client/init.lua b/lua/mason/providers/client/init.lua
index 0bc264fc..8035b7eb 100644
--- a/lua/mason/providers/client/init.lua
+++ b/lua/mason/providers/client/init.lua
@@ -5,4 +5,5 @@ return {
pypi = require "mason.providers.client.pypi",
rubygems = require "mason.providers.client.rubygems",
golang = require "mason.providers.client.golang",
+ openvsx = require "mason.providers.client.openvsx",
}
diff --git a/lua/mason/providers/client/openvsx.lua b/lua/mason/providers/client/openvsx.lua
new file mode 100644
index 00000000..32428be3
--- /dev/null
+++ b/lua/mason/providers/client/openvsx.lua
@@ -0,0 +1,26 @@
+local _ = require "mason-core.functional"
+local fetch = require "mason-core.fetch"
+local semver = require "mason-core.semver"
+
+---@param path string
+local function api_url(path)
+ return ("https://open-vsx.org/api/%s"):format(path)
+end
+
+---@param version string
+local function maybe_semver_sort(version)
+ return semver.parse(version):get_or_else(version)
+end
+
+---@type OpenVSXProvider
+return {
+ get_latest_version = function(namespace, extension)
+ return fetch(api_url("%s/%s"):format(namespace, extension)):map_catching(vim.json.decode):map(_.prop "version")
+ end,
+ get_all_versions = function(namespace, extension)
+ return fetch(api_url("%s/%s/versions"):format(namespace, extension))
+ :map_catching(vim.json.decode)
+ :map(_.compose(_.keys, _.prop "versions"))
+ :map(_.compose(_.reverse, _.sort_by(maybe_semver_sort)))
+ end,
+}
diff --git a/lua/mason/providers/registry-api/init.lua b/lua/mason/providers/registry-api/init.lua
index 0f98a407..d8802124 100644
--- a/lua/mason/providers/registry-api/init.lua
+++ b/lua/mason/providers/registry-api/init.lua
@@ -61,4 +61,12 @@ return {
return api.golang.versions.all { pkg = api.encode_uri_component(pkg) }
end,
},
+ openvsx = {
+ get_latest_version = function(namespace, extension)
+ return api.openvsx.versions.latest { namespace = namespace, extension = extension }
+ end,
+ get_all_versions = function(namespace, extension)
+ return api.openvsx.versions.all { namespace = namespace, extension = extension }
+ end,
+ },
}