From 3376754c0158dc784a2af2f35bac0909bdf17088 Mon Sep 17 00:00:00 2001 From: KTrain5369 Date: Sat, 1 Aug 2026 11:57:25 +1000 Subject: [PATCH 1/2] feat: allow explicitly disabling Vite+'s Node.js version management with `node-version: off` --- action.yml | 2 +- src/index.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index 1fcece1..e2833eb 100644 --- a/action.yml +++ b/action.yml @@ -22,7 +22,7 @@ inputs: required: false default: "false" node-version: - description: "Node.js version to install via `vp env use`. Defaults to Node.js latest LTS version." + description: "Node.js version to install via `vp env use`. Defaults to Node.js latest LTS version. Pass `off` to disable." required: false node-version-file: description: "Path to file containing the Node.js version spec (.nvmrc, .node-version, .tool-versions, package.json). Ignored when node-version is specified." diff --git a/src/index.ts b/src/index.ts index 4398eb6..4f7433e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -30,9 +30,12 @@ async function runMain(inputs: Inputs): Promise { await installVitePlus({ ...inputs, version }); // Step 3: Set up Node.js version if specified - if (nodeVersion) { + if (nodeVersion && nodeVersion !== "off") { info(`Setting up Node.js ${nodeVersion} via vp env use...`); await exec("vp", ["env", "use", nodeVersion]); + } else if (nodeVersion === "off") { + info("Disabling Node.js version management with vp env off..."); + await exec("vp", ["env", "off"]); } // Step 4: Configure registry authentication From 6c0536d6ffe6b5c5dea773c9cf4aab85cbe61598 Mon Sep 17 00:00:00 2001 From: KTrain5369 Date: Sat, 1 Aug 2026 12:06:47 +1000 Subject: [PATCH 2/2] Rebuild dist/index.mjs for GitHub --- dist/index.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/index.mjs b/dist/index.mjs index 37a1d1e..e7b9a9b 100644 --- a/dist/index.mjs +++ b/dist/index.mjs @@ -181,4 +181,4 @@ More info on storage limits: https://docs.github.com/en/billing/managing-billing `));let r=e.split(` `).map(e=>e.trim());for(let e of r)if(!e||e.startsWith(`#`))continue;else n.patterns.push(new Yv(e));return n.searchPaths.push(...getSearchPaths(n.patterns)),n})}static stat(e,t,n){return __awaiter$2(this,void 0,void 0,function*(){let r;if(t.followSymbolicLinks)try{r=yield a.promises.stat(e.path)}catch(n){if(n.code===`ENOENT`){if(t.omitBrokenSymbolicLinks){debug(`Broken symlink '${e.path}'`);return}throw Error(`No information found for the path '${e.path}'. This may indicate a broken symbolic link.`)}throw n}else r=yield a.promises.lstat(e.path);if(r.isDirectory()&&t.followSymbolicLinks){let t=yield a.promises.realpath(e.path);for(;n.length>=e.level;)n.pop();if(n.some(e=>e===t)){debug(`Symlink cycle detected for path '${e.path}' and realpath '${t}'`);return}n.push(t)}return r})}},__awaiter$1=function(e,t,n,r){function adopt(e){return e instanceof n?e:new n(function(t){t(e)})}return new(n||=Promise)(function(n,i){function fulfilled(e){try{step(r.next(e))}catch(e){i(e)}}function rejected(e){try{step(r.throw(e))}catch(e){i(e)}}function step(e){e.done?n(e.value):adopt(e.value).then(fulfilled,rejected)}step((r=r.apply(e,t||[])).next())})},__asyncValues=function(e){if(!Symbol.asyncIterator)throw TypeError(`Symbol.asyncIterator is not defined.`);var t=e[Symbol.asyncIterator],n;return t?t.call(e):(e=typeof __values==`function`?__values(e):e[Symbol.iterator](),n={},verb(`next`),verb(`throw`),verb(`return`),n[Symbol.asyncIterator]=function(){return this},n);function verb(t){n[t]=e[t]&&function(n){return new Promise(function(r,i){n=e[t](n),settle(r,i,n.done,n.value)})}}function settle(e,t,n,r){Promise.resolve(r).then(function(t){e({value:t,done:n})},t)}};function hashFiles$1(e,t){return __awaiter$1(this,arguments,void 0,function*(e,t,n=!1){var r,o,s,c;let l=n?info:debug,d=!1,f=t||(process.env.GITHUB_WORKSPACE??process.cwd()),p=i.createHash(`sha256`),h=0;try{for(var g=!0,v=__asyncValues(e.globGenerator()),b;b=yield v.next(),r=b.done,!r;g=!0){c=b.value,g=!1;let e=c;if(l(e),!e.startsWith(`${f}${u.sep}`)){l(`Ignore '${e}' since it is not under GITHUB_WORKSPACE.`);continue}if(a.statSync(e).isDirectory()){l(`Skip directory '${e}'.`);continue}let t=i.createHash(`sha256`);yield y.promisify(ve.pipeline)(a.createReadStream(e),t),p.write(t.digest()),h++,d||=!0}}catch(e){o={error:e}}finally{try{!g&&!r&&(s=v.return)&&(yield s.call(v))}finally{if(o)throw o.error}}return p.end(),d?(l(`Found ${h} files to hash.`),p.digest(`hex`)):(l(`No matches found for glob`),``)})}var __awaiter=function(e,t,n,r){function adopt(e){return e instanceof n?e:new n(function(t){t(e)})}return new(n||=Promise)(function(n,i){function fulfilled(e){try{step(r.next(e))}catch(e){i(e)}}function rejected(e){try{step(r.throw(e))}catch(e){i(e)}}function step(e){e.done?n(e.value):adopt(e.value).then(fulfilled,rejected)}step((r=r.apply(e,t||[])).next())})};function create(e,t){return __awaiter(this,void 0,void 0,function*(){return yield Zv.create(e,t)})}function hashFiles(e){return __awaiter(this,arguments,void 0,function*(e,t=``,n,r=!1){let i=!0;return n&&typeof n.followSymbolicLinks==`boolean`&&(i=n.followSymbolicLinks),hashFiles$1(yield create(e,{followSymbolicLinks:i}),t,r)})}async function restoreCache(e){let t=getConfiguredProjectDir(e),n=detectLockFile(e.cacheDependencyPath,t);if(!n){warning(e.cacheDependencyPath?`No lock file found for cache-dependency-path: ${e.cacheDependencyPath}. Skipping cache restore.`:`No lock file found in project directory: ${t}. Skipping cache restore.`),setOutput(`cache-hit`,!1);return}info(`Using lock file: ${n.path}`);let r=I(n.path);info(`Resolving dependency cache directory in: ${r}`);let i=await getCacheDirectories(n.type,r);if(!i.length){warning(`No cache directories found for ${n.type} in ${r}. Skipping cache restore.`),setOutput(`cache-hit`,!1);return}debug(`Cache paths: ${i.join(`, `)}`),saveState(`CACHE_PATHS`,JSON.stringify(i));let a=process.env.RUNNER_OS||_e(),o=he(),s=await hashFiles(n.path);if(!s)throw Error(`Failed to generate hash for lock file: ${n.path}`);let c=`vite-plus-${a}-${o}-${n.type}-${s}`,l=[`vite-plus-${a}-${o}-${n.type}-`,`vite-plus-${a}-${o}-`];debug(`Primary key: ${c}`),debug(`Restore keys: ${l.join(`, `)}`),saveState(`CACHE_PRIMARY_KEY`,c);let u=await restoreCache$1(i,c,l);u?(info(`Cache restored from key: ${u}`),saveState(`CACHE_MATCHED_KEY`,u),setOutput(`cache-hit`,!0)):(info(`Cache not found`),setOutput(`cache-hit`,!1))}async function saveCache(){let e=getState(`CACHE_PRIMARY_KEY`),t=getState(`CACHE_MATCHED_KEY`),n=getState(`CACHE_PATHS`);if(!e){info(`No cache key found. Skipping cache save.`);return}if(!n){info(`No cache paths found. Skipping cache save.`);return}if(e===t){info(`Cache hit on primary key "${e}". Skipping save.`);return}let r=JSON.parse(n);if(!r.length){info(`Empty cache paths. Skipping cache save.`);return}try{if(await saveCache$1(r,e)===-1){info(`Cache not saved (key already reserved by a concurrent job, or save was skipped).`);return}info(`Cache saved with key: ${e}`)}catch(e){warning(`Failed to save cache: ${String(e)}`)}}function resolveNodeVersionFile(e,t){let n=resolvePath(e,t||getWorkspaceDir()),r;try{r=ue(n,`utf-8`)}catch{throw Error(`node-version-file not found: ${n}`)}let i=F(n),a;if(a=i===`.tool-versions`?parseToolVersions(r):i===`package.json`?parsePackageJson(r):parsePlainVersionFile(r),!a)throw Error(`No Node.js version found in ${e}`);return a=a.replace(/^v/i,``),info(`Resolved Node.js version '${a}' from ${e}`),a}function parsePlainVersionFile(e){for(let t of e.split(` `)){let e=(t.includes(`#`)?t.slice(0,t.indexOf(`#`)):t).trim();if(e)return normalizeNvmAlias(e)}}function normalizeNvmAlias(e){let t=e.toLowerCase();return t===`node`||t===`stable`?`latest`:e}function parseToolVersions(e){for(let t of e.split(` -`)){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}const Qv=/^\d+\.\d+\.\d+/;function tryResolveVitePlusVersionFromLockfile(e,t){let n=detectLockfileForProject(e,t);if(!n)return;let r=n.filename.endsWith(`.lockb`)?textBunLockBeside(n):n;if(!r){debug(`Cannot read ${n.filename} (binary) to resolve the ${Ui} version; using "latest". Use the text bun.lock, or set the \`version\` input.`);return}let i=parseVitePlusVersionFromLockfile(r,workspaceSubPath(I(r.path),e));if(i)return info(`Resolved ${Ui} version '${i}' from ${r.filename}`),i;debug(`No ${Ui} version found in ${r.path}`)}function detectLockfileForProject(e,t){if(t)return detectLockFile(t,e,!0);let n=getWorkspaceDir(),r=e;for(;;){let e=detectLockFile(void 0,r,!0);if(e)return e;let t=I(r);if(r===n||t===r||!isWithin(t,n))break;r=t}}function textBunLockBeside(e){let t=te(I(e.path),`bun.lock`);return ce(t)?{type:`bun`,path:t,filename:`bun.lock`}:void 0}function workspaceSubPath(e,t){if(!isWithin(t,e))return``;let n=ne(e,t);return n?n.split(ie).join(`/`):``}function parseVitePlusVersionFromLockfile(e,t=``){if(e.filename.endsWith(`.lockb`))return;let n;try{n=ue(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&&Qv.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/${Wi}`]?.version;if(typeof e==`string`)return e;if(!npmPackageDeclaresVitePlus(r?.[t]))return}let i=r?.[`node_modules/${Wi}`]?.version;if(typeof i==`string`)return i;let a=n.dependencies?.[Wi]?.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,Bi.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[Wi],t=typeof e==`string`?e:e?.version;if(typeof t==`string`){let e=t.replace(/\(.*$/,``).trim();if(Qv.test(e))return e}}}}function fromYarnLock(e){let t=new Set,n=e.split(/\r?\n/);for(let e=0;e!n.has(authKeyFor(e))),envVarRefs:r}}function writeSupplementalAuth(e){let t=getRunnerNpmrcPath(),n=new Set(e.map(authKeyFor)),r=readNpmrc(t),i=[...(r===void 0?[]:r.split(/\r?\n/)).filter(e=>{let t=e.indexOf(`=`);return t<=0?!0:!n.has(e.slice(0,t).trim().toLowerCase())}),...e.map(buildAuthLine)].join(L);if(exportVariable(`NPM_CONFIG_USERCONFIG`,t),exportVariable(`PNPM_CONFIG_USERCONFIG`,t),r===i){debug(`Supplemental .npmrc at ${t} already current`);return}pe(t,i),info(`Wrote _authToken entries to ${t} for registries: ${e.join(`, `)}`)}function propagateProjectNpmrcAuth(e){let t=te(e,`.npmrc`),n=readNpmrc(t);if(n===void 0)return;let{registriesNeedingAuth:r,envVarRefs:i}=analyzeProjectNpmrc(n);process.env.NODE_AUTH_TOKEN&&r.length>0&&(writeSupplementalAuth(r),i.add(`NODE_AUTH_TOKEN`));let a=[...i].filter(e=>!isReservedEnvVar(e)&&!!process.env[e]);if(a.length===0){debug(`Project .npmrc at ${t}: no auth env vars to propagate`);return}info(`Detected project .npmrc at ${t}. Propagating auth env vars: ${a.join(`, `)}`);for(let e of a)exportVariable(e,process.env[e])}async function runMain(e){saveState(`IS_POST`,`true`);let t=getConfiguredProjectDir(e),n=e.nodeVersion;!n&&e.nodeVersionFile&&(n=resolveNodeVersionFile(e.nodeVersionFile,t));let r=resolveVitePlusVersion(e,t);await installVitePlus({...e,version:r}),n&&(info(`Setting up Node.js ${n} via vp env use...`),await exec(`vp`,[`env`,`use`,n])),e.registryUrl?configAuthentication(e.registryUrl,e.scope):propagateProjectNpmrcAuth(t),e.cache&&await restoreCache(e);let i=await setupSfw(e);e.runInstall.length>0&&await runViteInstall({...e,sfw:i}),await printViteVersion(t)}async function printViteVersion(e){try{let t=(await getExecOutput(`vp`,[`--version`],{cwd:e,silent:!0})).stdout.trim();info(t);let n=parseInstalledVpVersion(t);saveState(`INSTALLED_VERSION`,n),setOutput(`version`,n)}catch(e){warning(`Could not get vp version: ${String(e)}`),setOutput(`version`,`unknown`)}}async function runPost(e){e.cache&&await saveCache()}async function main(){let e=getInputs();getState(`IS_POST`)===`true`?await runPost(e):await runMain(e)}main().catch(e=>{console.error(e),setFailed(e instanceof Error?e.message:String(e))});export{}; \ No newline at end of file +`)){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}const Qv=/^\d+\.\d+\.\d+/;function tryResolveVitePlusVersionFromLockfile(e,t){let n=detectLockfileForProject(e,t);if(!n)return;let r=n.filename.endsWith(`.lockb`)?textBunLockBeside(n):n;if(!r){debug(`Cannot read ${n.filename} (binary) to resolve the ${Ui} version; using "latest". Use the text bun.lock, or set the \`version\` input.`);return}let i=parseVitePlusVersionFromLockfile(r,workspaceSubPath(I(r.path),e));if(i)return info(`Resolved ${Ui} version '${i}' from ${r.filename}`),i;debug(`No ${Ui} version found in ${r.path}`)}function detectLockfileForProject(e,t){if(t)return detectLockFile(t,e,!0);let n=getWorkspaceDir(),r=e;for(;;){let e=detectLockFile(void 0,r,!0);if(e)return e;let t=I(r);if(r===n||t===r||!isWithin(t,n))break;r=t}}function textBunLockBeside(e){let t=te(I(e.path),`bun.lock`);return ce(t)?{type:`bun`,path:t,filename:`bun.lock`}:void 0}function workspaceSubPath(e,t){if(!isWithin(t,e))return``;let n=ne(e,t);return n?n.split(ie).join(`/`):``}function parseVitePlusVersionFromLockfile(e,t=``){if(e.filename.endsWith(`.lockb`))return;let n;try{n=ue(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&&Qv.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/${Wi}`]?.version;if(typeof e==`string`)return e;if(!npmPackageDeclaresVitePlus(r?.[t]))return}let i=r?.[`node_modules/${Wi}`]?.version;if(typeof i==`string`)return i;let a=n.dependencies?.[Wi]?.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,Bi.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[Wi],t=typeof e==`string`?e:e?.version;if(typeof t==`string`){let e=t.replace(/\(.*$/,``).trim();if(Qv.test(e))return e}}}}function fromYarnLock(e){let t=new Set,n=e.split(/\r?\n/);for(let e=0;e!n.has(authKeyFor(e))),envVarRefs:r}}function writeSupplementalAuth(e){let t=getRunnerNpmrcPath(),n=new Set(e.map(authKeyFor)),r=readNpmrc(t),i=[...(r===void 0?[]:r.split(/\r?\n/)).filter(e=>{let t=e.indexOf(`=`);return t<=0?!0:!n.has(e.slice(0,t).trim().toLowerCase())}),...e.map(buildAuthLine)].join(L);if(exportVariable(`NPM_CONFIG_USERCONFIG`,t),exportVariable(`PNPM_CONFIG_USERCONFIG`,t),r===i){debug(`Supplemental .npmrc at ${t} already current`);return}pe(t,i),info(`Wrote _authToken entries to ${t} for registries: ${e.join(`, `)}`)}function propagateProjectNpmrcAuth(e){let t=te(e,`.npmrc`),n=readNpmrc(t);if(n===void 0)return;let{registriesNeedingAuth:r,envVarRefs:i}=analyzeProjectNpmrc(n);process.env.NODE_AUTH_TOKEN&&r.length>0&&(writeSupplementalAuth(r),i.add(`NODE_AUTH_TOKEN`));let a=[...i].filter(e=>!isReservedEnvVar(e)&&!!process.env[e]);if(a.length===0){debug(`Project .npmrc at ${t}: no auth env vars to propagate`);return}info(`Detected project .npmrc at ${t}. Propagating auth env vars: ${a.join(`, `)}`);for(let e of a)exportVariable(e,process.env[e])}async function runMain(e){saveState(`IS_POST`,`true`);let t=getConfiguredProjectDir(e),n=e.nodeVersion;!n&&e.nodeVersionFile&&(n=resolveNodeVersionFile(e.nodeVersionFile,t));let r=resolveVitePlusVersion(e,t);await installVitePlus({...e,version:r}),n&&n!==`off`?(info(`Setting up Node.js ${n} via vp env use...`),await exec(`vp`,[`env`,`use`,n])):n===`off`&&(info(`Disabling Node.js version management with vp env off...`),await exec(`vp`,[`env`,`off`])),e.registryUrl?configAuthentication(e.registryUrl,e.scope):propagateProjectNpmrcAuth(t),e.cache&&await restoreCache(e);let i=await setupSfw(e);e.runInstall.length>0&&await runViteInstall({...e,sfw:i}),await printViteVersion(t)}async function printViteVersion(e){try{let t=(await getExecOutput(`vp`,[`--version`],{cwd:e,silent:!0})).stdout.trim();info(t);let n=parseInstalledVpVersion(t);saveState(`INSTALLED_VERSION`,n),setOutput(`version`,n)}catch(e){warning(`Could not get vp version: ${String(e)}`),setOutput(`version`,`unknown`)}}async function runPost(e){e.cache&&await saveCache()}async function main(){let e=getInputs();getState(`IS_POST`)===`true`?await runPost(e):await runMain(e)}main().catch(e=>{console.error(e),setFailed(e instanceof Error?e.message:String(e))});export{}; \ No newline at end of file