UNPKG

bunvm

Version:

Bun Version Manager - Switch between different versions of Bun easily

17 lines 8.61 kB
#!/usr/bin/env node import{Command as Or}from"commander";import{mkdirSync as Vr,existsSync as L}from"fs";import{join as Z}from"path";import U from"chalk";import{homedir as k}from"os";import{join as f}from"path";var S=f(k(),".bun"),w=f(S,"bin"),s=f(w,"bun"),x=f(w,"bunx"),cr=f(k(),".bvm"),p=f(cr,"versions"),lr="https://api.github.com",H=`${lr}/repos/oven-sh/bun/releases`,N=f(S,"_bun"),$=f(k(),".config","fish","config.fish");import y from"chalk";var n={log:r=>console.log(r),info:r=>console.log(`${y.blue("i")} ${r}`),success:r=>console.log(`${y.green("\u2705")} ${r}`),warn:r=>console.warn(`${y.yellow("\u26A0\uFE0F")} ${y.yellow(r)}`),error:r=>console.error(`${y.red("\u274C")} ${y.red(r)}`)};import{execSync as yr}from"child_process";import{createReadStream as O,existsSync as vr,readdirSync as Sr}from"fs";import l from"chalk";import{dirname as $r,join as j}from"path";import br from"axios";import{pipeline as xr}from"stream/promises";import Nr from"unzipper";import{chmod as Ir}from"fs/promises";import{createWriteStream as ur,existsSync as T,lstatSync as mr,mkdirSync as pr,rmSync as fr,symlinkSync as dr}from"fs";import{rm as gr,stat as hr,unlink as Br}from"fs/promises";async function C(r,e){let t=ur(e);await new Promise((o,a)=>{t.on("finish",o),t.on("error",a),r.pipe(t)})}async function g(r){try{return await hr(r),!0}catch{return!1}}async function b(r,e=!1){try{await g(r)&&(e?await gr(r,{recursive:!0,force:!0}):await Br(r))}catch(t){t.code!=="ENOENT"&&n.warn(`Failed to clean path: ${r}`)}}function I(r){let e=["B","KB","MB","GB"];if(r===0)return"0 B";let t=Math.floor(Math.log(r)/Math.log(1024));return`${(r/Math.pow(1024,t)).toFixed(1)} ${e[t]}`}function _(r){T(r)||pr(r,{recursive:!0})}function wr(r){if(T(r)){let e=mr(r).isSymbolicLink();try{fr(r,{force:!0}),e||n.warn(`Replaced non-symlink file at ${r}`)}catch(t){n.warn(`Couldn't remove existing file at ${r}: ${t.message}`)}}}function M(r,e){T(r)&&(wr(e),dr(r,e))}import z from"cli-progress";function V(){try{return yr("bun --version",{encoding:"utf8",stdio:["pipe"]}).trim()||null}catch{return null}}function D(){return vr(p)?Sr(p):[]}function F(r,e,t){let o=e===r,a=t.has(r);return o?`${l.magenta("v"+r)} ${l.yellow("\u2B50 (current)")}`:a?`${l.magenta("v"+r)} ${l.green("\u2713 (installed)")}`:`${l.magenta("v"+r)} ${l.red("\u2717 (not installed)")}`}function _r(){let r=`${process.platform}-${process.arch}`;switch(r){case"darwin-arm64":return"darwin-aarch64";default:return r}}function Er(r){async function e(){console.log(l.red(` Download interrupted. Cleaning up...`)),await b(r,!0),process.exit(1)}return process.once("SIGINT",e),()=>process.removeListener("SIGINT",e)}async function G(r,e){let t=_r(),o=`https://github.com/oven-sh/bun/releases/download/bun-v${r}/bun-${t}.zip`,a=`${e}.zip`,i=$r(e),c=j(i,`bun-${t}`),u=j(c,"bun"),v=Er(i);try{let m=await br.get(o,{responseType:"stream"});if(m.status!==200)throw new Error(`Failed to download ZIP file. Status: ${m.status}`);let B=Number(m.headers["content-length"])||0,P=0,R=new z.SingleBar({format:`${l.magenta("Downloading")} {bar} {percentage}% | {downloaded}/{totalSize}`,barCompleteChar:"\u2588",barIncompleteChar:"\u2591",hideCursor:!0},z.Presets.shades_classic);if(B&&R.start(B,0,{downloaded:"0 B",totalSize:I(B)}),m.data.on("data",ar=>{P+=ar.length,B&&R.update(P,{downloaded:I(P),totalSize:I(B)})}),await C(m.data,a),B&&R.stop(),n.log(l.yellow("\u{1F4E6} Extracting...")),await xr(O(a),Nr.Extract({path:i})),!await g(u))throw new Error(`Expected binary not found at ${u}`);await C(O(u),e),await Ir(e,493),await b(c,!0),await b(a),n.success(`Downloaded Bun ${l.bold(`v${r}`)}`)}catch(m){n.error(`Failed to install Bun: ${m instanceof Error?m.message:m}`),await b(i,!0),process.exit(1)}finally{v()}}import{join as Tr}from"path";import{existsSync as Cr}from"fs";import Mr from"chalk";import{homedir as Lr}from"os";import{join as d}from"path";import{readFile as K,writeFile as Y}from"fs/promises";import{execSync as Ur}from"child_process";async function J(){if(!await g(s)){n.error(`Bun binary not found at ${s}, skipping completions`);return}let r=X();if(!r){n.warn("Unknown shell. Please manually set up Bun completions.");return}try{Ur(`${s} completions`,{env:{...process.env,IS_BUN_AUTO_UPDATE:"true",SHELL:r},stdio:"ignore"})}catch(e){n.error(`Failed to set up ${r} completions: ${e}`)}}function X(){let r=process.env.SHELL??"";return r.includes("bash")?"bash":r.includes("zsh")?"zsh":r.includes("fish")?"fish":null}function Pr(r){let e=Lr();switch(r){case"bash":{let t=process.env.XDG_CONFIG_HOME;return[d(e,".bashrc"),d(e,".bash_profile"),...t?[d(t,".bashrc"),d(t,".bash_profile"),d(t,"bashrc"),d(t,"bash_profile")]:[]]}case"zsh":return[d(e,".zshrc")];case"fish":return[d(e,".config","fish","config.fish")];default:return[]}}async function Rr(){let r=[`set --export BUN_INSTALL "${S}"`,'set --export PATH "$BUN_INSTALL/bin" $PATH'];if(await g($))try{let e=await K($,"utf8"),t=r.filter(o=>!e.includes(o));if(t.length>0){let o=e+` # bun ${t.join(` `)} `;await Y($,o),n.success(`Updated ${$} with Bun configuration`)}}catch(e){let t=e instanceof Error?e.message:String(e);n.warn(`Could not update Fish config: ${t}`)}else n.warn("Fish config file not found. Please add Bun configuration manually.")}async function kr(r){if(!r){n.warn("Invalid shell provided");return}if(r==="fish"){await Rr();return}let e=`export BUN_INSTALL="${S}" `,t=`export PATH="$BUN_INSTALL/bin:$PATH" `,o=`[ -s "${N}" ] && source "${N}" `,a=Pr(r);for(let i of a)if(await g(i))try{let c=await K(i,"utf8"),u=!1,v=c;c.includes("BUN_INSTALL")||(v+=` # bun ${e}${t}`,u=!0),c.includes(N)||(v+=` # bun completions ${o}`,u=!0),u&&(await Y(i,v),n.success(`Updated ${i} with Bun configuration`));return}catch(c){let u=c instanceof Error?c.message:String(c);n.warn(`Could not update ${i}: ${u}`)}n.warn(`No writable ${r} config file found. Please add manually.`)}async function W(){let r=X();if(!r){n.warn("Unknown shell. Please manually add Bun to your shell config.");return}await kr(r)}async function E(r){let e=Tr(p,r,"bun");if(!Cr(e)){n.error(`Bun version ${r} is not installed.`),n.info(`Run ${Mr.cyan(`bvm install ${r}`)} to install it.`);return}try{_(w),M(e,s),M(e,x),await J(),n.success(`Now using Bun ${r}`)}catch(t){n.error(`Failed to switch Bun version: ${t.message}`)}}async function q(r){let e=Z(p,r),t=Z(e,"bun");if(L(e)&&L(t)){n.warn(`Bun ${U.green(`v${r}`)} is already installed.`);return}if(Vr(e,{recursive:!0}),n.log(`${U.cyan("\u{1F4E5} Installing")} Bun ${U.green(`v${r}`)}...`),await G(r,t),!L(s)||!L(x)){n.warn("No previously installed Bun versions found. Setting up environment..."),_(w);try{await W()}catch(o){n.error(`Failed to configure shell: ${o.message}. Please set up completions manually.`)}await E(r);return}n.success(`Installed Bun ${U.bold(`v${r}`)}`)}import Q from"chalk";import Dr from"axios";function rr(){try{let r=V();n.log(`Current Bun version: ${r??"none"}`);let e=D();if(e.length===0){n.warn("No Bun versions installed yet.");return}n.log(Q.green(`\u{1F680} Installed Bun versions: `)),e.forEach(t=>{n.log(F(t,r,new Set(e)))})}catch{n.error("No Bun versions installed yet.")}}async function er(){try{let{data:r}=await Dr.get(H),e=r.map(({tag_name:i})=>i.replace(/^bun-v/,""));if(e.length===0){n.warn("No Bun versions found remotely.");return}let t=D(),o=new Set(t),a=V();n.log(Q.green(`\u{1F680} Available Bun versions: `)),e.forEach(i=>{n.log(F(i,a,o))})}catch(r){n.error(`Error fetching remote versions: ${r instanceof Error?r.message:r}`)}}import{join as nr,resolve as tr}from"path";import{existsSync as A,readlinkSync as Fr,rmSync as or}from"fs";import Ar from"chalk";function ir(r){let e=nr(p,r),t=nr(e,"bun");if(!A(e)||!A(t)){n.warn(`Bun version ${r} is not installed.`);return}if(A(s))try{tr(Fr(s))===tr(t)&&(or(s,{force:!0}),n.log(`\u{1F517} Removed active symlink for Bun ${r}.`))}catch{}try{or(e,{recursive:!0,force:!0}),n.log(Ar.green(`\u{1F5D1}\uFE0F Bun ${r} has been uninstalled.`))}catch(o){n.error(`Failed to uninstall Bun ${r}: ${o.message}`)}}var sr="1.0.2";var h=new Or;h.name("bvm").description("Bun Version Manager - Manage multiple Bun versions").version(sr);h.command("install <version>").alias("i").description("Install a specific Bun version").action(q);h.command("use <version>").description("Use a specific Bun version").action(E);h.command("uninstall <version>").alias("u").description("Uninstall a specific Bun version").action(ir);h.command("list").alias("ls").description("List installed Bun versions").action(rr);h.command("remote").alias("r").description("List remote Bun versions").action(er);h.parse(); //# sourceMappingURL=bvm.js.map