diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 555fa70..5b32ff6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -284,6 +284,60 @@ jobs: assert.equal(node.mode, 'managed', 'Node.js management must remain enabled'); NODE + - name: Verify command resolution without and with system package managers + shell: bash + env: + EXPECTED_MODES: ${{ matrix.config.modes }} + run: | + node --input-type=module <<'NODE' + import assert from 'node:assert/strict'; + import { execFileSync } from 'node:child_process'; + import { copyFileSync, mkdirSync, mkdtempSync, rmSync, symlinkSync } from 'node:fs'; + import { tmpdir } from 'node:os'; + import { delimiter, join } from 'node:path'; + + const managers = ['npm', 'pnpm', 'yarn', 'bun']; + const modes = JSON.parse(process.env.EXPECTED_MODES); + const windows = process.platform === 'win32'; + const dirs = Object.fromEntries(execFileSync('vp', [], { + env: { ...process.env, VP_DUMP_DIRS: '1' }, encoding: 'utf8', + }).trim().split(/\r?\n/).map(line => line.split('\t'))); + const system = mkdtempSync(join(tmpdir(), 'setup-vp-system-')); + const command = manager => windows ? `${manager}.exe` : manager; + const version = (manager, path = process.env.PATH) => execFileSync(command(manager), ['--version'], { + env: { ...process.env, PATH: path }, cwd: system, encoding: 'utf8', + }).trim(); + try { + // Preserve the actual exported entries and ordering; do not manufacture the missing fallback. + const shimDirs = [dirs.bin, join(dirs.data, 'fallback-bin')]; + const isolated = process.env.PATH.split(delimiter).filter(entry => shimDirs.includes(entry)); + if (windows) { + isolated.push(join(process.env.SystemRoot, 'System32')); + } else { + // pnpm's native launcher needs these utilities, but no system package managers. + const utilities = join(system, 'utilities'); + mkdirSync(utilities); + for (const name of ['sed', 'dirname', 'uname']) { + const executable = execFileSync('/bin/sh', ['-c', `command -v ${name}`], { encoding: 'utf8' }).trim(); + symlinkSync(executable, join(utilities, name)); + } + isolated.push(utilities); + } + for (const [index, manager] of managers.entries()) { + const managedVersion = version(manager, isolated.join(delimiter)); + assert.ok(managedVersion, `${manager} must have a managed fallback`); + // A copy of Node acts as a native system executable on every OS. + copyFileSync(process.execPath, join(system, command(manager))); + const withSystem = [dirs.bin, system, ...isolated.slice(1)].join(delimiter); + assert.equal(version(manager, withSystem), modes[index] === 'managed' ? managedVersion : process.version); + const laterAddition = [system, process.env.PATH].join(delimiter); + assert.equal(version(manager, laterAddition), process.version, 'later PATH additions must win'); + } + } finally { + rmSync(system, { recursive: true, force: true }); + } + NODE + test-default-version: # End-to-end check of the default version-resolution logic: with no `version` # or `version-file` input, the action auto-detects the vite-plus version from diff --git a/dist/azure/index.mjs b/dist/azure/index.mjs index 5f53d01..ea53f46 100644 --- a/dist/azure/index.mjs +++ b/dist/azure/index.mjs @@ -145,7 +145,7 @@ n?this.stack.push(n):(yield*this.pop(),yield*this.step())}else{let t=this.peek(2 `,n,r);return n.NODE_AUTH_TOKEN=n.NODE_AUTH_TOKEN||`XXXXX-XXXXX-XXXXX-XXXXX`,r?.(`NODE_AUTH_TOKEN`,n.NODE_AUTH_TOKEN),d}function resolveSfwEnabled(e,t,n){return e?!pkgPrNewCommitSha(t)||(n(`sfw was requested but is automatically disabled for Vite+ preview build ${t}; Socket Firewall Free will not be used.`),!1):!1}const Q=`v1.15.1`,st=`https://github.com/SocketDev/sfw-free/releases/download/${Q}`;function isMuslLinux(){if(process.platform!==`linux`)return!1;try{let e=process.report?.getReport();if(e?.header&&!e.header.glibcVersionRuntime)return!0}catch{}return n(`/etc/alpine-release`)}function getSfwAssetName(e,t,n){if(e===`darwin`){if(t===`arm64`)return`sfw-free-macos-arm64`;if(t===`x64`)return`sfw-free-macos-x86_64`}else if(e===`linux`){if(t===`arm64`)return n?`sfw-free-musl-linux-arm64`:`sfw-free-linux-arm64`;if(t===`x64`)return n?`sfw-free-musl-linux-x86_64`:`sfw-free-linux-x86_64`}else if(isWindows(e)){if(t===`arm64`)return`sfw-free-windows-arm64.exe`;if(t===`x64`)return`sfw-free-windows-x86_64.exe`}throw Error(`Unsupported platform/arch for sfw: ${e}/${t}${e===`linux`?` (${n?`musl`:`glibc`})`:``}`)}function downloadFileWithShell(e,t,n){let r=Math.max(1,Math.ceil(n/1e3)),i=commandPath(`curl`);if(i){let n=y(i,[`-fsSL`,`--connect-timeout`,`5`,`--max-time`,String(r),e,`-o`,t],{stdio:`ignore`});if(n.status===0)return;throw n.error||/* @__PURE__ */ Error(`curl failed while downloading ${e}`)}let a=commandPath(`wget`);if(a){let n=y(a,[`-q`,`-T`,String(r),`-t`,`2`,`-O`,t,e],{stdio:`ignore`});if(n.status===0)return;throw n.error||/* @__PURE__ */ Error(`wget failed while downloading ${e}`)}throw Error(`curl or wget is required to download sfw`)}function downloadFile(e,n,r=0,i=6e4,a){return r>5?Promise.reject(/* @__PURE__ */ Error(`too many redirects while downloading ${e}`)):a?new Promise((o,s)=>{let c=!1,finish=e=>{c||(c=!0,clearTimeout(u),e?s(e):o())},l=a(e,o=>{let s=o.statusCode??0,c=o.headers.location;if(s>=300&&s<400&&c){o.resume(),downloadFile(new URL(c,e).toString(),n,r+1,i,a).then(()=>finish(),finish);return}if(s!==200){o.resume(),finish(/* @__PURE__ */ Error(`download failed with HTTP ${s}: ${e}`));return}let l=t(n);o.pipe(l),l.on(`finish`,()=>l.close(()=>finish())),l.on(`error`,finish)}),u=setTimeout(()=>{l.destroy(/* @__PURE__ */ Error(`download timed out after ${i}ms: ${e}`))},i);l.on(`error`,finish)}):(downloadFileWithShell(e,n,i),Promise.resolve())}async function setupSfw(e,t={}){let n=t.env??process.env,r=t.sfwEnabled??n.SETUP_VP_SFW===`true`,i=t.platform??process.platform,a=t.arch??process.arch,o=t.isMusl??isMuslLinux(),s=t.download??downloadFile;if(!resolveSfwEnabled(r,t.vitePlusVersion??``,t.logWarning??console.warn))return`vp`;if(e.length===0)return console.log(`setup-vp: sfw was requested but run-install is disabled; sfw will not be invoked.`),`vp`;let c=commandPath(`sfw`);if(c)return console.log(`setup-vp: using existing sfw on PATH: ${c}`),`sfw`;let l;try{l=getSfwAssetName(i,a,o)}catch{return console.error(`setup-vp: sfw has no published binary for this runner's platform/architecture (process.platform=${i}, process.arch=${a}, musl=${o}) and none was found on PATH; falling back to plain vp install.`),`vp`}let d=t.cacheDirectory||n.SETUP_VP_SFW_CACHE_DIR,f=d?u.join(d,Q,l):await w(u.join(x(),`setup-vp-sfw-`));await C(f,{recursive:!0});let p=u.join(f,isWindows(i)?`sfw.exe`:`sfw`),m=`${st}/${l}`;function activate(){let e=isWindows(i)?`;`:`:`;return n.PATH=`${f}${e}${n.PATH||``}`,t.exportVariable?.(`PATH`,n.PATH),`sfw`}if(await ee(p).then(e=>e.isFile()&&e.size>0,()=>!1))return console.log(`setup-vp: using cached sfw ${Q}: ${p}`),activate();for(let e=1;e<=2;e+=1){let t=await w(u.join(f,`.download-`)),n=u.join(t,`sfw`);try{if(console.log(`setup-vp: installing sfw ${Q} from ${m}`),await s(m,n),(await ee(n)).size===0)throw Error(`Downloaded sfw binary is empty`);return await S(n,493),await T(n,p),activate()}catch(t){if(e===2)throw t;await new Promise(e=>setTimeout(e,2e3))}finally{await E(t,{recursive:!0,force:!0})}}throw Error(`failed to install sfw after retrying`)}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function validateRunInstallEntry(e){if(!isRecord(e))throw Error(`run-install entries must be objects`);for(let t of Object.keys(e))if(t!==`cwd`&&t!==`args`)throw Error(`unsupported run-install key: ${t}`);let t={};if(e.cwd!==void 0){if(typeof e.cwd!=`string`)throw Error(`run-install.cwd must be a string`);t.cwd=e.cwd}if(e.args!==void 0){if(!Array.isArray(e.args)||e.args.some(e=>typeof e!=`string`))throw Error(`run-install.args must be an array of strings`);t.args=e.args}return t}function validateRunInstallInput(e){return e===null||typeof e==`boolean`?e:Array.isArray(e)?e.map(validateRunInstallEntry):validateRunInstallEntry(e)}function parseRunInstall(e){let t=validateRunInstallInput((0,Y.parse)(e)??null);return t?t===!0?[{}]:Array.isArray(t)?t:[t]:[]}function isSfwVpNotFoundFlake(e,t){return/Command 'vp' not found in PATH/.test(e+` `+t)}async function runInstall(e,t,n,r=process.env,i={}){let a={...r};delete a.SETUP_VP_ENV_FILE;let o=i.execute??runWithOutput,s=[];for(let r of e){let e=r.cwd?u.resolve(t,r.cwd):t,c=[`install`,...r.args||[]],l=n===`sfw`?[`vp`,...c]:c,d=`${n} ${l.join(` `)} (cwd: ${e})`;console.log(`setup-vp: running ${d}`);try{let t=await o(n,l,{cwd:e,env:a});if(t.exitCode!==0&&n===`sfw`&&isSfwVpNotFoundFlake(t.stdout,t.stderr)){let r=isWindows(i.platform);if(console.warn(r?`setup-vp: sfw could not resolve vp; warming the PowerShell command cache and retrying once.`:`setup-vp: sfw could not resolve vp; retrying once.`),r)try{await o(`powershell.exe`,[`-NoProfile`,`-Command`,`Get-Command vp`],{cwd:e,env:a})}catch{}t=await o(n,l,{cwd:e,env:a})}t.exitCode!==0&&s.push(`${d} exited with code ${t.exitCode}\n${t.stderr.trim()||t.stdout.trim()}`)}catch(e){s.push(`${d}: ${String(e)}`)}}if(s.length)throw Error(s.join(` `))}function escapeLoggingCommandData(e){return e.replaceAll(`%`,`%AZP25`).replaceAll(`\r`,`%0D`).replaceAll(` -`,`%0A`).replaceAll(`;`,`%3B`).replaceAll(`]`,`%5D`)}function prependPath(e){process.stdout.write(`##vso[task.prependpath]${escapeLoggingCommandData(e)}\n`)}function setVariable(e,t,n={}){let r=[`variable=${e}`];n.isOutput&&r.push(`isOutput=true`),n.isReadonly&&r.push(`isReadonly=true`),n.isSecret&&r.push(`issecret=true`),process.stdout.write(`##vso[task.setvariable ${r.join(`;`)}]${escapeLoggingCommandData(t)}\n`)}function logWarning(e){process.stdout.write(`##vso[task.logissue type=warning]${escapeLoggingCommandData(e)}\n`)}function logInfo(e){console.log(e)}const $=`SETUP_VP_DIRS_FILE`,ct=/^v?(\d+)\.(\d+)\.\d+(?:-[0-9A-Za-z.-]+)?$/;function supportsVitePlusDirs(e){if(pkgPrNewCommitSha(e))return!0;let t=e.match(ct);if(!t)return!0;let n=Number(t[1]),r=Number(t[2]);return n>0||r>=3}function createVitePlusDirsFile(){return m(x(),`setup-vp-dirs-${ne()}.txt`)}function removeVitePlusDirsFile(e){s(e,{force:!0})}function readVitePlusProbe(e){try{return a(e,`utf8`)}catch(e){if(e.code===`ENOENT`)return;throw e}}function resolveVitePlusBinDir(e,t,n){if(!t){if(!supportsVitePlusDirs(e))return n;throw Error(`Vite+ was installed successfully, but setup-vp could not resolve its VpDirs.`)}let r=readVitePlusProbe(t),i=r===void 0?void 0:parseVitePlusDirs(r);if(i)return i.bin;if(!(pkgPrNewCommitSha(e)!==void 0||ct.test(e))&&r!==void 0){let e=parseInstalledVpVersion(r);if(e!==`unknown`&&!supportsVitePlusDirs(e))return n}throw Error(`Vite+ was installed successfully, but setup-vp could not resolve its VpDirs.`)}function parseVitePlusDirs(e){let t=/* @__PURE__ */ new Map;for(let n of e.split(/\r?\n/)){let e=n.indexOf(` `);if(e<1)continue;let r=n.slice(0,e).replace(/^\uFEFF/,``),i=n.slice(e+1).trim();i&&t.set(r,i)}let n=t.get(`data`),r=t.get(`bin`),i=t.get(`cache`),a=t.get(`config`),o=t.get(`state`);if(n&&r&&i&&a&&o)return{data:n,bin:r,cache:i,config:a,state:o}}function getInstallScriptCommand(e,t=process.platform,n=!0){if(isWindows(t))return n?{command:`pwsh`,args:[`-Command`,` +`,`%0A`).replaceAll(`;`,`%3B`).replaceAll(`]`,`%5D`)}function prependPath(e){process.stdout.write(`##vso[task.prependpath]${escapeLoggingCommandData(e)}\n`)}function setVariable(e,t,n={}){let r=[`variable=${e}`];n.isOutput&&r.push(`isOutput=true`),n.isReadonly&&r.push(`isReadonly=true`),n.isSecret&&r.push(`issecret=true`),process.stdout.write(`##vso[task.setvariable ${r.join(`;`)}]${escapeLoggingCommandData(t)}\n`)}function logWarning(e){process.stdout.write(`##vso[task.logissue type=warning]${escapeLoggingCommandData(e)}\n`)}function logInfo(e){console.log(e)}const $=`SETUP_VP_DIRS_FILE`,ct=/^v?(\d+)\.(\d+)\.\d+(?:-[0-9A-Za-z.-]+)?$/;function supportsVitePlusDirs(e){if(pkgPrNewCommitSha(e))return!0;let t=e.match(ct);if(!t)return!0;let n=Number(t[1]),r=Number(t[2]);return n>0||r>=3}function createVitePlusDirsFile(){return m(x(),`setup-vp-dirs-${ne()}.txt`)}function removeVitePlusDirsFile(e){s(e,{force:!0})}function readVitePlusPath(e){if(e)return readVitePlusProbe(e)?.split(/\r?\n/).find(e=>e.startsWith(`path `))?.slice(5)}function readVitePlusProbe(e){try{return a(e,`utf8`)}catch(e){if(e.code===`ENOENT`)return;throw e}}function resolveVitePlusBinDir(e,t,n){if(!t){if(!supportsVitePlusDirs(e))return n;throw Error(`Vite+ was installed successfully, but setup-vp could not resolve its VpDirs.`)}let r=readVitePlusProbe(t),i=r===void 0?void 0:parseVitePlusDirs(r);if(i)return i.bin;if(!(pkgPrNewCommitSha(e)!==void 0||ct.test(e))&&r!==void 0){let e=parseInstalledVpVersion(r);if(e!==`unknown`&&!supportsVitePlusDirs(e))return n}throw Error(`Vite+ was installed successfully, but setup-vp could not resolve its VpDirs.`)}function parseVitePlusDirs(e){let t=/* @__PURE__ */ new Map;for(let n of e.split(/\r?\n/)){let e=n.indexOf(` `);if(e<1)continue;let r=n.slice(0,e).replace(/^\uFEFF/,``),i=n.slice(e+1).trim();i&&t.set(r,i)}let n=t.get(`data`),r=t.get(`bin`),i=t.get(`cache`),a=t.get(`config`),o=t.get(`state`);if(n&&r&&i&&a&&o)return{data:n,bin:r,cache:i,config:a,state:o}}function getInstallScriptCommand(e,t=process.platform,n=!0){if(isWindows(t))return n?{command:`pwsh`,args:[`-Command`,` $dirsFile = $env:${$} Set-Content -LiteralPath $dirsFile -Value '' -NoNewline -Encoding UTF8 . ([scriptblock]::Create((irm -TimeoutSec 15 ${e}))) @@ -165,6 +165,15 @@ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } $env:VP_DUMP_DIRS = '1' & $vpPath | Add-Content -LiteralPath $dirsFile -Encoding UTF8 if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } +# Use Vite+'s generated environment so system-first shims stay last in PATH. +$configLine = Get-Content -LiteralPath $dirsFile | Where-Object { $_.StartsWith("config" + [char]9) } | Select-Object -Last 1 +if ($configLine) { + $envFile = Join-Path $configLine.Substring(7) 'env.ps1' + if (Test-Path -LiteralPath $envFile -PathType Leaf) { + . $envFile + Add-Content -LiteralPath $dirsFile -Value ("path" + [char]9 + $env:PATH) -Encoding UTF8 + } +} `.trim()]}:{command:`pwsh`,args:[`-Command`,`& ([scriptblock]::Create((irm -TimeoutSec 15 ${e})))`]};let r=` if command -v curl >/dev/null 2>&1; then curl -fsSL --connect-timeout 5 --max-time 15 "${e}"${n?` -o "$installer_file"`:``} @@ -186,9 +195,17 @@ vp_dir="\${SHIM_DIR:-\${INSTALL_DIR:-\${VP_HOME:-$HOME/.vite-plus}}/bin}" if [ -x "$vp_dir/vp" ]; then "$vp_dir/vp" --version > "$${$}" VP_DUMP_DIRS=1 "$vp_dir/vp" >> "$${$}" + # Read the resolved config directory, including split/custom installations. + while IFS=$'\\t' read -r key value; do + if [ "$key" = config ] && [ -f "$value/env" ]; then + source "$value/env" + printf 'path\\t%s\\n' "$PATH" >> "$${$}" + break + fi + done < "$${$}" fi `.trim()]}:{command:`bash`,args:[`-c`,` set +u set -o pipefail ${r} | bash -`.trim()]}}const lt=2e3;function getVitePlusHome(e=process.platform,t=process.env){let n=isWindows(e)?t.USERPROFILE||b():t.HOME||b();return m(n,`.vite-plus`)}function runInstallCommand(e,t,n=process.platform){let{command:r,args:i}=getInstallScriptCommand(e,n,t.VP_VPDIRS_AWARE===`1`),a={env:{...process.env,...t},stdio:`inherit`},o=y(r,i,a);if(isWindows(n)&&o.error?.code===`ENOENT`&&(o=y(`powershell.exe`,i,a)),o.error)throw o.error;return o.status??1}async function installVitePlus(e,t={}){let n=t.platform??process.platform,r=t.env??process.env,i=t.prependPath,a=t.sleep??te,o=t.runInstall??runInstallCommand,s=t.logWarningFn??console.warn,c={...Object.fromEntries(Object.entries(r).filter(e=>e[1]!==void 0)),VP_VERSION:e,VITE_PLUS_VERSION:e},l=supportsVitePlusDirs(e)?createVitePlusDirsFile():void 0;l?(c.VP_VPDIRS_AWARE=`1`,c[$]=l):(delete c.VP_VPDIRS_AWARE,delete c[$]);let u=pkgPrNewCommitSha(e);u&&(c.VP_PR_VERSION=u);let{pinned:d,latest:f}=getInstallScriptUrls(e,n),p=d.length+f.length,h=2*p,g=``,_=0;async function tryUrls(e){for(let t=0;t<2;t+=1)for(let t of e){_+=1;try{let e=o(t,c,n);if(e===0)return!0;g=`exit code ${e}`}catch(e){g=e instanceof Error?e.message:String(e)}_0){if(await tryUrls(d)){ensureBinInPath();return}s(`setup-vp: could not fetch the install script pinned to Vite+ ${e}. Falling back to the latest install script. The latest script may not be compatible with ${e}.`)}if(await tryUrls(f)){ensureBinInPath();return}throw Error(`Failed to install Vite+ after ${h} attempts across ${p} URL(s): ${g}`)}finally{l&&removeVitePlusDirsFile(l)}}function parseBoolean(e){return e?.toLowerCase()===`true`}function parseAzureInputs(e){return{version:e.SETUP_VP_VERSION||``,versionFile:e.SETUP_VP_VERSION_FILE||void 0,nodeVersion:e.SETUP_VP_NODE_VERSION||void 0,nodeVersionFile:e.SETUP_VP_NODE_VERSION_FILE||void 0,workingDirectory:e.SETUP_VP_WORKING_DIRECTORY||`.`,runInstall:e.SETUP_VP_RUN_INSTALL??`true`,sfw:parseBoolean(e.SETUP_VP_SFW),nodeManager:parseNodeManager(e.SETUP_VP_NODE_MANAGER),packageManager:parsePackageManager(e.SETUP_VP_PACKAGE_MANAGER),registryUrl:e.SETUP_VP_REGISTRY_URL||``,scope:e.SETUP_VP_SCOPE||``,cache:parseBoolean(e.SETUP_VP_CACHE),cacheDependencyPath:e.SETUP_VP_CACHE_DEPENDENCY_PATH||``,workspaceRoot:e.SYSTEM_DEFAULTWORKINGDIRECTORY||process.cwd()}}function resolveProjectDirFromInputs(e){return resolveProjectDirectory({workingDirectory:e.workingDirectory,workspaceRoot:e.workspaceRoot})}const ut={installVitePlus,prepareCacheMetadata,configureAuth,setupSfw,parseRunInstall,runInstall,getCommandOutput,run,parseInstalledVpVersion,prependPath,setVariable,logWarning,logInfo};function fail(e){console.error(`setup-vp: ${e}`),process.exit(1)}async function runPrepare(e=process.env,t=ut){let n=parseAzureInputs(e),i=resolveProjectDirFromInputs(n);if(n.nodeManager===!1&&(n.nodeVersion||n.nodeVersionFile))throw Error(`node-version and node-version-file cannot be used with node-manager: false`);let a={...resolutionContext(n.workspaceRoot),info:t.logInfo,warning:t.logWarning},o=createVersionResolver(a).resolveVitePlusVersion(n,i),s=n.nodeVersion||(n.nodeVersionFile?createNodeVersionResolver(a).resolveNodeVersionFile(n.nodeVersionFile,i):void 0);t.setVariable(`SETUP_VP_CACHE_HIT`,`false`),t.setVariable(`SETUP_VP_CACHE_READY`,`false`),t.setVariable(`SETUP_VP_SFW_READY`,`false`),t.setVariable(`SETUP_VP_BOOTSTRAP_NODE`,process.execPath),await t.installVitePlus(o,{env:e,prependPath:e=>t.prependPath(e),logWarningFn:t.logWarning}),t.setVariable(`SETUP_VP_RESOLVED_VERSION`,o);let c=(n.nodeManager===!1||n.packageManager!==void 0)&&t.getCommandOutput(`vp`,[`--version`])||``,l=packageManagerArgs(n.packageManager,c);n.nodeManager===!1?t.run(`vp`,nodeManagerOffArgs(c)):s&&t.run(`vp`,[`env`,`use`,s],{cwd:i});for(let e of l)t.run(`vp`,e);let d=u.resolve(process.argv[1]||``);if(t.setVariable(`SETUP_VP_RUNTIME_PATH`,d),n.sfw&&!pkgPrNewCommitSha(o)&&t.parseRunInstall(n.runInstall).length>0)try{let i=getSfwAssetName(process.platform,process.arch,isMuslLinux()),a=u.join(e.PIPELINE_WORKSPACE||n.workspaceRoot,`.setup-vp-sfw`);r(a,{recursive:!0}),t.setVariable(`SETUP_VP_SFW_CACHE_DIR`,a),t.setVariable(`SETUP_VP_SFW_CACHE_KEY`,`${Q}-${i}`),t.setVariable(`SETUP_VP_SFW_READY`,`true`)}catch(e){t.logWarning(String(e))}if(!n.cache)return;let f=t.prepareCacheMetadata({projectDir:i,cacheDependencyPath:n.cacheDependencyPath||void 0,logWarning:t.logWarning});if(!f.ready){t.setVariable(`SETUP_VP_CACHE_READY`,`false`);return}t.setVariable(`SETUP_VP_CACHE_READY`,`true`),f.cachePath&&t.setVariable(`SETUP_VP_CACHE_PATH`,f.cachePath),f.lockFile&&t.setVariable(`SETUP_VP_LOCK_FILE`,f.lockFile),f.lockType&&t.setVariable(`SETUP_VP_LOCK_TYPE`,f.lockType)}async function runFinalize(e=process.env,t=ut){let n=parseAzureInputs(e),r=resolveProjectDirFromInputs(n),i=analyzeProjectNpmrc(readNpmrc(u.join(r,`.npmrc`))).envVarRefs;i.add(`NODE_AUTH_TOKEN`);for(let t of i)!isReservedAuthVariable(t)&&/^\$\([^)]+\)$/.test(e[t]||``)&&delete e[t];t.configureAuth(n.registryUrl,n.scope,e,(e,n)=>{e!==`NODE_AUTH_TOKEN`&&n!==void 0&&t.setVariable(e,n,{isSecret:e!==`NPM_CONFIG_USERCONFIG`&&e!==`PNPM_CONFIG_USERCONFIG`})},r);let a=t.parseRunInstall(n.runInstall),o=await t.setupSfw(a,{env:e,sfwEnabled:n.sfw,vitePlusVersion:e.SETUP_VP_RESOLVED_VERSION||n.version,logWarning:t.logWarning,exportVariable:(e,n)=>{n!==void 0&&(e===`PATH`?t.prependPath(n.split(u.delimiter)[0]):t.setVariable(e,n))}});a.length>0&&await t.runInstall(a,r,o,e);let s=t.getCommandOutput(`vp`,[`--version`],{cwd:r});if(!s)throw Error(`Failed to verify Vite+ installation: vp --version failed or returned no output.`);t.logInfo(s);let c=t.parseInstalledVpVersion(s);t.setVariable(`SETUP_VP_INSTALLED_VERSION`,c),t.setVariable(`version`,c,{isOutput:!0}),t.setVariable(`cacheHit`,String(e.SETUP_VP_CACHE_HIT===`true`),{isOutput:!0})}async function main(e){if(e===`prepare`){await runPrepare();return}if(e===`finalize`){await runFinalize();return}fail(`invalid phase "${String(e)}"; expected "prepare" or "finalize"`)}function isEntrypoint(e=process.argv[1],t=import.meta.url){return!!(e&&t===_(u.resolve(e)).href)}if(isEntrypoint()){let e=process.argv[2];e||fail(`missing phase argument; expected "prepare" or "finalize"`);try{await main(e)}catch(e){fail(e instanceof Error?e.message:String(e))}}export{isEntrypoint,main,runFinalize,runPrepare}; \ No newline at end of file +`.trim()]}}const lt=2e3;function getVitePlusHome(e=process.platform,t=process.env){let n=isWindows(e)?t.USERPROFILE||b():t.HOME||b();return m(n,`.vite-plus`)}function runInstallCommand(e,t,n=process.platform){let{command:r,args:i}=getInstallScriptCommand(e,n,t.VP_VPDIRS_AWARE===`1`),a={env:{...process.env,...t},stdio:`inherit`},o=y(r,i,a);if(isWindows(n)&&o.error?.code===`ENOENT`&&(o=y(`powershell.exe`,i,a)),o.error)throw o.error;return o.status??1}async function installVitePlus(e,t={}){let n=t.platform??process.platform,r=t.env??process.env,i=t.prependPath,a=t.sleep??te,o=t.runInstall??runInstallCommand,s=t.logWarningFn??console.warn,c={...Object.fromEntries(Object.entries(r).filter(e=>e[1]!==void 0)),VP_VERSION:e,VITE_PLUS_VERSION:e},l=supportsVitePlusDirs(e)?createVitePlusDirsFile():void 0;l?(c.VP_VPDIRS_AWARE=`1`,c[$]=l):(delete c.VP_VPDIRS_AWARE,delete c[$]);let u=pkgPrNewCommitSha(e);u&&(c.VP_PR_VERSION=u);let{pinned:d,latest:f}=getInstallScriptUrls(e,n),p=d.length+f.length,h=2*p,g=``,_=0;async function tryUrls(e){for(let t=0;t<2;t+=1)for(let t of e){_+=1;try{let e=o(t,c,n);if(e===0)return!0;g=`exit code ${e}`}catch(e){g=e instanceof Error?e.message:String(e)}_0){if(await tryUrls(d)){ensureBinInPath();return}s(`setup-vp: could not fetch the install script pinned to Vite+ ${e}. Falling back to the latest install script. The latest script may not be compatible with ${e}.`)}if(await tryUrls(f)){ensureBinInPath();return}throw Error(`Failed to install Vite+ after ${h} attempts across ${p} URL(s): ${g}`)}finally{l&&removeVitePlusDirsFile(l)}}function parseBoolean(e){return e?.toLowerCase()===`true`}function parseAzureInputs(e){return{version:e.SETUP_VP_VERSION||``,versionFile:e.SETUP_VP_VERSION_FILE||void 0,nodeVersion:e.SETUP_VP_NODE_VERSION||void 0,nodeVersionFile:e.SETUP_VP_NODE_VERSION_FILE||void 0,workingDirectory:e.SETUP_VP_WORKING_DIRECTORY||`.`,runInstall:e.SETUP_VP_RUN_INSTALL??`true`,sfw:parseBoolean(e.SETUP_VP_SFW),nodeManager:parseNodeManager(e.SETUP_VP_NODE_MANAGER),packageManager:parsePackageManager(e.SETUP_VP_PACKAGE_MANAGER),registryUrl:e.SETUP_VP_REGISTRY_URL||``,scope:e.SETUP_VP_SCOPE||``,cache:parseBoolean(e.SETUP_VP_CACHE),cacheDependencyPath:e.SETUP_VP_CACHE_DEPENDENCY_PATH||``,workspaceRoot:e.SYSTEM_DEFAULTWORKINGDIRECTORY||process.cwd()}}function resolveProjectDirFromInputs(e){return resolveProjectDirectory({workingDirectory:e.workingDirectory,workspaceRoot:e.workspaceRoot})}const ut={installVitePlus,prepareCacheMetadata,configureAuth,setupSfw,parseRunInstall,runInstall,getCommandOutput,run,parseInstalledVpVersion,prependPath,setVariable,logWarning,logInfo};function fail(e){console.error(`setup-vp: ${e}`),process.exit(1)}async function runPrepare(e=process.env,t=ut){let n=parseAzureInputs(e),i=resolveProjectDirFromInputs(n);if(n.nodeManager===!1&&(n.nodeVersion||n.nodeVersionFile))throw Error(`node-version and node-version-file cannot be used with node-manager: false`);let a={...resolutionContext(n.workspaceRoot),info:t.logInfo,warning:t.logWarning},o=createVersionResolver(a).resolveVitePlusVersion(n,i),s=n.nodeVersion||(n.nodeVersionFile?createNodeVersionResolver(a).resolveNodeVersionFile(n.nodeVersionFile,i):void 0);t.setVariable(`SETUP_VP_CACHE_HIT`,`false`),t.setVariable(`SETUP_VP_CACHE_READY`,`false`),t.setVariable(`SETUP_VP_SFW_READY`,`false`),t.setVariable(`SETUP_VP_BOOTSTRAP_NODE`,process.execPath),await t.installVitePlus(o,{env:e,prependPath:e=>t.prependPath(e),exportPath:e=>t.setVariable(`PATH`,e),logWarningFn:t.logWarning}),t.setVariable(`SETUP_VP_RESOLVED_VERSION`,o);let c=(n.nodeManager===!1||n.packageManager!==void 0)&&t.getCommandOutput(`vp`,[`--version`])||``,l=packageManagerArgs(n.packageManager,c);n.nodeManager===!1?t.run(`vp`,nodeManagerOffArgs(c)):s&&t.run(`vp`,[`env`,`use`,s],{cwd:i});for(let e of l)t.run(`vp`,e);let d=u.resolve(process.argv[1]||``);if(t.setVariable(`SETUP_VP_RUNTIME_PATH`,d),n.sfw&&!pkgPrNewCommitSha(o)&&t.parseRunInstall(n.runInstall).length>0)try{let i=getSfwAssetName(process.platform,process.arch,isMuslLinux()),a=u.join(e.PIPELINE_WORKSPACE||n.workspaceRoot,`.setup-vp-sfw`);r(a,{recursive:!0}),t.setVariable(`SETUP_VP_SFW_CACHE_DIR`,a),t.setVariable(`SETUP_VP_SFW_CACHE_KEY`,`${Q}-${i}`),t.setVariable(`SETUP_VP_SFW_READY`,`true`)}catch(e){t.logWarning(String(e))}if(!n.cache)return;let f=t.prepareCacheMetadata({projectDir:i,cacheDependencyPath:n.cacheDependencyPath||void 0,logWarning:t.logWarning});if(!f.ready){t.setVariable(`SETUP_VP_CACHE_READY`,`false`);return}t.setVariable(`SETUP_VP_CACHE_READY`,`true`),f.cachePath&&t.setVariable(`SETUP_VP_CACHE_PATH`,f.cachePath),f.lockFile&&t.setVariable(`SETUP_VP_LOCK_FILE`,f.lockFile),f.lockType&&t.setVariable(`SETUP_VP_LOCK_TYPE`,f.lockType)}async function runFinalize(e=process.env,t=ut){let n=parseAzureInputs(e),r=resolveProjectDirFromInputs(n),i=analyzeProjectNpmrc(readNpmrc(u.join(r,`.npmrc`))).envVarRefs;i.add(`NODE_AUTH_TOKEN`);for(let t of i)!isReservedAuthVariable(t)&&/^\$\([^)]+\)$/.test(e[t]||``)&&delete e[t];t.configureAuth(n.registryUrl,n.scope,e,(e,n)=>{e!==`NODE_AUTH_TOKEN`&&n!==void 0&&t.setVariable(e,n,{isSecret:e!==`NPM_CONFIG_USERCONFIG`&&e!==`PNPM_CONFIG_USERCONFIG`})},r);let a=t.parseRunInstall(n.runInstall),o=await t.setupSfw(a,{env:e,sfwEnabled:n.sfw,vitePlusVersion:e.SETUP_VP_RESOLVED_VERSION||n.version,logWarning:t.logWarning,exportVariable:(e,n)=>{n!==void 0&&(e===`PATH`?t.prependPath(n.split(u.delimiter)[0]):t.setVariable(e,n))}});a.length>0&&await t.runInstall(a,r,o,e);let s=t.getCommandOutput(`vp`,[`--version`],{cwd:r});if(!s)throw Error(`Failed to verify Vite+ installation: vp --version failed or returned no output.`);t.logInfo(s);let c=t.parseInstalledVpVersion(s);t.setVariable(`SETUP_VP_INSTALLED_VERSION`,c),t.setVariable(`version`,c,{isOutput:!0}),t.setVariable(`cacheHit`,String(e.SETUP_VP_CACHE_HIT===`true`),{isOutput:!0})}async function main(e){if(e===`prepare`){await runPrepare();return}if(e===`finalize`){await runFinalize();return}fail(`invalid phase "${String(e)}"; expected "prepare" or "finalize"`)}function isEntrypoint(e=process.argv[1],t=import.meta.url){return!!(e&&t===_(u.resolve(e)).href)}if(isEntrypoint()){let e=process.argv[2];e||fail(`missing phase argument; expected "prepare" or "finalize"`);try{await main(e)}catch(e){fail(e instanceof Error?e.message:String(e))}}export{isEntrypoint,main,runFinalize,runPrepare}; \ No newline at end of file diff --git a/dist/gitlab/index.mjs b/dist/gitlab/index.mjs index 0e0dd7f..fcf5487 100644 --- a/dist/gitlab/index.mjs +++ b/dist/gitlab/index.mjs @@ -138,7 +138,7 @@ n?this.stack.push(n):(yield*this.pop(),yield*this.step())}else{let t=this.peek(2 `)+1;for(;e!==0;)this.onNewLine(this.offset+e),e=this.source.indexOf(` `,e)+1}return{type:e,offset:this.offset,indent:this.indent,source:this.source}}startBlockValue(e){switch(this.type){case`alias`:case`scalar`:case`single-quoted-scalar`:case`double-quoted-scalar`:return this.flowScalar(this.type);case`block-scalar-header`:return{type:`block-scalar`,offset:this.offset,indent:this.indent,props:[this.sourceToken],source:``};case`flow-map-start`:case`flow-seq-start`:return{type:`flow-collection`,offset:this.offset,indent:this.indent,start:this.sourceToken,items:[],end:[]};case`seq-item-ind`:return{type:`block-seq`,offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken]}]};case`explicit-key-ind`:{this.onKeyLine=!0;let t=getFirstKeyStartProps(getPrevProps(e));return t.push(this.sourceToken),{type:`block-map`,offset:this.offset,indent:this.indent,items:[{start:t,explicitKey:!0}]}}case`map-value-ind`:{this.onKeyLine=!0;let t=getFirstKeyStartProps(getPrevProps(e));return{type:`block-map`,offset:this.offset,indent:this.indent,items:[{start:t,key:null,sep:[this.sourceToken]}]}}}return null}atIndentedComment(e,t){return this.type!==`comment`||this.indent<=t?!1:e.every(e=>e.type===`newline`||e.type===`space`)}*documentEnd(e){this.type!==`doc-mode`&&(e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type===`newline`&&(yield*this.pop()))}*lineEnd(e){switch(this.type){case`comma`:case`doc-start`:case`doc-end`:case`flow-seq-end`:case`flow-map-end`:case`map-value-ind`:yield*this.pop(),yield*this.step();break;case`newline`:this.onKeyLine=!1;default:e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type===`newline`&&(yield*this.pop())}}}})),it=/* @__PURE__ */ __commonJSMin((e=>{var t=Xe(),n=G(),r=K(),i=he(),a=O(),o=nt(),s=rt();function parseOptions(e){let t=e.prettyErrors!==!1;return{lineCounter:e.lineCounter||t&&new o.LineCounter||null,prettyErrors:t}}function parseAllDocuments(e,n={}){let{lineCounter:i,prettyErrors:a}=parseOptions(n),o=new s.Parser(i?.addNewLine),c=new t.Composer(n),l=Array.from(c.compose(o.parse(e)));if(a&&i)for(let t of l)t.errors.forEach(r.prettifyError(e,i)),t.warnings.forEach(r.prettifyError(e,i));return l.length>0?l:Object.assign([],{empty:!0},c.streamInfo())}function parseDocument(e,n={}){let{lineCounter:i,prettyErrors:a}=parseOptions(n),o=new s.Parser(i?.addNewLine),c=new t.Composer(n),l=null;for(let t of c.compose(o.parse(e),!0,e.length))if(!l)l=t;else if(l.options.logLevel!==`silent`){l.errors.push(new r.YAMLParseError(t.range.slice(0,2),`MULTIPLE_DOCS`,`Source contains multiple documents; please use YAML.parseAllDocuments()`));break}return a&&i&&(l.errors.forEach(r.prettifyError(e,i)),l.warnings.forEach(r.prettifyError(e,i))),l}function parse(e,t,n){let r;typeof t==`function`?r=t:n===void 0&&t&&typeof t==`object`&&(n=t);let a=parseDocument(e,n);if(!a)return null;if(a.warnings.forEach(e=>i.warn(a.options.logLevel,e)),a.errors.length>0){if(a.options.logLevel!==`silent`)throw a.errors[0];a.errors=[]}return a.toJS(Object.assign({reviver:r},n))}function stringify(e,t,r){let i=null;if(typeof t==`function`||Array.isArray(t)?i=t:r===void 0&&t&&(r=t),typeof r==`string`&&(r=r.length),typeof r==`number`){let e=Math.round(r);r=e<1?void 0:e>8?{indent:8}:{indent:e}}if(e===void 0){let{keepUndefined:e}=r??t??{};if(!e)return}return a.isDocument(e)&&!i?e.toString(r):new n.Document(e,i,r).toString(r)}e.parse=parse,e.parseAllDocuments=parseAllDocuments,e.parseDocument=parseDocument,e.stringify=stringify})),Y=(/* @__PURE__ */ __commonJSMin((e=>{var t=Xe(),n=G(),r=Fe(),i=K(),a=M(),o=O(),s=R(),c=N(),l=z(),u=V();et();var d=tt(),f=nt(),p=rt(),m=it(),h=k();e.Composer=t.Composer,e.Document=n.Document,e.Schema=r.Schema,e.YAMLError=i.YAMLError,e.YAMLParseError=i.YAMLParseError,e.YAMLWarning=i.YAMLWarning,e.Alias=a.Alias,e.isAlias=o.isAlias,e.isCollection=o.isCollection,e.isDocument=o.isDocument,e.isMap=o.isMap,e.isNode=o.isNode,e.isPair=o.isPair,e.isScalar=o.isScalar,e.isSeq=o.isSeq,e.Pair=s.Pair,e.Scalar=c.Scalar,e.YAMLMap=l.YAMLMap,e.YAMLSeq=u.YAMLSeq,e.Lexer=d.Lexer,e.LineCounter=f.LineCounter,e.Parser=p.Parser,e.parse=m.parse,e.parseAllDocuments=m.parseAllDocuments,e.parseDocument=m.parseDocument,e.stringify=m.stringify,e.visit=h.visit,e.visitAsync=h.visitAsync})))();const X=`Vite+`,Z=`vite-plus`;function resolvePath$1(e,t){return h.isAbsolute(e)?e:h.join(t,e)}function isWithin(e,t){let n=h.relative(t,e);return!h.isAbsolute(n)&&n!==`..`&&!n.startsWith(`..${h.sep}`)}function resolveProjectDirectory(e){let{workingDirectory:t,workspaceRoot:n}=e,r=h.isAbsolute(t)?t:h.join(n,t);try{if(!f(r).isDirectory())throw Error(`working-directory is not a directory: ${t} (resolved to ${r})`)}catch(e){throw e instanceof Error&&`code`in e&&e.code===`ENOENT`?Error(`working-directory not found: ${t} (resolved to ${r})`):e}return r}function isWindows(e=process.platform){return e===`win32`}function run(e,t,n={}){let r=w(e,t,{stdio:`inherit`,...n});if(r.error)throw r.error;if(r.status!==0)throw Error(`${e} ${t.join(` `)} exited with code ${r.status??1}`)}function runWithOutput(e,t,n={}){return new Promise((r,i)=>{let a=C(e,t,{...n,stdio:[`ignore`,`pipe`,`pipe`]}),o=``,s=``;a.stdout.on(`data`,e=>{process.stdout.write(e),o=(o+e.toString()).slice(-4e3)}),a.stderr.on(`data`,e=>{process.stderr.write(e),s=(s+e.toString()).slice(-4e3)}),a.on(`error`,i),a.on(`close`,e=>r({exitCode:e??1,stdout:o,stderr:s}))})}function commandPath(e){if(isWindows()){let t=w(`where`,[e],{encoding:`utf8`});return t.status===0&&t.stdout.trim().split(/\r?\n/)[0]?.trim()||void 0}let t=w(`sh`,[`-c`,`command -v "$1"`,`sh`,e],{encoding:`utf8`});if(t.status===0)return t.stdout.trim()}function getCommandOutput(e,t,n){let r=w(e,t,{cwd:n?.cwd,encoding:`utf8`,stdio:[`ignore`,`pipe`,`pipe`]});if(r.status===0)return r.stdout.trim()}const at=[{filename:`pnpm-lock.yaml`,type:`pnpm`},{filename:`bun.lockb`,type:`bun`},{filename:`bun.lock`,type:`bun`},{filename:`package-lock.json`,type:`npm`},{filename:`npm-shrinkwrap.json`,type:`npm`},{filename:`yarn.lock`,type:`yarn`}];function resolvePath(e,t){return v(e)?e:y(t,e)}function inferLockFileType(e,t){return t.includes(`pnpm`)?{type:`pnpm`,path:e,filename:t}:t.includes(`yarn`)?{type:`yarn`,path:e,filename:t}:t.startsWith(`bun.`)?{type:`bun`,path:e,filename:t}:{type:`npm`,path:e,filename:t}}function detectLockFile(e,t){if(e){let n=resolvePath(e,t);if(i(n)){let e=g(n),t=at.find(t=>t.filename===e);return t?{type:t.type,path:n,filename:e}:inferLockFileType(n,e)}return}let n=l(t);for(let e of at)if(n.includes(e.filename)){let n=y(t,e.filename);return{type:e.type,path:n,filename:e.filename}}}function prepareCacheMetadata(e){let{projectDir:t,cacheDependencyPath:n,logWarning:r}=e,i=detectLockFile(n||void 0,t);if(!i)return r?.(`setup-vp: cache is enabled but no supported lock file was found; skipping cache.`),{ready:!1};let a=getCommandOutput(`vp`,[`pm`,`cache`,`dir`],{cwd:h.dirname(i.path)});return a?{ready:!0,cachePath:a,lockFile:i.path,lockType:i.type}:(r?.(`setup-vp: could not resolve package-manager cache directory for ${i.filename}; skipping cache.`),{ready:!1})}function createLockfileResolver(e){let{getWorkspaceDir:t,info:n,debug:r}=e,a=/^\d+\.\d+\.\d+/;function tryResolveVitePlusVersionFromLockfile(e,t){let i=detectLockfileForProject(e,t);if(!i)return;let a=i.filename.endsWith(`.lockb`)?textBunLockBeside(i):i;if(!a){r(`Cannot read ${i.filename} (binary) to resolve the ${X} version; using "latest". Use the text bun.lock, or set the \`version\` input.`);return}let o=parseVitePlusVersionFromLockfile(a,workspaceSubPath(_(a.path),e));if(o)return n(`Resolved ${X} version '${o}' from ${a.filename}`),o;r(`No ${X} version found in ${a.path}`)}function detectLockfileForProject(e,n){if(n)return detectLockFile(n,e);let r=t(),i=e;for(;;){let e=detectLockFile(void 0,i);if(e)return e;let t=_(i);if(i===r||t===i||!isWithin(t,r))break;i=t}}function textBunLockBeside(e){let t=y(_(e.path),`bun.lock`);return i(t)?{type:`bun`,path:t,filename:`bun.lock`}:void 0}function workspaceSubPath(e,t){if(!isWithin(t,e))return``;let n=b(e,t);return n?n.split(x).join(`/`):``}function parseVitePlusVersionFromLockfile(e,t=``){if(e.filename.endsWith(`.lockb`))return;let n;try{n=c(e.path,`utf-8`)}catch{return}let r;switch(e.type){case`npm`:r=fromNpmLock(n,t);break;case`pnpm`:r=fromPnpmLock(n,t);break;case`yarn`:r=fromYarnLock(n);break;case`bun`:r=fromBunTextLock(n);break;default:return}return r&&a.test(r)?r:void 0}function fromNpmLock(e,t){let n;try{n=JSON.parse(e)}catch{return}let r=n.packages;if(t){let e=r?.[`${t}/node_modules/${Z}`]?.version;if(typeof e==`string`)return e;if(!npmPackageDeclaresVitePlus(r?.[t]))return}let i=r?.[`node_modules/${Z}`]?.version;if(typeof i==`string`)return i;let a=n.dependencies?.[Z]?.version;return typeof a==`string`?a:void 0}function npmPackageDeclaresVitePlus(e){if(!e)return!1;for(let t of[`dependencies`,`devDependencies`]){let n=e[t];if(n&&typeof n==`object`&&`vite-plus`in n)return!0}return!1}function fromPnpmLock(e,t){let n;try{n=(0,Y.parse)(e)}catch{return}if(!n||typeof n!=`object`)return;let r=n,i=r.importers;if(i&&typeof i==`object`){let e=t||`.`;return e in i?pnpmImporterVersion(i[e]):void 0}return pnpmImporterVersion(r)||e.match(/^\s*\/?vite-plus@(\d+\.\d+\.\d+[^\s():'"]*)/m)?.[1]}function pnpmImporterVersion(e){if(!e||typeof e!=`object`)return;let t=e;for(let e of[`dependencies`,`devDependencies`,`optionalDependencies`]){let n=t[e];if(n&&typeof n==`object`){let e=n[Z],t=typeof e==`string`?e:e?.version;if(typeof t==`string`){let e=t.replace(/\(.*$/,``).trim();if(a.test(e))return e}}}}function fromYarnLock(e){let t=/* @__PURE__ */ new Set,n=e.split(/\r?\n/);for(let e=0;ee,info:console.info,debug:()=>{},warning:console.warn}}const ot=`https://raw.githubusercontent.com/voidzero-dev/vite-plus`,st=`packages/cli`,ct=/^0\.0\.0-commit\.([0-9a-f]{40})$/i,lt=/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;function pkgPrNewCommitSha(e){return e.match(ct)?.[1]}function getInstallScriptUrls(e,t=process.platform){let n=isWindows(t)?`install.ps1`:`install.sh`,r=installScriptRef(e);return{pinned:r?[`${ot}/${r}/${st}/${n}`,`https://cdn.jsdelivr.net/gh/voidzero-dev/vite-plus@${r}/${st}/${n}`]:[],latest:[`https://viteplus.dev/${n}`,`${ot}/main/${st}/${n}`]}}function installScriptRef(e){let t=pkgPrNewCommitSha(e);if(t)return t.toLowerCase();if(lt.test(e))return`v${e}`}function parseInstalledVpVersion(e){return(e.match(/^\s*vp\s+v?(\d[^\s]*)/im)??e.match(/Global:\s*v?(\d[^\s]*)/i))?.[1]??`unknown`}const Q=`SETUP_VP_DIRS_FILE`,ut=/^v?(\d+)\.(\d+)\.\d+(?:-[0-9A-Za-z.-]+)?$/;function supportsVitePlusDirs(e){if(pkgPrNewCommitSha(e))return!0;let t=e.match(ut);if(!t)return!0;let n=Number(t[1]),r=Number(t[2]);return n>0||r>=3}function createVitePlusDirsFile(){return y(E(),`setup-vp-dirs-${ne()}.txt`)}function removeVitePlusDirsFile(e){d(e,{force:!0})}function readVitePlusProbe(e){try{return c(e,`utf8`)}catch(e){if(e.code===`ENOENT`)return;throw e}}function resolveVitePlusBinDir(e,t,n){if(!t){if(!supportsVitePlusDirs(e))return n;throw Error(`Vite+ was installed successfully, but setup-vp could not resolve its VpDirs.`)}let r=readVitePlusProbe(t),i=r===void 0?void 0:parseVitePlusDirs(r);if(i)return i.bin;if(!(pkgPrNewCommitSha(e)!==void 0||ut.test(e))&&r!==void 0){let e=parseInstalledVpVersion(r);if(e!==`unknown`&&!supportsVitePlusDirs(e))return n}throw Error(`Vite+ was installed successfully, but setup-vp could not resolve its VpDirs.`)}function parseVitePlusDirs(e){let t=/* @__PURE__ */ new Map;for(let n of e.split(/\r?\n/)){let e=n.indexOf(` `);if(e<1)continue;let r=n.slice(0,e).replace(/^\uFEFF/,``),i=n.slice(e+1).trim();i&&t.set(r,i)}let n=t.get(`data`),r=t.get(`bin`),i=t.get(`cache`),a=t.get(`config`),o=t.get(`state`);if(n&&r&&i&&a&&o)return{data:n,bin:r,cache:i,config:a,state:o}}function getInstallScriptCommand(e,t=process.platform,n=!0){if(isWindows(t))return n?{command:`pwsh`,args:[`-Command`,` +`)){let e=t.trim();if(!e||e.startsWith(`#`))continue;let[n,...r]=e.split(/\s+/);if(n===`nodejs`||n===`node`){for(let e of r)if(isAsdfInstallableVersion(e))return e}}}function isAsdfInstallableVersion(e){return!!e&&e!==`system`&&!e.startsWith(`ref:`)&&!e.startsWith(`path:`)}function parsePackageJson(e){let t;try{t=JSON.parse(e)}catch{throw Error(`Failed to parse package.json: invalid JSON`)}let n=t.devEngines;if(n?.runtime){let e=findNodeRuntime(n.runtime);if(e)return e}let r=t.engines;if(r?.node&&typeof r.node==`string`)return r.node}function findNodeRuntime(e){let t=Array.isArray(e)?e:[e];for(let e of t)if(e?.name===`node`&&typeof e.version==`string`)return e.version}return{resolveNodeVersionFile}}function resolutionContext(e){return{getWorkspaceDir:()=>e,info:console.info,debug:()=>{},warning:console.warn}}const ot=`https://raw.githubusercontent.com/voidzero-dev/vite-plus`,st=`packages/cli`,ct=/^0\.0\.0-commit\.([0-9a-f]{40})$/i,lt=/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;function pkgPrNewCommitSha(e){return e.match(ct)?.[1]}function getInstallScriptUrls(e,t=process.platform){let n=isWindows(t)?`install.ps1`:`install.sh`,r=installScriptRef(e);return{pinned:r?[`${ot}/${r}/${st}/${n}`,`https://cdn.jsdelivr.net/gh/voidzero-dev/vite-plus@${r}/${st}/${n}`]:[],latest:[`https://viteplus.dev/${n}`,`${ot}/main/${st}/${n}`]}}function installScriptRef(e){let t=pkgPrNewCommitSha(e);if(t)return t.toLowerCase();if(lt.test(e))return`v${e}`}function parseInstalledVpVersion(e){return(e.match(/^\s*vp\s+v?(\d[^\s]*)/im)??e.match(/Global:\s*v?(\d[^\s]*)/i))?.[1]??`unknown`}const Q=`SETUP_VP_DIRS_FILE`,ut=/^v?(\d+)\.(\d+)\.\d+(?:-[0-9A-Za-z.-]+)?$/;function supportsVitePlusDirs(e){if(pkgPrNewCommitSha(e))return!0;let t=e.match(ut);if(!t)return!0;let n=Number(t[1]),r=Number(t[2]);return n>0||r>=3}function createVitePlusDirsFile(){return y(E(),`setup-vp-dirs-${ne()}.txt`)}function removeVitePlusDirsFile(e){d(e,{force:!0})}function readVitePlusPath(e){if(e)return readVitePlusProbe(e)?.split(/\r?\n/).find(e=>e.startsWith(`path `))?.slice(5)}function readVitePlusProbe(e){try{return c(e,`utf8`)}catch(e){if(e.code===`ENOENT`)return;throw e}}function resolveVitePlusBinDir(e,t,n){if(!t){if(!supportsVitePlusDirs(e))return n;throw Error(`Vite+ was installed successfully, but setup-vp could not resolve its VpDirs.`)}let r=readVitePlusProbe(t),i=r===void 0?void 0:parseVitePlusDirs(r);if(i)return i.bin;if(!(pkgPrNewCommitSha(e)!==void 0||ut.test(e))&&r!==void 0){let e=parseInstalledVpVersion(r);if(e!==`unknown`&&!supportsVitePlusDirs(e))return n}throw Error(`Vite+ was installed successfully, but setup-vp could not resolve its VpDirs.`)}function parseVitePlusDirs(e){let t=/* @__PURE__ */ new Map;for(let n of e.split(/\r?\n/)){let e=n.indexOf(` `);if(e<1)continue;let r=n.slice(0,e).replace(/^\uFEFF/,``),i=n.slice(e+1).trim();i&&t.set(r,i)}let n=t.get(`data`),r=t.get(`bin`),i=t.get(`cache`),a=t.get(`config`),o=t.get(`state`);if(n&&r&&i&&a&&o)return{data:n,bin:r,cache:i,config:a,state:o}}function getInstallScriptCommand(e,t=process.platform,n=!0){if(isWindows(t))return n?{command:`pwsh`,args:[`-Command`,` $dirsFile = $env:${Q} Set-Content -LiteralPath $dirsFile -Value '' -NoNewline -Encoding UTF8 . ([scriptblock]::Create((irm -TimeoutSec 15 ${e}))) @@ -158,6 +158,15 @@ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } $env:VP_DUMP_DIRS = '1' & $vpPath | Add-Content -LiteralPath $dirsFile -Encoding UTF8 if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } +# Use Vite+'s generated environment so system-first shims stay last in PATH. +$configLine = Get-Content -LiteralPath $dirsFile | Where-Object { $_.StartsWith("config" + [char]9) } | Select-Object -Last 1 +if ($configLine) { + $envFile = Join-Path $configLine.Substring(7) 'env.ps1' + if (Test-Path -LiteralPath $envFile -PathType Leaf) { + . $envFile + Add-Content -LiteralPath $dirsFile -Value ("path" + [char]9 + $env:PATH) -Encoding UTF8 + } +} `.trim()]}:{command:`pwsh`,args:[`-Command`,`& ([scriptblock]::Create((irm -TimeoutSec 15 ${e})))`]};let r=` if command -v curl >/dev/null 2>&1; then curl -fsSL --connect-timeout 5 --max-time 15 "${e}"${n?` -o "$installer_file"`:``} @@ -179,15 +188,23 @@ vp_dir="\${SHIM_DIR:-\${INSTALL_DIR:-\${VP_HOME:-$HOME/.vite-plus}}/bin}" if [ -x "$vp_dir/vp" ]; then "$vp_dir/vp" --version > "$${Q}" VP_DUMP_DIRS=1 "$vp_dir/vp" >> "$${Q}" + # Read the resolved config directory, including split/custom installations. + while IFS=$'\\t' read -r key value; do + if [ "$key" = config ] && [ -f "$value/env" ]; then + source "$value/env" + printf 'path\\t%s\\n' "$PATH" >> "$${Q}" + break + fi + done < "$${Q}" fi `.trim()]}:{command:`bash`,args:[`-c`,` set +u set -o pipefail ${r} | bash -`.trim()]}}const dt=2e3;function getVitePlusHome(e=process.platform,t=process.env){let n=isWindows(e)?t.USERPROFILE||T():t.HOME||T();return y(n,`.vite-plus`)}function runInstallCommand(e,t,n=process.platform){let{command:r,args:i}=getInstallScriptCommand(e,n,t.VP_VPDIRS_AWARE===`1`),a={env:{...process.env,...t},stdio:`inherit`},o=w(r,i,a);if(isWindows(n)&&o.error?.code===`ENOENT`&&(o=w(`powershell.exe`,i,a)),o.error)throw o.error;return o.status??1}async function installVitePlus(e,t={}){let n=t.platform??process.platform,r=t.env??process.env,i=t.prependPath,a=t.sleep??ee,o=t.runInstall??runInstallCommand,s=t.logWarningFn??console.warn,c={...Object.fromEntries(Object.entries(r).filter(e=>e[1]!==void 0)),VP_VERSION:e,VITE_PLUS_VERSION:e},l=supportsVitePlusDirs(e)?createVitePlusDirsFile():void 0;l?(c.VP_VPDIRS_AWARE=`1`,c[Q]=l):(delete c.VP_VPDIRS_AWARE,delete c[Q]);let u=pkgPrNewCommitSha(e);u&&(c.VP_PR_VERSION=u);let{pinned:d,latest:f}=getInstallScriptUrls(e,n),p=d.length+f.length,m=2*p,h=``,g=0;async function tryUrls(e){for(let t=0;t<2;t+=1)for(let t of e){g+=1;try{let e=o(t,c,n);if(e===0)return!0;h=`exit code ${e}`}catch(e){h=e instanceof Error?e.message:String(e)}g0){if(await tryUrls(d)){ensureBinInPath();return}s(`setup-vp: could not fetch the install script pinned to Vite+ ${e}. Falling back to the latest install script. The latest script may not be compatible with ${e}.`)}if(await tryUrls(f)){ensureBinInPath();return}throw Error(`Failed to install Vite+ after ${m} attempts across ${p} URL(s): ${h}`)}finally{l&&removeVitePlusDirsFile(l)}}function copyCacheDirectory(e,t,r){e=h.resolve(e),t=h.resolve(t),n(e,t,{recursive:!0,force:r,errorOnExist:!1,filter:(n,i)=>{let s=a(i,{throwIfNoEntry:!1}),c=a(n);if(s&&!r)return c.isDirectory()&&s.isDirectory();if(s&&(s.isSymbolicLink()||c.isSymbolicLink())&&d(i,{recursive:!0,force:!0}),c.isSymbolicLink()){let r=h.resolve(h.dirname(n),u(n)),a=r;if(isWithin(r,e)){let n=h.join(t,h.relative(e,r));a=h.relative(h.dirname(i),n)||`.`}return o(h.dirname(i),{recursive:!0}),p(a,i,f(r,{throwIfNoEntry:!1})?.isDirectory()?`dir`:`file`),!1}return!0}})}function restoreCacheSnapshot(e,t,n=console.warn,r=!0){if(!e.ready||!e.cachePath||!e.lockFile||!e.lockType)return{hit:!1,save:()=>{}};let a=e.cachePath;if(isWithin(h.resolve(a),h.resolve(t))||isWithin(h.resolve(t),h.resolve(a)))return n(`setup-vp: package-manager cache overlaps the snapshot directory; skipping cache.`),{hit:!1,save:()=>{}};let s=h.join(t,process.platform,process.arch,e.lockType),l=h.join(s,`packages`),u=h.join(s,`lock-hash`),d=e.lockFile;function hashLockFile(){return te(`sha256`).update(c(d)).digest(`hex`)}let f;try{f=hashLockFile()}catch(e){return n(`setup-vp: could not read cache lock file: ${String(e)}`),{hit:!1,save:()=>{}}}let p=!1;try{r&&i(l)&&(o(a,{recursive:!0}),copyCacheDirectory(l,a,!1),p=c(u,`utf8`)===f)}catch(e){n(`setup-vp: could not restore package-manager cache: ${String(e)}`)}return{hit:p,save:()=>{try{if(!i(a))return;let e=hashLockFile();o(s,{recursive:!0}),copyCacheDirectory(a,l,!0),m(u,e,`utf8`)}catch(e){n(`setup-vp: could not save package-manager cache: ${String(e)}`)}}}}const ft=/* @__PURE__ */ new Set([`true`,`True`,`TRUE`]),pt=/* @__PURE__ */ new Set([`false`,`False`,`FALSE`]);function parseNodeManager(e){if(e){if(ft.has(e))return!0;if(pt.has(e))return!1;throw Error(`Invalid node-manager input: "${e}". Expected "true", "false", or unset.`)}}function supportsScopedEnv(e){let t=parseInstalledVpVersion(e);if(t.startsWith(`0.0.0-commit.`))return!0;let n=t.match(/^(\d+)\.(\d+)\.(\d+)/);if(!n)throw Error(`Could not determine the installed Vite+ version for env configuration.`);let[,r,i,a]=n.map(Number);return r>0||i>3||i===3&&a>=1}function nodeManagerOffArgs(e){return parseInstalledVpVersion(e).startsWith(`0.0.0-commit.`)&&console.info("setup-vp: node-manager: false requires a preview build that supports `vp env off node`. If this command is unsupported, use a newer preview or a stable release. setup-vp will not fall back to disabling package-manager management."),supportsScopedEnv(e)?[`env`,`off`,`node`]:[`env`,`off`]}const mt=[`npm`,`pnpm`,`yarn`,`bun`];function parsePackageManager(e){if(!e?.trim())return;let t;try{t=(0,Y.parse)(e)}catch(e){throw Error(`Invalid package-manager input: ${String(e)}`)}if(t!==``){if(typeof t==`boolean`)return t;if(t&&typeof t==`object`&&!Array.isArray(t)){for(let[e,n]of Object.entries(t))if(!mt.includes(e)||typeof n!=`boolean`)throw Error(`Invalid package-manager input: ${e} must be npm, pnpm, yarn, or bun with a boolean value.`);return t}throw Error(`Invalid package-manager input: expected a boolean or a mapping of npm, pnpm, yarn, and bun to booleans.`)}}function packageManagerArgs(e,t){if(e===void 0)return[];if(!supportsScopedEnv(t))throw Error(`package-manager configuration requires Vite+ 0.3.1 or newer.`);return typeof e==`boolean`?e?[]:[[`env`,`off`,`pm`]]:mt.filter(t=>e[t]===!1).map(e=>[`env`,`off`,e])}function readNpmrc(e){try{return c(e,`utf8`)}catch(e){if(e.code===`ENOENT`)return``;throw e}}function authKeyFor(e){return(e.replace(/^\w+:/,``)+`:_authtoken`).toLowerCase()}function analyzeProjectNpmrc(e){let t=/* @__PURE__ */ new Set,n=/* @__PURE__ */ new Set,r=/* @__PURE__ */ new Set;for(let i of e.split(/\r?\n/)){let e=i.trim();if(!e||e.startsWith(`;`)||e.startsWith(`#`))continue;let a=e.indexOf(`=`);if(a<0)continue;let o=e.slice(0,a).trim().toLowerCase(),s=e.slice(a+1).trim();(o===`registry`||o.endsWith(`:registry`))&&(s.includes("${")||t.add(s.endsWith(`/`)?s:s+`/`)),o.startsWith(`//`)&&o.endsWith(`:_authtoken`)&&n.add(o);for(let e of s.matchAll(/\$\{(\w+)\}/g))r.add(e[1])}return{registriesNeedingAuth:[...t].filter(e=>!n.has(authKeyFor(e))),envVarRefs:r}}function readUserConfigLines(e,t){let n=e.HOME||e.USERPROFILE,r=e.NPM_CONFIG_USERCONFIG||e.PNPM_CONFIG_USERCONFIG||n&&h.join(n,`.npmrc`);return(r?readNpmrc(r):``).split(/\r?\n/).filter(e=>!t.has(e.split(`=`)[0].trim().toLowerCase()))}function isReservedAuthVariable(e){return[`GITHUB_TOKEN`,`CI_JOB_TOKEN`,`SYSTEM_ACCESSTOKEN`].includes(e)?!1:/^(?:PATH|HOME|USERPROFILE|TMPDIR|CI)$/i.test(e)||/^(?:SETUP_VP_|RUNNER_|GITHUB_|CI_|SYSTEM_|AGENT_|BUILD_|RELEASE_)/i.test(e)}function writeUserConfig(e,t,n){let r=s(h.join(E(),`setup-vp-npmrc-`)),i=h.join(r,`.npmrc`);m(i,e,{encoding:`utf8`,mode:384});for(let e of[`NPM_CONFIG_USERCONFIG`,`PNPM_CONFIG_USERCONFIG`])t[e]=i,n?.(e,i);return i}function configureAuth$1(e,t,n,r,i){if(!e){if(!i)return;let{registriesNeedingAuth:e,envVarRefs:t}=analyzeProjectNpmrc(readNpmrc(h.join(i,`.npmrc`))),a;if(n.NODE_AUTH_TOKEN&&e.length>0){let i=readUserConfigLines(n,new Set(e.map(e=>(e.replace(/^\w+:/,``)+`:_authtoken`).toLowerCase())));i.push(...e.map(e=>e.replace(/^\w+:/,``)+":_authToken=${NODE_AUTH_TOKEN}")),a=writeUserConfig(i.join(` +`.trim()]}}const dt=2e3;function getVitePlusHome(e=process.platform,t=process.env){let n=isWindows(e)?t.USERPROFILE||T():t.HOME||T();return y(n,`.vite-plus`)}function runInstallCommand(e,t,n=process.platform){let{command:r,args:i}=getInstallScriptCommand(e,n,t.VP_VPDIRS_AWARE===`1`),a={env:{...process.env,...t},stdio:`inherit`},o=w(r,i,a);if(isWindows(n)&&o.error?.code===`ENOENT`&&(o=w(`powershell.exe`,i,a)),o.error)throw o.error;return o.status??1}async function installVitePlus(e,t={}){let n=t.platform??process.platform,r=t.env??process.env,i=t.prependPath,a=t.sleep??ee,o=t.runInstall??runInstallCommand,s=t.logWarningFn??console.warn,c={...Object.fromEntries(Object.entries(r).filter(e=>e[1]!==void 0)),VP_VERSION:e,VITE_PLUS_VERSION:e},l=supportsVitePlusDirs(e)?createVitePlusDirsFile():void 0;l?(c.VP_VPDIRS_AWARE=`1`,c[Q]=l):(delete c.VP_VPDIRS_AWARE,delete c[Q]);let u=pkgPrNewCommitSha(e);u&&(c.VP_PR_VERSION=u);let{pinned:d,latest:f}=getInstallScriptUrls(e,n),p=d.length+f.length,m=2*p,h=``,g=0;async function tryUrls(e){for(let t=0;t<2;t+=1)for(let t of e){g+=1;try{let e=o(t,c,n);if(e===0)return!0;h=`exit code ${e}`}catch(e){h=e instanceof Error?e.message:String(e)}g0){if(await tryUrls(d)){ensureBinInPath();return}s(`setup-vp: could not fetch the install script pinned to Vite+ ${e}. Falling back to the latest install script. The latest script may not be compatible with ${e}.`)}if(await tryUrls(f)){ensureBinInPath();return}throw Error(`Failed to install Vite+ after ${m} attempts across ${p} URL(s): ${h}`)}finally{l&&removeVitePlusDirsFile(l)}}function copyCacheDirectory(e,t,r){e=h.resolve(e),t=h.resolve(t),n(e,t,{recursive:!0,force:r,errorOnExist:!1,filter:(n,i)=>{let s=a(i,{throwIfNoEntry:!1}),c=a(n);if(s&&!r)return c.isDirectory()&&s.isDirectory();if(s&&(s.isSymbolicLink()||c.isSymbolicLink())&&d(i,{recursive:!0,force:!0}),c.isSymbolicLink()){let r=h.resolve(h.dirname(n),u(n)),a=r;if(isWithin(r,e)){let n=h.join(t,h.relative(e,r));a=h.relative(h.dirname(i),n)||`.`}return o(h.dirname(i),{recursive:!0}),p(a,i,f(r,{throwIfNoEntry:!1})?.isDirectory()?`dir`:`file`),!1}return!0}})}function restoreCacheSnapshot(e,t,n=console.warn,r=!0){if(!e.ready||!e.cachePath||!e.lockFile||!e.lockType)return{hit:!1,save:()=>{}};let a=e.cachePath;if(isWithin(h.resolve(a),h.resolve(t))||isWithin(h.resolve(t),h.resolve(a)))return n(`setup-vp: package-manager cache overlaps the snapshot directory; skipping cache.`),{hit:!1,save:()=>{}};let s=h.join(t,process.platform,process.arch,e.lockType),l=h.join(s,`packages`),u=h.join(s,`lock-hash`),d=e.lockFile;function hashLockFile(){return te(`sha256`).update(c(d)).digest(`hex`)}let f;try{f=hashLockFile()}catch(e){return n(`setup-vp: could not read cache lock file: ${String(e)}`),{hit:!1,save:()=>{}}}let p=!1;try{r&&i(l)&&(o(a,{recursive:!0}),copyCacheDirectory(l,a,!1),p=c(u,`utf8`)===f)}catch(e){n(`setup-vp: could not restore package-manager cache: ${String(e)}`)}return{hit:p,save:()=>{try{if(!i(a))return;let e=hashLockFile();o(s,{recursive:!0}),copyCacheDirectory(a,l,!0),m(u,e,`utf8`)}catch(e){n(`setup-vp: could not save package-manager cache: ${String(e)}`)}}}}const ft=/* @__PURE__ */ new Set([`true`,`True`,`TRUE`]),pt=/* @__PURE__ */ new Set([`false`,`False`,`FALSE`]);function parseNodeManager(e){if(e){if(ft.has(e))return!0;if(pt.has(e))return!1;throw Error(`Invalid node-manager input: "${e}". Expected "true", "false", or unset.`)}}function supportsScopedEnv(e){let t=parseInstalledVpVersion(e);if(t.startsWith(`0.0.0-commit.`))return!0;let n=t.match(/^(\d+)\.(\d+)\.(\d+)/);if(!n)throw Error(`Could not determine the installed Vite+ version for env configuration.`);let[,r,i,a]=n.map(Number);return r>0||i>3||i===3&&a>=1}function nodeManagerOffArgs(e){return parseInstalledVpVersion(e).startsWith(`0.0.0-commit.`)&&console.info("setup-vp: node-manager: false requires a preview build that supports `vp env off node`. If this command is unsupported, use a newer preview or a stable release. setup-vp will not fall back to disabling package-manager management."),supportsScopedEnv(e)?[`env`,`off`,`node`]:[`env`,`off`]}const mt=[`npm`,`pnpm`,`yarn`,`bun`];function parsePackageManager(e){if(!e?.trim())return;let t;try{t=(0,Y.parse)(e)}catch(e){throw Error(`Invalid package-manager input: ${String(e)}`)}if(t!==``){if(typeof t==`boolean`)return t;if(t&&typeof t==`object`&&!Array.isArray(t)){for(let[e,n]of Object.entries(t))if(!mt.includes(e)||typeof n!=`boolean`)throw Error(`Invalid package-manager input: ${e} must be npm, pnpm, yarn, or bun with a boolean value.`);return t}throw Error(`Invalid package-manager input: expected a boolean or a mapping of npm, pnpm, yarn, and bun to booleans.`)}}function packageManagerArgs(e,t){if(e===void 0)return[];if(!supportsScopedEnv(t))throw Error(`package-manager configuration requires Vite+ 0.3.1 or newer.`);return typeof e==`boolean`?e?[]:[[`env`,`off`,`pm`]]:mt.filter(t=>e[t]===!1).map(e=>[`env`,`off`,e])}function readNpmrc(e){try{return c(e,`utf8`)}catch(e){if(e.code===`ENOENT`)return``;throw e}}function authKeyFor(e){return(e.replace(/^\w+:/,``)+`:_authtoken`).toLowerCase()}function analyzeProjectNpmrc(e){let t=/* @__PURE__ */ new Set,n=/* @__PURE__ */ new Set,r=/* @__PURE__ */ new Set;for(let i of e.split(/\r?\n/)){let e=i.trim();if(!e||e.startsWith(`;`)||e.startsWith(`#`))continue;let a=e.indexOf(`=`);if(a<0)continue;let o=e.slice(0,a).trim().toLowerCase(),s=e.slice(a+1).trim();(o===`registry`||o.endsWith(`:registry`))&&(s.includes("${")||t.add(s.endsWith(`/`)?s:s+`/`)),o.startsWith(`//`)&&o.endsWith(`:_authtoken`)&&n.add(o);for(let e of s.matchAll(/\$\{(\w+)\}/g))r.add(e[1])}return{registriesNeedingAuth:[...t].filter(e=>!n.has(authKeyFor(e))),envVarRefs:r}}function readUserConfigLines(e,t){let n=e.HOME||e.USERPROFILE,r=e.NPM_CONFIG_USERCONFIG||e.PNPM_CONFIG_USERCONFIG||n&&h.join(n,`.npmrc`);return(r?readNpmrc(r):``).split(/\r?\n/).filter(e=>!t.has(e.split(`=`)[0].trim().toLowerCase()))}function isReservedAuthVariable(e){return[`GITHUB_TOKEN`,`CI_JOB_TOKEN`,`SYSTEM_ACCESSTOKEN`].includes(e)?!1:/^(?:PATH|HOME|USERPROFILE|TMPDIR|CI)$/i.test(e)||/^(?:SETUP_VP_|RUNNER_|GITHUB_|CI_|SYSTEM_|AGENT_|BUILD_|RELEASE_)/i.test(e)}function writeUserConfig(e,t,n){let r=s(h.join(E(),`setup-vp-npmrc-`)),i=h.join(r,`.npmrc`);m(i,e,{encoding:`utf8`,mode:384});for(let e of[`NPM_CONFIG_USERCONFIG`,`PNPM_CONFIG_USERCONFIG`])t[e]=i,n?.(e,i);return i}function configureAuth$1(e,t,n,r,i){if(!e){if(!i)return;let{registriesNeedingAuth:e,envVarRefs:t}=analyzeProjectNpmrc(readNpmrc(h.join(i,`.npmrc`))),a;if(n.NODE_AUTH_TOKEN&&e.length>0){let i=readUserConfigLines(n,new Set(e.map(e=>(e.replace(/^\w+:/,``)+`:_authtoken`).toLowerCase())));i.push(...e.map(e=>e.replace(/^\w+:/,``)+":_authToken=${NODE_AUTH_TOKEN}")),a=writeUserConfig(i.join(` `)+` `,n,r),t.add(`NODE_AUTH_TOKEN`)}for(let e of t)!isReservedAuthVariable(e)&&n[e]&&r?.(e,n[e]);return a}let a;try{a=new URL(e)}catch{throw Error(`Invalid registry-url: "${e}". Must be a valid URL.`)}let o=a.href.endsWith(`/`)?a.href:`${a.href}/`,s=``;t&&(s=`${(t.startsWith(`@`)?t:`@${t}`).toLowerCase()}:`);let c=o.replace(/^\w+:/,``).toLowerCase(),l=readUserConfigLines(n,/* @__PURE__ */ new Set([`${s}registry`,`${c}:_authtoken`]));l.push(`${c}:_authToken=\${NODE_AUTH_TOKEN}`,`${s}registry=${o}`);let u=writeUserConfig(l.filter(Boolean).join(` `)+` `,n,r);return n.NODE_AUTH_TOKEN=n.NODE_AUTH_TOKEN||`XXXXX-XXXXX-XXXXX-XXXXX`,r?.(`NODE_AUTH_TOKEN`,n.NODE_AUTH_TOKEN),u}function shellQuote(e){return`'${String(e).replaceAll(`'`,`'\\''`)}'`}function exportShellEnv(e,t,n=process.env){if(!n.SETUP_VP_ENV_FILE||t===void 0)return;if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e))throw Error(`Invalid environment variable name`);let r=n.SETUP_VP_ENV_FORMAT===`powershell`?`$env:${e} = '${t.replaceAll(`'`,`''`)}'\n`:`export ${e}=${shellQuote(t)}\n`;m(n.SETUP_VP_ENV_FILE,r,{encoding:`utf8`,flag:`a`})}function configureAuth(e,t,n=process.env,r){return configureAuth$1(e,t,n,n===process.env?(e,t)=>exportShellEnv(e,t,n):void 0,r)}function resolveSfwEnabled(e,t,n){return e?!pkgPrNewCommitSha(t)||(n(`sfw was requested but is automatically disabled for Vite+ preview build ${t}; Socket Firewall Free will not be used.`),!1):!1}const $=`v1.15.1`,ht=`https://github.com/SocketDev/sfw-free/releases/download/${$}`;function isMuslLinux(){if(process.platform!==`linux`)return!1;try{let e=process.report?.getReport();if(e?.header&&!e.header.glibcVersionRuntime)return!0}catch{}return i(`/etc/alpine-release`)}function getSfwAssetName(e,t,n){if(e===`darwin`){if(t===`arm64`)return`sfw-free-macos-arm64`;if(t===`x64`)return`sfw-free-macos-x86_64`}else if(e===`linux`){if(t===`arm64`)return n?`sfw-free-musl-linux-arm64`:`sfw-free-linux-arm64`;if(t===`x64`)return n?`sfw-free-musl-linux-x86_64`:`sfw-free-linux-x86_64`}else if(isWindows(e)){if(t===`arm64`)return`sfw-free-windows-arm64.exe`;if(t===`x64`)return`sfw-free-windows-x86_64.exe`}throw Error(`Unsupported platform/arch for sfw: ${e}/${t}${e===`linux`?` (${n?`musl`:`glibc`})`:``}`)}function downloadFileWithShell(e,t,n){let r=Math.max(1,Math.ceil(n/1e3)),i=commandPath(`curl`);if(i){let n=w(i,[`-fsSL`,`--connect-timeout`,`5`,`--max-time`,String(r),e,`-o`,t],{stdio:`ignore`});if(n.status===0)return;throw n.error||/* @__PURE__ */ Error(`curl failed while downloading ${e}`)}let a=commandPath(`wget`);if(a){let n=w(a,[`-q`,`-T`,String(r),`-t`,`2`,`-O`,t,e],{stdio:`ignore`});if(n.status===0)return;throw n.error||/* @__PURE__ */ Error(`wget failed while downloading ${e}`)}throw Error(`curl or wget is required to download sfw`)}function downloadFile(e,t,n=0,i=6e4,a){return n>5?Promise.reject(/* @__PURE__ */ Error(`too many redirects while downloading ${e}`)):a?new Promise((o,s)=>{let c=!1,finish=e=>{c||(c=!0,clearTimeout(u),e?s(e):o())},l=a(e,o=>{let s=o.statusCode??0,c=o.headers.location;if(s>=300&&s<400&&c){o.resume(),downloadFile(new URL(c,e).toString(),t,n+1,i,a).then(()=>finish(),finish);return}if(s!==200){o.resume(),finish(/* @__PURE__ */ Error(`download failed with HTTP ${s}: ${e}`));return}let l=r(t);o.pipe(l),l.on(`finish`,()=>l.close(()=>finish())),l.on(`error`,finish)}),u=setTimeout(()=>{l.destroy(/* @__PURE__ */ Error(`download timed out after ${i}ms: ${e}`))},i);l.on(`error`,finish)}):(downloadFileWithShell(e,t,i),Promise.resolve())}async function setupSfw$1(e,t={}){let n=t.env??process.env,r=t.sfwEnabled??n.SETUP_VP_SFW===`true`,i=t.platform??process.platform,a=t.arch??process.arch,o=t.isMusl??isMuslLinux(),s=t.download??downloadFile;if(!resolveSfwEnabled(r,t.vitePlusVersion??``,t.logWarning??console.warn))return`vp`;if(e.length===0)return console.log(`setup-vp: sfw was requested but run-install is disabled; sfw will not be invoked.`),`vp`;let c=commandPath(`sfw`);if(c)return console.log(`setup-vp: using existing sfw on PATH: ${c}`),`sfw`;let l;try{l=getSfwAssetName(i,a,o)}catch{return console.error(`setup-vp: sfw has no published binary for this runner's platform/architecture (process.platform=${i}, process.arch=${a}, musl=${o}) and none was found on PATH; falling back to plain vp install.`),`vp`}let u=t.cacheDirectory||n.SETUP_VP_SFW_CACHE_DIR,d=u?h.join(u,$,l):await ae(h.join(E(),`setup-vp-sfw-`));await ie(d,{recursive:!0});let f=h.join(d,isWindows(i)?`sfw.exe`:`sfw`),p=`${ht}/${l}`;function activate(){let e=isWindows(i)?`;`:`:`;return n.PATH=`${d}${e}${n.PATH||``}`,t.exportVariable?.(`PATH`,n.PATH),`sfw`}if(await ce(f).then(e=>e.isFile()&&e.size>0,()=>!1))return console.log(`setup-vp: using cached sfw ${$}: ${f}`),activate();for(let e=1;e<=2;e+=1){let t=await ae(h.join(d,`.download-`)),n=h.join(t,`sfw`);try{if(console.log(`setup-vp: installing sfw ${$} from ${p}`),await s(p,n),(await ce(n)).size===0)throw Error(`Downloaded sfw binary is empty`);return await re(n,493),await oe(n,f),activate()}catch(t){if(e===2)throw t;await new Promise(e=>setTimeout(e,2e3))}finally{await se(t,{recursive:!0,force:!0})}}throw Error(`failed to install sfw after retrying`)}async function setupSfw(e,t=process.env,n=``){return setupSfw$1(e,{env:t,vitePlusVersion:n,exportVariable:(e,n)=>exportShellEnv(e,n,t)})}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function validateRunInstallEntry(e){if(!isRecord(e))throw Error(`run-install entries must be objects`);for(let t of Object.keys(e))if(t!==`cwd`&&t!==`args`)throw Error(`unsupported run-install key: ${t}`);let t={};if(e.cwd!==void 0){if(typeof e.cwd!=`string`)throw Error(`run-install.cwd must be a string`);t.cwd=e.cwd}if(e.args!==void 0){if(!Array.isArray(e.args)||e.args.some(e=>typeof e!=`string`))throw Error(`run-install.args must be an array of strings`);t.args=e.args}return t}function validateRunInstallInput(e){return e===null||typeof e==`boolean`?e:Array.isArray(e)?e.map(validateRunInstallEntry):validateRunInstallEntry(e)}function parseRunInstall(e){let t=validateRunInstallInput((0,Y.parse)(e)??null);return t?t===!0?[{}]:Array.isArray(t)?t:[t]:[]}function isSfwVpNotFoundFlake(e,t){return/Command 'vp' not found in PATH/.test(e+` `+t)}async function runInstall(e,t,n,r=process.env,i={}){let a={...r};delete a.SETUP_VP_ENV_FILE;let o=i.execute??runWithOutput,s=[];for(let r of e){let e=r.cwd?h.resolve(t,r.cwd):t,c=[`install`,...r.args||[]],l=n===`sfw`?[`vp`,...c]:c,u=`${n} ${l.join(` `)} (cwd: ${e})`;console.log(`setup-vp: running ${u}`);try{let t=await o(n,l,{cwd:e,env:a});if(t.exitCode!==0&&n===`sfw`&&isSfwVpNotFoundFlake(t.stdout,t.stderr)){let r=isWindows(i.platform);if(console.warn(r?`setup-vp: sfw could not resolve vp; warming the PowerShell command cache and retrying once.`:`setup-vp: sfw could not resolve vp; retrying once.`),r)try{await o(`powershell.exe`,[`-NoProfile`,`-Command`,`Get-Command vp`],{cwd:e,env:a})}catch{}t=await o(n,l,{cwd:e,env:a})}t.exitCode!==0&&s.push(`${u} exited with code ${t.exitCode}\n${t.stderr.trim()||t.stdout.trim()}`)}catch(e){s.push(`${u}: ${String(e)}`)}}if(s.length)throw Error(s.join(` -`))}function resolveProjectDir(e=process.env){return resolveProjectDirectory({workingDirectory:e.SETUP_VP_WORKING_DIRECTORY||`.`,workspaceRoot:e.CI_PROJECT_DIR||process.cwd()})}function fail(e){console.error(`setup-vp: ${e}`),process.exit(1)}function applyEnvironmentModes(e=process.env,t=run){let n=parseNodeManager(e.SETUP_VP_NODE_MANAGER),r=parsePackageManager(e.SETUP_VP_PACKAGE_MANAGER),i=(n===!1||r!==void 0)&&getCommandOutput(`vp`,[`--version`])||``,a=packageManagerArgs(r,i);n===!1&&t(`vp`,nodeManagerOffArgs(i));for(let e of a)t(`vp`,e)}async function main(e=`setup`){let n=process.env,r=n.CI_PROJECT_DIR||process.cwd(),i=h.join(r,`.setup-vp-cache`),a=h.join(r,`.setup-vp-cache-state.json`),o=h.join(r,`.setup-vp-outputs.env`);if(e===`save-cache`){restoreCacheSnapshot(JSON.parse(c(a,`utf8`)),i,console.warn,!1).save();return}if(e!==`setup`)throw Error(`Invalid GitLab phase: ${e}`);let s=resolveProjectDir(n);d(a,{force:!0}),d(o,{force:!0});let l=resolutionContext(r),u=parseNodeManager(n.SETUP_VP_NODE_MANAGER);parsePackageManager(n.SETUP_VP_PACKAGE_MANAGER);let f=parseRunInstall(n.SETUP_VP_RUN_INSTALL??`true`);if(u===!1&&(n.SETUP_VP_NODE_VERSION||n.SETUP_VP_NODE_VERSION_FILE))throw Error(`node-version and node-version-file cannot be used with node-manager: false`);let p=n.SETUP_VP_NODE_VERSION||(n.SETUP_VP_NODE_VERSION_FILE?createNodeVersionResolver(l).resolveNodeVersionFile(n.SETUP_VP_NODE_VERSION_FILE,s):void 0),g=createVersionResolver(l).resolveVitePlusVersion({version:n.SETUP_VP_VERSION,versionFile:n.SETUP_VP_VERSION_FILE,cacheDependencyPath:n.SETUP_VP_CACHE_DEPENDENCY_PATH},s);await installVitePlus(g,{env:n,prependPath:()=>exportShellEnv(`PATH`,n.PATH)}),applyEnvironmentModes(),p&&run(`vp`,[`env`,`use`,p],{cwd:s}),configureAuth(n.SETUP_VP_REGISTRY_URL||``,n.SETUP_VP_SCOPE||``,n,s);let _=n.SETUP_VP_CACHE?.toLowerCase()===`true`;_?n.SETUP_VP_SFW_CACHE_DIR=h.join(i,`sfw`):delete n.SETUP_VP_SFW_CACHE_DIR;let v=_?prepareCacheMetadata({projectDir:s,cacheDependencyPath:n.SETUP_VP_CACHE_DEPENDENCY_PATH,logWarning:console.warn}):{ready:!1},y=restoreCacheSnapshot(v,i),b=n.SETUP_VP_CACHE_SAVE?.toLowerCase()!==`false`;v.ready&&b&&(m(a,JSON.stringify(v),{mode:384}),t(process.argv[1],h.join(r,`.setup-vp-runtime.mjs`))),await runInstall(f,s,await setupSfw(f,n,g)),b&&y.save();let x=getCommandOutput(`vp`,[`--version`],{cwd:s});if(!x)throw Error(`Failed to verify Vite+ installation: vp --version failed or returned no output.`);console.log(x);let S={SETUP_VP_INSTALLED_VERSION:parseInstalledVpVersion(x),SETUP_VP_CACHE_HIT:String(y.hit)};for(let[e,t]of Object.entries(S))n[e]=t,exportShellEnv(e,t);m(o,Object.entries(S).map(([e,t])=>`${e}=${t}\n`).join(``),{mode:384})}function isEntrypoint(e=process.argv[1],t=import.meta.url){return!!(e&&t===S(h.resolve(e)).href)}if(isEntrypoint())try{await main(process.argv[2])}catch(e){fail(e instanceof Error?e.message:String(e))}export{applyEnvironmentModes,isEntrypoint,main}; \ No newline at end of file +`))}function resolveProjectDir(e=process.env){return resolveProjectDirectory({workingDirectory:e.SETUP_VP_WORKING_DIRECTORY||`.`,workspaceRoot:e.CI_PROJECT_DIR||process.cwd()})}function fail(e){console.error(`setup-vp: ${e}`),process.exit(1)}function applyEnvironmentModes(e=process.env,t=run){let n=parseNodeManager(e.SETUP_VP_NODE_MANAGER),r=parsePackageManager(e.SETUP_VP_PACKAGE_MANAGER),i=(n===!1||r!==void 0)&&getCommandOutput(`vp`,[`--version`])||``,a=packageManagerArgs(r,i);n===!1&&t(`vp`,nodeManagerOffArgs(i));for(let e of a)t(`vp`,e)}async function main(e=`setup`){let n=process.env,r=n.CI_PROJECT_DIR||process.cwd(),i=h.join(r,`.setup-vp-cache`),a=h.join(r,`.setup-vp-cache-state.json`),o=h.join(r,`.setup-vp-outputs.env`);if(e===`save-cache`){restoreCacheSnapshot(JSON.parse(c(a,`utf8`)),i,console.warn,!1).save();return}if(e!==`setup`)throw Error(`Invalid GitLab phase: ${e}`);let s=resolveProjectDir(n);d(a,{force:!0}),d(o,{force:!0});let l=resolutionContext(r),u=parseNodeManager(n.SETUP_VP_NODE_MANAGER);parsePackageManager(n.SETUP_VP_PACKAGE_MANAGER);let f=parseRunInstall(n.SETUP_VP_RUN_INSTALL??`true`);if(u===!1&&(n.SETUP_VP_NODE_VERSION||n.SETUP_VP_NODE_VERSION_FILE))throw Error(`node-version and node-version-file cannot be used with node-manager: false`);let p=n.SETUP_VP_NODE_VERSION||(n.SETUP_VP_NODE_VERSION_FILE?createNodeVersionResolver(l).resolveNodeVersionFile(n.SETUP_VP_NODE_VERSION_FILE,s):void 0),g=createVersionResolver(l).resolveVitePlusVersion({version:n.SETUP_VP_VERSION,versionFile:n.SETUP_VP_VERSION_FILE,cacheDependencyPath:n.SETUP_VP_CACHE_DEPENDENCY_PATH},s);await installVitePlus(g,{env:n,exportPath:e=>exportShellEnv(`PATH`,e)}),applyEnvironmentModes(),p&&run(`vp`,[`env`,`use`,p],{cwd:s}),configureAuth(n.SETUP_VP_REGISTRY_URL||``,n.SETUP_VP_SCOPE||``,n,s);let _=n.SETUP_VP_CACHE?.toLowerCase()===`true`;_?n.SETUP_VP_SFW_CACHE_DIR=h.join(i,`sfw`):delete n.SETUP_VP_SFW_CACHE_DIR;let v=_?prepareCacheMetadata({projectDir:s,cacheDependencyPath:n.SETUP_VP_CACHE_DEPENDENCY_PATH,logWarning:console.warn}):{ready:!1},y=restoreCacheSnapshot(v,i),b=n.SETUP_VP_CACHE_SAVE?.toLowerCase()!==`false`;v.ready&&b&&(m(a,JSON.stringify(v),{mode:384}),t(process.argv[1],h.join(r,`.setup-vp-runtime.mjs`))),await runInstall(f,s,await setupSfw(f,n,g)),b&&y.save();let x=getCommandOutput(`vp`,[`--version`],{cwd:s});if(!x)throw Error(`Failed to verify Vite+ installation: vp --version failed or returned no output.`);console.log(x);let S={SETUP_VP_INSTALLED_VERSION:parseInstalledVpVersion(x),SETUP_VP_CACHE_HIT:String(y.hit)};for(let[e,t]of Object.entries(S))n[e]=t,exportShellEnv(e,t);m(o,Object.entries(S).map(([e,t])=>`${e}=${t}\n`).join(``),{mode:384})}function isEntrypoint(e=process.argv[1],t=import.meta.url){return!!(e&&t===S(h.resolve(e)).href)}if(isEntrypoint())try{await main(process.argv[2])}catch(e){fail(e instanceof Error?e.message:String(e))}export{applyEnvironmentModes,isEntrypoint,main}; \ No newline at end of file diff --git a/dist/index.mjs b/dist/index.mjs index 65e15fe..ee5a108 100644 --- a/dist/index.mjs +++ b/dist/index.mjs @@ -189,7 +189,7 @@ function _null(e){return/* @__PURE__ */ _null$1(ea,e)}const ta=/*@__PURE__*/ $co function array(e,t){return new ta({type:`array`,element:e,...normalizeParams(t)})}const na=/*@__PURE__*/ $constructor(`ZodMiniObject`,(e,t)=>{Ji.init(e,t),Zi.init(e,t),installLazyProp(e,`shape`,e=>e._zod.def.shape,!1)});// @__NO_SIDE_EFFECTS__ function object(e,t){let n={type:`object`,shape:e??{},...normalizeParams(t)};return new na(n)}const ra=/*@__PURE__*/ $constructor(`ZodMiniUnion`,(e,t)=>{Yi.init(e,t),Zi.init(e,t)});// @__NO_SIDE_EFFECTS__ function union(e,t){return new ra({type:`union`,options:e,...normalizeParams(t)})}const ia=/*@__PURE__*/ $constructor(`ZodMiniOptional`,(e,t)=>{Xi.init(e,t),Zi.init(e,t)});// @__NO_SIDE_EFFECTS__ -function optional(e){return new ia({type:`optional`,innerType:e})}const aa=`Vite+`,oa=`vite-plus`,sa=/* @__PURE__ */ object({cwd:/* @__PURE__ */ optional(/* @__PURE__ */ string()),args:/* @__PURE__ */ optional(/* @__PURE__ */ array(/* @__PURE__ */ string()))}),ca=/* @__PURE__ */ union([/* @__PURE__ */ _null(),/* @__PURE__ */ boolean(),sa,/* @__PURE__ */ array(sa)]),la=`Vite+`;function getInputs(){let e=getInput(`node-version`)||void 0,t=getInput(`node-version-file`)||void 0,n=parseNodeManager(getInput(`node-manager`));if(n===!1&&(e||t))throw Error(`node-manager: false cannot be combined with node-version or node-version-file: installing a Node.js version requires the Vite+ Node.js manager.`);return{version:getInput(`version`),versionFile:getInput(`version-file`)||void 0,nodeVersion:e,nodeVersionFile:t,nodeManager:n,packageManager:parsePackageManager(getInput(`package-manager`)),workingDirectory:getInput(`working-directory`)||void 0,runInstall:parseRunInstall(getInput(`run-install`)),sfw:getBooleanInput(`sfw`),cache:getBooleanInput(`cache`),cacheSave:getBooleanInput(`cache-save`),cacheDependencyPath:getInput(`cache-dependency-path`)||void 0,registryUrl:getInput(`registry-url`)||void 0,scope:getInput(`scope`)||void 0}}function parseRunInstall(e){if(!e||e===`false`||e===`null`)return[];if(e===`true`)return[{}];let t=(0,_i.parse)(e);try{let e=ca.parse(t);return e?e===!0?[{}]:Array.isArray(e)?e:[e]:[]}catch(e){throw e instanceof Mi?Error(`Invalid run-install input: ${e.issues.map(e=>e.message).join(`, `)}`):e}}function isWindows(e=process.platform){return e===`win32`}const ua=`https://raw.githubusercontent.com/voidzero-dev/vite-plus`,da=`packages/cli`,fa=/^0\.0\.0-commit\.([0-9a-f]{40})$/i,pa=/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;function pkgPrNewCommitSha(e){return e.match(fa)?.[1]}function getInstallScriptUrls(e,t=process.platform){let n=isWindows(t)?`install.ps1`:`install.sh`,r=installScriptRef(e);return{pinned:r?[`${ua}/${r}/${da}/${n}`,`https://cdn.jsdelivr.net/gh/voidzero-dev/vite-plus@${r}/${da}/${n}`]:[],latest:[`https://viteplus.dev/${n}`,`${ua}/main/${da}/${n}`]}}function installScriptRef(e){let t=pkgPrNewCommitSha(e);if(t)return t.toLowerCase();if(pa.test(e))return`v${e}`}const ma=`SETUP_VP_DIRS_FILE`,ha=/^v?(\d+)\.(\d+)\.\d+(?:-[0-9A-Za-z.-]+)?$/;function supportsVitePlusDirs(e){if(pkgPrNewCommitSha(e))return!0;let t=e.match(ha);if(!t)return!0;let n=Number(t[1]),r=Number(t[2]);return n>0||r>=3}function createVitePlusDirsFile(){return ae(Se(),`setup-vp-dirs-${k()}.txt`)}function removeVitePlusDirsFile(e){L(e,{force:!0})}function readVitePlusProbe(e){try{return pe(e,`utf8`)}catch(e){if(e.code===`ENOENT`)return;throw e}}function resolveVitePlusBinDir(e,t,n){if(!t){if(!supportsVitePlusDirs(e))return n;throw Error(`Vite+ was installed successfully, but setup-vp could not resolve its VpDirs.`)}let r=readVitePlusProbe(t),i=r===void 0?void 0:parseVitePlusDirs(r);if(i)return i.bin;if(!(pkgPrNewCommitSha(e)!==void 0||ha.test(e))&&r!==void 0){let e=parseInstalledVpVersion$1(r);if(e!==`unknown`&&!supportsVitePlusDirs(e))return n}throw Error(`Vite+ was installed successfully, but setup-vp could not resolve its VpDirs.`)}function parseVitePlusDirs(e){let t=/* @__PURE__ */ new Map;for(let n of e.split(/\r?\n/)){let e=n.indexOf(` `);if(e<1)continue;let r=n.slice(0,e).replace(/^\uFEFF/,``),i=n.slice(e+1).trim();i&&t.set(r,i)}let n=t.get(`data`),r=t.get(`bin`),i=t.get(`cache`),a=t.get(`config`),o=t.get(`state`);if(n&&r&&i&&a&&o)return{data:n,bin:r,cache:i,config:a,state:o}}function getInstallScriptCommand(e,t=process.platform,n=!0){if(isWindows(t))return n?{command:`pwsh`,args:[`-Command`,` +function optional(e){return new ia({type:`optional`,innerType:e})}const aa=`Vite+`,oa=`vite-plus`,sa=/* @__PURE__ */ object({cwd:/* @__PURE__ */ optional(/* @__PURE__ */ string()),args:/* @__PURE__ */ optional(/* @__PURE__ */ array(/* @__PURE__ */ string()))}),ca=/* @__PURE__ */ union([/* @__PURE__ */ _null(),/* @__PURE__ */ boolean(),sa,/* @__PURE__ */ array(sa)]),la=`Vite+`;function getInputs(){let e=getInput(`node-version`)||void 0,t=getInput(`node-version-file`)||void 0,n=parseNodeManager(getInput(`node-manager`));if(n===!1&&(e||t))throw Error(`node-manager: false cannot be combined with node-version or node-version-file: installing a Node.js version requires the Vite+ Node.js manager.`);return{version:getInput(`version`),versionFile:getInput(`version-file`)||void 0,nodeVersion:e,nodeVersionFile:t,nodeManager:n,packageManager:parsePackageManager(getInput(`package-manager`)),workingDirectory:getInput(`working-directory`)||void 0,runInstall:parseRunInstall(getInput(`run-install`)),sfw:getBooleanInput(`sfw`),cache:getBooleanInput(`cache`),cacheSave:getBooleanInput(`cache-save`),cacheDependencyPath:getInput(`cache-dependency-path`)||void 0,registryUrl:getInput(`registry-url`)||void 0,scope:getInput(`scope`)||void 0}}function parseRunInstall(e){if(!e||e===`false`||e===`null`)return[];if(e===`true`)return[{}];let t=(0,_i.parse)(e);try{let e=ca.parse(t);return e?e===!0?[{}]:Array.isArray(e)?e:[e]:[]}catch(e){throw e instanceof Mi?Error(`Invalid run-install input: ${e.issues.map(e=>e.message).join(`, `)}`):e}}function isWindows(e=process.platform){return e===`win32`}const ua=`https://raw.githubusercontent.com/voidzero-dev/vite-plus`,da=`packages/cli`,fa=/^0\.0\.0-commit\.([0-9a-f]{40})$/i,pa=/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;function pkgPrNewCommitSha(e){return e.match(fa)?.[1]}function getInstallScriptUrls(e,t=process.platform){let n=isWindows(t)?`install.ps1`:`install.sh`,r=installScriptRef(e);return{pinned:r?[`${ua}/${r}/${da}/${n}`,`https://cdn.jsdelivr.net/gh/voidzero-dev/vite-plus@${r}/${da}/${n}`]:[],latest:[`https://viteplus.dev/${n}`,`${ua}/main/${da}/${n}`]}}function installScriptRef(e){let t=pkgPrNewCommitSha(e);if(t)return t.toLowerCase();if(pa.test(e))return`v${e}`}const ma=`SETUP_VP_DIRS_FILE`,ha=/^v?(\d+)\.(\d+)\.\d+(?:-[0-9A-Za-z.-]+)?$/;function supportsVitePlusDirs(e){if(pkgPrNewCommitSha(e))return!0;let t=e.match(ha);if(!t)return!0;let n=Number(t[1]),r=Number(t[2]);return n>0||r>=3}function createVitePlusDirsFile(){return ae(Se(),`setup-vp-dirs-${k()}.txt`)}function removeVitePlusDirsFile(e){L(e,{force:!0})}function readVitePlusPath(e){if(e)return readVitePlusProbe(e)?.split(/\r?\n/).find(e=>e.startsWith(`path `))?.slice(5)}function readVitePlusProbe(e){try{return pe(e,`utf8`)}catch(e){if(e.code===`ENOENT`)return;throw e}}function resolveVitePlusBinDir(e,t,n){if(!t){if(!supportsVitePlusDirs(e))return n;throw Error(`Vite+ was installed successfully, but setup-vp could not resolve its VpDirs.`)}let r=readVitePlusProbe(t),i=r===void 0?void 0:parseVitePlusDirs(r);if(i)return i.bin;if(!(pkgPrNewCommitSha(e)!==void 0||ha.test(e))&&r!==void 0){let e=parseInstalledVpVersion$1(r);if(e!==`unknown`&&!supportsVitePlusDirs(e))return n}throw Error(`Vite+ was installed successfully, but setup-vp could not resolve its VpDirs.`)}function parseVitePlusDirs(e){let t=/* @__PURE__ */ new Map;for(let n of e.split(/\r?\n/)){let e=n.indexOf(` `);if(e<1)continue;let r=n.slice(0,e).replace(/^\uFEFF/,``),i=n.slice(e+1).trim();i&&t.set(r,i)}let n=t.get(`data`),r=t.get(`bin`),i=t.get(`cache`),a=t.get(`config`),o=t.get(`state`);if(n&&r&&i&&a&&o)return{data:n,bin:r,cache:i,config:a,state:o}}function getInstallScriptCommand(e,t=process.platform,n=!0){if(isWindows(t))return n?{command:`pwsh`,args:[`-Command`,` $dirsFile = $env:${ma} Set-Content -LiteralPath $dirsFile -Value '' -NoNewline -Encoding UTF8 . ([scriptblock]::Create((irm -TimeoutSec 15 ${e}))) @@ -209,6 +209,15 @@ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } $env:VP_DUMP_DIRS = '1' & $vpPath | Add-Content -LiteralPath $dirsFile -Encoding UTF8 if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } +# Use Vite+'s generated environment so system-first shims stay last in PATH. +$configLine = Get-Content -LiteralPath $dirsFile | Where-Object { $_.StartsWith("config" + [char]9) } | Select-Object -Last 1 +if ($configLine) { + $envFile = Join-Path $configLine.Substring(7) 'env.ps1' + if (Test-Path -LiteralPath $envFile -PathType Leaf) { + . $envFile + Add-Content -LiteralPath $dirsFile -Value ("path" + [char]9 + $env:PATH) -Encoding UTF8 + } +} `.trim()]}:{command:`pwsh`,args:[`-Command`,`& ([scriptblock]::Create((irm -TimeoutSec 15 ${e})))`]};let r=` if command -v curl >/dev/null 2>&1; then curl -fsSL --connect-timeout 5 --max-time 15 "${e}"${n?` -o "$installer_file"`:``} @@ -230,12 +239,20 @@ vp_dir="\${SHIM_DIR:-\${INSTALL_DIR:-\${VP_HOME:-$HOME/.vite-plus}}/bin}" if [ -x "$vp_dir/vp" ]; then "$vp_dir/vp" --version > "$${ma}" VP_DUMP_DIRS=1 "$vp_dir/vp" >> "$${ma}" + # Read the resolved config directory, including split/custom installations. + while IFS=$'\\t' read -r key value; do + if [ "$key" = config ] && [ -f "$value/env" ]; then + source "$value/env" + printf 'path\\t%s\\n' "$PATH" >> "$${ma}" + break + fi + done < "$${ma}" fi `.trim()]}:{command:`bash`,args:[`-c`,` set +u set -o pipefail ${r} | bash -`.trim()]}}function getVitePlusHome(){let e=isWindows()?process.env.USERPROFILE:process.env.HOME;return ae(e||be(),`.vite-plus`)}function parseInstalledVpVersion(e){return(e.match(/^\s*vp\s+v?(\d[^\s]*)/im)??e.match(/Global:\s*v?(\d[^\s]*)/i))?.[1]??`unknown`}function getWorkspaceDir(){return process.env.GITHUB_WORKSPACE||process.cwd()}function resolvePath$2(e,t){return ie(e)?e:ae(t,e)}function getConfiguredProjectDir(e){if(!e.workingDirectory)return getWorkspaceDir();let t=resolvePath$2(e.workingDirectory,getWorkspaceDir());if(!I(t))throw Error(`working-directory not found: ${e.workingDirectory} (resolved to ${t})`);if(!he(t).isDirectory())throw Error(`working-directory is not a directory: ${e.workingDirectory} (resolved to ${t})`);return t}function getInstallCwd(e,t){return t?resolvePath$2(t,e):e}const ga=[{filename:`pnpm-lock.yaml`,type:`pnpm`},{filename:`bun.lockb`,type:`bun`},{filename:`bun.lock`,type:`bun`},{filename:`package-lock.json`,type:`npm`},{filename:`npm-shrinkwrap.json`,type:`npm`},{filename:`yarn.lock`,type:`yarn`}];function detectLockFile$1(e,t=getWorkspaceDir(),n=!1){if(e){let n=resolvePath$2(e,t);if(I(n)){let e=te(n),t=ga.find(t=>t.filename===e);return t?{type:t.type,path:n,filename:e}:inferLockFileType$1(n,e)}return}let r=me(t);for(let e of ga)if(r.includes(e.filename)){let r=ae(t,e.filename);return n||info(`Auto-detected lock file: ${e.filename}`),{type:e.type,path:r,filename:e.filename}}}function inferLockFileType$1(e,t){return t.includes(`pnpm`)?{type:`pnpm`,path:e,filename:t}:t.includes(`yarn`)?{type:`yarn`,path:e,filename:t}:t.startsWith(`bun.`)?{type:`bun`,path:e,filename:t}:{type:`npm`,path:e,filename:t}}async function getCacheDirectories(e,t){switch(e){case`npm`:case`pnpm`:case`yarn`:case`bun`:return getViteCacheDir(t);default:return[]}}async function getCommandOutput(e,t,n){let r=`${e} ${t.join(` `)}`;try{let i=await getExecOutput(e,t,{cwd:n?.cwd,silent:!0,ignoreReturnCode:!0});if(i.exitCode===0)return i.stdout.trim();debug(`Command "${r}" exited with code ${i.exitCode}`);return}catch(e){warning(`Failed to run "${r}": ${String(e)}`);return}}async function getViteCacheDir(e){let t=await getCommandOutput(`vp`,[`pm`,`cache`,`dir`],{cwd:e});return t?[t]:[]}const _a=2e3;async function installVitePlus(e){let{version:t}=e;info(`Installing ${la}@${t}...`);let n={...process.env,VP_VERSION:t,VITE_PLUS_VERSION:t},r=supportsVitePlusDirs(t)?createVitePlusDirsFile():void 0;r?(n.VP_VPDIRS_AWARE=`1`,n[ma]=r):(delete n.VP_VPDIRS_AWARE,delete n[ma]);let i=pkgPrNewCommitSha(t);i&&(n.VP_PR_VERSION=i);let{pinned:a,latest:o}=getInstallScriptUrls(t),s=a.length+o.length,c=2*s,l=``,u=0,tryUrls=async e=>{for(let t=0;t<2;t++)for(let t of e){u++;try{let e=await runInstallCommand(t,n);if(e===0)return!0;l=`exit code ${e}`}catch(e){l=e instanceof Error?e.message:String(e)}u0){if(await tryUrls(a)){ensureVitePlusBinInPath(t,r);return}warning(`Could not fetch the install script pinned to ${la}@${t}. Falling back to the latest install script. The latest script may not be compatible with ${t}.`)}if(await tryUrls(o)){ensureVitePlusBinInPath(t,r);return}throw Error(`Failed to install ${la} after ${c} attempts across ${s} URL(s): ${l}`)}finally{r&&removeVitePlusDirsFile(r)}}async function runInstallCommand(e,t){let n={env:t,ignoreReturnCode:!0},{command:r,args:i}=getInstallScriptCommand(e,process.platform,t.VP_VPDIRS_AWARE===`1`);return exec(r,i,n)}function ensureVitePlusBinInPath(e,t){let n=resolveVitePlusBinDir(e,t,ae(getVitePlusHome(),`bin`));process.env.PATH?.split(ne).includes(n)||addPath(n)}function getOptions$1(e){let t={followSymbolicLinks:!0,implicitDescendants:!0,matchDirectories:!0,omitBrokenSymbolicLinks:!0,excludeHiddenFiles:!1};return e&&(typeof e.followSymbolicLinks==`boolean`&&(t.followSymbolicLinks=e.followSymbolicLinks,debug(`followSymbolicLinks '${t.followSymbolicLinks}'`)),typeof e.implicitDescendants==`boolean`&&(t.implicitDescendants=e.implicitDescendants,debug(`implicitDescendants '${t.implicitDescendants}'`)),typeof e.matchDirectories==`boolean`&&(t.matchDirectories=e.matchDirectories,debug(`matchDirectories '${t.matchDirectories}'`)),typeof e.omitBrokenSymbolicLinks==`boolean`&&(t.omitBrokenSymbolicLinks=e.omitBrokenSymbolicLinks,debug(`omitBrokenSymbolicLinks '${t.omitBrokenSymbolicLinks}'`)),typeof e.excludeHiddenFiles==`boolean`&&(t.excludeHiddenFiles=e.excludeHiddenFiles,debug(`excludeHiddenFiles '${t.excludeHiddenFiles}'`))),t}const va=process.platform===`win32`;function dirname$2(e){if(e=safeTrimTrailingSeparator$1(e),va&&/^\\\\[^\\]+(\\[^\\]+)?$/.test(e))return e;let t=u.dirname(e);return va&&/^\\\\[^\\]+\\[^\\]+\\$/.test(t)&&(t=safeTrimTrailingSeparator$1(t)),t}function ensureAbsoluteRoot$1(e,t){if(g(e,`ensureAbsoluteRoot parameter 'root' must not be empty`),g(t,`ensureAbsoluteRoot parameter 'itemPath' must not be empty`),hasAbsoluteRoot$1(t))return t;if(va){if(t.match(/^[A-Z]:[^\\/]|^[A-Z]:$/i)){let e=process.cwd();return g(e.match(/^[A-Z]:\\/i),`Expected current directory to start with an absolute drive root. Actual '${e}'`),t[0].toUpperCase()===e[0].toUpperCase()?t.length===2?`${t[0]}:\\${e.substr(3)}`:(e.endsWith(`\\`)||(e+=`\\`),`${t[0]}:\\${e.substr(3)}${t.substr(2)}`):`${t[0]}:\\${t.substr(2)}`}if(normalizeSeparators$1(t).match(/^\\$|^\\[^\\]/)){let e=process.cwd();return g(e.match(/^[A-Z]:\\/i),`Expected current directory to start with an absolute drive root. Actual '${e}'`),`${e[0]}:\\${t.substr(1)}`}}return g(hasAbsoluteRoot$1(e),`ensureAbsoluteRoot parameter 'root' must have an absolute root`),e.endsWith(`/`)||va&&e.endsWith(`\\`)||(e+=u.sep),e+t}function hasAbsoluteRoot$1(e){return g(e,`hasAbsoluteRoot parameter 'itemPath' must not be empty`),e=normalizeSeparators$1(e),va?e.startsWith(`\\\\`)||/^[A-Z]:\\/i.test(e):e.startsWith(`/`)}function hasRoot$1(e){return g(e,`isRooted parameter 'itemPath' must not be empty`),e=normalizeSeparators$1(e),va?e.startsWith(`\\`)||/^[A-Z]:/i.test(e):e.startsWith(`/`)}function normalizeSeparators$1(e){return e||=``,va?(e=e.replace(/\//g,`\\`),(/^\\\\+[^\\]/.test(e)?`\\`:``)+e.replace(/\\\\+/g,`\\`)):e.replace(/\/\/+/g,`/`)}function safeTrimTrailingSeparator$1(e){return e?(e=normalizeSeparators$1(e),!e.endsWith(u.sep)||e===u.sep||va&&/^[A-Z]:\\$/i.test(e)?e:e.substr(0,e.length-1)):``}var ya;(function(e){e[e.None=0]=`None`,e[e.Directory=1]=`Directory`,e[e.File=2]=`File`,e[e.All=3]=`All`})(ya||={});const ba=process.platform===`win32`;function getSearchPaths$1(e){e=e.filter(e=>!e.negate);let t={};for(let n of e){let e=ba?n.searchPath.toUpperCase():n.searchPath;t[e]=`candidate`}let n=[];for(let r of e){let e=ba?r.searchPath.toUpperCase():r.searchPath;if(t[e]===`included`)continue;let i=!1,a=e,o=dirname$2(a);for(;o!==a;){if(t[o]){i=!0;break}a=o,o=dirname$2(a)}i||(n.push(r.searchPath),t[e]=`included`)}return n}function match$2(e,t){let n=ya.None;for(let r of e)r.negate?n&=~r.match(t):n|=r.match(t);return n}function partialMatch$1(e,t){return e.some(e=>!e.negate&&e.partialMatch(t))}var xa=/* @__PURE__ */ __commonJSMin(((e,t)=>{t.exports=function(e,t){for(var r=[],i=0;i{t.exports=balanced;function balanced(e,t,n){e instanceof RegExp&&(e=maybeMatch(e,n)),t instanceof RegExp&&(t=maybeMatch(t,n));var r=range(e,t,n);return r&&{start:r[0],end:r[1],pre:n.slice(0,r[0]),body:n.slice(r[0]+e.length,r[1]),post:n.slice(r[1]+t.length)}}function maybeMatch(e,t){var n=t.match(e);return n?n[0]:null}balanced.range=range;function range(e,t,n){var r,i,a,o,s,c=n.indexOf(e),l=n.indexOf(t,c+1),u=c;if(c>=0&&l>0){if(e===t)return[c,l];for(r=[],a=n.length;u>=0&&!s;)u==c?(r.push(u),c=n.indexOf(e,u+1)):r.length==1?s=[r.pop(),l]:(i=r.pop(),i=0?c:l;r.length&&(s=[a,o])}return s}})),Ca=/* @__PURE__ */ __commonJSMin(((e,t)=>{xa();var n=Sa();t.exports=expandTop;var r=`\0SLASH`+Math.random()+`\0`,i=`\0OPEN`+Math.random()+`\0`,a=`\0CLOSE`+Math.random()+`\0`,o=`\0COMMA`+Math.random()+`\0`,s=`\0PERIOD`+Math.random()+`\0`,c=1e5,l=4e6;function numeric(e){return parseInt(e,10)==e?parseInt(e,10):e.charCodeAt(0)}function escapeBraces(e){return e.split(`\\\\`).join(r).split(`\\{`).join(i).split(`\\}`).join(a).split(`\\,`).join(o).split(`\\.`).join(s)}function unescapeBraces(e){return e.split(r).join(`\\`).split(i).join(`{`).split(a).join(`}`).split(o).join(`,`).split(s).join(`.`)}function parseCommaParts(e){if(!e)return[``];var t=[],r=n(`{`,`}`,e);if(!r)return e.split(`,`);var i=r.pre,a=r.body,o=r.post,s=i.split(`,`);s[s.length-1]+=`{`+a+`}`;var c=parseCommaParts(o);return o.length&&(s[s.length-1]+=c.shift(),s.push.apply(s,c)),t.push.apply(t,s),t}function expandTop(e,t){if(!e)return[];t||={};var n=t.max==null?c:t.max,r=t.maxLength==null?l:t.maxLength;return e.substr(0,2)===`{}`&&(e=`\\{\\}`+e.substr(2)),expand(escapeBraces(e),n,r,!0).map(unescapeBraces)}function embrace(e){return`{`+e+`}`}function isPadded(e){return/^-?0\d/.test(e)}function lte(e,t){return e<=t}function gte(e,t){return e>=t}function combine(e,t,n,r,i,a,o,s){for(var c=[],l=0,u=0;u=i)return c;var f=e[u]+n+r[d];if(!(o&&f.length===t[u])){if(l+f.length>a)return c;c.push(f),s.push(t[u]),l+=f.length}}return c}function expandSequence(e,t,n,r){var i=e.split(/\.\./),a=[]; +`.trim()]}}function getVitePlusHome(){let e=isWindows()?process.env.USERPROFILE:process.env.HOME;return ae(e||be(),`.vite-plus`)}function parseInstalledVpVersion(e){return(e.match(/^\s*vp\s+v?(\d[^\s]*)/im)??e.match(/Global:\s*v?(\d[^\s]*)/i))?.[1]??`unknown`}function getWorkspaceDir(){return process.env.GITHUB_WORKSPACE||process.cwd()}function resolvePath$2(e,t){return ie(e)?e:ae(t,e)}function getConfiguredProjectDir(e){if(!e.workingDirectory)return getWorkspaceDir();let t=resolvePath$2(e.workingDirectory,getWorkspaceDir());if(!I(t))throw Error(`working-directory not found: ${e.workingDirectory} (resolved to ${t})`);if(!he(t).isDirectory())throw Error(`working-directory is not a directory: ${e.workingDirectory} (resolved to ${t})`);return t}function getInstallCwd(e,t){return t?resolvePath$2(t,e):e}const ga=[{filename:`pnpm-lock.yaml`,type:`pnpm`},{filename:`bun.lockb`,type:`bun`},{filename:`bun.lock`,type:`bun`},{filename:`package-lock.json`,type:`npm`},{filename:`npm-shrinkwrap.json`,type:`npm`},{filename:`yarn.lock`,type:`yarn`}];function detectLockFile$1(e,t=getWorkspaceDir(),n=!1){if(e){let n=resolvePath$2(e,t);if(I(n)){let e=te(n),t=ga.find(t=>t.filename===e);return t?{type:t.type,path:n,filename:e}:inferLockFileType$1(n,e)}return}let r=me(t);for(let e of ga)if(r.includes(e.filename)){let r=ae(t,e.filename);return n||info(`Auto-detected lock file: ${e.filename}`),{type:e.type,path:r,filename:e.filename}}}function inferLockFileType$1(e,t){return t.includes(`pnpm`)?{type:`pnpm`,path:e,filename:t}:t.includes(`yarn`)?{type:`yarn`,path:e,filename:t}:t.startsWith(`bun.`)?{type:`bun`,path:e,filename:t}:{type:`npm`,path:e,filename:t}}async function getCacheDirectories(e,t){switch(e){case`npm`:case`pnpm`:case`yarn`:case`bun`:return getViteCacheDir(t);default:return[]}}async function getCommandOutput(e,t,n){let r=`${e} ${t.join(` `)}`;try{let i=await getExecOutput(e,t,{cwd:n?.cwd,silent:!0,ignoreReturnCode:!0});if(i.exitCode===0)return i.stdout.trim();debug(`Command "${r}" exited with code ${i.exitCode}`);return}catch(e){warning(`Failed to run "${r}": ${String(e)}`);return}}async function getViteCacheDir(e){let t=await getCommandOutput(`vp`,[`pm`,`cache`,`dir`],{cwd:e});return t?[t]:[]}const _a=2e3;async function installVitePlus(e){let{version:t}=e;info(`Installing ${la}@${t}...`);let n={...process.env,VP_VERSION:t,VITE_PLUS_VERSION:t},r=supportsVitePlusDirs(t)?createVitePlusDirsFile():void 0;r?(n.VP_VPDIRS_AWARE=`1`,n[ma]=r):(delete n.VP_VPDIRS_AWARE,delete n[ma]);let i=pkgPrNewCommitSha(t);i&&(n.VP_PR_VERSION=i);let{pinned:a,latest:o}=getInstallScriptUrls(t),s=a.length+o.length,c=2*s,l=``,u=0,tryUrls=async e=>{for(let t=0;t<2;t++)for(let t of e){u++;try{let e=await runInstallCommand(t,n);if(e===0)return!0;l=`exit code ${e}`}catch(e){l=e instanceof Error?e.message:String(e)}u0){if(await tryUrls(a)){ensureVitePlusBinInPath(t,r);return}warning(`Could not fetch the install script pinned to ${la}@${t}. Falling back to the latest install script. The latest script may not be compatible with ${t}.`)}if(await tryUrls(o)){ensureVitePlusBinInPath(t,r);return}throw Error(`Failed to install ${la} after ${c} attempts across ${s} URL(s): ${l}`)}finally{r&&removeVitePlusDirsFile(r)}}async function runInstallCommand(e,t){let n={env:t,ignoreReturnCode:!0},{command:r,args:i}=getInstallScriptCommand(e,process.platform,t.VP_VPDIRS_AWARE===`1`);return exec(r,i,n)}function ensureVitePlusBinInPath(e,t){let n=resolveVitePlusBinDir(e,t,ae(getVitePlusHome(),`bin`)),r=readVitePlusPath(t);(r!==void 0||!process.env.PATH?.split(ne).includes(n))&&addPath(n),r!==void 0&&exportVariable(`PATH`,r)}function getOptions$1(e){let t={followSymbolicLinks:!0,implicitDescendants:!0,matchDirectories:!0,omitBrokenSymbolicLinks:!0,excludeHiddenFiles:!1};return e&&(typeof e.followSymbolicLinks==`boolean`&&(t.followSymbolicLinks=e.followSymbolicLinks,debug(`followSymbolicLinks '${t.followSymbolicLinks}'`)),typeof e.implicitDescendants==`boolean`&&(t.implicitDescendants=e.implicitDescendants,debug(`implicitDescendants '${t.implicitDescendants}'`)),typeof e.matchDirectories==`boolean`&&(t.matchDirectories=e.matchDirectories,debug(`matchDirectories '${t.matchDirectories}'`)),typeof e.omitBrokenSymbolicLinks==`boolean`&&(t.omitBrokenSymbolicLinks=e.omitBrokenSymbolicLinks,debug(`omitBrokenSymbolicLinks '${t.omitBrokenSymbolicLinks}'`)),typeof e.excludeHiddenFiles==`boolean`&&(t.excludeHiddenFiles=e.excludeHiddenFiles,debug(`excludeHiddenFiles '${t.excludeHiddenFiles}'`))),t}const va=process.platform===`win32`;function dirname$2(e){if(e=safeTrimTrailingSeparator$1(e),va&&/^\\\\[^\\]+(\\[^\\]+)?$/.test(e))return e;let t=u.dirname(e);return va&&/^\\\\[^\\]+\\[^\\]+\\$/.test(t)&&(t=safeTrimTrailingSeparator$1(t)),t}function ensureAbsoluteRoot$1(e,t){if(g(e,`ensureAbsoluteRoot parameter 'root' must not be empty`),g(t,`ensureAbsoluteRoot parameter 'itemPath' must not be empty`),hasAbsoluteRoot$1(t))return t;if(va){if(t.match(/^[A-Z]:[^\\/]|^[A-Z]:$/i)){let e=process.cwd();return g(e.match(/^[A-Z]:\\/i),`Expected current directory to start with an absolute drive root. Actual '${e}'`),t[0].toUpperCase()===e[0].toUpperCase()?t.length===2?`${t[0]}:\\${e.substr(3)}`:(e.endsWith(`\\`)||(e+=`\\`),`${t[0]}:\\${e.substr(3)}${t.substr(2)}`):`${t[0]}:\\${t.substr(2)}`}if(normalizeSeparators$1(t).match(/^\\$|^\\[^\\]/)){let e=process.cwd();return g(e.match(/^[A-Z]:\\/i),`Expected current directory to start with an absolute drive root. Actual '${e}'`),`${e[0]}:\\${t.substr(1)}`}}return g(hasAbsoluteRoot$1(e),`ensureAbsoluteRoot parameter 'root' must have an absolute root`),e.endsWith(`/`)||va&&e.endsWith(`\\`)||(e+=u.sep),e+t}function hasAbsoluteRoot$1(e){return g(e,`hasAbsoluteRoot parameter 'itemPath' must not be empty`),e=normalizeSeparators$1(e),va?e.startsWith(`\\\\`)||/^[A-Z]:\\/i.test(e):e.startsWith(`/`)}function hasRoot$1(e){return g(e,`isRooted parameter 'itemPath' must not be empty`),e=normalizeSeparators$1(e),va?e.startsWith(`\\`)||/^[A-Z]:/i.test(e):e.startsWith(`/`)}function normalizeSeparators$1(e){return e||=``,va?(e=e.replace(/\//g,`\\`),(/^\\\\+[^\\]/.test(e)?`\\`:``)+e.replace(/\\\\+/g,`\\`)):e.replace(/\/\/+/g,`/`)}function safeTrimTrailingSeparator$1(e){return e?(e=normalizeSeparators$1(e),!e.endsWith(u.sep)||e===u.sep||va&&/^[A-Z]:\\$/i.test(e)?e:e.substr(0,e.length-1)):``}var ya;(function(e){e[e.None=0]=`None`,e[e.Directory=1]=`Directory`,e[e.File=2]=`File`,e[e.All=3]=`All`})(ya||={});const ba=process.platform===`win32`;function getSearchPaths$1(e){e=e.filter(e=>!e.negate);let t={};for(let n of e){let e=ba?n.searchPath.toUpperCase():n.searchPath;t[e]=`candidate`}let n=[];for(let r of e){let e=ba?r.searchPath.toUpperCase():r.searchPath;if(t[e]===`included`)continue;let i=!1,a=e,o=dirname$2(a);for(;o!==a;){if(t[o]){i=!0;break}a=o,o=dirname$2(a)}i||(n.push(r.searchPath),t[e]=`included`)}return n}function match$2(e,t){let n=ya.None;for(let r of e)r.negate?n&=~r.match(t):n|=r.match(t);return n}function partialMatch$1(e,t){return e.some(e=>!e.negate&&e.partialMatch(t))}var xa=/* @__PURE__ */ __commonJSMin(((e,t)=>{t.exports=function(e,t){for(var r=[],i=0;i{t.exports=balanced;function balanced(e,t,n){e instanceof RegExp&&(e=maybeMatch(e,n)),t instanceof RegExp&&(t=maybeMatch(t,n));var r=range(e,t,n);return r&&{start:r[0],end:r[1],pre:n.slice(0,r[0]),body:n.slice(r[0]+e.length,r[1]),post:n.slice(r[1]+t.length)}}function maybeMatch(e,t){var n=t.match(e);return n?n[0]:null}balanced.range=range;function range(e,t,n){var r,i,a,o,s,c=n.indexOf(e),l=n.indexOf(t,c+1),u=c;if(c>=0&&l>0){if(e===t)return[c,l];for(r=[],a=n.length;u>=0&&!s;)u==c?(r.push(u),c=n.indexOf(e,u+1)):r.length==1?s=[r.pop(),l]:(i=r.pop(),i=0?c:l;r.length&&(s=[a,o])}return s}})),Ca=/* @__PURE__ */ __commonJSMin(((e,t)=>{xa();var n=Sa();t.exports=expandTop;var r=`\0SLASH`+Math.random()+`\0`,i=`\0OPEN`+Math.random()+`\0`,a=`\0CLOSE`+Math.random()+`\0`,o=`\0COMMA`+Math.random()+`\0`,s=`\0PERIOD`+Math.random()+`\0`,c=1e5,l=4e6;function numeric(e){return parseInt(e,10)==e?parseInt(e,10):e.charCodeAt(0)}function escapeBraces(e){return e.split(`\\\\`).join(r).split(`\\{`).join(i).split(`\\}`).join(a).split(`\\,`).join(o).split(`\\.`).join(s)}function unescapeBraces(e){return e.split(r).join(`\\`).split(i).join(`{`).split(a).join(`}`).split(o).join(`,`).split(s).join(`.`)}function parseCommaParts(e){if(!e)return[``];var t=[],r=n(`{`,`}`,e);if(!r)return e.split(`,`);var i=r.pre,a=r.body,o=r.post,s=i.split(`,`);s[s.length-1]+=`{`+a+`}`;var c=parseCommaParts(o);return o.length&&(s[s.length-1]+=c.shift(),s.push.apply(s,c)),t.push.apply(t,s),t}function expandTop(e,t){if(!e)return[];t||={};var n=t.max==null?c:t.max,r=t.maxLength==null?l:t.maxLength;return e.substr(0,2)===`{}`&&(e=`\\{\\}`+e.substr(2)),expand(escapeBraces(e),n,r,!0).map(unescapeBraces)}function embrace(e){return`{`+e+`}`}function isPadded(e){return/^-?0\d/.test(e)}function lte(e,t){return e<=t}function gte(e,t){return e>=t}function combine(e,t,n,r,i,a,o,s){for(var c=[],l=0,u=0;u=i)return c;var f=e[u]+n+r[d];if(!(o&&f.length===t[u])){if(l+f.length>a)return c;c.push(f),s.push(t[u]),l+=f.length}}return c}function expandSequence(e,t,n,r){var i=e.split(/\.\./),a=[]; /* c8 ignore start */ if(i[0]===void 0||i[1]===void 0)return a; /* c8 ignore stop */ diff --git a/src/azure/index.test.ts b/src/azure/index.test.ts index afed72f..e4ee7c1 100644 --- a/src/azure/index.test.ts +++ b/src/azure/index.test.ts @@ -4,6 +4,8 @@ import { runFinalize, runPrepare } from "./index.js"; describe("Azure lifecycle", () => { it("runs prepare in install → cache order", async () => { const calls: string[] = []; + const setVariable = vi.fn(); + const prependPath = vi.fn(); await runPrepare( { SETUP_VP_VERSION: "latest", @@ -11,8 +13,10 @@ describe("Azure lifecycle", () => { SYSTEM_DEFAULTWORKINGDIRECTORY: process.cwd(), }, { - installVitePlus: async () => { + installVitePlus: async (_version, options) => { calls.push("install"); + options?.exportPath?.("/bin:/system:/fallback"); + options?.prependPath?.("/bin"); }, prepareCacheMetadata: () => { calls.push("cache"); @@ -25,14 +29,16 @@ describe("Azure lifecycle", () => { getCommandOutput: () => "vp v0.2.2", run: () => undefined, parseInstalledVpVersion: () => "0.2.2", - prependPath: () => undefined, - setVariable: () => undefined, + prependPath, + setVariable, logWarning: () => undefined, logInfo: () => undefined, }, ); expect(calls).toEqual(["install", "cache"]); + expect(setVariable).toHaveBeenCalledWith("PATH", "/bin:/system:/fallback"); + expect(prependPath).toHaveBeenCalledExactlyOnceWith("/bin"); }); it("runs finalize in auth → sfw → install → version order", async () => { diff --git a/src/azure/index.ts b/src/azure/index.ts index 66b8e6d..9f55edf 100644 --- a/src/azure/index.ts +++ b/src/azure/index.ts @@ -91,6 +91,7 @@ export async function runPrepare( await ports.installVitePlus(version, { env, prependPath: (binDir) => ports.prependPath(binDir), + exportPath: (value) => ports.setVariable("PATH", value), logWarningFn: ports.logWarning, }); // Finalize must use the resolved version, including pins from files or lockfiles. diff --git a/src/azure/install-viteplus.test.ts b/src/azure/install-viteplus.test.ts index 7251315..d2891b2 100644 --- a/src/azure/install-viteplus.test.ts +++ b/src/azure/install-viteplus.test.ts @@ -16,6 +16,33 @@ function writeDirsFile(env: Record, bin: string): void { } describe("installVitePlus", () => { + it.each(["linux", "win32"] as const)( + "propagates generated %s PATH even when main bin is already present", + async (platform) => { + const separator = platform === "win32" ? ";" : ":"; + const bin = platform === "win32" ? "C:\\custom bin" : "/custom bin"; + const originalPath = [bin, "system"].join(separator); + const installedPath = [originalPath, "fallback"].join(separator); + const env = { PATH: originalPath }; + const exportPath = vi.fn(); + const prependPath = vi.fn(); + await installVitePlus("0.3.3", { + platform, + env, + exportPath, + prependPath, + runInstall: (_url, installEnv) => { + writeDirsFile(installEnv, bin); + writeFileSync(installEnv.SETUP_VP_DIRS_FILE, `\npath\t${installedPath}\n`, { flag: "a" }); + return 0; + }, + }); + expect(env.PATH).toBe(installedPath); + expect(exportPath).toHaveBeenCalledExactlyOnceWith(installedPath); + expect(prependPath).toHaveBeenCalledExactlyOnceWith(bin); + }, + ); + it("uses PowerShell installers on Windows and bash installers on Unix", async () => { const calls: NodeJS.Platform[] = []; const runInstall = vi.fn( diff --git a/src/ci/install-path.test.ts b/src/ci/install-path.test.ts new file mode 100644 index 0000000..1282467 --- /dev/null +++ b/src/ci/install-path.test.ts @@ -0,0 +1,78 @@ +import { describe, expect, it } from "vite-plus/test"; +import { spawnSync } from "node:child_process"; +import { chmodSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { installVitePlus } from "./install-viteplus.js"; +import { isWindows } from "./platform.js"; +import { exportShellEnv, shellQuote } from "../gitlab/shell.js"; + +describe("installed PATH", () => { + it.skipIf(isWindows())( + "resolves managed and system-first tools now and in later GitLab shells", + async () => { + const root = mkdtempSync(join(tmpdir(), "setup-vp-path-")); + const bin = join(root, "custom bin"); + const data = join(root, "data"); + const config = join(root, "config"); + const fallback = join(data, "fallback-bin"); + const system = join(root, "system"); + const downloads = join(root, "downloads"); + const later = join(root, "later"); + const envFile = join(root, "exports"); + for (const dir of [bin, data, config, fallback, system, downloads, later]) + mkdirSync(dir, { recursive: true }); + const executable = (dir: string, name: string, body: string) => { + const file = join(dir, name); + writeFileSync(file, `#!/bin/bash\n${body}\n`); + chmodSync(file, 0o755); + }; + try { + // Serve an isolated installer and generated environment, without downloading or touching a real installation. + const installer = join(root, "install.sh"); + writeFileSync(installer, `SHIM_DIR=${shellQuote(bin)}\n`); + executable(downloads, "curl", `cp ${shellQuote(installer)} "$8"`); + executable( + bin, + "vp", + `if [ "$VP_DUMP_DIRS" = 1 ]; then\nprintf '%s\\n' ${["data\t" + data, "bin\t" + bin, "cache\t" + root, "config\t" + config, "state\t" + root].map(shellQuote).join(" ")}\nelse echo 'vp v0.3.3'; fi`, + ); + writeFileSync( + join(config, "env"), + `export PATH=${shellQuote(bin)}:"$PATH":${shellQuote(fallback)}\n`, + ); + executable(bin, "npm", "echo managed-npm"); + executable(bin, "pnpm", "echo managed-pnpm"); + executable(fallback, "pnpm", "echo fallback-pnpm"); + const env = { HOME: root, PATH: `${downloads}:/usr/bin:/bin`, SETUP_VP_ENV_FILE: envFile }; + await installVitePlus("0.3.3", { + env, + exportPath: (value) => exportShellEnv("PATH", value, env), + }); + const resolve = (command: string, persisted = false) => { + const result = spawnSync( + "/bin/bash", + ["-c", `${persisted ? `source ${shellQuote(envFile)}; ` : ""}${command}`], + { env: persisted ? { HOME: root, PATH: "/usr/bin:/bin" } : env, encoding: "utf8" }, + ); + expect(result.status, result.stderr).toBe(0); + return result.stdout.trim(); + }; + for (const persisted of [false, true]) + expect(resolve("pnpm", persisted)).toBe("managed-pnpm"); + // Model env off pnpm after setup: the shim leaves main bin; other families stay managed. + rmSync(join(bin, "pnpm")); + executable(system, "pnpm", "echo system-pnpm"); + executable(later, "pnpm", "echo later-pnpm"); + for (const persisted of [false, true]) { + expect(resolve("pnpm", persisted)).toBe("fallback-pnpm"); + expect(resolve("npm", persisted)).toBe("managed-npm"); + expect(resolve(`PATH=${shellQuote(system)}:"$PATH" pnpm`, persisted)).toBe("system-pnpm"); + expect(resolve(`PATH=${shellQuote(later)}:"$PATH" pnpm`, persisted)).toBe("later-pnpm"); + } + } finally { + rmSync(root, { recursive: true, force: true }); + } + }, + ); +}); diff --git a/src/ci/install-viteplus.ts b/src/ci/install-viteplus.ts index b3e5513..983c8e5 100644 --- a/src/ci/install-viteplus.ts +++ b/src/ci/install-viteplus.ts @@ -8,6 +8,7 @@ import { createVitePlusDirsFile, getInstallScriptCommand, removeVitePlusDirsFile, + readVitePlusPath, resolveVitePlusBinDir, supportsVitePlusDirs, VP_DIRS_FILE_ENV, @@ -53,6 +54,7 @@ export async function installVitePlus( platform?: NodeJS.Platform; env?: NodeJS.ProcessEnv; prependPath?: (binDir: string) => void; + exportPath?: (value: string) => void; sleep?: (ms: number) => Promise; runInstall?: typeof runInstallCommand; logWarningFn?: (message: string) => void; @@ -128,9 +130,17 @@ export async function installVitePlus( dirsFile, join(getVitePlusHome(platform, targetEnv), "bin"), ); + const installedPath = readVitePlusPath(dirsFile); + if (installedPath !== undefined) { + targetEnv.PATH = installedPath; + options.exportPath?.(installedPath); + prependPath?.(binDir); + return; + } const separator = isWindows(platform) ? ";" : ":"; if (!targetEnv.PATH?.split(separator).includes(binDir)) { targetEnv.PATH = `${binDir}${separator}${targetEnv.PATH || ""}`; + options.exportPath?.(targetEnv.PATH); prependPath?.(binDir); } } diff --git a/src/ci/vp-dirs.ts b/src/ci/vp-dirs.ts index 28b7be0..7aa022b 100644 --- a/src/ci/vp-dirs.ts +++ b/src/ci/vp-dirs.ts @@ -48,6 +48,14 @@ export function readVitePlusDirs(filePath: string): VitePlusDirs | undefined { return output === undefined ? undefined : parseVitePlusDirs(output); } +export function readVitePlusPath(filePath: string | undefined): string | undefined { + if (!filePath) return undefined; + return readVitePlusProbe(filePath) + ?.split(/\r?\n/) + .find((line) => line.startsWith("path\t")) + ?.slice(5); +} + function readVitePlusProbe(filePath: string): string | undefined { try { return readFileSync(filePath, "utf8"); @@ -140,6 +148,15 @@ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } $env:VP_DUMP_DIRS = '1' & $vpPath | Add-Content -LiteralPath $dirsFile -Encoding UTF8 if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } +# Use Vite+'s generated environment so system-first shims stay last in PATH. +$configLine = Get-Content -LiteralPath $dirsFile | Where-Object { $_.StartsWith("config" + [char]9) } | Select-Object -Last 1 +if ($configLine) { + $envFile = Join-Path $configLine.Substring(7) 'env.ps1' + if (Test-Path -LiteralPath $envFile -PathType Leaf) { + . $envFile + Add-Content -LiteralPath $dirsFile -Value ("path" + [char]9 + $env:PATH) -Encoding UTF8 + } +} `.trim(); return { command: "pwsh", args: ["-Command", script] }; } @@ -177,6 +194,14 @@ vp_dir="\${SHIM_DIR:-\${INSTALL_DIR:-\${VP_HOME:-$HOME/.vite-plus}}/bin}" if [ -x "$vp_dir/vp" ]; then "$vp_dir/vp" --version > "$${VP_DIRS_FILE_ENV}" VP_DUMP_DIRS=1 "$vp_dir/vp" >> "$${VP_DIRS_FILE_ENV}" + # Read the resolved config directory, including split/custom installations. + while IFS=$'\\t' read -r key value; do + if [ "$key" = config ] && [ -f "$value/env" ]; then + source "$value/env" + printf 'path\\t%s\\n' "$PATH" >> "$${VP_DIRS_FILE_ENV}" + break + fi + done < "$${VP_DIRS_FILE_ENV}" fi `.trim(); return { command: "bash", args: ["-c", script] }; diff --git a/src/gitlab/index.ts b/src/gitlab/index.ts index 9797afd..06a24ac 100644 --- a/src/gitlab/index.ts +++ b/src/gitlab/index.ts @@ -86,7 +86,7 @@ export async function main(phase = "setup"): Promise { projectDir, ); - await installVitePlus(version, { env, prependPath: () => exportShellEnv("PATH", env.PATH) }); + await installVitePlus(version, { env, exportPath: (value) => exportShellEnv("PATH", value) }); applyEnvironmentModes(); if (nodeVersion) run("vp", ["env", "use", nodeVersion], { cwd: projectDir }); diff --git a/src/install-viteplus.test.ts b/src/install-viteplus.test.ts index 2718572..d02dadd 100644 --- a/src/install-viteplus.test.ts +++ b/src/install-viteplus.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, beforeEach, afterEach, vi } from "vite-plus/test"; import { exec } from "@actions/exec"; -import { addPath, warning } from "@actions/core"; +import { addPath, warning, exportVariable } from "@actions/core"; import { writeFileSync } from "node:fs"; import { installVitePlus } from "./install-viteplus.js"; import type { Inputs } from "./types.js"; @@ -9,6 +9,7 @@ vi.mock("@actions/core", () => ({ info: vi.fn(), warning: vi.fn(), addPath: vi.fn(), + exportVariable: vi.fn(), })); vi.mock("@actions/exec", () => ({ @@ -86,6 +87,22 @@ describe("installVitePlus", () => { expect(addPath).toHaveBeenCalledWith("/test/data/bin"); }); + it("persists generated PATH while reserving GITHUB_PATH for the main bin", async () => { + const installedPath = "/custom/bin:/system/bin:/data/fallback-bin"; + vi.stubEnv("PATH", "/custom/bin:/system/bin"); + vi.mocked(exec).mockImplementationOnce(async (_command, _args, options) => { + writeDirsFile(options, "/custom/bin"); + const env = (options as { env: Record }).env; + writeFileSync(env.SETUP_VP_DIRS_FILE, `\npath\t${installedPath}\n`, { flag: "a" }); + return 0; + }); + + await installVitePlus(baseInputs); + + expect(exportVariable).toHaveBeenCalledWith("PATH", installedPath); + expect(addPath).toHaveBeenCalledExactlyOnceWith("/custom/bin"); + }); + it("should fall back to the legacy bin for Vite+ releases without VpDirs", async () => { vi.stubEnv("HOME", "/home/runner"); vi.stubEnv("PATH", "/usr/bin"); diff --git a/src/install-viteplus.ts b/src/install-viteplus.ts index 9f29833..b6a700b 100644 --- a/src/install-viteplus.ts +++ b/src/install-viteplus.ts @@ -1,4 +1,4 @@ -import { info, warning, addPath } from "@actions/core"; +import { info, warning, addPath, exportVariable } from "@actions/core"; import { exec } from "@actions/exec"; import { delimiter, join } from "node:path"; import { setTimeout as sleep } from "node:timers/promises"; @@ -7,6 +7,7 @@ import { createVitePlusDirsFile, getInstallScriptCommand, removeVitePlusDirsFile, + readVitePlusPath, resolveVitePlusBinDir, supportsVitePlusDirs, VP_DIRS_FILE_ENV, @@ -119,7 +120,10 @@ async function runInstallCommand(url: string, env: { [key: string]: string }): P function ensureVitePlusBinInPath(version: string, dirsFile: string | undefined): void { const binDir = resolveVitePlusBinDir(version, dirsFile, join(getVitePlusHome(), "bin")); - if (!process.env.PATH?.split(delimiter).includes(binDir)) { + const installedPath = readVitePlusPath(dirsFile); + // GITHUB_PATH only prepends; persist the full generated PATH through GITHUB_ENV. + if (installedPath !== undefined || !process.env.PATH?.split(delimiter).includes(binDir)) { addPath(binDir); } + if (installedPath !== undefined) exportVariable("PATH", installedPath); }