bvm-core 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/install.sh ADDED
@@ -0,0 +1,377 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # --- Configuration ---
5
+ DEFAULT_BVM_VERSION="v1.1.3" # Fallback
6
+ FALLBACK_BUN_VERSION="1.3.5"
7
+ BVM_SRC_VERSION="${BVM_INSTALL_VERSION}" # If empty, will resolve dynamically
8
+
9
+ # --- Colors (Matches src/utils/ui.ts) ---
10
+ if [ -t 1 ]; then
11
+ RED="\033[1;31m"
12
+ GREEN="\033[1;32m"
13
+ YELLOW="\033[1;33m"
14
+ BLUE="\033[1;34m"
15
+ CYAN="\033[1;36m"
16
+ GRAY="\033[90m"
17
+ BOLD="\033[1m"
18
+ DIM="\033[2m"
19
+ RESET="\033[0m"
20
+ else
21
+ RED="" GREEN="" YELLOW="" BLUE="" CYAN="" GRAY="" BOLD="" DIM="" RESET=""
22
+ fi
23
+
24
+ # --- Directories ---
25
+ BVM_DIR="${HOME}/.bvm"
26
+ BVM_SRC_DIR="${BVM_DIR}/src"
27
+ BVM_RUNTIME_DIR="${BVM_DIR}/runtime"
28
+ BVM_BIN_DIR="${BVM_DIR}/bin"
29
+ BVM_SHIMS_DIR="${BVM_DIR}/shims"
30
+ BVM_ALIAS_DIR="${BVM_DIR}/aliases"
31
+ TEMP_DIR=""
32
+
33
+ # --- Helpers ---
34
+ cleanup() {
35
+ # Restore cursor just in case
36
+ printf "\033[?25h"
37
+ if [ -n "$TEMP_DIR" ] && [ -d "$TEMP_DIR" ]; then
38
+ rm -rf "$TEMP_DIR"
39
+ fi
40
+ }
41
+ trap cleanup EXIT
42
+
43
+ info() { echo -e "${BLUE}ℹ${RESET} $1"; }
44
+ success() { echo -e "${GREEN}✓${RESET} $1"; }
45
+ warn() { echo -e "${YELLOW}?${RESET} $1"; }
46
+ error() { echo -e "${RED}✖${RESET} $1"; exit 1; }
47
+
48
+ # Usage: download_file <url> <dest> <description>
49
+ download_file() {
50
+ local url="$1"
51
+ local dest="$2"
52
+ local desc="$3"
53
+
54
+ # Print description without newline
55
+ echo -n -e "${BLUE}ℹ${RESET} $desc "
56
+
57
+ # Start download in background (Silent but show errors, fail on error)
58
+ curl -L -s -S -f "$url" -o "$dest" &
59
+ local pid=$!
60
+
61
+ local delay=0.1
62
+ local spinstr='|/-\'
63
+
64
+ # Hide cursor
65
+ printf "\033[?25l"
66
+
67
+ while kill -0 "$pid" 2>/dev/null; do
68
+ local temp=${spinstr#?}
69
+ printf "${CYAN}%c${RESET}" "$spinstr"
70
+ local spinstr=$temp${spinstr%"$temp"}
71
+ sleep $delay
72
+ printf "\b"
73
+ done
74
+
75
+ # Restore cursor
76
+ printf "\033[?25h"
77
+
78
+ wait "$pid"
79
+ local ret=$?
80
+
81
+ if [ $ret -eq 0 ]; then
82
+ echo -e "${GREEN}Done${RESET}"
83
+ else
84
+ echo -e "${RED}Failed${RESET}"
85
+ return 1
86
+ fi
87
+ }
88
+
89
+ # 0. Smart Network Detection (CN vs Global)
90
+ detect_network_zone() {
91
+ if [ -n "$BVM_REGION" ]; then
92
+ echo "$BVM_REGION"
93
+ return
94
+ fi
95
+
96
+ # Test connectivity to unpkg vs elemecdn
97
+ # We use a short timeout for the race
98
+ if [ -n "$BVM_TEST_FORCE_CN" ]; then
99
+ echo "cn"
100
+ elif [ -n "$BVM_TEST_FORCE_GLOBAL" ]; then
101
+ echo "global"
102
+ elif curl -s -m 1.5 https://npm.elemecdn.com > /dev/null; then
103
+ # Usually elemecdn is much faster in CN
104
+ echo "cn"
105
+ else
106
+ echo "global"
107
+ fi
108
+ }
109
+
110
+ detect_shell() {
111
+ local shell_name=""
112
+
113
+ # 1. Try to detect from parent process (PPID)
114
+ # Check if ps supports -p and -o (POSIX-ish)
115
+ if command -v ps >/dev/null 2>&1; then
116
+ # Try standard POSIX syntax first
117
+ local proc_name
118
+ proc_name=$(ps -p "$PPID" -o comm= 2>/dev/null)
119
+ if [ -n "$proc_name" ]; then
120
+ shell_name="${proc_name##*/}"
121
+ fi
122
+ fi
123
+
124
+ # Clean up shell name (remove leading hyphen for login shells)
125
+ shell_name="${shell_name#-}"
126
+
127
+ case "$shell_name" in
128
+ *zsh) echo "zsh" ;;
129
+ *bash) echo "bash" ;;
130
+ *fish) echo "fish" ;;
131
+ *)
132
+ # 2. Fallback to SHELL environment variable
133
+ if [ -n "$SHELL" ]; then
134
+ echo "${SHELL##*/}"
135
+ else
136
+ echo "unknown"
137
+ fi
138
+ ;;
139
+ esac
140
+ }
141
+
142
+ # --- Main Script ---
143
+
144
+ BVM_REGION=$(detect_network_zone)
145
+
146
+ if [ "$BVM_REGION" == "cn" ]; then
147
+ REGISTRY="registry.npmmirror.com"
148
+ NPM_CDN="https://npm.elemecdn.com"
149
+ else
150
+ REGISTRY="registry.npmjs.org"
151
+ NPM_CDN="https://unpkg.com"
152
+ fi
153
+
154
+ echo -e "${CYAN}"
155
+ echo -e "__________ "
156
+ echo -e "\\______ \\__ _______ "
157
+ echo -e " | | _| \\/ / \\ "
158
+ echo -e " | | \\\\ / Y Y \\ "
159
+ echo -e " |______ / \\_/|__|_| / "
160
+ echo -e " \\/ \\/ "
161
+ echo -e "${RESET}"
162
+ echo -e ""
163
+ echo -e "${CYAN}${BOLD}BVM Installer${RESET} ${DIM}(${BVM_REGION})${RESET}"
164
+ echo -e ""
165
+
166
+ # 1. Resolve BVM and Bun Versions
167
+ echo -n -e "${BLUE}ℹ${RESET} Resolving versions... "
168
+
169
+ # Resolve BVM Version dynamically if not provided
170
+ if [ -z "$BVM_SRC_VERSION" ]; then
171
+ if [ -f "./dist/index.js" ] && [ -f "./package.json" ]; then
172
+ # Use version from local package.json
173
+ BVM_SRC_VERSION="v$(grep -oE '"version": "[^"]+"' package.json | cut -d'"' -f4 || echo "0.0.0")"
174
+ info "Using local version from package.json: $BVM_SRC_VERSION"
175
+ else
176
+ BVM_LATEST=$(curl -s https://${REGISTRY}/bvm-core | grep -oE '"dist-tags":\{"latest":"[^"]+"\}' | cut -d'"' -f6 || echo "")
177
+ if [ -n "$BVM_LATEST" ]; then
178
+ BVM_SRC_VERSION="v$BVM_LATEST"
179
+ else
180
+ BVM_SRC_VERSION="$DEFAULT_BVM_VERSION"
181
+ fi
182
+ fi
183
+ fi
184
+
185
+ # Calculate Major version for Bun runtime
186
+ BVM_PLAIN_VER="${BVM_SRC_VERSION#v}"
187
+ BUN_MAJOR="${BVM_PLAIN_VER%%.*}"
188
+
189
+ # Resolve latest Bun matching that major version
190
+ if [ -n "$BVM_INSTALL_BUN_VERSION" ]; then
191
+ BUN_VER="$BVM_INSTALL_BUN_VERSION"
192
+ else
193
+ BUN_LATEST=$(curl -s https://${REGISTRY}/-/package/bun/dist-tags | grep -oE '"latest":"[^"]+"' | cut -d'"' -f4 || echo "")
194
+ if [[ "$BUN_LATEST" == "$BUN_MAJOR."* ]]; then
195
+ BUN_VER="$BUN_LATEST"
196
+ else
197
+ # Emergency fallback
198
+ BUN_VER="$FALLBACK_BUN_VERSION"
199
+ fi
200
+ fi
201
+
202
+ echo -e "${GREEN}${BVM_SRC_VERSION} (Bun v${BUN_VER})${RESET}"
203
+
204
+ # 2. Setup Directories
205
+ mkdir -p "$BVM_DIR" "$BVM_SRC_DIR" "$BVM_RUNTIME_DIR" "$BVM_BIN_DIR" "$BVM_SHIMS_DIR" "$BVM_ALIAS_DIR"
206
+
207
+ # 3. Download Runtime (if needed)
208
+ TARGET_RUNTIME_DIR="${BVM_RUNTIME_DIR}/v${BUN_VER}"
209
+ if [ -d "${TARGET_RUNTIME_DIR}/bin" ] && [ -x "${TARGET_RUNTIME_DIR}/bin/bun" ]; then
210
+ success "Runtime (bun@${BUN_VER}) already installed."
211
+ else
212
+ OS="$(uname -s | tr -d '"')"
213
+ ARCH="$(uname -m | tr -d '"')"
214
+ case "$OS" in
215
+ Linux) P="linux" ;;
216
+ Darwin) P="darwin" ;;
217
+ MINGW*|MSYS*|CYGWIN*) P="windows" ;;
218
+ *) error "Unsupported OS: $OS" ;;
219
+ esac
220
+ case "$ARCH" in
221
+ x86_64) A="x64" ;;
222
+ arm64|aarch64) A="aarch64" ;;
223
+ *) error "Unsupported Arch: $ARCH" ;;
224
+ esac
225
+
226
+ if [ "$P" == "darwin" ]; then
227
+ PKG="@oven/bun-darwin-$A"
228
+ EXE="bun"
229
+ elif [ "$P" == "windows" ]; then
230
+ PKG="@oven/bun-windows-$A"
231
+ EXE="bun.exe"
232
+ else
233
+ PKG="@oven/bun-linux-$A"
234
+ EXE="bun"
235
+ fi
236
+
237
+ URL="https://${REGISTRY}/${PKG}/-/${PKG##*/}-${BUN_VER}.tgz"
238
+
239
+ TEMP_DIR="$(mktemp -d)"
240
+ TEMP_TGZ="${TEMP_DIR}/bun-runtime.tgz"
241
+
242
+ download_file "$URL" "$TEMP_TGZ" "Downloading Runtime (bun@${BUN_VER})..."
243
+
244
+ # Check if download succeeded
245
+ if [ ! -f "$TEMP_TGZ" ] || [ ! -s "$TEMP_TGZ" ]; then
246
+ error "Download failed or empty file."
247
+ fi
248
+
249
+ # Extract
250
+ tar -xzf "$TEMP_TGZ" -C "$TEMP_DIR"
251
+
252
+ # Move
253
+ mkdir -p "${TARGET_RUNTIME_DIR}/bin"
254
+ FOUND_BIN="$(find "$TEMP_DIR" -type f -name "$EXE" | head -n 1)"
255
+ if [ -z "$FOUND_BIN" ]; then
256
+ error "Could not find '$EXE' binary in downloaded archive."
257
+ fi
258
+
259
+ mv "$FOUND_BIN" "${TARGET_RUNTIME_DIR}/bin/bun"
260
+ chmod +x "${TARGET_RUNTIME_DIR}/bin/bun"
261
+ success "Runtime installed."
262
+ fi
263
+
264
+ # Link current runtime
265
+ ln -sf "$TARGET_RUNTIME_DIR" "${BVM_RUNTIME_DIR}/current"
266
+
267
+ # 4. Download BVM Source & Shim
268
+ # Use the detected NPM CDN
269
+ BASE_URL="${NPM_CDN}/bvm-core@${BVM_SRC_VERSION#v}"
270
+ SRC_URL="${BASE_URL}/dist/index.js"
271
+ SHIM_URL="${BASE_URL}/dist/bvm-shim.sh"
272
+
273
+ # Local fallback for development/testing
274
+ if [ -f "./dist/index.js" ]; then
275
+ cp "./dist/index.js" "${BVM_SRC_DIR}/index.js"
276
+ info "Using local BVM source from dist/."
277
+ else
278
+ download_file "$SRC_URL" "${BVM_SRC_DIR}/index.js" "Downloading BVM Source (${BVM_SRC_VERSION})..."
279
+ fi
280
+
281
+ if [ -f "./dist/bvm-shim.sh" ]; then
282
+ cp "./dist/bvm-shim.sh" "${BVM_BIN_DIR}/bvm-shim.sh"
283
+ info "Using local shim logic from dist/."
284
+ else
285
+ download_file "$SHIM_URL" "${BVM_BIN_DIR}/bvm-shim.sh" "Downloading Shim Logic..."
286
+ fi
287
+
288
+ if [ ! -f "${BVM_SRC_DIR}/index.js" ] || [ ! -f "${BVM_BIN_DIR}/bvm-shim.sh" ]; then
289
+ error "Failed to download BVM source or shim."
290
+ fi
291
+ chmod +x "${BVM_BIN_DIR}/bvm-shim.sh"
292
+
293
+ # 5. Create Shims (Decoupled from index.js)
294
+ echo -n -e "${BLUE}ℹ${RESET} Initializing shims... "
295
+
296
+ # Create bvm wrapper
297
+ cat > "${BVM_BIN_DIR}/bvm" <<EOF
298
+ #!/bin/bash
299
+ export BVM_DIR="$BVM_DIR"
300
+ exec "${BVM_RUNTIME_DIR}/current/bin/bun" "$BVM_SRC_DIR/index.js" "\$@"
301
+ EOF
302
+ chmod +x "${BVM_BIN_DIR}/bvm"
303
+
304
+ # Create bun and bunx shims
305
+ for cmd in bun bunx; do
306
+ cat > "${BVM_SHIMS_DIR}/${cmd}" <<EOF
307
+ #!/bin/bash
308
+ export BVM_DIR="$BVM_DIR"
309
+ exec "${BVM_BIN_DIR}/bvm-shim.sh" "$cmd" "\$@"
310
+ EOF
311
+ chmod +x "${BVM_SHIMS_DIR}/${cmd}"
312
+ done
313
+
314
+ echo -e "${GREEN}Done${RESET}"
315
+
316
+ # 6. Initialize First Version
317
+ if [ ! -f "${BVM_ALIAS_DIR}/default" ]; then
318
+ # Create the versions entry for the first download
319
+ mkdir -p "${BVM_DIR}/versions/v${BUN_VER}/bin"
320
+ ln -sf "${TARGET_RUNTIME_DIR}/bin/bun" "${BVM_DIR}/versions/v${BUN_VER}/bin/bun"
321
+ # Set it as default
322
+ echo "v${BUN_VER}" > "${BVM_ALIAS_DIR}/default"
323
+ fi
324
+
325
+ # We no longer need to run '$WRAPPER rehash' because we just did it manually/statically
326
+ SETUP_SUCCESS=true
327
+ if ! "${BVM_BIN_DIR}/bvm" setup --silent >/dev/null 2>&1; then
328
+ SETUP_SUCCESS=false
329
+ fi
330
+
331
+ # 7. Final Instructions
332
+ echo ""
333
+ echo -e "${GREEN}${BOLD}🎉 BVM Installed Successfully!${RESET}"
334
+ echo ""
335
+
336
+ CURRENT_SHELL=$(detect_shell)
337
+ DISPLAY_PROFILE=""
338
+
339
+ case "$CURRENT_SHELL" in
340
+ zsh) DISPLAY_PROFILE="$HOME/.zshrc" ;;
341
+ bash)
342
+ # Prefer .bashrc if it exists (common for users who manually set up their environment)
343
+ if [ -f "$HOME/.bashrc" ]; then
344
+ DISPLAY_PROFILE="$HOME/.bashrc"
345
+ elif [ -f "$HOME/.bash_profile" ]; then
346
+ DISPLAY_PROFILE="$HOME/.bash_profile"
347
+ else
348
+ DISPLAY_PROFILE="$HOME/.bashrc"
349
+ fi
350
+ ;;
351
+ fish) DISPLAY_PROFILE="$HOME/.config/fish/config.fish" ;;
352
+ *) DISPLAY_PROFILE="$HOME/.profile" ;;
353
+ esac
354
+
355
+ echo "To start using bvm:"
356
+ echo ""
357
+
358
+ if [ "$SETUP_SUCCESS" = true ]; then
359
+ # If setup succeeded, we don't need to show the long echo command
360
+ echo -e " ${YELLOW}1. Refresh your shell:${RESET}"
361
+ echo " source $DISPLAY_PROFILE"
362
+
363
+ echo ""
364
+ echo -e " ${YELLOW}2. Verify:${RESET}"
365
+ echo -e " bvm --version"
366
+ else
367
+ # If setup failed for some reason, we fallback to manual instructions
368
+ echo -e " ${YELLOW}1. Add to config:${RESET}"
369
+ echo " echo 'export PATH=\"\$HOME/.bvm/bin:\$PATH\"' >> $DISPLAY_PROFILE"
370
+ echo ""
371
+ echo -e " ${YELLOW}2. Refresh your shell:${RESET}"
372
+ echo " source $DISPLAY_PROFILE"
373
+
374
+ echo ""
375
+ echo -e " ${YELLOW}3. Verify:${RESET}"
376
+ echo -e " bvm --version"
377
+ fi
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "bvm-core",
3
+ "version": "1.1.3",
4
+ "description": "The native version manager for Bun. Cross-platform, shell-agnostic, and zero-dependency.",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "bvm": "dist/index.js"
8
+ },
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "scripts": {
13
+ "dev": "bun run src/index.ts",
14
+ "build": "bun build src/index.ts --target=bun --outfile dist/index.js --minify && bun run scripts/sync-runtime.ts",
15
+ "test": "bun test",
16
+ "bvm": "bun run src/index.ts",
17
+ "bvm:sandbox": "mkdir -p \"$PWD/.sandbox-home\" && HOME=\"$PWD/.sandbox-home\" bun run src/index.ts",
18
+ "release": "bun run scripts/release.ts",
19
+ "sync-runtime": "bun run scripts/sync-runtime.ts"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/EricLLLLLL/bvm.git"
24
+ },
25
+ "keywords": [
26
+ "bun",
27
+ "version-manager",
28
+ "cli",
29
+ "bvm",
30
+ "nvm",
31
+ "nvm-windows",
32
+ "fnm",
33
+ "nodenv",
34
+ "bun-nvm",
35
+ "version-switching"
36
+ ],
37
+ "files": [
38
+ "dist/index.js",
39
+ "dist/bvm-shim.sh",
40
+ "dist/bvm-shim.js",
41
+ "install.sh",
42
+ "install.ps1",
43
+ "README.md"
44
+ ],
45
+ "author": "EricLLLLLL",
46
+ "license": "MIT",
47
+ "type": "commonjs",
48
+ "dependencies": {
49
+ "@oven/bun-darwin-aarch64": "^1.3.5",
50
+ "cli-progress": "^3.12.0"
51
+ },
52
+ "devDependencies": {
53
+ "@types/bun": "^1.3.4",
54
+ "@types/cli-progress": "^3.11.6",
55
+ "@types/node": "^24.10.2",
56
+ "bun": "^1.3.5",
57
+ "esbuild": "^0.27.2",
58
+ "execa": "^9.6.1",
59
+ "typescript": "^5"
60
+ },
61
+ "peerDependencies": {
62
+ "typescript": "^5"
63
+ },
64
+ "bvm_fingerprints": {
65
+ "cli": "d5df14db9d48b83f4475d6b5106b35b3",
66
+ "shim_win": "c6f43afddfb205e130633fe00ee860d8",
67
+ "shim_unix": "8aa89a0324b52c9c81b96c0c03afe36c",
68
+ "install_sh": "ffb657ae178818ef4ad730a6b0eba5d9",
69
+ "install_ps1": "c98b4e2af524e8e891bcf84561e18bbf"
70
+ }
71
+ }