node-version-use 2.1.6 → 2.1.7
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/assets/installBinaries.cjs +284 -0
- package/assets/postinstall.cjs +11 -404
- package/dist/cjs/assets/installBinaries.cjs +284 -0
- package/dist/cjs/assets/installBinaries.cjs.map +1 -0
- package/dist/cjs/assets/installBinaries.d.cts +1 -0
- package/dist/cjs/assets/postinstall.cjs +11 -404
- package/dist/cjs/assets/postinstall.cjs.map +1 -1
- package/dist/cjs/commands/index.js +2 -3
- package/dist/cjs/commands/index.js.map +1 -1
- package/dist/cjs/commands/setup.js +23 -41
- package/dist/cjs/commands/setup.js.map +1 -1
- package/dist/cjs/commands/teardown.js +2 -1
- package/dist/cjs/commands/teardown.js.map +1 -1
- package/dist/cjs/compat.d.cts +1 -0
- package/dist/cjs/compat.d.ts +1 -0
- package/dist/cjs/compat.js +11 -4
- package/dist/cjs/compat.js.map +1 -1
- package/dist/esm/assets/installBinaries.cjs +282 -0
- package/dist/esm/assets/installBinaries.cjs.map +1 -0
- package/dist/esm/assets/installBinaries.d.cts +1 -0
- package/dist/esm/assets/postinstall.cjs +11 -404
- package/dist/esm/assets/postinstall.cjs.map +1 -1
- package/dist/esm/commands/index.js +2 -3
- package/dist/esm/commands/index.js.map +1 -1
- package/dist/esm/commands/setup.js +24 -42
- package/dist/esm/commands/setup.js.map +1 -1
- package/dist/esm/commands/teardown.js +2 -1
- package/dist/esm/commands/teardown.js.map +1 -1
- package/dist/esm/compat.d.ts +1 -0
- package/dist/esm/compat.js +8 -4
- package/dist/esm/compat.js.map +1 -1
- package/package.json +13 -8
|
@@ -8,416 +8,23 @@
|
|
|
8
8
|
* 1. Download to temp file
|
|
9
9
|
* 2. Extract to temp directory
|
|
10
10
|
* 3. Atomic rename to final location
|
|
11
|
-
*/ const
|
|
12
|
-
const
|
|
13
|
-
const fs = require('fs');
|
|
14
|
-
const mkdirp = require('mkdirp-classic');
|
|
15
|
-
const os = require('os');
|
|
16
|
-
const path = require('path');
|
|
17
|
-
const hasHomedir = typeof os.homedir === 'function';
|
|
18
|
-
function homedir() {
|
|
19
|
-
if (hasHomedir) {
|
|
20
|
-
return os.homedir();
|
|
21
|
-
}
|
|
22
|
-
var home = require('homedir-polyfill');
|
|
23
|
-
return home();
|
|
24
|
-
}
|
|
25
|
-
module.exports = {
|
|
26
|
-
homedir
|
|
27
|
-
};
|
|
28
|
-
// Configuration
|
|
29
|
-
const GITHUB_REPO = 'kmalakoff/node-version-use';
|
|
30
|
-
// Path is relative to dist/cjs/scripts/ at runtime
|
|
31
|
-
const BINARY_VERSION = require(path.join(__dirname, '..', 'package.json')).binaryVersion;
|
|
32
|
-
/**
|
|
33
|
-
* Get the platform-specific archive base name (without extension)
|
|
34
|
-
*/ function getArchiveBaseName() {
|
|
35
|
-
const platform = os.platform();
|
|
36
|
-
const arch = os.arch();
|
|
37
|
-
const platformMap = {
|
|
38
|
-
darwin: 'darwin',
|
|
39
|
-
linux: 'linux',
|
|
40
|
-
win32: 'win32'
|
|
41
|
-
};
|
|
42
|
-
const archMap = {
|
|
43
|
-
x64: 'x64',
|
|
44
|
-
arm64: 'arm64',
|
|
45
|
-
amd64: 'x64'
|
|
46
|
-
};
|
|
47
|
-
const platformName = platformMap[platform];
|
|
48
|
-
const archName = archMap[arch];
|
|
49
|
-
if (!platformName || !archName) {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
return `nvu-binary-${platformName}-${archName}`;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Get the extracted binary name (includes .exe on Windows)
|
|
56
|
-
*/ function getExtractedBinaryName(archiveBaseName) {
|
|
57
|
-
const ext = os.platform() === 'win32' ? '.exe' : '';
|
|
58
|
-
return archiveBaseName + ext;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Get the download URL for the binary archive
|
|
62
|
-
*/ function getDownloadUrl(archiveBaseName) {
|
|
63
|
-
const ext = os.platform() === 'win32' ? '.zip' : '.tar.gz';
|
|
64
|
-
return `https://github.com/${GITHUB_REPO}/releases/download/binary-v${BINARY_VERSION}/${archiveBaseName}${ext}`;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Copy file
|
|
68
|
-
*/ function copyFileSync(src, dest) {
|
|
69
|
-
const content = fs.readFileSync(src);
|
|
70
|
-
fs.writeFileSync(dest, content);
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Atomic rename with fallback to copy+delete for cross-device moves
|
|
74
|
-
*/ function atomicRename(src, dest, callback) {
|
|
75
|
-
fs.rename(src, dest, (err)=>{
|
|
76
|
-
if (!err) {
|
|
77
|
-
callback(null);
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
// Cross-device link error - fall back to copy + delete
|
|
81
|
-
if (err.code === 'EXDEV') {
|
|
82
|
-
try {
|
|
83
|
-
copyFileSync(src, dest);
|
|
84
|
-
fs.unlinkSync(src);
|
|
85
|
-
callback(null);
|
|
86
|
-
} catch (copyErr) {
|
|
87
|
-
callback(copyErr);
|
|
88
|
-
}
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
callback(err);
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Remove directory recursively
|
|
96
|
-
*/ function rmRecursive(dir) {
|
|
97
|
-
if (!fs.existsSync(dir)) return;
|
|
98
|
-
const files = fs.readdirSync(dir);
|
|
99
|
-
for(let i = 0; i < files.length; i++){
|
|
100
|
-
const filePath = path.join(dir, files[i]);
|
|
101
|
-
const stat = fs.statSync(filePath);
|
|
102
|
-
if (stat.isDirectory()) {
|
|
103
|
-
rmRecursive(filePath);
|
|
104
|
-
} else {
|
|
105
|
-
fs.unlinkSync(filePath);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
fs.rmdirSync(dir);
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Get temp directory
|
|
112
|
-
*/ function getTmpDir() {
|
|
113
|
-
return typeof os.tmpdir === 'function' ? os.tmpdir() : process.env.TMPDIR || process.env.TMP || process.env.TEMP || '/tmp';
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Download using curl (macOS, Linux, Windows 10+)
|
|
117
|
-
*/ function downloadWithCurl(downloadUrl, destPath, callback) {
|
|
118
|
-
const curl = spawn('curl', [
|
|
119
|
-
'-L',
|
|
120
|
-
'-f',
|
|
121
|
-
'-s',
|
|
122
|
-
'-o',
|
|
123
|
-
destPath,
|
|
124
|
-
downloadUrl
|
|
125
|
-
]);
|
|
126
|
-
curl.on('close', (code)=>{
|
|
127
|
-
if (code !== 0) {
|
|
128
|
-
// curl exit codes: 22 = HTTP error (4xx/5xx), 56 = receive error (often 404 with -f)
|
|
129
|
-
if (code === 22 || code === 56) {
|
|
130
|
-
callback(new Error('HTTP 404'));
|
|
131
|
-
} else {
|
|
132
|
-
callback(new Error(`curl failed with exit code ${code}`));
|
|
133
|
-
}
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
callback(null);
|
|
137
|
-
});
|
|
138
|
-
curl.on('error', (err)=>{
|
|
139
|
-
callback(err);
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Download using PowerShell (Windows 7+ fallback)
|
|
144
|
-
*/ function downloadWithPowerShell(downloadUrl, destPath, callback) {
|
|
145
|
-
const psCommand = `Invoke-WebRequest -Uri "${downloadUrl}" -OutFile "${destPath}" -UseBasicParsing`;
|
|
146
|
-
const ps = spawn('powershell', [
|
|
147
|
-
'-NoProfile',
|
|
148
|
-
'-Command',
|
|
149
|
-
psCommand
|
|
150
|
-
]);
|
|
151
|
-
ps.on('close', (code)=>{
|
|
152
|
-
if (code !== 0) {
|
|
153
|
-
callback(new Error(`PowerShell download failed with exit code ${code}`));
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
callback(null);
|
|
157
|
-
});
|
|
158
|
-
ps.on('error', (err)=>{
|
|
159
|
-
callback(err);
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Download a file - tries curl first, falls back to PowerShell on Windows
|
|
164
|
-
* Node 0.8's OpenSSL doesn't support TLS 1.2+ required by GitHub
|
|
165
|
-
*/ function downloadFile(downloadUrl, destPath, callback) {
|
|
166
|
-
downloadWithCurl(downloadUrl, destPath, (err)=>{
|
|
167
|
-
var _err_message;
|
|
168
|
-
if (!err) {
|
|
169
|
-
callback(null);
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
// If curl failed and we're on Windows, try PowerShell
|
|
173
|
-
if (os.platform() === 'win32' && (err === null || err === void 0 ? void 0 : (_err_message = err.message) === null || _err_message === void 0 ? void 0 : _err_message.indexOf('ENOENT')) >= 0) {
|
|
174
|
-
downloadWithPowerShell(downloadUrl, destPath, callback);
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
callback(err);
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Extract archive to a directory (callback-based)
|
|
182
|
-
*/ function extractArchive(archivePath, destDir, callback) {
|
|
183
|
-
const platform = os.platform();
|
|
184
|
-
if (platform === 'win32') {
|
|
185
|
-
// Windows: extract zip using PowerShell
|
|
186
|
-
const ps = spawn('powershell', [
|
|
187
|
-
'-Command',
|
|
188
|
-
`Expand-Archive -Path '${archivePath}' -DestinationPath '${destDir}' -Force`
|
|
189
|
-
]);
|
|
190
|
-
ps.on('close', (code)=>{
|
|
191
|
-
if (code !== 0) {
|
|
192
|
-
callback(new Error('Failed to extract archive'));
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
callback(null);
|
|
196
|
-
});
|
|
197
|
-
} else {
|
|
198
|
-
// Unix: extract tar.gz
|
|
199
|
-
const tar = spawn('tar', [
|
|
200
|
-
'-xzf',
|
|
201
|
-
archivePath,
|
|
202
|
-
'-C',
|
|
203
|
-
destDir
|
|
204
|
-
]);
|
|
205
|
-
tar.on('close', (code)=>{
|
|
206
|
-
if (code !== 0) {
|
|
207
|
-
callback(new Error('Failed to extract archive'));
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
callback(null);
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* Install binaries using atomic rename pattern
|
|
216
|
-
* 1. Extract to temp directory
|
|
217
|
-
* 2. Copy binary to temp files in destination directory
|
|
218
|
-
* 3. Atomic rename temp files to final names
|
|
219
|
-
*/ function extractAndInstall(archivePath, destDir, binaryName, callback) {
|
|
220
|
-
const platform = os.platform();
|
|
221
|
-
const isWindows = platform === 'win32';
|
|
222
|
-
const ext = isWindows ? '.exe' : '';
|
|
223
|
-
// Create temp extraction directory
|
|
224
|
-
const tempExtractDir = path.join(getTmpDir(), `nvu-extract-${Date.now()}`);
|
|
225
|
-
mkdirp.sync(tempExtractDir);
|
|
226
|
-
extractArchive(archivePath, tempExtractDir, (extractErr)=>{
|
|
227
|
-
if (extractErr) {
|
|
228
|
-
rmRecursive(tempExtractDir);
|
|
229
|
-
callback(extractErr);
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
const extractedPath = path.join(tempExtractDir, binaryName);
|
|
233
|
-
if (!fs.existsSync(extractedPath)) {
|
|
234
|
-
rmRecursive(tempExtractDir);
|
|
235
|
-
callback(new Error(`Extracted binary not found: ${binaryName}`));
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
// Binary names to install
|
|
239
|
-
const binaries = [
|
|
240
|
-
'node',
|
|
241
|
-
'npm',
|
|
242
|
-
'npx',
|
|
243
|
-
'corepack'
|
|
244
|
-
];
|
|
245
|
-
const timestamp = Date.now();
|
|
246
|
-
let installError = null;
|
|
247
|
-
// Step 1: Copy extracted binary to temp files in destination directory
|
|
248
|
-
// This ensures the temp files are on the same filesystem for atomic rename
|
|
249
|
-
for(let i = 0; i < binaries.length; i++){
|
|
250
|
-
const name = binaries[i];
|
|
251
|
-
const tempDest = path.join(destDir, `${name}.tmp-${timestamp}${ext}`);
|
|
252
|
-
try {
|
|
253
|
-
// Copy to temp file in destination directory
|
|
254
|
-
copyFileSync(extractedPath, tempDest);
|
|
255
|
-
// Set permissions on Unix
|
|
256
|
-
if (!isWindows) {
|
|
257
|
-
fs.chmodSync(tempDest, 0o755);
|
|
258
|
-
}
|
|
259
|
-
} catch (err) {
|
|
260
|
-
installError = err;
|
|
261
|
-
break;
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
if (installError) {
|
|
265
|
-
// Clean up any temp files we created
|
|
266
|
-
for(let j = 0; j < binaries.length; j++){
|
|
267
|
-
const tempPath = path.join(destDir, `${binaries[j]}.tmp-${timestamp}${ext}`);
|
|
268
|
-
if (fs.existsSync(tempPath)) {
|
|
269
|
-
try {
|
|
270
|
-
fs.unlinkSync(tempPath);
|
|
271
|
-
} catch (_e) {
|
|
272
|
-
// ignore cleanup errors
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
rmRecursive(tempExtractDir);
|
|
277
|
-
callback(installError);
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
|
-
// Step 2: Atomic rename temp files to final names
|
|
281
|
-
let renameError = null;
|
|
282
|
-
function doRename(index) {
|
|
283
|
-
if (index >= binaries.length) {
|
|
284
|
-
// All renames complete
|
|
285
|
-
rmRecursive(tempExtractDir);
|
|
286
|
-
callback(renameError);
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
const name = binaries[index];
|
|
290
|
-
const tempDest = path.join(destDir, `${name}.tmp-${timestamp}${ext}`);
|
|
291
|
-
const finalDest = path.join(destDir, `${name}${ext}`);
|
|
292
|
-
// Remove existing file if present (for atomic replacement)
|
|
293
|
-
if (fs.existsSync(finalDest)) {
|
|
294
|
-
try {
|
|
295
|
-
fs.unlinkSync(finalDest);
|
|
296
|
-
} catch (_e) {
|
|
297
|
-
// ignore cleanup errors
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
atomicRename(tempDest, finalDest, (err)=>{
|
|
301
|
-
if (err && !renameError) {
|
|
302
|
-
renameError = err;
|
|
303
|
-
}
|
|
304
|
-
doRename(index + 1);
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
doRename(0);
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* Print setup instructions
|
|
312
|
-
*/ function printInstructions(installed) {
|
|
313
|
-
const homedirPath = homedir();
|
|
314
|
-
const nvuBinPath = path.join(homedirPath, '.nvu', 'bin');
|
|
315
|
-
const platform = os.platform();
|
|
316
|
-
console.log('');
|
|
317
|
-
console.log('============================================================');
|
|
318
|
-
if (installed) {
|
|
319
|
-
console.log(' nvu binaries installed to ~/.nvu/bin/');
|
|
320
|
-
} else {
|
|
321
|
-
console.log(' nvu installed (binaries not yet available)');
|
|
322
|
-
}
|
|
323
|
-
console.log('============================================================');
|
|
324
|
-
console.log('');
|
|
325
|
-
console.log('To enable transparent Node version switching, add to your shell profile:');
|
|
326
|
-
console.log('');
|
|
327
|
-
if (platform === 'win32') {
|
|
328
|
-
console.log(' PowerShell (add to $PROFILE):');
|
|
329
|
-
console.log(` $env:PATH = "${nvuBinPath};$env:PATH"`);
|
|
330
|
-
console.log('');
|
|
331
|
-
console.log(' CMD (run as administrator):');
|
|
332
|
-
console.log(` setx PATH "${nvuBinPath};%PATH%"`);
|
|
333
|
-
} else {
|
|
334
|
-
console.log(' # For bash (~/.bashrc):');
|
|
335
|
-
console.log(' export PATH="$HOME/.nvu/bin:$PATH"');
|
|
336
|
-
console.log('');
|
|
337
|
-
console.log(' # For zsh (~/.zshrc):');
|
|
338
|
-
console.log(' export PATH="$HOME/.nvu/bin:$PATH"');
|
|
339
|
-
console.log('');
|
|
340
|
-
console.log(' # For fish (~/.config/fish/config.fish):');
|
|
341
|
-
console.log(' set -gx PATH $HOME/.nvu/bin $PATH');
|
|
342
|
-
}
|
|
343
|
-
console.log('');
|
|
344
|
-
console.log('Then restart your terminal or source your shell profile.');
|
|
345
|
-
console.log('');
|
|
346
|
-
console.log("Without this, 'nvu 18 npm test' still works - you just won't have");
|
|
347
|
-
console.log("transparent 'node' command override.");
|
|
348
|
-
console.log('============================================================');
|
|
349
|
-
}
|
|
11
|
+
*/ const exit = require('exit-compat');
|
|
12
|
+
const { installBinaries, printInstructions } = require('./installBinaries.cjs');
|
|
350
13
|
/**
|
|
351
14
|
* Main installation function
|
|
352
15
|
*/ function main() {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
exit(0);
|
|
359
|
-
return;
|
|
360
|
-
}
|
|
361
|
-
const extractedBinaryName = getExtractedBinaryName(archiveBaseName);
|
|
362
|
-
const homedirPath = homedir();
|
|
363
|
-
const nvuDir = path.join(homedirPath, '.nvu');
|
|
364
|
-
const binDir = path.join(nvuDir, 'bin');
|
|
365
|
-
// Create directories
|
|
366
|
-
mkdirp.sync(nvuDir);
|
|
367
|
-
mkdirp.sync(binDir);
|
|
368
|
-
const downloadUrl = getDownloadUrl(archiveBaseName);
|
|
369
|
-
const ext = os.platform() === 'win32' ? '.zip' : '.tar.gz';
|
|
370
|
-
const tempPath = path.join(getTmpDir(), `nvu-binary-${Date.now()}${ext}`);
|
|
371
|
-
console.log(`postinstall: Downloading binary for ${os.platform()}-${os.arch()}...`);
|
|
372
|
-
downloadFile(downloadUrl, tempPath, (downloadErr)=>{
|
|
373
|
-
if (downloadErr) {
|
|
374
|
-
var _downloadErr_message;
|
|
375
|
-
// Clean up temp file if it exists
|
|
376
|
-
if (fs.existsSync(tempPath)) {
|
|
377
|
-
try {
|
|
378
|
-
fs.unlinkSync(tempPath);
|
|
379
|
-
} catch (_e) {
|
|
380
|
-
// ignore cleanup errors
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
if (((_downloadErr_message = downloadErr.message) === null || _downloadErr_message === void 0 ? void 0 : _downloadErr_message.indexOf('404')) >= 0) {
|
|
384
|
-
console.log('postinstall: Binaries not yet published to GitHub releases.');
|
|
385
|
-
console.log('');
|
|
386
|
-
console.log('To build and install binaries locally:');
|
|
387
|
-
console.log(' cd node_modules/node-version-use/binary');
|
|
388
|
-
console.log(' make install');
|
|
389
|
-
console.log('');
|
|
390
|
-
console.log('Or wait for the next release which will include pre-built binaries.');
|
|
391
|
-
} else {
|
|
392
|
-
console.log(`postinstall warning: Failed to install binary: ${downloadErr.message || downloadErr}`);
|
|
393
|
-
console.log('You can still use nvu with explicit versions: nvu 18 npm test');
|
|
394
|
-
console.log('To install binaries manually: cd node_modules/node-version-use/binary && make install');
|
|
395
|
-
}
|
|
396
|
-
printInstructions(false);
|
|
397
|
-
exit(0);
|
|
16
|
+
installBinaries({}, (err, installed)=>{
|
|
17
|
+
if (err) {
|
|
18
|
+
console.log(`postinstall warning: Failed to install binary: ${err.message || err}`);
|
|
19
|
+
console.log('You can still use nvu with explicit versions: nvu 18 npm test');
|
|
20
|
+
exit(1);
|
|
398
21
|
return;
|
|
399
22
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
// Clean up temp file
|
|
403
|
-
if (fs.existsSync(tempPath)) {
|
|
404
|
-
try {
|
|
405
|
-
fs.unlinkSync(tempPath);
|
|
406
|
-
} catch (_e) {
|
|
407
|
-
// ignore cleanup errors
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
if (extractErr) {
|
|
411
|
-
console.log(`postinstall warning: Failed to extract binary: ${extractErr.message || extractErr}`);
|
|
412
|
-
console.log('You can still use nvu with explicit versions: nvu 18 npm test');
|
|
413
|
-
printInstructions(false);
|
|
414
|
-
exit(0);
|
|
415
|
-
return;
|
|
416
|
-
}
|
|
23
|
+
if (installed) {
|
|
24
|
+
printInstructions();
|
|
417
25
|
console.log('postinstall: Binary installed successfully!');
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
});
|
|
26
|
+
}
|
|
27
|
+
exit(0);
|
|
421
28
|
});
|
|
422
29
|
}
|
|
423
30
|
main();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/assets/postinstall.cts"],"sourcesContent":["/**\n * Postinstall script for node-version-use\n *\n * Downloads the platform-specific binary and installs it to ~/.nvu/bin/\n * This enables transparent Node version switching.\n *\n * Uses safe atomic download pattern:\n * 1. Download to temp file\n * 2. Extract to temp directory\n * 3. Atomic rename to final location\n */\n\nconst { spawn } = require('child_process');\nconst exit = require('exit-compat');\nconst fs = require('fs');\nconst mkdirp = require('mkdirp-classic');\nconst os = require('os');\nconst path = require('path');\n\nconst hasHomedir = typeof os.homedir === 'function';\nfunction homedir(): string {\n if (hasHomedir) {\n return os.homedir();\n }\n var home = require('homedir-polyfill');\n return home();\n}\n\nmodule.exports = { homedir };\n\n// Configuration\nconst GITHUB_REPO = 'kmalakoff/node-version-use';\n// Path is relative to dist/cjs/scripts/ at runtime\nconst BINARY_VERSION = require(path.join(__dirname, '..', 'package.json')).binaryVersion;\n\ntype Callback = (err?: Error | null) => void;\n\ninterface PlatformMap {\n [key: string]: string;\n}\n\n/**\n * Get the platform-specific archive base name (without extension)\n */\nfunction getArchiveBaseName(): string | null {\n const platform = os.platform();\n const arch = os.arch();\n\n const platformMap: PlatformMap = {\n darwin: 'darwin',\n linux: 'linux',\n win32: 'win32',\n };\n\n const archMap: PlatformMap = {\n x64: 'x64',\n arm64: 'arm64',\n amd64: 'x64',\n };\n\n const platformName = platformMap[platform];\n const archName = archMap[arch];\n\n if (!platformName || !archName) {\n return null;\n }\n\n return `nvu-binary-${platformName}-${archName}`;\n}\n\n/**\n * Get the extracted binary name (includes .exe on Windows)\n */\nfunction getExtractedBinaryName(archiveBaseName: string): string {\n const ext = os.platform() === 'win32' ? '.exe' : '';\n return archiveBaseName + ext;\n}\n\n/**\n * Get the download URL for the binary archive\n */\nfunction getDownloadUrl(archiveBaseName: string): string {\n const ext = os.platform() === 'win32' ? '.zip' : '.tar.gz';\n return `https://github.com/${GITHUB_REPO}/releases/download/binary-v${BINARY_VERSION}/${archiveBaseName}${ext}`;\n}\n\n/**\n * Copy file\n */\nfunction copyFileSync(src: string, dest: string): void {\n const content = fs.readFileSync(src);\n fs.writeFileSync(dest, content);\n}\n\n/**\n * Atomic rename with fallback to copy+delete for cross-device moves\n */\nfunction atomicRename(src: string, dest: string, callback: Callback): void {\n fs.rename(src, dest, (err) => {\n if (!err) {\n callback(null);\n return;\n }\n\n // Cross-device link error - fall back to copy + delete\n if ((err as NodeJS.ErrnoException).code === 'EXDEV') {\n try {\n copyFileSync(src, dest);\n fs.unlinkSync(src);\n callback(null);\n } catch (copyErr) {\n callback(copyErr as Error);\n }\n return;\n }\n\n callback(err);\n });\n}\n\n/**\n * Remove directory recursively\n */\nfunction rmRecursive(dir: string): void {\n if (!fs.existsSync(dir)) return;\n\n const files = fs.readdirSync(dir);\n for (let i = 0; i < files.length; i++) {\n const filePath = path.join(dir, files[i]);\n const stat = fs.statSync(filePath);\n if (stat.isDirectory()) {\n rmRecursive(filePath);\n } else {\n fs.unlinkSync(filePath);\n }\n }\n fs.rmdirSync(dir);\n}\n\n/**\n * Get temp directory\n */\nfunction getTmpDir(): string {\n return typeof os.tmpdir === 'function' ? os.tmpdir() : process.env.TMPDIR || process.env.TMP || process.env.TEMP || '/tmp';\n}\n\n/**\n * Download using curl (macOS, Linux, Windows 10+)\n */\nfunction downloadWithCurl(downloadUrl: string, destPath: string, callback: Callback): void {\n const curl = spawn('curl', ['-L', '-f', '-s', '-o', destPath, downloadUrl]);\n\n curl.on('close', (code) => {\n if (code !== 0) {\n // curl exit codes: 22 = HTTP error (4xx/5xx), 56 = receive error (often 404 with -f)\n if (code === 22 || code === 56) {\n callback(new Error('HTTP 404'));\n } else {\n callback(new Error(`curl failed with exit code ${code}`));\n }\n return;\n }\n callback(null);\n });\n\n curl.on('error', (err) => {\n callback(err);\n });\n}\n\n/**\n * Download using PowerShell (Windows 7+ fallback)\n */\nfunction downloadWithPowerShell(downloadUrl: string, destPath: string, callback: Callback): void {\n const psCommand = `Invoke-WebRequest -Uri \"${downloadUrl}\" -OutFile \"${destPath}\" -UseBasicParsing`;\n const ps = spawn('powershell', ['-NoProfile', '-Command', psCommand]);\n\n ps.on('close', (code) => {\n if (code !== 0) {\n callback(new Error(`PowerShell download failed with exit code ${code}`));\n return;\n }\n callback(null);\n });\n\n ps.on('error', (err) => {\n callback(err);\n });\n}\n\n/**\n * Download a file - tries curl first, falls back to PowerShell on Windows\n * Node 0.8's OpenSSL doesn't support TLS 1.2+ required by GitHub\n */\nfunction downloadFile(downloadUrl: string, destPath: string, callback: Callback): void {\n downloadWithCurl(downloadUrl, destPath, (err) => {\n if (!err) {\n callback(null);\n return;\n }\n\n // If curl failed and we're on Windows, try PowerShell\n if (os.platform() === 'win32' && err?.message?.indexOf('ENOENT') >= 0) {\n downloadWithPowerShell(downloadUrl, destPath, callback);\n return;\n }\n\n callback(err);\n });\n}\n\n/**\n * Extract archive to a directory (callback-based)\n */\nfunction extractArchive(archivePath: string, destDir: string, callback: Callback): void {\n const platform = os.platform();\n\n if (platform === 'win32') {\n // Windows: extract zip using PowerShell\n const ps = spawn('powershell', ['-Command', `Expand-Archive -Path '${archivePath}' -DestinationPath '${destDir}' -Force`]);\n ps.on('close', (code) => {\n if (code !== 0) {\n callback(new Error('Failed to extract archive'));\n return;\n }\n callback(null);\n });\n } else {\n // Unix: extract tar.gz\n const tar = spawn('tar', ['-xzf', archivePath, '-C', destDir]);\n tar.on('close', (code) => {\n if (code !== 0) {\n callback(new Error('Failed to extract archive'));\n return;\n }\n callback(null);\n });\n }\n}\n\n/**\n * Install binaries using atomic rename pattern\n * 1. Extract to temp directory\n * 2. Copy binary to temp files in destination directory\n * 3. Atomic rename temp files to final names\n */\nfunction extractAndInstall(archivePath: string, destDir: string, binaryName: string, callback: Callback): void {\n const platform = os.platform();\n const isWindows = platform === 'win32';\n const ext = isWindows ? '.exe' : '';\n\n // Create temp extraction directory\n const tempExtractDir = path.join(getTmpDir(), `nvu-extract-${Date.now()}`);\n mkdirp.sync(tempExtractDir);\n\n extractArchive(archivePath, tempExtractDir, (extractErr) => {\n if (extractErr) {\n rmRecursive(tempExtractDir);\n callback(extractErr);\n return;\n }\n\n const extractedPath = path.join(tempExtractDir, binaryName);\n if (!fs.existsSync(extractedPath)) {\n rmRecursive(tempExtractDir);\n callback(new Error(`Extracted binary not found: ${binaryName}`));\n return;\n }\n\n // Binary names to install\n const binaries = ['node', 'npm', 'npx', 'corepack'];\n const timestamp = Date.now();\n let installError: Error | null = null;\n\n // Step 1: Copy extracted binary to temp files in destination directory\n // This ensures the temp files are on the same filesystem for atomic rename\n for (let i = 0; i < binaries.length; i++) {\n const name = binaries[i];\n const tempDest = path.join(destDir, `${name}.tmp-${timestamp}${ext}`);\n\n try {\n // Copy to temp file in destination directory\n copyFileSync(extractedPath, tempDest);\n\n // Set permissions on Unix\n if (!isWindows) {\n fs.chmodSync(tempDest, 0o755);\n }\n } catch (err) {\n installError = err as Error;\n break;\n }\n }\n\n if (installError) {\n // Clean up any temp files we created\n for (let j = 0; j < binaries.length; j++) {\n const tempPath = path.join(destDir, `${binaries[j]}.tmp-${timestamp}${ext}`);\n if (fs.existsSync(tempPath)) {\n try {\n fs.unlinkSync(tempPath);\n } catch (_e) {\n // ignore cleanup errors\n }\n }\n }\n rmRecursive(tempExtractDir);\n callback(installError);\n return;\n }\n\n // Step 2: Atomic rename temp files to final names\n let renameError: Error | null = null;\n\n function doRename(index: number): void {\n if (index >= binaries.length) {\n // All renames complete\n rmRecursive(tempExtractDir);\n callback(renameError);\n return;\n }\n\n const name = binaries[index];\n const tempDest = path.join(destDir, `${name}.tmp-${timestamp}${ext}`);\n const finalDest = path.join(destDir, `${name}${ext}`);\n\n // Remove existing file if present (for atomic replacement)\n if (fs.existsSync(finalDest)) {\n try {\n fs.unlinkSync(finalDest);\n } catch (_e) {\n // ignore cleanup errors\n }\n }\n\n atomicRename(tempDest, finalDest, (err) => {\n if (err && !renameError) {\n renameError = err;\n }\n doRename(index + 1);\n });\n }\n\n doRename(0);\n });\n}\n\n/**\n * Print setup instructions\n */\nfunction printInstructions(installed: boolean): void {\n const homedirPath = homedir();\n const nvuBinPath = path.join(homedirPath, '.nvu', 'bin');\n const platform = os.platform();\n\n console.log('');\n console.log('============================================================');\n if (installed) {\n console.log(' nvu binaries installed to ~/.nvu/bin/');\n } else {\n console.log(' nvu installed (binaries not yet available)');\n }\n console.log('============================================================');\n console.log('');\n console.log('To enable transparent Node version switching, add to your shell profile:');\n console.log('');\n\n if (platform === 'win32') {\n console.log(' PowerShell (add to $PROFILE):');\n console.log(` $env:PATH = \"${nvuBinPath};$env:PATH\"`);\n console.log('');\n console.log(' CMD (run as administrator):');\n console.log(` setx PATH \"${nvuBinPath};%PATH%\"`);\n } else {\n console.log(' # For bash (~/.bashrc):');\n console.log(' export PATH=\"$HOME/.nvu/bin:$PATH\"');\n console.log('');\n console.log(' # For zsh (~/.zshrc):');\n console.log(' export PATH=\"$HOME/.nvu/bin:$PATH\"');\n console.log('');\n console.log(' # For fish (~/.config/fish/config.fish):');\n console.log(' set -gx PATH $HOME/.nvu/bin $PATH');\n }\n\n console.log('');\n console.log('Then restart your terminal or source your shell profile.');\n console.log('');\n console.log(\"Without this, 'nvu 18 npm test' still works - you just won't have\");\n console.log(\"transparent 'node' command override.\");\n console.log('============================================================');\n}\n\n/**\n * Main installation function\n */\nfunction main(): void {\n const archiveBaseName = getArchiveBaseName();\n\n if (!archiveBaseName) {\n console.log('postinstall: Unsupported platform/architecture for binary.');\n console.log(`Platform: ${os.platform()}, Arch: ${os.arch()}`);\n console.log('Binary not installed. You can still use nvu with explicit versions: nvu 18 npm test');\n exit(0);\n return;\n }\n\n const extractedBinaryName = getExtractedBinaryName(archiveBaseName);\n\n const homedirPath = homedir();\n const nvuDir = path.join(homedirPath, '.nvu');\n const binDir = path.join(nvuDir, 'bin');\n\n // Create directories\n mkdirp.sync(nvuDir);\n mkdirp.sync(binDir);\n\n const downloadUrl = getDownloadUrl(archiveBaseName);\n const ext = os.platform() === 'win32' ? '.zip' : '.tar.gz';\n const tempPath = path.join(getTmpDir(), `nvu-binary-${Date.now()}${ext}`);\n\n console.log(`postinstall: Downloading binary for ${os.platform()}-${os.arch()}...`);\n\n downloadFile(downloadUrl, tempPath, (downloadErr) => {\n if (downloadErr) {\n // Clean up temp file if it exists\n if (fs.existsSync(tempPath)) {\n try {\n fs.unlinkSync(tempPath);\n } catch (_e) {\n // ignore cleanup errors\n }\n }\n\n if (downloadErr.message?.indexOf('404') >= 0) {\n console.log('postinstall: Binaries not yet published to GitHub releases.');\n console.log('');\n console.log('To build and install binaries locally:');\n console.log(' cd node_modules/node-version-use/binary');\n console.log(' make install');\n console.log('');\n console.log('Or wait for the next release which will include pre-built binaries.');\n } else {\n console.log(`postinstall warning: Failed to install binary: ${downloadErr.message || downloadErr}`);\n console.log('You can still use nvu with explicit versions: nvu 18 npm test');\n console.log('To install binaries manually: cd node_modules/node-version-use/binary && make install');\n }\n printInstructions(false);\n exit(0);\n return;\n }\n\n console.log('postinstall: Extracting binary...');\n\n extractAndInstall(tempPath, binDir, extractedBinaryName, (extractErr) => {\n // Clean up temp file\n if (fs.existsSync(tempPath)) {\n try {\n fs.unlinkSync(tempPath);\n } catch (_e) {\n // ignore cleanup errors\n }\n }\n\n if (extractErr) {\n console.log(`postinstall warning: Failed to extract binary: ${extractErr.message || extractErr}`);\n console.log('You can still use nvu with explicit versions: nvu 18 npm test');\n printInstructions(false);\n exit(0);\n return;\n }\n\n console.log('postinstall: Binary installed successfully!');\n printInstructions(true);\n exit(0);\n });\n });\n}\n\nmain();\n"],"names":["spawn","require","exit","fs","mkdirp","os","path","hasHomedir","homedir","home","module","exports","GITHUB_REPO","BINARY_VERSION","join","__dirname","binaryVersion","getArchiveBaseName","platform","arch","platformMap","darwin","linux","win32","archMap","x64","arm64","amd64","platformName","archName","getExtractedBinaryName","archiveBaseName","ext","getDownloadUrl","copyFileSync","src","dest","content","readFileSync","writeFileSync","atomicRename","callback","rename","err","code","unlinkSync","copyErr","rmRecursive","dir","existsSync","files","readdirSync","i","length","filePath","stat","statSync","isDirectory","rmdirSync","getTmpDir","tmpdir","process","env","TMPDIR","TMP","TEMP","downloadWithCurl","downloadUrl","destPath","curl","on","Error","downloadWithPowerShell","psCommand","ps","downloadFile","message","indexOf","extractArchive","archivePath","destDir","tar","extractAndInstall","binaryName","isWindows","tempExtractDir","Date","now","sync","extractErr","extractedPath","binaries","timestamp","installError","name","tempDest","chmodSync","j","tempPath","_e","renameError","doRename","index","finalDest","printInstructions","installed","homedirPath","nvuBinPath","console","log","main","extractedBinaryName","nvuDir","binDir","downloadErr"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/assets/postinstall.cts"],"sourcesContent":["/**\n * Postinstall script for node-version-use\n *\n * Downloads the platform-specific binary and installs it to ~/.nvu/bin/\n * This enables transparent Node version switching.\n *\n * Uses safe atomic download pattern:\n * 1. Download to temp file\n * 2. Extract to temp directory\n * 3. Atomic rename to final location\n */\n\nconst exit = require('exit-compat');\nconst { installBinaries, printInstructions } = require('./installBinaries.cjs');\n\n/**\n * Main installation function\n */\nfunction main(): void {\n installBinaries({}, (err, installed) => {\n if (err) {\n console.log(`postinstall warning: Failed to install binary: ${err.message || err}`);\n console.log('You can still use nvu with explicit versions: nvu 18 npm test');\n exit(1);\n return;\n }\n\n if (installed) {\n printInstructions();\n console.log('postinstall: Binary installed successfully!');\n }\n exit(0);\n });\n}\n\nmain();\n"],"names":["exit","require","installBinaries","printInstructions","main","err","installed","console","log","message"],"mappings":"AAAA;;;;;;;;;;CAUC,GAED,MAAMA,OAAOC,QAAQ;AACrB,MAAM,EAAEC,eAAe,EAAEC,iBAAiB,EAAE,GAAGF,QAAQ;AAEvD;;CAEC,GACD,SAASG;IACPF,gBAAgB,CAAC,GAAG,CAACG,KAAKC;QACxB,IAAID,KAAK;YACPE,QAAQC,GAAG,CAAC,CAAC,+CAA+C,EAAEH,IAAII,OAAO,IAAIJ,KAAK;YAClFE,QAAQC,GAAG,CAAC;YACZR,KAAK;YACL;QACF;QAEA,IAAIM,WAAW;YACbH;YACAI,QAAQC,GAAG,CAAC;QACd;QACAR,KAAK;IACP;AACF;AAEAI"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/commands/index.ts"],"sourcesContent":["import defaultCmd from './default.ts';\nimport installCmd from './install.ts';\nimport listCmd from './list.ts';\nimport localCmd from './local.ts';\nimport setupCmd from './setup.ts';\nimport teardownCmd from './teardown.ts';\nimport uninstallCmd from './uninstall.ts';\nimport whichCmd from './which.ts';\n\nexport const commands: Record<string, (args: string[]) => void> = {\n default: defaultCmd,\n local: localCmd,\n list: listCmd,\n which: whichCmd,\n install: installCmd,\n uninstall: uninstallCmd,\n setup: setupCmd,\n teardown: teardownCmd,\n};\n\nexport function isCommand(name: string): boolean {\n return name in commands;\n}\n\nexport function runCommand(name: string, args: string[]): void {\n const cmd = commands[name];\n if (cmd)
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node-version/node-version-use/src/commands/index.ts"],"sourcesContent":["import defaultCmd from './default.ts';\nimport installCmd from './install.ts';\nimport listCmd from './list.ts';\nimport localCmd from './local.ts';\nimport setupCmd from './setup.ts';\nimport teardownCmd from './teardown.ts';\nimport uninstallCmd from './uninstall.ts';\nimport whichCmd from './which.ts';\n\nexport const commands: Record<string, (args: string[]) => void> = {\n default: defaultCmd,\n local: localCmd,\n list: listCmd,\n which: whichCmd,\n install: installCmd,\n uninstall: uninstallCmd,\n setup: setupCmd,\n teardown: teardownCmd,\n};\n\nexport function isCommand(name: string): boolean {\n return name in commands;\n}\n\nexport function runCommand(name: string, args: string[]): void {\n const cmd = commands[name];\n if (cmd) cmd(args);\n else console.error(`Unknown command: ${name}`);\n}\n"],"names":["defaultCmd","installCmd","listCmd","localCmd","setupCmd","teardownCmd","uninstallCmd","whichCmd","commands","default","local","list","which","install","uninstall","setup","teardown","isCommand","name","runCommand","args","cmd","console","error"],"mappings":"AAAA,OAAOA,gBAAgB,eAAe;AACtC,OAAOC,gBAAgB,eAAe;AACtC,OAAOC,aAAa,YAAY;AAChC,OAAOC,cAAc,aAAa;AAClC,OAAOC,cAAc,aAAa;AAClC,OAAOC,iBAAiB,gBAAgB;AACxC,OAAOC,kBAAkB,iBAAiB;AAC1C,OAAOC,cAAc,aAAa;AAElC,OAAO,MAAMC,WAAqD;IAChEC,SAAST;IACTU,OAAOP;IACPQ,MAAMT;IACNU,OAAOL;IACPM,SAASZ;IACTa,WAAWR;IACXS,OAAOX;IACPY,UAAUX;AACZ,EAAE;AAEF,OAAO,SAASY,UAAUC,IAAY;IACpC,OAAOA,QAAQV;AACjB;AAEA,OAAO,SAASW,WAAWD,IAAY,EAAEE,IAAc;IACrD,MAAMC,MAAMb,QAAQ,CAACU,KAAK;IAC1B,IAAIG,KAAKA,IAAID;SACRE,QAAQC,KAAK,CAAC,CAAC,iBAAiB,EAAEL,MAAM;AAC/C"}
|
|
@@ -1,54 +1,38 @@
|
|
|
1
|
-
import { execSync } from 'child_process';
|
|
2
1
|
import exit from 'exit-compat';
|
|
3
2
|
import fs from 'fs';
|
|
3
|
+
import getopts from 'getopts-compat';
|
|
4
|
+
import Module from 'module';
|
|
4
5
|
import path from 'path';
|
|
5
|
-
import
|
|
6
|
-
import { mkdirpSync, readdirWithTypes } from '../compat.js';
|
|
6
|
+
import { readdirWithTypes } from '../compat.js';
|
|
7
7
|
import { storagePath } from '../constants.js';
|
|
8
8
|
import { findInstalledVersions } from '../lib/findInstalledVersions.js';
|
|
9
|
-
const
|
|
9
|
+
const _require = typeof require === 'undefined' ? Module.createRequire(import.meta.url) : require;
|
|
10
|
+
const { installBinaries, printInstructions } = _require('../assets/installBinaries.cjs');
|
|
10
11
|
/**
|
|
11
12
|
* nvu setup [--shims]
|
|
12
13
|
*
|
|
13
14
|
* Install/reinstall nvu binaries to ~/.nvu/bin
|
|
14
15
|
* With --shims: create shims for existing global packages
|
|
15
16
|
*/ export default function setupCmd(args) {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
for(let i = 0; i < args.length; i++){
|
|
27
|
-
if (args[i] === '--shims') {
|
|
28
|
-
hasShimsFlag = true;
|
|
29
|
-
break;
|
|
17
|
+
const options = getopts(args, {
|
|
18
|
+
boolean: [
|
|
19
|
+
'force'
|
|
20
|
+
]
|
|
21
|
+
});
|
|
22
|
+
installBinaries(options, (err, installed)=>{
|
|
23
|
+
if (err) {
|
|
24
|
+
console.error(`Setup failed: ${err.message || err}`);
|
|
25
|
+
exit(1);
|
|
26
|
+
return;
|
|
30
27
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const postinstallPath = path.join(__dirname, '..', '..', '..', 'scripts', 'postinstall.cjs');
|
|
38
|
-
if (fs.existsSync(postinstallPath)) {
|
|
39
|
-
// Run the postinstall script
|
|
40
|
-
try {
|
|
41
|
-
execSync(`node "${postinstallPath}"`, {
|
|
42
|
-
stdio: 'inherit'
|
|
43
|
-
});
|
|
44
|
-
} catch (_err) {
|
|
45
|
-
// postinstall handles its own errors gracefully
|
|
28
|
+
printInstructions();
|
|
29
|
+
if (!installed) console.log('Use --force to reinstall.');
|
|
30
|
+
if (options.force) {
|
|
31
|
+
const binDir = path.join(storagePath, 'bin');
|
|
32
|
+
createShimsForGlobalPackages(binDir);
|
|
33
|
+
return;
|
|
46
34
|
}
|
|
47
|
-
}
|
|
48
|
-
console.log('Setup script not found.');
|
|
49
|
-
console.log('Try reinstalling: npm install -g node-version-use');
|
|
50
|
-
exit(1);
|
|
51
|
-
}
|
|
35
|
+
});
|
|
52
36
|
}
|
|
53
37
|
/**
|
|
54
38
|
* Create shims for all global packages in the default Node version
|
|
@@ -92,9 +76,7 @@ const __dirname = path.dirname(typeof __filename !== 'undefined' ? __filename :
|
|
|
92
76
|
const entry = entries[i];
|
|
93
77
|
const name = entry.name;
|
|
94
78
|
// Skip our routing shims (node/npm/npx) - don't overwrite them
|
|
95
|
-
if (name === 'node' || name === 'npm' || name === 'npx')
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
79
|
+
if (name === 'node' || name === 'npm' || name === 'npx') continue;
|
|
98
80
|
const shimPath = path.join(binDir, name);
|
|
99
81
|
// Skip if shim already exists
|
|
100
82
|
if (fs.existsSync(shimPath)) {
|
|
@@ -113,6 +95,6 @@ const __dirname = path.dirname(typeof __filename !== 'undefined' ? __filename :
|
|
|
113
95
|
}
|
|
114
96
|
}
|
|
115
97
|
console.log('');
|
|
116
|
-
console.log(`Done. Created ${created} shims, skipped ${skipped} (already
|
|
98
|
+
console.log(`Done. Created ${created} shims, skipped ${skipped} (already exists).`);
|
|
117
99
|
exit(0);
|
|
118
100
|
}
|