node-version-use 2.4.0 → 2.4.1
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/README.md +61 -84
- package/assets/bin/node +0 -0
- package/assets/installBinaries.cjs +95 -18
- package/assets/postinstall.cjs +16 -1
- package/dist/cjs/assets/installBinaries.cjs +95 -18
- package/dist/cjs/assets/installBinaries.cjs.map +1 -1
- package/dist/cjs/assets/postinstall.cjs +16 -1
- package/dist/cjs/assets/postinstall.cjs.map +1 -1
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/commands/default.js +30 -4
- package/dist/cjs/commands/default.js.map +1 -1
- package/dist/cjs/commands/index.js.map +1 -1
- package/dist/cjs/commands/install.js.map +1 -1
- package/dist/cjs/commands/list.js.map +1 -1
- package/dist/cjs/commands/local.js.map +1 -1
- package/dist/cjs/commands/setup.d.cts +2 -3
- package/dist/cjs/commands/setup.d.ts +2 -3
- package/dist/cjs/commands/setup.js +9 -84
- package/dist/cjs/commands/setup.js.map +1 -1
- package/dist/cjs/commands/teardown.js.map +1 -1
- package/dist/cjs/commands/uninstall.js.map +1 -1
- package/dist/cjs/commands/which.js.map +1 -1
- package/dist/cjs/compat.js.map +1 -1
- package/dist/cjs/constants.js.map +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/lib/findInstalledVersions.js.map +1 -1
- package/dist/cjs/lib/loadNodeVersionInstall.js.map +1 -1
- package/dist/cjs/worker.js.map +1 -1
- package/dist/esm/assets/installBinaries.cjs +78 -18
- package/dist/esm/assets/installBinaries.cjs.map +1 -1
- package/dist/esm/assets/postinstall.cjs +16 -1
- package/dist/esm/assets/postinstall.cjs.map +1 -1
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/commands/default.js +30 -4
- package/dist/esm/commands/default.js.map +1 -1
- package/dist/esm/commands/index.js.map +1 -1
- package/dist/esm/commands/install.js.map +1 -1
- package/dist/esm/commands/list.js.map +1 -1
- package/dist/esm/commands/local.js.map +1 -1
- package/dist/esm/commands/setup.d.ts +2 -3
- package/dist/esm/commands/setup.js +9 -84
- package/dist/esm/commands/setup.js.map +1 -1
- package/dist/esm/commands/teardown.js.map +1 -1
- package/dist/esm/commands/uninstall.js.map +1 -1
- package/dist/esm/commands/which.js.map +1 -1
- package/dist/esm/compat.js.map +1 -1
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/findInstalledVersions.js.map +1 -1
- package/dist/esm/lib/loadNodeVersionInstall.js.map +1 -1
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/worker.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,140 +1,117 @@
|
|
|
1
1
|
## node-version-use
|
|
2
2
|
|
|
3
|
-
Cross-platform solution for using multiple versions of Node.js.
|
|
3
|
+
Cross-platform solution for using multiple versions of Node.js. Transparent version switching via command interception.
|
|
4
4
|
|
|
5
5
|
### Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install -g node-version-use
|
|
9
|
+
export PATH="$HOME/.nvu/bin:$PATH" # Add to shell profile
|
|
9
10
|
```
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
### Quick Start
|
|
12
13
|
|
|
13
14
|
```bash
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
# For fish (~/.config/fish/config.fish):
|
|
18
|
-
set -gx PATH $HOME/.nvu/bin $PATH
|
|
15
|
+
nvu default 20 # Set global default
|
|
16
|
+
nvu local 18 # Set project version (.nvmrc)
|
|
17
|
+
node --version # Uses v20 (or v18 in project)
|
|
19
18
|
```
|
|
20
19
|
|
|
21
|
-
###
|
|
20
|
+
### Commands
|
|
22
21
|
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
nvu default
|
|
22
|
+
```
|
|
23
|
+
nvu default 20 # Global default
|
|
24
|
+
nvu default system # Use system Node
|
|
25
|
+
nvu local 18 # Project version (.nvmrc)
|
|
26
|
+
nvu install 22 # Install Node
|
|
27
|
+
nvu uninstall 22 # Uninstall Node
|
|
28
|
+
nvu list # List installed
|
|
29
|
+
nvu 22 npm run test # Run with specific version
|
|
30
|
+
```
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
nvu local 18
|
|
32
|
+
### How It Works
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
```
|
|
35
|
+
~/.nvu/bin/ # Go binary shims (node, npm, npx, nvu, ...)
|
|
36
|
+
↓
|
|
37
|
+
~/.nvu/default # Contains "22", "20", or "system"
|
|
38
|
+
↓
|
|
39
|
+
~/.nvu/installed/v22/ # Real Node.js installation
|
|
40
|
+
└── bin/node # Actual Node binary
|
|
32
41
|
```
|
|
33
42
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
#### Version Management
|
|
43
|
+
**Key design decisions:**
|
|
37
44
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
nvu
|
|
45
|
+
1. **Strict routing** - Each command routes to exactly one version (the default)
|
|
46
|
+
2. **npm compatibility** - Uses `npm_config_prefix` so npm behaves normally
|
|
47
|
+
3. **System escape hatch** - `nvu system npm ...` bypasses version routing
|
|
48
|
+
4. **Version-specific packages** - Global npm packages live in the version's directory
|
|
41
49
|
|
|
42
|
-
|
|
43
|
-
nvu local 18
|
|
50
|
+
### Frequently Asked Questions
|
|
44
51
|
|
|
45
|
-
|
|
46
|
-
nvu install 22
|
|
52
|
+
#### How do I reinstall nvu if it's missing?
|
|
47
53
|
|
|
48
|
-
|
|
49
|
-
nvu
|
|
54
|
+
```bash
|
|
55
|
+
nvu system npm install -g node-version-use
|
|
56
|
+
```
|
|
50
57
|
|
|
51
|
-
|
|
52
|
-
nvu list
|
|
58
|
+
This bypasses version routing entirely.
|
|
53
59
|
|
|
54
|
-
|
|
55
|
-
nvu which
|
|
56
|
-
```
|
|
60
|
+
#### Are global npm packages shared across versions?
|
|
57
61
|
|
|
58
|
-
|
|
62
|
+
No. Each Node version has its own `lib/node_modules/`. Install separately:
|
|
59
63
|
|
|
60
64
|
```bash
|
|
61
|
-
|
|
62
|
-
nvu
|
|
63
|
-
|
|
64
|
-
# Remove binaries
|
|
65
|
-
nvu teardown
|
|
65
|
+
nvu 22 npm install -g some-package
|
|
66
|
+
nvu 20 npm install -g some-package
|
|
66
67
|
```
|
|
67
68
|
|
|
68
|
-
####
|
|
69
|
+
#### Can I use system Node?
|
|
69
70
|
|
|
70
71
|
```bash
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
# Run with highest matching major version
|
|
75
|
-
nvu 12 npm run test
|
|
72
|
+
nvu default system
|
|
73
|
+
```
|
|
76
74
|
|
|
77
|
-
|
|
78
|
-
nvu lts npm run test
|
|
75
|
+
Routes all commands to system binaries via PATH.
|
|
79
76
|
|
|
80
|
-
|
|
81
|
-
nvu 0.8,4,8,14 npm run test
|
|
77
|
+
#### Why not search all installed versions for binaries?
|
|
82
78
|
|
|
83
|
-
|
|
84
|
-
nvu >=0.8 node --version
|
|
79
|
+
Explicit is better than implicit. You know exactly which version runs. Use `nvu <version> <command>` for specific versions.
|
|
85
80
|
|
|
86
|
-
|
|
87
|
-
nvu engines node --version
|
|
88
|
-
```
|
|
81
|
+
### How nvu Differs from Other Version Managers
|
|
89
82
|
|
|
90
|
-
|
|
83
|
+
| Feature | nvu | nvm | Volta |
|
|
84
|
+
|---------|-----|-----|-------|
|
|
85
|
+
| Command routing | Go binary shim | Shell function | npm shim |
|
|
86
|
+
| Default version | Global or per-project | Global | Per-project (package.json) |
|
|
87
|
+
| Global packages | Version-specific | Shared (via symlinks) | Pin to version |
|
|
88
|
+
| System Node | `nvu default system` | `nvm use system` | `volta off` |
|
|
89
|
+
| Recovery when broken | `nvu system npm ...` | Reinstall nvm | Reinstall volta |
|
|
91
90
|
|
|
92
|
-
nvu uses
|
|
91
|
+
**nvu** uses a single Go binary that intercepts commands. Simple, predictable routing.
|
|
93
92
|
|
|
94
|
-
|
|
95
|
-
2. Checks for `.nvmrc` in current/parent directories
|
|
96
|
-
3. Falls back to `~/.nvu/default`
|
|
97
|
-
4. Executes the matching installed Node version
|
|
93
|
+
**nvm** is a shell function that changes `$NODE_HOME` environment variable.
|
|
98
94
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
### Version Resolution
|
|
102
|
-
|
|
103
|
-
The binary resolves partial versions to installed versions:
|
|
104
|
-
- `20` matches `v20.19.6`
|
|
105
|
-
- `18.19` matches `v18.19.0`
|
|
106
|
-
- `v22` matches `v22.0.0`
|
|
95
|
+
**Volta** pins packages to specific Node versions in package.json and uses npm shims.
|
|
107
96
|
|
|
108
97
|
### JavaScript API
|
|
109
98
|
|
|
110
99
|
```javascript
|
|
111
100
|
const nvu = require('node-version-use');
|
|
112
|
-
|
|
113
|
-
// Run with callback
|
|
114
|
-
nvu('>=0.8', 'node', ['--version'], { versions: '12', stdio: 'inherit' }, (err, results) => {
|
|
115
|
-
// results is an array per-version of form {version, error, result}
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// Run with async/await
|
|
119
|
-
const results = await nvu('engines', 'node', ['--version'], { stdio: 'inherit' });
|
|
101
|
+
const results = await nvu('>=0.8', 'node', ['--version'], { stdio: 'inherit' });
|
|
120
102
|
```
|
|
121
103
|
|
|
122
|
-
###
|
|
104
|
+
### Uninstall
|
|
123
105
|
|
|
124
106
|
```bash
|
|
125
|
-
# Remove
|
|
126
|
-
nvu
|
|
127
|
-
|
|
128
|
-
# Optionally remove all nvu data
|
|
129
|
-
rm -rf ~/.nvu
|
|
107
|
+
nvu teardown # Remove ~/.nvu/bin
|
|
108
|
+
rm -rf ~/.nvu # Remove all data
|
|
130
109
|
```
|
|
131
110
|
|
|
132
|
-
Then remove the PATH line from your shell profile.
|
|
133
|
-
|
|
134
111
|
### Compatibility
|
|
135
112
|
|
|
136
113
|
- macOS (arm64, x64)
|
|
137
114
|
- Linux (arm64, x64)
|
|
138
115
|
- Windows (arm64, x64)
|
|
139
116
|
|
|
140
|
-
Compatible with `.nvmrc` files from nvm, fnm, and other
|
|
117
|
+
Compatible with `.nvmrc` files from nvm, fnm, and other tools.
|
package/assets/bin/node
ADDED
|
Binary file
|
|
@@ -37,21 +37,24 @@ function removeIfExistsSync(filePath) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
40
|
+
* Move a file out of the way (works even if running on Windows)
|
|
41
|
+
* First tries to unlink; if that fails (Windows locked), rename to .old-timestamp
|
|
42
42
|
*/ function moveOutOfWay(filePath) {
|
|
43
43
|
if (!fs.existsSync(filePath)) return;
|
|
44
|
+
// First try to unlink (works on Unix, fails on Windows if running)
|
|
45
|
+
try {
|
|
46
|
+
fs.unlinkSync(filePath);
|
|
47
|
+
return;
|
|
48
|
+
} catch (_e) {
|
|
49
|
+
// Unlink failed (likely Windows locked file), try rename
|
|
50
|
+
}
|
|
51
|
+
// Rename to .old-timestamp as fallback
|
|
44
52
|
var timestamp = Date.now();
|
|
45
53
|
var oldPath = "".concat(filePath, ".old-").concat(timestamp);
|
|
46
54
|
try {
|
|
47
55
|
fs.renameSync(filePath, oldPath);
|
|
48
|
-
} catch (
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
fs.unlinkSync(filePath);
|
|
52
|
-
} catch (_e2) {
|
|
53
|
-
// ignore - will fail on atomic rename instead
|
|
54
|
-
}
|
|
56
|
+
} catch (_e2) {
|
|
57
|
+
// Both unlink and rename failed - will fail on atomic rename instead
|
|
55
58
|
}
|
|
56
59
|
}
|
|
57
60
|
/**
|
|
@@ -114,6 +117,55 @@ function removeIfExistsSync(filePath) {
|
|
|
114
117
|
var content = fs.readFileSync(src);
|
|
115
118
|
fs.writeFileSync(dest, content);
|
|
116
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Sync all shims by copying the nvu binary to all other files in the bin directory
|
|
122
|
+
* All shims (node, npm, npx, corepack, eslint, etc.) are copies of the same binary
|
|
123
|
+
*/ module.exports.syncAllShims = function syncAllShims(binDir) {
|
|
124
|
+
var isWindows = process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE);
|
|
125
|
+
var ext = isWindows ? '.exe' : '';
|
|
126
|
+
// Source: nvu binary
|
|
127
|
+
var nvuSource = path.join(binDir, "nvu".concat(ext));
|
|
128
|
+
if (!fs.existsSync(nvuSource)) return;
|
|
129
|
+
try {
|
|
130
|
+
var entries = fs.readdirSync(binDir);
|
|
131
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
132
|
+
try {
|
|
133
|
+
for(var _iterator = entries[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
134
|
+
var name = _step.value;
|
|
135
|
+
// Skip nvu itself and nvu.json
|
|
136
|
+
if (name === "nvu".concat(ext) || name === 'nvu.json') continue;
|
|
137
|
+
// On Windows, only process .exe files
|
|
138
|
+
if (isWindows && !name.endsWith('.exe')) continue;
|
|
139
|
+
var shimPath = path.join(binDir, name);
|
|
140
|
+
var stat = fs.statSync(shimPath);
|
|
141
|
+
if (!stat.isFile()) continue;
|
|
142
|
+
// Move existing file out of the way (Windows compatibility)
|
|
143
|
+
moveOutOfWay(shimPath);
|
|
144
|
+
// Copy nvu binary to shim
|
|
145
|
+
copyFileSync(nvuSource, shimPath);
|
|
146
|
+
// Make executable on Unix
|
|
147
|
+
if (!isWindows) {
|
|
148
|
+
fs.chmodSync(shimPath, 493);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
} catch (err) {
|
|
152
|
+
_didIteratorError = true;
|
|
153
|
+
_iteratorError = err;
|
|
154
|
+
} finally{
|
|
155
|
+
try {
|
|
156
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
157
|
+
_iterator.return();
|
|
158
|
+
}
|
|
159
|
+
} finally{
|
|
160
|
+
if (_didIteratorError) {
|
|
161
|
+
throw _iteratorError;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
} catch (_e) {
|
|
166
|
+
// Ignore errors - shim sync is best effort
|
|
167
|
+
}
|
|
168
|
+
};
|
|
117
169
|
/**
|
|
118
170
|
* Atomic rename with fallback to copy+delete for cross-device moves
|
|
119
171
|
*/ function atomicRename(src, dest, callback) {
|
|
@@ -296,38 +348,63 @@ function removeIfExistsSync(filePath) {
|
|
|
296
348
|
}
|
|
297
349
|
var extractedBinaryName = "".concat(archiveBaseName).concat(isWindows ? '.exe' : '');
|
|
298
350
|
var binDir = path.join(storagePath, 'bin');
|
|
351
|
+
var nvuJsonPath = path.join(binDir, 'nvu.json');
|
|
299
352
|
// check if we need to upgrade
|
|
300
353
|
if (!options.force) {
|
|
301
354
|
try {
|
|
302
|
-
// already installed
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
}
|
|
355
|
+
// already installed - read nvu.json
|
|
356
|
+
var nvuJson = JSON.parse(fs.readFileSync(nvuJsonPath, 'utf8'));
|
|
357
|
+
if (nvuJson.binaryVersion === BINARY_VERSION) {
|
|
358
|
+
callback(null, false);
|
|
359
|
+
return;
|
|
308
360
|
}
|
|
309
361
|
} catch (_err) {}
|
|
310
362
|
}
|
|
311
363
|
// Create directories
|
|
312
364
|
mkdirp.sync(storagePath);
|
|
313
365
|
mkdirp.sync(binDir);
|
|
366
|
+
mkdirp.sync(path.join(storagePath, 'cache'));
|
|
314
367
|
// Clean up old .old-* files from previous installs
|
|
315
368
|
cleanupOldFiles(binDir);
|
|
316
369
|
var downloadUrl = "https://github.com/".concat(GITHUB_REPO, "/releases/download/binary-v").concat(BINARY_VERSION, "/").concat(archiveBaseName).concat(isWindows ? '.zip' : '.tar.gz');
|
|
317
|
-
var
|
|
370
|
+
var cachePath = path.join(storagePath, 'cache', "".concat(archiveBaseName).concat(isWindows ? '.zip' : '.tar.gz'));
|
|
371
|
+
// Check cache first
|
|
372
|
+
if (fs.existsSync(cachePath)) {
|
|
373
|
+
console.log('Using cached binary...');
|
|
374
|
+
// Use cached file
|
|
375
|
+
extractAndInstall(cachePath, binDir, extractedBinaryName, function(err) {
|
|
376
|
+
if (err) return callback(err);
|
|
377
|
+
// save binary version for upgrade checks
|
|
378
|
+
fs.writeFileSync(nvuJsonPath, JSON.stringify({
|
|
379
|
+
binaryVersion: BINARY_VERSION
|
|
380
|
+
}, null, 2), 'utf8');
|
|
381
|
+
console.log('Binary installed successfully!');
|
|
382
|
+
callback(null, true);
|
|
383
|
+
});
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
// Download to temp file
|
|
318
387
|
console.log("Downloading binary for ".concat(process.platform, "-").concat(process.arch, "..."));
|
|
388
|
+
var tempPath = path.join(tmpdir(), "nvu-binary-".concat(Date.now()).concat(isWindows ? '.zip' : '.tar.gz'));
|
|
319
389
|
getFile(downloadUrl, tempPath, function(err) {
|
|
320
390
|
if (err) {
|
|
321
391
|
removeIfExistsSync(tempPath);
|
|
322
392
|
callback(new Error("No prebuilt binary available for ".concat(process.platform, "-").concat(process.arch, ". Download: ").concat(downloadUrl, ". Error: ").concat(err.message)));
|
|
323
393
|
return;
|
|
324
394
|
}
|
|
325
|
-
|
|
395
|
+
// Copy to cache for future use
|
|
396
|
+
try {
|
|
397
|
+
copyFileSync(tempPath, cachePath);
|
|
398
|
+
} catch (_e) {
|
|
399
|
+
// Cache write failed, continue anyway
|
|
400
|
+
}
|
|
326
401
|
extractAndInstall(tempPath, binDir, extractedBinaryName, function(err) {
|
|
327
402
|
removeIfExistsSync(tempPath);
|
|
328
403
|
if (err) return callback(err);
|
|
329
404
|
// save binary version for upgrade checks
|
|
330
|
-
fs.writeFileSync(
|
|
405
|
+
fs.writeFileSync(nvuJsonPath, JSON.stringify({
|
|
406
|
+
binaryVersion: BINARY_VERSION
|
|
407
|
+
}, null, 2), 'utf8');
|
|
331
408
|
console.log('Binary installed successfully!');
|
|
332
409
|
callback(null, true);
|
|
333
410
|
});
|
package/assets/postinstall.cjs
CHANGED
|
@@ -10,7 +10,17 @@
|
|
|
10
10
|
* 2. Extract to temp directory
|
|
11
11
|
* 3. Atomic rename to final location
|
|
12
12
|
*/ var exit = require('exit-compat');
|
|
13
|
-
var
|
|
13
|
+
var path = require('path');
|
|
14
|
+
var os = require('os');
|
|
15
|
+
var _require = require('./installBinaries.cjs'), installBinaries = _require.installBinaries, printInstructions = _require.printInstructions, syncAllShims = _require.syncAllShims;
|
|
16
|
+
var hasHomedir = typeof os.homedir === 'function';
|
|
17
|
+
function homedir() {
|
|
18
|
+
if (hasHomedir) return os.homedir();
|
|
19
|
+
var home = require('homedir-polyfill');
|
|
20
|
+
return home();
|
|
21
|
+
}
|
|
22
|
+
// Allow NVU_HOME override for testing
|
|
23
|
+
var storagePath = process.env.NVU_HOME || path.join(homedir(), '.nvu');
|
|
14
24
|
/**
|
|
15
25
|
* Main installation function
|
|
16
26
|
*/ function main() {
|
|
@@ -22,8 +32,13 @@ var _require = require('./installBinaries.cjs'), installBinaries = _require.inst
|
|
|
22
32
|
return;
|
|
23
33
|
}
|
|
24
34
|
if (installed) {
|
|
35
|
+
// Sync all shims to the new binary version
|
|
36
|
+
var binDir = path.join(storagePath, 'bin');
|
|
37
|
+
syncAllShims(binDir);
|
|
25
38
|
printInstructions();
|
|
26
39
|
console.log('postinstall: Binary installed successfully!');
|
|
40
|
+
} else {
|
|
41
|
+
console.log('postinstall: Binaries already up to date.');
|
|
27
42
|
}
|
|
28
43
|
exit(0);
|
|
29
44
|
});
|
|
@@ -37,21 +37,24 @@ function removeIfExistsSync(filePath) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
40
|
+
* Move a file out of the way (works even if running on Windows)
|
|
41
|
+
* First tries to unlink; if that fails (Windows locked), rename to .old-timestamp
|
|
42
42
|
*/ function moveOutOfWay(filePath) {
|
|
43
43
|
if (!fs.existsSync(filePath)) return;
|
|
44
|
+
// First try to unlink (works on Unix, fails on Windows if running)
|
|
45
|
+
try {
|
|
46
|
+
fs.unlinkSync(filePath);
|
|
47
|
+
return;
|
|
48
|
+
} catch (_e) {
|
|
49
|
+
// Unlink failed (likely Windows locked file), try rename
|
|
50
|
+
}
|
|
51
|
+
// Rename to .old-timestamp as fallback
|
|
44
52
|
var timestamp = Date.now();
|
|
45
53
|
var oldPath = "".concat(filePath, ".old-").concat(timestamp);
|
|
46
54
|
try {
|
|
47
55
|
fs.renameSync(filePath, oldPath);
|
|
48
|
-
} catch (
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
fs.unlinkSync(filePath);
|
|
52
|
-
} catch (_e2) {
|
|
53
|
-
// ignore - will fail on atomic rename instead
|
|
54
|
-
}
|
|
56
|
+
} catch (_e2) {
|
|
57
|
+
// Both unlink and rename failed - will fail on atomic rename instead
|
|
55
58
|
}
|
|
56
59
|
}
|
|
57
60
|
/**
|
|
@@ -114,6 +117,55 @@ function removeIfExistsSync(filePath) {
|
|
|
114
117
|
var content = fs.readFileSync(src);
|
|
115
118
|
fs.writeFileSync(dest, content);
|
|
116
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Sync all shims by copying the nvu binary to all other files in the bin directory
|
|
122
|
+
* All shims (node, npm, npx, corepack, eslint, etc.) are copies of the same binary
|
|
123
|
+
*/ module.exports.syncAllShims = function syncAllShims(binDir) {
|
|
124
|
+
var isWindows = process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE);
|
|
125
|
+
var ext = isWindows ? '.exe' : '';
|
|
126
|
+
// Source: nvu binary
|
|
127
|
+
var nvuSource = path.join(binDir, "nvu".concat(ext));
|
|
128
|
+
if (!fs.existsSync(nvuSource)) return;
|
|
129
|
+
try {
|
|
130
|
+
var entries = fs.readdirSync(binDir);
|
|
131
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
132
|
+
try {
|
|
133
|
+
for(var _iterator = entries[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
134
|
+
var name = _step.value;
|
|
135
|
+
// Skip nvu itself and nvu.json
|
|
136
|
+
if (name === "nvu".concat(ext) || name === 'nvu.json') continue;
|
|
137
|
+
// On Windows, only process .exe files
|
|
138
|
+
if (isWindows && !name.endsWith('.exe')) continue;
|
|
139
|
+
var shimPath = path.join(binDir, name);
|
|
140
|
+
var stat = fs.statSync(shimPath);
|
|
141
|
+
if (!stat.isFile()) continue;
|
|
142
|
+
// Move existing file out of the way (Windows compatibility)
|
|
143
|
+
moveOutOfWay(shimPath);
|
|
144
|
+
// Copy nvu binary to shim
|
|
145
|
+
copyFileSync(nvuSource, shimPath);
|
|
146
|
+
// Make executable on Unix
|
|
147
|
+
if (!isWindows) {
|
|
148
|
+
fs.chmodSync(shimPath, 493);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
} catch (err) {
|
|
152
|
+
_didIteratorError = true;
|
|
153
|
+
_iteratorError = err;
|
|
154
|
+
} finally{
|
|
155
|
+
try {
|
|
156
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
157
|
+
_iterator.return();
|
|
158
|
+
}
|
|
159
|
+
} finally{
|
|
160
|
+
if (_didIteratorError) {
|
|
161
|
+
throw _iteratorError;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
} catch (_e) {
|
|
166
|
+
// Ignore errors - shim sync is best effort
|
|
167
|
+
}
|
|
168
|
+
};
|
|
117
169
|
/**
|
|
118
170
|
* Atomic rename with fallback to copy+delete for cross-device moves
|
|
119
171
|
*/ function atomicRename(src, dest, callback) {
|
|
@@ -296,38 +348,63 @@ function removeIfExistsSync(filePath) {
|
|
|
296
348
|
}
|
|
297
349
|
var extractedBinaryName = "".concat(archiveBaseName).concat(isWindows ? '.exe' : '');
|
|
298
350
|
var binDir = path.join(storagePath, 'bin');
|
|
351
|
+
var nvuJsonPath = path.join(binDir, 'nvu.json');
|
|
299
352
|
// check if we need to upgrade
|
|
300
353
|
if (!options.force) {
|
|
301
354
|
try {
|
|
302
|
-
// already installed
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
}
|
|
355
|
+
// already installed - read nvu.json
|
|
356
|
+
var nvuJson = JSON.parse(fs.readFileSync(nvuJsonPath, 'utf8'));
|
|
357
|
+
if (nvuJson.binaryVersion === BINARY_VERSION) {
|
|
358
|
+
callback(null, false);
|
|
359
|
+
return;
|
|
308
360
|
}
|
|
309
361
|
} catch (_err) {}
|
|
310
362
|
}
|
|
311
363
|
// Create directories
|
|
312
364
|
mkdirp.sync(storagePath);
|
|
313
365
|
mkdirp.sync(binDir);
|
|
366
|
+
mkdirp.sync(path.join(storagePath, 'cache'));
|
|
314
367
|
// Clean up old .old-* files from previous installs
|
|
315
368
|
cleanupOldFiles(binDir);
|
|
316
369
|
var downloadUrl = "https://github.com/".concat(GITHUB_REPO, "/releases/download/binary-v").concat(BINARY_VERSION, "/").concat(archiveBaseName).concat(isWindows ? '.zip' : '.tar.gz');
|
|
317
|
-
var
|
|
370
|
+
var cachePath = path.join(storagePath, 'cache', "".concat(archiveBaseName).concat(isWindows ? '.zip' : '.tar.gz'));
|
|
371
|
+
// Check cache first
|
|
372
|
+
if (fs.existsSync(cachePath)) {
|
|
373
|
+
console.log('Using cached binary...');
|
|
374
|
+
// Use cached file
|
|
375
|
+
extractAndInstall(cachePath, binDir, extractedBinaryName, function(err) {
|
|
376
|
+
if (err) return callback(err);
|
|
377
|
+
// save binary version for upgrade checks
|
|
378
|
+
fs.writeFileSync(nvuJsonPath, JSON.stringify({
|
|
379
|
+
binaryVersion: BINARY_VERSION
|
|
380
|
+
}, null, 2), 'utf8');
|
|
381
|
+
console.log('Binary installed successfully!');
|
|
382
|
+
callback(null, true);
|
|
383
|
+
});
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
// Download to temp file
|
|
318
387
|
console.log("Downloading binary for ".concat(process.platform, "-").concat(process.arch, "..."));
|
|
388
|
+
var tempPath = path.join(tmpdir(), "nvu-binary-".concat(Date.now()).concat(isWindows ? '.zip' : '.tar.gz'));
|
|
319
389
|
getFile(downloadUrl, tempPath, function(err) {
|
|
320
390
|
if (err) {
|
|
321
391
|
removeIfExistsSync(tempPath);
|
|
322
392
|
callback(new Error("No prebuilt binary available for ".concat(process.platform, "-").concat(process.arch, ". Download: ").concat(downloadUrl, ". Error: ").concat(err.message)));
|
|
323
393
|
return;
|
|
324
394
|
}
|
|
325
|
-
|
|
395
|
+
// Copy to cache for future use
|
|
396
|
+
try {
|
|
397
|
+
copyFileSync(tempPath, cachePath);
|
|
398
|
+
} catch (_e) {
|
|
399
|
+
// Cache write failed, continue anyway
|
|
400
|
+
}
|
|
326
401
|
extractAndInstall(tempPath, binDir, extractedBinaryName, function(err) {
|
|
327
402
|
removeIfExistsSync(tempPath);
|
|
328
403
|
if (err) return callback(err);
|
|
329
404
|
// save binary version for upgrade checks
|
|
330
|
-
fs.writeFileSync(
|
|
405
|
+
fs.writeFileSync(nvuJsonPath, JSON.stringify({
|
|
406
|
+
binaryVersion: BINARY_VERSION
|
|
407
|
+
}, null, 2), 'utf8');
|
|
331
408
|
console.log('Binary installed successfully!');
|
|
332
409
|
callback(null, true);
|
|
333
410
|
});
|