Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions hooks/available.lua
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,27 @@ end

function PLUGIN:Available(ctx)
local versions = {}

-- Get Yarn ZPM versions (v6.x+)
local zpm_tags = fetch_github_tags("https://github.com/yarnpkg/zpm.git")
local zpm_versions = {}
for _, tag in ipairs(zpm_tags) do
-- ZPM versions are prefixed with 'v'
local version = tag:match("^v(.+)$")
if version then
table.insert(zpm_versions, version)
end
end

-- Sort ZPM versions in descending order
table.sort(zpm_versions, version_compare)

-- Add ZPM versions to the list
for _, version in ipairs(zpm_versions) do
table.insert(versions, {
version = version
})
end

-- Get Yarn Berry versions (v2.x+)
local berry_tags = fetch_github_tags("https://github.com/yarnpkg/berry.git")
Expand Down
86 changes: 70 additions & 16 deletions hooks/post_install.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ end

local function download_file(url, output_path)
-- Detect Windows
local is_windows = package.config:sub(1,1) == '\\'
local is_windows = package.config:sub(1, 1) == '\\'
local stderr_redirect = is_windows and " 2>NUL" or " 2>/dev/null"

-- Try curl first (more likely to be available on Windows via Git Bash)
Expand All @@ -22,53 +22,83 @@ local function download_file(url, output_path)
return false
end

local function get_target_platform()
-- Detect platform and architecture for Yarn v6+ binary downloads
-- Available targets: aarch64-apple-darwin, aarch64-unknown-linux-musl,
-- i686-unknown-linux-musl, x86_64-unknown-linux-musl
local is_windows = package.config:sub(1, 1) == '\\'

if is_windows then
error("Yarn v6+ does not support Windows binaries at this time.")
else
-- Unix-like systems (Linux, macOS, etc.)
local handle = io.popen("uname -ms 2>/dev/null")
local result = handle and handle:read("*a") or ""
if handle then handle:close() end

if result:match("Darwin arm64") or result:match("Darwin aarch64") then
return "aarch64-apple-darwin"
elseif result:match("Darwin") then
-- Intel macOS is not supported in Yarn v6+
error("Yarn v6+ only supports ARM64 (Apple Silicon) macOS. Your system is x86_64 Intel.")
elseif result:match("Linux aarch64") or result:match("Linux arm64") then
return "aarch64-unknown-linux-musl"
elseif result:match("Linux i686") or result:match("Linux i386") then
return "i686-unknown-linux-musl"
elseif result:match("Linux") then
-- Default to x86_64 for Linux if not explicitly detected as 32-bit
return "x86_64-unknown-linux-musl"
else
error("Unsupported platform: " .. result)
end
end
end

function PLUGIN:PostInstall(ctx)
-- Get install path - it should be in sdkInfo
local install_path = nil
local version = nil

-- Try to get path from sdkInfo
if ctx.sdkInfo and ctx.sdkInfo.yarn then
install_path = ctx.sdkInfo.yarn.path
version = ctx.sdkInfo.yarn.version
end

-- Fallback to environment variable
if not install_path then
install_path = os.getenv("MISE_INSTALL_PATH")
end
if not version then
version = os.getenv("MISE_INSTALL_VERSION") or ctx.version
end

if not install_path or not version then
-- For v1, mise handles everything, so this is OK
return {}
end

local major_version = string.sub(version, 1, 1)

if major_version ~= "1" then
local is_windows = package.config:sub(1, 1) == '\\'

if major_version == "2" or major_version == "3" or major_version == "4" or major_version == "5" then
-- Yarn Berry (v2.x+) - download single JS file
local yarn_url = "https://repo.yarnpkg.com/" .. version .. "/packages/yarnpkg-cli/bin/yarn.js"

-- Detect Windows
local is_windows = package.config:sub(1,1) == '\\'


-- Create bin directory (cross-platform)
local bin_dir = install_path .. "/bin"
if is_windows then
os.execute('mkdir "' .. bin_dir .. '" 2>NUL')
else
os.execute("mkdir -p " .. bin_dir)
end

-- Download yarn.js
local yarn_js_file = bin_dir .. "/yarn.js"
if not download_file(yarn_url, yarn_js_file) then
error("Failed to download Yarn v2+")
end

-- Create wrapper script
if is_windows then
-- Create yarn.cmd wrapper for Windows
Expand All @@ -79,7 +109,7 @@ function PLUGIN:PostInstall(ctx)
cmd_file:write('node "%~dp0yarn.js" %*\n')
cmd_file:close()
end

-- Also create yarn without extension for Git Bash
local yarn_sh = bin_dir .. "/yarn"
local sh_file = io.open(yarn_sh, "w")
Expand All @@ -100,9 +130,33 @@ function PLUGIN:PostInstall(ctx)
-- Make executable
os.execute("chmod +x " .. yarn_file)
end
elseif major_version ~= "1" then
-- Yarn ZPM (v6+) - download pre-compiled Rust binary from NPM
local target = get_target_platform()
local npm_url = "https://registry.npmjs.org/@yarnpkg/yarn-" ..
target .. "/-/yarn-" .. target .. "-" .. version .. ".tgz"

-- Create bin directory
local bin_dir = install_path .. "/bin"
os.execute("mkdir -p " .. bin_dir)

-- Download the binary (tar.gz from NPM or repo)
local archive_path = bin_dir .. "/yarn.tar.gz"
if not download_file(npm_url, archive_path) then
error("Failed to download Yarn " .. version .. " from npm (" .. npm_url .. ")")
end

-- Extract the tar.gz file
if not exec_success(os.execute("tar -xzf " .. archive_path .. " -C " .. bin_dir)) then
error("Failed to extract Yarn binary. Ensure tar is installed.")
end

-- Move /package/yarn to /bin/yarn and clean up
os.execute("mv " .. bin_dir .. "/package/yarn " .. bin_dir .. "/yarn")
os.execute("rm -rf " .. bin_dir .. "/package " .. archive_path)
end

return {}
end

return PLUGIN
return PLUGIN