bvm-core 1.1.35 → 1.1.37
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/dist/bvm-shim.js +131 -33
- package/dist/bvm-shim.sh +24 -1
- package/dist/index.js +411 -139
- package/install.ps1 +72 -32
- package/install.sh +154 -63
- package/package.json +10 -11
- package/scripts/postinstall.js +185 -149
package/dist/bvm-shim.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
|
-
const { spawn } = require('child_process');
|
|
2
|
+
const { spawn, spawnSync } = require('child_process');
|
|
3
3
|
const os = require('os');
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* BVM Shim for Windows (JavaScript version)
|
|
8
|
+
* Features: Physical Execution Proxy - No Drift, Full Compatibility.
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
11
|
const BVM_DIR = process.env.BVM_DIR || path.join(os.homedir(), '.bvm');
|
|
11
|
-
const CMD = process.argv[2] ? process.argv[2].replace(/\.exe
|
|
12
|
+
const CMD = process.argv[2] ? process.argv[2].replace(/\.(exe|cmd|bat|ps1)$/i, '') : 'bun';
|
|
12
13
|
const ARGS = process.argv.slice(3);
|
|
13
14
|
|
|
14
15
|
function resolveVersion() {
|
|
@@ -50,57 +51,154 @@ function resolveVersion() {
|
|
|
50
51
|
return '';
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
// Simple synchronous execution for performance
|
|
54
54
|
const version = resolveVersion();
|
|
55
55
|
if (!version) {
|
|
56
|
-
console.error("BVM Error: No Bun version is active
|
|
56
|
+
console.error("BVM Error: No Bun version is active.");
|
|
57
57
|
process.exit(1);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
const versionDir = path.join(BVM_DIR, 'versions', version);
|
|
61
61
|
const binDir = path.join(versionDir, 'bin');
|
|
62
|
-
const
|
|
62
|
+
const bunExe = path.join(binDir, 'bun.exe');
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
let realExecutable = '';
|
|
65
|
+
let isShellScript = false;
|
|
66
|
+
|
|
67
|
+
// 1. Core Logic: Resolve the PHYSICAL executable
|
|
68
|
+
if (CMD === 'bun') {
|
|
69
|
+
realExecutable = bunExe;
|
|
70
|
+
} else if (CMD === 'bunx') {
|
|
71
|
+
// Windows Bun doesn't have a physical bunx.exe, it's 'bun x'
|
|
72
|
+
realExecutable = bunExe;
|
|
73
|
+
ARGS.unshift('x');
|
|
74
|
+
} else {
|
|
75
|
+
// For 3rd party tools, find the physical shim created by Bun in the version dir
|
|
76
|
+
const extensions = ['.exe', '.cmd', '.bat', '.ps1'];
|
|
77
|
+
for (const ext of extensions) {
|
|
78
|
+
const p = path.join(binDir, CMD + ext);
|
|
79
|
+
if (fs.existsSync(p)) {
|
|
80
|
+
realExecutable = p;
|
|
81
|
+
isShellScript = (ext !== '.exe');
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!realExecutable || !fs.existsSync(realExecutable)) {
|
|
88
|
+
// Strict version isolation:
|
|
89
|
+
// If a tool isn't physically present in this version's bin dir,
|
|
90
|
+
// do NOT fall back to `bun x <tool>` (that would bypass isolation).
|
|
91
|
+
console.error(`BVM Error: Command '${CMD}' not found in Bun ${version}.`);
|
|
66
92
|
process.exit(127);
|
|
93
|
+
} else if (isShellScript) {
|
|
94
|
+
// JIT SELF-HEALING: If we are about to run a shell script (shim),
|
|
95
|
+
// ensure it's not broken by relative path drift.
|
|
96
|
+
try {
|
|
97
|
+
let content = fs.readFileSync(realExecutable, 'utf8');
|
|
98
|
+
// console.log("[DEBUG] Checking shim:", realExecutable);
|
|
99
|
+
if (content.includes('%~dp0\\..') || content.includes('$PSScriptRoot\\..')) {
|
|
100
|
+
console.log(`[bvm] Fixing broken shim: ${realExecutable}`);
|
|
101
|
+
const binDir = path.dirname(realExecutable);
|
|
102
|
+
const nodeModulesPeer = path.join(binDir, '..', 'node_modules');
|
|
103
|
+
const nodeModulesNested = path.join(binDir, '..', 'install', 'global', 'node_modules');
|
|
104
|
+
|
|
105
|
+
let nodeModulesBase = '';
|
|
106
|
+
if (fs.existsSync(nodeModulesPeer)) nodeModulesBase = nodeModulesPeer;
|
|
107
|
+
else if (fs.existsSync(nodeModulesNested)) nodeModulesBase = nodeModulesNested;
|
|
108
|
+
|
|
109
|
+
if (nodeModulesBase) {
|
|
110
|
+
const absNodeModules = path.resolve(nodeModulesBase).replace(/\//g, '\\');
|
|
111
|
+
const oldPatterns = [
|
|
112
|
+
'%~dp0\\..\\node_modules',
|
|
113
|
+
'%dp0%\\..\\node_modules',
|
|
114
|
+
'%~dp0\\..\\install\\global\\node_modules',
|
|
115
|
+
'%dp0%\\..\\install\\global\\node_modules',
|
|
116
|
+
'$PSScriptRoot\\..\\node_modules',
|
|
117
|
+
'$PSScriptRoot\\..\\install\\global\\node_modules'
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
let fixed = false;
|
|
121
|
+
for (const pat of oldPatterns) {
|
|
122
|
+
if (content.includes(pat)) {
|
|
123
|
+
content = content.split(pat).join(absNodeModules);
|
|
124
|
+
fixed = true;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (fixed) {
|
|
129
|
+
fs.writeFileSync(realExecutable, content, 'utf8');
|
|
130
|
+
console.log(`[bvm] Shim fixed. New target: ${absNodeModules}`);
|
|
131
|
+
} else {
|
|
132
|
+
console.log(`[bvm] Failed to fix shim patterns.`);
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
console.log(`[bvm] Could not find node_modules in peer or nested location.`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
} catch (e) {
|
|
139
|
+
console.error(`[bvm] JIT Fix Error: ${e.message}`);
|
|
140
|
+
}
|
|
67
141
|
}
|
|
68
142
|
|
|
69
|
-
|
|
70
|
-
|
|
143
|
+
// 2. CONFIGURE ENVIRONMENT
|
|
144
|
+
const bunfigPath = path.join(versionDir, 'bunfig.toml');
|
|
145
|
+
const env = Object.assign({}, process.env, {
|
|
146
|
+
BUN_INSTALL: versionDir,
|
|
147
|
+
BUN_INSTALL_GLOBAL_DIR: versionDir,
|
|
148
|
+
BUN_INSTALL_GLOBAL_BIN: binDir,
|
|
149
|
+
BUN_CONFIG_FILE: bunfigPath, // Force bun to use version-specific bunfig
|
|
150
|
+
PATH: binDir + path.delimiter + process.env.PATH
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// 3. EXECUTE THE PHYSICAL ORIGINAL
|
|
154
|
+
const child = spawn(realExecutable, ARGS, {
|
|
155
|
+
stdio: 'inherit',
|
|
156
|
+
shell: isShellScript,
|
|
157
|
+
env: env
|
|
158
|
+
});
|
|
71
159
|
|
|
72
|
-
const child = spawn(realExecutable, ARGS, { stdio: 'inherit', shell: false });
|
|
73
160
|
child.on('exit', (code) => {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
161
|
+
// AUTOMATIC REHASH: Ensure new commands are exposed immediately after installation
|
|
162
|
+
const installCmds = ['install', 'i', 'add', 'a', 'remove', 'rm', 'uninstall', 'upgrade', 'link', 'unlink'];
|
|
163
|
+
|
|
164
|
+
let needRehash = false;
|
|
165
|
+
|
|
166
|
+
if (CMD === 'bun' && ARGS.length > 0) {
|
|
167
|
+
const subCmd = ARGS[0];
|
|
168
|
+
const hasGlobalFlag = ARGS.includes('-g') || ARGS.includes('--global');
|
|
77
169
|
|
|
78
|
-
if
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
170
|
+
// For install/add/remove commands, only rehash if -g/--global is present
|
|
171
|
+
if (['install', 'i', 'add', 'a', 'remove', 'rm', 'uninstall', 'upgrade'].includes(subCmd)) {
|
|
172
|
+
needRehash = hasGlobalFlag;
|
|
173
|
+
}
|
|
174
|
+
// For link/unlink, always rehash
|
|
175
|
+
else if (['link', 'unlink'].includes(subCmd)) {
|
|
176
|
+
needRehash = true;
|
|
82
177
|
}
|
|
83
178
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
179
|
+
|
|
180
|
+
if (code === 0 && needRehash) {
|
|
181
|
+
const bvmCmd = path.join(BVM_DIR, 'bin', 'bvm.cmd');
|
|
182
|
+
if (fs.existsSync(bvmCmd)) {
|
|
183
|
+
try {
|
|
184
|
+
console.log('[bvm] Updating command registry...');
|
|
185
|
+
// Use synchronous call so user sees completion
|
|
186
|
+
const result = spawnSync(bvmCmd, ['rehash', '--silent'], {
|
|
187
|
+
stdio: 'inherit',
|
|
188
|
+
env: Object.assign({}, process.env, { BVM_DIR })
|
|
189
|
+
});
|
|
190
|
+
if (result.status === 0) {
|
|
191
|
+
console.log('[bvm] Done! New commands are now available.');
|
|
97
192
|
}
|
|
193
|
+
} catch(e) {
|
|
194
|
+
// Silent fail - rehash is not critical
|
|
98
195
|
}
|
|
99
196
|
}
|
|
100
|
-
}
|
|
101
|
-
|
|
197
|
+
}
|
|
198
|
+
process.exit(code ?? 0);
|
|
199
|
+
});
|
|
102
200
|
|
|
103
201
|
child.on('error', (err) => {
|
|
104
|
-
console.error("BVM Error:
|
|
202
|
+
console.error("BVM Error: " + err.message);
|
|
105
203
|
process.exit(1);
|
|
106
204
|
});
|
package/dist/bvm-shim.sh
CHANGED
|
@@ -58,7 +58,30 @@ REAL_EXECUTABLE="$VERSION_DIR/bin/$CMD_NAME"
|
|
|
58
58
|
if [ -x "$REAL_EXECUTABLE" ]; then
|
|
59
59
|
export BUN_INSTALL="$VERSION_DIR"
|
|
60
60
|
export PATH="$VERSION_DIR/bin:$PATH"
|
|
61
|
-
|
|
61
|
+
|
|
62
|
+
# Inject version-specific config if present
|
|
63
|
+
if [ -f "$VERSION_DIR/bunfig.toml" ]; then
|
|
64
|
+
export BUN_CONFIG_FILE="$VERSION_DIR/bunfig.toml"
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# Execute the command
|
|
68
|
+
"$REAL_EXECUTABLE" "$@"
|
|
69
|
+
EXIT_CODE=$?
|
|
70
|
+
|
|
71
|
+
# Auto-Rehash Logic
|
|
72
|
+
if [ "$CMD_NAME" = "bun" ] && [ $EXIT_CODE -eq 0 ]; then
|
|
73
|
+
case "$1" in
|
|
74
|
+
install|i|add|a|remove|rm|upgrade|link|unlink)
|
|
75
|
+
(export BVM_DIR="$BVM_DIR"; "$BVM_DIR/bin/bvm" rehash --silent >/dev/null 2>&1 & disown)
|
|
76
|
+
;;
|
|
77
|
+
esac
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
exit $EXIT_CODE
|
|
81
|
+
elif [ "$CMD_NAME" = "bunx" ] && [ -x "$VERSION_DIR/bin/bun" ]; then
|
|
82
|
+
export BUN_INSTALL="$VERSION_DIR"
|
|
83
|
+
export PATH="$VERSION_DIR/bin:$PATH"
|
|
84
|
+
exec "$VERSION_DIR/bin/bun" x "$@"
|
|
62
85
|
else
|
|
63
86
|
echo "BVM Error: Command '$CMD_NAME' not found in Bun $VERSION." >&2
|
|
64
87
|
exit 127
|